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.
34 #include "ptvcursor.h"
36 #include "addr_resolv.h"
40 #include "epan_dissect.h"
45 #include "asm_utils.h"
46 #include "column-utils.h"
50 #include "wspython/wspy_register.h"
52 #define SUBTREE_ONCE_ALLOCATION_NUMBER 8
53 #define SUBTREE_MAX_LEVELS 256
54 /* Throw an exception if we exceed this many tree items. */
55 /* XXX - This should probably be a preference */
56 #define MAX_TREE_ITEMS (1 * 1000 * 1000)
59 typedef struct __subtree_lvl {
66 subtree_lvl *pushed_tree;
67 guint8 pushed_tree_index;
68 guint8 pushed_tree_max;
74 /* Candidates for assembler */
76 wrs_count_bitshift(const guint32 bitmask)
80 while ((bitmask & (1 << bitshift)) == 0)
85 #define cVALS(x) (const value_string*)(x)
87 /** See inlined comments.
88 @param tree the tree to append this item to
89 @param hfindex field index
90 @param hfinfo header_field
91 @return the header field matching 'hfinfo' */
92 #define TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo) \
93 /* If this item is not referenced we dont have to do much work \
94 at all but we should still return a node so that field items \
95 below this node (think proto_item_add_subtree()) will still \
96 have somewhere to attach to or else filtering will not work \
97 (they would be ignored since tree would be NULL). \
98 DONT try to fake a node where PTREE_FINFO(tree) is NULL \
99 since dissectors that want to do proto_item_set_len() or \
100 other operations that dereference this would crash. \
101 We fake FT_PROTOCOL unless some clients have requested us \
106 PTREE_DATA(tree)->count++; \
107 if (PTREE_DATA(tree)->count > MAX_TREE_ITEMS) { \
108 if (getenv("WIRESHARK_ABORT_ON_DISSECTOR_BUG") != NULL) \
110 /* Let the exception handler add items to the tree */ \
111 PTREE_DATA(tree)->count = 0; \
112 THROW_MESSAGE(DissectorError, \
113 ep_strdup_printf("More than %d items in the tree -- possible infinite loop", MAX_TREE_ITEMS)); \
115 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo); \
116 if (!(PTREE_DATA(tree)->visible)) { \
117 if (PTREE_FINFO(tree)) { \
118 if ((hfinfo->ref_type != HF_REF_TYPE_DIRECT) \
119 && (hfinfo->type != FT_PROTOCOL || \
120 PTREE_DATA(tree)->fake_protocols)) { \
121 /* just return tree back to the caller */\
127 /** See inlined comments.
128 @param tree the tree to append this item to
129 @param pi the created protocol item we're about to return */
130 #define TRY_TO_FAKE_THIS_REPR(tree, pi) \
133 if (!(PTREE_DATA(tree)->visible)) { \
134 /* If the tree (GUI) isn't visible it's pointless for us to generate the protocol \
135 * items string representation */ \
139 static void fill_label_boolean(field_info *fi, gchar *label_str);
140 static void fill_label_uint(field_info *fi, gchar *label_str);
141 static void fill_label_uint64(field_info *fi, gchar *label_str);
142 static void fill_label_bitfield(field_info *fi, gchar *label_str);
143 static void fill_label_int(field_info *fi, gchar *label_str);
144 static void fill_label_int64(field_info *fi, gchar *label_str);
146 static const char* hfinfo_uint_vals_format(const header_field_info *hfinfo);
147 static const char* hfinfo_uint_format(const header_field_info *hfinfo);
148 static const char* hfinfo_uint_value_format(const header_field_info *hfinfo);
149 static const char* hfinfo_uint64_format(const header_field_info *hfinfo);
150 static const char* hfinfo_int_vals_format(const header_field_info *hfinfo);
151 static const char* hfinfo_int_format(const header_field_info *hfinfo);
152 static const char* hfinfo_int_value_format(const header_field_info *hfinfo);
153 static const char* hfinfo_int64_format(const header_field_info *hfinfo);
154 static const char* hfinfo_numeric_value_format(const header_field_info *hfinfo);
157 proto_tree_add_node(proto_tree *tree, field_info *fi);
159 static header_field_info *
160 get_hfi_and_length(int hfindex, tvbuff_t *tvb, const gint start, gint *length,
164 new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
165 const gint start, const gint item_length);
168 alloc_field_info(proto_tree *tree, int hfindex, tvbuff_t *tvb,
169 const gint start, gint *length);
172 proto_tree_add_pi(proto_tree *tree, int hfindex, tvbuff_t *tvb,
173 gint start, gint *length, field_info **pfi);
176 proto_tree_set_representation_value(proto_item *pi, const char *format, va_list ap);
178 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap);
181 proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb);
183 proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length);
185 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length);
187 proto_tree_set_time(field_info *fi, nstime_t *value_ptr);
189 proto_tree_set_string(field_info *fi, const char* value);
191 proto_tree_set_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length, gint encoding);
193 proto_tree_set_ax25(field_info *fi, const guint8* value);
195 proto_tree_set_ax25_tvb(field_info *fi, tvbuff_t *tvb, gint start);
197 proto_tree_set_ether(field_info *fi, const guint8* value);
199 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start);
201 proto_tree_set_ipxnet(field_info *fi, guint32 value);
203 proto_tree_set_ipv4(field_info *fi, guint32 value);
205 proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr);
207 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
209 proto_tree_set_guid(field_info *fi, const e_guid_t *value_ptr);
211 proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, gint start, const guint encoding);
213 proto_tree_set_oid(field_info *fi, const guint8* value_ptr, gint length);
215 proto_tree_set_oid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
217 proto_tree_set_boolean(field_info *fi, guint32 value);
219 proto_tree_set_float(field_info *fi, float value);
221 proto_tree_set_double(field_info *fi, double value);
223 proto_tree_set_uint(field_info *fi, guint32 value);
225 proto_tree_set_int(field_info *fi, gint32 value);
227 proto_tree_set_uint64(field_info *fi, guint64 value);
229 proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start, guint length, const guint encoding);
231 proto_tree_set_eui64(field_info *fi, const guint64 value);
233 proto_tree_set_eui64_tvb(field_info *fi, tvbuff_t *tvb, gint start, const guint encoding);
235 proto_item_add_bitmask_tree(proto_item *item, tvbuff_t *tvb, const int offset,
236 const int len, const gint ett, const gint **fields,
237 const guint encoding, const int flags,
240 static int proto_register_field_init(header_field_info *hfinfo, const int parent);
242 /* special-case header field used within proto.c */
243 int hf_text_only = -1;
245 /* Structure for information about a protocol */
247 const char *name; /* long description */
248 const char *short_name; /* short description */
249 const char *filter_name; /* name of this protocol in filters */
250 int proto_id; /* field ID for this protocol */
251 GList *fields; /* fields for this protocol */
252 GList *last_field; /* pointer to end of list of fields */
253 gboolean is_enabled; /* TRUE if protocol is enabled */
254 gboolean can_toggle; /* TRUE if is_enabled can be changed */
255 gboolean is_private; /* TRUE is protocol is private */
258 /* List of all protocols */
259 static GList *protocols = NULL;
261 #define INITIAL_NUM_PROTOCOL_HFINFO 1500
263 /* Contains information about a field when a dissector calls
264 * proto_tree_add_item. */
265 static struct ws_memory_slab field_info_slab =
266 WS_MEMORY_SLAB_INIT(field_info, 128);
268 #define FIELD_INFO_NEW(fi) \
269 fi = sl_alloc(&field_info_slab)
270 #define FIELD_INFO_FREE(fi) \
271 sl_free(&field_info_slab, fi)
273 /* Contains the space for proto_nodes. */
274 static struct ws_memory_slab proto_node_slab =
275 WS_MEMORY_SLAB_INIT(proto_node, 128);
277 #define PROTO_NODE_NEW(node) \
278 node = sl_alloc(&proto_node_slab); \
279 node->first_child = NULL; \
280 node->last_child = NULL; \
283 #define PROTO_NODE_FREE(node) \
284 sl_free(&proto_node_slab, node)
286 /* String space for protocol and field items for the GUI */
287 static struct ws_memory_slab item_label_slab =
288 WS_MEMORY_SLAB_INIT(item_label_t, 128);
290 #define ITEM_LABEL_NEW(il) \
291 il = sl_alloc(&item_label_slab);
292 #define ITEM_LABEL_FREE(il) \
293 sl_free(&item_label_slab, il);
295 #define PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo) \
296 DISSECTOR_ASSERT((guint)hfindex < gpa_hfinfo.len); \
297 hfinfo = gpa_hfinfo.hfi[hfindex];
299 /* List which stores protocols and fields that have been registered */
300 typedef struct _gpa_hfinfo_t {
302 guint32 allocated_len;
303 header_field_info **hfi;
305 gpa_hfinfo_t gpa_hfinfo;
307 /* Balanced tree of abbreviations and IDs */
308 static GTree *gpa_name_tree = NULL;
309 static header_field_info *same_name_hfinfo;
311 static void save_same_name_hfinfo(gpointer data)
313 same_name_hfinfo = (header_field_info*)data;
316 /* Points to the first element of an array of Booleans, indexed by
317 a subtree item type; that array element is TRUE if subtrees of
318 an item of that type are to be expanded. */
319 gboolean *tree_is_expanded;
321 /* Number of elements in that array. */
324 /* Name hashtables for fast detection of duplicate names */
325 static GHashTable* proto_names = NULL;
326 static GHashTable* proto_short_names = NULL;
327 static GHashTable* proto_filter_names = NULL;
330 proto_compare_name(gconstpointer p1_arg, gconstpointer p2_arg)
332 const protocol_t *p1 = p1_arg;
333 const protocol_t *p2 = p2_arg;
335 return g_ascii_strcasecmp(p1->short_name, p2->short_name);
339 /* initialize data structures and register protocols and fields */
341 proto_init(void (register_all_protocols_func)(register_cb cb, gpointer client_data),
342 void (register_all_handoffs_func)(register_cb cb, gpointer client_data),
344 gpointer client_data)
346 static hf_register_info hf[] = {
348 { "Text item", "text", FT_NONE, BASE_NONE, NULL, 0x0,
354 proto_names = g_hash_table_new_full(g_int_hash, g_int_equal, g_free, NULL);
355 proto_short_names = g_hash_table_new(wrs_str_hash, g_str_equal);
356 proto_filter_names = g_hash_table_new(wrs_str_hash, g_str_equal);
359 gpa_hfinfo.allocated_len = 0;
360 gpa_hfinfo.hfi = NULL;
361 gpa_name_tree = g_tree_new_full(wrs_strcmp_with_data, NULL, NULL, save_same_name_hfinfo);
363 /* Initialize the ftype subsystem */
366 /* Register one special-case FT_TEXT_ONLY field for use when
367 converting wireshark to new-style proto_tree. These fields
368 are merely strings on the GUI tree; they are not filterable */
369 proto_register_field_array(-1, hf, array_length(hf));
371 /* Have each built-in dissector register its protocols, fields,
372 dissector tables, and dissectors to be called through a
373 handle, and do whatever one-time initialization it needs to
375 register_all_protocols_func(cb, client_data);
377 /* Now scan for python protocols */
379 (*cb)(RA_PYTHON_REGISTER, NULL, client_data);
380 register_all_py_protocols_func();
384 /* Now scan for plugins and load all the ones we find, calling
385 their register routines to do the stuff described above. */
387 (*cb)(RA_PLUGIN_REGISTER, NULL, client_data);
389 register_all_plugin_registrations();
392 /* Now call the "handoff registration" routines of all built-in
393 dissectors; those routines register the dissector in other
394 dissectors' handoff tables, and fetch any dissector handles
396 register_all_handoffs_func(cb, client_data);
399 /* Now do the same with python dissectors */
401 (*cb)(RA_PYTHON_HANDOFF, NULL, client_data);
402 register_all_py_handoffs_func();
406 /* Now do the same with plugins. */
408 (*cb)(RA_PLUGIN_HANDOFF, NULL, client_data);
409 register_all_plugin_handoffs();
412 /* sort the protocols by protocol name */
413 protocols = g_list_sort(protocols, proto_compare_name);
415 /* We've assigned all the subtree type values; allocate the array
416 for them, and zero it out. */
417 tree_is_expanded = g_new0(gboolean, num_tree_types);
423 /* Free the abbrev/ID GTree */
425 g_tree_destroy(gpa_name_tree);
426 gpa_name_tree = NULL;
430 protocol_t *protocol = protocols->data;
431 header_field_info *hfinfo;
432 PROTO_REGISTRAR_GET_NTH(protocol->proto_id, hfinfo);
433 DISSECTOR_ASSERT(protocol->proto_id == hfinfo->id);
435 g_slice_free(header_field_info, hfinfo);
436 g_list_free(protocol->fields);
437 protocols = g_list_remove(protocols, protocol);
442 g_hash_table_destroy(proto_names);
446 if (proto_short_names) {
447 g_hash_table_destroy(proto_short_names);
448 proto_short_names = NULL;
451 if (proto_filter_names) {
452 g_hash_table_destroy(proto_filter_names);
453 proto_filter_names = NULL;
456 if (gpa_hfinfo.allocated_len) {
458 gpa_hfinfo.allocated_len = 0;
459 g_free(gpa_hfinfo.hfi);
460 gpa_hfinfo.hfi = NULL;
462 g_free(tree_is_expanded);
463 tree_is_expanded = NULL;
467 proto_tree_traverse_pre_order(proto_tree *tree, proto_tree_traverse_func func,
470 proto_node *pnode = tree;
474 if (func(pnode, data))
477 child = pnode->first_child;
478 while (child != NULL) {
480 * The routine we call might modify the child, e.g. by
481 * freeing it, so we get the child's successor before
482 * calling that routine.
485 child = current->next;
486 if (proto_tree_traverse_pre_order((proto_tree *)current, func, data))
494 proto_tree_traverse_post_order(proto_tree *tree, proto_tree_traverse_func func,
497 proto_node *pnode = tree;
501 child = pnode->first_child;
502 while (child != NULL) {
504 * The routine we call might modify the child, e.g. by
505 * freeing it, so we get the child's successor before
506 * calling that routine.
509 child = current->next;
510 if (proto_tree_traverse_post_order((proto_tree *)current, func, data))
513 if (func(pnode, data))
520 proto_tree_children_foreach(proto_tree *tree, proto_tree_foreach_func func,
523 proto_node *node = tree;
526 node = node->first_child;
527 while (node != NULL) {
529 node = current->next;
530 func((proto_tree *)current, data);
535 free_GPtrArray_value(gpointer key, gpointer value, gpointer user_data _U_)
537 GPtrArray *ptrs = value;
538 gint hfid = (gint)(long)key;
539 header_field_info *hfinfo;
541 PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
542 if (hfinfo->ref_type != HF_REF_TYPE_NONE) {
543 /* when a field is referenced by a filter this also
544 affects the refcount for the parent protocol so we need
545 to adjust the refcount for the parent as well
547 if (hfinfo->parent != -1) {
548 header_field_info *parent_hfinfo;
549 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
550 parent_hfinfo->ref_type = HF_REF_TYPE_NONE;
552 hfinfo->ref_type = HF_REF_TYPE_NONE;
555 g_ptr_array_free(ptrs, TRUE);
559 free_node_tree_data(tree_data_t *tree_data)
561 if (tree_data->interesting_hfids) {
562 /* Free all the GPtrArray's in the interesting_hfids hash. */
563 g_hash_table_foreach(tree_data->interesting_hfids,
564 free_GPtrArray_value, NULL);
566 /* And then destroy the hash. */
567 g_hash_table_destroy(tree_data->interesting_hfids);
569 if (tree_data->fi_tmp)
570 FIELD_INFO_FREE(tree_data->fi_tmp);
572 /* And finally the tree_data_t itself. */
576 #define FREE_NODE_FIELD_INFO(finfo) \
578 ITEM_LABEL_FREE(finfo->rep); \
580 FVALUE_CLEANUP(&finfo->value); \
581 FIELD_INFO_FREE(finfo);
584 proto_tree_free_node(proto_node *node, gpointer data _U_)
586 field_info *finfo = PNODE_FINFO(node);
588 proto_tree_children_foreach(node, proto_tree_free_node, NULL);
590 /* free the field_info data. */
591 FREE_NODE_FIELD_INFO(finfo);
593 /* Free the proto_node. */
594 PROTO_NODE_FREE(node);
597 /* frees the resources that the dissection a proto_tree uses */
599 proto_tree_free(proto_tree *tree)
601 tree_data_t *tree_data = PTREE_DATA(tree);
603 proto_tree_children_foreach(tree, proto_tree_free_node, NULL);
606 PROTO_NODE_FREE(tree);
609 free_node_tree_data(tree_data);
612 /* Is the parsing being done for a visible proto_tree or an invisible one?
613 * By setting this correctly, the proto_tree creation is sped up by not
614 * having to call g_vsnprintf and copy strings around.
617 proto_tree_set_visible(proto_tree *tree, gboolean visible)
619 gboolean old_visible = PTREE_DATA(tree)->visible;
621 PTREE_DATA(tree)->visible = visible;
627 proto_tree_set_fake_protocols(proto_tree *tree, gboolean fake_protocols)
629 PTREE_DATA(tree)->fake_protocols = fake_protocols;
632 /* Assume dissector set only its protocol fields.
633 This function is called by dissectors and allows the speeding up of filtering
634 in wireshark; if this function returns FALSE it is safe to reset tree to NULL
635 and thus skip calling most of the expensive proto_tree_add_...()
637 If the tree is visible we implicitly assume the field is referenced.
640 proto_field_is_referenced(proto_tree *tree, int proto_id)
642 register header_field_info *hfinfo;
648 if (PTREE_DATA(tree)->visible)
651 PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
652 if (hfinfo->ref_type != HF_REF_TYPE_NONE)
655 if (hfinfo->type == FT_PROTOCOL && !PTREE_DATA(tree)->fake_protocols)
662 /* Finds a record in the hf_info_records array by id. */
664 proto_registrar_get_nth(guint hfindex)
666 register header_field_info *hfinfo;
668 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
673 /* Prefix initialization
674 * this allows for a dissector to register a display filter name prefix
675 * so that it can delay the initialization of the hf array as long as
679 /* compute a hash for the part before the dot of a display filter */
681 prefix_hash (gconstpointer key) {
682 /* end the string at the dot and compute its hash */
683 gchar* copy = ep_strdup(key);
693 return g_str_hash(copy);
696 /* are both strings equal up to the end or the dot? */
698 prefix_equal (gconstpointer ap, gconstpointer bp) {
706 if ( (ac == '.' || ac == '\0') && (bc == '.' || bc == '\0') ) return TRUE;
708 if ( (ac == '.' || ac == '\0') && ! (bc == '.' || bc == '\0') ) return FALSE;
709 if ( (bc == '.' || bc == '\0') && ! (ac == '.' || ac == '\0') ) return FALSE;
711 if (ac != bc) return FALSE;
718 /* indexed by prefix, contains initializers */
719 static GHashTable* prefixes = NULL;
722 /* Register a new prefix for "delayed" initialization of field arrays */
724 proto_register_prefix(const char *prefix, prefix_initializer_t pi ) {
726 prefixes = g_hash_table_new(prefix_hash, prefix_equal);
729 g_hash_table_insert(prefixes, (gpointer)prefix, pi);
732 /* helper to call all prefix initializers */
734 initialize_prefix(gpointer k, gpointer v, gpointer u _U_) {
735 ((prefix_initializer_t)v)(k);
739 /** Initialize every remaining uninitialized prefix. */
741 proto_initialize_all_prefixes(void) {
742 g_hash_table_foreach_remove(prefixes, initialize_prefix, NULL);
745 /* Finds a record in the hf_info_records array by name.
746 * If it fails to find it in the already registered fields,
747 * it tries to find and call an initializer in the prefixes
748 * table and if so it looks again.
751 proto_registrar_get_byname(const char *field_name)
753 header_field_info *hfinfo;
754 prefix_initializer_t pi;
759 hfinfo = g_tree_lookup(gpa_name_tree, field_name);
767 if ((pi = g_hash_table_lookup(prefixes, field_name) ) != NULL) {
769 g_hash_table_remove(prefixes, field_name);
774 return g_tree_lookup(gpa_name_tree, field_name);
779 ptvcursor_new_subtree_levels(ptvcursor_t *ptvc)
781 subtree_lvl *pushed_tree;
783 DISSECTOR_ASSERT(ptvc->pushed_tree_max <= SUBTREE_MAX_LEVELS-SUBTREE_ONCE_ALLOCATION_NUMBER);
784 ptvc->pushed_tree_max += SUBTREE_ONCE_ALLOCATION_NUMBER;
786 pushed_tree = ep_alloc(sizeof(subtree_lvl) * ptvc->pushed_tree_max);
787 DISSECTOR_ASSERT(pushed_tree != NULL);
788 if (ptvc->pushed_tree)
789 memcpy(pushed_tree, ptvc->pushed_tree, ptvc->pushed_tree_max - SUBTREE_ONCE_ALLOCATION_NUMBER);
790 ptvc->pushed_tree = pushed_tree;
794 ptvcursor_free_subtree_levels(ptvcursor_t *ptvc)
796 ptvc->pushed_tree = NULL;
797 ptvc->pushed_tree_max = 0;
798 DISSECTOR_ASSERT(ptvc->pushed_tree_index == 0);
799 ptvc->pushed_tree_index = 0;
802 /* Allocates an initializes a ptvcursor_t with 3 variables:
803 * proto_tree, tvbuff, and offset. */
805 ptvcursor_new(proto_tree *tree, tvbuff_t *tvb, gint offset)
809 ptvc = ep_alloc(sizeof(ptvcursor_t));
812 ptvc->offset = offset;
813 ptvc->pushed_tree = NULL;
814 ptvc->pushed_tree_max = 0;
815 ptvc->pushed_tree_index = 0;
820 /* Frees memory for ptvcursor_t, but nothing deeper than that. */
822 ptvcursor_free(ptvcursor_t *ptvc)
824 ptvcursor_free_subtree_levels(ptvc);
828 /* Returns tvbuff. */
830 ptvcursor_tvbuff(ptvcursor_t *ptvc)
835 /* Returns current offset. */
837 ptvcursor_current_offset(ptvcursor_t *ptvc)
843 ptvcursor_tree(ptvcursor_t *ptvc)
852 ptvcursor_set_tree(ptvcursor_t *ptvc, proto_tree *tree)
857 /* creates a subtree, sets it as the working tree and pushes the old working tree */
859 ptvcursor_push_subtree(ptvcursor_t *ptvc, proto_item *it, gint ett_subtree)
861 subtree_lvl *subtree;
862 if (ptvc->pushed_tree_index >= ptvc->pushed_tree_max)
863 ptvcursor_new_subtree_levels(ptvc);
865 subtree = ptvc->pushed_tree + ptvc->pushed_tree_index;
866 subtree->tree = ptvc->tree;
868 ptvc->pushed_tree_index++;
869 return ptvcursor_set_subtree(ptvc, it, ett_subtree);
874 ptvcursor_pop_subtree(ptvcursor_t *ptvc)
876 subtree_lvl *subtree;
878 if (ptvc->pushed_tree_index <= 0)
881 ptvc->pushed_tree_index--;
882 subtree = ptvc->pushed_tree + ptvc->pushed_tree_index;
883 if (subtree->it != NULL)
884 proto_item_set_len(subtree->it, ptvcursor_current_offset(ptvc) - subtree->cursor_offset);
886 ptvc->tree = subtree->tree;
889 /* saves the current tvb offset and the item in the current subtree level */
891 ptvcursor_subtree_set_item(ptvcursor_t *ptvc, proto_item *it)
893 subtree_lvl *subtree;
895 DISSECTOR_ASSERT(ptvc->pushed_tree_index > 0);
897 subtree = ptvc->pushed_tree + ptvc->pushed_tree_index - 1;
899 subtree->cursor_offset = ptvcursor_current_offset(ptvc);
902 /* Creates a subtree and adds it to the cursor as the working tree but does not
903 * save the old working tree */
905 ptvcursor_set_subtree(ptvcursor_t *ptvc, proto_item *it, gint ett_subtree)
907 ptvc->tree = proto_item_add_subtree(it, ett_subtree);
912 ptvcursor_add_subtree_item(ptvcursor_t *ptvc, proto_item *it, gint ett_subtree, gint length)
914 ptvcursor_push_subtree(ptvc, it, ett_subtree);
915 if (length == SUBTREE_UNDEFINED_LENGTH)
916 ptvcursor_subtree_set_item(ptvc, it);
917 return ptvcursor_tree(ptvc);
920 /* Add an item to the tree and create a subtree
921 * If the length is unknown, length may be defined as SUBTREE_UNDEFINED_LENGTH.
922 * In this case, when the subtree will be closed, the parent item length will
923 * be equal to the advancement of the cursor since the creation of the subtree.
926 ptvcursor_add_with_subtree(ptvcursor_t *ptvc, int hfindex, gint length,
927 const guint encoding, gint ett_subtree)
931 it = ptvcursor_add_no_advance(ptvc, hfindex, length, encoding);
932 return ptvcursor_add_subtree_item(ptvc, it, ett_subtree, length);
936 proto_tree_add_text_node(proto_tree *tree, tvbuff_t *tvb, gint start, gint length);
938 /* Add a text node to the tree and create a subtree
939 * If the length is unknown, length may be defined as SUBTREE_UNDEFINED_LENGTH.
940 * In this case, when the subtree will be closed, the item length will be equal
941 * to the advancement of the cursor since the creation of the subtree.
944 ptvcursor_add_text_with_subtree(ptvcursor_t *ptvc, gint length,
945 gint ett_subtree, const char *format, ...)
949 header_field_info *hfinfo;
952 tree = ptvcursor_tree(ptvc);
954 TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
956 pi = proto_tree_add_text_node(tree, ptvcursor_tvbuff(ptvc),
957 ptvcursor_current_offset(ptvc), length);
959 TRY_TO_FAKE_THIS_REPR(tree, pi);
961 va_start(ap, format);
962 proto_tree_set_representation(pi, format, ap);
965 return ptvcursor_add_subtree_item(ptvc, pi, ett_subtree, length);
968 /* Add a text-only node, leaving it to our caller to fill the text in */
970 proto_tree_add_text_node(proto_tree *tree, tvbuff_t *tvb, gint start, gint length)
974 pi = proto_tree_add_pi(tree, hf_text_only, tvb, start, &length, NULL);
979 /* Add a text-only node to the proto_tree */
981 proto_tree_add_text(proto_tree *tree, tvbuff_t *tvb, gint start, gint length,
982 const char *format, ...)
986 header_field_info *hfinfo;
988 TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
990 pi = proto_tree_add_text_node(tree, tvb, start, length);
992 TRY_TO_FAKE_THIS_REPR(tree, pi);
994 va_start(ap, format);
995 proto_tree_set_representation(pi, format, ap);
1001 /* Add a text-only node to the proto_tree (va_list version) */
1003 proto_tree_add_text_valist(proto_tree *tree, tvbuff_t *tvb, gint start,
1004 gint length, const char *format, va_list ap)
1007 header_field_info *hfinfo;
1009 TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
1011 pi = proto_tree_add_text_node(tree, tvb, start, length);
1013 TRY_TO_FAKE_THIS_REPR(tree, pi);
1015 proto_tree_set_representation(pi, format, ap);
1020 /* Add a text-only node for debugging purposes. The caller doesn't need
1021 * to worry about tvbuff, start, or length. Debug message gets sent to
1024 proto_tree_add_debug_text(proto_tree *tree, const char *format, ...)
1029 pi = proto_tree_add_text_node(tree, NULL, 0, 0);
1032 va_start(ap, format);
1033 proto_tree_set_representation(pi, format, ap);
1036 va_start(ap, format);
1037 vprintf(format, ap);
1044 /* We could probably get away with changing is_error to a minimum length value. */
1046 report_type_length_mismatch(proto_tree *tree, const gchar *descr, int length, gboolean is_error) {
1047 tree_data_t *tree_data = PTREE_DATA(tree);
1048 field_info *fi_save = tree_data->fi_tmp;
1050 /* Keep the current item from getting freed by proto_tree_new_item. */
1051 tree_data->fi_tmp = NULL;
1053 expert_add_info_format(NULL, tree, PI_MALFORMED, is_error ? PI_ERROR : PI_WARN, "Trying to fetch %s with length %d", descr, length);
1055 tree_data->fi_tmp = fi_save;
1058 THROW(ReportedBoundsError);
1063 * NOTE: to support code written when proto_tree_add_item() took a
1064 * gboolean as its last argument, with FALSE meaning "big-endian"
1065 * and TRUE meaning "little-endian", we treat any non-zero value of
1066 * "encoding" as meaning "little-endian".
1069 get_uint_value(proto_tree *tree, tvbuff_t *tvb, gint offset, gint length, const guint encoding)
1072 gboolean length_error;
1077 value = tvb_get_guint8(tvb, offset);
1081 value = encoding ? tvb_get_letohs(tvb, offset)
1082 : tvb_get_ntohs(tvb, offset);
1086 value = encoding ? tvb_get_letoh24(tvb, offset)
1087 : tvb_get_ntoh24(tvb, offset);
1091 value = encoding ? tvb_get_letohl(tvb, offset)
1092 : tvb_get_ntohl(tvb, offset);
1097 length_error = TRUE;
1100 length_error = FALSE;
1101 value = encoding ? tvb_get_letohl(tvb, offset)
1102 : tvb_get_ntohl(tvb, offset);
1104 report_type_length_mismatch(tree, "an unsigned integer", length, length_error);
1111 * NOTE: to support code written when proto_tree_add_item() took a
1112 * gboolean as its last argument, with FALSE meaning "big-endian"
1113 * and TRUE meaning "little-endian", we treat any non-zero value of
1114 * "encoding" as meaning "little-endian".
1117 get_int_value(proto_tree *tree, tvbuff_t *tvb, gint offset, gint length, const guint encoding)
1120 gboolean length_error;
1125 value = (gint8)tvb_get_guint8(tvb, offset);
1129 value = (gint16) (encoding ? tvb_get_letohs(tvb, offset)
1130 : tvb_get_ntohs(tvb, offset));
1134 value = encoding ? tvb_get_letoh24(tvb, offset)
1135 : tvb_get_ntoh24(tvb, offset);
1136 if (value & 0x00800000) {
1137 /* Sign bit is set; sign-extend it. */
1138 value |= 0xFF000000;
1143 value = encoding ? tvb_get_letohl(tvb, offset)
1144 : tvb_get_ntohl(tvb, offset);
1149 length_error = TRUE;
1152 length_error = FALSE;
1153 value = encoding ? tvb_get_letohl(tvb, offset)
1154 : tvb_get_ntohl(tvb, offset);
1156 report_type_length_mismatch(tree, "a signed integer", length, length_error);
1163 proto_lookup_or_create_interesting_hfids(proto_tree *tree,
1164 header_field_info *hfinfo)
1166 GPtrArray *ptrs = NULL;
1168 DISSECTOR_ASSERT(tree);
1169 DISSECTOR_ASSERT(hfinfo);
1171 if (hfinfo->ref_type == HF_REF_TYPE_DIRECT) {
1172 if (PTREE_DATA(tree)->interesting_hfids == NULL) {
1173 /* Initialize the hash because we now know that it is needed */
1174 PTREE_DATA(tree)->interesting_hfids =
1175 g_hash_table_new(g_direct_hash, NULL /* g_direct_equal */);
1178 ptrs = g_hash_table_lookup(PTREE_DATA(tree)->interesting_hfids,
1179 GINT_TO_POINTER(hfinfo->id));
1181 /* First element triggers the creation of pointer array */
1182 ptrs = g_ptr_array_new();
1183 g_hash_table_insert(PTREE_DATA(tree)->interesting_hfids,
1184 GINT_TO_POINTER(hfinfo->id), ptrs);
1191 /* Add an item to a proto_tree, using the text label registered to that item;
1192 the item is extracted from the tvbuff handed to it. */
1194 proto_tree_new_item(field_info *new_fi, proto_tree *tree,
1195 tvbuff_t *tvb, gint start, gint length,
1198 tree_data_t *tree_data = PTREE_DATA(tree);
1204 nstime_t time_stamp;
1207 gboolean length_error;
1209 /* there is a possibility here that we might raise an exception
1210 * and thus would lose track of the field_info.
1211 * store it in a temp so that if we come here again we can reclaim
1212 * the field_info without leaking memory.
1214 if (tree_data->fi_tmp) {
1215 /* oops, last one we got must have been lost due
1217 * good thing we saved it, now we can reverse the
1218 * memory leak and reclaim it.
1220 FIELD_INFO_FREE(tree_data->fi_tmp);
1222 /* we might throw an exception, keep track of this one
1223 * across the "dangerous" section below.
1225 tree_data->fi_tmp = new_fi;
1227 switch (new_fi->hfinfo->type) {
1229 /* no value to set for FT_NONE */
1233 proto_tree_set_protocol_tvb(new_fi, tvb);
1237 proto_tree_set_bytes_tvb(new_fi, tvb, start, length);
1242 * Map all non-zero values to little-endian for
1243 * backwards compatibility.
1246 encoding = ENC_LITTLE_ENDIAN;
1247 n = get_uint_value(tree, tvb, start, length, encoding);
1248 proto_tree_set_bytes_tvb(new_fi, tvb, start + length, n);
1250 /* Instead of calling proto_item_set_len(), since we don't yet
1251 * have a proto_item, we set the field_info's length ourselves. */
1252 new_fi->length = n + length;
1257 * Map all non-zero values to little-endian for
1258 * backwards compatibility.
1261 encoding = ENC_LITTLE_ENDIAN;
1262 proto_tree_set_boolean(new_fi,
1263 get_uint_value(tree, tvb, start, length, encoding));
1266 /* XXX - make these just FT_UINT? */
1272 * Map all non-zero values to little-endian for
1273 * backwards compatibility.
1276 encoding = ENC_LITTLE_ENDIAN;
1277 proto_tree_set_uint(new_fi,
1278 get_uint_value(tree, tvb, start, length, encoding));
1284 * Map all non-zero values to little-endian for
1285 * backwards compatibility.
1288 encoding = ENC_LITTLE_ENDIAN;
1289 if (length < 1 || length > 8) {
1290 length_error = length < 1 ? TRUE : FALSE;
1291 report_type_length_mismatch(tree, "a 64-bit integer", length, length_error);
1293 proto_tree_set_uint64_tvb(new_fi, tvb, start, length, encoding);
1296 /* XXX - make these just FT_INT? */
1302 * Map all non-zero values to little-endian for
1303 * backwards compatibility.
1306 encoding = ENC_LITTLE_ENDIAN;
1307 proto_tree_set_int(new_fi,
1308 get_int_value(tree, tvb, start, length, encoding));
1313 * Map all non-zero values to little-endian for
1314 * backwards compatibility.
1317 encoding = ENC_LITTLE_ENDIAN;
1318 if (length != FT_IPv4_LEN) {
1319 length_error = length < FT_IPv4_LEN ? TRUE : FALSE;
1320 report_type_length_mismatch(tree, "an IPv4 address", length, length_error);
1322 value = tvb_get_ipv4(tvb, start);
1324 * NOTE: to support code written when
1325 * proto_tree_add_item() took a gboolean as its
1326 * last argument, with FALSE meaning "big-endian"
1327 * and TRUE meaning "little-endian", we treat any
1328 * non-zero value of "encoding" as meaning
1331 proto_tree_set_ipv4(new_fi, encoding ? GUINT32_SWAP_LE_BE(value) : value);
1335 if (length != FT_IPXNET_LEN) {
1336 length_error = length < FT_IPXNET_LEN ? TRUE : FALSE;
1337 report_type_length_mismatch(tree, "an IPXNET address", length, length_error);
1339 proto_tree_set_ipxnet(new_fi,
1340 get_uint_value(tree, tvb, start, FT_IPXNET_LEN, FALSE));
1344 if (length != FT_IPv6_LEN) {
1345 length_error = length < FT_IPv6_LEN ? TRUE : FALSE;
1346 report_type_length_mismatch(tree, "an IPv6 address", length, length_error);
1348 proto_tree_set_ipv6_tvb(new_fi, tvb, start, length);
1353 length_error = length < 7 ? TRUE : FALSE;
1354 expert_add_info_format(NULL, tree, PI_MALFORMED, PI_ERROR, "Trying to fetch an AX.25 address with length %d", length);
1355 THROW(ReportedBoundsError);
1357 proto_tree_set_ax25_tvb(new_fi, tvb, start);
1361 if (length != FT_ETHER_LEN) {
1362 length_error = length < FT_ETHER_LEN ? TRUE : FALSE;
1363 report_type_length_mismatch(tree, "an Ethernet", length, length_error);
1365 proto_tree_set_ether_tvb(new_fi, tvb, start);
1370 * Map all non-zero values to little-endian for
1371 * backwards compatibility.
1374 encoding = ENC_LITTLE_ENDIAN;
1375 if (length != FT_EUI64_LEN) {
1376 length_error = length < FT_EUI64_LEN ? TRUE : FALSE;
1377 report_type_length_mismatch(tree, "an EUI-64 address", length, length_error);
1379 proto_tree_set_eui64_tvb(new_fi, tvb, start, encoding);
1383 * Map all non-zero values to little-endian for
1384 * backwards compatibility.
1387 encoding = ENC_LITTLE_ENDIAN;
1388 if (length != FT_GUID_LEN) {
1389 length_error = length < FT_GUID_LEN ? TRUE : FALSE;
1390 report_type_length_mismatch(tree, "a GUID", length, length_error);
1392 proto_tree_set_guid_tvb(new_fi, tvb, start, encoding);
1396 proto_tree_set_oid_tvb(new_fi, tvb, start, length);
1401 * NOTE: to support code written when
1402 * proto_tree_add_item() took a gboolean as its
1403 * last argument, with FALSE meaning "big-endian"
1404 * and TRUE meaning "little-endian", we treat any
1405 * non-zero value of "encoding" as meaning
1408 * At some point in the future, we might
1409 * support non-IEEE-binary floating-point
1410 * formats in the encoding as well
1411 * (IEEE decimal, System/3x0, VAX).
1414 encoding = ENC_LITTLE_ENDIAN;
1416 length_error = length < 4 ? TRUE : FALSE;
1417 report_type_length_mismatch(tree, "a single-precision floating point number", length, length_error);
1420 floatval = tvb_get_letohieee_float(tvb, start);
1422 floatval = tvb_get_ntohieee_float(tvb, start);
1423 proto_tree_set_float(new_fi, floatval);
1428 * NOTE: to support code written when
1429 * proto_tree_add_item() took a gboolean as its
1430 * last argument, with FALSE meaning "big-endian"
1431 * and TRUE meaning "little-endian", we treat any
1432 * non-zero value of "encoding" as meaning
1435 * At some point in the future, we might
1436 * support non-IEEE-binary floating-point
1437 * formats in the encoding as well
1438 * (IEEE decimal, System/3x0, VAX).
1440 if (encoding == TRUE)
1441 encoding = ENC_LITTLE_ENDIAN;
1443 length_error = length < 8 ? TRUE : FALSE;
1444 report_type_length_mismatch(tree, "a double-precision floating point number", length, length_error);
1447 doubleval = tvb_get_letohieee_double(tvb, start);
1449 doubleval = tvb_get_ntohieee_double(tvb, start);
1450 proto_tree_set_double(new_fi, doubleval);
1454 proto_tree_set_string_tvb(new_fi, tvb, start, length,
1460 report_type_length_mismatch(tree, "a string", length, TRUE);
1462 /* Instead of calling proto_item_set_len(),
1463 * since we don't yet have a proto_item, we
1464 * set the field_info's length ourselves.
1466 * XXX - our caller can't use that length to
1467 * advance an offset unless they arrange that
1468 * there always be a protocol tree into which
1469 * we're putting this item.
1472 /* This can throw an exception */
1473 string = tvb_get_stringz_enc(tvb, start, &length, encoding);
1474 } else if (length == 0) {
1477 /* In this case, length signifies
1478 * the length of the string.
1480 * This could either be a null-padded
1481 * string, which doesn't necessarily
1482 * have a '\0' at the end, or a
1483 * null-terminated string, with a
1484 * trailing '\0'. (Yes, there are
1485 * cases where you have a string
1486 * that's both counted and null-
1489 * In the first case, we must
1490 * allocate a buffer of length
1491 * "length+1", to make room for
1494 * In the second case, we don't
1495 * assume that there is a trailing
1496 * '\0' there, as the packet might
1497 * be malformed. (XXX - should we
1498 * throw an exception if there's no
1499 * trailing '\0'?) Therefore, we
1500 * allocate a buffer of length
1501 * "length+1", and put in a trailing
1502 * '\0', just to be safe.
1504 * (XXX - this would change if
1505 * we made string values counted
1506 * rather than null-terminated.)
1508 string = tvb_get_ephemeral_string_enc(tvb, start, length, encoding);
1510 new_fi->length = length;
1511 proto_tree_set_string(new_fi, string);
1514 case FT_UINT_STRING:
1516 * NOTE: to support code written when
1517 * proto_tree_add_item() took a gboolean as its
1518 * last argument, with FALSE meaning "big-endian"
1519 * and TRUE meaning "little-endian", if the
1520 * encoding value is TRUE, treat that as
1521 * ASCII with a little-endian length.
1523 * This won't work for code that passes
1524 * arbitrary non-zero values; that code
1525 * will need to be fixed.
1527 if (encoding == TRUE)
1528 encoding = ENC_ASCII|ENC_LITTLE_ENDIAN;
1529 n = get_uint_value(tree, tvb, start, length, encoding & ~ENC_CHARENCODING_MASK);
1530 proto_tree_set_string_tvb(new_fi, tvb, start + length, n,
1533 /* Instead of calling proto_item_set_len(), since we
1534 * don't yet have a proto_item, we set the
1535 * field_info's length ourselves.
1537 * XXX - our caller can't use that length to
1538 * advance an offset unless they arrange that
1539 * there always be a protocol tree into which
1540 * we're putting this item.
1542 new_fi->length = n + length;
1545 case FT_ABSOLUTE_TIME:
1547 * Absolute times can be in any of a number of
1548 * formats, and they can be big-endian or
1551 * Historically FT_TIMEs were only timespecs;
1552 * the only question was whether they were stored
1553 * in big- or little-endian format.
1555 * For backwards compatibility, we interpret an
1556 * encoding of 1 as meaning "little-endian timespec",
1557 * so that passing TRUE is interpreted as that.
1559 if (encoding == TRUE)
1560 encoding = ENC_TIME_TIMESPEC|ENC_LITTLE_ENDIAN;
1562 if (length != 8 && length != 4) {
1563 length_error = length < 4 ? TRUE : FALSE;
1564 report_type_length_mismatch(tree, "an absolute time value", length, length_error);
1569 case ENC_TIME_TIMESPEC|ENC_BIG_ENDIAN:
1571 * 4-byte UNIX epoch, possibly followed by
1572 * 4-byte fractional time in nanoseconds,
1575 time_stamp.secs = tvb_get_ntohl(tvb, start);
1577 time_stamp.nsecs = tvb_get_ntohl(tvb, start+4);
1579 time_stamp.nsecs = 0;
1582 case ENC_TIME_TIMESPEC|ENC_LITTLE_ENDIAN:
1584 * 4-byte UNIX epoch, possibly followed by
1585 * 4-byte fractional time in nanoseconds,
1586 * both little-endian.
1588 time_stamp.secs = tvb_get_letohl(tvb, start);
1590 time_stamp.nsecs = tvb_get_letohl(tvb, start+4);
1592 time_stamp.nsecs = 0;
1595 case ENC_TIME_NTP|ENC_BIG_ENDIAN:
1597 * NTP time stamp, big-endian.
1600 /* XXX - where should this go? */
1601 #define NTP_BASETIME 2208988800ul
1603 /* We need a temporary variable here so the unsigned math
1604 * works correctly (for years > 2036 according to RFC 2030
1607 tmpsecs = tvb_get_ntohl(tvb, start);
1609 time_stamp.secs = tmpsecs - (guint32)NTP_BASETIME;
1611 time_stamp.secs = tmpsecs; /* 0 */
1615 * We're using nanoseconds here (and we will
1616 * display nanoseconds), but NTP's timestamps
1617 * have a precision in microseconds or greater.
1618 * Round to 1 microsecond.
1620 time_stamp.nsecs = (int)(1000000*(tvb_get_ntohl(tvb, start+4)/4294967296.0));
1621 time_stamp.nsecs *= 1000;
1623 time_stamp.nsecs = 0;
1627 case ENC_TIME_NTP|ENC_LITTLE_ENDIAN:
1629 * NTP time stamp, big-endian.
1631 tmpsecs = tvb_get_letohl(tvb, start);
1633 time_stamp.secs = tmpsecs - (guint32)NTP_BASETIME;
1635 time_stamp.secs = tmpsecs; /* 0 */
1639 * We're using nanoseconds here (and we will
1640 * display nanoseconds), but NTP's timestamps
1641 * have a precision in microseconds or greater.
1642 * Round to 1 microsecond.
1644 time_stamp.nsecs = (int)(1000000*(tvb_get_letohl(tvb, start+4)/4294967296.0));
1645 time_stamp.nsecs *= 1000;
1647 time_stamp.nsecs = 0;
1652 DISSECTOR_ASSERT_NOT_REACHED();
1653 time_stamp.secs = 0;
1654 time_stamp.nsecs = 0;
1657 proto_tree_set_time(new_fi, &time_stamp);
1660 case FT_RELATIVE_TIME:
1662 * Relative times can be in any of a number of
1663 * formats, and they can be big-endian or
1666 * Historically FT_TIMEs were only timespecs;
1667 * the only question was whether they were stored
1668 * in big- or little-endian format.
1670 * For backwards compatibility, we interpret an
1671 * encoding of 1 as meaning "little-endian timespec",
1672 * so that passing TRUE is interpreted as that.
1674 if (encoding == TRUE)
1675 encoding = ENC_TIME_TIMESPEC|ENC_LITTLE_ENDIAN;
1678 if (length != 8 && length != 4) {
1679 length_error = length < 4 ? TRUE : FALSE;
1680 report_type_length_mismatch(tree, "a relative time value", length, length_error);
1683 case ENC_TIME_TIMESPEC|ENC_BIG_ENDIAN:
1685 * 4-byte UNIX epoch, possibly followed by
1686 * 4-byte fractional time in nanoseconds,
1689 time_stamp.secs = tvb_get_ntohl(tvb, start);
1691 time_stamp.nsecs = tvb_get_ntohl(tvb, start+4);
1693 time_stamp.nsecs = 0;
1696 case ENC_TIME_TIMESPEC|ENC_LITTLE_ENDIAN:
1698 * 4-byte UNIX epoch, possibly followed by
1699 * 4-byte fractional time in nanoseconds,
1700 * both little-endian.
1702 time_stamp.secs = tvb_get_letohl(tvb, start);
1704 time_stamp.nsecs = tvb_get_letohl(tvb, start+4);
1706 time_stamp.nsecs = 0;
1709 proto_tree_set_time(new_fi, &time_stamp);
1713 g_error("new_fi->hfinfo->type %d (%s) not handled\n",
1714 new_fi->hfinfo->type,
1715 ftype_name(new_fi->hfinfo->type));
1716 DISSECTOR_ASSERT_NOT_REACHED();
1719 FI_SET_FLAG(new_fi, (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN);
1721 /* Don't add new node to proto_tree until now so that any exceptions
1722 * raised by a tvbuff access method doesn't leave junk in the proto_tree. */
1723 /* XXX. wouldn't be better to add this item to tree, with some special flag (FI_EXCEPTION?)
1724 * to know which item caused exception? */
1725 pi = proto_tree_add_node(tree, new_fi);
1727 /* we did not raise an exception so we dont have to remember this
1728 * field_info struct any more.
1730 tree_data->fi_tmp = NULL;
1732 /* If the proto_tree wants to keep a record of this finfo
1733 * for quick lookup, then record it. */
1734 ptrs = proto_lookup_or_create_interesting_hfids(tree, new_fi->hfinfo);
1736 g_ptr_array_add(ptrs, new_fi);
1741 /* Gets data from tvbuff, adds it to proto_tree, increments offset,
1742 and returns proto_item* */
1744 ptvcursor_add(ptvcursor_t *ptvc, int hfindex, gint length,
1745 const guint encoding)
1748 header_field_info *hfinfo;
1753 /* We can't fake it just yet. We have to advance the cursor
1754 TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfindex, hfinfo); */
1756 offset = ptvc->offset;
1757 hfinfo = get_hfi_and_length(hfindex, ptvc->tvb, offset, &length,
1759 ptvc->offset += length;
1760 if (hfinfo->type == FT_UINT_BYTES || hfinfo->type == FT_UINT_STRING) {
1762 * The length of the rest of the item is in the first N
1763 * bytes of the item.
1765 n = get_uint_value(ptvc->tree, ptvc->tvb, offset, length, encoding);
1769 /* Coast clear. Try and fake it */
1770 TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfindex, hfinfo);
1772 new_fi = new_field_info(ptvc->tree, hfinfo, ptvc->tvb, offset, item_length);
1774 return proto_tree_new_item(new_fi, ptvc->tree, ptvc->tvb,
1775 offset, length, encoding);
1778 /* Add an item to a proto_tree, using the text label registered to that item;
1779 the item is extracted from the tvbuff handed to it. */
1781 proto_tree_add_item(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
1782 const gint start, gint length, const guint encoding)
1785 header_field_info *hfinfo;
1787 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1789 new_fi = alloc_field_info(tree, hfindex, tvb, start, &length);
1794 return proto_tree_new_item(new_fi, tree, tvb, start,
1798 /* Add a FT_NONE to a proto_tree */
1800 proto_tree_add_none_format(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
1801 const gint start, gint length, const char *format,
1806 header_field_info *hfinfo;
1808 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1810 DISSECTOR_ASSERT(hfinfo->type == FT_NONE);
1812 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, NULL);
1814 TRY_TO_FAKE_THIS_REPR(tree, pi);
1816 va_start(ap, format);
1817 proto_tree_set_representation(pi, format, ap);
1820 /* no value to set for FT_NONE */
1824 /* Gets data from tvbuff, adds it to proto_tree, *DOES NOT* increment
1825 * offset, and returns proto_item* */
1827 ptvcursor_add_no_advance(ptvcursor_t* ptvc, int hf, gint length,
1828 const guint encoding)
1832 item = proto_tree_add_item(ptvc->tree, hf, ptvc->tvb, ptvc->offset,
1838 /* Advance the ptvcursor's offset within its tvbuff without
1839 * adding anything to the proto_tree. */
1841 ptvcursor_advance(ptvcursor_t* ptvc, gint length)
1843 ptvc->offset += length;
1848 proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb)
1850 fvalue_set(&fi->value, tvb, TRUE);
1853 /* Add a FT_PROTOCOL to a proto_tree */
1855 proto_tree_add_protocol_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1856 gint start, gint length, const char *format, ...)
1861 header_field_info *hfinfo;
1863 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1865 DISSECTOR_ASSERT(hfinfo->type == FT_PROTOCOL);
1867 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1869 proto_tree_set_protocol_tvb(new_fi, (start == 0 ? tvb : tvb_new_subset(tvb, start, length, length)));
1871 TRY_TO_FAKE_THIS_REPR(tree, pi);
1873 va_start(ap, format);
1874 proto_tree_set_representation(pi, format, ap);
1881 /* Add a FT_BYTES to a proto_tree */
1883 proto_tree_add_bytes(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1884 gint length, const guint8 *start_ptr)
1888 header_field_info *hfinfo;
1890 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1892 DISSECTOR_ASSERT(hfinfo->type == FT_BYTES);
1894 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1895 proto_tree_set_bytes(new_fi, start_ptr, length);
1901 proto_tree_add_bytes_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1902 gint start, gint length,
1903 const guint8 *start_ptr,
1904 const char *format, ...)
1908 header_field_info *hfinfo;
1910 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1913 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length,
1916 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length,
1917 tvb_get_ptr(tvb, start, length));
1919 TRY_TO_FAKE_THIS_REPR(tree, pi);
1921 va_start(ap, format);
1922 proto_tree_set_representation_value(pi, format, ap);
1929 proto_tree_add_bytes_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1930 gint start, gint length, const guint8 *start_ptr,
1931 const char *format, ...)
1935 header_field_info *hfinfo;
1937 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1940 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length,
1943 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length,
1944 tvb_get_ptr(tvb, start, length));
1946 TRY_TO_FAKE_THIS_REPR(tree, pi);
1948 va_start(ap, format);
1949 proto_tree_set_representation(pi, format, ap);
1956 proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length)
1960 bytes = g_byte_array_new();
1962 g_byte_array_append(bytes, start_ptr, length);
1964 fvalue_set(&fi->value, bytes, TRUE);
1969 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length)
1971 proto_tree_set_bytes(fi, tvb_get_ptr(tvb, offset, length), length);
1974 /* Add a FT_*TIME to a proto_tree */
1976 proto_tree_add_time(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1977 gint length, nstime_t *value_ptr)
1981 header_field_info *hfinfo;
1983 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1985 DISSECTOR_ASSERT(hfinfo->type == FT_ABSOLUTE_TIME ||
1986 hfinfo->type == FT_RELATIVE_TIME);
1988 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1989 proto_tree_set_time(new_fi, value_ptr);
1995 proto_tree_add_time_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1996 gint start, gint length, nstime_t *value_ptr,
1997 const char *format, ...)
2001 header_field_info *hfinfo;
2003 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2005 pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
2007 TRY_TO_FAKE_THIS_REPR(tree, pi);
2009 va_start(ap, format);
2010 proto_tree_set_representation_value(pi, format, ap);
2017 proto_tree_add_time_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2018 gint start, gint length, nstime_t *value_ptr,
2019 const char *format, ...)
2023 header_field_info *hfinfo;
2025 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2027 pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
2029 TRY_TO_FAKE_THIS_REPR(tree, pi);
2031 va_start(ap, format);
2032 proto_tree_set_representation(pi, format, ap);
2038 /* Set the FT_*TIME value */
2040 proto_tree_set_time(field_info *fi, nstime_t *value_ptr)
2042 DISSECTOR_ASSERT(value_ptr != NULL);
2044 fvalue_set(&fi->value, value_ptr, FALSE);
2047 /* Add a FT_IPXNET to a proto_tree */
2049 proto_tree_add_ipxnet(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2050 gint length, guint32 value)
2054 header_field_info *hfinfo;
2056 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2058 DISSECTOR_ASSERT(hfinfo->type == FT_IPXNET);
2060 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2061 proto_tree_set_ipxnet(new_fi, value);
2067 proto_tree_add_ipxnet_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2068 gint start, gint length, guint32 value,
2069 const char *format, ...)
2073 header_field_info *hfinfo;
2075 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2077 pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
2079 TRY_TO_FAKE_THIS_REPR(tree, pi);
2081 va_start(ap, format);
2082 proto_tree_set_representation_value(pi, format, ap);
2089 proto_tree_add_ipxnet_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2090 gint start, gint length, guint32 value,
2091 const char *format, ...)
2095 header_field_info *hfinfo;
2097 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2099 pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
2101 TRY_TO_FAKE_THIS_REPR(tree, pi);
2103 va_start(ap, format);
2104 proto_tree_set_representation(pi, format, ap);
2110 /* Set the FT_IPXNET value */
2112 proto_tree_set_ipxnet(field_info *fi, guint32 value)
2114 fvalue_set_uinteger(&fi->value, value);
2117 /* Add a FT_IPv4 to a proto_tree */
2119 proto_tree_add_ipv4(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2120 gint length, guint32 value)
2124 header_field_info *hfinfo;
2126 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2128 DISSECTOR_ASSERT(hfinfo->type == FT_IPv4);
2130 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2131 proto_tree_set_ipv4(new_fi, value);
2137 proto_tree_add_ipv4_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2138 gint start, gint length, guint32 value,
2139 const char *format, ...)
2143 header_field_info *hfinfo;
2145 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2147 pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
2149 TRY_TO_FAKE_THIS_REPR(tree, pi);
2151 va_start(ap, format);
2152 proto_tree_set_representation_value(pi, format, ap);
2159 proto_tree_add_ipv4_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2160 gint start, gint length, guint32 value,
2161 const char *format, ...)
2165 header_field_info *hfinfo;
2167 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2169 pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
2171 TRY_TO_FAKE_THIS_REPR(tree, pi);
2173 va_start(ap, format);
2174 proto_tree_set_representation(pi, format, ap);
2180 /* Set the FT_IPv4 value */
2182 proto_tree_set_ipv4(field_info *fi, guint32 value)
2184 fvalue_set_uinteger(&fi->value, value);
2187 /* Add a FT_IPv6 to a proto_tree */
2189 proto_tree_add_ipv6(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2190 gint length, const guint8* value_ptr)
2194 header_field_info *hfinfo;
2196 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2198 DISSECTOR_ASSERT(hfinfo->type == FT_IPv6);
2200 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2201 proto_tree_set_ipv6(new_fi, value_ptr);
2207 proto_tree_add_ipv6_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2208 gint start, gint length,
2209 const guint8* value_ptr,
2210 const char *format, ...)
2214 header_field_info *hfinfo;
2216 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2218 pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
2220 TRY_TO_FAKE_THIS_REPR(tree, pi);
2222 va_start(ap, format);
2223 proto_tree_set_representation_value(pi, format, ap);
2230 proto_tree_add_ipv6_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2231 gint start, gint length, const guint8* value_ptr,
2232 const char *format, ...)
2236 header_field_info *hfinfo;
2238 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2240 pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
2242 TRY_TO_FAKE_THIS_REPR(tree, pi);
2244 va_start(ap, format);
2245 proto_tree_set_representation(pi, format, ap);
2251 /* Set the FT_IPv6 value */
2253 proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr)
2255 DISSECTOR_ASSERT(value_ptr != NULL);
2256 fvalue_set(&fi->value, (gpointer) value_ptr, FALSE);
2260 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
2262 proto_tree_set_ipv6(fi, tvb_get_ptr(tvb, start, length));
2265 /* Add a FT_GUID to a proto_tree */
2267 proto_tree_add_guid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2268 gint length, const e_guid_t *value_ptr)
2272 header_field_info *hfinfo;
2274 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2276 DISSECTOR_ASSERT(hfinfo->type == FT_GUID);
2278 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2279 proto_tree_set_guid(new_fi, value_ptr);
2285 proto_tree_add_guid_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2286 gint start, gint length,
2287 const e_guid_t *value_ptr,
2288 const char *format, ...)
2292 header_field_info *hfinfo;
2294 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2296 pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
2298 TRY_TO_FAKE_THIS_REPR(tree, pi);
2300 va_start(ap, format);
2301 proto_tree_set_representation_value(pi, format, ap);
2308 proto_tree_add_guid_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2309 gint start, gint length, const e_guid_t *value_ptr,
2310 const char *format, ...)
2314 header_field_info *hfinfo;
2316 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2318 pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
2320 TRY_TO_FAKE_THIS_REPR(tree, pi);
2322 va_start(ap, format);
2323 proto_tree_set_representation(pi, format, ap);
2329 /* Set the FT_GUID value */
2331 proto_tree_set_guid(field_info *fi, const e_guid_t *value_ptr)
2333 DISSECTOR_ASSERT(value_ptr != NULL);
2334 fvalue_set(&fi->value, (gpointer) value_ptr, FALSE);
2338 proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, gint start,
2339 const guint encoding)
2343 tvb_get_guid(tvb, start, &guid, encoding);
2344 proto_tree_set_guid(fi, &guid);
2347 /* Add a FT_OID to a proto_tree */
2349 proto_tree_add_oid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2350 gint length, const guint8* value_ptr)
2354 header_field_info *hfinfo;
2356 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2358 DISSECTOR_ASSERT(hfinfo->type == FT_OID);
2360 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2361 proto_tree_set_oid(new_fi, value_ptr, length);
2367 proto_tree_add_oid_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2368 gint start, gint length,
2369 const guint8* value_ptr,
2370 const char *format, ...)
2374 header_field_info *hfinfo;
2376 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2378 pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
2380 TRY_TO_FAKE_THIS_REPR(tree, pi);
2382 va_start(ap, format);
2383 proto_tree_set_representation_value(pi, format, ap);
2390 proto_tree_add_oid_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2391 gint start, gint length, const guint8* value_ptr,
2392 const char *format, ...)
2396 header_field_info *hfinfo;
2398 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2400 pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
2402 TRY_TO_FAKE_THIS_REPR(tree, pi);
2404 va_start(ap, format);
2405 proto_tree_set_representation(pi, format, ap);
2411 /* Set the FT_OID value */
2413 proto_tree_set_oid(field_info *fi, const guint8* value_ptr, gint length)
2417 DISSECTOR_ASSERT(value_ptr != NULL);
2419 bytes = g_byte_array_new();
2421 g_byte_array_append(bytes, value_ptr, length);
2423 fvalue_set(&fi->value, bytes, TRUE);
2427 proto_tree_set_oid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
2429 proto_tree_set_oid(fi, tvb_get_ptr(tvb, start, length), length);
2433 proto_tree_set_uint64(field_info *fi, guint64 value)
2435 fvalue_set_integer64(&fi->value, value);
2439 * NOTE: to support code written when proto_tree_add_item() took a
2440 * gboolean as its last argument, with FALSE meaning "big-endian"
2441 * and TRUE meaning "little-endian", we treat any non-zero value of
2442 * "encoding" as meaning "little-endian".
2445 proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start,
2446 guint length, const guint encoding)
2449 guint8* b = ep_tvb_memdup(tvb, start, length);
2454 default: DISSECTOR_ASSERT_NOT_REACHED();
2455 case 8: value <<= 8; value += *--b;
2456 case 7: value <<= 8; value += *--b;
2457 case 6: value <<= 8; value += *--b;
2458 case 5: value <<= 8; value += *--b;
2459 case 4: value <<= 8; value += *--b;
2460 case 3: value <<= 8; value += *--b;
2461 case 2: value <<= 8; value += *--b;
2462 case 1: value <<= 8; value += *--b;
2467 default: DISSECTOR_ASSERT_NOT_REACHED();
2468 case 8: value <<= 8; value += *b++;
2469 case 7: value <<= 8; value += *b++;
2470 case 6: value <<= 8; value += *b++;
2471 case 5: value <<= 8; value += *b++;
2472 case 4: value <<= 8; value += *b++;
2473 case 3: value <<= 8; value += *b++;
2474 case 2: value <<= 8; value += *b++;
2475 case 1: value <<= 8; value += *b++;
2480 proto_tree_set_uint64(fi, value);
2483 /* Add a FT_STRING or FT_STRINGZ to a proto_tree. Creates own copy of string,
2484 * and frees it when the proto_tree is destroyed. */
2486 proto_tree_add_string(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2487 gint length, const char* value)
2491 header_field_info *hfinfo;
2493 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2495 DISSECTOR_ASSERT(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ);
2497 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2498 DISSECTOR_ASSERT(length >= 0);
2499 proto_tree_set_string(new_fi, value);
2505 proto_tree_add_unicode_string(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2506 gint length, const char* value)
2508 DISSECTOR_ASSERT(g_utf8_validate(value, -1, NULL));
2509 return proto_tree_add_string_format_value(tree, hfindex, tvb, start, length, value, "%s", value);
2513 proto_tree_add_string_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2514 gint start, gint length, const char* value,
2520 header_field_info *hfinfo;
2522 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2524 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
2526 TRY_TO_FAKE_THIS_REPR(tree, pi);
2528 va_start(ap, format);
2529 proto_tree_set_representation_value(pi, format, ap);
2536 proto_tree_add_string_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2537 gint start, gint length, const char* value,
2538 const char *format, ...)
2542 header_field_info *hfinfo;
2544 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2546 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
2548 TRY_TO_FAKE_THIS_REPR(tree, pi);
2550 va_start(ap, format);
2551 proto_tree_set_representation(pi, format, ap);
2557 /* Appends string data to a FT_STRING or FT_STRINGZ, allowing progressive
2558 * field info update instead of only updating the representation as does
2559 * proto_item_append_text()
2561 /* NOTE: this function will break with the TRY_TO_FAKE_THIS_ITEM()
2562 * speed optimization.
2563 * Currently only WSP use this function so it is not that bad but try to
2564 * avoid using this one if possible.
2565 * IF you must use this function you MUST also disable the
2566 * TRY_TO_FAKE_THIS_ITEM() optimization for your dissector/function
2567 * using proto_item_append_string().
2568 * Do that by faking that the tree is visible by calling
2569 * proto_tree_set_visible(tree, TRUE) (see packet-wsp.c)
2570 * BEFORE you create the item you are later going to use
2571 * proto_item_append_string() on.
2574 proto_item_append_string(proto_item *pi, const char *str)
2577 header_field_info *hfinfo;
2578 gchar *old_str, *new_str;
2585 fi = PITEM_FINFO(pi);
2586 DISSECTOR_ASSERT_HINT(fi, "proto_tree_set_visible(tree, TRUE) should have been called previously");
2588 hfinfo = fi->hfinfo;
2589 if (hfinfo->type == FT_PROTOCOL) {
2590 /* TRY_TO_FAKE_THIS_ITEM() speed optimization: silently skip */
2593 DISSECTOR_ASSERT(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ);
2594 old_str = fvalue_get(&fi->value);
2595 new_str = ep_strdup_printf("%s%s", old_str, str);
2596 fvalue_set(&fi->value, new_str, FALSE);
2599 /* Set the FT_STRING value */
2601 proto_tree_set_string(field_info *fi, const char* value)
2604 fvalue_set(&fi->value, (gpointer) value, FALSE);
2606 fvalue_set(&fi->value, (gpointer) "[ Null ]", FALSE);
2611 proto_tree_set_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length, gint encoding)
2616 length = tvb_ensure_length_remaining(tvb, start);
2619 string = tvb_get_ephemeral_string_enc(tvb, start, length, encoding);
2620 proto_tree_set_string(fi, string);
2624 /* Add a FT_AX25 to a proto_tree */
2626 proto_tree_add_ax25(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2627 const guint8* value)
2631 header_field_info *hfinfo;
2636 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2638 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2639 DISSECTOR_ASSERT(hfinfo->type == FT_AX25);
2641 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2642 proto_tree_set_ax25(new_fi, value);
2647 /* Set the FT_AX25 value */
2649 proto_tree_set_ax25(field_info *fi, const guint8* value)
2651 fvalue_set(&fi->value, (gpointer) value, FALSE);
2655 proto_tree_set_ax25_tvb(field_info *fi, tvbuff_t *tvb, gint start)
2657 proto_tree_set_ax25(fi, tvb_get_ptr(tvb, start, 7));
2661 /* Add a FT_ETHER to a proto_tree */
2663 proto_tree_add_ether(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2664 gint length, const guint8* value)
2668 header_field_info *hfinfo;
2670 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2672 DISSECTOR_ASSERT(hfinfo->type == FT_ETHER);
2674 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2675 proto_tree_set_ether(new_fi, value);
2681 proto_tree_add_ether_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2682 gint start, gint length, const guint8* value,
2683 const char *format, ...)
2687 header_field_info *hfinfo;
2689 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2691 pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
2693 TRY_TO_FAKE_THIS_REPR(tree, pi);
2695 va_start(ap, format);
2696 proto_tree_set_representation_value(pi, format, ap);
2703 proto_tree_add_ether_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2704 gint start, gint length, const guint8* value,
2705 const char *format, ...)
2709 header_field_info *hfinfo;
2711 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2713 pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
2715 TRY_TO_FAKE_THIS_REPR(tree, pi);
2717 va_start(ap, format);
2718 proto_tree_set_representation(pi, format, ap);
2724 /* Set the FT_ETHER value */
2726 proto_tree_set_ether(field_info *fi, const guint8* value)
2728 fvalue_set(&fi->value, (gpointer) value, FALSE);
2732 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start)
2734 proto_tree_set_ether(fi, tvb_get_ptr(tvb, start, FT_ETHER_LEN));
2737 /* Add a FT_BOOLEAN to a proto_tree */
2739 proto_tree_add_boolean(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2740 gint length, guint32 value)
2744 header_field_info *hfinfo;
2746 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2748 DISSECTOR_ASSERT(hfinfo->type == FT_BOOLEAN);
2750 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2751 proto_tree_set_boolean(new_fi, value);
2757 proto_tree_add_boolean_format_value(proto_tree *tree, int hfindex,
2758 tvbuff_t *tvb, gint start, gint length,
2759 guint32 value, const char *format, ...)
2763 header_field_info *hfinfo;
2765 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2767 pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
2769 TRY_TO_FAKE_THIS_REPR(tree, pi);
2771 va_start(ap, format);
2772 proto_tree_set_representation_value(pi, format, ap);
2779 proto_tree_add_boolean_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2780 gint start, gint length, guint32 value,
2781 const char *format, ...)
2785 header_field_info *hfinfo;
2787 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2789 pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
2791 TRY_TO_FAKE_THIS_REPR(tree, pi);
2793 va_start(ap, format);
2794 proto_tree_set_representation(pi, format, ap);
2800 /* Set the FT_BOOLEAN value */
2802 proto_tree_set_boolean(field_info *fi, guint32 value)
2804 proto_tree_set_uint(fi, value);
2807 /* Add a FT_FLOAT to a proto_tree */
2809 proto_tree_add_float(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2810 gint length, float value)
2814 header_field_info *hfinfo;
2816 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2818 DISSECTOR_ASSERT(hfinfo->type == FT_FLOAT);
2820 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2821 proto_tree_set_float(new_fi, value);
2827 proto_tree_add_float_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2828 gint start, gint length, float value,
2829 const char *format, ...)
2833 header_field_info *hfinfo;
2835 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2837 pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
2839 TRY_TO_FAKE_THIS_REPR(tree, pi);
2841 va_start(ap, format);
2842 proto_tree_set_representation_value(pi, format, ap);
2849 proto_tree_add_float_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2850 gint start, gint length, float value,
2851 const char *format, ...)
2855 header_field_info *hfinfo;
2857 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2859 pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
2861 TRY_TO_FAKE_THIS_REPR(tree, pi);
2863 va_start(ap, format);
2864 proto_tree_set_representation(pi, format, ap);
2870 /* Set the FT_FLOAT value */
2872 proto_tree_set_float(field_info *fi, float value)
2874 fvalue_set_floating(&fi->value, value);
2877 /* Add a FT_DOUBLE to a proto_tree */
2879 proto_tree_add_double(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2880 gint length, double value)
2884 header_field_info *hfinfo;
2886 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2888 DISSECTOR_ASSERT(hfinfo->type == FT_DOUBLE);
2890 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2891 proto_tree_set_double(new_fi, value);
2897 proto_tree_add_double_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2898 gint start, gint length, double value,
2899 const char *format, ...)
2903 header_field_info *hfinfo;
2905 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2907 pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
2909 TRY_TO_FAKE_THIS_REPR(tree, pi);
2911 va_start(ap, format);
2912 proto_tree_set_representation_value(pi, format, ap);
2919 proto_tree_add_double_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2920 gint start, gint length, double value,
2921 const char *format, ...)
2925 header_field_info *hfinfo;
2927 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2929 pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
2931 TRY_TO_FAKE_THIS_REPR(tree, pi);
2933 va_start(ap, format);
2934 proto_tree_set_representation(pi, format, ap);
2940 /* Set the FT_DOUBLE value */
2942 proto_tree_set_double(field_info *fi, double value)
2944 fvalue_set_floating(&fi->value, value);
2947 /* Add FT_UINT{8,16,24,32} to a proto_tree */
2949 proto_tree_add_uint(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2950 gint length, guint32 value)
2952 proto_item *pi = NULL;
2954 header_field_info *hfinfo;
2956 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2958 switch (hfinfo->type) {
2964 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length,
2966 proto_tree_set_uint(new_fi, value);
2970 DISSECTOR_ASSERT_NOT_REACHED();
2977 proto_tree_add_uint_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2978 gint start, gint length, guint32 value,
2979 const char *format, ...)
2983 header_field_info *hfinfo;
2985 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2987 pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
2989 TRY_TO_FAKE_THIS_REPR(tree, pi);
2991 va_start(ap, format);
2992 proto_tree_set_representation_value(pi, format, ap);
2999 proto_tree_add_uint_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3000 gint start, gint length, guint32 value,
3001 const char *format, ...)
3005 header_field_info *hfinfo;
3007 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3009 pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
3011 TRY_TO_FAKE_THIS_REPR(tree, pi);
3013 va_start(ap, format);
3014 proto_tree_set_representation(pi, format, ap);
3020 /* Set the FT_UINT{8,16,24,32} value */
3022 proto_tree_set_uint(field_info *fi, guint32 value)
3024 header_field_info *hfinfo;
3027 hfinfo = fi->hfinfo;
3030 if (hfinfo->bitmask) {
3031 /* Mask out irrelevant portions */
3032 integer &= hfinfo->bitmask;
3035 if (hfinfo->bitshift > 0) {
3036 integer >>= hfinfo->bitshift;
3040 fvalue_set_uinteger(&fi->value, integer);
3043 /* Add FT_UINT64 to a proto_tree */
3045 proto_tree_add_uint64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3046 gint length, guint64 value)
3048 proto_item *pi = NULL;
3050 header_field_info *hfinfo;
3052 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3054 DISSECTOR_ASSERT(hfinfo->type == FT_UINT64);
3056 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
3057 proto_tree_set_uint64(new_fi, value);
3063 proto_tree_add_uint64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3064 gint start, gint length, guint64 value,
3065 const char *format, ...)
3069 header_field_info *hfinfo;
3071 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3073 pi = proto_tree_add_uint64(tree, hfindex, tvb, start, length, value);
3075 TRY_TO_FAKE_THIS_REPR(tree, pi);
3077 va_start(ap, format);
3078 proto_tree_set_representation_value(pi, format, ap);
3085 proto_tree_add_uint64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3086 gint start, gint length, guint64 value,
3087 const char *format, ...)
3091 header_field_info *hfinfo;
3093 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3095 pi = proto_tree_add_uint64(tree, hfindex, tvb, start, length, value);
3097 TRY_TO_FAKE_THIS_REPR(tree, pi);
3099 va_start(ap, format);
3100 proto_tree_set_representation(pi, format, ap);
3106 /* Add FT_INT{8,16,24,32} to a proto_tree */
3108 proto_tree_add_int(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3109 gint length, gint32 value)
3111 proto_item *pi = NULL;
3113 header_field_info *hfinfo;
3115 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3117 switch (hfinfo->type) {
3122 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length,
3124 proto_tree_set_int(new_fi, value);
3128 DISSECTOR_ASSERT_NOT_REACHED();
3135 proto_tree_add_int_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3136 gint start, gint length, gint32 value,
3137 const char *format, ...)
3139 proto_item *pi = NULL;
3141 header_field_info *hfinfo;
3143 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3145 pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
3147 TRY_TO_FAKE_THIS_REPR(tree, pi);
3149 va_start(ap, format);
3150 proto_tree_set_representation_value(pi, format, ap);
3157 proto_tree_add_int_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3158 gint start, gint length, gint32 value,
3159 const char *format, ...)
3161 proto_item *pi = NULL;
3163 header_field_info *hfinfo;
3165 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3167 pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
3169 TRY_TO_FAKE_THIS_REPR(tree, pi);
3171 va_start(ap, format);
3172 proto_tree_set_representation(pi, format, ap);
3178 /* Set the FT_INT{8,16,24,32} value */
3180 proto_tree_set_int(field_info *fi, gint32 value)
3182 header_field_info *hfinfo;
3185 hfinfo = fi->hfinfo;
3186 integer = (guint32) value;
3188 if (hfinfo->bitmask) {
3189 /* Mask out irrelevant portions */
3190 integer &= hfinfo->bitmask;
3193 if (hfinfo->bitshift > 0) {
3194 integer >>= hfinfo->bitshift;
3198 fvalue_set_sinteger(&fi->value, integer);
3201 /* Add FT_INT64 to a proto_tree */
3203 proto_tree_add_int64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3204 gint length, gint64 value)
3206 proto_item *pi = NULL;
3208 header_field_info *hfinfo;
3210 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3212 DISSECTOR_ASSERT(hfinfo->type == FT_INT64);
3214 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
3215 proto_tree_set_uint64(new_fi, (guint64)value);
3221 proto_tree_add_int64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3222 gint start, gint length, gint64 value,
3223 const char *format, ...)
3227 header_field_info *hfinfo;
3229 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3231 pi = proto_tree_add_int64(tree, hfindex, tvb, start, length, value);
3233 TRY_TO_FAKE_THIS_REPR(tree, pi);
3235 va_start(ap, format);
3236 proto_tree_set_representation_value(pi, format, ap);
3243 proto_tree_add_int64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3244 gint start, gint length, gint64 value,
3245 const char *format, ...)
3249 header_field_info *hfinfo;
3251 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3253 pi = proto_tree_add_int64(tree, hfindex, tvb, start, length, value);
3255 TRY_TO_FAKE_THIS_REPR(tree, pi);
3257 va_start(ap, format);
3258 proto_tree_set_representation(pi, format, ap);
3263 /* Add a FT_EUI64 to a proto_tree */
3265 proto_tree_add_eui64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3266 gint length, const guint64 value)
3270 header_field_info *hfinfo;
3272 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3274 DISSECTOR_ASSERT(hfinfo->type == FT_EUI64);
3276 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
3277 proto_tree_set_eui64(new_fi, value);
3283 proto_tree_add_eui64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3284 gint start, gint length, const guint64 value,
3285 const char *format, ...)
3289 header_field_info *hfinfo;
3291 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3293 pi = proto_tree_add_eui64(tree, hfindex, tvb, start, length, value);
3295 TRY_TO_FAKE_THIS_REPR(tree, pi);
3297 va_start(ap, format);
3298 proto_tree_set_representation_value(pi, format, ap);
3305 proto_tree_add_eui64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3306 gint start, gint length, const guint64 value,
3307 const char *format, ...)
3311 header_field_info *hfinfo;
3313 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3315 pi = proto_tree_add_eui64(tree, hfindex, tvb, start, length, value);
3317 TRY_TO_FAKE_THIS_REPR(tree, pi);
3319 va_start(ap, format);
3320 proto_tree_set_representation(pi, format, ap);
3326 /* Set the FT_EUI64 value */
3328 proto_tree_set_eui64(field_info *fi, const guint64 value)
3330 fvalue_set_integer64(&fi->value, value);
3333 proto_tree_set_eui64_tvb(field_info *fi, tvbuff_t *tvb, gint start, const guint encoding)
3337 proto_tree_set_eui64(fi, tvb_get_letoh64(tvb, start));
3339 proto_tree_set_eui64(fi, tvb_get_ntoh64(tvb, start));
3343 /* Add a field_info struct to the proto_tree, encapsulating it in a proto_node */
3345 proto_tree_add_node(proto_tree *tree, field_info *fi)
3347 proto_node *pnode, *tnode, *sibling;
3351 * Make sure "tree" is ready to have subtrees under it, by
3352 * checking whether it's been given an ett_ value.
3354 * "PNODE_FINFO(tnode)" may be null; that's the case for the root
3355 * node of the protocol tree. That node is not displayed,
3356 * so it doesn't need an ett_ value to remember whether it
3360 tfi = PNODE_FINFO(tnode);
3361 if (tfi != NULL && (tfi->tree_type < 0 || tfi->tree_type >= num_tree_types)) {
3362 REPORT_DISSECTOR_BUG(ep_strdup_printf("\"%s\" - \"%s\" tfi->tree_type: %u invalid (%s:%u)",
3363 fi->hfinfo->name, fi->hfinfo->abbrev, tfi->tree_type, __FILE__, __LINE__));
3364 /* XXX - is it safe to continue here? */
3367 DISSECTOR_ASSERT(tfi == NULL ||
3368 (tfi->tree_type >= 0 && tfi->tree_type < num_tree_types));
3370 PROTO_NODE_NEW(pnode);
3371 pnode->parent = tnode;
3372 PNODE_FINFO(pnode) = fi;
3373 pnode->tree_data = PTREE_DATA(tree);
3375 if (tnode->last_child != NULL) {
3376 sibling = tnode->last_child;
3377 DISSECTOR_ASSERT(sibling->next == NULL);
3378 sibling->next = pnode;
3380 tnode->first_child = pnode;
3381 tnode->last_child = pnode;
3383 return (proto_item *)pnode;
3387 /* Generic way to allocate field_info and add to proto_tree.
3388 * Sets *pfi to address of newly-allocated field_info struct, if pfi is
3391 proto_tree_add_pi(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3392 gint *length, field_info **pfi)
3401 fi = alloc_field_info(tree, hfindex, tvb, start, length);
3402 pi = proto_tree_add_node(tree, fi);
3404 /* If the proto_tree wants to keep a record of this finfo
3405 * for quick lookup, then record it. */
3406 ptrs = proto_lookup_or_create_interesting_hfids(tree, fi->hfinfo);
3408 g_ptr_array_add(ptrs, fi);
3410 /* Does the caller want to know the fi pointer? */
3419 static header_field_info *
3420 get_hfi_and_length(int hfindex, tvbuff_t *tvb, const gint start, gint *length,
3423 header_field_info *hfinfo;
3424 gint length_remaining;
3427 * We only allow a null tvbuff if the item has a zero length,
3428 * i.e. if there's no data backing it.
3430 DISSECTOR_ASSERT(tvb != NULL || *length == 0);
3432 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
3435 * XXX - in some protocols, there are 32-bit unsigned length
3436 * fields, so lengths in protocol tree and tvbuff routines
3437 * should really be unsigned. We should have, for those
3438 * field types for which "to the end of the tvbuff" makes sense,
3439 * additional routines that take no length argument and
3440 * add fields that run to the end of the tvbuff.
3442 if (*length == -1) {
3444 * For FT_NONE, FT_PROTOCOL, FT_BYTES, and FT_STRING fields,
3445 * a length of -1 means "set the length to what remains in
3448 * The assumption is either that
3450 * 1) the length of the item can only be determined
3451 * by dissection (typically true of items with
3452 * subitems, which are probably FT_NONE or
3457 * 2) if the tvbuff is "short" (either due to a short
3458 * snapshot length or due to lack of reassembly of
3459 * fragments/segments/whatever), we want to display
3460 * what's available in the field (probably FT_BYTES
3461 * or FT_STRING) and then throw an exception later
3465 * 3) the field is defined to be "what's left in the
3468 * so we set the length to what remains in the tvbuff so
3469 * that, if we throw an exception while dissecting, it
3470 * has what is probably the right value.
3472 * For FT_STRINGZ, it means "the string is null-terminated,
3473 * not null-padded; set the length to the actual length
3474 * of the string", and if the tvbuff if short, we just
3475 * throw an exception.
3477 * It's not valid for any other type of field.
3479 switch (hfinfo->type) {
3483 * We allow this to be zero-length - for
3484 * example, an ONC RPC NULL procedure has
3485 * neither arguments nor reply, so the
3486 * payload for that protocol is empty.
3488 * However, if the length is negative, the
3489 * start offset is *past* the byte past the
3490 * end of the tvbuff, so we throw an
3493 *length = tvb_length_remaining(tvb, start);
3496 * Use "tvb_ensure_bytes_exist()"
3497 * to force the appropriate exception
3500 tvb_ensure_bytes_exist(tvb, start, 0);
3502 DISSECTOR_ASSERT(*length >= 0);
3508 *length = tvb_ensure_length_remaining(tvb, start);
3509 DISSECTOR_ASSERT(*length >= 0);
3514 * Leave the length as -1, so our caller knows
3520 DISSECTOR_ASSERT_NOT_REACHED();
3522 *item_length = *length;
3524 *item_length = *length;
3525 if (hfinfo->type == FT_PROTOCOL || hfinfo->type == FT_NONE) {
3527 * These types are for interior nodes of the
3528 * tree, and don't have data associated with
3529 * them; if the length is negative (XXX - see
3530 * above) or goes past the end of the tvbuff,
3531 * cut it short at the end of the tvbuff.
3532 * That way, if this field is selected in
3533 * Wireshark, we don't highlight stuff past
3534 * the end of the data.
3536 /* XXX - what to do, if we don't have a tvb? */
3538 length_remaining = tvb_length_remaining(tvb, start);
3539 if (*item_length < 0 ||
3540 (*item_length > 0 &&
3541 (length_remaining < *item_length)))
3542 *item_length = length_remaining;
3545 if (*item_length < 0) {
3546 THROW(ReportedBoundsError);
3554 new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
3555 const gint start, const gint item_length)
3561 fi->hfinfo = hfinfo;
3563 fi->start += (tvb)?tvb_raw_offset(tvb):0;
3564 fi->length = item_length;
3567 if (!PTREE_DATA(tree)->visible)
3568 FI_SET_FLAG(fi, FI_HIDDEN);
3569 fvalue_init(&fi->value, fi->hfinfo->type);
3572 /* add the data source tvbuff */
3573 fi->ds_tvb = tvb ? tvb_get_ds_tvb(tvb) : NULL;
3575 fi->appendix_start = 0;
3576 fi->appendix_length = 0;
3582 alloc_field_info(proto_tree *tree, int hfindex, tvbuff_t *tvb, const gint start,
3585 header_field_info *hfinfo;
3588 hfinfo = get_hfi_and_length(hfindex, tvb, start, length, &item_length);
3589 return new_field_info(tree, hfinfo, tvb, start, item_length);
3592 /* If the protocol tree is to be visible, set the representation of a
3593 proto_tree entry with the name of the field for the item and with
3594 the value formatted with the supplied printf-style format and
3597 proto_tree_set_representation_value(proto_item *pi, const char *format, va_list ap)
3599 int ret; /*tmp return value */
3600 field_info *fi = PITEM_FINFO(pi);
3601 header_field_info *hf;
3603 DISSECTOR_ASSERT(fi);
3607 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
3608 ITEM_LABEL_NEW(fi->rep);
3609 if (hf->bitmask && (hf->type == FT_BOOLEAN || IS_FT_UINT(hf->type))) {
3613 val = fvalue_get_uinteger(&fi->value);
3614 if (hf->bitshift > 0) {
3615 val <<= hf->bitshift;
3617 decode_bitfield_value(tmpbuf, val, hf->bitmask, hfinfo_bitwidth(hf));
3618 /* put in the hf name */
3619 ret = g_snprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
3620 "%s%s: ", tmpbuf, fi->hfinfo->name);
3622 /* put in the hf name */
3623 ret = g_snprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
3624 "%s: ", fi->hfinfo->name);
3627 /* If possible, Put in the value of the string */
3628 if (ret < ITEM_LABEL_LENGTH) {
3629 ret += g_vsnprintf(fi->rep->representation + ret,
3630 ITEM_LABEL_LENGTH - ret, format, ap);
3632 if (ret >= ITEM_LABEL_LENGTH) {
3633 /* Uh oh, we don't have enough room. Tell the user
3634 * that the field is truncated.
3638 /* Argh, we cannot reuse 'ap' here. So make a copy
3639 * of what we formatted for (re)use below.
3641 oldrep = g_strdup(fi->rep->representation);
3643 g_snprintf(fi->rep->representation,
3652 /* If the protocol tree is to be visible, set the representation of a
3653 proto_tree entry with the representation formatted with the supplied
3654 printf-style format and argument list. */
3656 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap)
3658 int ret; /*tmp return value */
3659 field_info *fi = PITEM_FINFO(pi);
3661 DISSECTOR_ASSERT(fi);
3663 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
3664 ITEM_LABEL_NEW(fi->rep);
3665 ret = g_vsnprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
3667 if (ret >= ITEM_LABEL_LENGTH) {
3668 /* Uh oh, we don't have enough room. Tell the user
3669 * that the field is truncated.
3673 /* Argh, we cannot reuse 'ap' here. So make a copy
3674 * of what we formatted for (re)use below.
3676 oldrep = g_strdup(fi->rep->representation);
3678 g_snprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
3679 "[truncated] %s", oldrep);
3686 protoo_strlcpy(gchar *dest, const gchar *src, gsize dest_size)
3688 gsize res = g_strlcpy(dest, src, dest_size);
3690 if (res > dest_size)
3695 /* -------------------------- */
3697 proto_custom_set(proto_tree* tree, const int field_id, gint occurrence,
3698 gchar *result, gchar *expr, const int size)
3704 struct e_in6_addr *ipv6;
3706 guint32 n_addr; /* network-order IPv4 address */
3708 const true_false_string *tfstring;
3710 int len, prev_len = 0, last, i, offset_r = 0, offset_e = 0;
3712 field_info *finfo = NULL;
3713 header_field_info* hfinfo;
3714 const gchar *abbrev = NULL;
3716 g_assert(field_id >= 0);
3718 hfinfo = proto_registrar_get_nth((guint)field_id);
3720 /* do we need to rewind ? */
3724 if (occurrence < 0) {
3725 /* Search other direction */
3726 while (hfinfo->same_name_prev) {
3727 hfinfo = hfinfo->same_name_prev;
3732 finfos = proto_get_finfo_ptr_array(tree, hfinfo->id);
3734 if (!finfos || !(len = g_ptr_array_len(finfos))) {
3735 if (occurrence < 0) {
3736 hfinfo = hfinfo->same_name_next;
3738 hfinfo = hfinfo->same_name_prev;
3743 /* Are there enough occurrences of the field? */
3744 if (((occurrence - prev_len) > len) || ((occurrence + prev_len) < -len)) {
3745 if (occurrence < 0) {
3746 hfinfo = hfinfo->same_name_next;
3748 hfinfo = hfinfo->same_name_prev;
3754 /* Calculate single index or set outer bounderies */
3755 if (occurrence < 0) {
3756 i = occurrence + len + prev_len;
3758 } else if (occurrence > 0) {
3759 i = occurrence - 1 - prev_len;
3766 prev_len += len; /* Count handled occurrences */
3769 finfo = g_ptr_array_index(finfos, i);
3771 if (offset_r && (offset_r < (size - 2)))
3772 result[offset_r++] = ',';
3774 if (offset_e && (offset_e < (size - 2)))
3775 expr[offset_e++] = ',';
3777 switch (hfinfo->type) {
3779 case FT_NONE: /* Nothing to add */
3780 if (offset_r == 0) {
3782 } else if (result[offset_r-1] == ',') {
3783 result[offset_r-1] = '\0';
3788 /* prevent multiple "yes" entries by setting result directly */
3789 g_strlcpy(result, "Yes", size);
3794 bytes = fvalue_get(&finfo->value);
3795 offset_r += protoo_strlcpy(result+offset_r,
3797 fvalue_length(&finfo->value)),
3801 case FT_ABSOLUTE_TIME:
3802 offset_r += protoo_strlcpy(result+offset_r,
3803 abs_time_to_str(fvalue_get(&finfo->value),
3804 hfinfo->display, TRUE),
3808 case FT_RELATIVE_TIME:
3809 offset_r += protoo_strlcpy(result+offset_r,
3810 rel_time_to_secs_str(fvalue_get(&finfo->value)),
3815 u_integer = fvalue_get_uinteger(&finfo->value);
3816 tfstring = (const true_false_string *)&tfs_true_false;
3817 if (hfinfo->strings) {
3818 tfstring = (const struct true_false_string*) hfinfo->strings;
3820 offset_r += protoo_strlcpy(result+offset_r,
3822 tfstring->true_string :
3823 tfstring->false_string, size-offset_r);
3825 g_snprintf(expr+offset_e, size-offset_e, "%u",
3826 fvalue_get_uinteger(&finfo->value) ? 1 : 0);
3827 offset_e = (int)strlen(expr);
3835 u_integer = fvalue_get_uinteger(&finfo->value);
3836 if ((hfinfo->display & BASE_DISPLAY_E_MASK) == BASE_CUSTOM) {
3837 gchar tmp[ITEM_LABEL_LENGTH];
3838 custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hfinfo->strings;
3840 DISSECTOR_ASSERT(fmtfunc);
3841 fmtfunc(tmp, u_integer);
3842 g_snprintf(result+offset_r, size-offset_r, "%s", tmp);
3843 } else if (hfinfo->strings) {
3844 if (hfinfo->display & BASE_RANGE_STRING) {
3845 g_strlcpy(result+offset_r,
3846 rval_to_str(u_integer, hfinfo->strings, "%u"),
3848 } else if (hfinfo->display & BASE_EXT_STRING) {
3849 g_strlcpy(result+offset_r,
3850 val_to_str_ext(u_integer,
3851 (value_string_ext *)(hfinfo->strings),
3852 "%u"), size-offset_r);
3854 g_strlcpy(result+offset_r,
3855 val_to_str(u_integer, cVALS(hfinfo->strings), "%u"),
3858 } else if (IS_BASE_DUAL(hfinfo->display)) {
3859 g_snprintf(result+offset_r, size-offset_r,
3860 hfinfo_uint_value_format(hfinfo), u_integer, u_integer);
3862 g_snprintf(result+offset_r, size-offset_r,
3863 hfinfo_uint_value_format(hfinfo), u_integer);
3866 if (hfinfo->strings && (hfinfo->display & BASE_DISPLAY_E_MASK) == BASE_NONE) {
3867 g_snprintf(expr+offset_e, size-offset_e,
3868 "\"%s\"", result+offset_r);
3870 g_snprintf(expr+offset_e, size-offset_e,
3871 hfinfo_numeric_value_format(hfinfo),
3872 fvalue_get_uinteger(&finfo->value));
3875 offset_r = (int)strlen(result);
3876 offset_e = (int)strlen(expr);
3880 /* XXX: Should handle BASE_CUSTOM ? */
3881 g_snprintf(result+offset_r, size-offset_r,
3882 "%" G_GINT64_MODIFIER "d",
3883 fvalue_get_integer64(&finfo->value));
3884 offset_r = (int)strlen(result);
3887 g_snprintf(result+offset_r, size-offset_r,
3888 /* XXX: Should handle BASE_CUSTOM ? */
3889 "%" G_GINT64_MODIFIER "u",
3890 fvalue_get_integer64(&finfo->value));
3891 offset_r = (int)strlen(result);
3894 offset_r += protoo_strlcpy(result+offset_r,
3895 eui64_to_str(fvalue_get_integer64(&finfo->value)),
3898 /* XXX - make these just FT_INT? */
3903 integer = fvalue_get_sinteger(&finfo->value);
3904 if ((hfinfo->display & BASE_DISPLAY_E_MASK) == BASE_CUSTOM) {
3905 gchar tmp[ITEM_LABEL_LENGTH];
3906 custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hfinfo->strings;
3908 DISSECTOR_ASSERT(fmtfunc);
3909 fmtfunc(tmp, integer);
3910 g_snprintf(result+offset_r, size-offset_r, "%s", tmp);
3911 } else if (hfinfo->strings) {
3912 if (hfinfo->display & BASE_RANGE_STRING) {
3913 g_strlcpy(result+offset_r,
3914 rval_to_str(integer, hfinfo->strings, "%d"),
3916 } else if (hfinfo->display & BASE_EXT_STRING) {
3917 g_strlcpy(result+offset_r,
3918 val_to_str_ext(integer,
3919 (value_string_ext *)(hfinfo->strings),
3923 g_strlcpy(result+offset_r,
3924 val_to_str(integer, cVALS(hfinfo->strings), "%d"),
3927 } else if (IS_BASE_DUAL(hfinfo->display)) {
3928 g_snprintf(result+offset_r, size-offset_r,
3929 hfinfo_int_value_format(hfinfo), integer, integer);
3931 g_snprintf(result+offset_r, size-offset_r,
3932 hfinfo_int_value_format(hfinfo), integer);
3935 if (hfinfo->strings && (hfinfo->display & BASE_DISPLAY_E_MASK) == BASE_NONE) {
3936 g_snprintf(expr+offset_e, size-offset_e, "\"%s\"", result+offset_r);
3938 g_snprintf(expr+offset_e, size-offset_e,
3939 hfinfo_numeric_value_format(hfinfo),
3940 fvalue_get_sinteger(&finfo->value));
3943 offset_r = (int)strlen(result);
3944 offset_e = (int)strlen(expr);
3948 ipv4 = fvalue_get(&finfo->value);
3949 n_addr = ipv4_get_net_order_addr(ipv4);
3950 offset_r += protoo_strlcpy(result+offset_r,
3951 ip_to_str((guint8 *)&n_addr),
3956 ipv6 = fvalue_get(&finfo->value);
3957 SET_ADDRESS (&addr, AT_IPv6, sizeof(struct e_in6_addr), ipv6);
3958 address_to_str_buf(&addr, result+offset_r, size-offset_r);
3959 offset_r = (int)strlen(result);
3963 offset_r += protoo_strlcpy(result+offset_r,
3964 bytes_to_str_punct(fvalue_get(&finfo->value),
3970 offset_r += protoo_strlcpy(result+offset_r,
3971 guid_to_str((e_guid_t *)fvalue_get(&finfo->value)),
3976 bytes = fvalue_get(&finfo->value);
3977 offset_r += protoo_strlcpy(result+offset_r,
3978 oid_resolved_from_encoded(bytes,
3979 fvalue_length(&finfo->value)),
3981 offset_e += protoo_strlcpy(expr+offset_e,
3982 oid_encoded2string(bytes, fvalue_length(&finfo->value)),
3987 g_snprintf(result+offset_r, size-offset_r,
3988 "%." STRINGIFY(FLT_DIG) "g", fvalue_get_floating(&finfo->value));
3989 offset_r = (int)strlen(result);
3993 g_snprintf(result+offset_r, size-offset_r,
3994 "%." STRINGIFY(DBL_DIG) "g", fvalue_get_floating(&finfo->value));
3995 offset_r = (int)strlen(result);
4000 case FT_UINT_STRING:
4001 bytes = fvalue_get(&finfo->value);
4002 offset_r += protoo_strlcpy(result+offset_r,
4003 format_text(bytes, strlen(bytes)),
4007 case FT_IPXNET: /*XXX really No column custom ?*/
4010 g_error("hfinfo->type %d (%s) not handled\n",
4012 ftype_name(hfinfo->type));
4013 DISSECTOR_ASSERT_NOT_REACHED();
4019 switch (hfinfo->type) {
4032 /* for these types, "expr" is filled in the loop above */
4036 /* for all others, just copy "result" to "expr" */
4037 g_strlcpy(expr, result, size);
4042 /* Store abbrev for return value */
4043 abbrev = hfinfo->abbrev;
4046 if (occurrence == 0) {
4047 /* Fetch next hfinfo with same name (abbrev) */
4048 hfinfo = hfinfo->same_name_prev;
4054 return abbrev ? abbrev : "";
4058 /* Set text of proto_item after having already been created. */
4060 proto_item_set_text(proto_item *pi, const char *format, ...)
4062 field_info *fi = NULL;
4069 fi = PITEM_FINFO(pi);
4074 ITEM_LABEL_FREE(fi->rep);
4077 va_start(ap, format);
4078 proto_tree_set_representation(pi, format, ap);
4082 /* Append to text of proto_item after having already been created. */
4084 proto_item_append_text(proto_item *pi, const char *format, ...)
4086 field_info *fi = NULL;
4094 fi = PITEM_FINFO(pi);
4099 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
4101 * If we don't already have a representation,
4102 * generate the default representation.
4104 if (fi->rep == NULL) {
4105 ITEM_LABEL_NEW(fi->rep);
4106 proto_item_fill_label(fi, fi->rep->representation);
4109 curlen = strlen(fi->rep->representation);
4110 if (ITEM_LABEL_LENGTH > curlen) {
4111 va_start(ap, format);
4112 g_vsnprintf(fi->rep->representation + curlen,
4113 ITEM_LABEL_LENGTH - (gulong) curlen, format, ap);
4119 /* Prepend to text of proto_item after having already been created. */
4121 proto_item_prepend_text(proto_item *pi, const char *format, ...)
4123 field_info *fi = NULL;
4124 char representation[ITEM_LABEL_LENGTH];
4131 fi = PITEM_FINFO(pi);
4136 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
4138 * If we don't already have a representation,
4139 * generate the default representation.
4141 if (fi->rep == NULL) {
4142 ITEM_LABEL_NEW(fi->rep);
4143 proto_item_fill_label(fi, fi->rep->representation);
4146 g_strlcpy(representation, fi->rep->representation, ITEM_LABEL_LENGTH);
4147 va_start(ap, format);
4148 g_vsnprintf(fi->rep->representation,
4149 ITEM_LABEL_LENGTH, format, ap);
4151 g_strlcat(fi->rep->representation, representation, ITEM_LABEL_LENGTH);
4156 proto_item_set_len(proto_item *pi, const gint length)
4163 fi = PITEM_FINFO(pi);
4167 DISSECTOR_ASSERT(length >= 0);
4168 fi->length = length;
4171 * You cannot just make the "len" field of a GByteArray
4172 * larger, if there's no data to back that length;
4173 * you can only make it smaller.
4175 if (fi->value.ftype->ftype == FT_BYTES && length <= (gint)fi->value.value.bytes->len)
4176 fi->value.value.bytes->len = length;
4180 * Sets the length of the item based on its start and on the specified
4181 * offset, which is the offset past the end of the item; as the start
4182 * in the item is relative to the beginning of the data source tvbuff,
4183 * we need to pass in a tvbuff - the end offset is relative to the beginning
4187 proto_item_set_end(proto_item *pi, tvbuff_t *tvb, gint end)
4194 fi = PITEM_FINFO(pi);
4198 end += tvb_raw_offset(tvb);
4199 DISSECTOR_ASSERT(end >= fi->start);
4200 fi->length = end - fi->start;
4204 proto_item_get_len(const proto_item *pi)
4206 field_info *fi = PITEM_FINFO(pi);
4207 return fi ? fi->length : -1;
4211 /** clear flags according to the mask and set new flag values */
4212 #define FI_REPLACE_FLAGS(fi, mask, flags_in) { \
4213 (fi->flags = (fi)->flags & ~(mask)); \
4214 (fi->flags = (fi)->flags | (flags_in)); \
4218 proto_item_set_expert_flags(proto_item *pi, const int group, const guint severity)
4220 if (pi == NULL || PITEM_FINFO(pi) == NULL)
4223 /* only change things if severity is worse or at least equal than before */
4224 if (severity >= FI_GET_FLAG(PITEM_FINFO(pi), PI_SEVERITY_MASK)) {
4225 FI_REPLACE_FLAGS(PITEM_FINFO(pi), PI_GROUP_MASK, group);
4226 FI_REPLACE_FLAGS(PITEM_FINFO(pi), PI_SEVERITY_MASK, severity);
4235 proto_tree_create_root(packet_info *pinfo)
4239 /* Initialize the proto_node */
4240 PROTO_NODE_NEW(pnode);
4241 pnode->parent = NULL;
4242 PNODE_FINFO(pnode) = NULL;
4243 pnode->tree_data = g_new(tree_data_t, 1);
4245 /* Make sure we can access pinfo everywhere */
4246 pnode->tree_data->pinfo = pinfo;
4248 /* Don't initialize the tree_data_t. Wait until we know we need it */
4249 pnode->tree_data->interesting_hfids = NULL;
4251 /* Set the default to FALSE so it's easier to
4252 * find errors; if we expect to see the protocol tree
4253 * but for some reason the default 'visible' is not
4254 * changed, then we'll find out very quickly. */
4255 pnode->tree_data->visible = FALSE;
4257 /* Make sure that we fake protocols (if possible) */
4258 pnode->tree_data->fake_protocols = TRUE;
4260 /* Keep track of the number of children */
4261 pnode->tree_data->count = 0;
4263 pnode->tree_data->fi_tmp = NULL;
4265 return (proto_tree *)pnode;
4269 /* "prime" a proto_tree with a single hfid that a dfilter
4270 * is interested in. */
4272 proto_tree_prime_hfid(proto_tree *tree _U_, const gint hfid)
4274 header_field_info *hfinfo;
4276 PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
4277 /* this field is referenced by a filter so increase the refcount.
4278 also increase the refcount for the parent, i.e the protocol.
4280 hfinfo->ref_type = HF_REF_TYPE_DIRECT;
4281 /* only increase the refcount if there is a parent.
4282 if this is a protocol and not a field then parent will be -1
4283 and there is no parent to add any refcounting for.
4285 if (hfinfo->parent != -1) {
4286 header_field_info *parent_hfinfo;
4287 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
4289 /* Mark parent as indirectly referenced unless it is already directly
4290 * referenced, i.e. the user has specified the parent in a filter.
4292 if (parent_hfinfo->ref_type != HF_REF_TYPE_DIRECT)
4293 parent_hfinfo->ref_type = HF_REF_TYPE_INDIRECT;
4298 proto_item_add_subtree(proto_item *pi, const gint idx) {
4304 DISSECTOR_ASSERT(idx >= 0 && idx < num_tree_types);
4306 fi = PITEM_FINFO(pi);
4308 return (proto_tree *)pi;
4310 fi->tree_type = idx;
4312 return (proto_tree *)pi;
4316 proto_item_get_subtree(const proto_item *pi) {
4321 fi = PITEM_FINFO(pi);
4322 if ( (!fi) || (fi->tree_type == -1) )
4324 return (proto_tree *)pi;
4328 proto_item_get_parent(const proto_item *ti) {
4335 proto_item_get_parent_nth(proto_item *ti, int gen) {
4348 proto_tree_get_parent(const proto_tree *tree) {
4351 return (proto_item *)tree;
4355 proto_tree_get_root(proto_tree *tree) {
4358 while (tree->parent) {
4359 tree = tree->parent;
4365 proto_tree_move_item(proto_tree *tree, proto_item *fixed_item,
4366 proto_item *item_to_move)
4369 /* Revert part of: http://anonsvn.wireshark.org/viewvc?view=rev&revision=32443
4370 * See https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=5500
4372 /* This function doesn't generate any values. It only reorganizes the prococol tree
4373 * so we can bail out immediately if it isn't visible. */
4374 if (!tree || !PTREE_DATA(tree)->visible)
4377 DISSECTOR_ASSERT(item_to_move->parent == tree);
4378 DISSECTOR_ASSERT(fixed_item->parent == tree);
4380 /*** cut item_to_move out ***/
4382 /* is item_to_move the first? */
4383 if (tree->first_child == item_to_move) {
4384 /* simply change first child to next */
4385 tree->first_child = item_to_move->next;
4387 DISSECTOR_ASSERT(tree->last_child != item_to_move);
4389 proto_item *curr_item;
4390 /* find previous and change it's next */
4391 for(curr_item = tree->first_child; curr_item != NULL; curr_item = curr_item->next) {
4392 if (curr_item->next == item_to_move) {
4397 DISSECTOR_ASSERT(curr_item);
4399 curr_item->next = item_to_move->next;
4401 /* fix last_child if required */
4402 if (tree->last_child == item_to_move) {
4403 tree->last_child = curr_item;
4407 /*** insert to_move after fixed ***/
4408 item_to_move->next = fixed_item->next;
4409 fixed_item->next = item_to_move;
4410 if (tree->last_child == fixed_item) {
4411 tree->last_child = item_to_move;
4416 proto_tree_set_appendix(proto_tree *tree, tvbuff_t *tvb, gint start,
4424 fi = PTREE_FINFO(tree);
4428 start += tvb_raw_offset(tvb);
4429 DISSECTOR_ASSERT(start >= 0);
4430 DISSECTOR_ASSERT(length >= 0);
4432 fi->appendix_start = start;
4433 fi->appendix_length = length;
4437 proto_register_protocol(const char *name, const char *short_name,
4438 const char *filter_name)
4440 protocol_t *protocol;
4441 header_field_info *hfinfo;
4443 char *existing_name;
4447 gboolean found_invalid;
4450 * Make sure there's not already a protocol with any of those
4451 * names. Crash if there is, as that's an error in the code
4452 * or an inappropriate plugin.
4453 * This situation has to be fixed to not register more than one
4454 * protocol with the same name.
4456 * This is done by reducing the number of strcmp (and alike) calls
4457 * as much as possible, as this significally slows down startup time.
4459 * Drawback: As a hash value is used to reduce insert time,
4460 * this might lead to a hash collision.
4461 * However, although we have somewhat over 1000 protocols, we're using
4462 * a 32 bit int so this is very, very unlikely.
4465 key = g_malloc (sizeof(gint));
4466 *key = wrs_str_hash(name);
4468 existing_name = g_hash_table_lookup(proto_names, key);
4469 if (existing_name != NULL) {
4470 /* g_error will terminate the program */
4471 g_error("Duplicate protocol name \"%s\"!"
4472 " This might be caused by an inappropriate plugin or a development error.", name);
4474 g_hash_table_insert(proto_names, key, (gpointer)name);
4476 existing_name = g_hash_table_lookup(proto_short_names, (gpointer)short_name);
4477 if (existing_name != NULL) {
4478 g_error("Duplicate protocol short_name \"%s\"!"
4479 " This might be caused by an inappropriate plugin or a development error.", short_name);
4481 g_hash_table_insert(proto_short_names, (gpointer)short_name, (gpointer)short_name);
4483 found_invalid = FALSE;
4484 for (i = 0; filter_name[i]; i++) {
4486 if (!(islower(c) || isdigit(c) || c == '-' || c == '_' || c == '.')) {
4487 found_invalid = TRUE;
4490 if (found_invalid) {
4491 g_error("Protocol filter name \"%s\" has one or more invalid characters."
4492 " Allowed are lower characters, digits, '-', '_' and '.'."
4493 " This might be caused by an inappropriate plugin or a development error.", filter_name);
4495 existing_name = g_hash_table_lookup(proto_filter_names, (gpointer)filter_name);
4496 if (existing_name != NULL) {
4497 g_error("Duplicate protocol filter_name \"%s\"!"
4498 " This might be caused by an inappropriate plugin or a development error.", filter_name);
4500 g_hash_table_insert(proto_filter_names, (gpointer)filter_name, (gpointer)filter_name);
4502 /* Add this protocol to the list of known protocols; the list
4503 is sorted by protocol short name. */
4504 protocol = g_new(protocol_t, 1);
4505 protocol->name = name;
4506 protocol->short_name = short_name;
4507 protocol->filter_name = filter_name;
4508 protocol->fields = NULL;
4509 protocol->is_enabled = TRUE; /* protocol is enabled by default */
4510 protocol->can_toggle = TRUE;
4511 protocol->is_private = FALSE;
4512 /* list will be sorted later by name, when all protocols completed registering */
4513 protocols = g_list_prepend(protocols, protocol);
4515 /* Here we allocate a new header_field_info struct */
4516 hfinfo = g_slice_new(header_field_info);
4517 hfinfo->name = name;
4518 hfinfo->abbrev = filter_name;
4519 hfinfo->type = FT_PROTOCOL;
4520 hfinfo->display = BASE_NONE;
4521 hfinfo->strings = protocol;
4522 hfinfo->bitmask = 0;
4523 hfinfo->bitshift = 0;
4524 hfinfo->ref_type = HF_REF_TYPE_NONE;
4525 hfinfo->blurb = NULL;
4526 hfinfo->parent = -1; /* this field differentiates protos and fields */
4528 proto_id = proto_register_field_init(hfinfo, hfinfo->parent);
4529 protocol->proto_id = proto_id;
4534 proto_mark_private(const int proto_id)
4536 protocol_t *protocol = find_protocol_by_id(proto_id);
4538 protocol->is_private = TRUE;
4542 proto_is_private(const int proto_id)
4544 protocol_t *protocol = find_protocol_by_id(proto_id);
4546 return protocol->is_private;
4552 * Routines to use to iterate over the protocols.
4553 * The argument passed to the iterator routines is an opaque cookie to
4554 * their callers; it's the GList pointer for the current element in
4556 * The ID of the protocol is returned, or -1 if there is no protocol.
4559 proto_get_first_protocol(void **cookie)
4561 protocol_t *protocol;
4563 if (protocols == NULL)
4565 *cookie = protocols;
4566 protocol = protocols->data;
4567 return protocol->proto_id;
4571 proto_get_data_protocol(void *cookie)
4573 GList *list_item = cookie;
4575 protocol_t *protocol = list_item->data;
4576 return protocol->proto_id;
4580 proto_get_next_protocol(void **cookie)
4582 GList *list_item = *cookie;
4583 protocol_t *protocol;
4585 list_item = g_list_next(list_item);
4586 if (list_item == NULL)
4588 *cookie = list_item;
4589 protocol = list_item->data;
4590 return protocol->proto_id;
4594 proto_get_first_protocol_field(const int proto_id, void **cookie)
4596 protocol_t *protocol = find_protocol_by_id(proto_id);
4597 hf_register_info *ptr;
4599 if ((protocol == NULL) || (protocol->fields == NULL))
4602 *cookie = protocol->fields;
4603 ptr = protocol->fields->data;
4604 return &ptr->hfinfo;
4608 proto_get_next_protocol_field(void **cookie)
4610 GList *list_item = *cookie;
4611 hf_register_info *ptr;
4613 list_item = g_list_next(list_item);
4614 if (list_item == NULL)
4617 *cookie = list_item;
4618 ptr = list_item->data;
4619 return &ptr->hfinfo;
4623 find_protocol_by_id(const int proto_id)
4625 header_field_info *hfinfo;
4630 PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
4631 DISSECTOR_ASSERT(hfinfo->type == FT_PROTOCOL);
4632 return (protocol_t *)hfinfo->strings;
4635 static gint compare_filter_name(gconstpointer proto_arg,
4636 gconstpointer filter_name)
4638 const protocol_t *protocol = proto_arg;
4639 const gchar *f_name = filter_name;
4641 return (strcmp(protocol->filter_name, f_name));
4645 proto_get_id(const protocol_t *protocol)
4647 return protocol->proto_id;
4650 int proto_get_id_by_filter_name(const gchar* filter_name)
4653 protocol_t *protocol;
4656 fprintf(stderr, "No filter name present");
4657 DISSECTOR_ASSERT(filter_name);
4660 list_entry = g_list_find_custom(protocols, filter_name,
4661 compare_filter_name);
4663 if (list_entry == NULL)
4665 protocol = list_entry->data;
4666 return protocol->proto_id;
4670 proto_get_protocol_name(const int proto_id)
4672 protocol_t *protocol;
4674 protocol = find_protocol_by_id(proto_id);
4676 if (protocol == NULL)
4678 return protocol->name;
4682 proto_get_protocol_short_name(const protocol_t *protocol)
4684 if (protocol == NULL)
4686 return protocol->short_name;
4690 proto_get_protocol_long_name(const protocol_t *protocol)
4692 if (protocol == NULL)
4694 return protocol->name;
4698 proto_get_protocol_filter_name(const int proto_id)
4700 protocol_t *protocol;
4702 protocol = find_protocol_by_id(proto_id);
4703 if (protocol == NULL)
4705 return protocol->filter_name;
4709 proto_is_protocol_enabled(const protocol_t *protocol)
4711 return protocol->is_enabled;
4715 proto_can_toggle_protocol(const int proto_id)
4717 protocol_t *protocol;
4719 protocol = find_protocol_by_id(proto_id);
4720 return protocol->can_toggle;
4724 proto_set_decoding(const int proto_id, const gboolean enabled)
4726 protocol_t *protocol;
4728 protocol = find_protocol_by_id(proto_id);
4729 DISSECTOR_ASSERT(protocol->can_toggle);
4730 protocol->is_enabled = enabled;
4734 proto_enable_all(void)
4736 protocol_t *protocol;
4737 GList *list_item = protocols;
4739 if (protocols == NULL)
4743 protocol = list_item->data;
4744 if (protocol->can_toggle)
4745 protocol->is_enabled = TRUE;
4746 list_item = g_list_next(list_item);
4751 proto_set_cant_toggle(const int proto_id)
4753 protocol_t *protocol;
4755 protocol = find_protocol_by_id(proto_id);
4756 protocol->can_toggle = FALSE;
4759 /* for use with static arrays only, since we don't allocate our own copies
4760 of the header_field_info struct contained within the hf_register_info struct */
4762 proto_register_field_array(const int parent, hf_register_info *hf, const int num_records)
4765 hf_register_info *ptr = hf;
4768 proto = find_protocol_by_id(parent);
4769 for (i = 0; i < num_records; i++, ptr++) {
4771 * Make sure we haven't registered this yet.
4772 * Most fields have variables associated with them
4773 * that are initialized to -1; some have array elements,
4774 * or possibly uninitialized variables, so we also allow
4775 * 0 (which is unlikely to be the field ID we get back
4776 * from "proto_register_field_init()").
4778 if (*ptr->p_id != -1 && *ptr->p_id != 0) {
4780 "Duplicate field detected in call to proto_register_field_array: %s is already registered\n",
4781 ptr->hfinfo.abbrev);
4785 if (proto != NULL) {
4786 if (proto->fields == NULL) {
4787 proto->fields = g_list_append(NULL, ptr);
4788 proto->last_field = proto->fields;
4791 g_list_append(proto->last_field, ptr)->next;
4794 field_id = proto_register_field_init(&ptr->hfinfo, parent);
4795 *ptr->p_id = field_id;
4799 /* unregister already registered fields */
4801 proto_unregister_field (const int parent, gint hf_id)
4803 hf_register_info *hf;
4807 if (hf_id == -1 || hf_id == 0)
4810 proto = find_protocol_by_id (parent);
4811 if (!proto || !proto->fields) {
4815 for (field = g_list_first (proto->fields); field; field = g_list_next (field)) {
4817 if (*hf->p_id == hf_id) {
4818 /* Found the hf_id in this protocol */
4819 g_tree_steal (gpa_name_tree, hf->hfinfo.abbrev);
4820 proto->fields = g_list_remove_link (proto->fields, field);
4821 proto->last_field = g_list_last (proto->fields);
4827 /* chars allowed in field abbrev */
4829 const guchar fld_abbrev_chars[256] = {
4830 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00-0x0F */
4831 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10-0x1F */
4832 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, /* 0x20-0x2F '-', '.' */
4833 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 0x30-0x3F '0'-'9' */
4834 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x40-0x4F 'A'-'O' */
4835 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 0x50-0x5F 'P'-'Z', '_' */
4836 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x60-0x6F 'a'-'o' */
4837 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 0x70-0x7F 'p'-'z' */
4838 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80-0x8F */
4839 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90-0x9F */
4840 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xA0-0xAF */
4841 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xB0-0xBF */
4842 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xC0-0xCF */
4843 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xD0-0xDF */
4844 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xE0-0xEF */
4845 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xF0-0xFF */
4848 static const value_string hf_types[] = {
4849 { FT_NONE, "FT_NONE" },
4850 { FT_PROTOCOL, "FT_PROTOCOL" },
4851 { FT_BOOLEAN, "FT_BOOLEAN" },
4852 { FT_UINT8, "FT_UINT8" },
4853 { FT_UINT16, "FT_UINT16" },
4854 { FT_UINT24, "FT_UINT24" },
4855 { FT_UINT32, "FT_UINT32" },
4856 { FT_UINT64, "FT_UINT64" },
4857 { FT_INT8, "FT_INT8" },
4858 { FT_INT16, "FT_INT16" },
4859 { FT_INT24, "FT_INT24" },
4860 { FT_INT32, "FT_INT32" },
4861 { FT_INT64, "FT_INT64" },
4862 { FT_EUI64, "FT_EUI64" },
4863 { FT_FLOAT, "FT_FLOAT" },
4864 { FT_DOUBLE, "FT_DOUBLE" },
4865 { FT_ABSOLUTE_TIME, "FT_ABSOLUTE_TIME" },
4866 { FT_RELATIVE_TIME, "FT_RELATIVE_TIME" },
4867 { FT_STRING, "FT_STRING" },
4868 { FT_STRINGZ, "FT_STRINGZ" },
4869 { FT_UINT_STRING, "FT_UINT_STRING" },
4870 { FT_ETHER, "FT_ETHER" },
4871 { FT_BYTES, "FT_BYTES" },
4872 { FT_UINT_BYTES, "FT_UINT_BYTES" },
4873 { FT_IPv4, "FT_IPv4" },
4874 { FT_IPv6, "FT_IPv6" },
4875 { FT_IPXNET, "FT_IPXNET" },
4876 { FT_FRAMENUM, "FT_FRAMENUM" },
4877 { FT_PCRE, "FT_PCR" },
4878 { FT_GUID, "FT_GUID" },
4879 { FT_OID, "FT_OID" },
4882 static const value_string hf_display[] = {
4883 { BASE_NONE, "BASE_NONE" },
4884 { BASE_DEC, "BASE_DEC" },
4885 { BASE_HEX, "BASE_HEX" },
4886 { BASE_OCT, "BASE_OCT" },
4887 { BASE_DEC_HEX, "BASE_DEC_HEX" },
4888 { BASE_HEX_DEC, "BASE_HEX_DEC" },
4889 { BASE_CUSTOM, "BASE_CUSTOM" },
4890 { BASE_NONE|BASE_RANGE_STRING, "BASE_NONE|BASE_RANGE_STRING" },
4891 { BASE_DEC|BASE_RANGE_STRING, "BASE_DEC|BASE_RANGE_STRING" },
4892 { BASE_HEX|BASE_RANGE_STRING, "BASE_HEX|BASE_RANGE_STRING" },
4893 { BASE_OCT|BASE_RANGE_STRING, "BASE_OCT|BASE_RANGE_STRING" },
4894 { BASE_DEC_HEX|BASE_RANGE_STRING, "BASE_DEC_HEX|BASE_RANGE_STRING" },
4895 { BASE_HEX_DEC|BASE_RANGE_STRING, "BASE_HEX_DEC|BASE_RANGE_STRING" },
4896 { BASE_CUSTOM|BASE_RANGE_STRING, "BASE_CUSTOM|BASE_RANGE_STRING" },
4897 { ABSOLUTE_TIME_LOCAL, "ABSOLUTE_TIME_LOCAL" },
4898 { ABSOLUTE_TIME_UTC, "ABSOLUTE_TIME_UTC" },
4899 { ABSOLUTE_TIME_DOY_UTC, "ABSOLUTE_TIME_DOY_UTC" },
4902 /* temporary function containing assert part for easier profiling */
4904 tmp_fld_check_assert(header_field_info *hfinfo)
4907 /* The field must have a name (with length > 0) */
4908 if (!hfinfo->name || !hfinfo->name[0]) {
4910 /* Try to identify the field */
4911 g_error("Field (abbrev='%s') does not have a name\n",
4915 g_error("Field does not have a name (nor an abbreviation)\n");
4918 /* fields with an empty string for an abbreviation aren't filterable */
4919 if (!hfinfo->abbrev || !hfinfo->abbrev[0])
4920 g_error("Field '%s' does not have an abbreviation\n", hfinfo->name);
4922 /* These types of fields are allowed to have value_strings,
4923 * true_false_strings or a protocol_t struct
4925 if (hfinfo->strings != NULL && !(
4926 (hfinfo->type == FT_UINT8) ||
4927 (hfinfo->type == FT_UINT16) ||
4928 (hfinfo->type == FT_UINT24) ||
4929 (hfinfo->type == FT_UINT32) ||
4930 (hfinfo->type == FT_INT8) ||
4931 (hfinfo->type == FT_INT16) ||
4932 (hfinfo->type == FT_INT24) ||
4933 (hfinfo->type == FT_INT32) ||
4934 (hfinfo->type == FT_BOOLEAN) ||
4935 (hfinfo->type == FT_PROTOCOL) ||
4936 (hfinfo->type == FT_FRAMENUM) ))
4937 g_error("Field '%s' (%s) has a 'strings' value but is of type %s"
4938 " (which is not allowed to have strings)\n",
4939 hfinfo->name, hfinfo->abbrev,
4940 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"));
4942 /* TODO: This check may slow down startup, and output quite a few warnings.
4943 It would be good to be able to enable this (and possibly other checks?)
4944 in non-release builds. */
4946 /* Check for duplicate value_string values.
4947 There are lots that have the same value *and* string, so for now only
4948 report those that have same value but different string. */
4949 if ((hfinfo->strings != NULL) &&
4950 !(hfinfo->display & BASE_RANGE_STRING) &&
4951 !((hfinfo->display & BASE_DISPLAY_E_MASK) == BASE_CUSTOM) &&
4953 (hfinfo->type == FT_UINT8) ||
4954 (hfinfo->type == FT_UINT16) ||
4955 (hfinfo->type == FT_UINT24) ||
4956 (hfinfo->type == FT_UINT32) ||
4957 (hfinfo->type == FT_INT8) ||
4958 (hfinfo->type == FT_INT16) ||
4959 (hfinfo->type == FT_INT24) ||
4960 (hfinfo->type == FT_INT32) ||
4961 (hfinfo->type == FT_FRAMENUM) )) {
4964 const value_string *start_values;
4965 const value_string *current;
4967 if (hfinfo->display & BASE_EXT_STRING)
4968 start_values = VALUE_STRING_EXT_VS_P(((const value_string_ext*)hfinfo->strings));
4970 start_values = (const value_string*)hfinfo->strings;
4971 current = start_values;
4973 for (n=0; current; n++, current++) {
4974 /* Drop out if we reached the end. */
4975 if ((current->value == 0) && (current->strptr == NULL)) {
4979 /* Check value against all previous */
4980 for (m=0; m < n; m++) {
4981 /* There are lots of duplicates with the same string,
4982 so only report if different... */
4983 if ((start_values[m].value == current->value) &&
4984 (strcmp(start_values[m].strptr, current->strptr) != 0)) {
4985 g_warning("Field '%s' (%s) has a conflicting entry in its"
4986 " value_string: %u is at indices %u (%s) and %u (%s))\n",
4987 hfinfo->name, hfinfo->abbrev,
4988 current->value, m, start_values[m].strptr, n, current->strptr);
4996 switch (hfinfo->type) {
5003 /* Hexadecimal and octal are, in printf() and everywhere
5004 * else, unsigned so don't allow dissectors to register a
5005 * signed field to be displayed unsigned. (Else how would
5006 * we display negative values?)
5008 * If you want to take out this check, be sure to fix
5009 * hfinfo_numeric_format() so that it does not assert out
5010 * when trying to construct a hexadecimal representation of
5013 if (hfinfo->display == BASE_HEX ||
5014 hfinfo->display == BASE_OCT)
5015 g_error("Field '%s' (%s) is signed (%s) but is being displayed unsigned (%s)\n",
5016 hfinfo->name, hfinfo->abbrev,
5017 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"),
5018 val_to_str(hfinfo->display, hf_display, "(Bit count: %d)"));
5025 /* Require integral types (other than frame number,
5026 * which is always displayed in decimal) to have a
5028 * If there is a strings value then this base is not
5029 * normally used except when constructing a display
5030 * filter for a value not found in the strings lookup.
5032 switch (hfinfo->display & BASE_DISPLAY_E_MASK) {
5038 case BASE_CUSTOM: /* hfinfo_numeric_value_format() treats this as decimal */
5041 g_error("Field '%s' (%s) is an integral value (%s)"
5042 " but is being displayed as %s\n",
5043 hfinfo->name, hfinfo->abbrev,
5044 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"),
5045 val_to_str(hfinfo->display, hf_display, "(Unknown: 0x%x)"));
5051 if (hfinfo->display != BASE_NONE)
5052 g_error("Field '%s' (%s) is an %s but is being displayed as %s instead of BASE_NONE\n",
5053 hfinfo->name, hfinfo->abbrev,
5054 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"),
5055 val_to_str(hfinfo->display, hf_display, "(Bit count: %d)"));
5056 if (hfinfo->bitmask != 0)
5057 g_error("Field '%s' (%s) is an %s but has a bitmask\n",
5058 hfinfo->name, hfinfo->abbrev,
5059 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"));
5065 case FT_ABSOLUTE_TIME:
5066 if (!(hfinfo->display == ABSOLUTE_TIME_LOCAL ||
5067 hfinfo->display == ABSOLUTE_TIME_UTC ||
5068 hfinfo->display == ABSOLUTE_TIME_DOY_UTC))
5069 g_error("Field '%s' (%s) is a %s but is being displayed as %s instead of as a time\n",
5070 hfinfo->name, hfinfo->abbrev,
5071 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"),
5072 val_to_str(hfinfo->display, hf_display, "(Bit count: %d)"));
5073 if (hfinfo->bitmask != 0)
5074 g_error("Field '%s' (%s) is an %s but has a bitmask\n",
5075 hfinfo->name, hfinfo->abbrev,
5076 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"));
5080 if (hfinfo->display != BASE_NONE)
5081 g_error("Field '%s' (%s) is an %s but is being displayed as %s instead of BASE_NONE\n",
5082 hfinfo->name, hfinfo->abbrev,
5083 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"),
5084 val_to_str(hfinfo->display, hf_display, "(Bit count: %d)"));
5085 if (hfinfo->bitmask != 0)
5086 g_error("Field '%s' (%s) is an %s but has a bitmask\n",
5087 hfinfo->name, hfinfo->abbrev,
5088 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"));
5089 if (hfinfo->strings != NULL)
5090 g_error("Field '%s' (%s) is an %s but has a strings value\n",
5091 hfinfo->name, hfinfo->abbrev,
5092 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"));
5097 #define PROTO_PRE_ALLOC_HF_FIELDS_MEM 120000
5099 proto_register_field_init(header_field_info *hfinfo, const int parent)
5102 tmp_fld_check_assert(hfinfo);
5104 /* if this is a bitfield, compute bitshift */
5105 if (hfinfo->bitmask) {
5106 hfinfo->bitshift = wrs_count_bitshift(hfinfo->bitmask);
5109 hfinfo->parent = parent;
5110 hfinfo->same_name_next = NULL;
5111 hfinfo->same_name_prev = NULL;
5113 /* if we always add and never delete, then id == len - 1 is correct */
5114 if (gpa_hfinfo.len >= gpa_hfinfo.allocated_len) {
5115 if (!gpa_hfinfo.hfi) {
5116 gpa_hfinfo.allocated_len = PROTO_PRE_ALLOC_HF_FIELDS_MEM;
5117 gpa_hfinfo.hfi = g_malloc(sizeof(header_field_info *)*PROTO_PRE_ALLOC_HF_FIELDS_MEM);
5119 gpa_hfinfo.allocated_len += 1000;
5120 gpa_hfinfo.hfi = g_realloc(gpa_hfinfo.hfi,
5121 sizeof(header_field_info *)*gpa_hfinfo.allocated_len);
5122 /*g_warning("gpa_hfinfo.allocated_len %u", gpa_hfinfo.allocated_len);*/
5125 gpa_hfinfo.hfi[gpa_hfinfo.len] = hfinfo;
5127 hfinfo->id = gpa_hfinfo.len - 1;
5129 /* if we have real names, enter this field in the name tree */
5130 if ((hfinfo->name[0] != 0) && (hfinfo->abbrev[0] != 0 )) {
5132 header_field_info *same_name_next_hfinfo;
5135 /* Check that the filter name (abbreviation) is legal;
5136 * it must contain only alphanumerics, '-', "_", and ".". */
5137 c = wrs_check_charset(fld_abbrev_chars, hfinfo->abbrev);
5139 fprintf(stderr, "Invalid character '%c' in filter name '%s'\n", c, hfinfo->abbrev);
5140 DISSECTOR_ASSERT(!c);
5143 /* We allow multiple hfinfo's to be registered under the same
5144 * abbreviation. This was done for X.25, as, depending
5145 * on whether it's modulo-8 or modulo-128 operation,
5146 * some bitfield fields may be in different bits of
5147 * a byte, and we want to be able to refer to that field
5148 * with one name regardless of whether the packets
5149 * are modulo-8 or modulo-128 packets. */
5151 same_name_hfinfo = NULL;
5153 g_tree_insert(gpa_name_tree, (gpointer) (hfinfo->abbrev), hfinfo);
5154 /* GLIB 2.x - if it is already present
5155 * the previous hfinfo with the same name is saved
5156 * to same_name_hfinfo by value destroy callback */
5157 if (same_name_hfinfo) {
5158 /* There's already a field with this name.
5159 * Put it after that field in the list of
5160 * fields with this name, then allow the code
5161 * after this if{} block to replace the old
5162 * hfinfo with the new hfinfo in the GTree. Thus,
5163 * we end up with a linked-list of same-named hfinfo's,
5164 * with the root of the list being the hfinfo in the GTree */
5165 same_name_next_hfinfo =
5166 same_name_hfinfo->same_name_next;
5168 hfinfo->same_name_next = same_name_next_hfinfo;
5169 if (same_name_next_hfinfo)
5170 same_name_next_hfinfo->same_name_prev = hfinfo;
5172 same_name_hfinfo->same_name_next = hfinfo;
5173 hfinfo->same_name_prev = same_name_hfinfo;
5181 proto_register_subtree_array(gint *const *indices, const int num_indices)
5184 gint *const *ptr = indices;
5187 * If we've already allocated the array of tree types, expand
5188 * it; this lets plugins such as mate add tree types after
5189 * the initial startup. (If we haven't already allocated it,
5190 * we don't allocate it; on the first pass, we just assign
5191 * ett values and keep track of how many we've assigned, and
5192 * when we're finished registering all dissectors we allocate
5193 * the array, so that we do only one allocation rather than
5194 * wasting CPU time and memory by growing the array for each
5195 * dissector that registers ett values.)
5197 if (tree_is_expanded != NULL) {
5199 g_realloc(tree_is_expanded,
5200 (num_tree_types + num_indices)*sizeof (gboolean));
5201 memset(tree_is_expanded + num_tree_types, 0,
5202 num_indices*sizeof (gboolean));
5206 * Assign "num_indices" subtree numbers starting at "num_tree_types",
5207 * returning the indices through the pointers in the array whose
5208 * first element is pointed to by "indices", and update
5209 * "num_tree_types" appropriately.
5211 for (i = 0; i < num_indices; i++, ptr++, num_tree_types++) {
5213 /* g_error will terminate the program */
5214 g_error("register_subtree_array: subtree item type (ett_...) not -1 !"
5215 " This is a development error:"
5216 " Either the subtree item type has already been assigned or"
5217 " was not initialized to -1.");
5219 **ptr = num_tree_types;
5224 label_fill_descr(char *label_str, const header_field_info *hfinfo, const char *text, const char *descr)
5228 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH, "%s: %s (%s)", hfinfo->name, text, descr);
5229 if (ret >= ITEM_LABEL_LENGTH) {
5230 /* Uh oh, we don't have enough room. Tell the user that the field is truncated. */
5231 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH, "%s [truncated]: %s (%s)", hfinfo->name, text, descr);
5238 label_fill(char *label_str, const header_field_info *hfinfo, const char *text)
5242 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH, "%s: %s", hfinfo->name, text);
5243 if (ret >= ITEM_LABEL_LENGTH) {
5244 /* Uh oh, we don't have enough room. Tell the user that the field is truncated. */
5245 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH, "%s [truncated]: %s", hfinfo->name, text);
5252 proto_item_fill_label(field_info *fi, gchar *label_str)
5254 header_field_info *hfinfo;
5260 guint32 n_addr; /* network-order IPv4 address */
5266 /* XXX: Check validity of hfinfo->type */
5270 hfinfo = fi->hfinfo;
5272 switch (hfinfo->type) {
5275 g_strlcpy(label_str, hfinfo->name, ITEM_LABEL_LENGTH);
5279 fill_label_boolean(fi, label_str);
5284 bytes = fvalue_get(&fi->value);
5285 label_fill(label_str, hfinfo,
5286 (bytes) ? bytes_to_str(bytes, fvalue_length(&fi->value)) : "<MISSING>");
5289 /* Four types of integers to take care of:
5290 * Bitfield, with val_string
5291 * Bitfield, w/o val_string
5292 * Non-bitfield, with val_string
5293 * Non-bitfield, w/o val_string
5299 if (hfinfo->bitmask) {
5300 fill_label_bitfield(fi, label_str);
5302 fill_label_uint(fi, label_str);
5307 fill_label_uint(fi, label_str);
5311 fill_label_uint64(fi, label_str);
5318 DISSECTOR_ASSERT(!hfinfo->bitmask);
5319 fill_label_int(fi, label_str);
5323 fill_label_int64(fi, label_str);
5327 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5328 "%s: %." STRINGIFY(FLT_DIG) "g",
5329 hfinfo->name, fvalue_get_floating(&fi->value));
5333 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5334 "%s: %." STRINGIFY(DBL_DIG) "g",
5335 hfinfo->name, fvalue_get_floating(&fi->value));
5338 case FT_ABSOLUTE_TIME:
5339 label_fill(label_str, hfinfo,
5340 abs_time_to_str(fvalue_get(&fi->value), hfinfo->display, TRUE));
5343 case FT_RELATIVE_TIME:
5344 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5345 "%s: %s seconds", hfinfo->name,
5346 rel_time_to_secs_str(fvalue_get(&fi->value)));
5350 integer = fvalue_get_uinteger(&fi->value);
5351 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5352 "%s: %s (0x%08X)", hfinfo->name,
5353 get_ipxnet_name(integer), integer);
5357 bytes = fvalue_get(&fi->value);
5358 label_fill_descr(label_str, hfinfo,
5359 get_ax25_name(bytes),
5360 ax25_to_str(bytes));
5364 bytes = fvalue_get(&fi->value);
5365 label_fill_descr(label_str, hfinfo,
5366 get_ether_name(bytes),
5367 ether_to_str(bytes));
5371 ipv4 = fvalue_get(&fi->value);
5372 n_addr = ipv4_get_net_order_addr(ipv4);
5373 label_fill_descr(label_str, hfinfo,
5374 get_hostname(n_addr),
5375 ip_to_str((guint8*)&n_addr));
5379 bytes = fvalue_get(&fi->value);
5380 label_fill_descr(label_str, hfinfo,
5381 get_hostname6((struct e_in6_addr *)bytes),
5382 ip6_to_str((struct e_in6_addr*)bytes));
5386 guid = fvalue_get(&fi->value);
5387 label_fill(label_str, hfinfo, guid_to_str(guid));
5391 bytes = fvalue_get(&fi->value);
5392 name = oid_resolved_from_encoded(bytes, fvalue_length(&fi->value));
5394 label_fill_descr(label_str, hfinfo,
5395 oid_encoded2string(bytes, fvalue_length(&fi->value)), name);
5397 label_fill(label_str, hfinfo,
5398 oid_encoded2string(bytes, fvalue_length(&fi->value)));
5402 integer64 = fvalue_get_integer64(&fi->value);
5403 label_fill_descr(label_str, hfinfo,
5404 get_eui64_name(integer64),
5405 eui64_to_str(integer64));
5409 case FT_UINT_STRING:
5410 bytes = fvalue_get(&fi->value);
5411 label_fill(label_str, hfinfo, format_text(bytes, strlen(bytes)));
5415 g_error("hfinfo->type %d (%s) not handled\n",
5416 hfinfo->type, ftype_name(hfinfo->type));
5417 DISSECTOR_ASSERT_NOT_REACHED();
5423 fill_label_boolean(field_info *fi, gchar *label_str)
5425 char *p = label_str;
5426 int bitfield_byte_length = 0, bitwidth;
5427 guint32 unshifted_value;
5430 header_field_info *hfinfo = fi->hfinfo;
5431 const true_false_string *tfstring = (const true_false_string *)&tfs_true_false;
5433 if (hfinfo->strings) {
5434 tfstring = (const struct true_false_string*) hfinfo->strings;
5437 value = fvalue_get_uinteger(&fi->value);
5438 if (hfinfo->bitmask) {
5439 /* Figure out the bit width */
5440 bitwidth = hfinfo_bitwidth(hfinfo);
5443 unshifted_value = value;
5444 if (hfinfo->bitshift > 0) {
5445 unshifted_value <<= hfinfo->bitshift;
5448 /* Create the bitfield first */
5449 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
5450 bitfield_byte_length = (int) (p - label_str);
5453 /* Fill in the textual info */
5454 g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
5455 "%s: %s", hfinfo->name,
5456 value ? tfstring->true_string : tfstring->false_string);
5459 /* Fills data for bitfield ints with val_strings */
5461 fill_label_bitfield(field_info *fi, gchar *label_str)
5463 const char *format = NULL;
5465 int bitfield_byte_length, bitwidth;
5466 guint32 unshifted_value;
5469 header_field_info *hfinfo = fi->hfinfo;
5471 /* Figure out the bit width */
5472 bitwidth = hfinfo_bitwidth(hfinfo);
5475 unshifted_value = fvalue_get_uinteger(&fi->value);
5476 value = unshifted_value;
5477 if (hfinfo->bitshift > 0) {
5478 unshifted_value <<= hfinfo->bitshift;
5481 /* Create the bitfield first */
5482 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
5483 bitfield_byte_length = (int) (p - label_str);
5485 /* Fill in the textual info using stored (shifted) value */
5486 if (hfinfo->display == BASE_CUSTOM) {
5487 gchar tmp[ITEM_LABEL_LENGTH];
5488 custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hfinfo->strings;
5490 DISSECTOR_ASSERT(fmtfunc);
5491 fmtfunc(tmp, value);
5492 g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
5493 "%s: %s", hfinfo->name, tmp);
5495 else if (hfinfo->strings) {
5496 format = hfinfo_uint_vals_format(hfinfo);
5497 if (hfinfo->display & BASE_RANGE_STRING) {
5498 g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
5499 format, hfinfo->name,
5500 rval_to_str(value, hfinfo->strings, "Unknown"), value);
5501 } else if (hfinfo->display & BASE_EXT_STRING) {
5502 g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
5503 format, hfinfo->name,
5504 val_to_str_ext_const(value, (value_string_ext *) hfinfo->strings, "Unknown"), value);
5506 g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
5507 format, hfinfo->name,
5508 val_to_str_const(value, cVALS(hfinfo->strings), "Unknown"), value);
5512 format = hfinfo_uint_format(hfinfo);
5513 if (IS_BASE_DUAL(hfinfo->display)) {
5514 g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
5515 format, hfinfo->name, value, value);
5517 g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
5518 format, hfinfo->name, value);
5524 fill_label_uint(field_info *fi, gchar *label_str)
5526 const char *format = NULL;
5527 header_field_info *hfinfo = fi->hfinfo;
5530 value = fvalue_get_uinteger(&fi->value);
5532 /* Fill in the textual info */
5533 if (hfinfo->display == BASE_CUSTOM) {
5534 gchar tmp[ITEM_LABEL_LENGTH];
5535 custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hfinfo->strings;
5537 DISSECTOR_ASSERT(fmtfunc);
5538 fmtfunc(tmp, value);
5539 label_fill(label_str, hfinfo, tmp);
5541 else if (hfinfo->strings) {
5542 format = hfinfo_uint_vals_format(hfinfo);
5543 if (hfinfo->display & BASE_RANGE_STRING) {
5544 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5545 format, hfinfo->name,
5546 rval_to_str(value, hfinfo->strings, "Unknown"), value);
5547 } else if (hfinfo->display & BASE_EXT_STRING) {
5548 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5549 format, hfinfo->name,
5550 val_to_str_ext_const(value, (value_string_ext *) hfinfo->strings, "Unknown"), value);
5552 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5553 format, hfinfo->name,
5554 val_to_str_const(value, cVALS(hfinfo->strings), "Unknown"), value);
5558 format = hfinfo_uint_format(hfinfo);
5559 if (IS_BASE_DUAL(hfinfo->display)) {
5560 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5561 format, hfinfo->name, value, value);
5563 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5564 format, hfinfo->name, value);
5570 fill_label_uint64(field_info *fi, gchar *label_str)
5572 const char *format = NULL;
5573 header_field_info *hfinfo = fi->hfinfo;
5576 /* Pick the proper format string */
5577 format = hfinfo_uint64_format(hfinfo);
5578 value = fvalue_get_integer64(&fi->value);
5580 /* Fill in the textual info */
5581 if (IS_BASE_DUAL(hfinfo->display)) {
5582 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5583 format, hfinfo->name, value, value);
5585 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5586 format, hfinfo->name, value);
5591 fill_label_int(field_info *fi, gchar *label_str)
5593 const char *format = NULL;
5594 header_field_info *hfinfo = fi->hfinfo;
5597 value = fvalue_get_sinteger(&fi->value);
5599 /* Fill in the textual info */
5600 if (hfinfo->display == BASE_CUSTOM) {
5601 gchar tmp[ITEM_LABEL_LENGTH];
5602 custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hfinfo->strings;
5604 DISSECTOR_ASSERT(fmtfunc);
5605 fmtfunc(tmp, value);
5606 label_fill(label_str, hfinfo, tmp);
5608 else if (hfinfo->strings) {
5609 format = hfinfo_int_vals_format(hfinfo);
5610 if (hfinfo->display & BASE_RANGE_STRING) {
5611 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5612 format, hfinfo->name,
5613 rval_to_str(value, hfinfo->strings, "Unknown"), value);
5614 } else if (hfinfo->display & BASE_EXT_STRING) {
5615 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5616 format, hfinfo->name,
5617 val_to_str_ext_const(value, (value_string_ext *) hfinfo->strings, "Unknown"), value);
5619 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5620 format, hfinfo->name,
5621 val_to_str_const(value, cVALS(hfinfo->strings), "Unknown"), value);
5625 format = hfinfo_int_format(hfinfo);
5626 if (IS_BASE_DUAL(hfinfo->display)) {
5627 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5628 format, hfinfo->name, value, value);
5630 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5631 format, hfinfo->name, value);
5637 fill_label_int64(field_info *fi, gchar *label_str)
5639 const char *format = NULL;
5640 header_field_info *hfinfo = fi->hfinfo;
5643 /* Pick the proper format string */
5644 format = hfinfo_int64_format(hfinfo);
5645 value = fvalue_get_integer64(&fi->value);
5647 /* Fill in the textual info */
5648 if (IS_BASE_DUAL(hfinfo->display)) {
5649 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5650 format, hfinfo->name, value, value);
5652 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5653 format, hfinfo->name, value);
5658 hfinfo_bitwidth(const header_field_info *hfinfo)
5662 if (!hfinfo->bitmask) {
5666 switch (hfinfo->type) {
5684 bitwidth = hfinfo->display; /* hacky? :) */
5687 DISSECTOR_ASSERT_NOT_REACHED();
5694 hfinfo_uint_vals_format(const header_field_info *hfinfo)
5696 const char *format = NULL;
5698 /* Get the underlying BASE_ value */
5699 switch (hfinfo->display & BASE_DISPLAY_E_MASK) {
5705 format = "%s: %s (%u)";
5707 case BASE_OCT: /* I'm lazy */
5708 format = "%s: %s (%#o)";
5712 switch (hfinfo->type) {
5714 format = "%s: %s (0x%02x)";
5717 format = "%s: %s (0x%04x)";
5720 format = "%s: %s (0x%06x)";
5723 format = "%s: %s (0x%08x)";
5726 DISSECTOR_ASSERT_NOT_REACHED();
5731 DISSECTOR_ASSERT_NOT_REACHED();
5738 hfinfo_uint_format(const header_field_info *hfinfo)
5740 const char *format = NULL;
5742 /* Pick the proper format string */
5743 if (hfinfo->type == FT_FRAMENUM) {
5745 * Frame numbers are always displayed in decimal.
5749 switch (hfinfo->display) {
5754 switch (hfinfo->type) {
5756 format = "%s: %u (0x%02x)";
5759 format = "%s: %u (0x%04x)";
5762 format = "%s: %u (0x%06x)";
5765 format = "%s: %u (0x%08x)";
5768 DISSECTOR_ASSERT_NOT_REACHED();
5772 case BASE_OCT: /* I'm lazy */
5776 switch (hfinfo->type) {
5778 format = "%s: 0x%02x";
5781 format = "%s: 0x%04x";
5784 format = "%s: 0x%06x";
5787 format = "%s: 0x%08x";
5790 DISSECTOR_ASSERT_NOT_REACHED();
5795 switch (hfinfo->type) {
5797 format = "%s: 0x%02x (%u)";
5800 format = "%s: 0x%04x (%u)";
5803 format = "%s: 0x%06x (%u)";
5806 format = "%s: 0x%08x (%u)";
5809 DISSECTOR_ASSERT_NOT_REACHED();
5814 DISSECTOR_ASSERT_NOT_REACHED();
5822 hfinfo_uint_value_format(const header_field_info *hfinfo)
5824 const char *format = NULL;
5826 /* Pick the proper format string */
5827 if (hfinfo->type == FT_FRAMENUM) {
5829 * Frame numbers are always displayed in decimal.
5833 switch (hfinfo->display) {
5838 switch (hfinfo->type) {
5840 format = "%u (0x%02x)";
5843 format = "%u (0x%04x)";
5846 format = "%u (0x%06x)";
5849 format = "%u (0x%08x)";
5852 DISSECTOR_ASSERT_NOT_REACHED();
5860 switch (hfinfo->type) {
5874 DISSECTOR_ASSERT_NOT_REACHED();
5879 switch (hfinfo->type) {
5881 format = "0x%02x (%u)";
5884 format = "0x%04x (%u)";
5887 format = "0x%06x (%u)";
5890 format = "0x%08x (%u)";
5893 DISSECTOR_ASSERT_NOT_REACHED();
5898 DISSECTOR_ASSERT_NOT_REACHED();
5906 hfinfo_int_vals_format(const header_field_info *hfinfo)
5908 const char *format = NULL;
5910 /* Get the underlying BASE_ value */
5911 switch (hfinfo->display & BASE_DISPLAY_E_MASK) {
5917 format = "%s: %s (%d)";
5919 case BASE_OCT: /* I'm lazy */
5920 format = "%s: %s (%#o)";
5924 switch (hfinfo->type) {
5926 format = "%s: %s (0x%02x)";
5929 format = "%s: %s (0x%04x)";
5932 format = "%s: %s (0x%06x)";
5935 format = "%s: %s (0x%08x)";
5938 DISSECTOR_ASSERT_NOT_REACHED();
5943 DISSECTOR_ASSERT_NOT_REACHED();
5950 hfinfo_uint64_format(const header_field_info *hfinfo)
5952 const char *format = NULL;
5954 /* Pick the proper format string */
5955 switch (hfinfo->display) {
5957 format = "%s: %" G_GINT64_MODIFIER "u";
5960 format = "%s: %" G_GINT64_MODIFIER "u (0x%016" G_GINT64_MODIFIER "x)";
5962 case BASE_OCT: /* I'm lazy */
5963 format = "%s: %#" G_GINT64_MODIFIER "o";
5966 format = "%s: 0x%016" G_GINT64_MODIFIER "x";
5969 format = "%s: 0x%016" G_GINT64_MODIFIER "x (%" G_GINT64_MODIFIER "u)";
5972 DISSECTOR_ASSERT_NOT_REACHED();
5979 hfinfo_int_format(const header_field_info *hfinfo)
5981 const char *format = NULL;
5983 /* Pick the proper format string */
5984 switch (hfinfo->display) {
5989 switch (hfinfo->type) {
5991 format = "%s: %d (0x%02x)";
5994 format = "%s: %d (0x%04x)";
5997 format = "%s: %d (0x%06x)";
6000 format = "%s: %d (0x%08x)";
6003 DISSECTOR_ASSERT_NOT_REACHED();
6007 case BASE_OCT: /* I'm lazy */
6011 switch (hfinfo->type) {
6013 format = "%s: 0x%02x";
6016 format = "%s: 0x%04x";
6019 format = "%s: 0x%06x";
6022 format = "%s: 0x%08x";
6025 DISSECTOR_ASSERT_NOT_REACHED();
6030 switch (hfinfo->type) {
6032 format = "%s: 0x%02x (%d)";
6035 format = "%s: 0x%04x (%d)";
6038 format = "%s: 0x%06x (%d)";
6041 format = "%s: 0x%08x (%d)";
6044 DISSECTOR_ASSERT_NOT_REACHED();
6049 DISSECTOR_ASSERT_NOT_REACHED();
6056 hfinfo_int_value_format(const header_field_info *hfinfo)
6058 const char *format = NULL;
6060 /* Pick the proper format string */
6061 switch (hfinfo->display) {
6066 switch (hfinfo->type) {
6068 format = "%d (0x%02x)";
6071 format = "%d (0x%04x)";
6074 format = "%d (0x%06x)";
6077 format = "%d (0x%08x)";
6080 DISSECTOR_ASSERT_NOT_REACHED();
6088 switch (hfinfo->type) {
6102 DISSECTOR_ASSERT_NOT_REACHED();
6107 switch (hfinfo->type) {
6109 format = "0x%02x (%d)";
6112 format = "0x%04x (%d)";
6115 format = "0x%06x (%d)";
6118 format = "0x%08x (%d)";
6121 DISSECTOR_ASSERT_NOT_REACHED();
6126 DISSECTOR_ASSERT_NOT_REACHED();
6133 hfinfo_int64_format(const header_field_info *hfinfo)
6135 const char *format = NULL;
6137 /* Pick the proper format string */
6138 switch (hfinfo->display) {
6140 format = "%s: %" G_GINT64_MODIFIER "d";
6143 format = "%s: %" G_GINT64_MODIFIER "d (0x%016" G_GINT64_MODIFIER "x)";
6145 case BASE_OCT: /* I'm lazy */
6146 format = "%s: %#" G_GINT64_MODIFIER "o";
6149 format = "%s: 0x%016" G_GINT64_MODIFIER "x";
6152 format = "%s: 0x%016" G_GINT64_MODIFIER "x (%" G_GINT64_MODIFIER "d)";
6155 DISSECTOR_ASSERT_NOT_REACHED();
6162 proto_registrar_n(void)
6164 return gpa_hfinfo.len;
6168 proto_registrar_get_name(const int n)
6170 header_field_info *hfinfo;
6172 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
6173 return hfinfo->name;
6177 proto_registrar_get_abbrev(const int n)
6179 header_field_info *hfinfo;
6181 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
6182 return hfinfo->abbrev;
6186 proto_registrar_get_ftype(const int n)
6188 header_field_info *hfinfo;
6190 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
6191 return hfinfo->type;
6195 proto_registrar_get_parent(const int n)
6197 header_field_info *hfinfo;
6199 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
6200 return hfinfo->parent;
6204 proto_registrar_is_protocol(const int n)
6206 header_field_info *hfinfo;
6208 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
6209 return (hfinfo->parent == -1 ? TRUE : FALSE);
6212 /* Returns length of field in packet (not necessarily the length
6213 * in our internal representation, as in the case of IPv4).
6214 * 0 means undeterminable at time of registration
6215 * -1 means the field is not registered. */
6217 proto_registrar_get_length(const int n)
6219 header_field_info *hfinfo;
6221 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
6222 return ftype_length(hfinfo->type);
6225 /* Looks for a protocol or a field in a proto_tree. Returns TRUE if
6226 * it exists anywhere, or FALSE if it exists nowhere. */
6228 proto_check_for_protocol_or_field(const proto_tree* tree, const int id)
6230 GPtrArray *ptrs = proto_get_finfo_ptr_array(tree, id);
6235 else if (g_ptr_array_len(ptrs) > 0) {
6243 /* Return GPtrArray* of field_info pointers for all hfindex that appear in tree.
6244 * This only works if the hfindex was "primed" before the dissection
6245 * took place, as we just pass back the already-created GPtrArray*.
6246 * The caller should *not* free the GPtrArray*; proto_tree_free_node()
6249 proto_get_finfo_ptr_array(const proto_tree *tree, const int id)
6254 if (PTREE_DATA(tree)->interesting_hfids != NULL)
6255 return g_hash_table_lookup(PTREE_DATA(tree)->interesting_hfids,
6256 GINT_TO_POINTER(id));
6262 proto_tracking_interesting_fields(const proto_tree *tree)
6267 return (PTREE_DATA(tree)->interesting_hfids != NULL);
6270 /* Helper struct for proto_find_info() and proto_all_finfos() */
6276 /* Helper function for proto_find_info() */
6278 find_finfo(proto_node *node, gpointer data)
6280 field_info *fi = PNODE_FINFO(node);
6281 if (fi && fi->hfinfo) {
6282 if (fi->hfinfo->id == ((ffdata_t*)data)->id) {
6283 g_ptr_array_add(((ffdata_t*)data)->array, fi);
6287 /* Don't stop traversing. */
6291 /* Return GPtrArray* of field_info pointers for all hfindex that appear in a tree.
6292 * This works on any proto_tree, primed or unprimed, but actually searches
6293 * the tree, so it is slower than using proto_get_finfo_ptr_array on a primed tree.
6294 * The caller does need to free the returned GPtrArray with
6295 * g_ptr_array_free(<array>, TRUE).
6298 proto_find_finfo(proto_tree *tree, const int id)
6302 ffdata.array = g_ptr_array_new();
6305 proto_tree_traverse_pre_order(tree, find_finfo, &ffdata);
6307 return ffdata.array;
6310 /* Helper function for proto_all_finfos() */
6312 every_finfo(proto_node *node, gpointer data)
6314 field_info *fi = PNODE_FINFO(node);
6315 if (fi && fi->hfinfo) {
6316 g_ptr_array_add(((ffdata_t*)data)->array, fi);
6319 /* Don't stop traversing. */
6323 /* Return GPtrArray* of field_info pointers containing all hfindexes that appear in a tree. */
6325 proto_all_finfos(proto_tree *tree)
6329 ffdata.array = g_ptr_array_new();
6332 proto_tree_traverse_pre_order(tree, every_finfo, &ffdata);
6334 return ffdata.array;
6345 check_for_offset(proto_node *node, const gpointer data)
6347 field_info *fi = PNODE_FINFO(node);
6348 offset_search_t *offsearch = data;
6350 /* !fi == the top most container node which holds nothing */
6351 if (fi && !PROTO_ITEM_IS_HIDDEN(node) && fi->ds_tvb && offsearch->tvb == fi->ds_tvb) {
6352 if (offsearch->offset >= (guint) fi->start &&
6353 offsearch->offset < (guint) (fi->start + fi->length)) {
6355 offsearch->finfo = fi;
6356 return FALSE; /* keep traversing */
6359 return FALSE; /* keep traversing */
6362 /* Search a proto_tree backwards (from leaves to root) looking for the field
6363 * whose start/length occupies 'offset' */
6364 /* XXX - I couldn't find an easy way to search backwards, so I search
6365 * forwards, w/o stopping. Therefore, the last finfo I find will the be
6366 * the one I want to return to the user. This algorithm is inefficient
6367 * and could be re-done, but I'd have to handle all the children and
6368 * siblings of each node myself. When I have more time I'll do that.
6371 proto_find_field_from_offset(proto_tree *tree, guint offset, tvbuff_t *tvb)
6373 offset_search_t offsearch;
6375 offsearch.offset = offset;
6376 offsearch.finfo = NULL;
6377 offsearch.tvb = tvb;
6379 proto_tree_traverse_pre_order(tree, check_for_offset, &offsearch);
6381 return offsearch.finfo;
6384 /* Dumps the protocols in the registration database to stdout. An independent
6385 * program can take this output and format it into nice tables or HTML or
6388 * There is one record per line. The fields are tab-delimited.
6390 * Field 1 = protocol name
6391 * Field 2 = protocol short name
6392 * Field 3 = protocol filter name
6395 proto_registrar_dump_protocols(void)
6397 protocol_t *protocol;
6399 void *cookie = NULL;
6402 i = proto_get_first_protocol(&cookie);
6404 protocol = find_protocol_by_id(i);
6405 printf("%s\t%s\t%s\n", protocol->name, protocol->short_name,
6406 protocol->filter_name);
6407 i = proto_get_next_protocol(&cookie);
6411 /* Dumps the value_strings, extended value string headers, range_strings
6412 * or true/false strings for fields that have them.
6413 * There is one record per line. Fields are tab-delimited.
6414 * There are four types of records: Value String, Extended Value String Header,
6415 * Range String and True/False String. The first field, 'V', 'E', 'R' or 'T', indicates
6416 * the type of record.
6418 * Note that a record will be generated only if the value_string,... is referenced
6419 * in a registered hfinfo entry.
6425 * Field 2 = Field abbreviation to which this value string corresponds
6426 * Field 3 = Integer value
6429 * Extended Value String Headers
6430 * -----------------------------
6432 * Field 2 = Field abbreviation to which this extended value string header corresponds
6433 * Field 3 = Extended Value String "Name"
6434 * Field 4 = Number of entries in the associated value_string array
6435 * Field 5 = Access Type: "Linear Search", "Binary Search", "Direct (indexed) Access"
6440 * Field 2 = Field abbreviation to which this range string corresponds
6441 * Field 3 = Integer value: lower bound
6442 * Field 4 = Integer value: upper bound
6445 * True/False Strings
6446 * ------------------
6448 * Field 2 = Field abbreviation to which this true/false string corresponds
6449 * Field 3 = True String
6450 * Field 4 = False String
6453 proto_registrar_dump_values(void)
6455 header_field_info *hfinfo;
6457 const value_string *vals;
6458 const range_string *range;
6459 const true_false_string *tfs;
6461 len = gpa_hfinfo.len;
6462 for (i = 0; i < len ; i++) {
6463 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
6465 if (hfinfo->id == hf_text_only) {
6469 /* ignore protocols */
6470 if (proto_registrar_is_protocol(i)) {
6473 /* process header fields */
6476 * If this field isn't at the head of the list of
6477 * fields with this name, skip this field - all
6478 * fields with the same name are really just versions
6479 * of the same field stored in different bits, and
6480 * should have the same type/radix/value list, and
6481 * just differ in their bit masks. (If a field isn't
6482 * a bitfield, but can be, say, 1 or 2 bytes long,
6483 * it can just be made FT_UINT16, meaning the
6484 * *maximum* length is 2 bytes, and be used
6487 if (hfinfo->same_name_prev != NULL)
6494 if (hfinfo->strings != NULL) {
6495 if ((hfinfo->display & BASE_DISPLAY_E_MASK) != BASE_CUSTOM &&
6496 (hfinfo->type == FT_UINT8 ||
6497 hfinfo->type == FT_UINT16 ||
6498 hfinfo->type == FT_UINT24 ||
6499 hfinfo->type == FT_UINT32 ||
6500 hfinfo->type == FT_UINT64 ||
6501 hfinfo->type == FT_INT8 ||
6502 hfinfo->type == FT_INT16 ||
6503 hfinfo->type == FT_INT24 ||
6504 hfinfo->type == FT_INT32 ||
6505 hfinfo->type == FT_INT64)) {
6507 if (hfinfo->display & BASE_EXT_STRING) {
6508 vals = VALUE_STRING_EXT_VS_P((value_string_ext *)hfinfo->strings);
6509 } else if ((hfinfo->display & BASE_RANGE_STRING) == 0) {
6510 vals = hfinfo->strings;
6512 range = hfinfo->strings;
6515 else if (hfinfo->type == FT_BOOLEAN) {
6516 tfs = hfinfo->strings;
6520 /* Print value strings? */
6522 if (hfinfo->display & BASE_EXT_STRING) {
6523 value_string_ext *vse_p = (value_string_ext *)hfinfo->strings;
6524 if (!value_string_ext_validate(vse_p)) {
6525 g_warning("Invalid value_string_ext ptr for: %s", hfinfo->abbrev);
6528 match_strval_ext(0, vse_p); /* "prime" the extended value_string */
6529 printf("E\t%s\t%d\t%s\t%s\n",
6531 VALUE_STRING_EXT_VS_NUM_ENTRIES(vse_p),
6532 VALUE_STRING_EXT_VS_NAME(vse_p),
6533 value_string_ext_match_type_str(vse_p));
6536 while (vals[vi].strptr) {
6537 /* Print in the proper base */
6538 if (hfinfo->display == BASE_HEX) {
6539 printf("V\t%s\t0x%x\t%s\n",
6545 printf("V\t%s\t%u\t%s\n",
6554 /* print range strings? */
6557 while (range[vi].strptr) {
6558 /* Print in the proper base */
6559 if ((hfinfo->display & BASE_DISPLAY_E_MASK) == BASE_HEX) {
6560 printf("R\t%s\t0x%x\t0x%x\t%s\n",
6562 range[vi].value_min,
6563 range[vi].value_max,
6567 printf("R\t%s\t%u\t%u\t%s\n",
6569 range[vi].value_min,
6570 range[vi].value_max,
6577 /* Print true/false strings? */
6579 printf("T\t%s\t%s\t%s\n", hfinfo->abbrev,
6580 tfs->true_string, tfs->false_string);
6586 /* Dumps the contents of the registration database to stdout. An independent
6587 * program can take this output and format it into nice tables or HTML or
6590 * There is one record per line. Each record is either a protocol or a header
6591 * field, differentiated by the first field. The fields are tab-delimited.
6596 * Field 2 = descriptive protocol name
6597 * Field 3 = protocol abbreviation
6603 * Field 2 = descriptive field name
6604 * Field 3 = field abbreviation
6605 * Field 4 = type ( textual representation of the the ftenum type )
6606 * Field 5 = parent protocol abbreviation
6607 * Field 6 = blurb describing field
6611 * Field 2 = descriptive field name
6612 * Field 3 = field abbreviation
6613 * Field 4 = type ( textual representation of the the ftenum type )
6614 * Field 5 = parent protocol abbreviation
6615 * Field 6 = blurb describing field
6616 * Field 7 = base for display (for integer types); "parent bitfield width" for FT_BOOLEAN
6617 * Field 8 = blurb describing field (yes, apparently we repeated this accidentally)
6621 * Field 2 = descriptive field name
6622 * Field 3 = field abbreviation
6623 * Field 4 = type ( textual representation of the the ftenum type )
6624 * Field 5 = parent protocol abbreviation
6625 * Field 6 = blurb describing field
6626 * Field 7 = base for display (for integer types); "parent bitfield width" for FT_BOOLEAN
6627 * Field 8 = bitmask: format: hex: 0x....
6630 proto_registrar_dump_fields(const int format)
6632 header_field_info *hfinfo, *parent_hfinfo;
6634 const char *enum_name;
6635 const char *base_name;
6639 len = gpa_hfinfo.len;
6640 for (i = 0; i < len ; i++) {
6641 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
6644 * Skip the pseudo-field for "proto_tree_add_text()" since
6645 * we don't want it in the list of filterable fields.
6647 if (hfinfo->id == hf_text_only)
6650 /* format for protocols */
6651 if (proto_registrar_is_protocol(i)) {
6652 printf("P\t%s\t%s\n", hfinfo->name, hfinfo->abbrev);
6654 /* format for header fields */
6657 * If this field isn't at the head of the list of
6658 * fields with this name, skip this field - all
6659 * fields with the same name are really just versions
6660 * of the same field stored in different bits, and
6661 * should have the same type/radix/value list, and
6662 * just differ in their bit masks. (If a field isn't
6663 * a bitfield, but can be, say, 1 or 2 bytes long,
6664 * it can just be made FT_UINT16, meaning the
6665 * *maximum* length is 2 bytes, and be used
6668 if (hfinfo->same_name_prev != NULL)
6671 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
6673 enum_name = ftype_name(hfinfo->type);
6677 if (hfinfo->type == FT_UINT8 ||
6678 hfinfo->type == FT_UINT16 ||
6679 hfinfo->type == FT_UINT24 ||
6680 hfinfo->type == FT_UINT32 ||
6681 hfinfo->type == FT_UINT64 ||
6682 hfinfo->type == FT_INT8 ||
6683 hfinfo->type == FT_INT16 ||
6684 hfinfo->type == FT_INT24 ||
6685 hfinfo->type == FT_INT32 ||
6686 hfinfo->type == FT_INT64) {
6689 switch (hfinfo->display & BASE_DISPLAY_E_MASK) {
6691 base_name = "BASE_NONE";
6694 base_name = "BASE_DEC";
6697 base_name = "BASE_HEX";
6700 base_name = "BASE_OCT";
6703 base_name = "BASE_DEC_HEX";
6706 base_name = "BASE_HEX_DEC";
6709 base_name = "BASE_CUSTOM";
6715 } else if (hfinfo->type == FT_BOOLEAN) {
6716 /* For FT_BOOLEAN: 'display' can be "parent bitfield width" */
6717 g_snprintf(width, sizeof(width), "%d", hfinfo->display);
6722 blurb = hfinfo->blurb;
6725 else if (strlen(blurb) == 0)
6728 printf("F\t%s\t%s\t%s\t%s\t%s\n",
6729 hfinfo->name, hfinfo->abbrev, enum_name,
6730 parent_hfinfo->abbrev, blurb);
6732 else if (format == 2) {
6733 printf("F\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n",
6734 hfinfo->name, hfinfo->abbrev, enum_name,
6735 parent_hfinfo->abbrev, blurb,
6738 else if (format == 3) {
6739 printf("F\t%s\t%s\t%s\t%s\t%s\t%s\t0x%x\n",
6740 hfinfo->name, hfinfo->abbrev, enum_name,
6741 parent_hfinfo->abbrev, blurb,
6742 base_name, hfinfo->bitmask);
6745 g_assert_not_reached();
6751 /* Dumps field types and descriptive names to stdout. An independent
6752 * program can take this output and format it into nice tables or HTML or
6755 * There is one record per line. The fields are tab-delimited.
6757 * Field 1 = field type name, e.g. FT_UINT8
6758 * Field 2 = descriptive name, e.g. "Unsigned, 1 byte"
6761 proto_registrar_dump_ftypes(void)
6765 for (fte = 0; fte < FT_NUM_TYPES; fte++) {
6766 printf("%s\t%s\n", ftype_name(fte), ftype_pretty_name(fte));
6771 hfinfo_numeric_format(const header_field_info *hfinfo)
6773 const char *format = NULL;
6775 /* Pick the proper format string */
6776 if (hfinfo->type == FT_FRAMENUM) {
6778 * Frame numbers are always displayed in decimal.
6780 format = "%s == %u";
6782 /* Get the underlying BASE_ value */
6783 switch (hfinfo->display & BASE_DISPLAY_E_MASK) {
6786 case BASE_OCT: /* I'm lazy */
6788 switch (hfinfo->type) {
6793 format = "%s == %u";
6796 format = "%s == %" G_GINT64_MODIFIER "u";
6802 format = "%s == %d";
6805 format = "%s == %" G_GINT64_MODIFIER "d";
6808 DISSECTOR_ASSERT_NOT_REACHED();
6814 switch (hfinfo->type) {
6817 format = "%s == 0x%02x";
6821 format = "%s == 0x%04x";
6825 format = "%s == 0x%06x";
6829 format = "%s == 0x%08x";
6833 format = "%s == 0x%016" G_GINT64_MODIFIER "x";
6836 DISSECTOR_ASSERT_NOT_REACHED();
6841 DISSECTOR_ASSERT_NOT_REACHED();
6849 hfinfo_numeric_value_format(const header_field_info *hfinfo)
6851 const char *format = NULL;
6853 /* Pick the proper format string */
6854 if (hfinfo->type == FT_FRAMENUM) {
6856 * Frame numbers are always displayed in decimal.
6860 /* Get the underlying BASE_ value */
6861 switch (hfinfo->display & BASE_DISPLAY_E_MASK) {
6865 case BASE_OCT: /* I'm lazy */
6867 switch (hfinfo->type) {
6875 format = "%" G_GINT64_MODIFIER "u";
6884 format = "%" G_GINT64_MODIFIER "d";
6887 DISSECTOR_ASSERT_NOT_REACHED();
6893 switch (hfinfo->type) {
6912 format = "0x%016" G_GINT64_MODIFIER "x";
6915 DISSECTOR_ASSERT_NOT_REACHED();
6920 DISSECTOR_ASSERT_NOT_REACHED();
6927 /* This function indicates whether it's possible to construct a
6928 * "match selected" display filter string for the specified field,
6929 * returns an indication of whether it's possible, and, if it's
6930 * possible and "filter" is non-null, constructs the filter and
6931 * sets "*filter" to point to it.
6932 * You do not need to [g_]free() this string since it will be automatically
6933 * freed once the next packet is dissected.
6936 construct_match_selected_string(field_info *finfo, epan_dissect_t *edt,
6939 header_field_info *hfinfo;
6945 gint start, length, length_remaining;
6947 gchar is_signed_num = FALSE;
6949 hfinfo = finfo->hfinfo;
6950 DISSECTOR_ASSERT(hfinfo);
6951 abbrev_len = (int) strlen(hfinfo->abbrev);
6953 if (hfinfo->strings && (hfinfo->display & BASE_DISPLAY_E_MASK) == BASE_NONE) {
6954 const gchar *str = NULL;
6956 switch (hfinfo->type) {
6962 if (hfinfo->display & BASE_RANGE_STRING) {
6963 str = match_strrval(fvalue_get_sinteger(&finfo->value), hfinfo->strings);
6964 } else if (hfinfo->display & BASE_EXT_STRING) {
6965 str = match_strval_ext(fvalue_get_sinteger(&finfo->value), hfinfo->strings);
6967 str = match_strval(fvalue_get_sinteger(&finfo->value), hfinfo->strings);
6975 if (hfinfo->display & BASE_RANGE_STRING) {
6976 str = match_strrval(fvalue_get_uinteger(&finfo->value), hfinfo->strings);
6977 } else if (hfinfo->display & BASE_EXT_STRING) {
6978 str = match_strval_ext(fvalue_get_uinteger(&finfo->value), hfinfo->strings);
6980 str = match_strval(fvalue_get_uinteger(&finfo->value), hfinfo->strings);
6988 if (str != NULL && filter != NULL) {
6989 *filter = ep_strdup_printf("%s == \"%s\"", hfinfo->abbrev, str);
6995 * XXX - we can't use the "val_to_string_repr" and "string_repr_len"
6996 * functions for FT_UINT and FT_INT types, as we choose the base in
6997 * the string expression based on the display base of the field.
6999 * Note that the base does matter, as this is also used for
7000 * the protocolinfo tap.
7002 * It might be nice to use them in "proto_item_fill_label()"
7003 * as well, although, there, you'd have to deal with the base
7004 * *and* with resolved values for addresses.
7006 * Perhaps we need two different val_to_string routines, one
7007 * to generate items for display filters and one to generate
7008 * strings for display, and pass to both of them the
7009 * "display" and "strings" values in the header_field_info
7010 * structure for the field, so they can get the base and,
7011 * if the field is Boolean or an enumerated integer type,
7012 * the tables used to generate human-readable values.
7014 switch (hfinfo->type) {
7020 is_signed_num = TRUE;
7026 if (filter != NULL) {
7027 format = hfinfo_numeric_format(hfinfo);
7028 if (is_signed_num) {
7029 *filter = ep_strdup_printf(format,
7031 fvalue_get_sinteger(&finfo->value));
7033 *filter = ep_strdup_printf(format,
7035 fvalue_get_uinteger(&finfo->value));
7041 DISSECTOR_ASSERT(!is_signed_num);
7042 if (filter != NULL) {
7043 format = hfinfo_numeric_format(hfinfo);
7044 *filter = ep_strdup_printf(format,
7046 fvalue_get_uinteger(&finfo->value));
7052 if (filter != NULL) {
7053 format = hfinfo_numeric_format(hfinfo);
7054 *filter = ep_strdup_printf(format,
7056 fvalue_get_integer64(&finfo->value));
7062 *filter = ep_strdup(finfo->hfinfo->abbrev);
7067 * If the length is 0, just match the name of the
7070 * (Also check for negative values, just in case,
7071 * as we'll cast it to an unsigned value later.)
7073 length = finfo->length;
7076 *filter = ep_strdup(finfo->hfinfo->abbrev);
7083 * This doesn't have a value, so we'd match
7084 * on the raw bytes at this address.
7086 * Should we be allowed to access to the raw bytes?
7087 * If "edt" is NULL, the answer is "no".
7093 * Is this field part of the raw frame tvbuff?
7094 * If not, we can't use "frame[N:M]" to match
7097 * XXX - should this be frame-relative, or
7098 * protocol-relative?
7100 * XXX - does this fallback for non-registered
7101 * fields even make sense?
7103 if (finfo->ds_tvb != edt->tvb)
7104 return FALSE; /* you lose */
7107 * Don't go past the end of that tvbuff.
7109 length_remaining = tvb_length_remaining(finfo->ds_tvb, finfo->start);
7110 if (length > length_remaining)
7111 length = length_remaining;
7115 if (filter != NULL) {
7116 start = finfo->start;
7117 buf_len = 32 + length * 3;
7118 *filter = ep_alloc0(buf_len);
7121 ptr += g_snprintf(ptr, (gulong) (buf_len-(ptr-*filter)),
7122 "frame[%d:%d] == ", finfo->start, length);
7123 for (i=0; i<length; i++) {
7124 c = tvb_get_guint8(finfo->ds_tvb, start);
7127 ptr += g_snprintf(ptr, (gulong) (buf_len-(ptr-*filter)), "%02x", c);
7130 ptr += g_snprintf(ptr, (gulong) (buf_len-(ptr-*filter)), ":%02x", c);
7137 /* FT_PCRE never appears as a type for a registered field. It is
7138 * only used internally. */
7139 DISSECTOR_ASSERT_NOT_REACHED();
7142 /* By default, use the fvalue's "to_string_repr" method. */
7144 /* Figure out the string length needed.
7145 * The ft_repr length.
7146 * 4 bytes for " == ".
7147 * 1 byte for trailing NUL.
7149 if (filter != NULL) {
7150 dfilter_len = fvalue_string_repr_len(&finfo->value,
7152 dfilter_len += abbrev_len + 4 + 1;
7153 *filter = ep_alloc0(dfilter_len);
7155 /* Create the string */
7156 g_snprintf(*filter, dfilter_len, "%s == ",
7158 fvalue_to_string_repr(&finfo->value,
7160 &(*filter)[abbrev_len + 4]);
7169 * Returns TRUE if we can do a "match selected" on the field, FALSE
7173 proto_can_match_selected(field_info *finfo, epan_dissect_t *edt)
7175 return construct_match_selected_string(finfo, edt, NULL);
7178 /* This function attempts to construct a "match selected" display filter
7179 * string for the specified field; if it can do so, it returns a pointer
7180 * to the string, otherwise it returns NULL.
7182 * The string is allocated with packet lifetime scope.
7183 * You do not need to [g_]free() this string since it will be automatically
7184 * freed once the next packet is dissected.
7187 proto_construct_match_selected_string(field_info *finfo, epan_dissect_t *edt)
7191 if (!construct_match_selected_string(finfo, edt, &filter))
7196 /* This function is common code for both proto_tree_add_bitmask() and
7197 * proto_tree_add_bitmask_text() functions.
7200 /* NOTE: to support code written when proto_tree_add_bitmask() and
7201 * proto_tree_add_bitmask_text took a
7202 * gboolean as its last argument, with FALSE meaning "big-endian"
7203 * and TRUE meaning "little-endian", we treat any non-zero value of
7204 * "encoding" as meaning "little-endian".
7207 proto_item_add_bitmask_tree(proto_item *item, tvbuff_t *tvb, const int offset,
7208 const int len, const gint ett, const int **fields,
7209 const guint encoding, const int flags,
7214 proto_tree *tree = NULL;
7215 header_field_info *hf;
7220 value = tvb_get_guint8(tvb, offset);
7223 value = encoding ? tvb_get_letohs(tvb, offset) :
7224 tvb_get_ntohs(tvb, offset);
7227 value = encoding ? tvb_get_letoh24(tvb, offset) :
7228 tvb_get_ntoh24(tvb, offset);
7231 value = encoding ? tvb_get_letohl(tvb, offset) :
7232 tvb_get_ntohl(tvb, offset);
7235 g_assert_not_reached();
7238 tree = proto_item_add_subtree(item, ett);
7240 proto_tree_add_item(tree, **fields, tvb, offset, len, encoding);
7241 if (flags & BMT_NO_APPEND) {
7245 hf = proto_registrar_get_nth(**fields);
7246 DISSECTOR_ASSERT(hf->bitmask != 0);
7247 tmpval = (value & hf->bitmask) >> hf->bitshift;
7258 DISSECTOR_ASSERT(len == ftype_length(hf->type));
7260 if (hf->display == BASE_CUSTOM) {
7261 gchar lbl[ITEM_LABEL_LENGTH];
7262 custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hf->strings;
7264 DISSECTOR_ASSERT(fmtfunc);
7265 fmtfunc(lbl, tmpval);
7266 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
7270 else if (hf->strings) {
7271 if (hf->display & BASE_RANGE_STRING) {
7272 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
7273 hf->name, rval_to_str(tmpval, hf->strings, "Unknown"));
7274 } else if (hf->display & BASE_EXT_STRING) {
7275 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
7276 hf->name, val_to_str_ext_const(tmpval, (value_string_ext *) (hf->strings), "Unknown"));
7278 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
7279 hf->name, val_to_str_const(tmpval, cVALS(hf->strings), "Unknown"));
7283 else if (!(flags & BMT_NO_INT)) {
7285 proto_item_append_text(item, ", ");
7288 fmt = IS_FT_INT(hf->type) ? hfinfo_int_format(hf) : hfinfo_uint_format(hf);
7289 if (IS_BASE_DUAL(hf->display)) {
7290 proto_item_append_text(item, fmt, hf->name, tmpval, tmpval);
7292 proto_item_append_text(item, fmt, hf->name, tmpval);
7299 DISSECTOR_ASSERT(len * 8 == hf->display);
7301 if (hf->strings && !(flags & BMT_NO_TFS)) {
7302 /* If we have true/false strings, emit full - otherwise messages
7304 const struct true_false_string *tfs =
7305 (const struct true_false_string *)hf->strings;
7308 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
7309 hf->name, tfs->true_string);
7311 } else if (!(flags & BMT_NO_FALSE)) {
7312 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
7313 hf->name, tfs->false_string);
7316 } else if (hf->bitmask & value) {
7317 /* If the flag is set, show the name */
7318 proto_item_append_text(item, "%s%s", first ? "" : ", ", hf->name);
7323 g_assert_not_reached();
7332 /* This function will dissect a sequence of bytes that describe a
7334 * hf_hdr is a 8/16/24/32 bit integer that describes the bitmask to be dissected.
7335 * This field will form an expansion under which the individual fields of the
7336 * bitmask is dissected and displayed.
7337 * This field must be of the type FT_[U]INT{8|16|24|32}.
7339 * fields is an array of pointers to int that lists all the fields of the
7340 * bitmask. These fields can be either of the type FT_BOOLEAN for flags
7341 * or another integer of the same type/size as hf_hdr with a mask specified.
7342 * This array is terminated by a NULL entry.
7344 * FT_BOOLEAN bits that are set to 1 will have the name added to the expansion.
7345 * FT_integer fields that have a value_string attached will have the
7346 * matched string displayed on the expansion line.
7349 proto_tree_add_bitmask(proto_tree *parent_tree, tvbuff_t *tvb,
7350 const guint offset, const int hf_hdr,
7351 const gint ett, const int **fields,
7352 const guint encoding)
7354 proto_item *item = NULL;
7355 header_field_info *hf;
7358 hf = proto_registrar_get_nth(hf_hdr);
7359 DISSECTOR_ASSERT(IS_FT_INT(hf->type) || IS_FT_UINT(hf->type));
7360 len = ftype_length(hf->type);
7363 item = proto_tree_add_item(parent_tree, hf_hdr, tvb, offset, len, encoding);
7364 proto_item_add_bitmask_tree(item, tvb, offset, len, ett, fields, encoding,
7365 BMT_NO_INT|BMT_NO_TFS, FALSE);
7371 /* The same as proto_tree_add_bitmask(), but using an arbitrary text as a top-level item */
7373 proto_tree_add_bitmask_text(proto_tree *parent_tree, tvbuff_t *tvb,
7374 const guint offset, const guint len,
7375 const char *name, const char *fallback,
7376 const gint ett, const int **fields,
7377 const guint encoding, const int flags)
7379 proto_item *item = NULL;
7382 item = proto_tree_add_text(parent_tree, tvb, offset, len, "%s", name ? name : "");
7383 if (proto_item_add_bitmask_tree(item, tvb, offset, len, ett, fields, encoding,
7384 flags, TRUE) && fallback) {
7385 /* Still at first item - append 'fallback' text if any */
7386 proto_item_append_text(item, "%s", fallback);
7394 proto_tree_add_bits_item(proto_tree *tree, const int hf_index, tvbuff_t *tvb,
7395 const guint bit_offset, const gint no_of_bits,
7396 const guint encoding)
7398 header_field_info *hfinfo;
7400 TRY_TO_FAKE_THIS_ITEM(tree, hf_index, hfinfo);
7402 return proto_tree_add_bits_ret_val(tree, hf_index, tvb, bit_offset, no_of_bits, NULL, encoding);
7406 * This function will dissect a sequence of bits that does not need to be byte aligned; the bits
7407 * set will be shown in the tree as ..10 10.. and the integer value returned if return_value is set.
7408 * Offset should be given in bits from the start of the tvb.
7412 _proto_tree_add_bits_ret_val(proto_tree *tree, const int hf_index, tvbuff_t *tvb,
7413 const guint bit_offset, const gint no_of_bits,
7414 guint64 *return_value, const guint encoding)
7420 char lbl_str[ITEM_LABEL_LENGTH];
7424 header_field_info *hf_field;
7426 const true_false_string *tfstring;
7428 /* We can't fake it just yet. We have to fill in the 'return_value' parameter */
7429 PROTO_REGISTRAR_GET_NTH(hf_index, hf_field);
7431 if (hf_field->bitmask != 0) {
7432 REPORT_DISSECTOR_BUG(ep_strdup_printf("Incompatible use of proto_tree_add_bits_ret_val"
7433 " with field '%s' (%s) with bitmask != 0",
7434 hf_field->abbrev, hf_field->name));
7437 DISSECTOR_ASSERT(no_of_bits > 0);
7439 /* Byte align offset */
7440 offset = bit_offset>>3;
7443 * Calculate the number of octets used to hold the bits
7445 tot_no_bits = ((bit_offset&0x7) + no_of_bits);
7446 length = tot_no_bits>>3;
7447 /* If we are using part of the next octet, increase length by 1 */
7448 if (tot_no_bits & 0x07)
7451 if (no_of_bits < 65) {
7452 value = tvb_get_bits64(tvb, bit_offset, no_of_bits, encoding);
7454 DISSECTOR_ASSERT_NOT_REACHED();
7458 /* Sign extend for signed types */
7459 switch (hf_field->type) {
7465 if (value & (G_GINT64_CONSTANT(1) << (no_of_bits-1)))
7466 value |= (G_GINT64_CONSTANT(-1) << no_of_bits);
7474 *return_value = value;
7477 /* Coast clear. Try and fake it */
7478 TRY_TO_FAKE_THIS_ITEM(tree, hf_index, hf_field);
7480 bf_str = decode_bits_in_field(bit_offset, no_of_bits, value);
7482 switch (hf_field->type) {
7485 tfstring = (const true_false_string *) &tfs_true_false;
7486 if (hf_field->strings)
7487 tfstring = (const true_false_string *)hf_field->strings;
7488 return proto_tree_add_boolean_format(tree, hf_index, tvb, offset, length, (guint32)value,
7490 bf_str, hf_field->name,
7491 (guint32)value ? tfstring->true_string : tfstring->false_string);
7498 pi = proto_tree_add_uint(tree, hf_index, tvb, offset, length, (guint32)value);
7499 fill_label_uint(PITEM_FINFO(pi), lbl_str);
7506 pi = proto_tree_add_int(tree, hf_index, tvb, offset, length, (gint32)value);
7507 fill_label_int(PITEM_FINFO(pi), lbl_str);
7511 pi = proto_tree_add_uint64(tree, hf_index, tvb, offset, length, value);
7512 fill_label_uint64(PITEM_FINFO(pi), lbl_str);
7516 pi = proto_tree_add_int64(tree, hf_index, tvb, offset, length, (gint64)value);
7517 fill_label_int64(PITEM_FINFO(pi), lbl_str);
7521 DISSECTOR_ASSERT_NOT_REACHED();
7526 proto_item_set_text(pi, "%s = %s", bf_str, lbl_str);
7531 proto_tree_add_split_bits_item_ret_val(proto_tree *tree, const int hf_index, tvbuff_t *tvb,
7532 const guint bit_offset, const crumb_spec_t *crumb_spec,
7533 guint64 *return_value)
7538 guint mask_initial_bit_offset;
7539 guint mask_greatest_bit_offset;
7543 char lbl_str[ITEM_LABEL_LENGTH];
7545 guint64 composite_bitmask;
7546 guint64 composite_bitmap;
7548 header_field_info *hf_field;
7549 const true_false_string *tfstring;
7551 /* We can't fake it just yet. We have to fill in the 'return_value' parameter */
7552 PROTO_REGISTRAR_GET_NTH(hf_index, hf_field);
7554 if (hf_field->bitmask != 0) {
7555 REPORT_DISSECTOR_BUG(ep_strdup_printf(
7556 "Incompatible use of proto_tree_add_split_bits_item_ret_val"
7557 " with field '%s' (%s) with bitmask != 0",
7558 hf_field->abbrev, hf_field->name));
7561 mask_initial_bit_offset = bit_offset % 8;
7566 mask_greatest_bit_offset = 0;
7567 composite_bitmask = 0;
7568 composite_bitmap = 0;
7570 while (crumb_spec[i].crumb_bit_length != 0) {
7571 guint64 crumb_mask, crumb_value;
7572 guint8 crumb_end_bit_offset;
7574 DISSECTOR_ASSERT(i < 64);
7575 crumb_value = tvb_get_bits64(tvb,
7576 bit_offset + crumb_spec[i].crumb_bit_offset,
7577 crumb_spec[i].crumb_bit_length,
7579 value += crumb_value;
7580 no_of_bits += crumb_spec[i].crumb_bit_length;
7582 /* The bitmask is 64 bit, left-aligned, starting at the first bit of the
7583 octet containing the initial offset.
7584 If the mask is beyond 32 bits, then give up on bit map display.
7585 This could be improved in future, probably showing a table
7586 of 32 or 64 bits per row */
7587 if (mask_greatest_bit_offset < 32) {
7588 crumb_end_bit_offset = mask_initial_bit_offset
7589 + crumb_spec[i].crumb_bit_offset
7590 + crumb_spec[i].crumb_bit_length;
7591 crumb_mask = (G_GUINT64_CONSTANT(1) << crumb_spec[i].crumb_bit_length) - 1;
7593 if (crumb_end_bit_offset > mask_greatest_bit_offset) {
7594 mask_greatest_bit_offset = crumb_end_bit_offset;
7596 composite_bitmask |= (crumb_mask << (64 - crumb_end_bit_offset));
7597 composite_bitmap |= (crumb_value << (64 - crumb_end_bit_offset));
7599 /* Shift left for the next segment */
7600 value <<= crumb_spec[++i].crumb_bit_length;
7603 /* Sign extend for signed types */
7604 switch (hf_field->type) {
7610 if (value & no_of_bits && (G_GINT64_CONSTANT(1) << (no_of_bits-1)))
7611 value |= (G_GINT64_CONSTANT(-1) << no_of_bits);
7618 *return_value = value;
7621 /* Coast clear. Try and fake it */
7622 TRY_TO_FAKE_THIS_ITEM(tree, hf_index, hf_field);
7624 /* initialise the format string */
7625 bf_str = ep_alloc(256);
7628 octet_offset = bit_offset >> 3;
7630 /* Round up mask length to nearest octet */
7631 octet_length = ((mask_greatest_bit_offset + 7) >> 3);
7632 mask_greatest_bit_offset = octet_length << 3;
7634 /* As noted above, we currently only produce a bitmap if the crumbs span less than 4 octets of the tvb.
7635 It would be a useful enhancement to eliminate this restriction. */
7636 if (mask_greatest_bit_offset <= 32) {
7637 other_decode_bitfield_value(bf_str,
7638 (guint32)(composite_bitmap >> (64 - mask_greatest_bit_offset)),
7639 (guint32)(composite_bitmask >> (64 - mask_greatest_bit_offset)),
7640 mask_greatest_bit_offset);
7643 switch (hf_field->type) {
7644 case FT_BOOLEAN: /* it is a bit odd to have a boolean encoded as split-bits, but possible, I suppose? */
7646 tfstring = (const true_false_string *) &tfs_true_false;
7647 if (hf_field->strings)
7648 tfstring = (const true_false_string *) hf_field->strings;
7649 return proto_tree_add_boolean_format(tree, hf_index,
7650 tvb, octet_offset, octet_length, (guint32)value,
7652 bf_str, hf_field->name,
7653 (guint32)value ? tfstring->true_string : tfstring->false_string);
7660 pi = proto_tree_add_uint(tree, hf_index, tvb, octet_offset, octet_length, (guint32)value);
7661 fill_label_uint(PITEM_FINFO(pi), lbl_str);
7668 pi = proto_tree_add_int(tree, hf_index, tvb, octet_offset, octet_length, (gint32)value);
7669 fill_label_int(PITEM_FINFO(pi), lbl_str);
7673 pi = proto_tree_add_uint64(tree, hf_index, tvb, octet_offset, octet_length, value);
7674 fill_label_uint64(PITEM_FINFO(pi), lbl_str);
7678 pi = proto_tree_add_int64(tree, hf_index, tvb, octet_offset, octet_length, (gint64)value);
7679 fill_label_int64(PITEM_FINFO(pi), lbl_str);
7683 DISSECTOR_ASSERT_NOT_REACHED();
7687 proto_item_set_text(pi, "%s = %s", bf_str, lbl_str);
7692 proto_tree_add_split_bits_crumb(proto_tree *tree, const int hf_index, tvbuff_t *tvb, const guint bit_offset,
7693 const crumb_spec_t *crumb_spec, guint16 crumb_index)
7695 header_field_info *hf_info;
7697 PROTO_REGISTRAR_GET_NTH(hf_index, hf_info);
7698 proto_tree_add_text(tree, tvb,
7700 ((bit_offset + crumb_spec[crumb_index].crumb_bit_length - 1) >> 3) - (bit_offset >> 3) + 1,
7701 "%s crumb %d of %s (decoded above)",
7702 decode_bits_in_field(bit_offset, crumb_spec[crumb_index].crumb_bit_length,
7705 crumb_spec[crumb_index].crumb_bit_length,
7712 proto_tree_add_bits_ret_val(proto_tree *tree, const int hf_index, tvbuff_t *tvb,
7713 const guint bit_offset, const gint no_of_bits,
7714 guint64 *return_value, const guint encoding)
7718 if ((item = _proto_tree_add_bits_ret_val(tree, hf_index, tvb,
7719 bit_offset, no_of_bits,
7720 return_value, encoding))) {
7721 FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_OFFSET(bit_offset));
7722 FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_SIZE(no_of_bits));
7728 _proto_tree_add_bits_format_value(proto_tree *tree, const int hf_index,
7729 tvbuff_t *tvb, const guint bit_offset,
7730 const gint no_of_bits, void *value_ptr,
7738 header_field_info *hf_field;
7740 /* We do not have to return a value, try to fake it as soon as possible */
7741 TRY_TO_FAKE_THIS_ITEM(tree, hf_index, hf_field);
7743 if (hf_field->bitmask != 0) {
7744 REPORT_DISSECTOR_BUG(ep_strdup_printf(
7745 "Incompatible use of proto_tree_add_bits_format_value"
7746 " with field '%s' (%s) with bitmask != 0",
7747 hf_field->abbrev, hf_field->name));
7750 DISSECTOR_ASSERT(no_of_bits > 0);
7752 /* Byte align offset */
7753 offset = bit_offset>>3;
7756 * Calculate the number of octets used to hold the bits
7758 tot_no_bits = ((bit_offset&0x7) + no_of_bits);
7759 length = tot_no_bits>>3;
7760 /* If we are using part of the next octet, increase length by 1 */
7761 if (tot_no_bits & 0x07)
7764 if (no_of_bits < 65) {
7765 value = tvb_get_bits64(tvb, bit_offset, no_of_bits, ENC_BIG_ENDIAN);
7767 DISSECTOR_ASSERT_NOT_REACHED();
7771 str = decode_bits_in_field(bit_offset, no_of_bits, value);
7774 strcat(str, hf_field->name);
7777 * This function does not receive an actual value but a dimensionless pointer to that value.
7778 * For this reason, the type of the header field is examined in order to determine
7779 * what kind of value we should read from this address.
7780 * The caller of this function must make sure that for the specific header field type the address of
7781 * a compatible value is provided.
7783 switch (hf_field->type) {
7785 return proto_tree_add_boolean_format(tree, hf_index, tvb, offset, length, *(guint32 *)value_ptr,
7786 "%s: %s", str, value_str);
7793 return proto_tree_add_uint_format(tree, hf_index, tvb, offset, length, *(guint32 *)value_ptr,
7794 "%s: %s", str, value_str);
7798 return proto_tree_add_uint64_format(tree, hf_index, tvb, offset, length, *(guint64 *)value_ptr,
7799 "%s: %s", str, value_str);
7806 return proto_tree_add_int_format(tree, hf_index, tvb, offset, length, *(gint32 *)value_ptr,
7807 "%s: %s", str, value_str);
7811 return proto_tree_add_int64_format(tree, hf_index, tvb, offset, length, *(gint64 *)value_ptr,
7812 "%s: %s", str, value_str);
7816 return proto_tree_add_float_format(tree, hf_index, tvb, offset, length, *(float *)value_ptr,
7817 "%s: %s", str, value_str);
7821 DISSECTOR_ASSERT_NOT_REACHED();
7828 proto_tree_add_bits_format_value(proto_tree *tree, const int hf_index,
7829 tvbuff_t *tvb, const guint bit_offset,
7830 const gint no_of_bits, void *value_ptr,
7835 if ((item = _proto_tree_add_bits_format_value(tree, hf_index,
7836 tvb, bit_offset, no_of_bits,
7837 value_ptr, value_str))) {
7838 FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_OFFSET(bit_offset));
7839 FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_SIZE(no_of_bits));
7844 #define CREATE_VALUE_STRING(dst,format,ap) \
7845 va_start(ap, format); \
7846 dst = ep_strdup_vprintf(format, ap); \
7850 proto_tree_add_uint_bits_format_value(proto_tree *tree, const int hf_index,
7851 tvbuff_t *tvb, const guint bit_offset,
7852 const gint no_of_bits, guint32 value,
7853 const char *format, ...)
7857 header_field_info *hf_field;
7859 TRY_TO_FAKE_THIS_ITEM(tree, hf_index, hf_field);
7861 switch (hf_field->type) {
7869 DISSECTOR_ASSERT_NOT_REACHED();
7874 CREATE_VALUE_STRING(dst, format, ap);
7876 return proto_tree_add_bits_format_value(tree, hf_index, tvb, bit_offset, no_of_bits, &value, dst);
7880 proto_tree_add_float_bits_format_value(proto_tree *tree, const int hf_index,
7881 tvbuff_t *tvb, const guint bit_offset,
7882 const gint no_of_bits, float value,
7883 const char *format, ...)
7887 header_field_info *hf_field;
7889 TRY_TO_FAKE_THIS_ITEM(tree, hf_index, hf_field);
7891 DISSECTOR_ASSERT(hf_field->type == FT_FLOAT);
7893 CREATE_VALUE_STRING(dst, format, ap);
7895 return proto_tree_add_bits_format_value(tree, hf_index, tvb, bit_offset, no_of_bits, &value, dst);
7899 proto_tree_add_int_bits_format_value(proto_tree *tree, const int hf_index,
7900 tvbuff_t *tvb, const guint bit_offset,
7901 const gint no_of_bits, gint32 value,
7902 const char *format, ...)
7906 header_field_info *hf_field;
7908 TRY_TO_FAKE_THIS_ITEM(tree, hf_index, hf_field);
7910 switch (hf_field->type) {
7918 DISSECTOR_ASSERT_NOT_REACHED();
7923 CREATE_VALUE_STRING(dst, format, ap);
7925 return proto_tree_add_bits_format_value(tree, hf_index, tvb, bit_offset, no_of_bits, &value, dst);
7929 proto_tree_add_boolean_bits_format_value(proto_tree *tree, const int hf_index,
7930 tvbuff_t *tvb, const guint bit_offset,
7931 const gint no_of_bits, guint32 value,
7932 const char *format, ...)
7936 header_field_info *hf_field;
7938 TRY_TO_FAKE_THIS_ITEM(tree, hf_index, hf_field);
7940 DISSECTOR_ASSERT(hf_field->type == FT_BOOLEAN);
7942 CREATE_VALUE_STRING(dst, format, ap);
7944 return proto_tree_add_bits_format_value(tree, hf_index, tvb, bit_offset, no_of_bits, &value, dst);
7948 proto_check_field_name(const gchar *field_name)
7950 return wrs_check_charset(fld_abbrev_chars, field_name);