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.
32 #include <wsutil/swar.h>
35 #include "ptvcursor.h"
37 #include "addr_resolv.h"
41 #include "epan_dissect.h"
44 #include "wmem/wmem.h"
46 #include "asm_utils.h"
47 #include "column-utils.h"
50 #include "show_exception.h"
52 #include "wspython/wspy_register.h"
54 #define SUBTREE_ONCE_ALLOCATION_NUMBER 8
55 #define SUBTREE_MAX_LEVELS 256
56 /* Throw an exception if we exceed this many tree items. */
57 /* XXX - This should probably be a preference */
58 #define MAX_TREE_ITEMS (1 * 1000 * 1000)
61 typedef struct __subtree_lvl {
68 subtree_lvl *pushed_tree;
69 guint8 pushed_tree_index;
70 guint8 pushed_tree_max;
76 #define cVALS(x) (const value_string*)(x)
78 /** See inlined comments.
79 @param tree the tree to append this item to
80 @param hfindex field index
81 @param hfinfo header_field
82 @return the header field matching 'hfinfo' */
83 #define TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo) \
84 /* If this item is not referenced we dont have to do much work \
85 at all but we should still return a node so that field items \
86 below this node (think proto_item_add_subtree()) will still \
87 have somewhere to attach to or else filtering will not work \
88 (they would be ignored since tree would be NULL). \
89 DONT try to fake a node where PTREE_FINFO(tree) is NULL \
90 since dissectors that want to do proto_item_set_len() or \
91 other operations that dereference this would crash. \
92 We fake FT_PROTOCOL unless some clients have requested us \
97 PTREE_DATA(tree)->count++; \
98 if (PTREE_DATA(tree)->count > MAX_TREE_ITEMS) { \
99 if (getenv("WIRESHARK_ABORT_ON_TOO_MANY_ITEMS") != NULL) \
100 g_error("More than %d items in the tree -- possible infinite loop", MAX_TREE_ITEMS); \
101 /* Let the exception handler add items to the tree */ \
102 PTREE_DATA(tree)->count = 0; \
103 THROW_MESSAGE(DissectorError, \
104 ep_strdup_printf("More than %d items in the tree -- possible infinite loop", MAX_TREE_ITEMS)); \
106 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo); \
107 if (!(PTREE_DATA(tree)->visible)) { \
108 if (PTREE_FINFO(tree)) { \
109 if ((hfinfo->ref_type != HF_REF_TYPE_DIRECT) \
110 && (hfinfo->type != FT_PROTOCOL || \
111 PTREE_DATA(tree)->fake_protocols)) { \
112 /* just return tree back to the caller */\
118 /** See inlined comments.
119 @param pi the created protocol item we're about to return */
120 #define TRY_TO_FAKE_THIS_REPR(pi) \
122 if (!(PTREE_DATA(pi)->visible)) { \
123 /* If the tree (GUI) isn't visible it's pointless for us to generate the protocol \
124 * items string representation */ \
128 static const char *hf_try_val_to_str(guint32 value, const header_field_info *hfinfo);
130 static void fill_label_boolean(field_info *fi, gchar *label_str);
131 static void fill_label_bitfield(field_info *fi, gchar *label_str, gboolean is_signed);
132 static void fill_label_number(field_info *fi, gchar *label_str, gboolean is_signed);
133 static void fill_label_number64(field_info *fi, gchar *label_str, gboolean is_signed);
135 static const char *hfinfo_number_value_format_display(const header_field_info *hfinfo, int display, char buf[32], guint32 value);
136 static const char *hfinfo_number_vals_format(const header_field_info *hfinfo, char buf[32], guint32 value);
137 static const char *hfinfo_number_value_format(const header_field_info *hfinfo, char buf[32], guint32 value);
138 static const char *hfinfo_numeric_value_format(const header_field_info *hfinfo, char buf[32], guint32 value);
140 static const char* hfinfo_uint64_format(const header_field_info *hfinfo);
141 static const char* hfinfo_int64_format(const header_field_info *hfinfo);
144 proto_tree_add_node(proto_tree *tree, field_info *fi);
147 get_hfi_length(header_field_info *hfinfo, tvbuff_t *tvb, const gint start, gint *length,
151 new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
152 const gint start, const gint item_length);
155 alloc_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
156 const gint start, gint *length);
159 proto_tree_add_pi(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
160 gint start, gint *length);
163 proto_tree_set_representation_value(proto_item *pi, const char *format, va_list ap);
165 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap);
168 proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb);
170 proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length);
172 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length);
174 proto_tree_set_time(field_info *fi, nstime_t *value_ptr);
176 proto_tree_set_string(field_info *fi, const char* value);
178 proto_tree_set_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length, gint encoding);
180 proto_tree_set_ax25(field_info *fi, const guint8* value);
182 proto_tree_set_ax25_tvb(field_info *fi, tvbuff_t *tvb, gint start);
184 proto_tree_set_vines(field_info *fi, const guint8* value);
186 proto_tree_set_vines_tvb(field_info *fi, tvbuff_t *tvb, gint start);
188 proto_tree_set_ether(field_info *fi, const guint8* value);
190 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start);
192 proto_tree_set_ipxnet(field_info *fi, guint32 value);
194 proto_tree_set_ipv4(field_info *fi, guint32 value);
196 proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr);
198 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
200 proto_tree_set_guid(field_info *fi, const e_guid_t *value_ptr);
202 proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, gint start, const guint encoding);
204 proto_tree_set_oid(field_info *fi, const guint8* value_ptr, gint length);
206 proto_tree_set_oid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
208 proto_tree_set_boolean(field_info *fi, guint32 value);
210 proto_tree_set_float(field_info *fi, float value);
212 proto_tree_set_double(field_info *fi, double value);
214 proto_tree_set_uint(field_info *fi, guint32 value);
216 proto_tree_set_int(field_info *fi, gint32 value);
218 proto_tree_set_uint64(field_info *fi, guint64 value);
220 proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start, guint length, const guint encoding);
222 proto_tree_set_eui64(field_info *fi, const guint64 value);
224 proto_tree_set_eui64_tvb(field_info *fi, tvbuff_t *tvb, gint start, const guint encoding);
226 /* Handle type length mismatch (now filterable) expert info */
227 static int proto_type_length_mismatch = -1;
228 static expert_field ei_type_length_mismatch_error = EI_INIT;
229 static expert_field ei_type_length_mismatch_warn = EI_INIT;
230 static void register_type_length_mismatch(void);
232 static int proto_register_field_init(header_field_info *hfinfo, const int parent);
234 /* special-case header field used within proto.c */
235 static header_field_info hfi_text_only =
236 { "Text item", "text", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL };
237 int hf_text_only = -1;
239 /* Structure for information about a protocol */
241 const char *name; /* long description */
242 const char *short_name; /* short description */
243 const char *filter_name; /* name of this protocol in filters */
244 int proto_id; /* field ID for this protocol */
245 GSList *fields; /* fields for this protocol */
246 GSList *last_field; /* pointer to end of list of fields */
247 gboolean is_enabled; /* TRUE if protocol is enabled */
248 gboolean can_toggle; /* TRUE if is_enabled can be changed */
249 gboolean is_private; /* TRUE is protocol is private */
252 /* List of all protocols */
253 static GList *protocols = NULL;
255 static wmem_allocator_t *tree_pool_cache = NULL;
257 /* Contains information about a field when a dissector calls
258 * proto_tree_add_item. */
259 #define FIELD_INFO_NEW(pool, fi) fi = wmem_new(pool, field_info)
260 #define FIELD_INFO_FREE(pool, fi) wmem_free(pool, fi)
262 /* Contains the space for proto_nodes. */
263 #define PROTO_NODE_NEW(pool, node) \
264 node = wmem_new(pool, proto_node); \
265 node->first_child = NULL; \
266 node->last_child = NULL; \
269 #define PROTO_NODE_FREE(pool, node) \
270 wmem_free(pool, node)
272 /* String space for protocol and field items for the GUI */
273 #define ITEM_LABEL_NEW(pool, il) \
274 il = wmem_new(pool, item_label_t);
275 #define ITEM_LABEL_FREE(pool, il) \
278 #define PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo) \
279 if((guint)hfindex >= gpa_hfinfo.len && getenv("WIRESHARK_ABORT_ON_DISSECTOR_BUG")) \
280 g_error("Unregistered hf! index=%d", hfindex); \
281 DISSECTOR_ASSERT_HINT((guint)hfindex < gpa_hfinfo.len, "Unregistered hf!"); \
282 hfinfo = gpa_hfinfo.hfi[hfindex];
284 /* List which stores protocols and fields that have been registered */
285 typedef struct _gpa_hfinfo_t {
287 guint32 allocated_len;
288 header_field_info **hfi;
291 static gpa_hfinfo_t gpa_hfinfo;
293 /* Balanced tree of abbreviations and IDs */
294 static GTree *gpa_name_tree = NULL;
295 static header_field_info *same_name_hfinfo;
297 static void save_same_name_hfinfo(gpointer data)
299 same_name_hfinfo = (header_field_info*)data;
302 /* Points to the first element of an array of bits, indexed by
303 a subtree item type; that array element is TRUE if subtrees of
304 an item of that type are to be expanded. */
305 static guint32 *tree_is_expanded;
307 /* Number of elements in that array. */
310 /* Name hashtables for fast detection of duplicate names */
311 static GHashTable* proto_names = NULL;
312 static GHashTable* proto_short_names = NULL;
313 static GHashTable* proto_filter_names = NULL;
316 proto_compare_name(gconstpointer p1_arg, gconstpointer p2_arg)
318 const protocol_t *p1 = (const protocol_t *)p1_arg;
319 const protocol_t *p2 = (const protocol_t *)p2_arg;
321 return g_ascii_strcasecmp(p1->short_name, p2->short_name);
325 /* initialize data structures and register protocols and fields */
327 proto_init(void (register_all_protocols_func)(register_cb cb, gpointer client_data),
328 void (register_all_handoffs_func)(register_cb cb, gpointer client_data),
330 gpointer client_data)
334 proto_names = g_hash_table_new_full(g_int_hash, g_int_equal, g_free, NULL);
335 proto_short_names = g_hash_table_new(wrs_str_hash, g_str_equal);
336 proto_filter_names = g_hash_table_new(wrs_str_hash, g_str_equal);
339 gpa_hfinfo.allocated_len = 0;
340 gpa_hfinfo.hfi = NULL;
341 gpa_name_tree = g_tree_new_full(wrs_strcmp_with_data, NULL, NULL, save_same_name_hfinfo);
343 /* Initialize the ftype subsystem */
346 /* Register one special-case FT_TEXT_ONLY field for use when
347 converting wireshark to new-style proto_tree. These fields
348 are merely strings on the GUI tree; they are not filterable */
349 hf_text_only = proto_register_field_init(&hfi_text_only, -1);
351 /* Register the pseudo-protocols used for exceptions. */
352 register_show_exception();
353 register_type_length_mismatch();
355 /* Have each built-in dissector register its protocols, fields,
356 dissector tables, and dissectors to be called through a
357 handle, and do whatever one-time initialization it needs to
359 register_all_protocols_func(cb, client_data);
361 /* Now scan for python protocols */
363 (*cb)(RA_PYTHON_REGISTER, NULL, client_data);
364 register_all_py_protocols_func();
368 /* Now scan for plugins and load all the ones we find, calling
369 their register routines to do the stuff described above. */
371 (*cb)(RA_PLUGIN_REGISTER, NULL, client_data);
373 register_all_plugin_registrations();
376 /* Now call the "handoff registration" routines of all built-in
377 dissectors; those routines register the dissector in other
378 dissectors' handoff tables, and fetch any dissector handles
380 register_all_handoffs_func(cb, client_data);
383 /* Now do the same with python dissectors */
385 (*cb)(RA_PYTHON_HANDOFF, NULL, client_data);
386 register_all_py_handoffs_func();
390 /* Now do the same with plugins. */
392 (*cb)(RA_PLUGIN_HANDOFF, NULL, client_data);
393 register_all_plugin_handoffs();
396 /* sort the protocols by protocol name */
397 protocols = g_list_sort(protocols, proto_compare_name);
399 /* We've assigned all the subtree type values; allocate the array
400 for them, and zero it out. */
401 tree_is_expanded = g_new0(guint32, (num_tree_types/32)+1);
407 /* Free the abbrev/ID GTree */
409 g_tree_destroy(gpa_name_tree);
410 gpa_name_tree = NULL;
414 protocol_t *protocol = (protocol_t *)protocols->data;
415 header_field_info *hfinfo;
416 PROTO_REGISTRAR_GET_NTH(protocol->proto_id, hfinfo);
417 DISSECTOR_ASSERT(protocol->proto_id == hfinfo->id);
419 g_slice_free(header_field_info, hfinfo);
420 g_slist_free(protocol->fields);
421 protocols = g_list_remove(protocols, protocol);
426 g_hash_table_destroy(proto_names);
430 if (proto_short_names) {
431 g_hash_table_destroy(proto_short_names);
432 proto_short_names = NULL;
435 if (proto_filter_names) {
436 g_hash_table_destroy(proto_filter_names);
437 proto_filter_names = NULL;
440 if (gpa_hfinfo.allocated_len) {
442 gpa_hfinfo.allocated_len = 0;
443 g_free(gpa_hfinfo.hfi);
444 gpa_hfinfo.hfi = NULL;
446 g_free(tree_is_expanded);
447 tree_is_expanded = NULL;
451 proto_tree_traverse_pre_order(proto_tree *tree, proto_tree_traverse_func func,
454 proto_node *pnode = tree;
458 if (func(pnode, data))
461 child = pnode->first_child;
462 while (child != NULL) {
464 * The routine we call might modify the child, e.g. by
465 * freeing it, so we get the child's successor before
466 * calling that routine.
469 child = current->next;
470 if (proto_tree_traverse_pre_order((proto_tree *)current, func, data))
478 proto_tree_traverse_post_order(proto_tree *tree, proto_tree_traverse_func func,
481 proto_node *pnode = tree;
485 child = pnode->first_child;
486 while (child != NULL) {
488 * The routine we call might modify the child, e.g. by
489 * freeing it, so we get the child's successor before
490 * calling that routine.
493 child = current->next;
494 if (proto_tree_traverse_post_order((proto_tree *)current, func, data))
497 if (func(pnode, data))
504 proto_tree_children_foreach(proto_tree *tree, proto_tree_foreach_func func,
507 proto_node *node = tree;
513 node = node->first_child;
514 while (node != NULL) {
516 node = current->next;
517 func((proto_tree *)current, data);
522 free_GPtrArray_value(gpointer key, gpointer value, gpointer user_data _U_)
524 GPtrArray *ptrs = (GPtrArray *)value;
525 gint hfid = (gint)(long)key;
526 header_field_info *hfinfo;
528 PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
529 if (hfinfo->ref_type != HF_REF_TYPE_NONE) {
530 /* when a field is referenced by a filter this also
531 affects the refcount for the parent protocol so we need
532 to adjust the refcount for the parent as well
534 if (hfinfo->parent != -1) {
535 header_field_info *parent_hfinfo;
536 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
537 parent_hfinfo->ref_type = HF_REF_TYPE_NONE;
539 hfinfo->ref_type = HF_REF_TYPE_NONE;
542 g_ptr_array_free(ptrs, TRUE);
546 proto_tree_free_node(proto_node *node, gpointer data _U_)
548 field_info *finfo = PNODE_FINFO(node);
550 proto_tree_children_foreach(node, proto_tree_free_node, NULL);
552 FVALUE_CLEANUP(&finfo->value);
555 /* frees the resources that the dissection a proto_tree uses */
557 proto_tree_free(proto_tree *tree)
559 wmem_allocator_t *pool = PNODE_POOL(tree);
560 tree_data_t *tree_data = PTREE_DATA(tree);
562 proto_tree_children_foreach(tree, proto_tree_free_node, NULL);
565 if (tree_data->interesting_hfids) {
566 /* Free all the GPtrArray's in the interesting_hfids hash. */
567 g_hash_table_foreach(tree_data->interesting_hfids,
568 free_GPtrArray_value, NULL);
570 /* And then destroy the hash. */
571 g_hash_table_destroy(tree_data->interesting_hfids);
574 if (tree_pool_cache) {
575 /* if we already have one cached then just destroy it */
576 wmem_destroy_allocator(pool);
580 tree_pool_cache = pool;
584 /* Is the parsing being done for a visible proto_tree or an invisible one?
585 * By setting this correctly, the proto_tree creation is sped up by not
586 * having to call g_vsnprintf and copy strings around.
589 proto_tree_set_visible(proto_tree *tree, gboolean visible)
591 gboolean old_visible = PTREE_DATA(tree)->visible;
593 PTREE_DATA(tree)->visible = visible;
599 proto_tree_set_fake_protocols(proto_tree *tree, gboolean fake_protocols)
601 PTREE_DATA(tree)->fake_protocols = fake_protocols;
604 /* Assume dissector set only its protocol fields.
605 This function is called by dissectors and allows the speeding up of filtering
606 in wireshark; if this function returns FALSE it is safe to reset tree to NULL
607 and thus skip calling most of the expensive proto_tree_add_...()
609 If the tree is visible we implicitly assume the field is referenced.
612 proto_field_is_referenced(proto_tree *tree, int proto_id)
614 register header_field_info *hfinfo;
620 if (PTREE_DATA(tree)->visible)
623 PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
624 if (hfinfo->ref_type != HF_REF_TYPE_NONE)
627 if (hfinfo->type == FT_PROTOCOL && !PTREE_DATA(tree)->fake_protocols)
634 /* Finds a record in the hfinfo array by id. */
636 proto_registrar_get_nth(guint hfindex)
638 register header_field_info *hfinfo;
640 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
645 /* Prefix initialization
646 * this allows for a dissector to register a display filter name prefix
647 * so that it can delay the initialization of the hf array as long as
651 /* compute a hash for the part before the dot of a display filter */
653 prefix_hash (gconstpointer key) {
654 /* end the string at the dot and compute its hash */
655 gchar* copy = ep_strdup((const gchar *)key);
665 return g_str_hash(copy);
668 /* are both strings equal up to the end or the dot? */
670 prefix_equal (gconstpointer ap, gconstpointer bp) {
671 const gchar* a = (const gchar *)ap;
672 const gchar* b = (const gchar *)bp;
678 if ( (ac == '.' || ac == '\0') && (bc == '.' || bc == '\0') ) return TRUE;
680 if ( (ac == '.' || ac == '\0') && ! (bc == '.' || bc == '\0') ) return FALSE;
681 if ( (bc == '.' || bc == '\0') && ! (ac == '.' || ac == '\0') ) return FALSE;
683 if (ac != bc) return FALSE;
690 /* indexed by prefix, contains initializers */
691 static GHashTable* prefixes = NULL;
694 /* Register a new prefix for "delayed" initialization of field arrays */
696 proto_register_prefix(const char *prefix, prefix_initializer_t pi ) {
698 prefixes = g_hash_table_new(prefix_hash, prefix_equal);
701 g_hash_table_insert(prefixes, (gpointer)prefix, pi);
704 /* helper to call all prefix initializers */
706 initialize_prefix(gpointer k, gpointer v, gpointer u _U_) {
707 ((prefix_initializer_t)v)((const char *)k);
711 /** Initialize every remaining uninitialized prefix. */
713 proto_initialize_all_prefixes(void) {
714 g_hash_table_foreach_remove(prefixes, initialize_prefix, NULL);
717 /* Finds a record in the hfinfo array by name.
718 * If it fails to find it in the already registered fields,
719 * it tries to find and call an initializer in the prefixes
720 * table and if so it looks again.
723 proto_registrar_get_byname(const char *field_name)
725 header_field_info *hfinfo;
726 prefix_initializer_t pi;
731 hfinfo = (header_field_info *)g_tree_lookup(gpa_name_tree, field_name);
739 if ((pi = (prefix_initializer_t)g_hash_table_lookup(prefixes, field_name) ) != NULL) {
741 g_hash_table_remove(prefixes, field_name);
746 return (header_field_info *)g_tree_lookup(gpa_name_tree, field_name);
750 proto_registrar_get_id_byname(const char *field_name)
752 header_field_info *hfinfo;
754 hfinfo = proto_registrar_get_byname(field_name);
764 ptvcursor_new_subtree_levels(ptvcursor_t *ptvc)
766 subtree_lvl *pushed_tree;
768 DISSECTOR_ASSERT(ptvc->pushed_tree_max <= SUBTREE_MAX_LEVELS-SUBTREE_ONCE_ALLOCATION_NUMBER);
769 ptvc->pushed_tree_max += SUBTREE_ONCE_ALLOCATION_NUMBER;
771 pushed_tree = (subtree_lvl *)ep_alloc(sizeof(subtree_lvl) * ptvc->pushed_tree_max);
772 DISSECTOR_ASSERT(pushed_tree != NULL);
773 if (ptvc->pushed_tree)
774 memcpy(pushed_tree, ptvc->pushed_tree, ptvc->pushed_tree_max - SUBTREE_ONCE_ALLOCATION_NUMBER);
775 ptvc->pushed_tree = pushed_tree;
779 ptvcursor_free_subtree_levels(ptvcursor_t *ptvc)
781 ptvc->pushed_tree = NULL;
782 ptvc->pushed_tree_max = 0;
783 DISSECTOR_ASSERT(ptvc->pushed_tree_index == 0);
784 ptvc->pushed_tree_index = 0;
787 /* Allocates an initializes a ptvcursor_t with 3 variables:
788 * proto_tree, tvbuff, and offset. */
790 ptvcursor_new(proto_tree *tree, tvbuff_t *tvb, gint offset)
794 ptvc = (ptvcursor_t *)ep_alloc(sizeof(ptvcursor_t));
797 ptvc->offset = offset;
798 ptvc->pushed_tree = NULL;
799 ptvc->pushed_tree_max = 0;
800 ptvc->pushed_tree_index = 0;
805 /* Frees memory for ptvcursor_t, but nothing deeper than that. */
807 ptvcursor_free(ptvcursor_t *ptvc)
809 ptvcursor_free_subtree_levels(ptvc);
813 /* Returns tvbuff. */
815 ptvcursor_tvbuff(ptvcursor_t *ptvc)
820 /* Returns current offset. */
822 ptvcursor_current_offset(ptvcursor_t *ptvc)
828 ptvcursor_tree(ptvcursor_t *ptvc)
837 ptvcursor_set_tree(ptvcursor_t *ptvc, proto_tree *tree)
842 /* creates a subtree, sets it as the working tree and pushes the old working tree */
844 ptvcursor_push_subtree(ptvcursor_t *ptvc, proto_item *it, gint ett_subtree)
846 subtree_lvl *subtree;
847 if (ptvc->pushed_tree_index >= ptvc->pushed_tree_max)
848 ptvcursor_new_subtree_levels(ptvc);
850 subtree = ptvc->pushed_tree + ptvc->pushed_tree_index;
851 subtree->tree = ptvc->tree;
853 ptvc->pushed_tree_index++;
854 return ptvcursor_set_subtree(ptvc, it, ett_subtree);
859 ptvcursor_pop_subtree(ptvcursor_t *ptvc)
861 subtree_lvl *subtree;
863 if (ptvc->pushed_tree_index <= 0)
866 ptvc->pushed_tree_index--;
867 subtree = ptvc->pushed_tree + ptvc->pushed_tree_index;
868 if (subtree->it != NULL)
869 proto_item_set_len(subtree->it, ptvcursor_current_offset(ptvc) - subtree->cursor_offset);
871 ptvc->tree = subtree->tree;
874 /* saves the current tvb offset and the item in the current subtree level */
876 ptvcursor_subtree_set_item(ptvcursor_t *ptvc, proto_item *it)
878 subtree_lvl *subtree;
880 DISSECTOR_ASSERT(ptvc->pushed_tree_index > 0);
882 subtree = ptvc->pushed_tree + ptvc->pushed_tree_index - 1;
884 subtree->cursor_offset = ptvcursor_current_offset(ptvc);
887 /* Creates a subtree and adds it to the cursor as the working tree but does not
888 * save the old working tree */
890 ptvcursor_set_subtree(ptvcursor_t *ptvc, proto_item *it, gint ett_subtree)
892 ptvc->tree = proto_item_add_subtree(it, ett_subtree);
897 ptvcursor_add_subtree_item(ptvcursor_t *ptvc, proto_item *it, gint ett_subtree, gint length)
899 ptvcursor_push_subtree(ptvc, it, ett_subtree);
900 if (length == SUBTREE_UNDEFINED_LENGTH)
901 ptvcursor_subtree_set_item(ptvc, it);
902 return ptvcursor_tree(ptvc);
905 /* Add an item to the tree and create a subtree
906 * If the length is unknown, length may be defined as SUBTREE_UNDEFINED_LENGTH.
907 * In this case, when the subtree will be closed, the parent item length will
908 * be equal to the advancement of the cursor since the creation of the subtree.
911 ptvcursor_add_with_subtree(ptvcursor_t *ptvc, int hfindex, gint length,
912 const guint encoding, gint ett_subtree)
916 it = ptvcursor_add_no_advance(ptvc, hfindex, length, encoding);
917 return ptvcursor_add_subtree_item(ptvc, it, ett_subtree, length);
921 proto_tree_add_text_node(proto_tree *tree, tvbuff_t *tvb, gint start, gint length);
923 /* Add a text node to the tree and create a subtree
924 * If the length is unknown, length may be defined as SUBTREE_UNDEFINED_LENGTH.
925 * In this case, when the subtree will be closed, the item length will be equal
926 * to the advancement of the cursor since the creation of the subtree.
929 ptvcursor_add_text_with_subtree(ptvcursor_t *ptvc, gint length,
930 gint ett_subtree, const char *format, ...)
934 header_field_info *hfinfo;
937 tree = ptvcursor_tree(ptvc);
939 TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
941 pi = proto_tree_add_text_node(tree, ptvcursor_tvbuff(ptvc),
942 ptvcursor_current_offset(ptvc), length);
944 TRY_TO_FAKE_THIS_REPR(pi);
946 va_start(ap, format);
947 proto_tree_set_representation(pi, format, ap);
950 return ptvcursor_add_subtree_item(ptvc, pi, ett_subtree, length);
953 /* Add a text-only node, leaving it to our caller to fill the text in */
955 proto_tree_add_text_node(proto_tree *tree, tvbuff_t *tvb, gint start, gint length)
962 pi = proto_tree_add_pi(tree, &hfi_text_only, tvb, start, &length);
967 /* Add a text-only node to the proto_tree */
969 proto_tree_add_text(proto_tree *tree, tvbuff_t *tvb, gint start, gint length,
970 const char *format, ...)
974 header_field_info *hfinfo;
976 TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
978 pi = proto_tree_add_text_node(tree, tvb, start, length);
980 TRY_TO_FAKE_THIS_REPR(pi);
982 va_start(ap, format);
983 proto_tree_set_representation(pi, format, ap);
989 /* Add a text-only node to the proto_tree (va_list version) */
991 proto_tree_add_text_valist(proto_tree *tree, tvbuff_t *tvb, gint start,
992 gint length, const char *format, va_list ap)
995 header_field_info *hfinfo;
997 TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
999 pi = proto_tree_add_text_node(tree, tvb, start, length);
1001 TRY_TO_FAKE_THIS_REPR(pi);
1003 proto_tree_set_representation(pi, format, ap);
1008 /* Add a text-only node for debugging purposes. The caller doesn't need
1009 * to worry about tvbuff, start, or length. Debug message gets sent to
1012 proto_tree_add_debug_text(proto_tree *tree, const char *format, ...)
1017 pi = proto_tree_add_text_node(tree, NULL, 0, 0);
1020 va_start(ap, format);
1021 proto_tree_set_representation(pi, format, ap);
1024 va_start(ap, format);
1025 vprintf(format, ap);
1032 /* We could probably get away with changing is_error to a minimum length value. */
1034 report_type_length_mismatch(proto_tree *tree, const gchar *descr, int length, gboolean is_error) {
1037 expert_add_info_format(NULL, tree, &ei_type_length_mismatch_error, "Trying to fetch %s with length %d", descr, length);
1039 expert_add_info_format(NULL, tree, &ei_type_length_mismatch_warn, "Trying to fetch %s with length %d", descr, length);
1043 THROW(ReportedBoundsError);
1048 get_uint_value(proto_tree *tree, tvbuff_t *tvb, gint offset, gint length, const guint encoding)
1051 gboolean length_error;
1056 value = tvb_get_guint8(tvb, offset);
1060 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letohs(tvb, offset)
1061 : tvb_get_ntohs(tvb, offset);
1065 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letoh24(tvb, offset)
1066 : tvb_get_ntoh24(tvb, offset);
1070 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letohl(tvb, offset)
1071 : tvb_get_ntohl(tvb, offset);
1076 length_error = TRUE;
1079 length_error = FALSE;
1080 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letohl(tvb, offset)
1081 : tvb_get_ntohl(tvb, offset);
1083 report_type_length_mismatch(tree, "an unsigned integer", length, length_error);
1090 * NOTE: to support code written when proto_tree_add_item() took a
1091 * gboolean as its last argument, with FALSE meaning "big-endian"
1092 * and TRUE meaning "little-endian", we treat any non-zero value of
1093 * "encoding" as meaning "little-endian".
1096 get_int_value(proto_tree *tree, tvbuff_t *tvb, gint offset, gint length, const guint encoding)
1099 gboolean length_error;
1104 value = (gint8)tvb_get_guint8(tvb, offset);
1108 value = (gint16) (encoding ? tvb_get_letohs(tvb, offset)
1109 : tvb_get_ntohs(tvb, offset));
1113 value = encoding ? tvb_get_letoh24(tvb, offset)
1114 : tvb_get_ntoh24(tvb, offset);
1115 if (value & 0x00800000) {
1116 /* Sign bit is set; sign-extend it. */
1117 value |= 0xFF000000;
1122 value = encoding ? tvb_get_letohl(tvb, offset)
1123 : tvb_get_ntohl(tvb, offset);
1128 length_error = TRUE;
1131 length_error = FALSE;
1132 value = encoding ? tvb_get_letohl(tvb, offset)
1133 : tvb_get_ntohl(tvb, offset);
1135 report_type_length_mismatch(tree, "a signed integer", length, length_error);
1142 tree_data_add_maybe_interesting_field(tree_data_t *tree_data, field_info *fi)
1144 const header_field_info *hfinfo = fi->hfinfo;
1146 if (hfinfo->ref_type == HF_REF_TYPE_DIRECT) {
1147 GPtrArray *ptrs = NULL;
1149 if (tree_data->interesting_hfids == NULL) {
1150 /* Initialize the hash because we now know that it is needed */
1151 tree_data->interesting_hfids =
1152 g_hash_table_new(g_direct_hash, NULL /* g_direct_equal */);
1154 ptrs = (GPtrArray *)g_hash_table_lookup(tree_data->interesting_hfids,
1155 GINT_TO_POINTER(hfinfo->id));
1157 /* First element triggers the creation of pointer array */
1158 ptrs = g_ptr_array_new();
1159 g_hash_table_insert(tree_data->interesting_hfids,
1160 GINT_TO_POINTER(hfinfo->id), ptrs);
1163 g_ptr_array_add(ptrs, fi);
1167 /* Add an item to a proto_tree, using the text label registered to that item;
1168 the item is extracted from the tvbuff handed to it. */
1170 proto_tree_new_item(field_info *new_fi, proto_tree *tree,
1171 tvbuff_t *tvb, gint start, gint length,
1179 nstime_t time_stamp;
1182 gboolean length_error;
1184 switch (new_fi->hfinfo->type) {
1186 /* no value to set for FT_NONE */
1190 proto_tree_set_protocol_tvb(new_fi, tvb);
1194 proto_tree_set_bytes_tvb(new_fi, tvb, start, length);
1199 * Map all non-zero values to little-endian for
1200 * backwards compatibility.
1203 encoding = ENC_LITTLE_ENDIAN;
1204 n = get_uint_value(tree, tvb, start, length, encoding);
1205 proto_tree_set_bytes_tvb(new_fi, tvb, start + length, n);
1207 /* Instead of calling proto_item_set_len(), since we don't yet
1208 * have a proto_item, we set the field_info's length ourselves. */
1209 new_fi->length = n + length;
1214 * Map all non-zero values to little-endian for
1215 * backwards compatibility.
1218 encoding = ENC_LITTLE_ENDIAN;
1219 proto_tree_set_boolean(new_fi,
1220 get_uint_value(tree, tvb, start, length, encoding));
1223 /* XXX - make these just FT_UINT? */
1229 * Map all non-zero values to little-endian for
1230 * backwards compatibility.
1233 encoding = ENC_LITTLE_ENDIAN;
1234 proto_tree_set_uint(new_fi,
1235 get_uint_value(tree, tvb, start, length, encoding));
1241 * Map all non-zero values to little-endian for
1242 * backwards compatibility.
1245 encoding = ENC_LITTLE_ENDIAN;
1246 if (length < 1 || length > 8) {
1247 length_error = length < 1 ? TRUE : FALSE;
1248 report_type_length_mismatch(tree, "a 64-bit integer", length, length_error);
1250 proto_tree_set_uint64_tvb(new_fi, tvb, start, length, encoding);
1253 /* XXX - make these just FT_INT? */
1259 * Map all non-zero values to little-endian for
1260 * backwards compatibility.
1263 encoding = ENC_LITTLE_ENDIAN;
1264 proto_tree_set_int(new_fi,
1265 get_int_value(tree, tvb, start, length, encoding));
1270 * Map all non-zero values to little-endian for
1271 * backwards compatibility.
1274 encoding = ENC_LITTLE_ENDIAN;
1275 if (length != FT_IPv4_LEN) {
1276 length_error = length < FT_IPv4_LEN ? TRUE : FALSE;
1277 report_type_length_mismatch(tree, "an IPv4 address", length, length_error);
1279 value = tvb_get_ipv4(tvb, start);
1281 * NOTE: to support code written when
1282 * proto_tree_add_item() took a gboolean as its
1283 * last argument, with FALSE meaning "big-endian"
1284 * and TRUE meaning "little-endian", we treat any
1285 * non-zero value of "encoding" as meaning
1288 proto_tree_set_ipv4(new_fi, encoding ? GUINT32_SWAP_LE_BE(value) : value);
1292 if (length != FT_IPXNET_LEN) {
1293 length_error = length < FT_IPXNET_LEN ? TRUE : FALSE;
1294 report_type_length_mismatch(tree, "an IPXNET address", length, length_error);
1296 proto_tree_set_ipxnet(new_fi,
1297 get_uint_value(tree, tvb, start, FT_IPXNET_LEN, ENC_BIG_ENDIAN));
1301 if (length != FT_IPv6_LEN) {
1302 length_error = length < FT_IPv6_LEN ? TRUE : FALSE;
1303 report_type_length_mismatch(tree, "an IPv6 address", length, length_error);
1305 proto_tree_set_ipv6_tvb(new_fi, tvb, start, length);
1310 length_error = length < 7 ? TRUE : FALSE;
1311 report_type_length_mismatch(tree, "an AX.25 address", length, length_error);
1313 proto_tree_set_ax25_tvb(new_fi, tvb, start);
1317 if (length != VINES_ADDR_LEN) {
1318 length_error = length < VINES_ADDR_LEN ? TRUE : FALSE;
1319 report_type_length_mismatch(tree, "a Vines address", length, length_error);
1321 proto_tree_set_vines_tvb(new_fi, tvb, start);
1325 if (length != FT_ETHER_LEN) {
1326 length_error = length < FT_ETHER_LEN ? TRUE : FALSE;
1327 report_type_length_mismatch(tree, "an Ethernet", length, length_error);
1329 proto_tree_set_ether_tvb(new_fi, tvb, start);
1334 * Map all non-zero values to little-endian for
1335 * backwards compatibility.
1338 encoding = ENC_LITTLE_ENDIAN;
1339 if (length != FT_EUI64_LEN) {
1340 length_error = length < FT_EUI64_LEN ? TRUE : FALSE;
1341 report_type_length_mismatch(tree, "an EUI-64 address", length, length_error);
1343 proto_tree_set_eui64_tvb(new_fi, tvb, start, encoding);
1347 * Map all non-zero values to little-endian for
1348 * backwards compatibility.
1351 encoding = ENC_LITTLE_ENDIAN;
1352 if (length != FT_GUID_LEN) {
1353 length_error = length < FT_GUID_LEN ? TRUE : FALSE;
1354 report_type_length_mismatch(tree, "a GUID", length, length_error);
1356 proto_tree_set_guid_tvb(new_fi, tvb, start, encoding);
1361 proto_tree_set_oid_tvb(new_fi, tvb, start, length);
1366 * NOTE: to support code written when
1367 * proto_tree_add_item() took a gboolean as its
1368 * last argument, with FALSE meaning "big-endian"
1369 * and TRUE meaning "little-endian", we treat any
1370 * non-zero value of "encoding" as meaning
1373 * At some point in the future, we might
1374 * support non-IEEE-binary floating-point
1375 * formats in the encoding as well
1376 * (IEEE decimal, System/3x0, VAX).
1379 encoding = ENC_LITTLE_ENDIAN;
1381 length_error = length < 4 ? TRUE : FALSE;
1382 report_type_length_mismatch(tree, "a single-precision floating point number", length, length_error);
1385 floatval = tvb_get_letohieee_float(tvb, start);
1387 floatval = tvb_get_ntohieee_float(tvb, start);
1388 proto_tree_set_float(new_fi, floatval);
1393 * NOTE: to support code written when
1394 * proto_tree_add_item() took a gboolean as its
1395 * last argument, with FALSE meaning "big-endian"
1396 * and TRUE meaning "little-endian", we treat any
1397 * non-zero value of "encoding" as meaning
1400 * At some point in the future, we might
1401 * support non-IEEE-binary floating-point
1402 * formats in the encoding as well
1403 * (IEEE decimal, System/3x0, VAX).
1405 if (encoding == TRUE)
1406 encoding = ENC_LITTLE_ENDIAN;
1408 length_error = length < 8 ? TRUE : FALSE;
1409 report_type_length_mismatch(tree, "a double-precision floating point number", length, length_error);
1412 doubleval = tvb_get_letohieee_double(tvb, start);
1414 doubleval = tvb_get_ntohieee_double(tvb, start);
1415 proto_tree_set_double(new_fi, doubleval);
1419 proto_tree_set_string_tvb(new_fi, tvb, start, length,
1425 report_type_length_mismatch(tree, "a string", length, TRUE);
1427 /* Instead of calling proto_item_set_len(),
1428 * since we don't yet have a proto_item, we
1429 * set the field_info's length ourselves.
1431 * XXX - our caller can't use that length to
1432 * advance an offset unless they arrange that
1433 * there always be a protocol tree into which
1434 * we're putting this item.
1437 /* This can throw an exception */
1438 string = tvb_get_stringz_enc(wmem_packet_scope(), tvb, start, &length, encoding);
1439 } else if (length == 0) {
1442 /* In this case, length signifies
1443 * the length of the string.
1445 * This could either be a null-padded
1446 * string, which doesn't necessarily
1447 * have a '\0' at the end, or a
1448 * null-terminated string, with a
1449 * trailing '\0'. (Yes, there are
1450 * cases where you have a string
1451 * that's both counted and null-
1454 * In the first case, we must
1455 * allocate a buffer of length
1456 * "length+1", to make room for
1459 * In the second case, we don't
1460 * assume that there is a trailing
1461 * '\0' there, as the packet might
1462 * be malformed. (XXX - should we
1463 * throw an exception if there's no
1464 * trailing '\0'?) Therefore, we
1465 * allocate a buffer of length
1466 * "length+1", and put in a trailing
1467 * '\0', just to be safe.
1469 * (XXX - this would change if
1470 * we made string values counted
1471 * rather than null-terminated.)
1473 string = tvb_get_string_enc(wmem_packet_scope(), tvb, start, length, encoding);
1475 new_fi->length = length;
1476 proto_tree_set_string(new_fi, string);
1479 case FT_UINT_STRING:
1481 * NOTE: to support code written when
1482 * proto_tree_add_item() took a gboolean as its
1483 * last argument, with FALSE meaning "big-endian"
1484 * and TRUE meaning "little-endian", if the
1485 * encoding value is TRUE, treat that as
1486 * ASCII with a little-endian length.
1488 * This won't work for code that passes
1489 * arbitrary non-zero values; that code
1490 * will need to be fixed.
1492 if (encoding == TRUE)
1493 encoding = ENC_ASCII|ENC_LITTLE_ENDIAN;
1494 n = get_uint_value(tree, tvb, start, length, encoding & ~ENC_CHARENCODING_MASK);
1495 proto_tree_set_string_tvb(new_fi, tvb, start + length, n,
1498 /* Instead of calling proto_item_set_len(), since we
1499 * don't yet have a proto_item, we set the
1500 * field_info's length ourselves.
1502 * XXX - our caller can't use that length to
1503 * advance an offset unless they arrange that
1504 * there always be a protocol tree into which
1505 * we're putting this item.
1507 new_fi->length = n + length;
1510 case FT_ABSOLUTE_TIME:
1512 * Absolute times can be in any of a number of
1513 * formats, and they can be big-endian or
1516 * Historically FT_TIMEs were only timespecs;
1517 * the only question was whether they were stored
1518 * in big- or little-endian format.
1520 * For backwards compatibility, we interpret an
1521 * encoding of 1 as meaning "little-endian timespec",
1522 * so that passing TRUE is interpreted as that.
1524 if (encoding == TRUE)
1525 encoding = ENC_TIME_TIMESPEC|ENC_LITTLE_ENDIAN;
1527 if (length != 8 && length != 4) {
1528 length_error = length < 4 ? TRUE : FALSE;
1529 report_type_length_mismatch(tree, "an absolute time value", length, length_error);
1534 case ENC_TIME_TIMESPEC|ENC_BIG_ENDIAN:
1536 * 4-byte UNIX epoch, possibly followed by
1537 * 4-byte fractional time in nanoseconds,
1540 time_stamp.secs = tvb_get_ntohl(tvb, start);
1542 time_stamp.nsecs = tvb_get_ntohl(tvb, start+4);
1544 time_stamp.nsecs = 0;
1547 case ENC_TIME_TIMESPEC|ENC_LITTLE_ENDIAN:
1549 * 4-byte UNIX epoch, possibly followed by
1550 * 4-byte fractional time in nanoseconds,
1551 * both little-endian.
1553 time_stamp.secs = tvb_get_letohl(tvb, start);
1555 time_stamp.nsecs = tvb_get_letohl(tvb, start+4);
1557 time_stamp.nsecs = 0;
1560 case ENC_TIME_TOD|ENC_BIG_ENDIAN:
1562 * TOD time stamp, big-endian.
1564 /* XXX - where should this go? */
1565 #define TOD_BASETIME 2208988800ul
1567 todsecs = tvb_get_ntoh64(tvb, start) >> 12;
1568 time_stamp.secs = (time_t)((todsecs / 1000000) - TOD_BASETIME);
1569 time_stamp.nsecs = (int)((todsecs % 1000000) * 1000);
1572 case ENC_TIME_TOD|ENC_LITTLE_ENDIAN:
1574 * TOD time stamp, big-endian.
1576 todsecs = tvb_get_letoh64(tvb, start) >> 12 ;
1577 time_stamp.secs = (time_t)((todsecs / 1000000) - TOD_BASETIME);
1578 time_stamp.nsecs = (int)((todsecs % 1000000) * 1000);
1581 case ENC_TIME_NTP|ENC_BIG_ENDIAN:
1583 * NTP time stamp, big-endian.
1586 /* XXX - where should this go? */
1587 #define NTP_BASETIME 2208988800ul
1589 /* We need a temporary variable here so the unsigned math
1590 * works correctly (for years > 2036 according to RFC 2030
1593 tmpsecs = tvb_get_ntohl(tvb, start);
1595 time_stamp.secs = tmpsecs - (guint32)NTP_BASETIME;
1597 time_stamp.secs = tmpsecs; /* 0 */
1601 * We're using nanoseconds here (and we will
1602 * display nanoseconds), but NTP's timestamps
1603 * have a precision in microseconds or greater.
1604 * Round to 1 microsecond.
1606 time_stamp.nsecs = (int)(1000000*(tvb_get_ntohl(tvb, start+4)/4294967296.0));
1607 time_stamp.nsecs *= 1000;
1609 time_stamp.nsecs = 0;
1613 case ENC_TIME_NTP|ENC_LITTLE_ENDIAN:
1615 * NTP time stamp, big-endian.
1617 tmpsecs = tvb_get_letohl(tvb, start);
1619 time_stamp.secs = tmpsecs - (guint32)NTP_BASETIME;
1621 time_stamp.secs = tmpsecs; /* 0 */
1625 * We're using nanoseconds here (and we will
1626 * display nanoseconds), but NTP's timestamps
1627 * have a precision in microseconds or greater.
1628 * Round to 1 microsecond.
1630 time_stamp.nsecs = (int)(1000000*(tvb_get_letohl(tvb, start+4)/4294967296.0));
1631 time_stamp.nsecs *= 1000;
1633 time_stamp.nsecs = 0;
1638 DISSECTOR_ASSERT_NOT_REACHED();
1639 time_stamp.secs = 0;
1640 time_stamp.nsecs = 0;
1643 proto_tree_set_time(new_fi, &time_stamp);
1646 case FT_RELATIVE_TIME:
1648 * Relative times can be in any of a number of
1649 * formats, and they can be big-endian or
1652 * Historically FT_TIMEs were only timespecs;
1653 * the only question was whether they were stored
1654 * in big- or little-endian format.
1656 * For backwards compatibility, we interpret an
1657 * encoding of 1 as meaning "little-endian timespec",
1658 * so that passing TRUE is interpreted as that.
1660 if (encoding == TRUE)
1661 encoding = ENC_TIME_TIMESPEC|ENC_LITTLE_ENDIAN;
1664 if (length != 8 && length != 4) {
1665 length_error = length < 4 ? TRUE : FALSE;
1666 report_type_length_mismatch(tree, "a relative time value", length, length_error);
1669 case ENC_TIME_TIMESPEC|ENC_BIG_ENDIAN:
1671 * 4-byte UNIX epoch, possibly followed by
1672 * 4-byte fractional time in nanoseconds,
1675 time_stamp.secs = tvb_get_ntohl(tvb, start);
1677 time_stamp.nsecs = tvb_get_ntohl(tvb, start+4);
1679 time_stamp.nsecs = 0;
1682 case ENC_TIME_TIMESPEC|ENC_LITTLE_ENDIAN:
1684 * 4-byte UNIX epoch, possibly followed by
1685 * 4-byte fractional time in nanoseconds,
1686 * both little-endian.
1688 time_stamp.secs = tvb_get_letohl(tvb, start);
1690 time_stamp.nsecs = tvb_get_letohl(tvb, start+4);
1692 time_stamp.nsecs = 0;
1695 proto_tree_set_time(new_fi, &time_stamp);
1699 g_error("new_fi->hfinfo->type %d (%s) not handled\n",
1700 new_fi->hfinfo->type,
1701 ftype_name(new_fi->hfinfo->type));
1702 DISSECTOR_ASSERT_NOT_REACHED();
1705 FI_SET_FLAG(new_fi, (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN);
1707 /* Don't add new node to proto_tree until now so that any exceptions
1708 * raised by a tvbuff access method doesn't leave junk in the proto_tree. */
1709 /* XXX. wouldn't be better to add this item to tree, with some special flag (FI_EXCEPTION?)
1710 * to know which item caused exception? */
1711 pi = proto_tree_add_node(tree, new_fi);
1716 /* Gets data from tvbuff, adds it to proto_tree, increments offset,
1717 and returns proto_item* */
1719 ptvcursor_add(ptvcursor_t *ptvc, int hfindex, gint length,
1720 const guint encoding)
1723 header_field_info *hfinfo;
1728 /* We can't fake it just yet. We have to advance the cursor
1729 TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfindex, hfinfo); */
1731 offset = ptvc->offset;
1732 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1733 get_hfi_length(hfinfo, ptvc->tvb, offset, &length, &item_length);
1734 ptvc->offset += length;
1735 if (hfinfo->type == FT_UINT_BYTES || hfinfo->type == FT_UINT_STRING) {
1737 * The length of the rest of the item is in the first N
1738 * bytes of the item.
1740 n = get_uint_value(ptvc->tree, ptvc->tvb, offset, length, encoding);
1744 /* Coast clear. Try and fake it */
1745 TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfindex, hfinfo);
1747 new_fi = new_field_info(ptvc->tree, hfinfo, ptvc->tvb, offset, item_length);
1749 return proto_tree_new_item(new_fi, ptvc->tree, ptvc->tvb,
1750 offset, length, encoding);
1754 * Validates that field length bytes are available starting from
1755 * start (pos/neg). Throws an exception if they aren't.
1758 test_length(header_field_info *hfinfo, proto_tree *tree, tvbuff_t *tvb,
1759 gint start, gint length, const guint encoding)
1766 if (hfinfo->type == FT_UINT_BYTES || hfinfo->type == FT_UINT_STRING) {
1769 n = get_uint_value(tree, tvb, start, length, encoding);
1771 /* If n > size + n then we have an integer overflow, so
1772 * set size to -1, which will force the
1773 * tvb_ensure_bytes_exist call below to throw a
1774 * ReportedBoundsError
1781 } else if (hfinfo->type == FT_STRINGZ) {
1782 /* If we're fetching until the end of the TVB, only validate
1783 * that the offset is within range.
1789 tvb_ensure_bytes_exist(tvb, start, size);
1792 /* Add an item to a proto_tree, using the text label registered to that item;
1793 the item is extracted from the tvbuff handed to it. */
1795 proto_tree_add_item_new(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
1796 const gint start, gint length, const guint encoding)
1801 DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");
1803 get_hfi_length(hfinfo, tvb, start, &length, &item_length);
1804 test_length(hfinfo, tree, tvb, start, item_length, encoding);
1806 TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
1808 new_fi = new_field_info(tree, hfinfo, tvb, start, item_length);
1813 return proto_tree_new_item(new_fi, tree, tvb, start, length, encoding);
1817 proto_tree_add_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1818 const gint start, gint length, const guint encoding)
1820 return proto_tree_add_item_new(tree, proto_registrar_get_nth(hfindex), tvb, start, length, encoding);
1823 /* Add a FT_NONE to a proto_tree */
1825 proto_tree_add_none_format(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
1826 const gint start, gint length, const char *format,
1831 header_field_info *hfinfo;
1833 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1835 DISSECTOR_ASSERT(hfinfo->type == FT_NONE);
1837 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
1839 TRY_TO_FAKE_THIS_REPR(pi);
1841 va_start(ap, format);
1842 proto_tree_set_representation(pi, format, ap);
1845 /* no value to set for FT_NONE */
1849 /* Gets data from tvbuff, adds it to proto_tree, *DOES NOT* increment
1850 * offset, and returns proto_item* */
1852 ptvcursor_add_no_advance(ptvcursor_t* ptvc, int hf, gint length,
1853 const guint encoding)
1857 item = proto_tree_add_item(ptvc->tree, hf, ptvc->tvb, ptvc->offset,
1863 /* Advance the ptvcursor's offset within its tvbuff without
1864 * adding anything to the proto_tree. */
1866 ptvcursor_advance(ptvcursor_t* ptvc, gint length)
1868 ptvc->offset += length;
1873 proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb)
1875 fvalue_set(&fi->value, tvb, TRUE);
1878 /* Add a FT_PROTOCOL to a proto_tree */
1880 proto_tree_add_protocol_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1881 gint start, gint length, const char *format, ...)
1885 header_field_info *hfinfo;
1887 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1889 DISSECTOR_ASSERT(hfinfo->type == FT_PROTOCOL);
1891 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
1893 proto_tree_set_protocol_tvb(PNODE_FINFO(pi), (start == 0 ? tvb : tvb_new_subset(tvb, start, length, length)));
1895 TRY_TO_FAKE_THIS_REPR(pi);
1897 va_start(ap, format);
1898 proto_tree_set_representation(pi, format, ap);
1905 /* Add a FT_BYTES to a proto_tree */
1907 proto_tree_add_bytes(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1908 gint length, const guint8 *start_ptr)
1911 header_field_info *hfinfo;
1913 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1915 DISSECTOR_ASSERT(hfinfo->type == FT_BYTES);
1917 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
1918 proto_tree_set_bytes(PNODE_FINFO(pi), start_ptr, length);
1924 proto_tree_add_bytes_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1925 gint start, gint length,
1926 const guint8 *start_ptr,
1927 const char *format, ...)
1931 header_field_info *hfinfo;
1933 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1936 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length,
1939 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length,
1940 tvb_get_ptr(tvb, start, length));
1942 va_start(ap, format);
1943 proto_tree_set_representation_value(pi, format, ap);
1950 proto_tree_add_bytes_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1951 gint start, gint length, const guint8 *start_ptr,
1952 const char *format, ...)
1956 header_field_info *hfinfo;
1958 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1961 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length,
1964 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length,
1965 tvb_get_ptr(tvb, start, length));
1967 TRY_TO_FAKE_THIS_REPR(pi);
1969 va_start(ap, format);
1970 proto_tree_set_representation(pi, format, ap);
1977 proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length)
1981 DISSECTOR_ASSERT(start_ptr != NULL || length == 0);
1983 bytes = g_byte_array_new();
1985 g_byte_array_append(bytes, start_ptr, length);
1987 fvalue_set(&fi->value, bytes, TRUE);
1992 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length)
1994 proto_tree_set_bytes(fi, tvb_get_ptr(tvb, offset, length), length);
1997 /* Add a FT_*TIME to a proto_tree */
1999 proto_tree_add_time(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2000 gint length, nstime_t *value_ptr)
2003 header_field_info *hfinfo;
2005 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2007 DISSECTOR_ASSERT(hfinfo->type == FT_ABSOLUTE_TIME ||
2008 hfinfo->type == FT_RELATIVE_TIME);
2010 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
2011 proto_tree_set_time(PNODE_FINFO(pi), value_ptr);
2017 proto_tree_add_time_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2018 gint start, gint length, nstime_t *value_ptr,
2019 const char *format, ...)
2024 pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
2026 va_start(ap, format);
2027 proto_tree_set_representation_value(pi, format, ap);
2035 proto_tree_add_time_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2036 gint start, gint length, nstime_t *value_ptr,
2037 const char *format, ...)
2042 pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
2044 TRY_TO_FAKE_THIS_REPR(pi);
2046 va_start(ap, format);
2047 proto_tree_set_representation(pi, format, ap);
2054 /* Set the FT_*TIME value */
2056 proto_tree_set_time(field_info *fi, nstime_t *value_ptr)
2058 DISSECTOR_ASSERT(value_ptr != NULL);
2060 fvalue_set(&fi->value, value_ptr, FALSE);
2063 /* Add a FT_IPXNET to a proto_tree */
2065 proto_tree_add_ipxnet(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2066 gint length, guint32 value)
2069 header_field_info *hfinfo;
2071 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2073 DISSECTOR_ASSERT(hfinfo->type == FT_IPXNET);
2075 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
2076 proto_tree_set_ipxnet(PNODE_FINFO(pi), value);
2082 proto_tree_add_ipxnet_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2083 gint start, gint length, guint32 value,
2084 const char *format, ...)
2089 pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
2091 va_start(ap, format);
2092 proto_tree_set_representation_value(pi, format, ap);
2100 proto_tree_add_ipxnet_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2101 gint start, gint length, guint32 value,
2102 const char *format, ...)
2107 pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
2109 TRY_TO_FAKE_THIS_REPR(pi);
2111 va_start(ap, format);
2112 proto_tree_set_representation(pi, format, ap);
2119 /* Set the FT_IPXNET value */
2121 proto_tree_set_ipxnet(field_info *fi, guint32 value)
2123 fvalue_set_uinteger(&fi->value, value);
2126 /* Add a FT_IPv4 to a proto_tree */
2128 proto_tree_add_ipv4(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2129 gint length, guint32 value)
2132 header_field_info *hfinfo;
2134 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2136 DISSECTOR_ASSERT(hfinfo->type == FT_IPv4);
2138 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
2139 proto_tree_set_ipv4(PNODE_FINFO(pi), value);
2145 proto_tree_add_ipv4_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2146 gint start, gint length, guint32 value,
2147 const char *format, ...)
2152 pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
2154 va_start(ap, format);
2155 proto_tree_set_representation_value(pi, format, ap);
2163 proto_tree_add_ipv4_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2164 gint start, gint length, guint32 value,
2165 const char *format, ...)
2170 pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
2172 TRY_TO_FAKE_THIS_REPR(pi);
2174 va_start(ap, format);
2175 proto_tree_set_representation(pi, format, ap);
2182 /* Set the FT_IPv4 value */
2184 proto_tree_set_ipv4(field_info *fi, guint32 value)
2186 fvalue_set_uinteger(&fi->value, value);
2189 /* Add a FT_IPv6 to a proto_tree */
2191 proto_tree_add_ipv6(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2192 gint length, const guint8* value_ptr)
2195 header_field_info *hfinfo;
2197 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2199 DISSECTOR_ASSERT(hfinfo->type == FT_IPv6);
2201 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
2202 proto_tree_set_ipv6(PNODE_FINFO(pi), value_ptr);
2208 proto_tree_add_ipv6_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2209 gint start, gint length,
2210 const guint8* value_ptr,
2211 const char *format, ...)
2216 pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
2218 va_start(ap, format);
2219 proto_tree_set_representation_value(pi, format, ap);
2227 proto_tree_add_ipv6_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2228 gint start, gint length, const guint8* value_ptr,
2229 const char *format, ...)
2234 pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
2236 TRY_TO_FAKE_THIS_REPR(pi);
2238 va_start(ap, format);
2239 proto_tree_set_representation(pi, format, ap);
2246 /* Set the FT_IPv6 value */
2248 proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr)
2250 DISSECTOR_ASSERT(value_ptr != NULL);
2251 fvalue_set(&fi->value, (gpointer) value_ptr, FALSE);
2255 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
2257 proto_tree_set_ipv6(fi, tvb_get_ptr(tvb, start, length));
2260 /* Add a FT_GUID to a proto_tree */
2262 proto_tree_add_guid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2263 gint length, const e_guid_t *value_ptr)
2266 header_field_info *hfinfo;
2268 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2270 DISSECTOR_ASSERT(hfinfo->type == FT_GUID);
2272 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
2273 proto_tree_set_guid(PNODE_FINFO(pi), value_ptr);
2279 proto_tree_add_guid_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2280 gint start, gint length,
2281 const e_guid_t *value_ptr,
2282 const char *format, ...)
2287 pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
2289 va_start(ap, format);
2290 proto_tree_set_representation_value(pi, format, ap);
2298 proto_tree_add_guid_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2299 gint start, gint length, const e_guid_t *value_ptr,
2300 const char *format, ...)
2305 pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
2307 TRY_TO_FAKE_THIS_REPR(pi);
2309 va_start(ap, format);
2310 proto_tree_set_representation(pi, format, ap);
2317 /* Set the FT_GUID value */
2319 proto_tree_set_guid(field_info *fi, const e_guid_t *value_ptr)
2321 DISSECTOR_ASSERT(value_ptr != NULL);
2322 fvalue_set(&fi->value, (gpointer) value_ptr, FALSE);
2326 proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, gint start,
2327 const guint encoding)
2331 tvb_get_guid(tvb, start, &guid, encoding);
2332 proto_tree_set_guid(fi, &guid);
2335 /* Add a FT_OID to a proto_tree */
2337 proto_tree_add_oid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2338 gint length, const guint8* value_ptr)
2341 header_field_info *hfinfo;
2343 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2345 DISSECTOR_ASSERT(hfinfo->type == FT_OID);
2347 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
2348 proto_tree_set_oid(PNODE_FINFO(pi), value_ptr, length);
2354 proto_tree_add_oid_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2355 gint start, gint length,
2356 const guint8* value_ptr,
2357 const char *format, ...)
2362 pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
2364 va_start(ap, format);
2365 proto_tree_set_representation_value(pi, format, ap);
2373 proto_tree_add_oid_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2374 gint start, gint length, const guint8* value_ptr,
2375 const char *format, ...)
2380 pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
2382 TRY_TO_FAKE_THIS_REPR(pi);
2384 va_start(ap, format);
2385 proto_tree_set_representation(pi, format, ap);
2392 /* Set the FT_OID value */
2394 proto_tree_set_oid(field_info *fi, const guint8* value_ptr, gint length)
2398 DISSECTOR_ASSERT(value_ptr != NULL || length == 0);
2400 bytes = g_byte_array_new();
2402 g_byte_array_append(bytes, value_ptr, length);
2404 fvalue_set(&fi->value, bytes, TRUE);
2408 proto_tree_set_oid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
2410 proto_tree_set_oid(fi, tvb_get_ptr(tvb, start, length), length);
2414 proto_tree_set_uint64(field_info *fi, guint64 value)
2416 fvalue_set_integer64(&fi->value, value);
2420 * NOTE: to support code written when proto_tree_add_item() took a
2421 * gboolean as its last argument, with FALSE meaning "big-endian"
2422 * and TRUE meaning "little-endian", we treat any non-zero value of
2423 * "encoding" as meaning "little-endian".
2426 proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start,
2427 guint length, const guint encoding)
2430 guint8* b = (guint8 *)tvb_memdup(wmem_packet_scope(), tvb, start, length);
2435 default: DISSECTOR_ASSERT_NOT_REACHED();
2436 case 8: value <<= 8; value += *--b;
2437 case 7: value <<= 8; value += *--b;
2438 case 6: value <<= 8; value += *--b;
2439 case 5: value <<= 8; value += *--b;
2440 case 4: value <<= 8; value += *--b;
2441 case 3: value <<= 8; value += *--b;
2442 case 2: value <<= 8; value += *--b;
2443 case 1: value <<= 8; value += *--b;
2448 default: DISSECTOR_ASSERT_NOT_REACHED();
2449 case 8: value <<= 8; value += *b++;
2450 case 7: value <<= 8; value += *b++;
2451 case 6: value <<= 8; value += *b++;
2452 case 5: value <<= 8; value += *b++;
2453 case 4: value <<= 8; value += *b++;
2454 case 3: value <<= 8; value += *b++;
2455 case 2: value <<= 8; value += *b++;
2456 case 1: value <<= 8; value += *b++;
2461 proto_tree_set_uint64(fi, value);
2464 /* Add a FT_STRING or FT_STRINGZ to a proto_tree. Creates own copy of string,
2465 * and frees it when the proto_tree is destroyed. */
2467 proto_tree_add_string(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2468 gint length, const char* value)
2471 header_field_info *hfinfo;
2473 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2475 DISSECTOR_ASSERT(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ);
2477 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
2478 DISSECTOR_ASSERT(length >= 0);
2479 proto_tree_set_string(PNODE_FINFO(pi), value);
2485 proto_tree_add_unicode_string(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2486 gint length, const char* value)
2488 DISSECTOR_ASSERT(g_utf8_validate(value, -1, NULL));
2489 return proto_tree_add_string_format_value(tree, hfindex, tvb, start, length, value, "%s", value);
2493 proto_tree_add_string_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2494 gint start, gint length, const char* value,
2501 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
2503 va_start(ap, format);
2504 proto_tree_set_representation_value(pi, format, ap);
2512 proto_tree_add_string_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2513 gint start, gint length, const char* value,
2514 const char *format, ...)
2519 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
2521 TRY_TO_FAKE_THIS_REPR(pi);
2523 va_start(ap, format);
2524 proto_tree_set_representation(pi, format, ap);
2531 /* Appends string data to a FT_STRING or FT_STRINGZ, allowing progressive
2532 * field info update instead of only updating the representation as does
2533 * proto_item_append_text()
2535 /* NOTE: this function will break with the TRY_TO_FAKE_THIS_ITEM()
2536 * speed optimization.
2537 * Currently only WSP use this function so it is not that bad but try to
2538 * avoid using this one if possible.
2539 * IF you must use this function you MUST also disable the
2540 * TRY_TO_FAKE_THIS_ITEM() optimization for your dissector/function
2541 * using proto_item_append_string().
2542 * Do that by faking that the tree is visible by calling
2543 * proto_tree_set_visible(tree, TRUE) (see packet-wsp.c)
2544 * BEFORE you create the item you are later going to use
2545 * proto_item_append_string() on.
2548 proto_item_append_string(proto_item *pi, const char *str)
2551 header_field_info *hfinfo;
2552 const gchar *old_str, *new_str;
2559 fi = PITEM_FINFO(pi);
2560 DISSECTOR_ASSERT_HINT(fi, "proto_tree_set_visible(tree, TRUE) should have been called previously");
2562 hfinfo = fi->hfinfo;
2563 if (hfinfo->type == FT_PROTOCOL) {
2564 /* TRY_TO_FAKE_THIS_ITEM() speed optimization: silently skip */
2567 DISSECTOR_ASSERT(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ);
2568 old_str = (guint8 *)fvalue_get(&fi->value);
2569 if (old_str && old_str[0])
2570 new_str = ep_strconcat(old_str, str, NULL);
2573 fvalue_set(&fi->value, (gpointer) new_str, FALSE);
2576 /* Set the FT_STRING value */
2578 proto_tree_set_string(field_info *fi, const char* value)
2581 fvalue_set(&fi->value, (gpointer) value, FALSE);
2583 fvalue_set(&fi->value, (gpointer) "[ Null ]", FALSE);
2588 proto_tree_set_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length, gint encoding)
2593 length = tvb_ensure_length_remaining(tvb, start);
2596 string = tvb_get_string_enc(wmem_packet_scope(), tvb, start, length, encoding);
2597 proto_tree_set_string(fi, string);
2601 /* Add a FT_AX25 to a proto_tree */
2603 proto_tree_add_ax25(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2604 const guint8* value)
2607 header_field_info *hfinfo;
2609 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2611 DISSECTOR_ASSERT(hfinfo->type == FT_AX25);
2613 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
2614 proto_tree_set_ax25(PNODE_FINFO(pi), value);
2619 /* Set the FT_AX25 value */
2621 proto_tree_set_ax25(field_info *fi, const guint8* value)
2623 fvalue_set(&fi->value, (gpointer) value, FALSE);
2627 proto_tree_set_ax25_tvb(field_info *fi, tvbuff_t *tvb, gint start)
2629 proto_tree_set_ax25(fi, tvb_get_ptr(tvb, start, 7));
2632 /* Set the FT_VINES value */
2634 proto_tree_set_vines(field_info *fi, const guint8* value)
2636 fvalue_set(&fi->value, (gpointer) value, FALSE);
2640 proto_tree_set_vines_tvb(field_info *fi, tvbuff_t *tvb, gint start)
2642 proto_tree_set_vines(fi, tvb_get_ptr(tvb, start, FT_VINES_ADDR_LEN));
2645 /* Add a FT_ETHER to a proto_tree */
2647 proto_tree_add_ether(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2648 gint length, const guint8* value)
2651 header_field_info *hfinfo;
2653 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2655 DISSECTOR_ASSERT(hfinfo->type == FT_ETHER);
2657 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
2658 proto_tree_set_ether(PNODE_FINFO(pi), value);
2664 proto_tree_add_ether_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2665 gint start, gint length, const guint8* value,
2666 const char *format, ...)
2671 pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
2673 va_start(ap, format);
2674 proto_tree_set_representation_value(pi, format, ap);
2682 proto_tree_add_ether_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2683 gint start, gint length, const guint8* value,
2684 const char *format, ...)
2689 pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
2691 TRY_TO_FAKE_THIS_REPR(pi);
2693 va_start(ap, format);
2694 proto_tree_set_representation(pi, format, ap);
2701 /* Set the FT_ETHER value */
2703 proto_tree_set_ether(field_info *fi, const guint8* value)
2705 fvalue_set(&fi->value, (gpointer) value, FALSE);
2709 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start)
2711 proto_tree_set_ether(fi, tvb_get_ptr(tvb, start, FT_ETHER_LEN));
2714 /* Add a FT_BOOLEAN to a proto_tree */
2716 proto_tree_add_boolean(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2717 gint length, guint32 value)
2720 header_field_info *hfinfo;
2722 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2724 DISSECTOR_ASSERT(hfinfo->type == FT_BOOLEAN);
2726 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
2727 proto_tree_set_boolean(PNODE_FINFO(pi), value);
2733 proto_tree_add_boolean_format_value(proto_tree *tree, int hfindex,
2734 tvbuff_t *tvb, gint start, gint length,
2735 guint32 value, const char *format, ...)
2740 pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
2742 va_start(ap, format);
2743 proto_tree_set_representation_value(pi, format, ap);
2751 proto_tree_add_boolean_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2752 gint start, gint length, guint32 value,
2753 const char *format, ...)
2758 pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
2760 TRY_TO_FAKE_THIS_REPR(pi);
2762 va_start(ap, format);
2763 proto_tree_set_representation(pi, format, ap);
2770 /* Set the FT_BOOLEAN value */
2772 proto_tree_set_boolean(field_info *fi, guint32 value)
2774 proto_tree_set_uint(fi, value);
2777 /* Add a FT_FLOAT to a proto_tree */
2779 proto_tree_add_float(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2780 gint length, float value)
2783 header_field_info *hfinfo;
2785 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2787 DISSECTOR_ASSERT(hfinfo->type == FT_FLOAT);
2789 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
2790 proto_tree_set_float(PNODE_FINFO(pi), value);
2796 proto_tree_add_float_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2797 gint start, gint length, float value,
2798 const char *format, ...)
2803 pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
2805 va_start(ap, format);
2806 proto_tree_set_representation_value(pi, format, ap);
2814 proto_tree_add_float_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2815 gint start, gint length, float value,
2816 const char *format, ...)
2821 pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
2823 TRY_TO_FAKE_THIS_REPR(pi);
2825 va_start(ap, format);
2826 proto_tree_set_representation(pi, format, ap);
2833 /* Set the FT_FLOAT value */
2835 proto_tree_set_float(field_info *fi, float value)
2837 fvalue_set_floating(&fi->value, value);
2840 /* Add a FT_DOUBLE to a proto_tree */
2842 proto_tree_add_double(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2843 gint length, double value)
2846 header_field_info *hfinfo;
2848 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2850 DISSECTOR_ASSERT(hfinfo->type == FT_DOUBLE);
2852 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
2853 proto_tree_set_double(PNODE_FINFO(pi), value);
2859 proto_tree_add_double_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2860 gint start, gint length, double value,
2861 const char *format, ...)
2866 pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
2868 va_start(ap, format);
2869 proto_tree_set_representation_value(pi, format, ap);
2877 proto_tree_add_double_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2878 gint start, gint length, double value,
2879 const char *format, ...)
2884 pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
2886 TRY_TO_FAKE_THIS_REPR(pi);
2888 va_start(ap, format);
2889 proto_tree_set_representation(pi, format, ap);
2896 /* Set the FT_DOUBLE value */
2898 proto_tree_set_double(field_info *fi, double value)
2900 fvalue_set_floating(&fi->value, value);
2903 /* Add FT_UINT{8,16,24,32} to a proto_tree */
2905 proto_tree_add_uint(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2906 gint length, guint32 value)
2908 proto_item *pi = NULL;
2909 header_field_info *hfinfo;
2911 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2913 switch (hfinfo->type) {
2919 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
2920 proto_tree_set_uint(PNODE_FINFO(pi), value);
2924 DISSECTOR_ASSERT_NOT_REACHED();
2931 proto_tree_add_uint_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2932 gint start, gint length, guint32 value,
2933 const char *format, ...)
2938 pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
2940 va_start(ap, format);
2941 proto_tree_set_representation_value(pi, format, ap);
2949 proto_tree_add_uint_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2950 gint start, gint length, guint32 value,
2951 const char *format, ...)
2956 pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
2958 TRY_TO_FAKE_THIS_REPR(pi);
2960 va_start(ap, format);
2961 proto_tree_set_representation(pi, format, ap);
2968 /* Set the FT_UINT{8,16,24,32} value */
2970 proto_tree_set_uint(field_info *fi, guint32 value)
2972 header_field_info *hfinfo;
2975 hfinfo = fi->hfinfo;
2978 if (hfinfo->bitmask) {
2979 /* Mask out irrelevant portions */
2980 integer &= hfinfo->bitmask;
2983 integer >>= hfinfo_bitshift(hfinfo);
2986 fvalue_set_uinteger(&fi->value, integer);
2989 /* Add FT_UINT64 to a proto_tree */
2991 proto_tree_add_uint64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2992 gint length, guint64 value)
2995 header_field_info *hfinfo;
2997 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2999 DISSECTOR_ASSERT(hfinfo->type == FT_UINT64);
3001 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
3002 proto_tree_set_uint64(PNODE_FINFO(pi), value);
3008 proto_tree_add_uint64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3009 gint start, gint length, guint64 value,
3010 const char *format, ...)
3015 pi = proto_tree_add_uint64(tree, hfindex, tvb, start, length, value);
3017 va_start(ap, format);
3018 proto_tree_set_representation_value(pi, format, ap);
3026 proto_tree_add_uint64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3027 gint start, gint length, guint64 value,
3028 const char *format, ...)
3033 pi = proto_tree_add_uint64(tree, hfindex, tvb, start, length, value);
3035 TRY_TO_FAKE_THIS_REPR(pi);
3037 va_start(ap, format);
3038 proto_tree_set_representation(pi, format, ap);
3045 /* Add FT_INT{8,16,24,32} to a proto_tree */
3047 proto_tree_add_int(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3048 gint length, gint32 value)
3050 proto_item *pi = NULL;
3051 header_field_info *hfinfo;
3053 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3055 switch (hfinfo->type) {
3060 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
3061 proto_tree_set_int(PNODE_FINFO(pi), value);
3065 DISSECTOR_ASSERT_NOT_REACHED();
3072 proto_tree_add_int_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3073 gint start, gint length, gint32 value,
3074 const char *format, ...)
3079 pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
3081 va_start(ap, format);
3082 proto_tree_set_representation_value(pi, format, ap);
3090 proto_tree_add_int_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3091 gint start, gint length, gint32 value,
3092 const char *format, ...)
3097 pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
3099 TRY_TO_FAKE_THIS_REPR(pi);
3101 va_start(ap, format);
3102 proto_tree_set_representation(pi, format, ap);
3109 /* Set the FT_INT{8,16,24,32} value */
3111 proto_tree_set_int(field_info *fi, gint32 value)
3113 header_field_info *hfinfo;
3117 hfinfo = fi->hfinfo;
3118 integer = (guint32) value;
3120 if (hfinfo->bitmask) {
3121 /* Mask out irrelevant portions */
3122 integer &= hfinfo->bitmask;
3125 integer >>= hfinfo_bitshift(hfinfo);
3127 no_of_bits = swar_count_bits(hfinfo->bitmask);
3128 if (integer & (1 << (no_of_bits-1)))
3129 integer |= (-1 << no_of_bits);
3132 fvalue_set_sinteger(&fi->value, integer);
3135 /* Add FT_INT64 to a proto_tree */
3137 proto_tree_add_int64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3138 gint length, gint64 value)
3141 header_field_info *hfinfo;
3143 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3145 DISSECTOR_ASSERT(hfinfo->type == FT_INT64);
3147 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
3148 proto_tree_set_uint64(PNODE_FINFO(pi), (guint64)value);
3154 proto_tree_add_int64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3155 gint start, gint length, gint64 value,
3156 const char *format, ...)
3161 pi = proto_tree_add_int64(tree, hfindex, tvb, start, length, value);
3163 va_start(ap, format);
3164 proto_tree_set_representation_value(pi, format, ap);
3172 proto_tree_add_int64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3173 gint start, gint length, gint64 value,
3174 const char *format, ...)
3179 pi = proto_tree_add_int64(tree, hfindex, tvb, start, length, value);
3181 TRY_TO_FAKE_THIS_REPR(pi);
3183 va_start(ap, format);
3184 proto_tree_set_representation(pi, format, ap);
3190 /* Add a FT_EUI64 to a proto_tree */
3192 proto_tree_add_eui64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3193 gint length, const guint64 value)
3196 header_field_info *hfinfo;
3198 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3200 DISSECTOR_ASSERT(hfinfo->type == FT_EUI64);
3202 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
3203 proto_tree_set_eui64(PNODE_FINFO(pi), value);
3209 proto_tree_add_eui64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3210 gint start, gint length, const guint64 value,
3211 const char *format, ...)
3216 pi = proto_tree_add_eui64(tree, hfindex, tvb, start, length, value);
3218 va_start(ap, format);
3219 proto_tree_set_representation_value(pi, format, ap);
3227 proto_tree_add_eui64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3228 gint start, gint length, const guint64 value,
3229 const char *format, ...)
3234 pi = proto_tree_add_eui64(tree, hfindex, tvb, start, length, value);
3236 TRY_TO_FAKE_THIS_REPR(pi);
3238 va_start(ap, format);
3239 proto_tree_set_representation(pi, format, ap);
3246 /* Set the FT_EUI64 value */
3248 proto_tree_set_eui64(field_info *fi, const guint64 value)
3250 fvalue_set_integer64(&fi->value, value);
3253 proto_tree_set_eui64_tvb(field_info *fi, tvbuff_t *tvb, gint start, const guint encoding)
3257 proto_tree_set_eui64(fi, tvb_get_letoh64(tvb, start));
3259 proto_tree_set_eui64(fi, tvb_get_ntoh64(tvb, start));
3263 /* Add a field_info struct to the proto_tree, encapsulating it in a proto_node */
3265 proto_tree_add_node(proto_tree *tree, field_info *fi)
3267 proto_node *pnode, *tnode, *sibling;
3271 * Make sure "tree" is ready to have subtrees under it, by
3272 * checking whether it's been given an ett_ value.
3274 * "PNODE_FINFO(tnode)" may be null; that's the case for the root
3275 * node of the protocol tree. That node is not displayed,
3276 * so it doesn't need an ett_ value to remember whether it
3280 tfi = PNODE_FINFO(tnode);
3281 if (tfi != NULL && (tfi->tree_type < 0 || tfi->tree_type >= num_tree_types)) {
3282 REPORT_DISSECTOR_BUG(ep_strdup_printf("\"%s\" - \"%s\" tfi->tree_type: %u invalid (%s:%u)",
3283 fi->hfinfo->name, fi->hfinfo->abbrev, tfi->tree_type, __FILE__, __LINE__));
3284 /* XXX - is it safe to continue here? */
3287 PROTO_NODE_NEW(PNODE_POOL(tree), pnode);
3288 pnode->parent = tnode;
3289 PNODE_FINFO(pnode) = fi;
3290 pnode->tree_data = PTREE_DATA(tree);
3292 if (tnode->last_child != NULL) {
3293 sibling = tnode->last_child;
3294 DISSECTOR_ASSERT(sibling->next == NULL);
3295 sibling->next = pnode;
3297 tnode->first_child = pnode;
3298 tnode->last_child = pnode;
3300 tree_data_add_maybe_interesting_field(pnode->tree_data, fi);
3302 return (proto_item *)pnode;
3306 /* Generic way to allocate field_info and add to proto_tree.
3307 * Sets *pfi to address of newly-allocated field_info struct */
3309 proto_tree_add_pi(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb, gint start,
3315 fi = alloc_field_info(tree, hfinfo, tvb, start, length);
3316 pi = proto_tree_add_node(tree, fi);
3323 get_hfi_length(header_field_info *hfinfo, tvbuff_t *tvb, const gint start, gint *length,
3326 gint length_remaining;
3329 * We only allow a null tvbuff if the item has a zero length,
3330 * i.e. if there's no data backing it.
3332 DISSECTOR_ASSERT(tvb != NULL || *length == 0);
3335 * XXX - in some protocols, there are 32-bit unsigned length
3336 * fields, so lengths in protocol tree and tvbuff routines
3337 * should really be unsigned. We should have, for those
3338 * field types for which "to the end of the tvbuff" makes sense,
3339 * additional routines that take no length argument and
3340 * add fields that run to the end of the tvbuff.
3342 if (*length == -1) {
3344 * For FT_NONE, FT_PROTOCOL, FT_BYTES, and FT_STRING fields,
3345 * a length of -1 means "set the length to what remains in
3348 * The assumption is either that
3350 * 1) the length of the item can only be determined
3351 * by dissection (typically true of items with
3352 * subitems, which are probably FT_NONE or
3357 * 2) if the tvbuff is "short" (either due to a short
3358 * snapshot length or due to lack of reassembly of
3359 * fragments/segments/whatever), we want to display
3360 * what's available in the field (probably FT_BYTES
3361 * or FT_STRING) and then throw an exception later
3365 * 3) the field is defined to be "what's left in the
3368 * so we set the length to what remains in the tvbuff so
3369 * that, if we throw an exception while dissecting, it
3370 * has what is probably the right value.
3372 * For FT_STRINGZ, it means "the string is null-terminated,
3373 * not null-padded; set the length to the actual length
3374 * of the string", and if the tvbuff if short, we just
3375 * throw an exception.
3377 * It's not valid for any other type of field.
3379 switch (hfinfo->type) {
3383 * We allow this to be zero-length - for
3384 * example, an ONC RPC NULL procedure has
3385 * neither arguments nor reply, so the
3386 * payload for that protocol is empty.
3388 * However, if the length is negative, the
3389 * start offset is *past* the byte past the
3390 * end of the tvbuff, so we throw an
3393 *length = tvb_length_remaining(tvb, start);
3396 * Use "tvb_ensure_bytes_exist()"
3397 * to force the appropriate exception
3400 tvb_ensure_bytes_exist(tvb, start, 0);
3402 DISSECTOR_ASSERT(*length >= 0);
3408 *length = tvb_ensure_length_remaining(tvb, start);
3409 DISSECTOR_ASSERT(*length >= 0);
3414 * Leave the length as -1, so our caller knows
3420 DISSECTOR_ASSERT_NOT_REACHED();
3422 *item_length = *length;
3424 *item_length = *length;
3425 if (hfinfo->type == FT_PROTOCOL || hfinfo->type == FT_NONE) {
3427 * These types are for interior nodes of the
3428 * tree, and don't have data associated with
3429 * them; if the length is negative (XXX - see
3430 * above) or goes past the end of the tvbuff,
3431 * cut it short at the end of the tvbuff.
3432 * That way, if this field is selected in
3433 * Wireshark, we don't highlight stuff past
3434 * the end of the data.
3436 /* XXX - what to do, if we don't have a tvb? */
3438 length_remaining = tvb_length_remaining(tvb, start);
3439 if (*item_length < 0 ||
3440 (*item_length > 0 &&
3441 (length_remaining < *item_length)))
3442 *item_length = length_remaining;
3445 if (*item_length < 0) {
3446 THROW(ReportedBoundsError);
3452 new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
3453 const gint start, const gint item_length)
3457 FIELD_INFO_NEW(PNODE_POOL(tree), fi);
3459 fi->hfinfo = hfinfo;
3461 fi->start += (tvb)?tvb_raw_offset(tvb):0;
3462 fi->length = item_length;
3465 if (!PTREE_DATA(tree)->visible)
3466 FI_SET_FLAG(fi, FI_HIDDEN);
3467 fvalue_init(&fi->value, fi->hfinfo->type);
3470 /* add the data source tvbuff */
3471 fi->ds_tvb = tvb ? tvb_get_ds_tvb(tvb) : NULL;
3473 fi->appendix_start = 0;
3474 fi->appendix_length = 0;
3480 alloc_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb, const gint start,
3485 get_hfi_length(hfinfo, tvb, start, length, &item_length);
3486 return new_field_info(tree, hfinfo, tvb, start, item_length);
3490 label_mark_truncated_start(char *label_str)
3492 static const char trunc_str[] = "[truncated] ";
3493 const size_t trunc_len = sizeof(trunc_str)-1;
3495 memmove(label_str + trunc_len, label_str, ITEM_LABEL_LENGTH - trunc_len);
3496 memcpy(label_str, trunc_str, trunc_len);
3497 label_str[ITEM_LABEL_LENGTH-1] = '\0';
3500 /* If the protocol tree is to be visible, set the representation of a
3501 proto_tree entry with the name of the field for the item and with
3502 the value formatted with the supplied printf-style format and
3505 proto_tree_set_representation_value(proto_item *pi, const char *format, va_list ap)
3509 /* If the tree (GUI) or item isn't visible it's pointless for us to generate the protocol
3510 * items string representation */
3511 if (PTREE_DATA(pi)->visible && !PROTO_ITEM_IS_HIDDEN(pi)) {
3513 field_info *fi = PITEM_FINFO(pi);
3514 header_field_info *hf;
3516 DISSECTOR_ASSERT(fi);
3520 ITEM_LABEL_NEW(PNODE_POOL(pi), fi->rep);
3521 if (hf->bitmask && (hf->type == FT_BOOLEAN || IS_FT_UINT(hf->type))) {
3525 val = fvalue_get_uinteger(&fi->value);
3526 val <<= hfinfo_bitshift(hf);
3528 p = decode_bitfield_value(fi->rep->representation, val, hf->bitmask, hfinfo_bitwidth(hf));
3529 ret = (int) (p - fi->rep->representation);
3532 /* put in the hf name */
3533 ret += g_snprintf(fi->rep->representation + ret, ITEM_LABEL_LENGTH - ret, "%s: ", hf->name);
3535 /* If possible, Put in the value of the string */
3536 if (ret < ITEM_LABEL_LENGTH) {
3537 ret += g_vsnprintf(fi->rep->representation + ret,
3538 ITEM_LABEL_LENGTH - ret, format, ap);
3540 if (ret >= ITEM_LABEL_LENGTH) {
3541 /* Uh oh, we don't have enough room. Tell the user
3542 * that the field is truncated.
3544 /* XXX, label_mark_truncated() ? */
3545 label_mark_truncated_start(fi->rep->representation);
3550 /* If the protocol tree is to be visible, set the representation of a
3551 proto_tree entry with the representation formatted with the supplied
3552 printf-style format and argument list. */
3554 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap)
3556 int ret; /*tmp return value */
3557 field_info *fi = PITEM_FINFO(pi);
3559 DISSECTOR_ASSERT(fi);
3561 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
3562 ITEM_LABEL_NEW(PNODE_POOL(pi), fi->rep);
3563 ret = g_vsnprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
3565 if (ret >= ITEM_LABEL_LENGTH) {
3566 /* Uh oh, we don't have enough room. Tell the user
3567 * that the field is truncated.
3569 label_mark_truncated_start(fi->rep->representation);
3575 protoo_strlcpy(gchar *dest, const gchar *src, gsize dest_size)
3577 gsize res = g_strlcpy(dest, src, dest_size);
3579 if (res > dest_size)
3584 static header_field_info *
3585 hfinfo_same_name_get_prev(const header_field_info *hfinfo)
3587 if (hfinfo->same_name_prev_id == -1)
3589 return proto_registrar_get_nth(hfinfo->same_name_prev_id);
3592 /* -------------------------- */
3594 proto_custom_set(proto_tree* tree, const int field_id, gint occurrence,
3595 gchar *result, gchar *expr, const int size)
3600 struct e_in6_addr *ipv6;
3602 guint32 n_addr; /* network-order IPv4 address */
3604 const true_false_string *tfstring;
3606 int len, prev_len = 0, last, i, offset_r = 0, offset_e = 0;
3608 field_info *finfo = NULL;
3609 header_field_info* hfinfo;
3610 const gchar *abbrev = NULL;
3612 const char *hf_str_val;
3613 char number_buf[32];
3614 const char *number_out;
3616 g_assert(field_id >= 0);
3618 hfinfo = proto_registrar_get_nth((guint)field_id);
3620 /* do we need to rewind ? */
3624 if (occurrence < 0) {
3625 /* Search other direction */
3626 while (hfinfo->same_name_prev_id != -1) {
3627 hfinfo = proto_registrar_get_nth(hfinfo->same_name_prev_id);
3632 finfos = proto_get_finfo_ptr_array(tree, hfinfo->id);
3634 if (!finfos || !(len = g_ptr_array_len(finfos))) {
3635 if (occurrence < 0) {
3636 hfinfo = hfinfo->same_name_next;
3638 hfinfo = hfinfo_same_name_get_prev(hfinfo);
3643 /* Are there enough occurrences of the field? */
3644 if (((occurrence - prev_len) > len) || ((occurrence + prev_len) < -len)) {
3645 if (occurrence < 0) {
3646 hfinfo = hfinfo->same_name_next;
3648 hfinfo = hfinfo_same_name_get_prev(hfinfo);
3654 /* Calculate single index or set outer bounderies */
3655 if (occurrence < 0) {
3656 i = occurrence + len + prev_len;
3658 } else if (occurrence > 0) {
3659 i = occurrence - 1 - prev_len;
3666 prev_len += len; /* Count handled occurrences */
3669 finfo = (field_info *)g_ptr_array_index(finfos, i);
3671 if (offset_r && (offset_r < (size - 2)))
3672 result[offset_r++] = ',';
3674 if (offset_e && (offset_e < (size - 2)))
3675 expr[offset_e++] = ',';
3677 switch (hfinfo->type) {
3679 case FT_NONE: /* Nothing to add */
3680 if (offset_r == 0) {
3682 } else if (result[offset_r-1] == ',') {
3683 result[offset_r-1] = '\0';
3688 /* prevent multiple "yes" entries by setting result directly */
3689 g_strlcpy(result, "Yes", size);
3694 bytes = (guint8 *)fvalue_get(&finfo->value);
3695 offset_r += protoo_strlcpy(result+offset_r,
3697 fvalue_length(&finfo->value)),
3701 case FT_ABSOLUTE_TIME:
3702 offset_r += protoo_strlcpy(result+offset_r,
3703 abs_time_to_str((const nstime_t *)fvalue_get(&finfo->value),
3704 (absolute_time_display_e)hfinfo->display, TRUE),
3708 case FT_RELATIVE_TIME:
3709 offset_r += protoo_strlcpy(result+offset_r,
3710 rel_time_to_secs_str((const nstime_t *)fvalue_get(&finfo->value)),
3715 number = fvalue_get_uinteger(&finfo->value);
3716 tfstring = (const true_false_string *)&tfs_true_false;
3717 if (hfinfo->strings) {
3718 tfstring = (const struct true_false_string*) hfinfo->strings;
3720 offset_r += protoo_strlcpy(result+offset_r,
3722 tfstring->true_string :
3723 tfstring->false_string, size-offset_r);
3725 offset_e += protoo_strlcpy(expr+offset_e,
3726 number ? "1" : "0", size-offset_e);
3729 /* XXX - make these just FT_NUMBER? */
3740 number = IS_FT_INT(hfinfo->type) ?
3741 (guint32) fvalue_get_sinteger(&finfo->value) :
3742 fvalue_get_uinteger(&finfo->value);
3744 if ((hfinfo->display & BASE_DISPLAY_E_MASK) == BASE_CUSTOM) {
3745 gchar tmp[ITEM_LABEL_LENGTH];
3746 custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hfinfo->strings;
3748 DISSECTOR_ASSERT(fmtfunc);
3749 fmtfunc(tmp, number);
3751 offset_r += protoo_strlcpy(result+offset_r, tmp, size-offset_r);
3753 } else if (hfinfo->strings) {
3754 number_out = hf_str_val = hf_try_val_to_str(number, hfinfo);
3757 number_out = hfinfo_number_value_format_display(hfinfo, BASE_DEC, number_buf, number);
3759 offset_r += protoo_strlcpy(result+offset_r, number_out, size-offset_r);
3762 number_out = hfinfo_number_value_format(hfinfo, number_buf, number);
3764 offset_r += protoo_strlcpy(result+offset_r, number_out, size-offset_r);
3767 if (hf_str_val && (hfinfo->display & BASE_DISPLAY_E_MASK) == BASE_NONE) {
3768 g_snprintf(expr+offset_e, size-offset_e, "\"%s\"", hf_str_val);
3770 number_out = hfinfo_numeric_value_format(hfinfo, number_buf, number);
3772 g_strlcpy(expr+offset_e, number_out, size-offset_e);
3775 offset_e = (int)strlen(expr);
3779 /* XXX: Should handle BASE_CUSTOM ? */
3780 g_snprintf(result+offset_r, size-offset_r,
3781 "%" G_GINT64_MODIFIER "d",
3782 fvalue_get_integer64(&finfo->value));
3783 offset_r = (int)strlen(result);
3786 g_snprintf(result+offset_r, size-offset_r,
3787 /* XXX: Should handle BASE_CUSTOM ? */
3788 "%" G_GINT64_MODIFIER "u",
3789 fvalue_get_integer64(&finfo->value));
3790 offset_r = (int)strlen(result);
3793 offset_r += protoo_strlcpy(result+offset_r,
3794 eui64_to_str(fvalue_get_integer64(&finfo->value)),
3799 ipv4 = (ipv4_addr *)fvalue_get(&finfo->value);
3800 n_addr = ipv4_get_net_order_addr(ipv4);
3801 offset_r += protoo_strlcpy(result+offset_r,
3802 ip_to_str((guint8 *)&n_addr),
3807 ipv6 = (struct e_in6_addr *)fvalue_get(&finfo->value);
3808 SET_ADDRESS (&addr, AT_IPv6, sizeof(struct e_in6_addr), ipv6);
3809 address_to_str_buf(&addr, result+offset_r, size-offset_r);
3810 offset_r = (int)strlen(result);
3814 offset_r += protoo_strlcpy(result+offset_r,
3815 bytes_to_str_punct((const guint8 *)fvalue_get(&finfo->value),
3821 offset_r += protoo_strlcpy(result+offset_r,
3822 guid_to_str((e_guid_t *)fvalue_get(&finfo->value)),
3827 bytes = (guint8 *)fvalue_get(&finfo->value);
3828 offset_r += protoo_strlcpy(result+offset_r,
3829 rel_oid_resolved_from_encoded(bytes,
3830 fvalue_length(&finfo->value)),
3832 offset_e += protoo_strlcpy(expr+offset_e,
3833 rel_oid_encoded2string(bytes, fvalue_length(&finfo->value)),
3838 bytes = (guint8 *)fvalue_get(&finfo->value);
3839 offset_r += protoo_strlcpy(result+offset_r,
3840 oid_resolved_from_encoded(bytes,
3841 fvalue_length(&finfo->value)),
3843 offset_e += protoo_strlcpy(expr+offset_e,
3844 oid_encoded2string(bytes, fvalue_length(&finfo->value)),
3849 g_snprintf(result+offset_r, size-offset_r,
3850 "%." STRINGIFY(FLT_DIG) "g", fvalue_get_floating(&finfo->value));
3851 offset_r = (int)strlen(result);
3855 g_snprintf(result+offset_r, size-offset_r,
3856 "%." STRINGIFY(DBL_DIG) "g", fvalue_get_floating(&finfo->value));
3857 offset_r = (int)strlen(result);
3862 case FT_UINT_STRING:
3863 bytes = (guint8 *)fvalue_get(&finfo->value);
3864 offset_r += protoo_strlcpy(result+offset_r,
3865 format_text(bytes, strlen(bytes)),
3869 case FT_IPXNET: /*XXX really No column custom ?*/
3872 g_error("hfinfo->type %d (%s) not handled\n",
3874 ftype_name(hfinfo->type));
3875 DISSECTOR_ASSERT_NOT_REACHED();
3881 switch (hfinfo->type) {
3895 /* for these types, "expr" is filled in the loop above */
3899 /* for all others, just copy "result" to "expr" */
3900 g_strlcpy(expr, result, size);
3905 /* Store abbrev for return value */
3906 abbrev = hfinfo->abbrev;
3909 if (occurrence == 0) {
3910 /* Fetch next hfinfo with same name (abbrev) */
3911 hfinfo = hfinfo_same_name_get_prev(hfinfo);
3917 return abbrev ? abbrev : "";
3921 /* Set text of proto_item after having already been created. */
3923 proto_item_set_text(proto_item *pi, const char *format, ...)
3925 field_info *fi = NULL;
3932 fi = PITEM_FINFO(pi);
3937 ITEM_LABEL_FREE(PNODE_POOL(pi), fi->rep);
3941 va_start(ap, format);
3942 proto_tree_set_representation(pi, format, ap);
3946 /* Append to text of proto_item after having already been created. */
3948 proto_item_append_text(proto_item *pi, const char *format, ...)
3950 field_info *fi = NULL;
3958 fi = PITEM_FINFO(pi);
3963 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
3965 * If we don't already have a representation,
3966 * generate the default representation.
3968 if (fi->rep == NULL) {
3969 ITEM_LABEL_NEW(PNODE_POOL(pi), fi->rep);
3970 proto_item_fill_label(fi, fi->rep->representation);
3973 curlen = strlen(fi->rep->representation);
3974 if (ITEM_LABEL_LENGTH > curlen) {
3975 va_start(ap, format);
3976 g_vsnprintf(fi->rep->representation + curlen,
3977 ITEM_LABEL_LENGTH - (gulong) curlen, format, ap);
3983 /* Prepend to text of proto_item after having already been created. */
3985 proto_item_prepend_text(proto_item *pi, const char *format, ...)
3987 field_info *fi = NULL;
3988 char representation[ITEM_LABEL_LENGTH];
3995 fi = PITEM_FINFO(pi);
4000 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
4002 * If we don't already have a representation,
4003 * generate the default representation.
4005 if (fi->rep == NULL) {
4006 ITEM_LABEL_NEW(PNODE_POOL(pi), fi->rep);
4007 proto_item_fill_label(fi, representation);
4009 g_strlcpy(representation, fi->rep->representation, ITEM_LABEL_LENGTH);
4011 va_start(ap, format);
4012 g_vsnprintf(fi->rep->representation,
4013 ITEM_LABEL_LENGTH, format, ap);
4015 g_strlcat(fi->rep->representation, representation, ITEM_LABEL_LENGTH);
4020 proto_item_set_len(proto_item *pi, const gint length)
4027 fi = PITEM_FINFO(pi);
4031 DISSECTOR_ASSERT(length >= 0);
4032 fi->length = length;
4035 * You cannot just make the "len" field of a GByteArray
4036 * larger, if there's no data to back that length;
4037 * you can only make it smaller.
4039 if (fi->value.ftype->ftype == FT_BYTES && length <= (gint)fi->value.value.bytes->len)
4040 fi->value.value.bytes->len = length;
4044 * Sets the length of the item based on its start and on the specified
4045 * offset, which is the offset past the end of the item; as the start
4046 * in the item is relative to the beginning of the data source tvbuff,
4047 * we need to pass in a tvbuff - the end offset is relative to the beginning
4051 proto_item_set_end(proto_item *pi, tvbuff_t *tvb, gint end)
4058 fi = PITEM_FINFO(pi);
4062 end += tvb_raw_offset(tvb);
4063 DISSECTOR_ASSERT(end >= fi->start);
4064 fi->length = end - fi->start;
4068 proto_item_get_len(const proto_item *pi)
4070 field_info *fi = PITEM_FINFO(pi);
4071 return fi ? fi->length : -1;
4075 proto_tree_create_root(packet_info *pinfo)
4077 wmem_allocator_t *pool;
4080 if (tree_pool_cache) {
4081 pool = tree_pool_cache;
4082 tree_pool_cache = NULL;
4085 pool = wmem_allocator_new(WMEM_ALLOCATOR_BLOCK);
4088 /* Initialize the proto_node */
4089 PROTO_NODE_NEW(pool, pnode);
4090 pnode->parent = NULL;
4091 PNODE_FINFO(pnode) = NULL;
4092 pnode->tree_data = wmem_new(pool, tree_data_t);
4094 /* Make sure we can access pinfo everywhere */
4095 pnode->tree_data->pinfo = pinfo;
4097 pnode->tree_data->mem_pool = pool;
4099 /* Don't initialize the tree_data_t. Wait until we know we need it */
4100 pnode->tree_data->interesting_hfids = NULL;
4102 /* Set the default to FALSE so it's easier to
4103 * find errors; if we expect to see the protocol tree
4104 * but for some reason the default 'visible' is not
4105 * changed, then we'll find out very quickly. */
4106 pnode->tree_data->visible = FALSE;
4108 /* Make sure that we fake protocols (if possible) */
4109 pnode->tree_data->fake_protocols = TRUE;
4111 /* Keep track of the number of children */
4112 pnode->tree_data->count = 0;
4114 return (proto_tree *)pnode;
4118 /* "prime" a proto_tree with a single hfid that a dfilter
4119 * is interested in. */
4121 proto_tree_prime_hfid(proto_tree *tree _U_, const gint hfid)
4123 header_field_info *hfinfo;
4125 PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
4126 /* this field is referenced by a filter so increase the refcount.
4127 also increase the refcount for the parent, i.e the protocol.
4129 hfinfo->ref_type = HF_REF_TYPE_DIRECT;
4130 /* only increase the refcount if there is a parent.
4131 if this is a protocol and not a field then parent will be -1
4132 and there is no parent to add any refcounting for.
4134 if (hfinfo->parent != -1) {
4135 header_field_info *parent_hfinfo;
4136 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
4138 /* Mark parent as indirectly referenced unless it is already directly
4139 * referenced, i.e. the user has specified the parent in a filter.
4141 if (parent_hfinfo->ref_type != HF_REF_TYPE_DIRECT)
4142 parent_hfinfo->ref_type = HF_REF_TYPE_INDIRECT;
4147 proto_item_add_subtree(proto_item *pi, const gint idx) {
4153 DISSECTOR_ASSERT(idx >= 0 && idx < num_tree_types);
4155 fi = PITEM_FINFO(pi);
4157 return (proto_tree *)pi;
4159 fi->tree_type = idx;
4161 return (proto_tree *)pi;
4165 proto_item_get_subtree(const proto_item *pi) {
4170 fi = PITEM_FINFO(pi);
4171 if ( (!fi) || (fi->tree_type == -1) )
4173 return (proto_tree *)pi;
4177 proto_item_get_parent(const proto_item *ti) {
4184 proto_item_get_parent_nth(proto_item *ti, int gen) {
4197 proto_tree_get_parent(const proto_tree *tree) {
4200 return (proto_item *)tree;
4204 proto_tree_get_root(proto_tree *tree) {
4207 while (tree->parent) {
4208 tree = tree->parent;
4214 proto_tree_move_item(proto_tree *tree, proto_item *fixed_item,
4215 proto_item *item_to_move)
4218 /* Revert part of: http://anonsvn.wireshark.org/viewvc?view=rev&revision=32443
4219 * See https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=5500
4221 /* This function doesn't generate any values. It only reorganizes the prococol tree
4222 * so we can bail out immediately if it isn't visible. */
4223 if (!tree || !PTREE_DATA(tree)->visible)
4226 DISSECTOR_ASSERT(item_to_move->parent == tree);
4227 DISSECTOR_ASSERT(fixed_item->parent == tree);
4229 /*** cut item_to_move out ***/
4231 /* is item_to_move the first? */
4232 if (tree->first_child == item_to_move) {
4233 /* simply change first child to next */
4234 tree->first_child = item_to_move->next;
4236 DISSECTOR_ASSERT(tree->last_child != item_to_move);
4238 proto_item *curr_item;
4239 /* find previous and change it's next */
4240 for(curr_item = tree->first_child; curr_item != NULL; curr_item = curr_item->next) {
4241 if (curr_item->next == item_to_move) {
4246 DISSECTOR_ASSERT(curr_item);
4248 curr_item->next = item_to_move->next;
4250 /* fix last_child if required */
4251 if (tree->last_child == item_to_move) {
4252 tree->last_child = curr_item;
4256 /*** insert to_move after fixed ***/
4257 item_to_move->next = fixed_item->next;
4258 fixed_item->next = item_to_move;
4259 if (tree->last_child == fixed_item) {
4260 tree->last_child = item_to_move;
4265 proto_tree_set_appendix(proto_tree *tree, tvbuff_t *tvb, gint start,
4273 fi = PTREE_FINFO(tree);
4277 start += tvb_raw_offset(tvb);
4278 DISSECTOR_ASSERT(start >= 0);
4279 DISSECTOR_ASSERT(length >= 0);
4281 fi->appendix_start = start;
4282 fi->appendix_length = length;
4286 proto_register_protocol(const char *name, const char *short_name,
4287 const char *filter_name)
4289 protocol_t *protocol;
4290 header_field_info *hfinfo;
4292 char *existing_name;
4296 gboolean found_invalid;
4299 * Make sure there's not already a protocol with any of those
4300 * names. Crash if there is, as that's an error in the code
4301 * or an inappropriate plugin.
4302 * This situation has to be fixed to not register more than one
4303 * protocol with the same name.
4305 * This is done by reducing the number of strcmp (and alike) calls
4306 * as much as possible, as this significally slows down startup time.
4308 * Drawback: As a hash value is used to reduce insert time,
4309 * this might lead to a hash collision.
4310 * However, although we have somewhat over 1000 protocols, we're using
4311 * a 32 bit int so this is very, very unlikely.
4314 key = (gint *)g_malloc (sizeof(gint));
4315 *key = wrs_str_hash(name);
4317 existing_name = (char *)g_hash_table_lookup(proto_names, key);
4318 if (existing_name != NULL) {
4319 /* g_error will terminate the program */
4320 g_error("Duplicate protocol name \"%s\"!"
4321 " This might be caused by an inappropriate plugin or a development error.", name);
4323 g_hash_table_insert(proto_names, key, (gpointer)name);
4325 existing_name = (char *)g_hash_table_lookup(proto_short_names, (gpointer)short_name);
4326 if (existing_name != NULL) {
4327 g_error("Duplicate protocol short_name \"%s\"!"
4328 " This might be caused by an inappropriate plugin or a development error.", short_name);
4330 g_hash_table_insert(proto_short_names, (gpointer)short_name, (gpointer)short_name);
4332 found_invalid = FALSE;
4333 for (i = 0; filter_name[i]; i++) {
4335 if (!(islower(c) || isdigit(c) || c == '-' || c == '_' || c == '.')) {
4336 found_invalid = TRUE;
4339 if (found_invalid) {
4340 g_error("Protocol filter name \"%s\" has one or more invalid characters."
4341 " Allowed are lower characters, digits, '-', '_' and '.'."
4342 " This might be caused by an inappropriate plugin or a development error.", filter_name);
4344 existing_name = (char *)g_hash_table_lookup(proto_filter_names, (gpointer)filter_name);
4345 if (existing_name != NULL) {
4346 g_error("Duplicate protocol filter_name \"%s\"!"
4347 " This might be caused by an inappropriate plugin or a development error.", filter_name);
4349 g_hash_table_insert(proto_filter_names, (gpointer)filter_name, (gpointer)filter_name);
4351 /* Add this protocol to the list of known protocols; the list
4352 is sorted by protocol short name. */
4353 protocol = g_new(protocol_t, 1);
4354 protocol->name = name;
4355 protocol->short_name = short_name;
4356 protocol->filter_name = filter_name;
4357 protocol->fields = NULL;
4358 protocol->is_enabled = TRUE; /* protocol is enabled by default */
4359 protocol->can_toggle = TRUE;
4360 protocol->is_private = FALSE;
4361 /* list will be sorted later by name, when all protocols completed registering */
4362 protocols = g_list_prepend(protocols, protocol);
4364 /* Here we allocate a new header_field_info struct */
4365 hfinfo = g_slice_new(header_field_info);
4366 hfinfo->name = name;
4367 hfinfo->abbrev = filter_name;
4368 hfinfo->type = FT_PROTOCOL;
4369 hfinfo->display = BASE_NONE;
4370 hfinfo->strings = protocol;
4371 hfinfo->bitmask = 0;
4372 hfinfo->ref_type = HF_REF_TYPE_NONE;
4373 hfinfo->blurb = NULL;
4374 hfinfo->parent = -1; /* this field differentiates protos and fields */
4376 proto_id = proto_register_field_init(hfinfo, hfinfo->parent);
4377 protocol->proto_id = proto_id;
4382 proto_mark_private(const int proto_id)
4384 protocol_t *protocol = find_protocol_by_id(proto_id);
4386 protocol->is_private = TRUE;
4390 proto_is_private(const int proto_id)
4392 protocol_t *protocol = find_protocol_by_id(proto_id);
4394 return protocol->is_private;
4400 * Routines to use to iterate over the protocols.
4401 * The argument passed to the iterator routines is an opaque cookie to
4402 * their callers; it's the GList pointer for the current element in
4404 * The ID of the protocol is returned, or -1 if there is no protocol.
4407 proto_get_first_protocol(void **cookie)
4409 protocol_t *protocol;
4411 if (protocols == NULL)
4413 *cookie = protocols;
4414 protocol = (protocol_t *)protocols->data;
4415 return protocol->proto_id;
4419 proto_get_data_protocol(void *cookie)
4421 GList *list_item = (GList *)cookie;
4423 protocol_t *protocol = (protocol_t *)list_item->data;
4424 return protocol->proto_id;
4428 proto_get_next_protocol(void **cookie)
4430 GList *list_item = (GList *)*cookie;
4431 protocol_t *protocol;
4433 list_item = g_list_next(list_item);
4434 if (list_item == NULL)
4436 *cookie = list_item;
4437 protocol = (protocol_t *)list_item->data;
4438 return protocol->proto_id;
4442 proto_get_first_protocol_field(const int proto_id, void **cookie)
4444 protocol_t *protocol = find_protocol_by_id(proto_id);
4446 if ((protocol == NULL) || (protocol->fields == NULL))
4449 *cookie = protocol->fields;
4450 return (header_field_info *)protocol->fields->data;
4454 proto_get_next_protocol_field(void **cookie)
4456 GSList *list_item = (GSList *)*cookie;
4458 list_item = g_slist_next(list_item);
4459 if (list_item == NULL)
4462 *cookie = list_item;
4463 return (header_field_info *)list_item->data;
4467 find_protocol_by_id(const int proto_id)
4469 header_field_info *hfinfo;
4474 PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
4475 DISSECTOR_ASSERT(hfinfo->type == FT_PROTOCOL);
4476 return (protocol_t *)hfinfo->strings;
4479 static gint compare_filter_name(gconstpointer proto_arg,
4480 gconstpointer filter_name)
4482 const protocol_t *protocol = (const protocol_t *)proto_arg;
4483 const gchar *f_name = (const gchar *)filter_name;
4485 return (strcmp(protocol->filter_name, f_name));
4489 proto_get_id(const protocol_t *protocol)
4491 return protocol->proto_id;
4494 int proto_get_id_by_filter_name(const gchar* filter_name)
4497 protocol_t *protocol;
4500 fprintf(stderr, "No filter name present");
4501 DISSECTOR_ASSERT(filter_name);
4504 list_entry = g_list_find_custom(protocols, filter_name,
4505 compare_filter_name);
4507 if (list_entry == NULL)
4509 protocol = (protocol_t *)list_entry->data;
4510 return protocol->proto_id;
4514 proto_get_protocol_name(const int proto_id)
4516 protocol_t *protocol;
4518 protocol = find_protocol_by_id(proto_id);
4520 if (protocol == NULL)
4522 return protocol->name;
4526 proto_get_protocol_short_name(const protocol_t *protocol)
4528 if (protocol == NULL)
4530 return protocol->short_name;
4534 proto_get_protocol_long_name(const protocol_t *protocol)
4536 if (protocol == NULL)
4538 return protocol->name;
4542 proto_get_protocol_filter_name(const int proto_id)
4544 protocol_t *protocol;
4546 protocol = find_protocol_by_id(proto_id);
4547 if (protocol == NULL)
4549 return protocol->filter_name;
4553 proto_is_protocol_enabled(const protocol_t *protocol)
4555 return protocol->is_enabled;
4559 proto_can_toggle_protocol(const int proto_id)
4561 protocol_t *protocol;
4563 protocol = find_protocol_by_id(proto_id);
4564 return protocol->can_toggle;
4568 proto_set_decoding(const int proto_id, const gboolean enabled)
4570 protocol_t *protocol;
4572 protocol = find_protocol_by_id(proto_id);
4573 DISSECTOR_ASSERT(protocol->can_toggle);
4574 protocol->is_enabled = enabled;
4578 proto_enable_all(void)
4580 protocol_t *protocol;
4581 GList *list_item = protocols;
4583 if (protocols == NULL)
4587 protocol = (protocol_t *)list_item->data;
4588 if (protocol->can_toggle)
4589 protocol->is_enabled = TRUE;
4590 list_item = g_list_next(list_item);
4595 proto_set_cant_toggle(const int proto_id)
4597 protocol_t *protocol;
4599 protocol = find_protocol_by_id(proto_id);
4600 protocol->can_toggle = FALSE;
4603 /* for use with static arrays only, since we don't allocate our own copies
4604 of the header_field_info struct contained within the hf_register_info struct */
4606 proto_register_field_array(const int parent, hf_register_info *hf, const int num_records)
4609 hf_register_info *ptr = hf;
4612 proto = find_protocol_by_id(parent);
4613 for (i = 0; i < num_records; i++, ptr++) {
4615 * Make sure we haven't registered this yet.
4616 * Most fields have variables associated with them
4617 * that are initialized to -1; some have array elements,
4618 * or possibly uninitialized variables, so we also allow
4619 * 0 (which is unlikely to be the field ID we get back
4620 * from "proto_register_field_init()").
4622 if (*ptr->p_id != -1 && *ptr->p_id != 0) {
4624 "Duplicate field detected in call to proto_register_field_array: %s is already registered\n",
4625 ptr->hfinfo.abbrev);
4629 if (proto != NULL) {
4630 if (proto->fields == NULL) {
4631 proto->fields = g_slist_append(NULL, &ptr->hfinfo);
4632 proto->last_field = proto->fields;
4635 g_slist_append(proto->last_field, &ptr->hfinfo)->next;
4638 field_id = proto_register_field_init(&ptr->hfinfo, parent);
4639 *ptr->p_id = field_id;
4644 proto_register_fields(const int parent, header_field_info **hfi, const int num_records)
4649 proto = find_protocol_by_id(parent);
4650 for (i = 0; i < num_records; i++) {
4652 * Make sure we haven't registered this yet.
4654 if (hfi[i]->id != -1) {
4656 "Duplicate field detected in call to proto_register_field_array: %s is already registered\n",
4661 if (proto != NULL) {
4662 if (proto->fields == NULL) {
4663 proto->fields = g_slist_append(NULL, hfi[i]);
4664 proto->last_field = proto->fields;
4667 g_slist_append(proto->last_field, hfi[i])->next;
4670 proto_register_field_init(hfi[i], parent);
4674 /* unregister already registered fields */
4676 proto_unregister_field (const int parent, gint hf_id)
4678 hf_register_info *hf;
4682 if (hf_id == -1 || hf_id == 0)
4685 proto = find_protocol_by_id (parent);
4686 if (!proto || !proto->fields) {
4690 for (field = proto->fields; field; field = field->next) {
4691 hf = (hf_register_info *)field->data;
4692 if (*hf->p_id == hf_id) {
4693 /* Found the hf_id in this protocol */
4694 g_tree_steal (gpa_name_tree, hf->hfinfo.abbrev);
4695 /* XXX, memleak? g_slist_delete_link() */
4696 proto->fields = g_slist_remove_link (proto->fields, field);
4697 proto->last_field = g_slist_last (proto->fields);
4703 /* chars allowed in field abbrev */
4705 const guchar fld_abbrev_chars[256] = {
4706 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00-0x0F */
4707 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10-0x1F */
4708 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, /* 0x20-0x2F '-', '.' */
4709 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 0x30-0x3F '0'-'9' */
4710 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x40-0x4F 'A'-'O' */
4711 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 0x50-0x5F 'P'-'Z', '_' */
4712 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x60-0x6F 'a'-'o' */
4713 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 0x70-0x7F 'p'-'z' */
4714 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80-0x8F */
4715 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90-0x9F */
4716 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xA0-0xAF */
4717 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xB0-0xBF */
4718 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xC0-0xCF */
4719 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xD0-0xDF */
4720 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xE0-0xEF */
4721 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xF0-0xFF */
4724 static const value_string hf_types[] = {
4725 { FT_NONE, "FT_NONE" },
4726 { FT_PROTOCOL, "FT_PROTOCOL" },
4727 { FT_BOOLEAN, "FT_BOOLEAN" },
4728 { FT_UINT8, "FT_UINT8" },
4729 { FT_UINT16, "FT_UINT16" },
4730 { FT_UINT24, "FT_UINT24" },
4731 { FT_UINT32, "FT_UINT32" },
4732 { FT_UINT64, "FT_UINT64" },
4733 { FT_INT8, "FT_INT8" },
4734 { FT_INT16, "FT_INT16" },
4735 { FT_INT24, "FT_INT24" },
4736 { FT_INT32, "FT_INT32" },
4737 { FT_INT64, "FT_INT64" },
4738 { FT_EUI64, "FT_EUI64" },
4739 { FT_FLOAT, "FT_FLOAT" },
4740 { FT_DOUBLE, "FT_DOUBLE" },
4741 { FT_ABSOLUTE_TIME, "FT_ABSOLUTE_TIME" },
4742 { FT_RELATIVE_TIME, "FT_RELATIVE_TIME" },
4743 { FT_STRING, "FT_STRING" },
4744 { FT_STRINGZ, "FT_STRINGZ" },
4745 { FT_UINT_STRING, "FT_UINT_STRING" },
4746 { FT_ETHER, "FT_ETHER" },
4747 { FT_BYTES, "FT_BYTES" },
4748 { FT_UINT_BYTES, "FT_UINT_BYTES" },
4749 { FT_IPv4, "FT_IPv4" },
4750 { FT_IPv6, "FT_IPv6" },
4751 { FT_IPXNET, "FT_IPXNET" },
4752 { FT_FRAMENUM, "FT_FRAMENUM" },
4753 { FT_PCRE, "FT_PCR" },
4754 { FT_GUID, "FT_GUID" },
4755 { FT_OID, "FT_OID" },
4756 { FT_REL_OID, "FT_REL_OID" },
4759 static const value_string hf_display[] = {
4760 { BASE_NONE, "BASE_NONE" },
4761 { BASE_DEC, "BASE_DEC" },
4762 { BASE_HEX, "BASE_HEX" },
4763 { BASE_OCT, "BASE_OCT" },
4764 { BASE_DEC_HEX, "BASE_DEC_HEX" },
4765 { BASE_HEX_DEC, "BASE_HEX_DEC" },
4766 { BASE_CUSTOM, "BASE_CUSTOM" },
4767 { BASE_NONE|BASE_RANGE_STRING, "BASE_NONE|BASE_RANGE_STRING" },
4768 { BASE_DEC|BASE_RANGE_STRING, "BASE_DEC|BASE_RANGE_STRING" },
4769 { BASE_HEX|BASE_RANGE_STRING, "BASE_HEX|BASE_RANGE_STRING" },
4770 { BASE_OCT|BASE_RANGE_STRING, "BASE_OCT|BASE_RANGE_STRING" },
4771 { BASE_DEC_HEX|BASE_RANGE_STRING, "BASE_DEC_HEX|BASE_RANGE_STRING" },
4772 { BASE_HEX_DEC|BASE_RANGE_STRING, "BASE_HEX_DEC|BASE_RANGE_STRING" },
4773 { BASE_CUSTOM|BASE_RANGE_STRING, "BASE_CUSTOM|BASE_RANGE_STRING" },
4774 { BASE_NONE|BASE_VAL64_STRING, "BASE_NONE|BASE_VAL64_STRING" },
4775 { BASE_DEC|BASE_VAL64_STRING, "BASE_DEC|BASE_VAL64_STRING" },
4776 { BASE_HEX|BASE_VAL64_STRING, "BASE_HEX|BASE_VAL64_STRING" },
4777 { BASE_OCT|BASE_VAL64_STRING, "BASE_OCT|BASE_VAL64_STRING" },
4778 { BASE_DEC_HEX|BASE_VAL64_STRING, "BASE_DEC_HEX|BASE_VAL64_STRING" },
4779 { BASE_HEX_DEC|BASE_VAL64_STRING, "BASE_HEX_DEC|BASE_VAL64_STRING" },
4780 { BASE_CUSTOM|BASE_VAL64_STRING, "BASE_CUSTOM|BASE_VAL64_STRING" },
4781 { ABSOLUTE_TIME_LOCAL, "ABSOLUTE_TIME_LOCAL" },
4782 { ABSOLUTE_TIME_UTC, "ABSOLUTE_TIME_UTC" },
4783 { ABSOLUTE_TIME_DOY_UTC, "ABSOLUTE_TIME_DOY_UTC" },
4786 /* temporary function containing assert part for easier profiling */
4788 tmp_fld_check_assert(header_field_info *hfinfo)
4791 /* The field must have a name (with length > 0) */
4792 if (!hfinfo->name || !hfinfo->name[0]) {
4794 /* Try to identify the field */
4795 g_error("Field (abbrev='%s') does not have a name\n",
4799 g_error("Field does not have a name (nor an abbreviation)\n");
4802 /* fields with an empty string for an abbreviation aren't filterable */
4803 if (!hfinfo->abbrev || !hfinfo->abbrev[0])
4804 g_error("Field '%s' does not have an abbreviation\n", hfinfo->name);
4806 /* These types of fields are allowed to have value_strings,
4807 * true_false_strings or a protocol_t struct
4809 if (hfinfo->strings != NULL && !(
4810 (hfinfo->type == FT_UINT8) ||
4811 (hfinfo->type == FT_UINT16) ||
4812 (hfinfo->type == FT_UINT24) ||
4813 (hfinfo->type == FT_UINT32) ||
4814 (hfinfo->type == FT_UINT64) ||
4815 (hfinfo->type == FT_INT8) ||
4816 (hfinfo->type == FT_INT16) ||
4817 (hfinfo->type == FT_INT24) ||
4818 (hfinfo->type == FT_INT32) ||
4819 (hfinfo->type == FT_INT64) ||
4820 (hfinfo->type == FT_BOOLEAN) ||
4821 (hfinfo->type == FT_PROTOCOL) ))
4822 g_error("Field '%s' (%s) has a 'strings' value but is of type %s"
4823 " (which is not allowed to have strings)\n",
4824 hfinfo->name, hfinfo->abbrev,
4825 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"));
4827 /* TODO: This check may slow down startup, and output quite a few warnings.
4828 It would be good to be able to enable this (and possibly other checks?)
4829 in non-release builds. */
4831 /* Check for duplicate value_string values.
4832 There are lots that have the same value *and* string, so for now only
4833 report those that have same value but different string. */
4834 if ((hfinfo->strings != NULL) &&
4835 !(hfinfo->display & BASE_RANGE_STRING) &&
4836 !((hfinfo->display & BASE_DISPLAY_E_MASK) == BASE_CUSTOM) &&
4838 (hfinfo->type == FT_UINT8) ||
4839 (hfinfo->type == FT_UINT16) ||
4840 (hfinfo->type == FT_UINT24) ||
4841 (hfinfo->type == FT_UINT32) ||
4842 (hfinfo->type == FT_INT8) ||
4843 (hfinfo->type == FT_INT16) ||
4844 (hfinfo->type == FT_INT24) ||
4845 (hfinfo->type == FT_INT32) ||
4846 (hfinfo->type == FT_FRAMENUM) )) {
4849 const value_string *start_values;
4850 const value_string *current;
4852 if (hfinfo->display & BASE_EXT_STRING)
4853 start_values = VALUE_STRING_EXT_VS_P(((const value_string_ext*)hfinfo->strings));
4855 start_values = (const value_string*)hfinfo->strings;
4856 current = start_values;
4858 for (n=0; current; n++, current++) {
4859 /* Drop out if we reached the end. */
4860 if ((current->value == 0) && (current->strptr == NULL)) {
4864 /* Check value against all previous */
4865 for (m=0; m < n; m++) {
4866 /* There are lots of duplicates with the same string,
4867 so only report if different... */
4868 if ((start_values[m].value == current->value) &&
4869 (strcmp(start_values[m].strptr, current->strptr) != 0)) {
4870 g_warning("Field '%s' (%s) has a conflicting entry in its"
4871 " value_string: %u is at indices %u (%s) and %u (%s))\n",
4872 hfinfo->name, hfinfo->abbrev,
4873 current->value, m, start_values[m].strptr, n, current->strptr);
4881 switch (hfinfo->type) {
4888 /* Hexadecimal and octal are, in printf() and everywhere
4889 * else, unsigned so don't allow dissectors to register a
4890 * signed field to be displayed unsigned. (Else how would
4891 * we display negative values?)
4893 switch (hfinfo->display & BASE_DISPLAY_E_MASK) {
4898 g_error("Field '%s' (%s) is signed (%s) but is being displayed unsigned (%s)\n",
4899 hfinfo->name, hfinfo->abbrev,
4900 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"),
4901 val_to_str(hfinfo->display, hf_display, "(Bit count: %d)"));
4909 /* Require integral types (other than frame number,
4910 * which is always displayed in decimal) to have a
4912 * If there is a strings value then this base is not
4913 * normally used except when constructing a display
4914 * filter for a value not found in the strings lookup.
4916 switch (hfinfo->display & BASE_DISPLAY_E_MASK) {
4922 case BASE_CUSTOM: /* hfinfo_numeric_value_format() treats this as decimal */
4925 g_error("Field '%s' (%s) is an integral value (%s)"
4926 " but is being displayed as %s\n",
4927 hfinfo->name, hfinfo->abbrev,
4928 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"),
4929 val_to_str(hfinfo->display, hf_display, "(Unknown: 0x%x)"));
4935 if (hfinfo->display != BASE_NONE)
4936 g_error("Field '%s' (%s) is an %s but is being displayed as %s instead of BASE_NONE\n",
4937 hfinfo->name, hfinfo->abbrev,
4938 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"),
4939 val_to_str(hfinfo->display, hf_display, "(Bit count: %d)"));
4940 if (hfinfo->bitmask != 0)
4941 g_error("Field '%s' (%s) is an %s but has a bitmask\n",
4942 hfinfo->name, hfinfo->abbrev,
4943 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"));
4949 case FT_ABSOLUTE_TIME:
4950 if (!(hfinfo->display == ABSOLUTE_TIME_LOCAL ||
4951 hfinfo->display == ABSOLUTE_TIME_UTC ||
4952 hfinfo->display == ABSOLUTE_TIME_DOY_UTC))
4953 g_error("Field '%s' (%s) is a %s but is being displayed as %s instead of as a time\n",
4954 hfinfo->name, hfinfo->abbrev,
4955 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"),
4956 val_to_str(hfinfo->display, hf_display, "(Bit count: %d)"));
4957 if (hfinfo->bitmask != 0)
4958 g_error("Field '%s' (%s) is an %s but has a bitmask\n",
4959 hfinfo->name, hfinfo->abbrev,
4960 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"));
4964 if (hfinfo->display != BASE_NONE)
4965 g_error("Field '%s' (%s) is an %s but is being displayed as %s instead of BASE_NONE\n",
4966 hfinfo->name, hfinfo->abbrev,
4967 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"),
4968 val_to_str(hfinfo->display, hf_display, "(Bit count: %d)"));
4969 if (hfinfo->bitmask != 0)
4970 g_error("Field '%s' (%s) is an %s but has a bitmask\n",
4971 hfinfo->name, hfinfo->abbrev,
4972 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"));
4973 if (hfinfo->strings != NULL)
4974 g_error("Field '%s' (%s) is an %s but has a strings value\n",
4975 hfinfo->name, hfinfo->abbrev,
4976 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"));
4982 register_type_length_mismatch(void)
4984 static ei_register_info ei[] = {
4985 { &ei_type_length_mismatch_error, { "_ws.type_length.mismatch", PI_MALFORMED, PI_ERROR, "Trying to fetch X with length Y", EXPFILL }},
4986 { &ei_type_length_mismatch_warn, { "_ws.type_length.mismatch", PI_MALFORMED, PI_WARN, "Trying to fetch X with length Y", EXPFILL }},
4989 expert_module_t* expert_type_length_mismatch;
4991 proto_type_length_mismatch = proto_register_protocol("Type Length Mismatch", "Type length mismatch", "_ws.type_length");
4993 expert_type_length_mismatch = expert_register_protocol(proto_type_length_mismatch);
4994 expert_register_field_array(expert_type_length_mismatch, ei, array_length(ei));
4996 /* "Type Length Mismatch" isn't really a protocol, it's an error indication;
4997 disabling them makes no sense. */
4998 proto_set_cant_toggle(proto_type_length_mismatch);
5001 #define PROTO_PRE_ALLOC_HF_FIELDS_MEM (120000+PRE_ALLOC_EXPERT_FIELDS_MEM)
5003 proto_register_field_init(header_field_info *hfinfo, const int parent)
5006 tmp_fld_check_assert(hfinfo);
5008 hfinfo->parent = parent;
5009 hfinfo->same_name_next = NULL;
5010 hfinfo->same_name_prev_id = -1;
5012 /* if we always add and never delete, then id == len - 1 is correct */
5013 if (gpa_hfinfo.len >= gpa_hfinfo.allocated_len) {
5014 if (!gpa_hfinfo.hfi) {
5015 gpa_hfinfo.allocated_len = PROTO_PRE_ALLOC_HF_FIELDS_MEM;
5016 gpa_hfinfo.hfi = (header_field_info **)g_malloc(sizeof(header_field_info *)*PROTO_PRE_ALLOC_HF_FIELDS_MEM);
5018 gpa_hfinfo.allocated_len += 1000;
5019 gpa_hfinfo.hfi = (header_field_info **)g_realloc(gpa_hfinfo.hfi,
5020 sizeof(header_field_info *)*gpa_hfinfo.allocated_len);
5021 /*g_warning("gpa_hfinfo.allocated_len %u", gpa_hfinfo.allocated_len);*/
5024 gpa_hfinfo.hfi[gpa_hfinfo.len] = hfinfo;
5026 hfinfo->id = gpa_hfinfo.len - 1;
5028 /* if we have real names, enter this field in the name tree */
5029 if ((hfinfo->name[0] != 0) && (hfinfo->abbrev[0] != 0 )) {
5031 header_field_info *same_name_next_hfinfo;
5034 /* Check that the filter name (abbreviation) is legal;
5035 * it must contain only alphanumerics, '-', "_", and ".". */
5036 c = wrs_check_charset(fld_abbrev_chars, hfinfo->abbrev);
5038 fprintf(stderr, "Invalid character '%c' in filter name '%s'\n", c, hfinfo->abbrev);
5039 DISSECTOR_ASSERT(!c);
5042 /* We allow multiple hfinfo's to be registered under the same
5043 * abbreviation. This was done for X.25, as, depending
5044 * on whether it's modulo-8 or modulo-128 operation,
5045 * some bitfield fields may be in different bits of
5046 * a byte, and we want to be able to refer to that field
5047 * with one name regardless of whether the packets
5048 * are modulo-8 or modulo-128 packets. */
5050 same_name_hfinfo = NULL;
5052 g_tree_insert(gpa_name_tree, (gpointer) (hfinfo->abbrev), hfinfo);
5053 /* GLIB 2.x - if it is already present
5054 * the previous hfinfo with the same name is saved
5055 * to same_name_hfinfo by value destroy callback */
5056 if (same_name_hfinfo) {
5057 /* There's already a field with this name.
5058 * Put it after that field in the list of
5059 * fields with this name, then allow the code
5060 * after this if{} block to replace the old
5061 * hfinfo with the new hfinfo in the GTree. Thus,
5062 * we end up with a linked-list of same-named hfinfo's,
5063 * with the root of the list being the hfinfo in the GTree */
5064 same_name_next_hfinfo =
5065 same_name_hfinfo->same_name_next;
5067 hfinfo->same_name_next = same_name_next_hfinfo;
5068 if (same_name_next_hfinfo)
5069 same_name_next_hfinfo->same_name_prev_id = hfinfo->id;
5071 same_name_hfinfo->same_name_next = hfinfo;
5072 hfinfo->same_name_prev_id = same_name_hfinfo->id;
5080 proto_register_subtree_array(gint *const *indices, const int num_indices)
5083 gint *const *ptr = indices;
5086 * If we've already allocated the array of tree types, expand
5087 * it; this lets plugins such as mate add tree types after
5088 * the initial startup. (If we haven't already allocated it,
5089 * we don't allocate it; on the first pass, we just assign
5090 * ett values and keep track of how many we've assigned, and
5091 * when we're finished registering all dissectors we allocate
5092 * the array, so that we do only one allocation rather than
5093 * wasting CPU time and memory by growing the array for each
5094 * dissector that registers ett values.)
5096 if (tree_is_expanded != NULL) {
5097 tree_is_expanded = (guint32 *)g_realloc(tree_is_expanded, (1+((num_tree_types + num_indices)/32)) * sizeof(guint32));
5099 /* set new items to 0 */
5100 /* XXX, slow!!! optimize when needed (align 'i' to 32, and set rest of guint32 to 0) */
5101 for (i = num_tree_types; i < num_tree_types + num_indices; i++)
5102 tree_is_expanded[i >> 5] &= ~(1 << (i & 31));
5106 * Assign "num_indices" subtree numbers starting at "num_tree_types",
5107 * returning the indices through the pointers in the array whose
5108 * first element is pointed to by "indices", and update
5109 * "num_tree_types" appropriately.
5111 for (i = 0; i < num_indices; i++, ptr++, num_tree_types++) {
5113 /* g_error will terminate the program */
5114 g_error("register_subtree_array: subtree item type (ett_...) not -1 !"
5115 " This is a development error:"
5116 " Either the subtree item type has already been assigned or"
5117 " was not initialized to -1.");
5119 **ptr = num_tree_types;
5124 label_concat(char *label_str, gsize pos, const char *str)
5126 if (pos < ITEM_LABEL_LENGTH)
5127 pos += g_strlcpy(label_str + pos, str, ITEM_LABEL_LENGTH - pos);
5133 label_mark_truncated(char *label_str, gsize name_pos)
5135 static const char trunc_str[] = " [truncated]";
5136 const size_t trunc_len = sizeof(trunc_str)-1;
5138 /* ..... field_name: dataaaaaaaaaaaaa
5142 * ..... field_name [truncated]: dataaaaaaaaaaaaa */
5144 if (name_pos < ITEM_LABEL_LENGTH - trunc_len) {
5145 memmove(label_str + name_pos + trunc_len, label_str + name_pos, ITEM_LABEL_LENGTH - name_pos - trunc_len);
5146 memcpy(label_str + name_pos, trunc_str, trunc_len);
5147 label_str[ITEM_LABEL_LENGTH-1] = '\0';
5149 } else if (name_pos < ITEM_LABEL_LENGTH)
5150 g_strlcpy(label_str + name_pos, trunc_str, ITEM_LABEL_LENGTH - name_pos);
5154 label_fill(char *label_str, gsize pos, const header_field_info *hfinfo, const char *text)
5158 /* "%s: %s", hfinfo->name, text */
5159 name_pos = pos = label_concat(label_str, pos, hfinfo->name);
5160 pos = label_concat(label_str, pos, ": ");
5161 pos = label_concat(label_str, pos, text ? text : "(null)");
5163 if (pos >= ITEM_LABEL_LENGTH) {
5164 /* Uh oh, we don't have enough room. Tell the user that the field is truncated. */
5165 label_mark_truncated(label_str, name_pos);
5172 label_fill_descr(char *label_str, gsize pos, const header_field_info *hfinfo, const char *text, const char *descr)
5176 /* "%s: %s (%s)", hfinfo->name, text, descr */
5177 name_pos = pos = label_concat(label_str, pos, hfinfo->name);
5178 pos = label_concat(label_str, pos, ": ");
5179 pos = label_concat(label_str, pos, text ? text : "(null)");
5180 pos = label_concat(label_str, pos, " (");
5181 pos = label_concat(label_str, pos, descr ? descr : "(null)");
5182 pos = label_concat(label_str, pos, ")");
5184 if (pos >= ITEM_LABEL_LENGTH) {
5185 /* Uh oh, we don't have enough room. Tell the user that the field is truncated. */
5186 label_mark_truncated(label_str, name_pos);
5193 proto_item_fill_label(field_info *fi, gchar *label_str)
5195 header_field_info *hfinfo;
5201 guint32 n_addr; /* network-order IPv4 address */
5208 /* XXX: Check validity of hfinfo->type */
5212 hfinfo = fi->hfinfo;
5214 switch (hfinfo->type) {
5217 g_strlcpy(label_str, hfinfo->name, ITEM_LABEL_LENGTH);
5221 fill_label_boolean(fi, label_str);
5226 bytes = (guint8 *)fvalue_get(&fi->value);
5227 label_fill(label_str, 0, hfinfo,
5228 (bytes) ? bytes_to_str(bytes, fvalue_length(&fi->value)) : "<MISSING>");
5231 /* Four types of integers to take care of:
5232 * Bitfield, with val_string
5233 * Bitfield, w/o val_string
5234 * Non-bitfield, with val_string
5235 * Non-bitfield, w/o val_string
5241 if (hfinfo->bitmask) {
5242 fill_label_bitfield(fi, label_str, FALSE);
5244 fill_label_number(fi, label_str, FALSE);
5249 fill_label_number(fi, label_str, FALSE);
5253 fill_label_number64(fi, label_str, FALSE);
5260 if (hfinfo->bitmask) {
5261 fill_label_bitfield(fi, label_str, TRUE);
5263 fill_label_number(fi, label_str, TRUE);
5268 fill_label_number64(fi, label_str, TRUE);
5272 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5273 "%s: %." STRINGIFY(FLT_DIG) "g",
5274 hfinfo->name, fvalue_get_floating(&fi->value));
5278 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5279 "%s: %." STRINGIFY(DBL_DIG) "g",
5280 hfinfo->name, fvalue_get_floating(&fi->value));
5283 case FT_ABSOLUTE_TIME:
5284 label_fill(label_str, 0, hfinfo,
5285 abs_time_to_str((const nstime_t *)fvalue_get(&fi->value),
5286 (absolute_time_display_e)hfinfo->display, TRUE));
5289 case FT_RELATIVE_TIME:
5290 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5291 "%s: %s seconds", hfinfo->name,
5292 rel_time_to_secs_str((const nstime_t *)fvalue_get(&fi->value)));
5296 integer = fvalue_get_uinteger(&fi->value);
5297 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5298 "%s: %s (0x%08X)", hfinfo->name,
5299 get_ipxnet_name(integer), integer);
5303 bytes = (guint8 *)fvalue_get(&fi->value);
5304 label_fill_descr(label_str, 0, hfinfo,
5305 get_ax25_name(bytes),
5306 ax25_to_str(bytes));
5310 addr.type = AT_VINES;
5311 addr.len = VINES_ADDR_LEN;
5312 addr.data = (guint8 *)fvalue_get(&fi->value);
5314 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5315 "%s: %s", hfinfo->name,
5316 address_to_str( &addr ));
5320 bytes = (guint8 *)fvalue_get(&fi->value);
5321 label_fill_descr(label_str, 0, hfinfo,
5322 get_ether_name(bytes),
5323 ether_to_str(bytes));
5327 ipv4 = (ipv4_addr *)fvalue_get(&fi->value);
5328 n_addr = ipv4_get_net_order_addr(ipv4);
5329 label_fill_descr(label_str, 0, hfinfo,
5330 get_hostname(n_addr),
5331 ip_to_str((guint8*)&n_addr));
5335 bytes = (guint8 *)fvalue_get(&fi->value);
5336 label_fill_descr(label_str, 0, hfinfo,
5337 get_hostname6((struct e_in6_addr *)bytes),
5338 ip6_to_str((struct e_in6_addr*)bytes));
5342 guid = (e_guid_t *)fvalue_get(&fi->value);
5343 label_fill(label_str, 0, hfinfo, guid_to_str(guid));
5347 bytes = (guint8 *)fvalue_get(&fi->value);
5348 name = oid_resolved_from_encoded(bytes, fvalue_length(&fi->value));
5350 label_fill_descr(label_str, 0, hfinfo,
5351 oid_encoded2string(bytes, fvalue_length(&fi->value)), name);
5353 label_fill(label_str, 0, hfinfo,
5354 oid_encoded2string(bytes, fvalue_length(&fi->value)));
5359 bytes = (guint8 *)fvalue_get(&fi->value);
5360 name = rel_oid_resolved_from_encoded(bytes, fvalue_length(&fi->value));
5362 label_fill_descr(label_str, 0, hfinfo,
5363 rel_oid_encoded2string(bytes, fvalue_length(&fi->value)), name);
5365 label_fill(label_str, 0, hfinfo,
5366 rel_oid_encoded2string(bytes, fvalue_length(&fi->value)));
5371 integer64 = fvalue_get_integer64(&fi->value);
5372 label_fill_descr(label_str, 0, hfinfo,
5373 get_eui64_name(integer64),
5374 eui64_to_str(integer64));
5378 case FT_UINT_STRING:
5379 bytes = (guint8 *)fvalue_get(&fi->value);
5380 label_fill(label_str, 0, hfinfo, format_text(bytes, strlen(bytes)));
5384 g_error("hfinfo->type %d (%s) not handled\n",
5385 hfinfo->type, ftype_name(hfinfo->type));
5386 DISSECTOR_ASSERT_NOT_REACHED();
5392 fill_label_boolean(field_info *fi, gchar *label_str)
5394 char *p = label_str;
5395 int bitfield_byte_length = 0, bitwidth;
5396 guint32 unshifted_value;
5399 header_field_info *hfinfo = fi->hfinfo;
5400 const true_false_string *tfstring = (const true_false_string *)&tfs_true_false;
5402 if (hfinfo->strings) {
5403 tfstring = (const struct true_false_string*) hfinfo->strings;
5406 value = fvalue_get_uinteger(&fi->value);
5407 if (hfinfo->bitmask) {
5408 /* Figure out the bit width */
5409 bitwidth = hfinfo_bitwidth(hfinfo);
5412 unshifted_value = value;
5413 unshifted_value <<= hfinfo_bitshift(hfinfo);
5415 /* Create the bitfield first */
5416 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
5417 bitfield_byte_length = (int) (p - label_str);
5420 /* Fill in the textual info */
5421 label_fill(label_str, bitfield_byte_length, hfinfo, value ? tfstring->true_string : tfstring->false_string);
5425 hf_try_val_to_str(guint32 value, const header_field_info *hfinfo)
5427 if (hfinfo->display & BASE_RANGE_STRING)
5428 return try_rval_to_str(value, (const range_string *) hfinfo->strings);
5430 if (hfinfo->display & BASE_EXT_STRING)
5431 return try_val_to_str_ext(value, (const value_string_ext *) hfinfo->strings);
5433 if (hfinfo->display & BASE_VAL64_STRING)
5434 return try_val64_to_str(value, (const val64_string *) hfinfo->strings);
5436 return try_val_to_str(value, (const value_string *) hfinfo->strings);
5440 hf_try_val64_to_str(guint64 value, const header_field_info *hfinfo)
5442 if (hfinfo->display & BASE_VAL64_STRING)
5443 return try_val64_to_str(value, (const val64_string *) hfinfo->strings);
5445 /* If this is reached somebody registered a 64-bit field with a 32-bit
5446 * value-string, which isn't right. */
5447 DISSECTOR_ASSERT_NOT_REACHED();
5449 /* This is necessary to squelch MSVC errors; is there
5450 any way to tell it that DISSECTOR_ASSERT_NOT_REACHED()
5456 hf_try_val_to_str_const(guint32 value, const header_field_info *hfinfo, const char *unknown_str)
5458 const char *str = hf_try_val_to_str(value, hfinfo);
5460 return (str) ? str : unknown_str;
5464 hf_try_val64_to_str_const(guint64 value, const header_field_info *hfinfo, const char *unknown_str)
5466 const char *str = hf_try_val64_to_str(value, hfinfo);
5468 return (str) ? str : unknown_str;
5471 /* Fills data for bitfield ints with val_strings */
5473 fill_label_bitfield(field_info *fi, gchar *label_str, gboolean is_signed)
5476 int bitfield_byte_length, bitwidth;
5477 guint32 unshifted_value;
5483 header_field_info *hfinfo = fi->hfinfo;
5485 /* Figure out the bit width */
5486 bitwidth = hfinfo_bitwidth(hfinfo);
5490 unshifted_value = fvalue_get_sinteger(&fi->value);
5492 unshifted_value = fvalue_get_uinteger(&fi->value);
5494 value = unshifted_value;
5495 if (hfinfo->bitmask) {
5496 unshifted_value <<= hfinfo_bitshift(hfinfo);
5499 /* Create the bitfield first */
5500 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
5501 bitfield_byte_length = (int) (p - label_str);
5503 /* Fill in the textual info using stored (shifted) value */
5504 if (hfinfo->display == BASE_CUSTOM) {
5505 gchar tmp[ITEM_LABEL_LENGTH];
5506 const custom_fmt_func_t fmtfunc = (const custom_fmt_func_t)hfinfo->strings;
5508 DISSECTOR_ASSERT(fmtfunc);
5509 fmtfunc(tmp, value);
5510 label_fill(label_str, bitfield_byte_length, hfinfo, tmp);
5512 else if (hfinfo->strings) {
5513 const char *val_str = hf_try_val_to_str_const(value, hfinfo, "Unknown");
5515 out = hfinfo_number_vals_format(hfinfo, buf, value);
5516 if (out == NULL) /* BASE_NONE so don't put integer in descr */
5517 label_fill(label_str, bitfield_byte_length, hfinfo, val_str);
5519 label_fill_descr(label_str, bitfield_byte_length, hfinfo, val_str, out);
5522 out = hfinfo_number_value_format(hfinfo, buf, value);
5524 label_fill(label_str, bitfield_byte_length, hfinfo, out);
5529 fill_label_number(field_info *fi, gchar *label_str, gboolean is_signed)
5531 header_field_info *hfinfo = fi->hfinfo;
5538 value = fvalue_get_sinteger(&fi->value);
5540 value = fvalue_get_uinteger(&fi->value);
5542 /* Fill in the textual info */
5543 if (hfinfo->display == BASE_CUSTOM) {
5544 gchar tmp[ITEM_LABEL_LENGTH];
5545 const custom_fmt_func_t fmtfunc = (const custom_fmt_func_t)hfinfo->strings;
5547 DISSECTOR_ASSERT(fmtfunc);
5548 fmtfunc(tmp, value);
5549 label_fill(label_str, 0, hfinfo, tmp);
5551 else if (hfinfo->strings) {
5552 const char *val_str = hf_try_val_to_str_const(value, hfinfo, "Unknown");
5554 out = hfinfo_number_vals_format(hfinfo, buf, value);
5555 if (out == NULL) /* BASE_NONE so don't put integer in descr */
5556 label_fill(label_str, 0, hfinfo, val_str);
5558 label_fill_descr(label_str, 0, hfinfo, val_str, out);
5561 out = hfinfo_number_value_format(hfinfo, buf, value);
5563 label_fill(label_str, 0, hfinfo, out);
5568 fill_label_number64(field_info *fi, gchar *label_str, gboolean is_signed)
5570 const char *format = NULL;
5571 header_field_info *hfinfo = fi->hfinfo;
5573 char tmp[ITEM_LABEL_LENGTH+1];
5575 /* Pick the proper format string */
5577 format = hfinfo_int64_format(hfinfo);
5579 format = hfinfo_uint64_format(hfinfo);
5581 value = fvalue_get_integer64(&fi->value);
5583 /* Format the temporary string */
5584 if (IS_BASE_DUAL(hfinfo->display))
5585 g_snprintf(tmp, ITEM_LABEL_LENGTH, format, value, value);
5587 g_snprintf(tmp, ITEM_LABEL_LENGTH, format, value);
5589 if (hfinfo->strings) {
5590 const char *val_str = hf_try_val64_to_str_const(value, hfinfo, "Unknown");
5592 if ((hfinfo->display & BASE_DISPLAY_E_MASK) == BASE_NONE) {
5593 label_fill(label_str, 0, hfinfo, val_str);
5596 label_fill_descr(label_str, 0, hfinfo, val_str, tmp);
5600 label_fill(label_str, 0, hfinfo, tmp);
5605 hfinfo_bitshift(const header_field_info *hfinfo)
5607 const guint32 bitmask = hfinfo->bitmask;
5609 #if defined(__GNUC__) && ((__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4))
5610 g_assert(bitmask != 0);
5612 return __builtin_ctz(bitmask);
5614 /* From http://graphics.stanford.edu/~seander/bithacks.html#ZerosOnRightMultLookup */
5615 static const int table[32] = {
5616 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
5617 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9
5620 return table[((guint32)((bitmask & -(gint32)bitmask) * 0x077CB531U)) >> 27];
5625 hfinfo_bitwidth(const header_field_info *hfinfo)
5629 if (!hfinfo->bitmask) {
5633 switch (hfinfo->type) {
5651 bitwidth = hfinfo->display; /* hacky? :) */
5654 DISSECTOR_ASSERT_NOT_REACHED();
5661 _hfinfo_type_hex_octet(int type)
5681 DISSECTOR_ASSERT_NOT_REACHED();
5687 /* private to_str.c API don't export to .h! */
5688 char *oct_to_str_back(char *ptr, guint32 value);
5689 char *hex_to_str_back(char *ptr, int pad, guint32 value);
5690 char *uint_to_str_back(char *ptr, guint32 value);
5691 char *int_to_str_back(char *ptr, gint32 value);
5694 hfinfo_number_value_format_display(const header_field_info *hfinfo, int display, char buf[32], guint32 value)
5696 char *ptr = &buf[31];
5697 gboolean isint = IS_FT_INT(hfinfo->type);
5700 /* Properly format value */
5703 return isint ? int_to_str_back(ptr, (gint32) value) : uint_to_str_back(ptr, value);
5707 ptr = hex_to_str_back(ptr, _hfinfo_type_hex_octet(hfinfo->type), value);
5710 ptr = isint ? int_to_str_back(ptr, (gint32) value) : uint_to_str_back(ptr, value);
5714 return oct_to_str_back(ptr, value);
5717 return hex_to_str_back(ptr, _hfinfo_type_hex_octet(hfinfo->type), value);
5721 ptr = isint ? int_to_str_back(ptr, (gint32) value) : uint_to_str_back(ptr, value);
5724 ptr = hex_to_str_back(ptr, _hfinfo_type_hex_octet(hfinfo->type), value);
5728 DISSECTOR_ASSERT_NOT_REACHED();
5735 hfinfo_number_value_format(const header_field_info *hfinfo, char buf[32], guint32 value)
5737 int display = hfinfo->display;
5739 if (hfinfo->type == FT_FRAMENUM) {
5741 * Frame numbers are always displayed in decimal.
5746 return hfinfo_number_value_format_display(hfinfo, display, buf, value);
5750 hfinfo_numeric_value_format(const header_field_info *hfinfo, char buf[32], guint32 value)
5752 /* Get the underlying BASE_ value */
5753 int display = hfinfo->display & BASE_DISPLAY_E_MASK;
5755 if (hfinfo->type == FT_FRAMENUM) {
5757 * Frame numbers are always displayed in decimal.
5764 /* case BASE_DEC: */
5766 case BASE_OCT: /* XXX, why we're changing BASE_OCT to BASE_DEC? */
5771 /* case BASE_HEX: */
5777 return hfinfo_number_value_format_display(hfinfo, display, buf, value);
5781 hfinfo_number_vals_format(const header_field_info *hfinfo, char buf[32], guint32 value)
5783 /* Get the underlying BASE_ value */
5784 int display = hfinfo->display & BASE_DISPLAY_E_MASK;
5786 if (display == BASE_NONE)
5789 if (display == BASE_DEC_HEX)
5791 if (display == BASE_HEX_DEC)
5794 return hfinfo_number_value_format_display(hfinfo, display, buf, value);
5798 hfinfo_uint64_format(const header_field_info *hfinfo)
5800 const char *format = NULL;
5802 /* Pick the proper format string */
5803 switch (hfinfo->display & BASE_DISPLAY_E_MASK) {
5805 format = "%" G_GINT64_MODIFIER "u";
5808 format = "%" G_GINT64_MODIFIER "u (0x%016" G_GINT64_MODIFIER "x)";
5810 case BASE_OCT: /* I'm lazy */
5811 format = "%#" G_GINT64_MODIFIER "o";
5814 format = "0x%016" G_GINT64_MODIFIER "x";
5817 format = "0x%016" G_GINT64_MODIFIER "x (%" G_GINT64_MODIFIER "u)";
5820 DISSECTOR_ASSERT_NOT_REACHED();
5827 hfinfo_int64_format(const header_field_info *hfinfo)
5829 const char *format = NULL;
5831 /* Pick the proper format string */
5832 switch (hfinfo->display & BASE_DISPLAY_E_MASK) {
5834 format = "%" G_GINT64_MODIFIER "d";
5837 format = "%" G_GINT64_MODIFIER "d (0x%016" G_GINT64_MODIFIER "x)";
5839 case BASE_OCT: /* I'm lazy */
5840 format = "%#" G_GINT64_MODIFIER "o";
5843 format = "0x%016" G_GINT64_MODIFIER "x";
5846 format = "0x%016" G_GINT64_MODIFIER "x (%" G_GINT64_MODIFIER "d)";
5849 DISSECTOR_ASSERT_NOT_REACHED();
5856 proto_registrar_n(void)
5858 return gpa_hfinfo.len;
5862 proto_registrar_get_name(const int n)
5864 header_field_info *hfinfo;
5866 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
5867 return hfinfo->name;
5871 proto_registrar_get_abbrev(const int n)
5873 header_field_info *hfinfo;
5875 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
5876 return hfinfo->abbrev;
5880 proto_registrar_get_ftype(const int n)
5882 header_field_info *hfinfo;
5884 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
5885 return hfinfo->type;
5889 proto_registrar_get_parent(const int n)
5891 header_field_info *hfinfo;
5893 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
5894 return hfinfo->parent;
5898 proto_registrar_is_protocol(const int n)
5900 header_field_info *hfinfo;
5902 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
5903 return (hfinfo->parent == -1 ? TRUE : FALSE);
5906 /* Returns length of field in packet (not necessarily the length
5907 * in our internal representation, as in the case of IPv4).
5908 * 0 means undeterminable at time of registration
5909 * -1 means the field is not registered. */
5911 proto_registrar_get_length(const int n)
5913 header_field_info *hfinfo;
5915 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
5916 return ftype_length(hfinfo->type);
5919 /* Looks for a protocol or a field in a proto_tree. Returns TRUE if
5920 * it exists anywhere, or FALSE if it exists nowhere. */
5922 proto_check_for_protocol_or_field(const proto_tree* tree, const int id)
5924 GPtrArray *ptrs = proto_get_finfo_ptr_array(tree, id);
5929 else if (g_ptr_array_len(ptrs) > 0) {
5937 /* Return GPtrArray* of field_info pointers for all hfindex that appear in tree.
5938 * This only works if the hfindex was "primed" before the dissection
5939 * took place, as we just pass back the already-created GPtrArray*.
5940 * The caller should *not* free the GPtrArray*; proto_tree_free_node()
5943 proto_get_finfo_ptr_array(const proto_tree *tree, const int id)
5948 if (PTREE_DATA(tree)->interesting_hfids != NULL)
5949 return (GPtrArray *)g_hash_table_lookup(PTREE_DATA(tree)->interesting_hfids,
5950 GINT_TO_POINTER(id));
5956 proto_tracking_interesting_fields(const proto_tree *tree)
5961 return (PTREE_DATA(tree)->interesting_hfids != NULL);
5964 /* Helper struct for proto_find_info() and proto_all_finfos() */
5970 /* Helper function for proto_find_info() */
5972 find_finfo(proto_node *node, gpointer data)
5974 field_info *fi = PNODE_FINFO(node);
5975 if (fi && fi->hfinfo) {
5976 if (fi->hfinfo->id == ((ffdata_t*)data)->id) {
5977 g_ptr_array_add(((ffdata_t*)data)->array, fi);
5981 /* Don't stop traversing. */
5985 /* Return GPtrArray* of field_info pointers for all hfindex that appear in a tree.
5986 * This works on any proto_tree, primed or unprimed, but actually searches
5987 * the tree, so it is slower than using proto_get_finfo_ptr_array on a primed tree.
5988 * The caller does need to free the returned GPtrArray with
5989 * g_ptr_array_free(<array>, TRUE).
5992 proto_find_finfo(proto_tree *tree, const int id)
5996 ffdata.array = g_ptr_array_new();
5999 proto_tree_traverse_pre_order(tree, find_finfo, &ffdata);
6001 return ffdata.array;
6004 /* Helper function for proto_all_finfos() */
6006 every_finfo(proto_node *node, gpointer data)
6008 field_info *fi = PNODE_FINFO(node);
6009 if (fi && fi->hfinfo) {
6010 g_ptr_array_add(((ffdata_t*)data)->array, fi);
6013 /* Don't stop traversing. */
6017 /* Return GPtrArray* of field_info pointers containing all hfindexes that appear in a tree. */
6019 proto_all_finfos(proto_tree *tree)
6023 ffdata.array = g_ptr_array_new();
6026 proto_tree_traverse_pre_order(tree, every_finfo, &ffdata);
6028 return ffdata.array;
6039 check_for_offset(proto_node *node, const gpointer data)
6041 field_info *fi = PNODE_FINFO(node);
6042 offset_search_t *offsearch = (offset_search_t *)data;
6044 /* !fi == the top most container node which holds nothing */
6045 if (fi && !PROTO_ITEM_IS_HIDDEN(node) && fi->ds_tvb && offsearch->tvb == fi->ds_tvb) {
6046 if (offsearch->offset >= (guint) fi->start &&
6047 offsearch->offset < (guint) (fi->start + fi->length)) {
6049 offsearch->finfo = fi;
6050 return FALSE; /* keep traversing */
6053 return FALSE; /* keep traversing */
6056 /* Search a proto_tree backwards (from leaves to root) looking for the field
6057 * whose start/length occupies 'offset' */
6058 /* XXX - I couldn't find an easy way to search backwards, so I search
6059 * forwards, w/o stopping. Therefore, the last finfo I find will the be
6060 * the one I want to return to the user. This algorithm is inefficient
6061 * and could be re-done, but I'd have to handle all the children and
6062 * siblings of each node myself. When I have more time I'll do that.
6065 proto_find_field_from_offset(proto_tree *tree, guint offset, tvbuff_t *tvb)
6067 offset_search_t offsearch;
6069 offsearch.offset = offset;
6070 offsearch.finfo = NULL;
6071 offsearch.tvb = tvb;
6073 proto_tree_traverse_pre_order(tree, check_for_offset, &offsearch);
6075 return offsearch.finfo;
6078 /* Dumps the protocols in the registration database to stdout. An independent
6079 * program can take this output and format it into nice tables or HTML or
6082 * There is one record per line. The fields are tab-delimited.
6084 * Field 1 = protocol name
6085 * Field 2 = protocol short name
6086 * Field 3 = protocol filter name
6089 proto_registrar_dump_protocols(void)
6091 protocol_t *protocol;
6093 void *cookie = NULL;
6096 i = proto_get_first_protocol(&cookie);
6098 protocol = find_protocol_by_id(i);
6099 printf("%s\t%s\t%s\n", protocol->name, protocol->short_name,
6100 protocol->filter_name);
6101 i = proto_get_next_protocol(&cookie);
6105 /* Dumps the value_strings, extended value string headers, range_strings
6106 * or true/false strings for fields that have them.
6107 * There is one record per line. Fields are tab-delimited.
6108 * There are four types of records: Value String, Extended Value String Header,
6109 * Range String and True/False String. The first field, 'V', 'E', 'R' or 'T', indicates
6110 * the type of record.
6112 * Note that a record will be generated only if the value_string,... is referenced
6113 * in a registered hfinfo entry.
6119 * Field 2 = Field abbreviation to which this value string corresponds
6120 * Field 3 = Integer value
6123 * Extended Value String Headers
6124 * -----------------------------
6126 * Field 2 = Field abbreviation to which this extended value string header corresponds
6127 * Field 3 = Extended Value String "Name"
6128 * Field 4 = Number of entries in the associated value_string array
6129 * Field 5 = Access Type: "Linear Search", "Binary Search", "Direct (indexed) Access"
6134 * Field 2 = Field abbreviation to which this range string corresponds
6135 * Field 3 = Integer value: lower bound
6136 * Field 4 = Integer value: upper bound
6139 * True/False Strings
6140 * ------------------
6142 * Field 2 = Field abbreviation to which this true/false string corresponds
6143 * Field 3 = True String
6144 * Field 4 = False String
6147 proto_registrar_dump_values(void)
6149 header_field_info *hfinfo;
6151 const value_string *vals;
6152 const val64_string *vals64;
6153 const range_string *range;
6154 const true_false_string *tfs;
6156 len = gpa_hfinfo.len;
6157 for (i = 0; i < len ; i++) {
6158 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
6160 if (hfinfo->id == hf_text_only) {
6164 /* ignore protocols */
6165 if (proto_registrar_is_protocol(i)) {
6168 /* process header fields */
6171 * If this field isn't at the head of the list of
6172 * fields with this name, skip this field - all
6173 * fields with the same name are really just versions
6174 * of the same field stored in different bits, and
6175 * should have the same type/radix/value list, and
6176 * just differ in their bit masks. (If a field isn't
6177 * a bitfield, but can be, say, 1 or 2 bytes long,
6178 * it can just be made FT_UINT16, meaning the
6179 * *maximum* length is 2 bytes, and be used
6182 if (hfinfo->same_name_prev_id != -1)
6190 if (hfinfo->strings != NULL) {
6191 if ((hfinfo->display & BASE_DISPLAY_E_MASK) != BASE_CUSTOM &&
6192 (hfinfo->type == FT_UINT8 ||
6193 hfinfo->type == FT_UINT16 ||
6194 hfinfo->type == FT_UINT24 ||
6195 hfinfo->type == FT_UINT32 ||
6196 hfinfo->type == FT_UINT64 ||
6197 hfinfo->type == FT_INT8 ||
6198 hfinfo->type == FT_INT16 ||
6199 hfinfo->type == FT_INT24 ||
6200 hfinfo->type == FT_INT32 ||
6201 hfinfo->type == FT_INT64)) {
6203 if (hfinfo->display & BASE_RANGE_STRING) {
6204 range = (const range_string *)hfinfo->strings;
6205 } else if (hfinfo->display & BASE_EXT_STRING) {
6206 vals = VALUE_STRING_EXT_VS_P((const value_string_ext *)hfinfo->strings);
6207 } else if (hfinfo->display & BASE_VAL64_STRING) {
6208 vals64 = (const val64_string *)hfinfo->strings;
6210 vals = (const value_string *)hfinfo->strings;
6213 else if (hfinfo->type == FT_BOOLEAN) {
6214 tfs = (const struct true_false_string *)hfinfo->strings;
6218 /* Print value strings? */
6220 if (hfinfo->display & BASE_EXT_STRING) {
6221 const value_string_ext *vse_p = (const value_string_ext *)hfinfo->strings;
6222 if (!value_string_ext_validate(vse_p)) {
6223 g_warning("Invalid value_string_ext ptr for: %s", hfinfo->abbrev);
6226 try_val_to_str_ext(0, vse_p); /* "prime" the extended value_string */
6227 printf("E\t%s\t%d\t%s\t%s\n",
6229 VALUE_STRING_EXT_VS_NUM_ENTRIES(vse_p),
6230 VALUE_STRING_EXT_VS_NAME(vse_p),
6231 value_string_ext_match_type_str(vse_p));
6234 while (vals[vi].strptr) {
6235 /* Print in the proper base */
6236 if (hfinfo->display == BASE_HEX) {
6237 printf("V\t%s\t0x%x\t%s\n",
6243 printf("V\t%s\t%u\t%s\n",
6253 while (vals64[vi].strptr) {
6254 printf("V64\t%s\t%" G_GINT64_MODIFIER "u\t%s\n",
6262 /* print range strings? */
6265 while (range[vi].strptr) {
6266 /* Print in the proper base */
6267 if ((hfinfo->display & BASE_DISPLAY_E_MASK) == BASE_HEX) {
6268 printf("R\t%s\t0x%x\t0x%x\t%s\n",
6270 range[vi].value_min,
6271 range[vi].value_max,
6275 printf("R\t%s\t%u\t%u\t%s\n",
6277 range[vi].value_min,
6278 range[vi].value_max,
6285 /* Print true/false strings? */
6287 printf("T\t%s\t%s\t%s\n", hfinfo->abbrev,
6288 tfs->true_string, tfs->false_string);
6294 /* Dumps the contents of the registration database to stdout. An independent
6295 * program can take this output and format it into nice tables or HTML or
6298 * There is one record per line. Each record is either a protocol or a header
6299 * field, differentiated by the first field. The fields are tab-delimited.
6304 * Field 2 = descriptive protocol name
6305 * Field 3 = protocol abbreviation
6310 * Field 2 = descriptive field name
6311 * Field 3 = field abbreviation
6312 * Field 4 = type ( textual representation of the the ftenum type )
6313 * Field 5 = parent protocol abbreviation
6314 * Field 6 = base for display (for integer types); "parent bitfield width" for FT_BOOLEAN
6315 * Field 7 = bitmask: format: hex: 0x....
6316 * Field 8 = blurb describing field
6319 proto_registrar_dump_fields(void)
6321 header_field_info *hfinfo, *parent_hfinfo;
6323 const char *enum_name;
6324 const char *base_name;
6328 len = gpa_hfinfo.len;
6329 for (i = 0; i < len ; i++) {
6330 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
6333 * Skip the pseudo-field for "proto_tree_add_text()" since
6334 * we don't want it in the list of filterable fields.
6336 if (hfinfo->id == hf_text_only)
6339 /* format for protocols */
6340 if (proto_registrar_is_protocol(i)) {
6341 printf("P\t%s\t%s\n", hfinfo->name, hfinfo->abbrev);
6343 /* format for header fields */
6346 * If this field isn't at the head of the list of
6347 * fields with this name, skip this field - all
6348 * fields with the same name are really just versions
6349 * of the same field stored in different bits, and
6350 * should have the same type/radix/value list, and
6351 * just differ in their bit masks. (If a field isn't
6352 * a bitfield, but can be, say, 1 or 2 bytes long,
6353 * it can just be made FT_UINT16, meaning the
6354 * *maximum* length is 2 bytes, and be used
6357 if (hfinfo->same_name_prev_id != -1)
6360 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
6362 enum_name = ftype_name(hfinfo->type);
6365 if (hfinfo->type == FT_UINT8 ||
6366 hfinfo->type == FT_UINT16 ||
6367 hfinfo->type == FT_UINT24 ||
6368 hfinfo->type == FT_UINT32 ||
6369 hfinfo->type == FT_UINT64 ||
6370 hfinfo->type == FT_INT8 ||
6371 hfinfo->type == FT_INT16 ||
6372 hfinfo->type == FT_INT24 ||
6373 hfinfo->type == FT_INT32 ||
6374 hfinfo->type == FT_INT64) {
6376 switch (hfinfo->display & BASE_DISPLAY_E_MASK) {
6378 base_name = "BASE_NONE";
6381 base_name = "BASE_DEC";
6384 base_name = "BASE_HEX";
6387 base_name = "BASE_OCT";
6390 base_name = "BASE_DEC_HEX";
6393 base_name = "BASE_HEX_DEC";
6396 base_name = "BASE_CUSTOM";
6402 } else if (hfinfo->type == FT_BOOLEAN) {
6403 /* For FT_BOOLEAN: 'display' can be "parent bitfield width" */
6404 g_snprintf(width, sizeof(width), "%d", hfinfo->display);
6408 blurb = hfinfo->blurb;
6411 else if (strlen(blurb) == 0)
6414 printf("F\t%s\t%s\t%s\t%s\t%s\t0x%x\t%s\n",
6415 hfinfo->name, hfinfo->abbrev, enum_name,
6416 parent_hfinfo->abbrev, base_name, hfinfo->bitmask, blurb);
6421 /* Dumps field types and descriptive names to stdout. An independent
6422 * program can take this output and format it into nice tables or HTML or
6425 * There is one record per line. The fields are tab-delimited.
6427 * Field 1 = field type name, e.g. FT_UINT8
6428 * Field 2 = descriptive name, e.g. "Unsigned, 1 byte"
6431 proto_registrar_dump_ftypes(void)
6435 for (fte = 0; fte < FT_NUM_TYPES; fte++) {
6436 printf("%s\t%s\n", ftype_name((ftenum_t)fte), ftype_pretty_name((ftenum_t)fte));
6441 hfinfo_numeric_format(const header_field_info *hfinfo)
6443 const char *format = NULL;
6445 /* Get the underlying BASE_ value */
6446 switch (hfinfo->display & BASE_DISPLAY_E_MASK) {
6449 case BASE_OCT: /* I'm lazy */
6451 switch (hfinfo->type) {
6453 format = "%s == %" G_GINT64_MODIFIER "u";
6456 format = "%s == %" G_GINT64_MODIFIER "d";
6459 DISSECTOR_ASSERT_NOT_REACHED();
6465 switch (hfinfo->type) {
6468 format = "%s == 0x%016" G_GINT64_MODIFIER "x";
6471 DISSECTOR_ASSERT_NOT_REACHED();
6476 DISSECTOR_ASSERT_NOT_REACHED();
6482 /* This function indicates whether it's possible to construct a
6483 * "match selected" display filter string for the specified field,
6484 * returns an indication of whether it's possible, and, if it's
6485 * possible and "filter" is non-null, constructs the filter and
6486 * sets "*filter" to point to it.
6487 * You do not need to [g_]free() this string since it will be automatically
6488 * freed once the next packet is dissected.
6491 construct_match_selected_string(field_info *finfo, epan_dissect_t *edt,
6494 header_field_info *hfinfo;
6499 gint start, length, length_remaining;
6501 gchar is_signed_num = FALSE;
6506 hfinfo = finfo->hfinfo;
6507 DISSECTOR_ASSERT(hfinfo);
6508 abbrev_len = (int) strlen(hfinfo->abbrev);
6510 if (hfinfo->strings && (hfinfo->display & BASE_DISPLAY_E_MASK) == BASE_NONE) {
6511 const gchar *str = NULL;
6513 switch (hfinfo->type) {
6519 str = hf_try_val_to_str(fvalue_get_sinteger(&finfo->value), hfinfo);
6526 str = hf_try_val_to_str(fvalue_get_uinteger(&finfo->value), hfinfo);
6533 if (str != NULL && filter != NULL) {
6534 *filter = ep_strdup_printf("%s == \"%s\"", hfinfo->abbrev, str);
6540 * XXX - we can't use the "val_to_string_repr" and "string_repr_len"
6541 * functions for FT_UINT and FT_INT types, as we choose the base in
6542 * the string expression based on the display base of the field.
6544 * Note that the base does matter, as this is also used for
6545 * the protocolinfo tap.
6547 * It might be nice to use them in "proto_item_fill_label()"
6548 * as well, although, there, you'd have to deal with the base
6549 * *and* with resolved values for addresses.
6551 * Perhaps we need two different val_to_string routines, one
6552 * to generate items for display filters and one to generate
6553 * strings for display, and pass to both of them the
6554 * "display" and "strings" values in the header_field_info
6555 * structure for the field, so they can get the base and,
6556 * if the field is Boolean or an enumerated integer type,
6557 * the tables used to generate human-readable values.
6559 switch (hfinfo->type) {
6565 is_signed_num = TRUE;
6572 if (filter != NULL) {
6579 number = fvalue_get_sinteger(&finfo->value);
6581 number = fvalue_get_uinteger(&finfo->value);
6583 out = hfinfo_numeric_value_format(hfinfo, buf, number);
6585 *filter = ep_strdup_printf("%s == %s", hfinfo->abbrev, out);
6591 if (filter != NULL) {
6592 const char *format = hfinfo_numeric_format(hfinfo);
6594 *filter = ep_strdup_printf(format,
6596 fvalue_get_integer64(&finfo->value));
6602 *filter = ep_strdup(finfo->hfinfo->abbrev);
6607 * If the length is 0, just match the name of the
6610 * (Also check for negative values, just in case,
6611 * as we'll cast it to an unsigned value later.)
6613 length = finfo->length;
6616 *filter = ep_strdup(finfo->hfinfo->abbrev);
6623 * This doesn't have a value, so we'd match
6624 * on the raw bytes at this address.
6626 * Should we be allowed to access to the raw bytes?
6627 * If "edt" is NULL, the answer is "no".
6633 * Is this field part of the raw frame tvbuff?
6634 * If not, we can't use "frame[N:M]" to match
6637 * XXX - should this be frame-relative, or
6638 * protocol-relative?
6640 * XXX - does this fallback for non-registered
6641 * fields even make sense?
6643 if (finfo->ds_tvb != edt->tvb)
6644 return FALSE; /* you lose */
6647 * Don't go past the end of that tvbuff.
6649 length_remaining = tvb_length_remaining(finfo->ds_tvb, finfo->start);
6650 if (length > length_remaining)
6651 length = length_remaining;
6655 if (filter != NULL) {
6656 start = finfo->start;
6657 buf_len = 32 + length * 3;
6658 *filter = (char *)ep_alloc0(buf_len);
6661 ptr += g_snprintf(ptr, (gulong) (buf_len-(ptr-*filter)),
6662 "frame[%d:%d] == ", finfo->start, length);
6663 for (i=0; i<length; i++) {
6664 c = tvb_get_guint8(finfo->ds_tvb, start);
6667 ptr += g_snprintf(ptr, (gulong) (buf_len-(ptr-*filter)), "%02x", c);
6670 ptr += g_snprintf(ptr, (gulong) (buf_len-(ptr-*filter)), ":%02x", c);
6677 /* FT_PCRE never appears as a type for a registered field. It is
6678 * only used internally. */
6679 DISSECTOR_ASSERT_NOT_REACHED();
6682 /* By default, use the fvalue's "to_string_repr" method. */
6684 /* Figure out the string length needed.
6685 * The ft_repr length.
6686 * 4 bytes for " == ".
6687 * 1 byte for trailing NUL.
6689 if (filter != NULL) {
6690 dfilter_len = fvalue_string_repr_len(&finfo->value,
6692 dfilter_len += abbrev_len + 4 + 1;
6693 *filter = (char *)ep_alloc0(dfilter_len);
6695 /* Create the string */
6696 g_snprintf(*filter, dfilter_len, "%s == ",
6698 fvalue_to_string_repr(&finfo->value,
6700 &(*filter)[abbrev_len + 4]);
6709 * Returns TRUE if we can do a "match selected" on the field, FALSE
6713 proto_can_match_selected(field_info *finfo, epan_dissect_t *edt)
6715 return construct_match_selected_string(finfo, edt, NULL);
6718 /* This function attempts to construct a "match selected" display filter
6719 * string for the specified field; if it can do so, it returns a pointer
6720 * to the string, otherwise it returns NULL.
6722 * The string is allocated with packet lifetime scope.
6723 * You do not need to [g_]free() this string since it will be automatically
6724 * freed once the next packet is dissected.
6727 proto_construct_match_selected_string(field_info *finfo, epan_dissect_t *edt)
6731 if (!construct_match_selected_string(finfo, edt, &filter))
6736 /* This function is common code for both proto_tree_add_bitmask() and
6737 * proto_tree_add_bitmask_text() functions.
6740 /* NOTE: to support code written when proto_tree_add_bitmask() and
6741 * proto_tree_add_bitmask_text took a
6742 * gboolean as its last argument, with FALSE meaning "big-endian"
6743 * and TRUE meaning "little-endian", we treat any non-zero value of
6744 * "encoding" as meaning "little-endian".
6747 proto_item_add_bitmask_tree(proto_item *item, tvbuff_t *tvb, const int offset,
6748 const int len, const gint ett, const int **fields,
6749 const guint encoding, const int flags,
6753 guint32 available_bits = 0;
6755 proto_tree *tree = NULL;
6756 header_field_info *hf;
6760 value = tvb_get_guint8(tvb, offset);
6761 available_bits = 0xFF;
6764 value = encoding ? tvb_get_letohs(tvb, offset) :
6765 tvb_get_ntohs(tvb, offset);
6766 available_bits = 0xFFFF;
6769 value = encoding ? tvb_get_letoh24(tvb, offset) :
6770 tvb_get_ntoh24(tvb, offset);
6771 available_bits = 0xFFFFFF;
6774 value = encoding ? tvb_get_letohl(tvb, offset) :
6775 tvb_get_ntohl(tvb, offset);
6776 available_bits = 0xFFFFFFFF;
6779 g_assert_not_reached();
6782 tree = proto_item_add_subtree(item, ett);
6784 guint32 present_bits;
6785 hf = proto_registrar_get_nth(**fields);
6786 DISSECTOR_ASSERT(hf->bitmask != 0);
6788 /* Skip fields that aren't fully present */
6789 present_bits = available_bits & hf->bitmask;
6790 if (present_bits != hf->bitmask) {
6795 proto_tree_add_item(tree, **fields, tvb, offset, len, encoding);
6796 if (flags & BMT_NO_APPEND) {
6800 tmpval = (value & hf->bitmask) >> hfinfo_bitshift(hf);
6811 if (hf->display == BASE_CUSTOM) {
6812 gchar lbl[ITEM_LABEL_LENGTH];
6813 const custom_fmt_func_t fmtfunc = (const custom_fmt_func_t)hf->strings;
6815 DISSECTOR_ASSERT(fmtfunc);
6816 fmtfunc(lbl, tmpval);
6817 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
6821 else if (hf->strings) {
6822 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
6823 hf->name, hf_try_val_to_str_const(tmpval, hf, "Unknown"));
6826 else if (!(flags & BMT_NO_INT)) {
6831 proto_item_append_text(item, ", ");
6834 out = hfinfo_number_value_format(hf, buf, tmpval);
6835 proto_item_append_text(item, "%s: %s", hf->name, out);
6841 if (hf->strings && !(flags & BMT_NO_TFS)) {
6842 /* If we have true/false strings, emit full - otherwise messages
6844 const struct true_false_string *tfs =
6845 (const struct true_false_string *)hf->strings;
6848 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
6849 hf->name, tfs->true_string);
6851 } else if (!(flags & BMT_NO_FALSE)) {
6852 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
6853 hf->name, tfs->false_string);
6856 } else if (hf->bitmask & value) {
6857 /* If the flag is set, show the name */
6858 proto_item_append_text(item, "%s%s", first ? "" : ", ", hf->name);
6863 g_assert_not_reached();
6872 /* This function will dissect a sequence of bytes that describe a
6874 * hf_hdr is a 8/16/24/32 bit integer that describes the bitmask to be dissected.
6875 * This field will form an expansion under which the individual fields of the
6876 * bitmask is dissected and displayed.
6877 * This field must be of the type FT_[U]INT{8|16|24|32}.
6879 * fields is an array of pointers to int that lists all the fields of the
6880 * bitmask. These fields can be either of the type FT_BOOLEAN for flags
6881 * or another integer of the same type/size as hf_hdr with a mask specified.
6882 * This array is terminated by a NULL entry.
6884 * FT_BOOLEAN bits that are set to 1 will have the name added to the expansion.
6885 * FT_integer fields that have a value_string attached will have the
6886 * matched string displayed on the expansion line.
6889 proto_tree_add_bitmask(proto_tree *parent_tree, tvbuff_t *tvb,
6890 const guint offset, const int hf_hdr,
6891 const gint ett, const int **fields,
6892 const guint encoding)
6894 proto_item *item = NULL;
6895 header_field_info *hf;
6898 hf = proto_registrar_get_nth(hf_hdr);
6899 DISSECTOR_ASSERT(IS_FT_INT(hf->type) || IS_FT_UINT(hf->type));
6900 len = ftype_length(hf->type);
6903 item = proto_tree_add_item(parent_tree, hf_hdr, tvb, offset, len, encoding);
6904 proto_item_add_bitmask_tree(item, tvb, offset, len, ett, fields, encoding,
6905 BMT_NO_INT|BMT_NO_TFS, FALSE);
6911 /* The same as proto_tree_add_bitmask(), but using a caller-supplied length.
6912 * This is intended to support bitmask fields whose lengths can vary, perhaps
6913 * as the underlying standard evolves over time.
6914 * With this API there is the possibility of being called to display more or
6915 * less data than the dissector was coded to support.
6916 * In such cases, it is assumed that bitmasks are extended on the MSb end.
6917 * Thus when presented with "too much" or "too little" data, MSbits will be
6918 * ignored or MSfields sacrificed.
6920 * Only fields for which all defined bits are available are displayed.
6923 proto_tree_add_bitmask_len(proto_tree *parent_tree, tvbuff_t *tvb,
6924 const guint offset, const guint len, const int hf_hdr,
6925 const gint ett, const int **fields, struct expert_field* exp,
6926 const guint encoding)
6928 proto_item *item = NULL;
6929 header_field_info *hf;
6930 guint decodable_len;
6931 guint decodable_offset;
6932 guint32 decodable_value;
6934 hf = proto_registrar_get_nth(hf_hdr);
6935 DISSECTOR_ASSERT(IS_FT_INT(hf->type) || IS_FT_UINT(hf->type));
6937 decodable_offset = offset;
6938 decodable_len = MIN(len, (guint) ftype_length(hf->type));
6940 /* If we are ftype_length-limited,
6941 * make sure we decode as many LSBs as possible.
6943 if (encoding == ENC_BIG_ENDIAN) {
6944 decodable_offset += (len - decodable_len);
6948 decodable_value = get_uint_value(parent_tree, tvb, decodable_offset,
6949 decodable_len, encoding);
6951 /* The root item covers all the bytes even if we can't decode them all */
6952 item = proto_tree_add_uint(parent_tree, hf_hdr, tvb, offset, len,
6956 if (decodable_len < len) {
6957 /* Dissector likely requires updating for new protocol revision */
6958 expert_add_info_format(NULL, item, exp,
6959 "Only least-significant %d of %d bytes decoded",
6960 decodable_len, len);
6964 proto_item_add_bitmask_tree(item, tvb, decodable_offset, decodable_len,
6965 ett, fields, encoding, BMT_NO_INT|BMT_NO_TFS, FALSE);
6971 /* The same as proto_tree_add_bitmask(), but using an arbitrary text as a top-level item */
6973 proto_tree_add_bitmask_text(proto_tree *parent_tree, tvbuff_t *tvb,
6974 const guint offset, const guint len,
6975 const char *name, const char *fallback,
6976 const gint ett, const int **fields,
6977 const guint encoding, const int flags)
6979 proto_item *item = NULL;
6982 item = proto_tree_add_text(parent_tree, tvb, offset, len, "%s", name ? name : "");
6983 if (proto_item_add_bitmask_tree(item, tvb, offset, len, ett, fields, encoding,
6984 flags, TRUE) && fallback) {
6985 /* Still at first item - append 'fallback' text if any */
6986 proto_item_append_text(item, "%s", fallback);
6994 proto_tree_add_bits_item(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
6995 const guint bit_offset, const gint no_of_bits,
6996 const guint encoding)
6998 header_field_info *hfinfo;
7002 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
7004 octet_length = (no_of_bits + 7) >> 3;
7005 octet_offset = bit_offset >> 3;
7006 test_length(hfinfo, tree, tvb, octet_offset, octet_length, encoding);
7008 /* Yes, we try to fake this item again in proto_tree_add_bits_ret_val()
7009 * but only after doing a bunch more work (which we can, in the common
7010 * case, shortcut here).
7012 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
7014 return proto_tree_add_bits_ret_val(tree, hfindex, tvb, bit_offset, no_of_bits, NULL, encoding);
7018 * This function will dissect a sequence of bits that does not need to be byte aligned; the bits
7019 * set will be shown in the tree as ..10 10.. and the integer value returned if return_value is set.
7020 * Offset should be given in bits from the start of the tvb.
7024 _proto_tree_add_bits_ret_val(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
7025 const guint bit_offset, const gint no_of_bits,
7026 guint64 *return_value, const guint encoding)
7032 char lbl_str[ITEM_LABEL_LENGTH];
7036 header_field_info *hf_field;
7038 const true_false_string *tfstring;
7040 /* We can't fake it just yet. We have to fill in the 'return_value' parameter */
7041 PROTO_REGISTRAR_GET_NTH(hfindex, hf_field);
7043 if (hf_field->bitmask != 0) {
7044 REPORT_DISSECTOR_BUG(ep_strdup_printf("Incompatible use of proto_tree_add_bits_ret_val"
7045 " with field '%s' (%s) with bitmask != 0",
7046 hf_field->abbrev, hf_field->name));
7049 DISSECTOR_ASSERT(no_of_bits > 0);
7051 /* Byte align offset */
7052 offset = bit_offset>>3;
7055 * Calculate the number of octets used to hold the bits
7057 tot_no_bits = ((bit_offset&0x7) + no_of_bits);
7058 length = (tot_no_bits + 7) >> 3;
7060 if (no_of_bits < 65) {
7061 value = tvb_get_bits64(tvb, bit_offset, no_of_bits, encoding);
7063 DISSECTOR_ASSERT_NOT_REACHED();
7067 /* Sign extend for signed types */
7068 switch (hf_field->type) {
7074 if (value & (G_GINT64_CONSTANT(1) << (no_of_bits-1)))
7075 value |= (G_GINT64_CONSTANT(-1) << no_of_bits);
7083 *return_value = value;
7086 /* Coast clear. Try and fake it */
7087 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
7089 bf_str = decode_bits_in_field(bit_offset, no_of_bits, value);
7091 switch (hf_field->type) {
7094 tfstring = (const true_false_string *) &tfs_true_false;
7095 if (hf_field->strings)
7096 tfstring = (const true_false_string *)hf_field->strings;
7097 return proto_tree_add_boolean_format(tree, hfindex, tvb, offset, length, (guint32)value,
7099 bf_str, hf_field->name,
7100 (guint32)value ? tfstring->true_string : tfstring->false_string);
7107 pi = proto_tree_add_uint(tree, hfindex, tvb, offset, length, (guint32)value);
7108 fill_label_number(PITEM_FINFO(pi), lbl_str, FALSE);
7115 pi = proto_tree_add_int(tree, hfindex, tvb, offset, length, (gint32)value);
7116 fill_label_number(PITEM_FINFO(pi), lbl_str, TRUE);
7120 pi = proto_tree_add_uint64(tree, hfindex, tvb, offset, length, value);
7121 fill_label_number64(PITEM_FINFO(pi), lbl_str, FALSE);
7125 pi = proto_tree_add_int64(tree, hfindex, tvb, offset, length, (gint64)value);
7126 fill_label_number64(PITEM_FINFO(pi), lbl_str, TRUE);
7130 DISSECTOR_ASSERT_NOT_REACHED();
7135 proto_item_set_text(pi, "%s = %s", bf_str, lbl_str);
7140 proto_tree_add_split_bits_item_ret_val(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
7141 const guint bit_offset, const crumb_spec_t *crumb_spec,
7142 guint64 *return_value)
7147 guint mask_initial_bit_offset;
7148 guint mask_greatest_bit_offset;
7152 char lbl_str[ITEM_LABEL_LENGTH];
7154 guint64 composite_bitmask;
7155 guint64 composite_bitmap;
7157 header_field_info *hf_field;
7158 const true_false_string *tfstring;
7160 /* We can't fake it just yet. We have to fill in the 'return_value' parameter */
7161 PROTO_REGISTRAR_GET_NTH(hfindex, hf_field);
7163 if (hf_field->bitmask != 0) {
7164 REPORT_DISSECTOR_BUG(ep_strdup_printf(
7165 "Incompatible use of proto_tree_add_split_bits_item_ret_val"
7166 " with field '%s' (%s) with bitmask != 0",
7167 hf_field->abbrev, hf_field->name));
7170 mask_initial_bit_offset = bit_offset % 8;
7175 mask_greatest_bit_offset = 0;
7176 composite_bitmask = 0;
7177 composite_bitmap = 0;
7179 while (crumb_spec[i].crumb_bit_length != 0) {
7180 guint64 crumb_mask, crumb_value;
7181 guint8 crumb_end_bit_offset;
7183 DISSECTOR_ASSERT(i < 64);
7184 crumb_value = tvb_get_bits64(tvb,
7185 bit_offset + crumb_spec[i].crumb_bit_offset,
7186 crumb_spec[i].crumb_bit_length,
7188 value += crumb_value;
7189 no_of_bits += crumb_spec[i].crumb_bit_length;
7191 /* The bitmask is 64 bit, left-aligned, starting at the first bit of the
7192 octet containing the initial offset.
7193 If the mask is beyond 32 bits, then give up on bit map display.
7194 This could be improved in future, probably showing a table
7195 of 32 or 64 bits per row */
7196 if (mask_greatest_bit_offset < 32) {
7197 crumb_end_bit_offset = mask_initial_bit_offset
7198 + crumb_spec[i].crumb_bit_offset
7199 + crumb_spec[i].crumb_bit_length;
7200 crumb_mask = (G_GUINT64_CONSTANT(1) << crumb_spec[i].crumb_bit_length) - 1;
7202 if (crumb_end_bit_offset > mask_greatest_bit_offset) {
7203 mask_greatest_bit_offset = crumb_end_bit_offset;
7205 composite_bitmask |= (crumb_mask << (64 - crumb_end_bit_offset));
7206 composite_bitmap |= (crumb_value << (64 - crumb_end_bit_offset));
7208 /* Shift left for the next segment */
7209 value <<= crumb_spec[++i].crumb_bit_length;
7212 /* Sign extend for signed types */
7213 switch (hf_field->type) {
7219 if (no_of_bits && (value & (G_GINT64_CONSTANT(1) << (no_of_bits-1))))
7220 value |= (G_GINT64_CONSTANT(-1) << no_of_bits);
7227 *return_value = value;
7230 /* Coast clear. Try and fake it */
7231 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
7233 /* initialise the format string */
7234 bf_str = (char *)ep_alloc(256);
7237 octet_offset = bit_offset >> 3;
7239 /* Round up mask length to nearest octet */
7240 octet_length = ((mask_greatest_bit_offset + 7) >> 3);
7241 mask_greatest_bit_offset = octet_length << 3;
7243 /* As noted above, we currently only produce a bitmap if the crumbs span less than 4 octets of the tvb.
7244 It would be a useful enhancement to eliminate this restriction. */
7245 if (mask_greatest_bit_offset <= 32) {
7246 other_decode_bitfield_value(bf_str,
7247 (guint32)(composite_bitmap >> (64 - mask_greatest_bit_offset)),
7248 (guint32)(composite_bitmask >> (64 - mask_greatest_bit_offset)),
7249 mask_greatest_bit_offset);
7252 switch (hf_field->type) {
7253 case FT_BOOLEAN: /* it is a bit odd to have a boolean encoded as split-bits, but possible, I suppose? */
7255 tfstring = (const true_false_string *) &tfs_true_false;
7256 if (hf_field->strings)
7257 tfstring = (const true_false_string *) hf_field->strings;
7258 return proto_tree_add_boolean_format(tree, hfindex,
7259 tvb, octet_offset, octet_length, (guint32)value,
7261 bf_str, hf_field->name,
7262 (guint32)value ? tfstring->true_string : tfstring->false_string);
7269 pi = proto_tree_add_uint(tree, hfindex, tvb, octet_offset, octet_length, (guint32)value);
7270 fill_label_number(PITEM_FINFO(pi), lbl_str, FALSE);
7277 pi = proto_tree_add_int(tree, hfindex, tvb, octet_offset, octet_length, (gint32)value);
7278 fill_label_number(PITEM_FINFO(pi), lbl_str, TRUE);
7282 pi = proto_tree_add_uint64(tree, hfindex, tvb, octet_offset, octet_length, value);
7283 fill_label_number64(PITEM_FINFO(pi), lbl_str, FALSE);
7287 pi = proto_tree_add_int64(tree, hfindex, tvb, octet_offset, octet_length, (gint64)value);
7288 fill_label_number64(PITEM_FINFO(pi), lbl_str, TRUE);
7292 DISSECTOR_ASSERT_NOT_REACHED();
7296 proto_item_set_text(pi, "%s = %s", bf_str, lbl_str);
7301 proto_tree_add_split_bits_crumb(proto_tree *tree, const int hfindex, tvbuff_t *tvb, const guint bit_offset,
7302 const crumb_spec_t *crumb_spec, guint16 crumb_index)
7304 header_field_info *hfinfo;
7306 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
7307 proto_tree_add_text(tree, tvb,
7309 ((bit_offset + crumb_spec[crumb_index].crumb_bit_length - 1) >> 3) - (bit_offset >> 3) + 1,
7310 "%s crumb %d of %s (decoded above)",
7311 decode_bits_in_field(bit_offset, crumb_spec[crumb_index].crumb_bit_length,
7314 crumb_spec[crumb_index].crumb_bit_length,
7321 proto_tree_add_bits_ret_val(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
7322 const guint bit_offset, const gint no_of_bits,
7323 guint64 *return_value, const guint encoding)
7327 if ((item = _proto_tree_add_bits_ret_val(tree, hfindex, tvb,
7328 bit_offset, no_of_bits,
7329 return_value, encoding))) {
7330 FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_OFFSET(bit_offset));
7331 FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_SIZE(no_of_bits));
7337 _proto_tree_add_bits_format_value(proto_tree *tree, const int hfindex,
7338 tvbuff_t *tvb, const guint bit_offset,
7339 const gint no_of_bits, void *value_ptr,
7347 header_field_info *hf_field;
7349 /* We do not have to return a value, try to fake it as soon as possible */
7350 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
7352 if (hf_field->bitmask != 0) {
7353 REPORT_DISSECTOR_BUG(ep_strdup_printf(
7354 "Incompatible use of proto_tree_add_bits_format_value"
7355 " with field '%s' (%s) with bitmask != 0",
7356 hf_field->abbrev, hf_field->name));
7359 DISSECTOR_ASSERT(no_of_bits > 0);
7361 /* Byte align offset */
7362 offset = bit_offset>>3;
7365 * Calculate the number of octets used to hold the bits
7367 tot_no_bits = ((bit_offset&0x7) + no_of_bits);
7368 length = tot_no_bits>>3;
7369 /* If we are using part of the next octet, increase length by 1 */
7370 if (tot_no_bits & 0x07)
7373 if (no_of_bits < 65) {
7374 value = tvb_get_bits64(tvb, bit_offset, no_of_bits, ENC_BIG_ENDIAN);
7376 DISSECTOR_ASSERT_NOT_REACHED();
7380 str = decode_bits_in_field(bit_offset, no_of_bits, value);
7383 strcat(str, hf_field->name);
7386 * This function does not receive an actual value but a dimensionless pointer to that value.
7387 * For this reason, the type of the header field is examined in order to determine
7388 * what kind of value we should read from this address.
7389 * The caller of this function must make sure that for the specific header field type the address of
7390 * a compatible value is provided.
7392 switch (hf_field->type) {
7394 return proto_tree_add_boolean_format(tree, hfindex, tvb, offset, length, *(guint32 *)value_ptr,
7395 "%s: %s", str, value_str);
7402 return proto_tree_add_uint_format(tree, hfindex, tvb, offset, length, *(guint32 *)value_ptr,
7403 "%s: %s", str, value_str);
7407 return proto_tree_add_uint64_format(tree, hfindex, tvb, offset, length, *(guint64 *)value_ptr,
7408 "%s: %s", str, value_str);
7415 return proto_tree_add_int_format(tree, hfindex, tvb, offset, length, *(gint32 *)value_ptr,
7416 "%s: %s", str, value_str);
7420 return proto_tree_add_int64_format(tree, hfindex, tvb, offset, length, *(gint64 *)value_ptr,
7421 "%s: %s", str, value_str);
7425 return proto_tree_add_float_format(tree, hfindex, tvb, offset, length, *(float *)value_ptr,
7426 "%s: %s", str, value_str);
7430 DISSECTOR_ASSERT_NOT_REACHED();
7437 proto_tree_add_bits_format_value(proto_tree *tree, const int hfindex,
7438 tvbuff_t *tvb, const guint bit_offset,
7439 const gint no_of_bits, void *value_ptr,
7444 if ((item = _proto_tree_add_bits_format_value(tree, hfindex,
7445 tvb, bit_offset, no_of_bits,
7446 value_ptr, value_str))) {
7447 FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_OFFSET(bit_offset));
7448 FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_SIZE(no_of_bits));
7453 #define CREATE_VALUE_STRING(dst,format,ap) \
7454 va_start(ap, format); \
7455 dst = ep_strdup_vprintf(format, ap); \
7459 proto_tree_add_uint_bits_format_value(proto_tree *tree, const int hfindex,
7460 tvbuff_t *tvb, const guint bit_offset,
7461 const gint no_of_bits, guint32 value,
7462 const char *format, ...)
7466 header_field_info *hf_field;
7468 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
7470 switch (hf_field->type) {
7478 DISSECTOR_ASSERT_NOT_REACHED();
7483 CREATE_VALUE_STRING(dst, format, ap);
7485 return proto_tree_add_bits_format_value(tree, hfindex, tvb, bit_offset, no_of_bits, &value, dst);
7489 proto_tree_add_float_bits_format_value(proto_tree *tree, const int hfindex,
7490 tvbuff_t *tvb, const guint bit_offset,
7491 const gint no_of_bits, float value,
7492 const char *format, ...)
7496 header_field_info *hf_field;
7498 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
7500 DISSECTOR_ASSERT(hf_field->type == FT_FLOAT);
7502 CREATE_VALUE_STRING(dst, format, ap);
7504 return proto_tree_add_bits_format_value(tree, hfindex, tvb, bit_offset, no_of_bits, &value, dst);
7508 proto_tree_add_int_bits_format_value(proto_tree *tree, const int hfindex,
7509 tvbuff_t *tvb, const guint bit_offset,
7510 const gint no_of_bits, gint32 value,
7511 const char *format, ...)
7515 header_field_info *hf_field;
7517 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
7519 switch (hf_field->type) {
7527 DISSECTOR_ASSERT_NOT_REACHED();
7532 CREATE_VALUE_STRING(dst, format, ap);
7534 return proto_tree_add_bits_format_value(tree, hfindex, tvb, bit_offset, no_of_bits, &value, dst);
7538 proto_tree_add_boolean_bits_format_value(proto_tree *tree, const int hfindex,
7539 tvbuff_t *tvb, const guint bit_offset,
7540 const gint no_of_bits, guint32 value,
7541 const char *format, ...)
7545 header_field_info *hf_field;
7547 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
7549 DISSECTOR_ASSERT(hf_field->type == FT_BOOLEAN);
7551 CREATE_VALUE_STRING(dst, format, ap);
7553 return proto_tree_add_bits_format_value(tree, hfindex, tvb, bit_offset, no_of_bits, &value, dst);
7557 proto_check_field_name(const gchar *field_name)
7559 return wrs_check_charset(fld_abbrev_chars, field_name);
7563 tree_expanded(int tree_type)
7565 g_assert(tree_type >= 0 && tree_type < num_tree_types);
7566 return tree_is_expanded[tree_type >> 5] & (1 << (tree_type & 31));
7570 tree_expanded_set(int tree_type, gboolean value)
7572 g_assert(tree_type >= 0 && tree_type < num_tree_types);
7575 tree_is_expanded[tree_type >> 5] |= (1 << (tree_type & 31));
7577 tree_is_expanded[tree_type >> 5] &= ~(1 << (tree_type & 31));
7581 * Editor modelines - http://www.wireshark.org/tools/modelines.html
7586 * indent-tabs-mode: t
7589 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
7590 * :indentSize=8:tabSize=8:noTabs=false: