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) \
109 g_error("More than %d items in the tree -- possible infinite loop", MAX_TREE_ITEMS); \
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 if((guint)hfindex >= gpa_hfinfo.len && getenv("WIRESHARK_ABORT_ON_DISSECTOR_BUG")) \
297 g_error("Unregistered hf! index=%d", hfindex); \
298 DISSECTOR_ASSERT((guint)hfindex < gpa_hfinfo.len); \
299 hfinfo = gpa_hfinfo.hfi[hfindex];
301 /* List which stores protocols and fields that have been registered */
302 typedef struct _gpa_hfinfo_t {
304 guint32 allocated_len;
305 header_field_info **hfi;
307 gpa_hfinfo_t gpa_hfinfo;
309 /* Balanced tree of abbreviations and IDs */
310 static GTree *gpa_name_tree = NULL;
311 static header_field_info *same_name_hfinfo;
313 static void save_same_name_hfinfo(gpointer data)
315 same_name_hfinfo = (header_field_info*)data;
318 /* Points to the first element of an array of Booleans, indexed by
319 a subtree item type; that array element is TRUE if subtrees of
320 an item of that type are to be expanded. */
321 gboolean *tree_is_expanded;
323 /* Number of elements in that array. */
326 /* Name hashtables for fast detection of duplicate names */
327 static GHashTable* proto_names = NULL;
328 static GHashTable* proto_short_names = NULL;
329 static GHashTable* proto_filter_names = NULL;
332 proto_compare_name(gconstpointer p1_arg, gconstpointer p2_arg)
334 const protocol_t *p1 = p1_arg;
335 const protocol_t *p2 = p2_arg;
337 return g_ascii_strcasecmp(p1->short_name, p2->short_name);
341 /* initialize data structures and register protocols and fields */
343 proto_init(void (register_all_protocols_func)(register_cb cb, gpointer client_data),
344 void (register_all_handoffs_func)(register_cb cb, gpointer client_data),
346 gpointer client_data)
348 static hf_register_info hf[] = {
350 { "Text item", "text", FT_NONE, BASE_NONE, NULL, 0x0,
356 proto_names = g_hash_table_new_full(g_int_hash, g_int_equal, g_free, NULL);
357 proto_short_names = g_hash_table_new(wrs_str_hash, g_str_equal);
358 proto_filter_names = g_hash_table_new(wrs_str_hash, g_str_equal);
361 gpa_hfinfo.allocated_len = 0;
362 gpa_hfinfo.hfi = NULL;
363 gpa_name_tree = g_tree_new_full(wrs_strcmp_with_data, NULL, NULL, save_same_name_hfinfo);
365 /* Initialize the ftype subsystem */
368 /* Register one special-case FT_TEXT_ONLY field for use when
369 converting wireshark to new-style proto_tree. These fields
370 are merely strings on the GUI tree; they are not filterable */
371 proto_register_field_array(-1, hf, array_length(hf));
373 /* Have each built-in dissector register its protocols, fields,
374 dissector tables, and dissectors to be called through a
375 handle, and do whatever one-time initialization it needs to
377 register_all_protocols_func(cb, client_data);
379 /* Now scan for python protocols */
381 (*cb)(RA_PYTHON_REGISTER, NULL, client_data);
382 register_all_py_protocols_func();
386 /* Now scan for plugins and load all the ones we find, calling
387 their register routines to do the stuff described above. */
389 (*cb)(RA_PLUGIN_REGISTER, NULL, client_data);
391 register_all_plugin_registrations();
394 /* Now call the "handoff registration" routines of all built-in
395 dissectors; those routines register the dissector in other
396 dissectors' handoff tables, and fetch any dissector handles
398 register_all_handoffs_func(cb, client_data);
401 /* Now do the same with python dissectors */
403 (*cb)(RA_PYTHON_HANDOFF, NULL, client_data);
404 register_all_py_handoffs_func();
408 /* Now do the same with plugins. */
410 (*cb)(RA_PLUGIN_HANDOFF, NULL, client_data);
411 register_all_plugin_handoffs();
414 /* sort the protocols by protocol name */
415 protocols = g_list_sort(protocols, proto_compare_name);
417 /* We've assigned all the subtree type values; allocate the array
418 for them, and zero it out. */
419 tree_is_expanded = g_new0(gboolean, num_tree_types);
425 /* Free the abbrev/ID GTree */
427 g_tree_destroy(gpa_name_tree);
428 gpa_name_tree = NULL;
432 protocol_t *protocol = protocols->data;
433 header_field_info *hfinfo;
434 PROTO_REGISTRAR_GET_NTH(protocol->proto_id, hfinfo);
435 DISSECTOR_ASSERT(protocol->proto_id == hfinfo->id);
437 g_slice_free(header_field_info, hfinfo);
438 g_list_free(protocol->fields);
439 protocols = g_list_remove(protocols, protocol);
444 g_hash_table_destroy(proto_names);
448 if (proto_short_names) {
449 g_hash_table_destroy(proto_short_names);
450 proto_short_names = NULL;
453 if (proto_filter_names) {
454 g_hash_table_destroy(proto_filter_names);
455 proto_filter_names = NULL;
458 if (gpa_hfinfo.allocated_len) {
460 gpa_hfinfo.allocated_len = 0;
461 g_free(gpa_hfinfo.hfi);
462 gpa_hfinfo.hfi = NULL;
464 g_free(tree_is_expanded);
465 tree_is_expanded = NULL;
469 proto_tree_traverse_pre_order(proto_tree *tree, proto_tree_traverse_func func,
472 proto_node *pnode = tree;
476 if (func(pnode, data))
479 child = pnode->first_child;
480 while (child != NULL) {
482 * The routine we call might modify the child, e.g. by
483 * freeing it, so we get the child's successor before
484 * calling that routine.
487 child = current->next;
488 if (proto_tree_traverse_pre_order((proto_tree *)current, func, data))
496 proto_tree_traverse_post_order(proto_tree *tree, proto_tree_traverse_func func,
499 proto_node *pnode = tree;
503 child = pnode->first_child;
504 while (child != NULL) {
506 * The routine we call might modify the child, e.g. by
507 * freeing it, so we get the child's successor before
508 * calling that routine.
511 child = current->next;
512 if (proto_tree_traverse_post_order((proto_tree *)current, func, data))
515 if (func(pnode, data))
522 proto_tree_children_foreach(proto_tree *tree, proto_tree_foreach_func func,
525 proto_node *node = tree;
528 node = node->first_child;
529 while (node != NULL) {
531 node = current->next;
532 func((proto_tree *)current, data);
537 free_GPtrArray_value(gpointer key, gpointer value, gpointer user_data _U_)
539 GPtrArray *ptrs = value;
540 gint hfid = (gint)(long)key;
541 header_field_info *hfinfo;
543 PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
544 if (hfinfo->ref_type != HF_REF_TYPE_NONE) {
545 /* when a field is referenced by a filter this also
546 affects the refcount for the parent protocol so we need
547 to adjust the refcount for the parent as well
549 if (hfinfo->parent != -1) {
550 header_field_info *parent_hfinfo;
551 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
552 parent_hfinfo->ref_type = HF_REF_TYPE_NONE;
554 hfinfo->ref_type = HF_REF_TYPE_NONE;
557 g_ptr_array_free(ptrs, TRUE);
561 free_node_tree_data(tree_data_t *tree_data)
563 if (tree_data->interesting_hfids) {
564 /* Free all the GPtrArray's in the interesting_hfids hash. */
565 g_hash_table_foreach(tree_data->interesting_hfids,
566 free_GPtrArray_value, NULL);
568 /* And then destroy the hash. */
569 g_hash_table_destroy(tree_data->interesting_hfids);
571 if (tree_data->fi_tmp)
572 FIELD_INFO_FREE(tree_data->fi_tmp);
574 /* And finally the tree_data_t itself. */
578 #define FREE_NODE_FIELD_INFO(finfo) \
580 ITEM_LABEL_FREE(finfo->rep); \
582 FVALUE_CLEANUP(&finfo->value); \
583 FIELD_INFO_FREE(finfo);
586 proto_tree_free_node(proto_node *node, gpointer data _U_)
588 field_info *finfo = PNODE_FINFO(node);
590 proto_tree_children_foreach(node, proto_tree_free_node, NULL);
592 /* free the field_info data. */
593 FREE_NODE_FIELD_INFO(finfo);
595 /* Free the proto_node. */
596 PROTO_NODE_FREE(node);
599 /* frees the resources that the dissection a proto_tree uses */
601 proto_tree_free(proto_tree *tree)
603 tree_data_t *tree_data = PTREE_DATA(tree);
605 proto_tree_children_foreach(tree, proto_tree_free_node, NULL);
608 PROTO_NODE_FREE(tree);
611 free_node_tree_data(tree_data);
614 /* Is the parsing being done for a visible proto_tree or an invisible one?
615 * By setting this correctly, the proto_tree creation is sped up by not
616 * having to call g_vsnprintf and copy strings around.
619 proto_tree_set_visible(proto_tree *tree, gboolean visible)
621 gboolean old_visible = PTREE_DATA(tree)->visible;
623 PTREE_DATA(tree)->visible = visible;
629 proto_tree_set_fake_protocols(proto_tree *tree, gboolean fake_protocols)
631 PTREE_DATA(tree)->fake_protocols = fake_protocols;
634 /* Assume dissector set only its protocol fields.
635 This function is called by dissectors and allows the speeding up of filtering
636 in wireshark; if this function returns FALSE it is safe to reset tree to NULL
637 and thus skip calling most of the expensive proto_tree_add_...()
639 If the tree is visible we implicitly assume the field is referenced.
642 proto_field_is_referenced(proto_tree *tree, int proto_id)
644 register header_field_info *hfinfo;
650 if (PTREE_DATA(tree)->visible)
653 PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
654 if (hfinfo->ref_type != HF_REF_TYPE_NONE)
657 if (hfinfo->type == FT_PROTOCOL && !PTREE_DATA(tree)->fake_protocols)
664 /* Finds a record in the hf_info_records array by id. */
666 proto_registrar_get_nth(guint hfindex)
668 register header_field_info *hfinfo;
670 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
675 /* Prefix initialization
676 * this allows for a dissector to register a display filter name prefix
677 * so that it can delay the initialization of the hf array as long as
681 /* compute a hash for the part before the dot of a display filter */
683 prefix_hash (gconstpointer key) {
684 /* end the string at the dot and compute its hash */
685 gchar* copy = ep_strdup(key);
695 return g_str_hash(copy);
698 /* are both strings equal up to the end or the dot? */
700 prefix_equal (gconstpointer ap, gconstpointer bp) {
708 if ( (ac == '.' || ac == '\0') && (bc == '.' || bc == '\0') ) return TRUE;
710 if ( (ac == '.' || ac == '\0') && ! (bc == '.' || bc == '\0') ) return FALSE;
711 if ( (bc == '.' || bc == '\0') && ! (ac == '.' || ac == '\0') ) return FALSE;
713 if (ac != bc) return FALSE;
720 /* indexed by prefix, contains initializers */
721 static GHashTable* prefixes = NULL;
724 /* Register a new prefix for "delayed" initialization of field arrays */
726 proto_register_prefix(const char *prefix, prefix_initializer_t pi ) {
728 prefixes = g_hash_table_new(prefix_hash, prefix_equal);
731 g_hash_table_insert(prefixes, (gpointer)prefix, pi);
734 /* helper to call all prefix initializers */
736 initialize_prefix(gpointer k, gpointer v, gpointer u _U_) {
737 ((prefix_initializer_t)v)(k);
741 /** Initialize every remaining uninitialized prefix. */
743 proto_initialize_all_prefixes(void) {
744 g_hash_table_foreach_remove(prefixes, initialize_prefix, NULL);
747 /* Finds a record in the hf_info_records array by name.
748 * If it fails to find it in the already registered fields,
749 * it tries to find and call an initializer in the prefixes
750 * table and if so it looks again.
753 proto_registrar_get_byname(const char *field_name)
755 header_field_info *hfinfo;
756 prefix_initializer_t pi;
761 hfinfo = g_tree_lookup(gpa_name_tree, field_name);
769 if ((pi = g_hash_table_lookup(prefixes, field_name) ) != NULL) {
771 g_hash_table_remove(prefixes, field_name);
776 return g_tree_lookup(gpa_name_tree, field_name);
781 ptvcursor_new_subtree_levels(ptvcursor_t *ptvc)
783 subtree_lvl *pushed_tree;
785 DISSECTOR_ASSERT(ptvc->pushed_tree_max <= SUBTREE_MAX_LEVELS-SUBTREE_ONCE_ALLOCATION_NUMBER);
786 ptvc->pushed_tree_max += SUBTREE_ONCE_ALLOCATION_NUMBER;
788 pushed_tree = ep_alloc(sizeof(subtree_lvl) * ptvc->pushed_tree_max);
789 DISSECTOR_ASSERT(pushed_tree != NULL);
790 if (ptvc->pushed_tree)
791 memcpy(pushed_tree, ptvc->pushed_tree, ptvc->pushed_tree_max - SUBTREE_ONCE_ALLOCATION_NUMBER);
792 ptvc->pushed_tree = pushed_tree;
796 ptvcursor_free_subtree_levels(ptvcursor_t *ptvc)
798 ptvc->pushed_tree = NULL;
799 ptvc->pushed_tree_max = 0;
800 DISSECTOR_ASSERT(ptvc->pushed_tree_index == 0);
801 ptvc->pushed_tree_index = 0;
804 /* Allocates an initializes a ptvcursor_t with 3 variables:
805 * proto_tree, tvbuff, and offset. */
807 ptvcursor_new(proto_tree *tree, tvbuff_t *tvb, gint offset)
811 ptvc = ep_alloc(sizeof(ptvcursor_t));
814 ptvc->offset = offset;
815 ptvc->pushed_tree = NULL;
816 ptvc->pushed_tree_max = 0;
817 ptvc->pushed_tree_index = 0;
822 /* Frees memory for ptvcursor_t, but nothing deeper than that. */
824 ptvcursor_free(ptvcursor_t *ptvc)
826 ptvcursor_free_subtree_levels(ptvc);
830 /* Returns tvbuff. */
832 ptvcursor_tvbuff(ptvcursor_t *ptvc)
837 /* Returns current offset. */
839 ptvcursor_current_offset(ptvcursor_t *ptvc)
845 ptvcursor_tree(ptvcursor_t *ptvc)
854 ptvcursor_set_tree(ptvcursor_t *ptvc, proto_tree *tree)
859 /* creates a subtree, sets it as the working tree and pushes the old working tree */
861 ptvcursor_push_subtree(ptvcursor_t *ptvc, proto_item *it, gint ett_subtree)
863 subtree_lvl *subtree;
864 if (ptvc->pushed_tree_index >= ptvc->pushed_tree_max)
865 ptvcursor_new_subtree_levels(ptvc);
867 subtree = ptvc->pushed_tree + ptvc->pushed_tree_index;
868 subtree->tree = ptvc->tree;
870 ptvc->pushed_tree_index++;
871 return ptvcursor_set_subtree(ptvc, it, ett_subtree);
876 ptvcursor_pop_subtree(ptvcursor_t *ptvc)
878 subtree_lvl *subtree;
880 if (ptvc->pushed_tree_index <= 0)
883 ptvc->pushed_tree_index--;
884 subtree = ptvc->pushed_tree + ptvc->pushed_tree_index;
885 if (subtree->it != NULL)
886 proto_item_set_len(subtree->it, ptvcursor_current_offset(ptvc) - subtree->cursor_offset);
888 ptvc->tree = subtree->tree;
891 /* saves the current tvb offset and the item in the current subtree level */
893 ptvcursor_subtree_set_item(ptvcursor_t *ptvc, proto_item *it)
895 subtree_lvl *subtree;
897 DISSECTOR_ASSERT(ptvc->pushed_tree_index > 0);
899 subtree = ptvc->pushed_tree + ptvc->pushed_tree_index - 1;
901 subtree->cursor_offset = ptvcursor_current_offset(ptvc);
904 /* Creates a subtree and adds it to the cursor as the working tree but does not
905 * save the old working tree */
907 ptvcursor_set_subtree(ptvcursor_t *ptvc, proto_item *it, gint ett_subtree)
909 ptvc->tree = proto_item_add_subtree(it, ett_subtree);
914 ptvcursor_add_subtree_item(ptvcursor_t *ptvc, proto_item *it, gint ett_subtree, gint length)
916 ptvcursor_push_subtree(ptvc, it, ett_subtree);
917 if (length == SUBTREE_UNDEFINED_LENGTH)
918 ptvcursor_subtree_set_item(ptvc, it);
919 return ptvcursor_tree(ptvc);
922 /* Add an item to the tree and create a subtree
923 * If the length is unknown, length may be defined as SUBTREE_UNDEFINED_LENGTH.
924 * In this case, when the subtree will be closed, the parent item length will
925 * be equal to the advancement of the cursor since the creation of the subtree.
928 ptvcursor_add_with_subtree(ptvcursor_t *ptvc, int hfindex, gint length,
929 const guint encoding, gint ett_subtree)
933 it = ptvcursor_add_no_advance(ptvc, hfindex, length, encoding);
934 return ptvcursor_add_subtree_item(ptvc, it, ett_subtree, length);
938 proto_tree_add_text_node(proto_tree *tree, tvbuff_t *tvb, gint start, gint length);
940 /* Add a text node to the tree and create a subtree
941 * If the length is unknown, length may be defined as SUBTREE_UNDEFINED_LENGTH.
942 * In this case, when the subtree will be closed, the item length will be equal
943 * to the advancement of the cursor since the creation of the subtree.
946 ptvcursor_add_text_with_subtree(ptvcursor_t *ptvc, gint length,
947 gint ett_subtree, const char *format, ...)
951 header_field_info *hfinfo;
954 tree = ptvcursor_tree(ptvc);
956 TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
958 pi = proto_tree_add_text_node(tree, ptvcursor_tvbuff(ptvc),
959 ptvcursor_current_offset(ptvc), length);
961 TRY_TO_FAKE_THIS_REPR(tree, pi);
963 va_start(ap, format);
964 proto_tree_set_representation(pi, format, ap);
967 return ptvcursor_add_subtree_item(ptvc, pi, ett_subtree, length);
970 /* Add a text-only node, leaving it to our caller to fill the text in */
972 proto_tree_add_text_node(proto_tree *tree, tvbuff_t *tvb, gint start, gint length)
976 pi = proto_tree_add_pi(tree, hf_text_only, tvb, start, &length, NULL);
981 /* Add a text-only node to the proto_tree */
983 proto_tree_add_text(proto_tree *tree, tvbuff_t *tvb, gint start, gint length,
984 const char *format, ...)
988 header_field_info *hfinfo;
990 TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
992 pi = proto_tree_add_text_node(tree, tvb, start, length);
994 TRY_TO_FAKE_THIS_REPR(tree, pi);
996 va_start(ap, format);
997 proto_tree_set_representation(pi, format, ap);
1003 /* Add a text-only node to the proto_tree (va_list version) */
1005 proto_tree_add_text_valist(proto_tree *tree, tvbuff_t *tvb, gint start,
1006 gint length, const char *format, va_list ap)
1009 header_field_info *hfinfo;
1011 TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
1013 pi = proto_tree_add_text_node(tree, tvb, start, length);
1015 TRY_TO_FAKE_THIS_REPR(tree, pi);
1017 proto_tree_set_representation(pi, format, ap);
1022 /* Add a text-only node for debugging purposes. The caller doesn't need
1023 * to worry about tvbuff, start, or length. Debug message gets sent to
1026 proto_tree_add_debug_text(proto_tree *tree, const char *format, ...)
1031 pi = proto_tree_add_text_node(tree, NULL, 0, 0);
1034 va_start(ap, format);
1035 proto_tree_set_representation(pi, format, ap);
1038 va_start(ap, format);
1039 vprintf(format, ap);
1046 /* We could probably get away with changing is_error to a minimum length value. */
1048 report_type_length_mismatch(proto_tree *tree, const gchar *descr, int length, gboolean is_error) {
1049 tree_data_t *tree_data = PTREE_DATA(tree);
1050 field_info *fi_save = tree_data->fi_tmp;
1052 /* Keep the current item from getting freed by proto_tree_new_item. */
1053 tree_data->fi_tmp = NULL;
1055 expert_add_info_format(NULL, tree, PI_MALFORMED, is_error ? PI_ERROR : PI_WARN, "Trying to fetch %s with length %d", descr, length);
1057 tree_data->fi_tmp = fi_save;
1060 THROW(ReportedBoundsError);
1065 * NOTE: to support code written when proto_tree_add_item() took a
1066 * gboolean as its last argument, with FALSE meaning "big-endian"
1067 * and TRUE meaning "little-endian", we treat any non-zero value of
1068 * "encoding" as meaning "little-endian".
1071 get_uint_value(proto_tree *tree, tvbuff_t *tvb, gint offset, gint length, const guint encoding)
1074 gboolean length_error;
1079 value = tvb_get_guint8(tvb, offset);
1083 value = encoding ? tvb_get_letohs(tvb, offset)
1084 : tvb_get_ntohs(tvb, offset);
1088 value = encoding ? tvb_get_letoh24(tvb, offset)
1089 : tvb_get_ntoh24(tvb, offset);
1093 value = encoding ? tvb_get_letohl(tvb, offset)
1094 : tvb_get_ntohl(tvb, offset);
1099 length_error = TRUE;
1102 length_error = FALSE;
1103 value = encoding ? tvb_get_letohl(tvb, offset)
1104 : tvb_get_ntohl(tvb, offset);
1106 report_type_length_mismatch(tree, "an unsigned integer", length, length_error);
1113 * NOTE: to support code written when proto_tree_add_item() took a
1114 * gboolean as its last argument, with FALSE meaning "big-endian"
1115 * and TRUE meaning "little-endian", we treat any non-zero value of
1116 * "encoding" as meaning "little-endian".
1119 get_int_value(proto_tree *tree, tvbuff_t *tvb, gint offset, gint length, const guint encoding)
1122 gboolean length_error;
1127 value = (gint8)tvb_get_guint8(tvb, offset);
1131 value = (gint16) (encoding ? tvb_get_letohs(tvb, offset)
1132 : tvb_get_ntohs(tvb, offset));
1136 value = encoding ? tvb_get_letoh24(tvb, offset)
1137 : tvb_get_ntoh24(tvb, offset);
1138 if (value & 0x00800000) {
1139 /* Sign bit is set; sign-extend it. */
1140 value |= 0xFF000000;
1145 value = encoding ? tvb_get_letohl(tvb, offset)
1146 : tvb_get_ntohl(tvb, offset);
1151 length_error = TRUE;
1154 length_error = FALSE;
1155 value = encoding ? tvb_get_letohl(tvb, offset)
1156 : tvb_get_ntohl(tvb, offset);
1158 report_type_length_mismatch(tree, "a signed integer", length, length_error);
1165 proto_lookup_or_create_interesting_hfids(proto_tree *tree,
1166 header_field_info *hfinfo)
1168 GPtrArray *ptrs = NULL;
1170 DISSECTOR_ASSERT(tree);
1171 DISSECTOR_ASSERT(hfinfo);
1173 if (hfinfo->ref_type == HF_REF_TYPE_DIRECT) {
1174 if (PTREE_DATA(tree)->interesting_hfids == NULL) {
1175 /* Initialize the hash because we now know that it is needed */
1176 PTREE_DATA(tree)->interesting_hfids =
1177 g_hash_table_new(g_direct_hash, NULL /* g_direct_equal */);
1180 ptrs = g_hash_table_lookup(PTREE_DATA(tree)->interesting_hfids,
1181 GINT_TO_POINTER(hfinfo->id));
1183 /* First element triggers the creation of pointer array */
1184 ptrs = g_ptr_array_new();
1185 g_hash_table_insert(PTREE_DATA(tree)->interesting_hfids,
1186 GINT_TO_POINTER(hfinfo->id), ptrs);
1193 /* Add an item to a proto_tree, using the text label registered to that item;
1194 the item is extracted from the tvbuff handed to it. */
1196 proto_tree_new_item(field_info *new_fi, proto_tree *tree,
1197 tvbuff_t *tvb, gint start, gint length,
1200 tree_data_t *tree_data = PTREE_DATA(tree);
1206 nstime_t time_stamp;
1209 gboolean length_error;
1211 /* there is a possibility here that we might raise an exception
1212 * and thus would lose track of the field_info.
1213 * store it in a temp so that if we come here again we can reclaim
1214 * the field_info without leaking memory.
1216 if (tree_data->fi_tmp) {
1217 /* oops, last one we got must have been lost due
1219 * good thing we saved it, now we can reverse the
1220 * memory leak and reclaim it.
1222 FIELD_INFO_FREE(tree_data->fi_tmp);
1224 /* we might throw an exception, keep track of this one
1225 * across the "dangerous" section below.
1227 tree_data->fi_tmp = new_fi;
1229 switch (new_fi->hfinfo->type) {
1231 /* no value to set for FT_NONE */
1235 proto_tree_set_protocol_tvb(new_fi, tvb);
1239 proto_tree_set_bytes_tvb(new_fi, tvb, start, length);
1244 * Map all non-zero values to little-endian for
1245 * backwards compatibility.
1248 encoding = ENC_LITTLE_ENDIAN;
1249 n = get_uint_value(tree, tvb, start, length, encoding);
1250 proto_tree_set_bytes_tvb(new_fi, tvb, start + length, n);
1252 /* Instead of calling proto_item_set_len(), since we don't yet
1253 * have a proto_item, we set the field_info's length ourselves. */
1254 new_fi->length = n + length;
1259 * Map all non-zero values to little-endian for
1260 * backwards compatibility.
1263 encoding = ENC_LITTLE_ENDIAN;
1264 proto_tree_set_boolean(new_fi,
1265 get_uint_value(tree, tvb, start, length, encoding));
1268 /* XXX - make these just FT_UINT? */
1274 * Map all non-zero values to little-endian for
1275 * backwards compatibility.
1278 encoding = ENC_LITTLE_ENDIAN;
1279 proto_tree_set_uint(new_fi,
1280 get_uint_value(tree, tvb, start, length, encoding));
1286 * Map all non-zero values to little-endian for
1287 * backwards compatibility.
1290 encoding = ENC_LITTLE_ENDIAN;
1291 if (length < 1 || length > 8) {
1292 length_error = length < 1 ? TRUE : FALSE;
1293 report_type_length_mismatch(tree, "a 64-bit integer", length, length_error);
1295 proto_tree_set_uint64_tvb(new_fi, tvb, start, length, encoding);
1298 /* XXX - make these just FT_INT? */
1304 * Map all non-zero values to little-endian for
1305 * backwards compatibility.
1308 encoding = ENC_LITTLE_ENDIAN;
1309 proto_tree_set_int(new_fi,
1310 get_int_value(tree, tvb, start, length, encoding));
1315 * Map all non-zero values to little-endian for
1316 * backwards compatibility.
1319 encoding = ENC_LITTLE_ENDIAN;
1320 if (length != FT_IPv4_LEN) {
1321 length_error = length < FT_IPv4_LEN ? TRUE : FALSE;
1322 report_type_length_mismatch(tree, "an IPv4 address", length, length_error);
1324 value = tvb_get_ipv4(tvb, start);
1326 * NOTE: to support code written when
1327 * proto_tree_add_item() took a gboolean as its
1328 * last argument, with FALSE meaning "big-endian"
1329 * and TRUE meaning "little-endian", we treat any
1330 * non-zero value of "encoding" as meaning
1333 proto_tree_set_ipv4(new_fi, encoding ? GUINT32_SWAP_LE_BE(value) : value);
1337 if (length != FT_IPXNET_LEN) {
1338 length_error = length < FT_IPXNET_LEN ? TRUE : FALSE;
1339 report_type_length_mismatch(tree, "an IPXNET address", length, length_error);
1341 proto_tree_set_ipxnet(new_fi,
1342 get_uint_value(tree, tvb, start, FT_IPXNET_LEN, FALSE));
1346 if (length != FT_IPv6_LEN) {
1347 length_error = length < FT_IPv6_LEN ? TRUE : FALSE;
1348 report_type_length_mismatch(tree, "an IPv6 address", length, length_error);
1350 proto_tree_set_ipv6_tvb(new_fi, tvb, start, length);
1355 length_error = length < 7 ? TRUE : FALSE;
1356 expert_add_info_format(NULL, tree, PI_MALFORMED, PI_ERROR, "Trying to fetch an AX.25 address with length %d", length);
1357 THROW(ReportedBoundsError);
1359 proto_tree_set_ax25_tvb(new_fi, tvb, start);
1363 if (length != FT_ETHER_LEN) {
1364 length_error = length < FT_ETHER_LEN ? TRUE : FALSE;
1365 report_type_length_mismatch(tree, "an Ethernet", length, length_error);
1367 proto_tree_set_ether_tvb(new_fi, tvb, start);
1372 * Map all non-zero values to little-endian for
1373 * backwards compatibility.
1376 encoding = ENC_LITTLE_ENDIAN;
1377 if (length != FT_EUI64_LEN) {
1378 length_error = length < FT_EUI64_LEN ? TRUE : FALSE;
1379 report_type_length_mismatch(tree, "an EUI-64 address", length, length_error);
1381 proto_tree_set_eui64_tvb(new_fi, tvb, start, encoding);
1385 * Map all non-zero values to little-endian for
1386 * backwards compatibility.
1389 encoding = ENC_LITTLE_ENDIAN;
1390 if (length != FT_GUID_LEN) {
1391 length_error = length < FT_GUID_LEN ? TRUE : FALSE;
1392 report_type_length_mismatch(tree, "a GUID", length, length_error);
1394 proto_tree_set_guid_tvb(new_fi, tvb, start, encoding);
1398 proto_tree_set_oid_tvb(new_fi, tvb, start, length);
1403 * NOTE: to support code written when
1404 * proto_tree_add_item() took a gboolean as its
1405 * last argument, with FALSE meaning "big-endian"
1406 * and TRUE meaning "little-endian", we treat any
1407 * non-zero value of "encoding" as meaning
1410 * At some point in the future, we might
1411 * support non-IEEE-binary floating-point
1412 * formats in the encoding as well
1413 * (IEEE decimal, System/3x0, VAX).
1416 encoding = ENC_LITTLE_ENDIAN;
1418 length_error = length < 4 ? TRUE : FALSE;
1419 report_type_length_mismatch(tree, "a single-precision floating point number", length, length_error);
1422 floatval = tvb_get_letohieee_float(tvb, start);
1424 floatval = tvb_get_ntohieee_float(tvb, start);
1425 proto_tree_set_float(new_fi, floatval);
1430 * NOTE: to support code written when
1431 * proto_tree_add_item() took a gboolean as its
1432 * last argument, with FALSE meaning "big-endian"
1433 * and TRUE meaning "little-endian", we treat any
1434 * non-zero value of "encoding" as meaning
1437 * At some point in the future, we might
1438 * support non-IEEE-binary floating-point
1439 * formats in the encoding as well
1440 * (IEEE decimal, System/3x0, VAX).
1442 if (encoding == TRUE)
1443 encoding = ENC_LITTLE_ENDIAN;
1445 length_error = length < 8 ? TRUE : FALSE;
1446 report_type_length_mismatch(tree, "a double-precision floating point number", length, length_error);
1449 doubleval = tvb_get_letohieee_double(tvb, start);
1451 doubleval = tvb_get_ntohieee_double(tvb, start);
1452 proto_tree_set_double(new_fi, doubleval);
1456 proto_tree_set_string_tvb(new_fi, tvb, start, length,
1462 report_type_length_mismatch(tree, "a string", length, TRUE);
1464 /* Instead of calling proto_item_set_len(),
1465 * since we don't yet have a proto_item, we
1466 * set the field_info's length ourselves.
1468 * XXX - our caller can't use that length to
1469 * advance an offset unless they arrange that
1470 * there always be a protocol tree into which
1471 * we're putting this item.
1474 /* This can throw an exception */
1475 string = tvb_get_stringz_enc(tvb, start, &length, encoding);
1476 } else if (length == 0) {
1479 /* In this case, length signifies
1480 * the length of the string.
1482 * This could either be a null-padded
1483 * string, which doesn't necessarily
1484 * have a '\0' at the end, or a
1485 * null-terminated string, with a
1486 * trailing '\0'. (Yes, there are
1487 * cases where you have a string
1488 * that's both counted and null-
1491 * In the first case, we must
1492 * allocate a buffer of length
1493 * "length+1", to make room for
1496 * In the second case, we don't
1497 * assume that there is a trailing
1498 * '\0' there, as the packet might
1499 * be malformed. (XXX - should we
1500 * throw an exception if there's no
1501 * trailing '\0'?) Therefore, we
1502 * allocate a buffer of length
1503 * "length+1", and put in a trailing
1504 * '\0', just to be safe.
1506 * (XXX - this would change if
1507 * we made string values counted
1508 * rather than null-terminated.)
1510 string = tvb_get_ephemeral_string_enc(tvb, start, length, encoding);
1512 new_fi->length = length;
1513 proto_tree_set_string(new_fi, string);
1516 case FT_UINT_STRING:
1518 * NOTE: to support code written when
1519 * proto_tree_add_item() took a gboolean as its
1520 * last argument, with FALSE meaning "big-endian"
1521 * and TRUE meaning "little-endian", if the
1522 * encoding value is TRUE, treat that as
1523 * ASCII with a little-endian length.
1525 * This won't work for code that passes
1526 * arbitrary non-zero values; that code
1527 * will need to be fixed.
1529 if (encoding == TRUE)
1530 encoding = ENC_ASCII|ENC_LITTLE_ENDIAN;
1531 n = get_uint_value(tree, tvb, start, length, encoding & ~ENC_CHARENCODING_MASK);
1532 proto_tree_set_string_tvb(new_fi, tvb, start + length, n,
1535 /* Instead of calling proto_item_set_len(), since we
1536 * don't yet have a proto_item, we set the
1537 * field_info's length ourselves.
1539 * XXX - our caller can't use that length to
1540 * advance an offset unless they arrange that
1541 * there always be a protocol tree into which
1542 * we're putting this item.
1544 new_fi->length = n + length;
1547 case FT_ABSOLUTE_TIME:
1549 * Absolute times can be in any of a number of
1550 * formats, and they can be big-endian or
1553 * Historically FT_TIMEs were only timespecs;
1554 * the only question was whether they were stored
1555 * in big- or little-endian format.
1557 * For backwards compatibility, we interpret an
1558 * encoding of 1 as meaning "little-endian timespec",
1559 * so that passing TRUE is interpreted as that.
1561 if (encoding == TRUE)
1562 encoding = ENC_TIME_TIMESPEC|ENC_LITTLE_ENDIAN;
1564 if (length != 8 && length != 4) {
1565 length_error = length < 4 ? TRUE : FALSE;
1566 report_type_length_mismatch(tree, "an absolute time value", length, length_error);
1571 case ENC_TIME_TIMESPEC|ENC_BIG_ENDIAN:
1573 * 4-byte UNIX epoch, possibly followed by
1574 * 4-byte fractional time in nanoseconds,
1577 time_stamp.secs = tvb_get_ntohl(tvb, start);
1579 time_stamp.nsecs = tvb_get_ntohl(tvb, start+4);
1581 time_stamp.nsecs = 0;
1584 case ENC_TIME_TIMESPEC|ENC_LITTLE_ENDIAN:
1586 * 4-byte UNIX epoch, possibly followed by
1587 * 4-byte fractional time in nanoseconds,
1588 * both little-endian.
1590 time_stamp.secs = tvb_get_letohl(tvb, start);
1592 time_stamp.nsecs = tvb_get_letohl(tvb, start+4);
1594 time_stamp.nsecs = 0;
1597 case ENC_TIME_NTP|ENC_BIG_ENDIAN:
1599 * NTP time stamp, big-endian.
1602 /* XXX - where should this go? */
1603 #define NTP_BASETIME 2208988800ul
1605 /* We need a temporary variable here so the unsigned math
1606 * works correctly (for years > 2036 according to RFC 2030
1609 tmpsecs = tvb_get_ntohl(tvb, start);
1611 time_stamp.secs = tmpsecs - (guint32)NTP_BASETIME;
1613 time_stamp.secs = tmpsecs; /* 0 */
1617 * We're using nanoseconds here (and we will
1618 * display nanoseconds), but NTP's timestamps
1619 * have a precision in microseconds or greater.
1620 * Round to 1 microsecond.
1622 time_stamp.nsecs = (int)(1000000*(tvb_get_ntohl(tvb, start+4)/4294967296.0));
1623 time_stamp.nsecs *= 1000;
1625 time_stamp.nsecs = 0;
1629 case ENC_TIME_NTP|ENC_LITTLE_ENDIAN:
1631 * NTP time stamp, big-endian.
1633 tmpsecs = tvb_get_letohl(tvb, start);
1635 time_stamp.secs = tmpsecs - (guint32)NTP_BASETIME;
1637 time_stamp.secs = tmpsecs; /* 0 */
1641 * We're using nanoseconds here (and we will
1642 * display nanoseconds), but NTP's timestamps
1643 * have a precision in microseconds or greater.
1644 * Round to 1 microsecond.
1646 time_stamp.nsecs = (int)(1000000*(tvb_get_letohl(tvb, start+4)/4294967296.0));
1647 time_stamp.nsecs *= 1000;
1649 time_stamp.nsecs = 0;
1654 DISSECTOR_ASSERT_NOT_REACHED();
1655 time_stamp.secs = 0;
1656 time_stamp.nsecs = 0;
1659 proto_tree_set_time(new_fi, &time_stamp);
1662 case FT_RELATIVE_TIME:
1664 * Relative times can be in any of a number of
1665 * formats, and they can be big-endian or
1668 * Historically FT_TIMEs were only timespecs;
1669 * the only question was whether they were stored
1670 * in big- or little-endian format.
1672 * For backwards compatibility, we interpret an
1673 * encoding of 1 as meaning "little-endian timespec",
1674 * so that passing TRUE is interpreted as that.
1676 if (encoding == TRUE)
1677 encoding = ENC_TIME_TIMESPEC|ENC_LITTLE_ENDIAN;
1680 if (length != 8 && length != 4) {
1681 length_error = length < 4 ? TRUE : FALSE;
1682 report_type_length_mismatch(tree, "a relative time value", length, length_error);
1685 case ENC_TIME_TIMESPEC|ENC_BIG_ENDIAN:
1687 * 4-byte UNIX epoch, possibly followed by
1688 * 4-byte fractional time in nanoseconds,
1691 time_stamp.secs = tvb_get_ntohl(tvb, start);
1693 time_stamp.nsecs = tvb_get_ntohl(tvb, start+4);
1695 time_stamp.nsecs = 0;
1698 case ENC_TIME_TIMESPEC|ENC_LITTLE_ENDIAN:
1700 * 4-byte UNIX epoch, possibly followed by
1701 * 4-byte fractional time in nanoseconds,
1702 * both little-endian.
1704 time_stamp.secs = tvb_get_letohl(tvb, start);
1706 time_stamp.nsecs = tvb_get_letohl(tvb, start+4);
1708 time_stamp.nsecs = 0;
1711 proto_tree_set_time(new_fi, &time_stamp);
1715 g_error("new_fi->hfinfo->type %d (%s) not handled\n",
1716 new_fi->hfinfo->type,
1717 ftype_name(new_fi->hfinfo->type));
1718 DISSECTOR_ASSERT_NOT_REACHED();
1721 FI_SET_FLAG(new_fi, (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN);
1723 /* Don't add new node to proto_tree until now so that any exceptions
1724 * raised by a tvbuff access method doesn't leave junk in the proto_tree. */
1725 /* XXX. wouldn't be better to add this item to tree, with some special flag (FI_EXCEPTION?)
1726 * to know which item caused exception? */
1727 pi = proto_tree_add_node(tree, new_fi);
1729 /* we did not raise an exception so we dont have to remember this
1730 * field_info struct any more.
1732 tree_data->fi_tmp = NULL;
1734 /* If the proto_tree wants to keep a record of this finfo
1735 * for quick lookup, then record it. */
1736 ptrs = proto_lookup_or_create_interesting_hfids(tree, new_fi->hfinfo);
1738 g_ptr_array_add(ptrs, new_fi);
1743 /* Gets data from tvbuff, adds it to proto_tree, increments offset,
1744 and returns proto_item* */
1746 ptvcursor_add(ptvcursor_t *ptvc, int hfindex, gint length,
1747 const guint encoding)
1750 header_field_info *hfinfo;
1755 /* We can't fake it just yet. We have to advance the cursor
1756 TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfindex, hfinfo); */
1758 offset = ptvc->offset;
1759 hfinfo = get_hfi_and_length(hfindex, ptvc->tvb, offset, &length,
1761 ptvc->offset += length;
1762 if (hfinfo->type == FT_UINT_BYTES || hfinfo->type == FT_UINT_STRING) {
1764 * The length of the rest of the item is in the first N
1765 * bytes of the item.
1767 n = get_uint_value(ptvc->tree, ptvc->tvb, offset, length, encoding);
1771 /* Coast clear. Try and fake it */
1772 TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfindex, hfinfo);
1774 new_fi = new_field_info(ptvc->tree, hfinfo, ptvc->tvb, offset, item_length);
1776 return proto_tree_new_item(new_fi, ptvc->tree, ptvc->tvb,
1777 offset, length, encoding);
1780 /* Add an item to a proto_tree, using the text label registered to that item;
1781 the item is extracted from the tvbuff handed to it. */
1783 proto_tree_add_item(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
1784 const gint start, gint length, const guint encoding)
1787 header_field_info *hfinfo;
1789 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1791 new_fi = alloc_field_info(tree, hfindex, tvb, start, &length);
1796 return proto_tree_new_item(new_fi, tree, tvb, start,
1800 /* Add a FT_NONE to a proto_tree */
1802 proto_tree_add_none_format(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
1803 const gint start, gint length, const char *format,
1808 header_field_info *hfinfo;
1810 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1812 DISSECTOR_ASSERT(hfinfo->type == FT_NONE);
1814 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, NULL);
1816 TRY_TO_FAKE_THIS_REPR(tree, pi);
1818 va_start(ap, format);
1819 proto_tree_set_representation(pi, format, ap);
1822 /* no value to set for FT_NONE */
1826 /* Gets data from tvbuff, adds it to proto_tree, *DOES NOT* increment
1827 * offset, and returns proto_item* */
1829 ptvcursor_add_no_advance(ptvcursor_t* ptvc, int hf, gint length,
1830 const guint encoding)
1834 item = proto_tree_add_item(ptvc->tree, hf, ptvc->tvb, ptvc->offset,
1840 /* Advance the ptvcursor's offset within its tvbuff without
1841 * adding anything to the proto_tree. */
1843 ptvcursor_advance(ptvcursor_t* ptvc, gint length)
1845 ptvc->offset += length;
1850 proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb)
1852 fvalue_set(&fi->value, tvb, TRUE);
1855 /* Add a FT_PROTOCOL to a proto_tree */
1857 proto_tree_add_protocol_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1858 gint start, gint length, const char *format, ...)
1863 header_field_info *hfinfo;
1865 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1867 DISSECTOR_ASSERT(hfinfo->type == FT_PROTOCOL);
1869 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1871 proto_tree_set_protocol_tvb(new_fi, (start == 0 ? tvb : tvb_new_subset(tvb, start, length, length)));
1873 TRY_TO_FAKE_THIS_REPR(tree, pi);
1875 va_start(ap, format);
1876 proto_tree_set_representation(pi, format, ap);
1883 /* Add a FT_BYTES to a proto_tree */
1885 proto_tree_add_bytes(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1886 gint length, const guint8 *start_ptr)
1890 header_field_info *hfinfo;
1892 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1894 DISSECTOR_ASSERT(hfinfo->type == FT_BYTES);
1896 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1897 proto_tree_set_bytes(new_fi, start_ptr, length);
1903 proto_tree_add_bytes_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1904 gint start, gint length,
1905 const guint8 *start_ptr,
1906 const char *format, ...)
1910 header_field_info *hfinfo;
1912 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1915 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length,
1918 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length,
1919 tvb_get_ptr(tvb, start, length));
1921 TRY_TO_FAKE_THIS_REPR(tree, pi);
1923 va_start(ap, format);
1924 proto_tree_set_representation_value(pi, format, ap);
1931 proto_tree_add_bytes_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1932 gint start, gint length, const guint8 *start_ptr,
1933 const char *format, ...)
1937 header_field_info *hfinfo;
1939 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1942 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length,
1945 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length,
1946 tvb_get_ptr(tvb, start, length));
1948 TRY_TO_FAKE_THIS_REPR(tree, pi);
1950 va_start(ap, format);
1951 proto_tree_set_representation(pi, format, ap);
1958 proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length)
1962 bytes = g_byte_array_new();
1964 g_byte_array_append(bytes, start_ptr, length);
1966 fvalue_set(&fi->value, bytes, TRUE);
1971 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length)
1973 proto_tree_set_bytes(fi, tvb_get_ptr(tvb, offset, length), length);
1976 /* Add a FT_*TIME to a proto_tree */
1978 proto_tree_add_time(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1979 gint length, nstime_t *value_ptr)
1983 header_field_info *hfinfo;
1985 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1987 DISSECTOR_ASSERT(hfinfo->type == FT_ABSOLUTE_TIME ||
1988 hfinfo->type == FT_RELATIVE_TIME);
1990 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1991 proto_tree_set_time(new_fi, value_ptr);
1997 proto_tree_add_time_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1998 gint start, gint length, nstime_t *value_ptr,
1999 const char *format, ...)
2003 header_field_info *hfinfo;
2005 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2007 pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
2009 TRY_TO_FAKE_THIS_REPR(tree, pi);
2011 va_start(ap, format);
2012 proto_tree_set_representation_value(pi, format, ap);
2019 proto_tree_add_time_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2020 gint start, gint length, nstime_t *value_ptr,
2021 const char *format, ...)
2025 header_field_info *hfinfo;
2027 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2029 pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
2031 TRY_TO_FAKE_THIS_REPR(tree, pi);
2033 va_start(ap, format);
2034 proto_tree_set_representation(pi, format, ap);
2040 /* Set the FT_*TIME value */
2042 proto_tree_set_time(field_info *fi, nstime_t *value_ptr)
2044 DISSECTOR_ASSERT(value_ptr != NULL);
2046 fvalue_set(&fi->value, value_ptr, FALSE);
2049 /* Add a FT_IPXNET to a proto_tree */
2051 proto_tree_add_ipxnet(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2052 gint length, guint32 value)
2056 header_field_info *hfinfo;
2058 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2060 DISSECTOR_ASSERT(hfinfo->type == FT_IPXNET);
2062 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2063 proto_tree_set_ipxnet(new_fi, value);
2069 proto_tree_add_ipxnet_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2070 gint start, gint length, guint32 value,
2071 const char *format, ...)
2075 header_field_info *hfinfo;
2077 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2079 pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
2081 TRY_TO_FAKE_THIS_REPR(tree, pi);
2083 va_start(ap, format);
2084 proto_tree_set_representation_value(pi, format, ap);
2091 proto_tree_add_ipxnet_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2092 gint start, gint length, guint32 value,
2093 const char *format, ...)
2097 header_field_info *hfinfo;
2099 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2101 pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
2103 TRY_TO_FAKE_THIS_REPR(tree, pi);
2105 va_start(ap, format);
2106 proto_tree_set_representation(pi, format, ap);
2112 /* Set the FT_IPXNET value */
2114 proto_tree_set_ipxnet(field_info *fi, guint32 value)
2116 fvalue_set_uinteger(&fi->value, value);
2119 /* Add a FT_IPv4 to a proto_tree */
2121 proto_tree_add_ipv4(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2122 gint length, guint32 value)
2126 header_field_info *hfinfo;
2128 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2130 DISSECTOR_ASSERT(hfinfo->type == FT_IPv4);
2132 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2133 proto_tree_set_ipv4(new_fi, value);
2139 proto_tree_add_ipv4_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2140 gint start, gint length, guint32 value,
2141 const char *format, ...)
2145 header_field_info *hfinfo;
2147 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2149 pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
2151 TRY_TO_FAKE_THIS_REPR(tree, pi);
2153 va_start(ap, format);
2154 proto_tree_set_representation_value(pi, format, ap);
2161 proto_tree_add_ipv4_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2162 gint start, gint length, guint32 value,
2163 const char *format, ...)
2167 header_field_info *hfinfo;
2169 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2171 pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
2173 TRY_TO_FAKE_THIS_REPR(tree, pi);
2175 va_start(ap, format);
2176 proto_tree_set_representation(pi, format, ap);
2182 /* Set the FT_IPv4 value */
2184 proto_tree_set_ipv4(field_info *fi, guint32 value)
2186 fvalue_set_uinteger(&fi->value, value);
2189 /* Add a FT_IPv6 to a proto_tree */
2191 proto_tree_add_ipv6(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2192 gint length, const guint8* value_ptr)
2196 header_field_info *hfinfo;
2198 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2200 DISSECTOR_ASSERT(hfinfo->type == FT_IPv6);
2202 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2203 proto_tree_set_ipv6(new_fi, value_ptr);
2209 proto_tree_add_ipv6_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2210 gint start, gint length,
2211 const guint8* value_ptr,
2212 const char *format, ...)
2216 header_field_info *hfinfo;
2218 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2220 pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
2222 TRY_TO_FAKE_THIS_REPR(tree, pi);
2224 va_start(ap, format);
2225 proto_tree_set_representation_value(pi, format, ap);
2232 proto_tree_add_ipv6_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2233 gint start, gint length, const guint8* value_ptr,
2234 const char *format, ...)
2238 header_field_info *hfinfo;
2240 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2242 pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
2244 TRY_TO_FAKE_THIS_REPR(tree, pi);
2246 va_start(ap, format);
2247 proto_tree_set_representation(pi, format, ap);
2253 /* Set the FT_IPv6 value */
2255 proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr)
2257 DISSECTOR_ASSERT(value_ptr != NULL);
2258 fvalue_set(&fi->value, (gpointer) value_ptr, FALSE);
2262 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
2264 proto_tree_set_ipv6(fi, tvb_get_ptr(tvb, start, length));
2267 /* Add a FT_GUID to a proto_tree */
2269 proto_tree_add_guid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2270 gint length, const e_guid_t *value_ptr)
2274 header_field_info *hfinfo;
2276 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2278 DISSECTOR_ASSERT(hfinfo->type == FT_GUID);
2280 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2281 proto_tree_set_guid(new_fi, value_ptr);
2287 proto_tree_add_guid_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2288 gint start, gint length,
2289 const e_guid_t *value_ptr,
2290 const char *format, ...)
2294 header_field_info *hfinfo;
2296 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2298 pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
2300 TRY_TO_FAKE_THIS_REPR(tree, pi);
2302 va_start(ap, format);
2303 proto_tree_set_representation_value(pi, format, ap);
2310 proto_tree_add_guid_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2311 gint start, gint length, const e_guid_t *value_ptr,
2312 const char *format, ...)
2316 header_field_info *hfinfo;
2318 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2320 pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
2322 TRY_TO_FAKE_THIS_REPR(tree, pi);
2324 va_start(ap, format);
2325 proto_tree_set_representation(pi, format, ap);
2331 /* Set the FT_GUID value */
2333 proto_tree_set_guid(field_info *fi, const e_guid_t *value_ptr)
2335 DISSECTOR_ASSERT(value_ptr != NULL);
2336 fvalue_set(&fi->value, (gpointer) value_ptr, FALSE);
2340 proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, gint start,
2341 const guint encoding)
2345 tvb_get_guid(tvb, start, &guid, encoding);
2346 proto_tree_set_guid(fi, &guid);
2349 /* Add a FT_OID to a proto_tree */
2351 proto_tree_add_oid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2352 gint length, const guint8* value_ptr)
2356 header_field_info *hfinfo;
2358 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2360 DISSECTOR_ASSERT(hfinfo->type == FT_OID);
2362 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2363 proto_tree_set_oid(new_fi, value_ptr, length);
2369 proto_tree_add_oid_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2370 gint start, gint length,
2371 const guint8* value_ptr,
2372 const char *format, ...)
2376 header_field_info *hfinfo;
2378 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2380 pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
2382 TRY_TO_FAKE_THIS_REPR(tree, pi);
2384 va_start(ap, format);
2385 proto_tree_set_representation_value(pi, format, ap);
2392 proto_tree_add_oid_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2393 gint start, gint length, const guint8* value_ptr,
2394 const char *format, ...)
2398 header_field_info *hfinfo;
2400 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2402 pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
2404 TRY_TO_FAKE_THIS_REPR(tree, pi);
2406 va_start(ap, format);
2407 proto_tree_set_representation(pi, format, ap);
2413 /* Set the FT_OID value */
2415 proto_tree_set_oid(field_info *fi, const guint8* value_ptr, gint length)
2419 DISSECTOR_ASSERT(value_ptr != NULL);
2421 bytes = g_byte_array_new();
2423 g_byte_array_append(bytes, value_ptr, length);
2425 fvalue_set(&fi->value, bytes, TRUE);
2429 proto_tree_set_oid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
2431 proto_tree_set_oid(fi, tvb_get_ptr(tvb, start, length), length);
2435 proto_tree_set_uint64(field_info *fi, guint64 value)
2437 fvalue_set_integer64(&fi->value, value);
2441 * NOTE: to support code written when proto_tree_add_item() took a
2442 * gboolean as its last argument, with FALSE meaning "big-endian"
2443 * and TRUE meaning "little-endian", we treat any non-zero value of
2444 * "encoding" as meaning "little-endian".
2447 proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start,
2448 guint length, const guint encoding)
2451 guint8* b = ep_tvb_memdup(tvb, start, length);
2456 default: DISSECTOR_ASSERT_NOT_REACHED();
2457 case 8: value <<= 8; value += *--b;
2458 case 7: value <<= 8; value += *--b;
2459 case 6: value <<= 8; value += *--b;
2460 case 5: value <<= 8; value += *--b;
2461 case 4: value <<= 8; value += *--b;
2462 case 3: value <<= 8; value += *--b;
2463 case 2: value <<= 8; value += *--b;
2464 case 1: value <<= 8; value += *--b;
2469 default: DISSECTOR_ASSERT_NOT_REACHED();
2470 case 8: value <<= 8; value += *b++;
2471 case 7: value <<= 8; value += *b++;
2472 case 6: value <<= 8; value += *b++;
2473 case 5: value <<= 8; value += *b++;
2474 case 4: value <<= 8; value += *b++;
2475 case 3: value <<= 8; value += *b++;
2476 case 2: value <<= 8; value += *b++;
2477 case 1: value <<= 8; value += *b++;
2482 proto_tree_set_uint64(fi, value);
2485 /* Add a FT_STRING or FT_STRINGZ to a proto_tree. Creates own copy of string,
2486 * and frees it when the proto_tree is destroyed. */
2488 proto_tree_add_string(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2489 gint length, const char* value)
2493 header_field_info *hfinfo;
2495 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2497 DISSECTOR_ASSERT(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ);
2499 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2500 DISSECTOR_ASSERT(length >= 0);
2501 proto_tree_set_string(new_fi, value);
2507 proto_tree_add_unicode_string(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2508 gint length, const char* value)
2510 DISSECTOR_ASSERT(g_utf8_validate(value, -1, NULL));
2511 return proto_tree_add_string_format_value(tree, hfindex, tvb, start, length, value, "%s", value);
2515 proto_tree_add_string_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2516 gint start, gint length, const char* value,
2522 header_field_info *hfinfo;
2524 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2526 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
2528 TRY_TO_FAKE_THIS_REPR(tree, pi);
2530 va_start(ap, format);
2531 proto_tree_set_representation_value(pi, format, ap);
2538 proto_tree_add_string_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2539 gint start, gint length, const char* value,
2540 const char *format, ...)
2544 header_field_info *hfinfo;
2546 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2548 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
2550 TRY_TO_FAKE_THIS_REPR(tree, pi);
2552 va_start(ap, format);
2553 proto_tree_set_representation(pi, format, ap);
2559 /* Appends string data to a FT_STRING or FT_STRINGZ, allowing progressive
2560 * field info update instead of only updating the representation as does
2561 * proto_item_append_text()
2563 /* NOTE: this function will break with the TRY_TO_FAKE_THIS_ITEM()
2564 * speed optimization.
2565 * Currently only WSP use this function so it is not that bad but try to
2566 * avoid using this one if possible.
2567 * IF you must use this function you MUST also disable the
2568 * TRY_TO_FAKE_THIS_ITEM() optimization for your dissector/function
2569 * using proto_item_append_string().
2570 * Do that by faking that the tree is visible by calling
2571 * proto_tree_set_visible(tree, TRUE) (see packet-wsp.c)
2572 * BEFORE you create the item you are later going to use
2573 * proto_item_append_string() on.
2576 proto_item_append_string(proto_item *pi, const char *str)
2579 header_field_info *hfinfo;
2580 gchar *old_str, *new_str;
2587 fi = PITEM_FINFO(pi);
2588 DISSECTOR_ASSERT_HINT(fi, "proto_tree_set_visible(tree, TRUE) should have been called previously");
2590 hfinfo = fi->hfinfo;
2591 if (hfinfo->type == FT_PROTOCOL) {
2592 /* TRY_TO_FAKE_THIS_ITEM() speed optimization: silently skip */
2595 DISSECTOR_ASSERT(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ);
2596 old_str = fvalue_get(&fi->value);
2597 new_str = ep_strdup_printf("%s%s", old_str, str);
2598 fvalue_set(&fi->value, new_str, FALSE);
2601 /* Set the FT_STRING value */
2603 proto_tree_set_string(field_info *fi, const char* value)
2606 fvalue_set(&fi->value, (gpointer) value, FALSE);
2608 fvalue_set(&fi->value, (gpointer) "[ Null ]", FALSE);
2613 proto_tree_set_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length, gint encoding)
2618 length = tvb_ensure_length_remaining(tvb, start);
2621 string = tvb_get_ephemeral_string_enc(tvb, start, length, encoding);
2622 proto_tree_set_string(fi, string);
2626 /* Add a FT_AX25 to a proto_tree */
2628 proto_tree_add_ax25(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2629 const guint8* value)
2633 header_field_info *hfinfo;
2638 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2640 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2641 DISSECTOR_ASSERT(hfinfo->type == FT_AX25);
2643 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2644 proto_tree_set_ax25(new_fi, value);
2649 /* Set the FT_AX25 value */
2651 proto_tree_set_ax25(field_info *fi, const guint8* value)
2653 fvalue_set(&fi->value, (gpointer) value, FALSE);
2657 proto_tree_set_ax25_tvb(field_info *fi, tvbuff_t *tvb, gint start)
2659 proto_tree_set_ax25(fi, tvb_get_ptr(tvb, start, 7));
2663 /* Add a FT_ETHER to a proto_tree */
2665 proto_tree_add_ether(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2666 gint length, const guint8* value)
2670 header_field_info *hfinfo;
2672 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2674 DISSECTOR_ASSERT(hfinfo->type == FT_ETHER);
2676 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2677 proto_tree_set_ether(new_fi, value);
2683 proto_tree_add_ether_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2684 gint start, gint length, const guint8* value,
2685 const char *format, ...)
2689 header_field_info *hfinfo;
2691 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2693 pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
2695 TRY_TO_FAKE_THIS_REPR(tree, pi);
2697 va_start(ap, format);
2698 proto_tree_set_representation_value(pi, format, ap);
2705 proto_tree_add_ether_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2706 gint start, gint length, const guint8* value,
2707 const char *format, ...)
2711 header_field_info *hfinfo;
2713 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2715 pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
2717 TRY_TO_FAKE_THIS_REPR(tree, pi);
2719 va_start(ap, format);
2720 proto_tree_set_representation(pi, format, ap);
2726 /* Set the FT_ETHER value */
2728 proto_tree_set_ether(field_info *fi, const guint8* value)
2730 fvalue_set(&fi->value, (gpointer) value, FALSE);
2734 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start)
2736 proto_tree_set_ether(fi, tvb_get_ptr(tvb, start, FT_ETHER_LEN));
2739 /* Add a FT_BOOLEAN to a proto_tree */
2741 proto_tree_add_boolean(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2742 gint length, guint32 value)
2746 header_field_info *hfinfo;
2748 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2750 DISSECTOR_ASSERT(hfinfo->type == FT_BOOLEAN);
2752 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2753 proto_tree_set_boolean(new_fi, value);
2759 proto_tree_add_boolean_format_value(proto_tree *tree, int hfindex,
2760 tvbuff_t *tvb, gint start, gint length,
2761 guint32 value, const char *format, ...)
2765 header_field_info *hfinfo;
2767 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2769 pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
2771 TRY_TO_FAKE_THIS_REPR(tree, pi);
2773 va_start(ap, format);
2774 proto_tree_set_representation_value(pi, format, ap);
2781 proto_tree_add_boolean_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2782 gint start, gint length, guint32 value,
2783 const char *format, ...)
2787 header_field_info *hfinfo;
2789 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2791 pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
2793 TRY_TO_FAKE_THIS_REPR(tree, pi);
2795 va_start(ap, format);
2796 proto_tree_set_representation(pi, format, ap);
2802 /* Set the FT_BOOLEAN value */
2804 proto_tree_set_boolean(field_info *fi, guint32 value)
2806 proto_tree_set_uint(fi, value);
2809 /* Add a FT_FLOAT to a proto_tree */
2811 proto_tree_add_float(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2812 gint length, float value)
2816 header_field_info *hfinfo;
2818 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2820 DISSECTOR_ASSERT(hfinfo->type == FT_FLOAT);
2822 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2823 proto_tree_set_float(new_fi, value);
2829 proto_tree_add_float_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2830 gint start, gint length, float value,
2831 const char *format, ...)
2835 header_field_info *hfinfo;
2837 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2839 pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
2841 TRY_TO_FAKE_THIS_REPR(tree, pi);
2843 va_start(ap, format);
2844 proto_tree_set_representation_value(pi, format, ap);
2851 proto_tree_add_float_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2852 gint start, gint length, float value,
2853 const char *format, ...)
2857 header_field_info *hfinfo;
2859 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2861 pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
2863 TRY_TO_FAKE_THIS_REPR(tree, pi);
2865 va_start(ap, format);
2866 proto_tree_set_representation(pi, format, ap);
2872 /* Set the FT_FLOAT value */
2874 proto_tree_set_float(field_info *fi, float value)
2876 fvalue_set_floating(&fi->value, value);
2879 /* Add a FT_DOUBLE to a proto_tree */
2881 proto_tree_add_double(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2882 gint length, double value)
2886 header_field_info *hfinfo;
2888 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2890 DISSECTOR_ASSERT(hfinfo->type == FT_DOUBLE);
2892 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2893 proto_tree_set_double(new_fi, value);
2899 proto_tree_add_double_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2900 gint start, gint length, double value,
2901 const char *format, ...)
2905 header_field_info *hfinfo;
2907 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2909 pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
2911 TRY_TO_FAKE_THIS_REPR(tree, pi);
2913 va_start(ap, format);
2914 proto_tree_set_representation_value(pi, format, ap);
2921 proto_tree_add_double_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2922 gint start, gint length, double value,
2923 const char *format, ...)
2927 header_field_info *hfinfo;
2929 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2931 pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
2933 TRY_TO_FAKE_THIS_REPR(tree, pi);
2935 va_start(ap, format);
2936 proto_tree_set_representation(pi, format, ap);
2942 /* Set the FT_DOUBLE value */
2944 proto_tree_set_double(field_info *fi, double value)
2946 fvalue_set_floating(&fi->value, value);
2949 /* Add FT_UINT{8,16,24,32} to a proto_tree */
2951 proto_tree_add_uint(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2952 gint length, guint32 value)
2954 proto_item *pi = NULL;
2956 header_field_info *hfinfo;
2958 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2960 switch (hfinfo->type) {
2966 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length,
2968 proto_tree_set_uint(new_fi, value);
2972 DISSECTOR_ASSERT_NOT_REACHED();
2979 proto_tree_add_uint_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2980 gint start, gint length, guint32 value,
2981 const char *format, ...)
2985 header_field_info *hfinfo;
2987 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2989 pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
2991 TRY_TO_FAKE_THIS_REPR(tree, pi);
2993 va_start(ap, format);
2994 proto_tree_set_representation_value(pi, format, ap);
3001 proto_tree_add_uint_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3002 gint start, gint length, guint32 value,
3003 const char *format, ...)
3007 header_field_info *hfinfo;
3009 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3011 pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
3013 TRY_TO_FAKE_THIS_REPR(tree, pi);
3015 va_start(ap, format);
3016 proto_tree_set_representation(pi, format, ap);
3022 /* Set the FT_UINT{8,16,24,32} value */
3024 proto_tree_set_uint(field_info *fi, guint32 value)
3026 header_field_info *hfinfo;
3029 hfinfo = fi->hfinfo;
3032 if (hfinfo->bitmask) {
3033 /* Mask out irrelevant portions */
3034 integer &= hfinfo->bitmask;
3037 if (hfinfo->bitshift > 0) {
3038 integer >>= hfinfo->bitshift;
3042 fvalue_set_uinteger(&fi->value, integer);
3045 /* Add FT_UINT64 to a proto_tree */
3047 proto_tree_add_uint64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3048 gint length, guint64 value)
3050 proto_item *pi = NULL;
3052 header_field_info *hfinfo;
3054 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3056 DISSECTOR_ASSERT(hfinfo->type == FT_UINT64);
3058 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
3059 proto_tree_set_uint64(new_fi, value);
3065 proto_tree_add_uint64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3066 gint start, gint length, guint64 value,
3067 const char *format, ...)
3071 header_field_info *hfinfo;
3073 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3075 pi = proto_tree_add_uint64(tree, hfindex, tvb, start, length, value);
3077 TRY_TO_FAKE_THIS_REPR(tree, pi);
3079 va_start(ap, format);
3080 proto_tree_set_representation_value(pi, format, ap);
3087 proto_tree_add_uint64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3088 gint start, gint length, guint64 value,
3089 const char *format, ...)
3093 header_field_info *hfinfo;
3095 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3097 pi = proto_tree_add_uint64(tree, hfindex, tvb, start, length, value);
3099 TRY_TO_FAKE_THIS_REPR(tree, pi);
3101 va_start(ap, format);
3102 proto_tree_set_representation(pi, format, ap);
3108 /* Add FT_INT{8,16,24,32} to a proto_tree */
3110 proto_tree_add_int(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3111 gint length, gint32 value)
3113 proto_item *pi = NULL;
3115 header_field_info *hfinfo;
3117 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3119 switch (hfinfo->type) {
3124 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length,
3126 proto_tree_set_int(new_fi, value);
3130 DISSECTOR_ASSERT_NOT_REACHED();
3137 proto_tree_add_int_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3138 gint start, gint length, gint32 value,
3139 const char *format, ...)
3141 proto_item *pi = NULL;
3143 header_field_info *hfinfo;
3145 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3147 pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
3149 TRY_TO_FAKE_THIS_REPR(tree, pi);
3151 va_start(ap, format);
3152 proto_tree_set_representation_value(pi, format, ap);
3159 proto_tree_add_int_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3160 gint start, gint length, gint32 value,
3161 const char *format, ...)
3163 proto_item *pi = NULL;
3165 header_field_info *hfinfo;
3167 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3169 pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
3171 TRY_TO_FAKE_THIS_REPR(tree, pi);
3173 va_start(ap, format);
3174 proto_tree_set_representation(pi, format, ap);
3180 /* Set the FT_INT{8,16,24,32} value */
3182 proto_tree_set_int(field_info *fi, gint32 value)
3184 header_field_info *hfinfo;
3187 hfinfo = fi->hfinfo;
3188 integer = (guint32) value;
3190 if (hfinfo->bitmask) {
3191 /* Mask out irrelevant portions */
3192 integer &= hfinfo->bitmask;
3195 if (hfinfo->bitshift > 0) {
3196 integer >>= hfinfo->bitshift;
3200 fvalue_set_sinteger(&fi->value, integer);
3203 /* Add FT_INT64 to a proto_tree */
3205 proto_tree_add_int64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3206 gint length, gint64 value)
3208 proto_item *pi = NULL;
3210 header_field_info *hfinfo;
3212 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3214 DISSECTOR_ASSERT(hfinfo->type == FT_INT64);
3216 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
3217 proto_tree_set_uint64(new_fi, (guint64)value);
3223 proto_tree_add_int64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3224 gint start, gint length, gint64 value,
3225 const char *format, ...)
3229 header_field_info *hfinfo;
3231 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3233 pi = proto_tree_add_int64(tree, hfindex, tvb, start, length, value);
3235 TRY_TO_FAKE_THIS_REPR(tree, pi);
3237 va_start(ap, format);
3238 proto_tree_set_representation_value(pi, format, ap);
3245 proto_tree_add_int64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3246 gint start, gint length, gint64 value,
3247 const char *format, ...)
3251 header_field_info *hfinfo;
3253 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3255 pi = proto_tree_add_int64(tree, hfindex, tvb, start, length, value);
3257 TRY_TO_FAKE_THIS_REPR(tree, pi);
3259 va_start(ap, format);
3260 proto_tree_set_representation(pi, format, ap);
3265 /* Add a FT_EUI64 to a proto_tree */
3267 proto_tree_add_eui64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3268 gint length, const guint64 value)
3272 header_field_info *hfinfo;
3274 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3276 DISSECTOR_ASSERT(hfinfo->type == FT_EUI64);
3278 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
3279 proto_tree_set_eui64(new_fi, value);
3285 proto_tree_add_eui64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3286 gint start, gint length, const guint64 value,
3287 const char *format, ...)
3291 header_field_info *hfinfo;
3293 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3295 pi = proto_tree_add_eui64(tree, hfindex, tvb, start, length, value);
3297 TRY_TO_FAKE_THIS_REPR(tree, pi);
3299 va_start(ap, format);
3300 proto_tree_set_representation_value(pi, format, ap);
3307 proto_tree_add_eui64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3308 gint start, gint length, const guint64 value,
3309 const char *format, ...)
3313 header_field_info *hfinfo;
3315 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3317 pi = proto_tree_add_eui64(tree, hfindex, tvb, start, length, value);
3319 TRY_TO_FAKE_THIS_REPR(tree, pi);
3321 va_start(ap, format);
3322 proto_tree_set_representation(pi, format, ap);
3328 /* Set the FT_EUI64 value */
3330 proto_tree_set_eui64(field_info *fi, const guint64 value)
3332 fvalue_set_integer64(&fi->value, value);
3335 proto_tree_set_eui64_tvb(field_info *fi, tvbuff_t *tvb, gint start, const guint encoding)
3339 proto_tree_set_eui64(fi, tvb_get_letoh64(tvb, start));
3341 proto_tree_set_eui64(fi, tvb_get_ntoh64(tvb, start));
3345 /* Add a field_info struct to the proto_tree, encapsulating it in a proto_node */
3347 proto_tree_add_node(proto_tree *tree, field_info *fi)
3349 proto_node *pnode, *tnode, *sibling;
3353 * Make sure "tree" is ready to have subtrees under it, by
3354 * checking whether it's been given an ett_ value.
3356 * "PNODE_FINFO(tnode)" may be null; that's the case for the root
3357 * node of the protocol tree. That node is not displayed,
3358 * so it doesn't need an ett_ value to remember whether it
3362 tfi = PNODE_FINFO(tnode);
3363 if (tfi != NULL && (tfi->tree_type < 0 || tfi->tree_type >= num_tree_types)) {
3364 REPORT_DISSECTOR_BUG(ep_strdup_printf("\"%s\" - \"%s\" tfi->tree_type: %u invalid (%s:%u)",
3365 fi->hfinfo->name, fi->hfinfo->abbrev, tfi->tree_type, __FILE__, __LINE__));
3366 /* XXX - is it safe to continue here? */
3369 DISSECTOR_ASSERT(tfi == NULL ||
3370 (tfi->tree_type >= 0 && tfi->tree_type < num_tree_types));
3372 PROTO_NODE_NEW(pnode);
3373 pnode->parent = tnode;
3374 PNODE_FINFO(pnode) = fi;
3375 pnode->tree_data = PTREE_DATA(tree);
3377 if (tnode->last_child != NULL) {
3378 sibling = tnode->last_child;
3379 DISSECTOR_ASSERT(sibling->next == NULL);
3380 sibling->next = pnode;
3382 tnode->first_child = pnode;
3383 tnode->last_child = pnode;
3385 return (proto_item *)pnode;
3389 /* Generic way to allocate field_info and add to proto_tree.
3390 * Sets *pfi to address of newly-allocated field_info struct, if pfi is
3393 proto_tree_add_pi(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3394 gint *length, field_info **pfi)
3403 fi = alloc_field_info(tree, hfindex, tvb, start, length);
3404 pi = proto_tree_add_node(tree, fi);
3406 /* If the proto_tree wants to keep a record of this finfo
3407 * for quick lookup, then record it. */
3408 ptrs = proto_lookup_or_create_interesting_hfids(tree, fi->hfinfo);
3410 g_ptr_array_add(ptrs, fi);
3412 /* Does the caller want to know the fi pointer? */
3421 static header_field_info *
3422 get_hfi_and_length(int hfindex, tvbuff_t *tvb, const gint start, gint *length,
3425 header_field_info *hfinfo;
3426 gint length_remaining;
3429 * We only allow a null tvbuff if the item has a zero length,
3430 * i.e. if there's no data backing it.
3432 DISSECTOR_ASSERT(tvb != NULL || *length == 0);
3434 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
3437 * XXX - in some protocols, there are 32-bit unsigned length
3438 * fields, so lengths in protocol tree and tvbuff routines
3439 * should really be unsigned. We should have, for those
3440 * field types for which "to the end of the tvbuff" makes sense,
3441 * additional routines that take no length argument and
3442 * add fields that run to the end of the tvbuff.
3444 if (*length == -1) {
3446 * For FT_NONE, FT_PROTOCOL, FT_BYTES, and FT_STRING fields,
3447 * a length of -1 means "set the length to what remains in
3450 * The assumption is either that
3452 * 1) the length of the item can only be determined
3453 * by dissection (typically true of items with
3454 * subitems, which are probably FT_NONE or
3459 * 2) if the tvbuff is "short" (either due to a short
3460 * snapshot length or due to lack of reassembly of
3461 * fragments/segments/whatever), we want to display
3462 * what's available in the field (probably FT_BYTES
3463 * or FT_STRING) and then throw an exception later
3467 * 3) the field is defined to be "what's left in the
3470 * so we set the length to what remains in the tvbuff so
3471 * that, if we throw an exception while dissecting, it
3472 * has what is probably the right value.
3474 * For FT_STRINGZ, it means "the string is null-terminated,
3475 * not null-padded; set the length to the actual length
3476 * of the string", and if the tvbuff if short, we just
3477 * throw an exception.
3479 * It's not valid for any other type of field.
3481 switch (hfinfo->type) {
3485 * We allow this to be zero-length - for
3486 * example, an ONC RPC NULL procedure has
3487 * neither arguments nor reply, so the
3488 * payload for that protocol is empty.
3490 * However, if the length is negative, the
3491 * start offset is *past* the byte past the
3492 * end of the tvbuff, so we throw an
3495 *length = tvb_length_remaining(tvb, start);
3498 * Use "tvb_ensure_bytes_exist()"
3499 * to force the appropriate exception
3502 tvb_ensure_bytes_exist(tvb, start, 0);
3504 DISSECTOR_ASSERT(*length >= 0);
3510 *length = tvb_ensure_length_remaining(tvb, start);
3511 DISSECTOR_ASSERT(*length >= 0);
3516 * Leave the length as -1, so our caller knows
3522 DISSECTOR_ASSERT_NOT_REACHED();
3524 *item_length = *length;
3526 *item_length = *length;
3527 if (hfinfo->type == FT_PROTOCOL || hfinfo->type == FT_NONE) {
3529 * These types are for interior nodes of the
3530 * tree, and don't have data associated with
3531 * them; if the length is negative (XXX - see
3532 * above) or goes past the end of the tvbuff,
3533 * cut it short at the end of the tvbuff.
3534 * That way, if this field is selected in
3535 * Wireshark, we don't highlight stuff past
3536 * the end of the data.
3538 /* XXX - what to do, if we don't have a tvb? */
3540 length_remaining = tvb_length_remaining(tvb, start);
3541 if (*item_length < 0 ||
3542 (*item_length > 0 &&
3543 (length_remaining < *item_length)))
3544 *item_length = length_remaining;
3547 if (*item_length < 0) {
3548 THROW(ReportedBoundsError);
3556 new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
3557 const gint start, const gint item_length)
3563 fi->hfinfo = hfinfo;
3565 fi->start += (tvb)?tvb_raw_offset(tvb):0;
3566 fi->length = item_length;
3569 if (!PTREE_DATA(tree)->visible)
3570 FI_SET_FLAG(fi, FI_HIDDEN);
3571 fvalue_init(&fi->value, fi->hfinfo->type);
3574 /* add the data source tvbuff */
3575 fi->ds_tvb = tvb ? tvb_get_ds_tvb(tvb) : NULL;
3577 fi->appendix_start = 0;
3578 fi->appendix_length = 0;
3584 alloc_field_info(proto_tree *tree, int hfindex, tvbuff_t *tvb, const gint start,
3587 header_field_info *hfinfo;
3590 hfinfo = get_hfi_and_length(hfindex, tvb, start, length, &item_length);
3591 return new_field_info(tree, hfinfo, tvb, start, item_length);
3594 /* If the protocol tree is to be visible, set the representation of a
3595 proto_tree entry with the name of the field for the item and with
3596 the value formatted with the supplied printf-style format and
3599 proto_tree_set_representation_value(proto_item *pi, const char *format, va_list ap)
3601 int ret; /*tmp return value */
3602 field_info *fi = PITEM_FINFO(pi);
3603 header_field_info *hf;
3605 DISSECTOR_ASSERT(fi);
3609 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
3610 ITEM_LABEL_NEW(fi->rep);
3611 if (hf->bitmask && (hf->type == FT_BOOLEAN || IS_FT_UINT(hf->type))) {
3615 val = fvalue_get_uinteger(&fi->value);
3616 if (hf->bitshift > 0) {
3617 val <<= hf->bitshift;
3619 decode_bitfield_value(tmpbuf, val, hf->bitmask, hfinfo_bitwidth(hf));
3620 /* put in the hf name */
3621 ret = g_snprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
3622 "%s%s: ", tmpbuf, fi->hfinfo->name);
3624 /* put in the hf name */
3625 ret = g_snprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
3626 "%s: ", fi->hfinfo->name);
3629 /* If possible, Put in the value of the string */
3630 if (ret < ITEM_LABEL_LENGTH) {
3631 ret += g_vsnprintf(fi->rep->representation + ret,
3632 ITEM_LABEL_LENGTH - ret, format, ap);
3634 if (ret >= ITEM_LABEL_LENGTH) {
3635 /* Uh oh, we don't have enough room. Tell the user
3636 * that the field is truncated.
3640 /* Argh, we cannot reuse 'ap' here. So make a copy
3641 * of what we formatted for (re)use below.
3643 oldrep = g_strdup(fi->rep->representation);
3645 g_snprintf(fi->rep->representation,
3654 /* If the protocol tree is to be visible, set the representation of a
3655 proto_tree entry with the representation formatted with the supplied
3656 printf-style format and argument list. */
3658 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap)
3660 int ret; /*tmp return value */
3661 field_info *fi = PITEM_FINFO(pi);
3663 DISSECTOR_ASSERT(fi);
3665 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
3666 ITEM_LABEL_NEW(fi->rep);
3667 ret = g_vsnprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
3669 if (ret >= ITEM_LABEL_LENGTH) {
3670 /* Uh oh, we don't have enough room. Tell the user
3671 * that the field is truncated.
3675 /* Argh, we cannot reuse 'ap' here. So make a copy
3676 * of what we formatted for (re)use below.
3678 oldrep = g_strdup(fi->rep->representation);
3680 g_snprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
3681 "[truncated] %s", oldrep);
3688 protoo_strlcpy(gchar *dest, const gchar *src, gsize dest_size)
3690 gsize res = g_strlcpy(dest, src, dest_size);
3692 if (res > dest_size)
3697 /* -------------------------- */
3699 proto_custom_set(proto_tree* tree, const int field_id, gint occurrence,
3700 gchar *result, gchar *expr, const int size)
3706 struct e_in6_addr *ipv6;
3708 guint32 n_addr; /* network-order IPv4 address */
3710 const true_false_string *tfstring;
3712 int len, prev_len = 0, last, i, offset_r = 0, offset_e = 0;
3714 field_info *finfo = NULL;
3715 header_field_info* hfinfo;
3716 const gchar *abbrev = NULL;
3718 g_assert(field_id >= 0);
3720 hfinfo = proto_registrar_get_nth((guint)field_id);
3722 /* do we need to rewind ? */
3726 if (occurrence < 0) {
3727 /* Search other direction */
3728 while (hfinfo->same_name_prev) {
3729 hfinfo = hfinfo->same_name_prev;
3734 finfos = proto_get_finfo_ptr_array(tree, hfinfo->id);
3736 if (!finfos || !(len = g_ptr_array_len(finfos))) {
3737 if (occurrence < 0) {
3738 hfinfo = hfinfo->same_name_next;
3740 hfinfo = hfinfo->same_name_prev;
3745 /* Are there enough occurrences of the field? */
3746 if (((occurrence - prev_len) > len) || ((occurrence + prev_len) < -len)) {
3747 if (occurrence < 0) {
3748 hfinfo = hfinfo->same_name_next;
3750 hfinfo = hfinfo->same_name_prev;
3756 /* Calculate single index or set outer bounderies */
3757 if (occurrence < 0) {
3758 i = occurrence + len + prev_len;
3760 } else if (occurrence > 0) {
3761 i = occurrence - 1 - prev_len;
3768 prev_len += len; /* Count handled occurrences */
3771 finfo = g_ptr_array_index(finfos, i);
3773 if (offset_r && (offset_r < (size - 2)))
3774 result[offset_r++] = ',';
3776 if (offset_e && (offset_e < (size - 2)))
3777 expr[offset_e++] = ',';
3779 switch (hfinfo->type) {
3781 case FT_NONE: /* Nothing to add */
3782 if (offset_r == 0) {
3784 } else if (result[offset_r-1] == ',') {
3785 result[offset_r-1] = '\0';
3790 /* prevent multiple "yes" entries by setting result directly */
3791 g_strlcpy(result, "Yes", size);
3796 bytes = fvalue_get(&finfo->value);
3797 offset_r += protoo_strlcpy(result+offset_r,
3799 fvalue_length(&finfo->value)),
3803 case FT_ABSOLUTE_TIME:
3804 offset_r += protoo_strlcpy(result+offset_r,
3805 abs_time_to_str(fvalue_get(&finfo->value),
3806 hfinfo->display, TRUE),
3810 case FT_RELATIVE_TIME:
3811 offset_r += protoo_strlcpy(result+offset_r,
3812 rel_time_to_secs_str(fvalue_get(&finfo->value)),
3817 u_integer = fvalue_get_uinteger(&finfo->value);
3818 tfstring = (const true_false_string *)&tfs_true_false;
3819 if (hfinfo->strings) {
3820 tfstring = (const struct true_false_string*) hfinfo->strings;
3822 offset_r += protoo_strlcpy(result+offset_r,
3824 tfstring->true_string :
3825 tfstring->false_string, size-offset_r);
3827 g_snprintf(expr+offset_e, size-offset_e, "%u",
3828 fvalue_get_uinteger(&finfo->value) ? 1 : 0);
3829 offset_e = (int)strlen(expr);
3837 u_integer = fvalue_get_uinteger(&finfo->value);
3838 if ((hfinfo->display & BASE_DISPLAY_E_MASK) == BASE_CUSTOM) {
3839 gchar tmp[ITEM_LABEL_LENGTH];
3840 custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hfinfo->strings;
3842 DISSECTOR_ASSERT(fmtfunc);
3843 fmtfunc(tmp, u_integer);
3844 g_snprintf(result+offset_r, size-offset_r, "%s", tmp);
3845 } else if (hfinfo->strings) {
3846 if (hfinfo->display & BASE_RANGE_STRING) {
3847 g_strlcpy(result+offset_r,
3848 rval_to_str(u_integer, hfinfo->strings, "%u"),
3850 } else if (hfinfo->display & BASE_EXT_STRING) {
3851 g_strlcpy(result+offset_r,
3852 val_to_str_ext(u_integer,
3853 (value_string_ext *)(hfinfo->strings),
3854 "%u"), size-offset_r);
3856 g_strlcpy(result+offset_r,
3857 val_to_str(u_integer, cVALS(hfinfo->strings), "%u"),
3860 } else if (IS_BASE_DUAL(hfinfo->display)) {
3861 g_snprintf(result+offset_r, size-offset_r,
3862 hfinfo_uint_value_format(hfinfo), u_integer, u_integer);
3864 g_snprintf(result+offset_r, size-offset_r,
3865 hfinfo_uint_value_format(hfinfo), u_integer);
3868 if (hfinfo->strings && (hfinfo->display & BASE_DISPLAY_E_MASK) == BASE_NONE) {
3869 g_snprintf(expr+offset_e, size-offset_e,
3870 "\"%s\"", result+offset_r);
3872 g_snprintf(expr+offset_e, size-offset_e,
3873 hfinfo_numeric_value_format(hfinfo),
3874 fvalue_get_uinteger(&finfo->value));
3877 offset_r = (int)strlen(result);
3878 offset_e = (int)strlen(expr);
3882 /* XXX: Should handle BASE_CUSTOM ? */
3883 g_snprintf(result+offset_r, size-offset_r,
3884 "%" G_GINT64_MODIFIER "d",
3885 fvalue_get_integer64(&finfo->value));
3886 offset_r = (int)strlen(result);
3889 g_snprintf(result+offset_r, size-offset_r,
3890 /* XXX: Should handle BASE_CUSTOM ? */
3891 "%" G_GINT64_MODIFIER "u",
3892 fvalue_get_integer64(&finfo->value));
3893 offset_r = (int)strlen(result);
3896 offset_r += protoo_strlcpy(result+offset_r,
3897 eui64_to_str(fvalue_get_integer64(&finfo->value)),
3900 /* XXX - make these just FT_INT? */
3905 integer = fvalue_get_sinteger(&finfo->value);
3906 if ((hfinfo->display & BASE_DISPLAY_E_MASK) == BASE_CUSTOM) {
3907 gchar tmp[ITEM_LABEL_LENGTH];
3908 custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hfinfo->strings;
3910 DISSECTOR_ASSERT(fmtfunc);
3911 fmtfunc(tmp, integer);
3912 g_snprintf(result+offset_r, size-offset_r, "%s", tmp);
3913 } else if (hfinfo->strings) {
3914 if (hfinfo->display & BASE_RANGE_STRING) {
3915 g_strlcpy(result+offset_r,
3916 rval_to_str(integer, hfinfo->strings, "%d"),
3918 } else if (hfinfo->display & BASE_EXT_STRING) {
3919 g_strlcpy(result+offset_r,
3920 val_to_str_ext(integer,
3921 (value_string_ext *)(hfinfo->strings),
3925 g_strlcpy(result+offset_r,
3926 val_to_str(integer, cVALS(hfinfo->strings), "%d"),
3929 } else if (IS_BASE_DUAL(hfinfo->display)) {
3930 g_snprintf(result+offset_r, size-offset_r,
3931 hfinfo_int_value_format(hfinfo), integer, integer);
3933 g_snprintf(result+offset_r, size-offset_r,
3934 hfinfo_int_value_format(hfinfo), integer);
3937 if (hfinfo->strings && (hfinfo->display & BASE_DISPLAY_E_MASK) == BASE_NONE) {
3938 g_snprintf(expr+offset_e, size-offset_e, "\"%s\"", result+offset_r);
3940 g_snprintf(expr+offset_e, size-offset_e,
3941 hfinfo_numeric_value_format(hfinfo),
3942 fvalue_get_sinteger(&finfo->value));
3945 offset_r = (int)strlen(result);
3946 offset_e = (int)strlen(expr);
3950 ipv4 = fvalue_get(&finfo->value);
3951 n_addr = ipv4_get_net_order_addr(ipv4);
3952 offset_r += protoo_strlcpy(result+offset_r,
3953 ip_to_str((guint8 *)&n_addr),
3958 ipv6 = fvalue_get(&finfo->value);
3959 SET_ADDRESS (&addr, AT_IPv6, sizeof(struct e_in6_addr), ipv6);
3960 address_to_str_buf(&addr, result+offset_r, size-offset_r);
3961 offset_r = (int)strlen(result);
3965 offset_r += protoo_strlcpy(result+offset_r,
3966 bytes_to_str_punct(fvalue_get(&finfo->value),
3972 offset_r += protoo_strlcpy(result+offset_r,
3973 guid_to_str((e_guid_t *)fvalue_get(&finfo->value)),
3978 bytes = fvalue_get(&finfo->value);
3979 offset_r += protoo_strlcpy(result+offset_r,
3980 oid_resolved_from_encoded(bytes,
3981 fvalue_length(&finfo->value)),
3983 offset_e += protoo_strlcpy(expr+offset_e,
3984 oid_encoded2string(bytes, fvalue_length(&finfo->value)),
3989 g_snprintf(result+offset_r, size-offset_r,
3990 "%." STRINGIFY(FLT_DIG) "g", fvalue_get_floating(&finfo->value));
3991 offset_r = (int)strlen(result);
3995 g_snprintf(result+offset_r, size-offset_r,
3996 "%." STRINGIFY(DBL_DIG) "g", fvalue_get_floating(&finfo->value));
3997 offset_r = (int)strlen(result);
4002 case FT_UINT_STRING:
4003 bytes = fvalue_get(&finfo->value);
4004 offset_r += protoo_strlcpy(result+offset_r,
4005 format_text(bytes, strlen(bytes)),
4009 case FT_IPXNET: /*XXX really No column custom ?*/
4012 g_error("hfinfo->type %d (%s) not handled\n",
4014 ftype_name(hfinfo->type));
4015 DISSECTOR_ASSERT_NOT_REACHED();
4021 switch (hfinfo->type) {
4034 /* for these types, "expr" is filled in the loop above */
4038 /* for all others, just copy "result" to "expr" */
4039 g_strlcpy(expr, result, size);
4044 /* Store abbrev for return value */
4045 abbrev = hfinfo->abbrev;
4048 if (occurrence == 0) {
4049 /* Fetch next hfinfo with same name (abbrev) */
4050 hfinfo = hfinfo->same_name_prev;
4056 return abbrev ? abbrev : "";
4060 /* Set text of proto_item after having already been created. */
4062 proto_item_set_text(proto_item *pi, const char *format, ...)
4064 field_info *fi = NULL;
4071 fi = PITEM_FINFO(pi);
4076 ITEM_LABEL_FREE(fi->rep);
4079 va_start(ap, format);
4080 proto_tree_set_representation(pi, format, ap);
4084 /* Append to text of proto_item after having already been created. */
4086 proto_item_append_text(proto_item *pi, const char *format, ...)
4088 field_info *fi = NULL;
4096 fi = PITEM_FINFO(pi);
4101 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
4103 * If we don't already have a representation,
4104 * generate the default representation.
4106 if (fi->rep == NULL) {
4107 ITEM_LABEL_NEW(fi->rep);
4108 proto_item_fill_label(fi, fi->rep->representation);
4111 curlen = strlen(fi->rep->representation);
4112 if (ITEM_LABEL_LENGTH > curlen) {
4113 va_start(ap, format);
4114 g_vsnprintf(fi->rep->representation + curlen,
4115 ITEM_LABEL_LENGTH - (gulong) curlen, format, ap);
4121 /* Prepend to text of proto_item after having already been created. */
4123 proto_item_prepend_text(proto_item *pi, const char *format, ...)
4125 field_info *fi = NULL;
4126 char representation[ITEM_LABEL_LENGTH];
4133 fi = PITEM_FINFO(pi);
4138 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
4140 * If we don't already have a representation,
4141 * generate the default representation.
4143 if (fi->rep == NULL) {
4144 ITEM_LABEL_NEW(fi->rep);
4145 proto_item_fill_label(fi, fi->rep->representation);
4148 g_strlcpy(representation, fi->rep->representation, ITEM_LABEL_LENGTH);
4149 va_start(ap, format);
4150 g_vsnprintf(fi->rep->representation,
4151 ITEM_LABEL_LENGTH, format, ap);
4153 g_strlcat(fi->rep->representation, representation, ITEM_LABEL_LENGTH);
4158 proto_item_set_len(proto_item *pi, const gint length)
4165 fi = PITEM_FINFO(pi);
4169 DISSECTOR_ASSERT(length >= 0);
4170 fi->length = length;
4173 * You cannot just make the "len" field of a GByteArray
4174 * larger, if there's no data to back that length;
4175 * you can only make it smaller.
4177 if (fi->value.ftype->ftype == FT_BYTES && length <= (gint)fi->value.value.bytes->len)
4178 fi->value.value.bytes->len = length;
4182 * Sets the length of the item based on its start and on the specified
4183 * offset, which is the offset past the end of the item; as the start
4184 * in the item is relative to the beginning of the data source tvbuff,
4185 * we need to pass in a tvbuff - the end offset is relative to the beginning
4189 proto_item_set_end(proto_item *pi, tvbuff_t *tvb, gint end)
4196 fi = PITEM_FINFO(pi);
4200 end += tvb_raw_offset(tvb);
4201 DISSECTOR_ASSERT(end >= fi->start);
4202 fi->length = end - fi->start;
4206 proto_item_get_len(const proto_item *pi)
4208 field_info *fi = PITEM_FINFO(pi);
4209 return fi ? fi->length : -1;
4213 /** clear flags according to the mask and set new flag values */
4214 #define FI_REPLACE_FLAGS(fi, mask, flags_in) { \
4215 (fi->flags = (fi)->flags & ~(mask)); \
4216 (fi->flags = (fi)->flags | (flags_in)); \
4220 proto_item_set_expert_flags(proto_item *pi, const int group, const guint severity)
4222 if (pi == NULL || PITEM_FINFO(pi) == NULL)
4225 /* only change things if severity is worse or at least equal than before */
4226 if (severity >= FI_GET_FLAG(PITEM_FINFO(pi), PI_SEVERITY_MASK)) {
4227 FI_REPLACE_FLAGS(PITEM_FINFO(pi), PI_GROUP_MASK, group);
4228 FI_REPLACE_FLAGS(PITEM_FINFO(pi), PI_SEVERITY_MASK, severity);
4237 proto_tree_create_root(packet_info *pinfo)
4241 /* Initialize the proto_node */
4242 PROTO_NODE_NEW(pnode);
4243 pnode->parent = NULL;
4244 PNODE_FINFO(pnode) = NULL;
4245 pnode->tree_data = g_new(tree_data_t, 1);
4247 /* Make sure we can access pinfo everywhere */
4248 pnode->tree_data->pinfo = pinfo;
4250 /* Don't initialize the tree_data_t. Wait until we know we need it */
4251 pnode->tree_data->interesting_hfids = NULL;
4253 /* Set the default to FALSE so it's easier to
4254 * find errors; if we expect to see the protocol tree
4255 * but for some reason the default 'visible' is not
4256 * changed, then we'll find out very quickly. */
4257 pnode->tree_data->visible = FALSE;
4259 /* Make sure that we fake protocols (if possible) */
4260 pnode->tree_data->fake_protocols = TRUE;
4262 /* Keep track of the number of children */
4263 pnode->tree_data->count = 0;
4265 pnode->tree_data->fi_tmp = NULL;
4267 return (proto_tree *)pnode;
4271 /* "prime" a proto_tree with a single hfid that a dfilter
4272 * is interested in. */
4274 proto_tree_prime_hfid(proto_tree *tree _U_, const gint hfid)
4276 header_field_info *hfinfo;
4278 PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
4279 /* this field is referenced by a filter so increase the refcount.
4280 also increase the refcount for the parent, i.e the protocol.
4282 hfinfo->ref_type = HF_REF_TYPE_DIRECT;
4283 /* only increase the refcount if there is a parent.
4284 if this is a protocol and not a field then parent will be -1
4285 and there is no parent to add any refcounting for.
4287 if (hfinfo->parent != -1) {
4288 header_field_info *parent_hfinfo;
4289 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
4291 /* Mark parent as indirectly referenced unless it is already directly
4292 * referenced, i.e. the user has specified the parent in a filter.
4294 if (parent_hfinfo->ref_type != HF_REF_TYPE_DIRECT)
4295 parent_hfinfo->ref_type = HF_REF_TYPE_INDIRECT;
4300 proto_item_add_subtree(proto_item *pi, const gint idx) {
4306 DISSECTOR_ASSERT(idx >= 0 && idx < num_tree_types);
4308 fi = PITEM_FINFO(pi);
4310 return (proto_tree *)pi;
4312 fi->tree_type = idx;
4314 return (proto_tree *)pi;
4318 proto_item_get_subtree(const proto_item *pi) {
4323 fi = PITEM_FINFO(pi);
4324 if ( (!fi) || (fi->tree_type == -1) )
4326 return (proto_tree *)pi;
4330 proto_item_get_parent(const proto_item *ti) {
4337 proto_item_get_parent_nth(proto_item *ti, int gen) {
4350 proto_tree_get_parent(const proto_tree *tree) {
4353 return (proto_item *)tree;
4357 proto_tree_get_root(proto_tree *tree) {
4360 while (tree->parent) {
4361 tree = tree->parent;
4367 proto_tree_move_item(proto_tree *tree, proto_item *fixed_item,
4368 proto_item *item_to_move)
4371 /* Revert part of: http://anonsvn.wireshark.org/viewvc?view=rev&revision=32443
4372 * See https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=5500
4374 /* This function doesn't generate any values. It only reorganizes the prococol tree
4375 * so we can bail out immediately if it isn't visible. */
4376 if (!tree || !PTREE_DATA(tree)->visible)
4379 DISSECTOR_ASSERT(item_to_move->parent == tree);
4380 DISSECTOR_ASSERT(fixed_item->parent == tree);
4382 /*** cut item_to_move out ***/
4384 /* is item_to_move the first? */
4385 if (tree->first_child == item_to_move) {
4386 /* simply change first child to next */
4387 tree->first_child = item_to_move->next;
4389 DISSECTOR_ASSERT(tree->last_child != item_to_move);
4391 proto_item *curr_item;
4392 /* find previous and change it's next */
4393 for(curr_item = tree->first_child; curr_item != NULL; curr_item = curr_item->next) {
4394 if (curr_item->next == item_to_move) {
4399 DISSECTOR_ASSERT(curr_item);
4401 curr_item->next = item_to_move->next;
4403 /* fix last_child if required */
4404 if (tree->last_child == item_to_move) {
4405 tree->last_child = curr_item;
4409 /*** insert to_move after fixed ***/
4410 item_to_move->next = fixed_item->next;
4411 fixed_item->next = item_to_move;
4412 if (tree->last_child == fixed_item) {
4413 tree->last_child = item_to_move;
4418 proto_tree_set_appendix(proto_tree *tree, tvbuff_t *tvb, gint start,
4426 fi = PTREE_FINFO(tree);
4430 start += tvb_raw_offset(tvb);
4431 DISSECTOR_ASSERT(start >= 0);
4432 DISSECTOR_ASSERT(length >= 0);
4434 fi->appendix_start = start;
4435 fi->appendix_length = length;
4439 proto_register_protocol(const char *name, const char *short_name,
4440 const char *filter_name)
4442 protocol_t *protocol;
4443 header_field_info *hfinfo;
4445 char *existing_name;
4449 gboolean found_invalid;
4452 * Make sure there's not already a protocol with any of those
4453 * names. Crash if there is, as that's an error in the code
4454 * or an inappropriate plugin.
4455 * This situation has to be fixed to not register more than one
4456 * protocol with the same name.
4458 * This is done by reducing the number of strcmp (and alike) calls
4459 * as much as possible, as this significally slows down startup time.
4461 * Drawback: As a hash value is used to reduce insert time,
4462 * this might lead to a hash collision.
4463 * However, although we have somewhat over 1000 protocols, we're using
4464 * a 32 bit int so this is very, very unlikely.
4467 key = g_malloc (sizeof(gint));
4468 *key = wrs_str_hash(name);
4470 existing_name = g_hash_table_lookup(proto_names, key);
4471 if (existing_name != NULL) {
4472 /* g_error will terminate the program */
4473 g_error("Duplicate protocol name \"%s\"!"
4474 " This might be caused by an inappropriate plugin or a development error.", name);
4476 g_hash_table_insert(proto_names, key, (gpointer)name);
4478 existing_name = g_hash_table_lookup(proto_short_names, (gpointer)short_name);
4479 if (existing_name != NULL) {
4480 g_error("Duplicate protocol short_name \"%s\"!"
4481 " This might be caused by an inappropriate plugin or a development error.", short_name);
4483 g_hash_table_insert(proto_short_names, (gpointer)short_name, (gpointer)short_name);
4485 found_invalid = FALSE;
4486 for (i = 0; filter_name[i]; i++) {
4488 if (!(islower(c) || isdigit(c) || c == '-' || c == '_' || c == '.')) {
4489 found_invalid = TRUE;
4492 if (found_invalid) {
4493 g_error("Protocol filter name \"%s\" has one or more invalid characters."
4494 " Allowed are lower characters, digits, '-', '_' and '.'."
4495 " This might be caused by an inappropriate plugin or a development error.", filter_name);
4497 existing_name = g_hash_table_lookup(proto_filter_names, (gpointer)filter_name);
4498 if (existing_name != NULL) {
4499 g_error("Duplicate protocol filter_name \"%s\"!"
4500 " This might be caused by an inappropriate plugin or a development error.", filter_name);
4502 g_hash_table_insert(proto_filter_names, (gpointer)filter_name, (gpointer)filter_name);
4504 /* Add this protocol to the list of known protocols; the list
4505 is sorted by protocol short name. */
4506 protocol = g_new(protocol_t, 1);
4507 protocol->name = name;
4508 protocol->short_name = short_name;
4509 protocol->filter_name = filter_name;
4510 protocol->fields = NULL;
4511 protocol->is_enabled = TRUE; /* protocol is enabled by default */
4512 protocol->can_toggle = TRUE;
4513 protocol->is_private = FALSE;
4514 /* list will be sorted later by name, when all protocols completed registering */
4515 protocols = g_list_prepend(protocols, protocol);
4517 /* Here we allocate a new header_field_info struct */
4518 hfinfo = g_slice_new(header_field_info);
4519 hfinfo->name = name;
4520 hfinfo->abbrev = filter_name;
4521 hfinfo->type = FT_PROTOCOL;
4522 hfinfo->display = BASE_NONE;
4523 hfinfo->strings = protocol;
4524 hfinfo->bitmask = 0;
4525 hfinfo->bitshift = 0;
4526 hfinfo->ref_type = HF_REF_TYPE_NONE;
4527 hfinfo->blurb = NULL;
4528 hfinfo->parent = -1; /* this field differentiates protos and fields */
4530 proto_id = proto_register_field_init(hfinfo, hfinfo->parent);
4531 protocol->proto_id = proto_id;
4536 proto_mark_private(const int proto_id)
4538 protocol_t *protocol = find_protocol_by_id(proto_id);
4540 protocol->is_private = TRUE;
4544 proto_is_private(const int proto_id)
4546 protocol_t *protocol = find_protocol_by_id(proto_id);
4548 return protocol->is_private;
4554 * Routines to use to iterate over the protocols.
4555 * The argument passed to the iterator routines is an opaque cookie to
4556 * their callers; it's the GList pointer for the current element in
4558 * The ID of the protocol is returned, or -1 if there is no protocol.
4561 proto_get_first_protocol(void **cookie)
4563 protocol_t *protocol;
4565 if (protocols == NULL)
4567 *cookie = protocols;
4568 protocol = protocols->data;
4569 return protocol->proto_id;
4573 proto_get_data_protocol(void *cookie)
4575 GList *list_item = cookie;
4577 protocol_t *protocol = list_item->data;
4578 return protocol->proto_id;
4582 proto_get_next_protocol(void **cookie)
4584 GList *list_item = *cookie;
4585 protocol_t *protocol;
4587 list_item = g_list_next(list_item);
4588 if (list_item == NULL)
4590 *cookie = list_item;
4591 protocol = list_item->data;
4592 return protocol->proto_id;
4596 proto_get_first_protocol_field(const int proto_id, void **cookie)
4598 protocol_t *protocol = find_protocol_by_id(proto_id);
4599 hf_register_info *ptr;
4601 if ((protocol == NULL) || (protocol->fields == NULL))
4604 *cookie = protocol->fields;
4605 ptr = protocol->fields->data;
4606 return &ptr->hfinfo;
4610 proto_get_next_protocol_field(void **cookie)
4612 GList *list_item = *cookie;
4613 hf_register_info *ptr;
4615 list_item = g_list_next(list_item);
4616 if (list_item == NULL)
4619 *cookie = list_item;
4620 ptr = list_item->data;
4621 return &ptr->hfinfo;
4625 find_protocol_by_id(const int proto_id)
4627 header_field_info *hfinfo;
4632 PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
4633 DISSECTOR_ASSERT(hfinfo->type == FT_PROTOCOL);
4634 return (protocol_t *)hfinfo->strings;
4637 static gint compare_filter_name(gconstpointer proto_arg,
4638 gconstpointer filter_name)
4640 const protocol_t *protocol = proto_arg;
4641 const gchar *f_name = filter_name;
4643 return (strcmp(protocol->filter_name, f_name));
4647 proto_get_id(const protocol_t *protocol)
4649 return protocol->proto_id;
4652 int proto_get_id_by_filter_name(const gchar* filter_name)
4655 protocol_t *protocol;
4658 fprintf(stderr, "No filter name present");
4659 DISSECTOR_ASSERT(filter_name);
4662 list_entry = g_list_find_custom(protocols, filter_name,
4663 compare_filter_name);
4665 if (list_entry == NULL)
4667 protocol = list_entry->data;
4668 return protocol->proto_id;
4672 proto_get_protocol_name(const int proto_id)
4674 protocol_t *protocol;
4676 protocol = find_protocol_by_id(proto_id);
4678 if (protocol == NULL)
4680 return protocol->name;
4684 proto_get_protocol_short_name(const protocol_t *protocol)
4686 if (protocol == NULL)
4688 return protocol->short_name;
4692 proto_get_protocol_long_name(const protocol_t *protocol)
4694 if (protocol == NULL)
4696 return protocol->name;
4700 proto_get_protocol_filter_name(const int proto_id)
4702 protocol_t *protocol;
4704 protocol = find_protocol_by_id(proto_id);
4705 if (protocol == NULL)
4707 return protocol->filter_name;
4711 proto_is_protocol_enabled(const protocol_t *protocol)
4713 return protocol->is_enabled;
4717 proto_can_toggle_protocol(const int proto_id)
4719 protocol_t *protocol;
4721 protocol = find_protocol_by_id(proto_id);
4722 return protocol->can_toggle;
4726 proto_set_decoding(const int proto_id, const gboolean enabled)
4728 protocol_t *protocol;
4730 protocol = find_protocol_by_id(proto_id);
4731 DISSECTOR_ASSERT(protocol->can_toggle);
4732 protocol->is_enabled = enabled;
4736 proto_enable_all(void)
4738 protocol_t *protocol;
4739 GList *list_item = protocols;
4741 if (protocols == NULL)
4745 protocol = list_item->data;
4746 if (protocol->can_toggle)
4747 protocol->is_enabled = TRUE;
4748 list_item = g_list_next(list_item);
4753 proto_set_cant_toggle(const int proto_id)
4755 protocol_t *protocol;
4757 protocol = find_protocol_by_id(proto_id);
4758 protocol->can_toggle = FALSE;
4761 /* for use with static arrays only, since we don't allocate our own copies
4762 of the header_field_info struct contained within the hf_register_info struct */
4764 proto_register_field_array(const int parent, hf_register_info *hf, const int num_records)
4767 hf_register_info *ptr = hf;
4770 proto = find_protocol_by_id(parent);
4771 for (i = 0; i < num_records; i++, ptr++) {
4773 * Make sure we haven't registered this yet.
4774 * Most fields have variables associated with them
4775 * that are initialized to -1; some have array elements,
4776 * or possibly uninitialized variables, so we also allow
4777 * 0 (which is unlikely to be the field ID we get back
4778 * from "proto_register_field_init()").
4780 if (*ptr->p_id != -1 && *ptr->p_id != 0) {
4782 "Duplicate field detected in call to proto_register_field_array: %s is already registered\n",
4783 ptr->hfinfo.abbrev);
4787 if (proto != NULL) {
4788 if (proto->fields == NULL) {
4789 proto->fields = g_list_append(NULL, ptr);
4790 proto->last_field = proto->fields;
4793 g_list_append(proto->last_field, ptr)->next;
4796 field_id = proto_register_field_init(&ptr->hfinfo, parent);
4797 *ptr->p_id = field_id;
4801 /* unregister already registered fields */
4803 proto_unregister_field (const int parent, gint hf_id)
4805 hf_register_info *hf;
4809 if (hf_id == -1 || hf_id == 0)
4812 proto = find_protocol_by_id (parent);
4813 if (!proto || !proto->fields) {
4817 for (field = g_list_first (proto->fields); field; field = g_list_next (field)) {
4819 if (*hf->p_id == hf_id) {
4820 /* Found the hf_id in this protocol */
4821 g_tree_steal (gpa_name_tree, hf->hfinfo.abbrev);
4822 proto->fields = g_list_remove_link (proto->fields, field);
4823 proto->last_field = g_list_last (proto->fields);
4829 /* chars allowed in field abbrev */
4831 const guchar fld_abbrev_chars[256] = {
4832 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00-0x0F */
4833 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10-0x1F */
4834 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, /* 0x20-0x2F '-', '.' */
4835 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 0x30-0x3F '0'-'9' */
4836 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x40-0x4F 'A'-'O' */
4837 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 0x50-0x5F 'P'-'Z', '_' */
4838 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x60-0x6F 'a'-'o' */
4839 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 0x70-0x7F 'p'-'z' */
4840 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80-0x8F */
4841 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90-0x9F */
4842 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xA0-0xAF */
4843 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xB0-0xBF */
4844 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xC0-0xCF */
4845 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xD0-0xDF */
4846 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xE0-0xEF */
4847 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xF0-0xFF */
4850 static const value_string hf_types[] = {
4851 { FT_NONE, "FT_NONE" },
4852 { FT_PROTOCOL, "FT_PROTOCOL" },
4853 { FT_BOOLEAN, "FT_BOOLEAN" },
4854 { FT_UINT8, "FT_UINT8" },
4855 { FT_UINT16, "FT_UINT16" },
4856 { FT_UINT24, "FT_UINT24" },
4857 { FT_UINT32, "FT_UINT32" },
4858 { FT_UINT64, "FT_UINT64" },
4859 { FT_INT8, "FT_INT8" },
4860 { FT_INT16, "FT_INT16" },
4861 { FT_INT24, "FT_INT24" },
4862 { FT_INT32, "FT_INT32" },
4863 { FT_INT64, "FT_INT64" },
4864 { FT_EUI64, "FT_EUI64" },
4865 { FT_FLOAT, "FT_FLOAT" },
4866 { FT_DOUBLE, "FT_DOUBLE" },
4867 { FT_ABSOLUTE_TIME, "FT_ABSOLUTE_TIME" },
4868 { FT_RELATIVE_TIME, "FT_RELATIVE_TIME" },
4869 { FT_STRING, "FT_STRING" },
4870 { FT_STRINGZ, "FT_STRINGZ" },
4871 { FT_UINT_STRING, "FT_UINT_STRING" },
4872 { FT_ETHER, "FT_ETHER" },
4873 { FT_BYTES, "FT_BYTES" },
4874 { FT_UINT_BYTES, "FT_UINT_BYTES" },
4875 { FT_IPv4, "FT_IPv4" },
4876 { FT_IPv6, "FT_IPv6" },
4877 { FT_IPXNET, "FT_IPXNET" },
4878 { FT_FRAMENUM, "FT_FRAMENUM" },
4879 { FT_PCRE, "FT_PCR" },
4880 { FT_GUID, "FT_GUID" },
4881 { FT_OID, "FT_OID" },
4884 static const value_string hf_display[] = {
4885 { BASE_NONE, "BASE_NONE" },
4886 { BASE_DEC, "BASE_DEC" },
4887 { BASE_HEX, "BASE_HEX" },
4888 { BASE_OCT, "BASE_OCT" },
4889 { BASE_DEC_HEX, "BASE_DEC_HEX" },
4890 { BASE_HEX_DEC, "BASE_HEX_DEC" },
4891 { BASE_CUSTOM, "BASE_CUSTOM" },
4892 { BASE_NONE|BASE_RANGE_STRING, "BASE_NONE|BASE_RANGE_STRING" },
4893 { BASE_DEC|BASE_RANGE_STRING, "BASE_DEC|BASE_RANGE_STRING" },
4894 { BASE_HEX|BASE_RANGE_STRING, "BASE_HEX|BASE_RANGE_STRING" },
4895 { BASE_OCT|BASE_RANGE_STRING, "BASE_OCT|BASE_RANGE_STRING" },
4896 { BASE_DEC_HEX|BASE_RANGE_STRING, "BASE_DEC_HEX|BASE_RANGE_STRING" },
4897 { BASE_HEX_DEC|BASE_RANGE_STRING, "BASE_HEX_DEC|BASE_RANGE_STRING" },
4898 { BASE_CUSTOM|BASE_RANGE_STRING, "BASE_CUSTOM|BASE_RANGE_STRING" },
4899 { ABSOLUTE_TIME_LOCAL, "ABSOLUTE_TIME_LOCAL" },
4900 { ABSOLUTE_TIME_UTC, "ABSOLUTE_TIME_UTC" },
4901 { ABSOLUTE_TIME_DOY_UTC, "ABSOLUTE_TIME_DOY_UTC" },
4904 /* temporary function containing assert part for easier profiling */
4906 tmp_fld_check_assert(header_field_info *hfinfo)
4909 /* The field must have a name (with length > 0) */
4910 if (!hfinfo->name || !hfinfo->name[0]) {
4912 /* Try to identify the field */
4913 g_error("Field (abbrev='%s') does not have a name\n",
4917 g_error("Field does not have a name (nor an abbreviation)\n");
4920 /* fields with an empty string for an abbreviation aren't filterable */
4921 if (!hfinfo->abbrev || !hfinfo->abbrev[0])
4922 g_error("Field '%s' does not have an abbreviation\n", hfinfo->name);
4924 /* These types of fields are allowed to have value_strings,
4925 * true_false_strings or a protocol_t struct
4927 if (hfinfo->strings != NULL && !(
4928 (hfinfo->type == FT_UINT8) ||
4929 (hfinfo->type == FT_UINT16) ||
4930 (hfinfo->type == FT_UINT24) ||
4931 (hfinfo->type == FT_UINT32) ||
4932 (hfinfo->type == FT_INT8) ||
4933 (hfinfo->type == FT_INT16) ||
4934 (hfinfo->type == FT_INT24) ||
4935 (hfinfo->type == FT_INT32) ||
4936 (hfinfo->type == FT_BOOLEAN) ||
4937 (hfinfo->type == FT_PROTOCOL) ||
4938 (hfinfo->type == FT_FRAMENUM) ))
4939 g_error("Field '%s' (%s) has a 'strings' value but is of type %s"
4940 " (which is not allowed to have strings)\n",
4941 hfinfo->name, hfinfo->abbrev,
4942 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"));
4944 /* TODO: This check may slow down startup, and output quite a few warnings.
4945 It would be good to be able to enable this (and possibly other checks?)
4946 in non-release builds. */
4948 /* Check for duplicate value_string values.
4949 There are lots that have the same value *and* string, so for now only
4950 report those that have same value but different string. */
4951 if ((hfinfo->strings != NULL) &&
4952 !(hfinfo->display & BASE_RANGE_STRING) &&
4953 !((hfinfo->display & BASE_DISPLAY_E_MASK) == BASE_CUSTOM) &&
4955 (hfinfo->type == FT_UINT8) ||
4956 (hfinfo->type == FT_UINT16) ||
4957 (hfinfo->type == FT_UINT24) ||
4958 (hfinfo->type == FT_UINT32) ||
4959 (hfinfo->type == FT_INT8) ||
4960 (hfinfo->type == FT_INT16) ||
4961 (hfinfo->type == FT_INT24) ||
4962 (hfinfo->type == FT_INT32) ||
4963 (hfinfo->type == FT_FRAMENUM) )) {
4966 const value_string *start_values;
4967 const value_string *current;
4969 if (hfinfo->display & BASE_EXT_STRING)
4970 start_values = VALUE_STRING_EXT_VS_P(((const value_string_ext*)hfinfo->strings));
4972 start_values = (const value_string*)hfinfo->strings;
4973 current = start_values;
4975 for (n=0; current; n++, current++) {
4976 /* Drop out if we reached the end. */
4977 if ((current->value == 0) && (current->strptr == NULL)) {
4981 /* Check value against all previous */
4982 for (m=0; m < n; m++) {
4983 /* There are lots of duplicates with the same string,
4984 so only report if different... */
4985 if ((start_values[m].value == current->value) &&
4986 (strcmp(start_values[m].strptr, current->strptr) != 0)) {
4987 g_warning("Field '%s' (%s) has a conflicting entry in its"
4988 " value_string: %u is at indices %u (%s) and %u (%s))\n",
4989 hfinfo->name, hfinfo->abbrev,
4990 current->value, m, start_values[m].strptr, n, current->strptr);
4998 switch (hfinfo->type) {
5005 /* Hexadecimal and octal are, in printf() and everywhere
5006 * else, unsigned so don't allow dissectors to register a
5007 * signed field to be displayed unsigned. (Else how would
5008 * we display negative values?)
5010 * If you want to take out this check, be sure to fix
5011 * hfinfo_numeric_format() so that it does not assert out
5012 * when trying to construct a hexadecimal representation of
5015 if (hfinfo->display == BASE_HEX ||
5016 hfinfo->display == BASE_OCT)
5017 g_error("Field '%s' (%s) is signed (%s) but is being displayed unsigned (%s)\n",
5018 hfinfo->name, hfinfo->abbrev,
5019 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"),
5020 val_to_str(hfinfo->display, hf_display, "(Bit count: %d)"));
5027 /* Require integral types (other than frame number,
5028 * which is always displayed in decimal) to have a
5030 * If there is a strings value then this base is not
5031 * normally used except when constructing a display
5032 * filter for a value not found in the strings lookup.
5034 switch (hfinfo->display & BASE_DISPLAY_E_MASK) {
5040 case BASE_CUSTOM: /* hfinfo_numeric_value_format() treats this as decimal */
5043 g_error("Field '%s' (%s) is an integral value (%s)"
5044 " but is being displayed as %s\n",
5045 hfinfo->name, hfinfo->abbrev,
5046 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"),
5047 val_to_str(hfinfo->display, hf_display, "(Unknown: 0x%x)"));
5053 if (hfinfo->display != BASE_NONE)
5054 g_error("Field '%s' (%s) is an %s but is being displayed as %s instead of BASE_NONE\n",
5055 hfinfo->name, hfinfo->abbrev,
5056 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"),
5057 val_to_str(hfinfo->display, hf_display, "(Bit count: %d)"));
5058 if (hfinfo->bitmask != 0)
5059 g_error("Field '%s' (%s) is an %s but has a bitmask\n",
5060 hfinfo->name, hfinfo->abbrev,
5061 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"));
5067 case FT_ABSOLUTE_TIME:
5068 if (!(hfinfo->display == ABSOLUTE_TIME_LOCAL ||
5069 hfinfo->display == ABSOLUTE_TIME_UTC ||
5070 hfinfo->display == ABSOLUTE_TIME_DOY_UTC))
5071 g_error("Field '%s' (%s) is a %s but is being displayed as %s instead of as a time\n",
5072 hfinfo->name, hfinfo->abbrev,
5073 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"),
5074 val_to_str(hfinfo->display, hf_display, "(Bit count: %d)"));
5075 if (hfinfo->bitmask != 0)
5076 g_error("Field '%s' (%s) is an %s but has a bitmask\n",
5077 hfinfo->name, hfinfo->abbrev,
5078 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"));
5082 if (hfinfo->display != BASE_NONE)
5083 g_error("Field '%s' (%s) is an %s but is being displayed as %s instead of BASE_NONE\n",
5084 hfinfo->name, hfinfo->abbrev,
5085 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"),
5086 val_to_str(hfinfo->display, hf_display, "(Bit count: %d)"));
5087 if (hfinfo->bitmask != 0)
5088 g_error("Field '%s' (%s) is an %s but has a bitmask\n",
5089 hfinfo->name, hfinfo->abbrev,
5090 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"));
5091 if (hfinfo->strings != NULL)
5092 g_error("Field '%s' (%s) is an %s but has a strings value\n",
5093 hfinfo->name, hfinfo->abbrev,
5094 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"));
5099 #define PROTO_PRE_ALLOC_HF_FIELDS_MEM 120000
5101 proto_register_field_init(header_field_info *hfinfo, const int parent)
5104 tmp_fld_check_assert(hfinfo);
5106 /* if this is a bitfield, compute bitshift */
5107 if (hfinfo->bitmask) {
5108 hfinfo->bitshift = wrs_count_bitshift(hfinfo->bitmask);
5111 hfinfo->parent = parent;
5112 hfinfo->same_name_next = NULL;
5113 hfinfo->same_name_prev = NULL;
5115 /* if we always add and never delete, then id == len - 1 is correct */
5116 if (gpa_hfinfo.len >= gpa_hfinfo.allocated_len) {
5117 if (!gpa_hfinfo.hfi) {
5118 gpa_hfinfo.allocated_len = PROTO_PRE_ALLOC_HF_FIELDS_MEM;
5119 gpa_hfinfo.hfi = g_malloc(sizeof(header_field_info *)*PROTO_PRE_ALLOC_HF_FIELDS_MEM);
5121 gpa_hfinfo.allocated_len += 1000;
5122 gpa_hfinfo.hfi = g_realloc(gpa_hfinfo.hfi,
5123 sizeof(header_field_info *)*gpa_hfinfo.allocated_len);
5124 /*g_warning("gpa_hfinfo.allocated_len %u", gpa_hfinfo.allocated_len);*/
5127 gpa_hfinfo.hfi[gpa_hfinfo.len] = hfinfo;
5129 hfinfo->id = gpa_hfinfo.len - 1;
5131 /* if we have real names, enter this field in the name tree */
5132 if ((hfinfo->name[0] != 0) && (hfinfo->abbrev[0] != 0 )) {
5134 header_field_info *same_name_next_hfinfo;
5137 /* Check that the filter name (abbreviation) is legal;
5138 * it must contain only alphanumerics, '-', "_", and ".". */
5139 c = wrs_check_charset(fld_abbrev_chars, hfinfo->abbrev);
5141 fprintf(stderr, "Invalid character '%c' in filter name '%s'\n", c, hfinfo->abbrev);
5142 DISSECTOR_ASSERT(!c);
5145 /* We allow multiple hfinfo's to be registered under the same
5146 * abbreviation. This was done for X.25, as, depending
5147 * on whether it's modulo-8 or modulo-128 operation,
5148 * some bitfield fields may be in different bits of
5149 * a byte, and we want to be able to refer to that field
5150 * with one name regardless of whether the packets
5151 * are modulo-8 or modulo-128 packets. */
5153 same_name_hfinfo = NULL;
5155 g_tree_insert(gpa_name_tree, (gpointer) (hfinfo->abbrev), hfinfo);
5156 /* GLIB 2.x - if it is already present
5157 * the previous hfinfo with the same name is saved
5158 * to same_name_hfinfo by value destroy callback */
5159 if (same_name_hfinfo) {
5160 /* There's already a field with this name.
5161 * Put it after that field in the list of
5162 * fields with this name, then allow the code
5163 * after this if{} block to replace the old
5164 * hfinfo with the new hfinfo in the GTree. Thus,
5165 * we end up with a linked-list of same-named hfinfo's,
5166 * with the root of the list being the hfinfo in the GTree */
5167 same_name_next_hfinfo =
5168 same_name_hfinfo->same_name_next;
5170 hfinfo->same_name_next = same_name_next_hfinfo;
5171 if (same_name_next_hfinfo)
5172 same_name_next_hfinfo->same_name_prev = hfinfo;
5174 same_name_hfinfo->same_name_next = hfinfo;
5175 hfinfo->same_name_prev = same_name_hfinfo;
5183 proto_register_subtree_array(gint *const *indices, const int num_indices)
5186 gint *const *ptr = indices;
5189 * If we've already allocated the array of tree types, expand
5190 * it; this lets plugins such as mate add tree types after
5191 * the initial startup. (If we haven't already allocated it,
5192 * we don't allocate it; on the first pass, we just assign
5193 * ett values and keep track of how many we've assigned, and
5194 * when we're finished registering all dissectors we allocate
5195 * the array, so that we do only one allocation rather than
5196 * wasting CPU time and memory by growing the array for each
5197 * dissector that registers ett values.)
5199 if (tree_is_expanded != NULL) {
5201 g_realloc(tree_is_expanded,
5202 (num_tree_types + num_indices)*sizeof (gboolean));
5203 memset(tree_is_expanded + num_tree_types, 0,
5204 num_indices*sizeof (gboolean));
5208 * Assign "num_indices" subtree numbers starting at "num_tree_types",
5209 * returning the indices through the pointers in the array whose
5210 * first element is pointed to by "indices", and update
5211 * "num_tree_types" appropriately.
5213 for (i = 0; i < num_indices; i++, ptr++, num_tree_types++) {
5215 /* g_error will terminate the program */
5216 g_error("register_subtree_array: subtree item type (ett_...) not -1 !"
5217 " This is a development error:"
5218 " Either the subtree item type has already been assigned or"
5219 " was not initialized to -1.");
5221 **ptr = num_tree_types;
5226 label_fill_descr(char *label_str, const header_field_info *hfinfo, const char *text, const char *descr)
5230 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH, "%s: %s (%s)", hfinfo->name, text, descr);
5231 if (ret >= ITEM_LABEL_LENGTH) {
5232 /* Uh oh, we don't have enough room. Tell the user that the field is truncated. */
5233 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH, "%s [truncated]: %s (%s)", hfinfo->name, text, descr);
5240 label_fill(char *label_str, const header_field_info *hfinfo, const char *text)
5244 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH, "%s: %s", hfinfo->name, text);
5245 if (ret >= ITEM_LABEL_LENGTH) {
5246 /* Uh oh, we don't have enough room. Tell the user that the field is truncated. */
5247 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH, "%s [truncated]: %s", hfinfo->name, text);
5254 proto_item_fill_label(field_info *fi, gchar *label_str)
5256 header_field_info *hfinfo;
5262 guint32 n_addr; /* network-order IPv4 address */
5268 /* XXX: Check validity of hfinfo->type */
5272 hfinfo = fi->hfinfo;
5274 switch (hfinfo->type) {
5277 g_strlcpy(label_str, hfinfo->name, ITEM_LABEL_LENGTH);
5281 fill_label_boolean(fi, label_str);
5286 bytes = fvalue_get(&fi->value);
5287 label_fill(label_str, hfinfo,
5288 (bytes) ? bytes_to_str(bytes, fvalue_length(&fi->value)) : "<MISSING>");
5291 /* Four types of integers to take care of:
5292 * Bitfield, with val_string
5293 * Bitfield, w/o val_string
5294 * Non-bitfield, with val_string
5295 * Non-bitfield, w/o val_string
5301 if (hfinfo->bitmask) {
5302 fill_label_bitfield(fi, label_str);
5304 fill_label_uint(fi, label_str);
5309 fill_label_uint(fi, label_str);
5313 fill_label_uint64(fi, label_str);
5320 DISSECTOR_ASSERT(!hfinfo->bitmask);
5321 fill_label_int(fi, label_str);
5325 fill_label_int64(fi, label_str);
5329 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5330 "%s: %." STRINGIFY(FLT_DIG) "g",
5331 hfinfo->name, fvalue_get_floating(&fi->value));
5335 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5336 "%s: %." STRINGIFY(DBL_DIG) "g",
5337 hfinfo->name, fvalue_get_floating(&fi->value));
5340 case FT_ABSOLUTE_TIME:
5341 label_fill(label_str, hfinfo,
5342 abs_time_to_str(fvalue_get(&fi->value), hfinfo->display, TRUE));
5345 case FT_RELATIVE_TIME:
5346 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5347 "%s: %s seconds", hfinfo->name,
5348 rel_time_to_secs_str(fvalue_get(&fi->value)));
5352 integer = fvalue_get_uinteger(&fi->value);
5353 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5354 "%s: %s (0x%08X)", hfinfo->name,
5355 get_ipxnet_name(integer), integer);
5359 bytes = fvalue_get(&fi->value);
5360 label_fill_descr(label_str, hfinfo,
5361 get_ax25_name(bytes),
5362 ax25_to_str(bytes));
5366 bytes = fvalue_get(&fi->value);
5367 label_fill_descr(label_str, hfinfo,
5368 get_ether_name(bytes),
5369 ether_to_str(bytes));
5373 ipv4 = fvalue_get(&fi->value);
5374 n_addr = ipv4_get_net_order_addr(ipv4);
5375 label_fill_descr(label_str, hfinfo,
5376 get_hostname(n_addr),
5377 ip_to_str((guint8*)&n_addr));
5381 bytes = fvalue_get(&fi->value);
5382 label_fill_descr(label_str, hfinfo,
5383 get_hostname6((struct e_in6_addr *)bytes),
5384 ip6_to_str((struct e_in6_addr*)bytes));
5388 guid = fvalue_get(&fi->value);
5389 label_fill(label_str, hfinfo, guid_to_str(guid));
5393 bytes = fvalue_get(&fi->value);
5394 name = oid_resolved_from_encoded(bytes, fvalue_length(&fi->value));
5396 label_fill_descr(label_str, hfinfo,
5397 oid_encoded2string(bytes, fvalue_length(&fi->value)), name);
5399 label_fill(label_str, hfinfo,
5400 oid_encoded2string(bytes, fvalue_length(&fi->value)));
5404 integer64 = fvalue_get_integer64(&fi->value);
5405 label_fill_descr(label_str, hfinfo,
5406 get_eui64_name(integer64),
5407 eui64_to_str(integer64));
5411 case FT_UINT_STRING:
5412 bytes = fvalue_get(&fi->value);
5413 label_fill(label_str, hfinfo, format_text(bytes, strlen(bytes)));
5417 g_error("hfinfo->type %d (%s) not handled\n",
5418 hfinfo->type, ftype_name(hfinfo->type));
5419 DISSECTOR_ASSERT_NOT_REACHED();
5425 fill_label_boolean(field_info *fi, gchar *label_str)
5427 char *p = label_str;
5428 int bitfield_byte_length = 0, bitwidth;
5429 guint32 unshifted_value;
5432 header_field_info *hfinfo = fi->hfinfo;
5433 const true_false_string *tfstring = (const true_false_string *)&tfs_true_false;
5435 if (hfinfo->strings) {
5436 tfstring = (const struct true_false_string*) hfinfo->strings;
5439 value = fvalue_get_uinteger(&fi->value);
5440 if (hfinfo->bitmask) {
5441 /* Figure out the bit width */
5442 bitwidth = hfinfo_bitwidth(hfinfo);
5445 unshifted_value = value;
5446 if (hfinfo->bitshift > 0) {
5447 unshifted_value <<= hfinfo->bitshift;
5450 /* Create the bitfield first */
5451 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
5452 bitfield_byte_length = (int) (p - label_str);
5455 /* Fill in the textual info */
5456 g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
5457 "%s: %s", hfinfo->name,
5458 value ? tfstring->true_string : tfstring->false_string);
5461 /* Fills data for bitfield ints with val_strings */
5463 fill_label_bitfield(field_info *fi, gchar *label_str)
5465 const char *format = NULL;
5467 int bitfield_byte_length, bitwidth;
5468 guint32 unshifted_value;
5471 header_field_info *hfinfo = fi->hfinfo;
5473 /* Figure out the bit width */
5474 bitwidth = hfinfo_bitwidth(hfinfo);
5477 unshifted_value = fvalue_get_uinteger(&fi->value);
5478 value = unshifted_value;
5479 if (hfinfo->bitshift > 0) {
5480 unshifted_value <<= hfinfo->bitshift;
5483 /* Create the bitfield first */
5484 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
5485 bitfield_byte_length = (int) (p - label_str);
5487 /* Fill in the textual info using stored (shifted) value */
5488 if (hfinfo->display == BASE_CUSTOM) {
5489 gchar tmp[ITEM_LABEL_LENGTH];
5490 custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hfinfo->strings;
5492 DISSECTOR_ASSERT(fmtfunc);
5493 fmtfunc(tmp, value);
5494 g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
5495 "%s: %s", hfinfo->name, tmp);
5497 else if (hfinfo->strings) {
5498 format = hfinfo_uint_vals_format(hfinfo);
5499 if (hfinfo->display & BASE_RANGE_STRING) {
5500 g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
5501 format, hfinfo->name,
5502 rval_to_str(value, hfinfo->strings, "Unknown"), value);
5503 } else if (hfinfo->display & BASE_EXT_STRING) {
5504 g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
5505 format, hfinfo->name,
5506 val_to_str_ext_const(value, (value_string_ext *) hfinfo->strings, "Unknown"), value);
5508 g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
5509 format, hfinfo->name,
5510 val_to_str_const(value, cVALS(hfinfo->strings), "Unknown"), value);
5514 format = hfinfo_uint_format(hfinfo);
5515 if (IS_BASE_DUAL(hfinfo->display)) {
5516 g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
5517 format, hfinfo->name, value, value);
5519 g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
5520 format, hfinfo->name, value);
5526 fill_label_uint(field_info *fi, gchar *label_str)
5528 const char *format = NULL;
5529 header_field_info *hfinfo = fi->hfinfo;
5532 value = fvalue_get_uinteger(&fi->value);
5534 /* Fill in the textual info */
5535 if (hfinfo->display == BASE_CUSTOM) {
5536 gchar tmp[ITEM_LABEL_LENGTH];
5537 custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hfinfo->strings;
5539 DISSECTOR_ASSERT(fmtfunc);
5540 fmtfunc(tmp, value);
5541 label_fill(label_str, hfinfo, tmp);
5543 else if (hfinfo->strings) {
5544 format = hfinfo_uint_vals_format(hfinfo);
5545 if (hfinfo->display & BASE_RANGE_STRING) {
5546 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5547 format, hfinfo->name,
5548 rval_to_str(value, hfinfo->strings, "Unknown"), value);
5549 } else if (hfinfo->display & BASE_EXT_STRING) {
5550 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5551 format, hfinfo->name,
5552 val_to_str_ext_const(value, (value_string_ext *) hfinfo->strings, "Unknown"), value);
5554 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5555 format, hfinfo->name,
5556 val_to_str_const(value, cVALS(hfinfo->strings), "Unknown"), value);
5560 format = hfinfo_uint_format(hfinfo);
5561 if (IS_BASE_DUAL(hfinfo->display)) {
5562 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5563 format, hfinfo->name, value, value);
5565 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5566 format, hfinfo->name, value);
5572 fill_label_uint64(field_info *fi, gchar *label_str)
5574 const char *format = NULL;
5575 header_field_info *hfinfo = fi->hfinfo;
5578 /* Pick the proper format string */
5579 format = hfinfo_uint64_format(hfinfo);
5580 value = fvalue_get_integer64(&fi->value);
5582 /* Fill in the textual info */
5583 if (IS_BASE_DUAL(hfinfo->display)) {
5584 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5585 format, hfinfo->name, value, value);
5587 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5588 format, hfinfo->name, value);
5593 fill_label_int(field_info *fi, gchar *label_str)
5595 const char *format = NULL;
5596 header_field_info *hfinfo = fi->hfinfo;
5599 value = fvalue_get_sinteger(&fi->value);
5601 /* Fill in the textual info */
5602 if (hfinfo->display == BASE_CUSTOM) {
5603 gchar tmp[ITEM_LABEL_LENGTH];
5604 custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hfinfo->strings;
5606 DISSECTOR_ASSERT(fmtfunc);
5607 fmtfunc(tmp, value);
5608 label_fill(label_str, hfinfo, tmp);
5610 else if (hfinfo->strings) {
5611 format = hfinfo_int_vals_format(hfinfo);
5612 if (hfinfo->display & BASE_RANGE_STRING) {
5613 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5614 format, hfinfo->name,
5615 rval_to_str(value, hfinfo->strings, "Unknown"), value);
5616 } else if (hfinfo->display & BASE_EXT_STRING) {
5617 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5618 format, hfinfo->name,
5619 val_to_str_ext_const(value, (value_string_ext *) hfinfo->strings, "Unknown"), value);
5621 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5622 format, hfinfo->name,
5623 val_to_str_const(value, cVALS(hfinfo->strings), "Unknown"), value);
5627 format = hfinfo_int_format(hfinfo);
5628 if (IS_BASE_DUAL(hfinfo->display)) {
5629 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5630 format, hfinfo->name, value, value);
5632 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5633 format, hfinfo->name, value);
5639 fill_label_int64(field_info *fi, gchar *label_str)
5641 const char *format = NULL;
5642 header_field_info *hfinfo = fi->hfinfo;
5645 /* Pick the proper format string */
5646 format = hfinfo_int64_format(hfinfo);
5647 value = fvalue_get_integer64(&fi->value);
5649 /* Fill in the textual info */
5650 if (IS_BASE_DUAL(hfinfo->display)) {
5651 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5652 format, hfinfo->name, value, value);
5654 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5655 format, hfinfo->name, value);
5660 hfinfo_bitwidth(const header_field_info *hfinfo)
5664 if (!hfinfo->bitmask) {
5668 switch (hfinfo->type) {
5686 bitwidth = hfinfo->display; /* hacky? :) */
5689 DISSECTOR_ASSERT_NOT_REACHED();
5696 hfinfo_uint_vals_format(const header_field_info *hfinfo)
5698 const char *format = NULL;
5700 /* Get the underlying BASE_ value */
5701 switch (hfinfo->display & BASE_DISPLAY_E_MASK) {
5707 format = "%s: %s (%u)";
5709 case BASE_OCT: /* I'm lazy */
5710 format = "%s: %s (%#o)";
5714 switch (hfinfo->type) {
5716 format = "%s: %s (0x%02x)";
5719 format = "%s: %s (0x%04x)";
5722 format = "%s: %s (0x%06x)";
5725 format = "%s: %s (0x%08x)";
5728 DISSECTOR_ASSERT_NOT_REACHED();
5733 DISSECTOR_ASSERT_NOT_REACHED();
5740 hfinfo_uint_format(const header_field_info *hfinfo)
5742 const char *format = NULL;
5744 /* Pick the proper format string */
5745 if (hfinfo->type == FT_FRAMENUM) {
5747 * Frame numbers are always displayed in decimal.
5751 switch (hfinfo->display) {
5756 switch (hfinfo->type) {
5758 format = "%s: %u (0x%02x)";
5761 format = "%s: %u (0x%04x)";
5764 format = "%s: %u (0x%06x)";
5767 format = "%s: %u (0x%08x)";
5770 DISSECTOR_ASSERT_NOT_REACHED();
5774 case BASE_OCT: /* I'm lazy */
5778 switch (hfinfo->type) {
5780 format = "%s: 0x%02x";
5783 format = "%s: 0x%04x";
5786 format = "%s: 0x%06x";
5789 format = "%s: 0x%08x";
5792 DISSECTOR_ASSERT_NOT_REACHED();
5797 switch (hfinfo->type) {
5799 format = "%s: 0x%02x (%u)";
5802 format = "%s: 0x%04x (%u)";
5805 format = "%s: 0x%06x (%u)";
5808 format = "%s: 0x%08x (%u)";
5811 DISSECTOR_ASSERT_NOT_REACHED();
5816 DISSECTOR_ASSERT_NOT_REACHED();
5824 hfinfo_uint_value_format(const header_field_info *hfinfo)
5826 const char *format = NULL;
5828 /* Pick the proper format string */
5829 if (hfinfo->type == FT_FRAMENUM) {
5831 * Frame numbers are always displayed in decimal.
5835 switch (hfinfo->display) {
5840 switch (hfinfo->type) {
5842 format = "%u (0x%02x)";
5845 format = "%u (0x%04x)";
5848 format = "%u (0x%06x)";
5851 format = "%u (0x%08x)";
5854 DISSECTOR_ASSERT_NOT_REACHED();
5862 switch (hfinfo->type) {
5876 DISSECTOR_ASSERT_NOT_REACHED();
5881 switch (hfinfo->type) {
5883 format = "0x%02x (%u)";
5886 format = "0x%04x (%u)";
5889 format = "0x%06x (%u)";
5892 format = "0x%08x (%u)";
5895 DISSECTOR_ASSERT_NOT_REACHED();
5900 DISSECTOR_ASSERT_NOT_REACHED();
5908 hfinfo_int_vals_format(const header_field_info *hfinfo)
5910 const char *format = NULL;
5912 /* Get the underlying BASE_ value */
5913 switch (hfinfo->display & BASE_DISPLAY_E_MASK) {
5919 format = "%s: %s (%d)";
5921 case BASE_OCT: /* I'm lazy */
5922 format = "%s: %s (%#o)";
5926 switch (hfinfo->type) {
5928 format = "%s: %s (0x%02x)";
5931 format = "%s: %s (0x%04x)";
5934 format = "%s: %s (0x%06x)";
5937 format = "%s: %s (0x%08x)";
5940 DISSECTOR_ASSERT_NOT_REACHED();
5945 DISSECTOR_ASSERT_NOT_REACHED();
5952 hfinfo_uint64_format(const header_field_info *hfinfo)
5954 const char *format = NULL;
5956 /* Pick the proper format string */
5957 switch (hfinfo->display) {
5959 format = "%s: %" G_GINT64_MODIFIER "u";
5962 format = "%s: %" G_GINT64_MODIFIER "u (0x%016" G_GINT64_MODIFIER "x)";
5964 case BASE_OCT: /* I'm lazy */
5965 format = "%s: %#" G_GINT64_MODIFIER "o";
5968 format = "%s: 0x%016" G_GINT64_MODIFIER "x";
5971 format = "%s: 0x%016" G_GINT64_MODIFIER "x (%" G_GINT64_MODIFIER "u)";
5974 DISSECTOR_ASSERT_NOT_REACHED();
5981 hfinfo_int_format(const header_field_info *hfinfo)
5983 const char *format = NULL;
5985 /* Pick the proper format string */
5986 switch (hfinfo->display) {
5991 switch (hfinfo->type) {
5993 format = "%s: %d (0x%02x)";
5996 format = "%s: %d (0x%04x)";
5999 format = "%s: %d (0x%06x)";
6002 format = "%s: %d (0x%08x)";
6005 DISSECTOR_ASSERT_NOT_REACHED();
6009 case BASE_OCT: /* I'm lazy */
6013 switch (hfinfo->type) {
6015 format = "%s: 0x%02x";
6018 format = "%s: 0x%04x";
6021 format = "%s: 0x%06x";
6024 format = "%s: 0x%08x";
6027 DISSECTOR_ASSERT_NOT_REACHED();
6032 switch (hfinfo->type) {
6034 format = "%s: 0x%02x (%d)";
6037 format = "%s: 0x%04x (%d)";
6040 format = "%s: 0x%06x (%d)";
6043 format = "%s: 0x%08x (%d)";
6046 DISSECTOR_ASSERT_NOT_REACHED();
6051 DISSECTOR_ASSERT_NOT_REACHED();
6058 hfinfo_int_value_format(const header_field_info *hfinfo)
6060 const char *format = NULL;
6062 /* Pick the proper format string */
6063 switch (hfinfo->display) {
6068 switch (hfinfo->type) {
6070 format = "%d (0x%02x)";
6073 format = "%d (0x%04x)";
6076 format = "%d (0x%06x)";
6079 format = "%d (0x%08x)";
6082 DISSECTOR_ASSERT_NOT_REACHED();
6090 switch (hfinfo->type) {
6104 DISSECTOR_ASSERT_NOT_REACHED();
6109 switch (hfinfo->type) {
6111 format = "0x%02x (%d)";
6114 format = "0x%04x (%d)";
6117 format = "0x%06x (%d)";
6120 format = "0x%08x (%d)";
6123 DISSECTOR_ASSERT_NOT_REACHED();
6128 DISSECTOR_ASSERT_NOT_REACHED();
6135 hfinfo_int64_format(const header_field_info *hfinfo)
6137 const char *format = NULL;
6139 /* Pick the proper format string */
6140 switch (hfinfo->display) {
6142 format = "%s: %" G_GINT64_MODIFIER "d";
6145 format = "%s: %" G_GINT64_MODIFIER "d (0x%016" G_GINT64_MODIFIER "x)";
6147 case BASE_OCT: /* I'm lazy */
6148 format = "%s: %#" G_GINT64_MODIFIER "o";
6151 format = "%s: 0x%016" G_GINT64_MODIFIER "x";
6154 format = "%s: 0x%016" G_GINT64_MODIFIER "x (%" G_GINT64_MODIFIER "d)";
6157 DISSECTOR_ASSERT_NOT_REACHED();
6164 proto_registrar_n(void)
6166 return gpa_hfinfo.len;
6170 proto_registrar_get_name(const int n)
6172 header_field_info *hfinfo;
6174 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
6175 return hfinfo->name;
6179 proto_registrar_get_abbrev(const int n)
6181 header_field_info *hfinfo;
6183 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
6184 return hfinfo->abbrev;
6188 proto_registrar_get_ftype(const int n)
6190 header_field_info *hfinfo;
6192 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
6193 return hfinfo->type;
6197 proto_registrar_get_parent(const int n)
6199 header_field_info *hfinfo;
6201 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
6202 return hfinfo->parent;
6206 proto_registrar_is_protocol(const int n)
6208 header_field_info *hfinfo;
6210 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
6211 return (hfinfo->parent == -1 ? TRUE : FALSE);
6214 /* Returns length of field in packet (not necessarily the length
6215 * in our internal representation, as in the case of IPv4).
6216 * 0 means undeterminable at time of registration
6217 * -1 means the field is not registered. */
6219 proto_registrar_get_length(const int n)
6221 header_field_info *hfinfo;
6223 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
6224 return ftype_length(hfinfo->type);
6227 /* Looks for a protocol or a field in a proto_tree. Returns TRUE if
6228 * it exists anywhere, or FALSE if it exists nowhere. */
6230 proto_check_for_protocol_or_field(const proto_tree* tree, const int id)
6232 GPtrArray *ptrs = proto_get_finfo_ptr_array(tree, id);
6237 else if (g_ptr_array_len(ptrs) > 0) {
6245 /* Return GPtrArray* of field_info pointers for all hfindex that appear in tree.
6246 * This only works if the hfindex was "primed" before the dissection
6247 * took place, as we just pass back the already-created GPtrArray*.
6248 * The caller should *not* free the GPtrArray*; proto_tree_free_node()
6251 proto_get_finfo_ptr_array(const proto_tree *tree, const int id)
6256 if (PTREE_DATA(tree)->interesting_hfids != NULL)
6257 return g_hash_table_lookup(PTREE_DATA(tree)->interesting_hfids,
6258 GINT_TO_POINTER(id));
6264 proto_tracking_interesting_fields(const proto_tree *tree)
6269 return (PTREE_DATA(tree)->interesting_hfids != NULL);
6272 /* Helper struct for proto_find_info() and proto_all_finfos() */
6278 /* Helper function for proto_find_info() */
6280 find_finfo(proto_node *node, gpointer data)
6282 field_info *fi = PNODE_FINFO(node);
6283 if (fi && fi->hfinfo) {
6284 if (fi->hfinfo->id == ((ffdata_t*)data)->id) {
6285 g_ptr_array_add(((ffdata_t*)data)->array, fi);
6289 /* Don't stop traversing. */
6293 /* Return GPtrArray* of field_info pointers for all hfindex that appear in a tree.
6294 * This works on any proto_tree, primed or unprimed, but actually searches
6295 * the tree, so it is slower than using proto_get_finfo_ptr_array on a primed tree.
6296 * The caller does need to free the returned GPtrArray with
6297 * g_ptr_array_free(<array>, TRUE).
6300 proto_find_finfo(proto_tree *tree, const int id)
6304 ffdata.array = g_ptr_array_new();
6307 proto_tree_traverse_pre_order(tree, find_finfo, &ffdata);
6309 return ffdata.array;
6312 /* Helper function for proto_all_finfos() */
6314 every_finfo(proto_node *node, gpointer data)
6316 field_info *fi = PNODE_FINFO(node);
6317 if (fi && fi->hfinfo) {
6318 g_ptr_array_add(((ffdata_t*)data)->array, fi);
6321 /* Don't stop traversing. */
6325 /* Return GPtrArray* of field_info pointers containing all hfindexes that appear in a tree. */
6327 proto_all_finfos(proto_tree *tree)
6331 ffdata.array = g_ptr_array_new();
6334 proto_tree_traverse_pre_order(tree, every_finfo, &ffdata);
6336 return ffdata.array;
6347 check_for_offset(proto_node *node, const gpointer data)
6349 field_info *fi = PNODE_FINFO(node);
6350 offset_search_t *offsearch = data;
6352 /* !fi == the top most container node which holds nothing */
6353 if (fi && !PROTO_ITEM_IS_HIDDEN(node) && fi->ds_tvb && offsearch->tvb == fi->ds_tvb) {
6354 if (offsearch->offset >= (guint) fi->start &&
6355 offsearch->offset < (guint) (fi->start + fi->length)) {
6357 offsearch->finfo = fi;
6358 return FALSE; /* keep traversing */
6361 return FALSE; /* keep traversing */
6364 /* Search a proto_tree backwards (from leaves to root) looking for the field
6365 * whose start/length occupies 'offset' */
6366 /* XXX - I couldn't find an easy way to search backwards, so I search
6367 * forwards, w/o stopping. Therefore, the last finfo I find will the be
6368 * the one I want to return to the user. This algorithm is inefficient
6369 * and could be re-done, but I'd have to handle all the children and
6370 * siblings of each node myself. When I have more time I'll do that.
6373 proto_find_field_from_offset(proto_tree *tree, guint offset, tvbuff_t *tvb)
6375 offset_search_t offsearch;
6377 offsearch.offset = offset;
6378 offsearch.finfo = NULL;
6379 offsearch.tvb = tvb;
6381 proto_tree_traverse_pre_order(tree, check_for_offset, &offsearch);
6383 return offsearch.finfo;
6386 /* Dumps the protocols in the registration database to stdout. An independent
6387 * program can take this output and format it into nice tables or HTML or
6390 * There is one record per line. The fields are tab-delimited.
6392 * Field 1 = protocol name
6393 * Field 2 = protocol short name
6394 * Field 3 = protocol filter name
6397 proto_registrar_dump_protocols(void)
6399 protocol_t *protocol;
6401 void *cookie = NULL;
6404 i = proto_get_first_protocol(&cookie);
6406 protocol = find_protocol_by_id(i);
6407 printf("%s\t%s\t%s\n", protocol->name, protocol->short_name,
6408 protocol->filter_name);
6409 i = proto_get_next_protocol(&cookie);
6413 /* Dumps the value_strings, extended value string headers, range_strings
6414 * or true/false strings for fields that have them.
6415 * There is one record per line. Fields are tab-delimited.
6416 * There are four types of records: Value String, Extended Value String Header,
6417 * Range String and True/False String. The first field, 'V', 'E', 'R' or 'T', indicates
6418 * the type of record.
6420 * Note that a record will be generated only if the value_string,... is referenced
6421 * in a registered hfinfo entry.
6427 * Field 2 = Field abbreviation to which this value string corresponds
6428 * Field 3 = Integer value
6431 * Extended Value String Headers
6432 * -----------------------------
6434 * Field 2 = Field abbreviation to which this extended value string header corresponds
6435 * Field 3 = Extended Value String "Name"
6436 * Field 4 = Number of entries in the associated value_string array
6437 * Field 5 = Access Type: "Linear Search", "Binary Search", "Direct (indexed) Access"
6442 * Field 2 = Field abbreviation to which this range string corresponds
6443 * Field 3 = Integer value: lower bound
6444 * Field 4 = Integer value: upper bound
6447 * True/False Strings
6448 * ------------------
6450 * Field 2 = Field abbreviation to which this true/false string corresponds
6451 * Field 3 = True String
6452 * Field 4 = False String
6455 proto_registrar_dump_values(void)
6457 header_field_info *hfinfo;
6459 const value_string *vals;
6460 const range_string *range;
6461 const true_false_string *tfs;
6463 len = gpa_hfinfo.len;
6464 for (i = 0; i < len ; i++) {
6465 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
6467 if (hfinfo->id == hf_text_only) {
6471 /* ignore protocols */
6472 if (proto_registrar_is_protocol(i)) {
6475 /* process header fields */
6478 * If this field isn't at the head of the list of
6479 * fields with this name, skip this field - all
6480 * fields with the same name are really just versions
6481 * of the same field stored in different bits, and
6482 * should have the same type/radix/value list, and
6483 * just differ in their bit masks. (If a field isn't
6484 * a bitfield, but can be, say, 1 or 2 bytes long,
6485 * it can just be made FT_UINT16, meaning the
6486 * *maximum* length is 2 bytes, and be used
6489 if (hfinfo->same_name_prev != NULL)
6496 if (hfinfo->strings != NULL) {
6497 if ((hfinfo->display & BASE_DISPLAY_E_MASK) != BASE_CUSTOM &&
6498 (hfinfo->type == FT_UINT8 ||
6499 hfinfo->type == FT_UINT16 ||
6500 hfinfo->type == FT_UINT24 ||
6501 hfinfo->type == FT_UINT32 ||
6502 hfinfo->type == FT_UINT64 ||
6503 hfinfo->type == FT_INT8 ||
6504 hfinfo->type == FT_INT16 ||
6505 hfinfo->type == FT_INT24 ||
6506 hfinfo->type == FT_INT32 ||
6507 hfinfo->type == FT_INT64)) {
6509 if (hfinfo->display & BASE_EXT_STRING) {
6510 vals = VALUE_STRING_EXT_VS_P((value_string_ext *)hfinfo->strings);
6511 } else if ((hfinfo->display & BASE_RANGE_STRING) == 0) {
6512 vals = hfinfo->strings;
6514 range = hfinfo->strings;
6517 else if (hfinfo->type == FT_BOOLEAN) {
6518 tfs = hfinfo->strings;
6522 /* Print value strings? */
6524 if (hfinfo->display & BASE_EXT_STRING) {
6525 value_string_ext *vse_p = (value_string_ext *)hfinfo->strings;
6526 if (!value_string_ext_validate(vse_p)) {
6527 g_warning("Invalid value_string_ext ptr for: %s", hfinfo->abbrev);
6530 match_strval_ext(0, vse_p); /* "prime" the extended value_string */
6531 printf("E\t%s\t%d\t%s\t%s\n",
6533 VALUE_STRING_EXT_VS_NUM_ENTRIES(vse_p),
6534 VALUE_STRING_EXT_VS_NAME(vse_p),
6535 value_string_ext_match_type_str(vse_p));
6538 while (vals[vi].strptr) {
6539 /* Print in the proper base */
6540 if (hfinfo->display == BASE_HEX) {
6541 printf("V\t%s\t0x%x\t%s\n",
6547 printf("V\t%s\t%u\t%s\n",
6556 /* print range strings? */
6559 while (range[vi].strptr) {
6560 /* Print in the proper base */
6561 if ((hfinfo->display & BASE_DISPLAY_E_MASK) == BASE_HEX) {
6562 printf("R\t%s\t0x%x\t0x%x\t%s\n",
6564 range[vi].value_min,
6565 range[vi].value_max,
6569 printf("R\t%s\t%u\t%u\t%s\n",
6571 range[vi].value_min,
6572 range[vi].value_max,
6579 /* Print true/false strings? */
6581 printf("T\t%s\t%s\t%s\n", hfinfo->abbrev,
6582 tfs->true_string, tfs->false_string);
6588 /* Dumps the contents of the registration database to stdout. An independent
6589 * program can take this output and format it into nice tables or HTML or
6592 * There is one record per line. Each record is either a protocol or a header
6593 * field, differentiated by the first field. The fields are tab-delimited.
6598 * Field 2 = descriptive protocol name
6599 * Field 3 = protocol abbreviation
6605 * Field 2 = descriptive field name
6606 * Field 3 = field abbreviation
6607 * Field 4 = type ( textual representation of the the ftenum type )
6608 * Field 5 = parent protocol abbreviation
6609 * Field 6 = blurb describing field
6613 * Field 2 = descriptive field name
6614 * Field 3 = field abbreviation
6615 * Field 4 = type ( textual representation of the the ftenum type )
6616 * Field 5 = parent protocol abbreviation
6617 * Field 6 = blurb describing field
6618 * Field 7 = base for display (for integer types); "parent bitfield width" for FT_BOOLEAN
6619 * Field 8 = blurb describing field (yes, apparently we repeated this accidentally)
6623 * Field 2 = descriptive field name
6624 * Field 3 = field abbreviation
6625 * Field 4 = type ( textual representation of the the ftenum type )
6626 * Field 5 = parent protocol abbreviation
6627 * Field 6 = blurb describing field
6628 * Field 7 = base for display (for integer types); "parent bitfield width" for FT_BOOLEAN
6629 * Field 8 = bitmask: format: hex: 0x....
6632 proto_registrar_dump_fields(const int format)
6634 header_field_info *hfinfo, *parent_hfinfo;
6636 const char *enum_name;
6637 const char *base_name;
6641 len = gpa_hfinfo.len;
6642 for (i = 0; i < len ; i++) {
6643 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
6646 * Skip the pseudo-field for "proto_tree_add_text()" since
6647 * we don't want it in the list of filterable fields.
6649 if (hfinfo->id == hf_text_only)
6652 /* format for protocols */
6653 if (proto_registrar_is_protocol(i)) {
6654 printf("P\t%s\t%s\n", hfinfo->name, hfinfo->abbrev);
6656 /* format for header fields */
6659 * If this field isn't at the head of the list of
6660 * fields with this name, skip this field - all
6661 * fields with the same name are really just versions
6662 * of the same field stored in different bits, and
6663 * should have the same type/radix/value list, and
6664 * just differ in their bit masks. (If a field isn't
6665 * a bitfield, but can be, say, 1 or 2 bytes long,
6666 * it can just be made FT_UINT16, meaning the
6667 * *maximum* length is 2 bytes, and be used
6670 if (hfinfo->same_name_prev != NULL)
6673 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
6675 enum_name = ftype_name(hfinfo->type);
6679 if (hfinfo->type == FT_UINT8 ||
6680 hfinfo->type == FT_UINT16 ||
6681 hfinfo->type == FT_UINT24 ||
6682 hfinfo->type == FT_UINT32 ||
6683 hfinfo->type == FT_UINT64 ||
6684 hfinfo->type == FT_INT8 ||
6685 hfinfo->type == FT_INT16 ||
6686 hfinfo->type == FT_INT24 ||
6687 hfinfo->type == FT_INT32 ||
6688 hfinfo->type == FT_INT64) {
6691 switch (hfinfo->display & BASE_DISPLAY_E_MASK) {
6693 base_name = "BASE_NONE";
6696 base_name = "BASE_DEC";
6699 base_name = "BASE_HEX";
6702 base_name = "BASE_OCT";
6705 base_name = "BASE_DEC_HEX";
6708 base_name = "BASE_HEX_DEC";
6711 base_name = "BASE_CUSTOM";
6717 } else if (hfinfo->type == FT_BOOLEAN) {
6718 /* For FT_BOOLEAN: 'display' can be "parent bitfield width" */
6719 g_snprintf(width, sizeof(width), "%d", hfinfo->display);
6724 blurb = hfinfo->blurb;
6727 else if (strlen(blurb) == 0)
6730 printf("F\t%s\t%s\t%s\t%s\t%s\n",
6731 hfinfo->name, hfinfo->abbrev, enum_name,
6732 parent_hfinfo->abbrev, blurb);
6734 else if (format == 2) {
6735 printf("F\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n",
6736 hfinfo->name, hfinfo->abbrev, enum_name,
6737 parent_hfinfo->abbrev, blurb,
6740 else if (format == 3) {
6741 printf("F\t%s\t%s\t%s\t%s\t%s\t%s\t0x%x\n",
6742 hfinfo->name, hfinfo->abbrev, enum_name,
6743 parent_hfinfo->abbrev, blurb,
6744 base_name, hfinfo->bitmask);
6747 g_assert_not_reached();
6753 /* Dumps field types and descriptive names to stdout. An independent
6754 * program can take this output and format it into nice tables or HTML or
6757 * There is one record per line. The fields are tab-delimited.
6759 * Field 1 = field type name, e.g. FT_UINT8
6760 * Field 2 = descriptive name, e.g. "Unsigned, 1 byte"
6763 proto_registrar_dump_ftypes(void)
6767 for (fte = 0; fte < FT_NUM_TYPES; fte++) {
6768 printf("%s\t%s\n", ftype_name(fte), ftype_pretty_name(fte));
6773 hfinfo_numeric_format(const header_field_info *hfinfo)
6775 const char *format = NULL;
6777 /* Pick the proper format string */
6778 if (hfinfo->type == FT_FRAMENUM) {
6780 * Frame numbers are always displayed in decimal.
6782 format = "%s == %u";
6784 /* Get the underlying BASE_ value */
6785 switch (hfinfo->display & BASE_DISPLAY_E_MASK) {
6788 case BASE_OCT: /* I'm lazy */
6790 switch (hfinfo->type) {
6795 format = "%s == %u";
6798 format = "%s == %" G_GINT64_MODIFIER "u";
6804 format = "%s == %d";
6807 format = "%s == %" G_GINT64_MODIFIER "d";
6810 DISSECTOR_ASSERT_NOT_REACHED();
6816 switch (hfinfo->type) {
6819 format = "%s == 0x%02x";
6823 format = "%s == 0x%04x";
6827 format = "%s == 0x%06x";
6831 format = "%s == 0x%08x";
6835 format = "%s == 0x%016" G_GINT64_MODIFIER "x";
6838 DISSECTOR_ASSERT_NOT_REACHED();
6843 DISSECTOR_ASSERT_NOT_REACHED();
6851 hfinfo_numeric_value_format(const header_field_info *hfinfo)
6853 const char *format = NULL;
6855 /* Pick the proper format string */
6856 if (hfinfo->type == FT_FRAMENUM) {
6858 * Frame numbers are always displayed in decimal.
6862 /* Get the underlying BASE_ value */
6863 switch (hfinfo->display & BASE_DISPLAY_E_MASK) {
6867 case BASE_OCT: /* I'm lazy */
6869 switch (hfinfo->type) {
6877 format = "%" G_GINT64_MODIFIER "u";
6886 format = "%" G_GINT64_MODIFIER "d";
6889 DISSECTOR_ASSERT_NOT_REACHED();
6895 switch (hfinfo->type) {
6914 format = "0x%016" G_GINT64_MODIFIER "x";
6917 DISSECTOR_ASSERT_NOT_REACHED();
6922 DISSECTOR_ASSERT_NOT_REACHED();
6929 /* This function indicates whether it's possible to construct a
6930 * "match selected" display filter string for the specified field,
6931 * returns an indication of whether it's possible, and, if it's
6932 * possible and "filter" is non-null, constructs the filter and
6933 * sets "*filter" to point to it.
6934 * You do not need to [g_]free() this string since it will be automatically
6935 * freed once the next packet is dissected.
6938 construct_match_selected_string(field_info *finfo, epan_dissect_t *edt,
6941 header_field_info *hfinfo;
6947 gint start, length, length_remaining;
6949 gchar is_signed_num = FALSE;
6951 hfinfo = finfo->hfinfo;
6952 DISSECTOR_ASSERT(hfinfo);
6953 abbrev_len = (int) strlen(hfinfo->abbrev);
6955 if (hfinfo->strings && (hfinfo->display & BASE_DISPLAY_E_MASK) == BASE_NONE) {
6956 const gchar *str = NULL;
6958 switch (hfinfo->type) {
6964 if (hfinfo->display & BASE_RANGE_STRING) {
6965 str = match_strrval(fvalue_get_sinteger(&finfo->value), hfinfo->strings);
6966 } else if (hfinfo->display & BASE_EXT_STRING) {
6967 str = match_strval_ext(fvalue_get_sinteger(&finfo->value), hfinfo->strings);
6969 str = match_strval(fvalue_get_sinteger(&finfo->value), hfinfo->strings);
6977 if (hfinfo->display & BASE_RANGE_STRING) {
6978 str = match_strrval(fvalue_get_uinteger(&finfo->value), hfinfo->strings);
6979 } else if (hfinfo->display & BASE_EXT_STRING) {
6980 str = match_strval_ext(fvalue_get_uinteger(&finfo->value), hfinfo->strings);
6982 str = match_strval(fvalue_get_uinteger(&finfo->value), hfinfo->strings);
6990 if (str != NULL && filter != NULL) {
6991 *filter = ep_strdup_printf("%s == \"%s\"", hfinfo->abbrev, str);
6997 * XXX - we can't use the "val_to_string_repr" and "string_repr_len"
6998 * functions for FT_UINT and FT_INT types, as we choose the base in
6999 * the string expression based on the display base of the field.
7001 * Note that the base does matter, as this is also used for
7002 * the protocolinfo tap.
7004 * It might be nice to use them in "proto_item_fill_label()"
7005 * as well, although, there, you'd have to deal with the base
7006 * *and* with resolved values for addresses.
7008 * Perhaps we need two different val_to_string routines, one
7009 * to generate items for display filters and one to generate
7010 * strings for display, and pass to both of them the
7011 * "display" and "strings" values in the header_field_info
7012 * structure for the field, so they can get the base and,
7013 * if the field is Boolean or an enumerated integer type,
7014 * the tables used to generate human-readable values.
7016 switch (hfinfo->type) {
7022 is_signed_num = TRUE;
7028 if (filter != NULL) {
7029 format = hfinfo_numeric_format(hfinfo);
7030 if (is_signed_num) {
7031 *filter = ep_strdup_printf(format,
7033 fvalue_get_sinteger(&finfo->value));
7035 *filter = ep_strdup_printf(format,
7037 fvalue_get_uinteger(&finfo->value));
7043 DISSECTOR_ASSERT(!is_signed_num);
7044 if (filter != NULL) {
7045 format = hfinfo_numeric_format(hfinfo);
7046 *filter = ep_strdup_printf(format,
7048 fvalue_get_uinteger(&finfo->value));
7054 if (filter != NULL) {
7055 format = hfinfo_numeric_format(hfinfo);
7056 *filter = ep_strdup_printf(format,
7058 fvalue_get_integer64(&finfo->value));
7064 *filter = ep_strdup(finfo->hfinfo->abbrev);
7069 * If the length is 0, just match the name of the
7072 * (Also check for negative values, just in case,
7073 * as we'll cast it to an unsigned value later.)
7075 length = finfo->length;
7078 *filter = ep_strdup(finfo->hfinfo->abbrev);
7085 * This doesn't have a value, so we'd match
7086 * on the raw bytes at this address.
7088 * Should we be allowed to access to the raw bytes?
7089 * If "edt" is NULL, the answer is "no".
7095 * Is this field part of the raw frame tvbuff?
7096 * If not, we can't use "frame[N:M]" to match
7099 * XXX - should this be frame-relative, or
7100 * protocol-relative?
7102 * XXX - does this fallback for non-registered
7103 * fields even make sense?
7105 if (finfo->ds_tvb != edt->tvb)
7106 return FALSE; /* you lose */
7109 * Don't go past the end of that tvbuff.
7111 length_remaining = tvb_length_remaining(finfo->ds_tvb, finfo->start);
7112 if (length > length_remaining)
7113 length = length_remaining;
7117 if (filter != NULL) {
7118 start = finfo->start;
7119 buf_len = 32 + length * 3;
7120 *filter = ep_alloc0(buf_len);
7123 ptr += g_snprintf(ptr, (gulong) (buf_len-(ptr-*filter)),
7124 "frame[%d:%d] == ", finfo->start, length);
7125 for (i=0; i<length; i++) {
7126 c = tvb_get_guint8(finfo->ds_tvb, start);
7129 ptr += g_snprintf(ptr, (gulong) (buf_len-(ptr-*filter)), "%02x", c);
7132 ptr += g_snprintf(ptr, (gulong) (buf_len-(ptr-*filter)), ":%02x", c);
7139 /* FT_PCRE never appears as a type for a registered field. It is
7140 * only used internally. */
7141 DISSECTOR_ASSERT_NOT_REACHED();
7144 /* By default, use the fvalue's "to_string_repr" method. */
7146 /* Figure out the string length needed.
7147 * The ft_repr length.
7148 * 4 bytes for " == ".
7149 * 1 byte for trailing NUL.
7151 if (filter != NULL) {
7152 dfilter_len = fvalue_string_repr_len(&finfo->value,
7154 dfilter_len += abbrev_len + 4 + 1;
7155 *filter = ep_alloc0(dfilter_len);
7157 /* Create the string */
7158 g_snprintf(*filter, dfilter_len, "%s == ",
7160 fvalue_to_string_repr(&finfo->value,
7162 &(*filter)[abbrev_len + 4]);
7171 * Returns TRUE if we can do a "match selected" on the field, FALSE
7175 proto_can_match_selected(field_info *finfo, epan_dissect_t *edt)
7177 return construct_match_selected_string(finfo, edt, NULL);
7180 /* This function attempts to construct a "match selected" display filter
7181 * string for the specified field; if it can do so, it returns a pointer
7182 * to the string, otherwise it returns NULL.
7184 * The string is allocated with packet lifetime scope.
7185 * You do not need to [g_]free() this string since it will be automatically
7186 * freed once the next packet is dissected.
7189 proto_construct_match_selected_string(field_info *finfo, epan_dissect_t *edt)
7193 if (!construct_match_selected_string(finfo, edt, &filter))
7198 /* This function is common code for both proto_tree_add_bitmask() and
7199 * proto_tree_add_bitmask_text() functions.
7202 /* NOTE: to support code written when proto_tree_add_bitmask() and
7203 * proto_tree_add_bitmask_text took a
7204 * gboolean as its last argument, with FALSE meaning "big-endian"
7205 * and TRUE meaning "little-endian", we treat any non-zero value of
7206 * "encoding" as meaning "little-endian".
7209 proto_item_add_bitmask_tree(proto_item *item, tvbuff_t *tvb, const int offset,
7210 const int len, const gint ett, const int **fields,
7211 const guint encoding, const int flags,
7216 proto_tree *tree = NULL;
7217 header_field_info *hf;
7222 value = tvb_get_guint8(tvb, offset);
7225 value = encoding ? tvb_get_letohs(tvb, offset) :
7226 tvb_get_ntohs(tvb, offset);
7229 value = encoding ? tvb_get_letoh24(tvb, offset) :
7230 tvb_get_ntoh24(tvb, offset);
7233 value = encoding ? tvb_get_letohl(tvb, offset) :
7234 tvb_get_ntohl(tvb, offset);
7237 g_assert_not_reached();
7240 tree = proto_item_add_subtree(item, ett);
7242 proto_tree_add_item(tree, **fields, tvb, offset, len, encoding);
7243 if (flags & BMT_NO_APPEND) {
7247 hf = proto_registrar_get_nth(**fields);
7248 DISSECTOR_ASSERT(hf->bitmask != 0);
7249 tmpval = (value & hf->bitmask) >> hf->bitshift;
7260 DISSECTOR_ASSERT(len == ftype_length(hf->type));
7262 if (hf->display == BASE_CUSTOM) {
7263 gchar lbl[ITEM_LABEL_LENGTH];
7264 custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hf->strings;
7266 DISSECTOR_ASSERT(fmtfunc);
7267 fmtfunc(lbl, tmpval);
7268 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
7272 else if (hf->strings) {
7273 if (hf->display & BASE_RANGE_STRING) {
7274 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
7275 hf->name, rval_to_str(tmpval, hf->strings, "Unknown"));
7276 } else if (hf->display & BASE_EXT_STRING) {
7277 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
7278 hf->name, val_to_str_ext_const(tmpval, (value_string_ext *) (hf->strings), "Unknown"));
7280 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
7281 hf->name, val_to_str_const(tmpval, cVALS(hf->strings), "Unknown"));
7285 else if (!(flags & BMT_NO_INT)) {
7287 proto_item_append_text(item, ", ");
7290 fmt = IS_FT_INT(hf->type) ? hfinfo_int_format(hf) : hfinfo_uint_format(hf);
7291 if (IS_BASE_DUAL(hf->display)) {
7292 proto_item_append_text(item, fmt, hf->name, tmpval, tmpval);
7294 proto_item_append_text(item, fmt, hf->name, tmpval);
7301 DISSECTOR_ASSERT(len * 8 == hf->display);
7303 if (hf->strings && !(flags & BMT_NO_TFS)) {
7304 /* If we have true/false strings, emit full - otherwise messages
7306 const struct true_false_string *tfs =
7307 (const struct true_false_string *)hf->strings;
7310 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
7311 hf->name, tfs->true_string);
7313 } else if (!(flags & BMT_NO_FALSE)) {
7314 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
7315 hf->name, tfs->false_string);
7318 } else if (hf->bitmask & value) {
7319 /* If the flag is set, show the name */
7320 proto_item_append_text(item, "%s%s", first ? "" : ", ", hf->name);
7325 g_assert_not_reached();
7334 /* This function will dissect a sequence of bytes that describe a
7336 * hf_hdr is a 8/16/24/32 bit integer that describes the bitmask to be dissected.
7337 * This field will form an expansion under which the individual fields of the
7338 * bitmask is dissected and displayed.
7339 * This field must be of the type FT_[U]INT{8|16|24|32}.
7341 * fields is an array of pointers to int that lists all the fields of the
7342 * bitmask. These fields can be either of the type FT_BOOLEAN for flags
7343 * or another integer of the same type/size as hf_hdr with a mask specified.
7344 * This array is terminated by a NULL entry.
7346 * FT_BOOLEAN bits that are set to 1 will have the name added to the expansion.
7347 * FT_integer fields that have a value_string attached will have the
7348 * matched string displayed on the expansion line.
7351 proto_tree_add_bitmask(proto_tree *parent_tree, tvbuff_t *tvb,
7352 const guint offset, const int hf_hdr,
7353 const gint ett, const int **fields,
7354 const guint encoding)
7356 proto_item *item = NULL;
7357 header_field_info *hf;
7360 hf = proto_registrar_get_nth(hf_hdr);
7361 DISSECTOR_ASSERT(IS_FT_INT(hf->type) || IS_FT_UINT(hf->type));
7362 len = ftype_length(hf->type);
7365 item = proto_tree_add_item(parent_tree, hf_hdr, tvb, offset, len, encoding);
7366 proto_item_add_bitmask_tree(item, tvb, offset, len, ett, fields, encoding,
7367 BMT_NO_INT|BMT_NO_TFS, FALSE);
7373 /* The same as proto_tree_add_bitmask(), but using an arbitrary text as a top-level item */
7375 proto_tree_add_bitmask_text(proto_tree *parent_tree, tvbuff_t *tvb,
7376 const guint offset, const guint len,
7377 const char *name, const char *fallback,
7378 const gint ett, const int **fields,
7379 const guint encoding, const int flags)
7381 proto_item *item = NULL;
7384 item = proto_tree_add_text(parent_tree, tvb, offset, len, "%s", name ? name : "");
7385 if (proto_item_add_bitmask_tree(item, tvb, offset, len, ett, fields, encoding,
7386 flags, TRUE) && fallback) {
7387 /* Still at first item - append 'fallback' text if any */
7388 proto_item_append_text(item, "%s", fallback);
7396 proto_tree_add_bits_item(proto_tree *tree, const int hf_index, tvbuff_t *tvb,
7397 const guint bit_offset, const gint no_of_bits,
7398 const guint encoding)
7400 header_field_info *hfinfo;
7402 TRY_TO_FAKE_THIS_ITEM(tree, hf_index, hfinfo);
7404 return proto_tree_add_bits_ret_val(tree, hf_index, tvb, bit_offset, no_of_bits, NULL, encoding);
7408 * This function will dissect a sequence of bits that does not need to be byte aligned; the bits
7409 * set will be shown in the tree as ..10 10.. and the integer value returned if return_value is set.
7410 * Offset should be given in bits from the start of the tvb.
7414 _proto_tree_add_bits_ret_val(proto_tree *tree, const int hf_index, tvbuff_t *tvb,
7415 const guint bit_offset, const gint no_of_bits,
7416 guint64 *return_value, const guint encoding)
7422 char lbl_str[ITEM_LABEL_LENGTH];
7426 header_field_info *hf_field;
7428 const true_false_string *tfstring;
7430 /* We can't fake it just yet. We have to fill in the 'return_value' parameter */
7431 PROTO_REGISTRAR_GET_NTH(hf_index, hf_field);
7433 if (hf_field->bitmask != 0) {
7434 REPORT_DISSECTOR_BUG(ep_strdup_printf("Incompatible use of proto_tree_add_bits_ret_val"
7435 " with field '%s' (%s) with bitmask != 0",
7436 hf_field->abbrev, hf_field->name));
7439 DISSECTOR_ASSERT(no_of_bits > 0);
7441 /* Byte align offset */
7442 offset = bit_offset>>3;
7445 * Calculate the number of octets used to hold the bits
7447 tot_no_bits = ((bit_offset&0x7) + no_of_bits);
7448 length = tot_no_bits>>3;
7449 /* If we are using part of the next octet, increase length by 1 */
7450 if (tot_no_bits & 0x07)
7453 if (no_of_bits < 65) {
7454 value = tvb_get_bits64(tvb, bit_offset, no_of_bits, encoding);
7456 DISSECTOR_ASSERT_NOT_REACHED();
7460 /* Sign extend for signed types */
7461 switch (hf_field->type) {
7467 if (value & (G_GINT64_CONSTANT(1) << (no_of_bits-1)))
7468 value |= (G_GINT64_CONSTANT(-1) << no_of_bits);
7476 *return_value = value;
7479 /* Coast clear. Try and fake it */
7480 TRY_TO_FAKE_THIS_ITEM(tree, hf_index, hf_field);
7482 bf_str = decode_bits_in_field(bit_offset, no_of_bits, value);
7484 switch (hf_field->type) {
7487 tfstring = (const true_false_string *) &tfs_true_false;
7488 if (hf_field->strings)
7489 tfstring = (const true_false_string *)hf_field->strings;
7490 return proto_tree_add_boolean_format(tree, hf_index, tvb, offset, length, (guint32)value,
7492 bf_str, hf_field->name,
7493 (guint32)value ? tfstring->true_string : tfstring->false_string);
7500 pi = proto_tree_add_uint(tree, hf_index, tvb, offset, length, (guint32)value);
7501 fill_label_uint(PITEM_FINFO(pi), lbl_str);
7508 pi = proto_tree_add_int(tree, hf_index, tvb, offset, length, (gint32)value);
7509 fill_label_int(PITEM_FINFO(pi), lbl_str);
7513 pi = proto_tree_add_uint64(tree, hf_index, tvb, offset, length, value);
7514 fill_label_uint64(PITEM_FINFO(pi), lbl_str);
7518 pi = proto_tree_add_int64(tree, hf_index, tvb, offset, length, (gint64)value);
7519 fill_label_int64(PITEM_FINFO(pi), lbl_str);
7523 DISSECTOR_ASSERT_NOT_REACHED();
7528 proto_item_set_text(pi, "%s = %s", bf_str, lbl_str);
7533 proto_tree_add_split_bits_item_ret_val(proto_tree *tree, const int hf_index, tvbuff_t *tvb,
7534 const guint bit_offset, const crumb_spec_t *crumb_spec,
7535 guint64 *return_value)
7540 guint mask_initial_bit_offset;
7541 guint mask_greatest_bit_offset;
7545 char lbl_str[ITEM_LABEL_LENGTH];
7547 guint64 composite_bitmask;
7548 guint64 composite_bitmap;
7550 header_field_info *hf_field;
7551 const true_false_string *tfstring;
7553 /* We can't fake it just yet. We have to fill in the 'return_value' parameter */
7554 PROTO_REGISTRAR_GET_NTH(hf_index, hf_field);
7556 if (hf_field->bitmask != 0) {
7557 REPORT_DISSECTOR_BUG(ep_strdup_printf(
7558 "Incompatible use of proto_tree_add_split_bits_item_ret_val"
7559 " with field '%s' (%s) with bitmask != 0",
7560 hf_field->abbrev, hf_field->name));
7563 mask_initial_bit_offset = bit_offset % 8;
7568 mask_greatest_bit_offset = 0;
7569 composite_bitmask = 0;
7570 composite_bitmap = 0;
7572 while (crumb_spec[i].crumb_bit_length != 0) {
7573 guint64 crumb_mask, crumb_value;
7574 guint8 crumb_end_bit_offset;
7576 DISSECTOR_ASSERT(i < 64);
7577 crumb_value = tvb_get_bits64(tvb,
7578 bit_offset + crumb_spec[i].crumb_bit_offset,
7579 crumb_spec[i].crumb_bit_length,
7581 value += crumb_value;
7582 no_of_bits += crumb_spec[i].crumb_bit_length;
7584 /* The bitmask is 64 bit, left-aligned, starting at the first bit of the
7585 octet containing the initial offset.
7586 If the mask is beyond 32 bits, then give up on bit map display.
7587 This could be improved in future, probably showing a table
7588 of 32 or 64 bits per row */
7589 if (mask_greatest_bit_offset < 32) {
7590 crumb_end_bit_offset = mask_initial_bit_offset
7591 + crumb_spec[i].crumb_bit_offset
7592 + crumb_spec[i].crumb_bit_length;
7593 crumb_mask = (G_GUINT64_CONSTANT(1) << crumb_spec[i].crumb_bit_length) - 1;
7595 if (crumb_end_bit_offset > mask_greatest_bit_offset) {
7596 mask_greatest_bit_offset = crumb_end_bit_offset;
7598 composite_bitmask |= (crumb_mask << (64 - crumb_end_bit_offset));
7599 composite_bitmap |= (crumb_value << (64 - crumb_end_bit_offset));
7601 /* Shift left for the next segment */
7602 value <<= crumb_spec[++i].crumb_bit_length;
7605 /* Sign extend for signed types */
7606 switch (hf_field->type) {
7612 if (value & no_of_bits && (G_GINT64_CONSTANT(1) << (no_of_bits-1)))
7613 value |= (G_GINT64_CONSTANT(-1) << no_of_bits);
7620 *return_value = value;
7623 /* Coast clear. Try and fake it */
7624 TRY_TO_FAKE_THIS_ITEM(tree, hf_index, hf_field);
7626 /* initialise the format string */
7627 bf_str = ep_alloc(256);
7630 octet_offset = bit_offset >> 3;
7632 /* Round up mask length to nearest octet */
7633 octet_length = ((mask_greatest_bit_offset + 7) >> 3);
7634 mask_greatest_bit_offset = octet_length << 3;
7636 /* As noted above, we currently only produce a bitmap if the crumbs span less than 4 octets of the tvb.
7637 It would be a useful enhancement to eliminate this restriction. */
7638 if (mask_greatest_bit_offset <= 32) {
7639 other_decode_bitfield_value(bf_str,
7640 (guint32)(composite_bitmap >> (64 - mask_greatest_bit_offset)),
7641 (guint32)(composite_bitmask >> (64 - mask_greatest_bit_offset)),
7642 mask_greatest_bit_offset);
7645 switch (hf_field->type) {
7646 case FT_BOOLEAN: /* it is a bit odd to have a boolean encoded as split-bits, but possible, I suppose? */
7648 tfstring = (const true_false_string *) &tfs_true_false;
7649 if (hf_field->strings)
7650 tfstring = (const true_false_string *) hf_field->strings;
7651 return proto_tree_add_boolean_format(tree, hf_index,
7652 tvb, octet_offset, octet_length, (guint32)value,
7654 bf_str, hf_field->name,
7655 (guint32)value ? tfstring->true_string : tfstring->false_string);
7662 pi = proto_tree_add_uint(tree, hf_index, tvb, octet_offset, octet_length, (guint32)value);
7663 fill_label_uint(PITEM_FINFO(pi), lbl_str);
7670 pi = proto_tree_add_int(tree, hf_index, tvb, octet_offset, octet_length, (gint32)value);
7671 fill_label_int(PITEM_FINFO(pi), lbl_str);
7675 pi = proto_tree_add_uint64(tree, hf_index, tvb, octet_offset, octet_length, value);
7676 fill_label_uint64(PITEM_FINFO(pi), lbl_str);
7680 pi = proto_tree_add_int64(tree, hf_index, tvb, octet_offset, octet_length, (gint64)value);
7681 fill_label_int64(PITEM_FINFO(pi), lbl_str);
7685 DISSECTOR_ASSERT_NOT_REACHED();
7689 proto_item_set_text(pi, "%s = %s", bf_str, lbl_str);
7694 proto_tree_add_split_bits_crumb(proto_tree *tree, const int hf_index, tvbuff_t *tvb, const guint bit_offset,
7695 const crumb_spec_t *crumb_spec, guint16 crumb_index)
7697 header_field_info *hf_info;
7699 PROTO_REGISTRAR_GET_NTH(hf_index, hf_info);
7700 proto_tree_add_text(tree, tvb,
7702 ((bit_offset + crumb_spec[crumb_index].crumb_bit_length - 1) >> 3) - (bit_offset >> 3) + 1,
7703 "%s crumb %d of %s (decoded above)",
7704 decode_bits_in_field(bit_offset, crumb_spec[crumb_index].crumb_bit_length,
7707 crumb_spec[crumb_index].crumb_bit_length,
7714 proto_tree_add_bits_ret_val(proto_tree *tree, const int hf_index, tvbuff_t *tvb,
7715 const guint bit_offset, const gint no_of_bits,
7716 guint64 *return_value, const guint encoding)
7720 if ((item = _proto_tree_add_bits_ret_val(tree, hf_index, tvb,
7721 bit_offset, no_of_bits,
7722 return_value, encoding))) {
7723 FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_OFFSET(bit_offset));
7724 FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_SIZE(no_of_bits));
7730 _proto_tree_add_bits_format_value(proto_tree *tree, const int hf_index,
7731 tvbuff_t *tvb, const guint bit_offset,
7732 const gint no_of_bits, void *value_ptr,
7740 header_field_info *hf_field;
7742 /* We do not have to return a value, try to fake it as soon as possible */
7743 TRY_TO_FAKE_THIS_ITEM(tree, hf_index, hf_field);
7745 if (hf_field->bitmask != 0) {
7746 REPORT_DISSECTOR_BUG(ep_strdup_printf(
7747 "Incompatible use of proto_tree_add_bits_format_value"
7748 " with field '%s' (%s) with bitmask != 0",
7749 hf_field->abbrev, hf_field->name));
7752 DISSECTOR_ASSERT(no_of_bits > 0);
7754 /* Byte align offset */
7755 offset = bit_offset>>3;
7758 * Calculate the number of octets used to hold the bits
7760 tot_no_bits = ((bit_offset&0x7) + no_of_bits);
7761 length = tot_no_bits>>3;
7762 /* If we are using part of the next octet, increase length by 1 */
7763 if (tot_no_bits & 0x07)
7766 if (no_of_bits < 65) {
7767 value = tvb_get_bits64(tvb, bit_offset, no_of_bits, ENC_BIG_ENDIAN);
7769 DISSECTOR_ASSERT_NOT_REACHED();
7773 str = decode_bits_in_field(bit_offset, no_of_bits, value);
7776 strcat(str, hf_field->name);
7779 * This function does not receive an actual value but a dimensionless pointer to that value.
7780 * For this reason, the type of the header field is examined in order to determine
7781 * what kind of value we should read from this address.
7782 * The caller of this function must make sure that for the specific header field type the address of
7783 * a compatible value is provided.
7785 switch (hf_field->type) {
7787 return proto_tree_add_boolean_format(tree, hf_index, tvb, offset, length, *(guint32 *)value_ptr,
7788 "%s: %s", str, value_str);
7795 return proto_tree_add_uint_format(tree, hf_index, tvb, offset, length, *(guint32 *)value_ptr,
7796 "%s: %s", str, value_str);
7800 return proto_tree_add_uint64_format(tree, hf_index, tvb, offset, length, *(guint64 *)value_ptr,
7801 "%s: %s", str, value_str);
7808 return proto_tree_add_int_format(tree, hf_index, tvb, offset, length, *(gint32 *)value_ptr,
7809 "%s: %s", str, value_str);
7813 return proto_tree_add_int64_format(tree, hf_index, tvb, offset, length, *(gint64 *)value_ptr,
7814 "%s: %s", str, value_str);
7818 return proto_tree_add_float_format(tree, hf_index, tvb, offset, length, *(float *)value_ptr,
7819 "%s: %s", str, value_str);
7823 DISSECTOR_ASSERT_NOT_REACHED();
7830 proto_tree_add_bits_format_value(proto_tree *tree, const int hf_index,
7831 tvbuff_t *tvb, const guint bit_offset,
7832 const gint no_of_bits, void *value_ptr,
7837 if ((item = _proto_tree_add_bits_format_value(tree, hf_index,
7838 tvb, bit_offset, no_of_bits,
7839 value_ptr, value_str))) {
7840 FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_OFFSET(bit_offset));
7841 FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_SIZE(no_of_bits));
7846 #define CREATE_VALUE_STRING(dst,format,ap) \
7847 va_start(ap, format); \
7848 dst = ep_strdup_vprintf(format, ap); \
7852 proto_tree_add_uint_bits_format_value(proto_tree *tree, const int hf_index,
7853 tvbuff_t *tvb, const guint bit_offset,
7854 const gint no_of_bits, guint32 value,
7855 const char *format, ...)
7859 header_field_info *hf_field;
7861 TRY_TO_FAKE_THIS_ITEM(tree, hf_index, hf_field);
7863 switch (hf_field->type) {
7871 DISSECTOR_ASSERT_NOT_REACHED();
7876 CREATE_VALUE_STRING(dst, format, ap);
7878 return proto_tree_add_bits_format_value(tree, hf_index, tvb, bit_offset, no_of_bits, &value, dst);
7882 proto_tree_add_float_bits_format_value(proto_tree *tree, const int hf_index,
7883 tvbuff_t *tvb, const guint bit_offset,
7884 const gint no_of_bits, float value,
7885 const char *format, ...)
7889 header_field_info *hf_field;
7891 TRY_TO_FAKE_THIS_ITEM(tree, hf_index, hf_field);
7893 DISSECTOR_ASSERT(hf_field->type == FT_FLOAT);
7895 CREATE_VALUE_STRING(dst, format, ap);
7897 return proto_tree_add_bits_format_value(tree, hf_index, tvb, bit_offset, no_of_bits, &value, dst);
7901 proto_tree_add_int_bits_format_value(proto_tree *tree, const int hf_index,
7902 tvbuff_t *tvb, const guint bit_offset,
7903 const gint no_of_bits, gint32 value,
7904 const char *format, ...)
7908 header_field_info *hf_field;
7910 TRY_TO_FAKE_THIS_ITEM(tree, hf_index, hf_field);
7912 switch (hf_field->type) {
7920 DISSECTOR_ASSERT_NOT_REACHED();
7925 CREATE_VALUE_STRING(dst, format, ap);
7927 return proto_tree_add_bits_format_value(tree, hf_index, tvb, bit_offset, no_of_bits, &value, dst);
7931 proto_tree_add_boolean_bits_format_value(proto_tree *tree, const int hf_index,
7932 tvbuff_t *tvb, const guint bit_offset,
7933 const gint no_of_bits, guint32 value,
7934 const char *format, ...)
7938 header_field_info *hf_field;
7940 TRY_TO_FAKE_THIS_ITEM(tree, hf_index, hf_field);
7942 DISSECTOR_ASSERT(hf_field->type == FT_BOOLEAN);
7944 CREATE_VALUE_STRING(dst, format, ap);
7946 return proto_tree_add_bits_format_value(tree, hf_index, tvb, bit_offset, no_of_bits, &value, dst);
7950 proto_check_field_name(const gchar *field_name)
7952 return wrs_check_charset(fld_abbrev_chars, field_name);