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.
36 #include "ptvcursor.h"
38 #include "addr_resolv.h"
42 #include "epan_dissect.h"
47 #include "asm_utils.h"
48 #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(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 \
95 field items below this node ( think proto_item_add_subtree() )\
96 will still have somewhere to attach to \
97 or else filtering will not work (they would be ignored since tree\
99 We fake FT_PROTOCOL unless some clients have requested us \
104 PTREE_DATA(tree)->count++; \
105 if (PTREE_DATA(tree)->count > MAX_TREE_ITEMS) { \
106 /* Let the exception handler add items to the tree */ \
107 PTREE_DATA(tree)->count = 0; \
108 THROW_MESSAGE(DissectorError, \
109 ep_strdup_printf("More than %d items in the tree -- possible infinite loop", MAX_TREE_ITEMS)); \
111 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo); \
112 if(!(PTREE_DATA(tree)->visible)){ \
113 if((hfinfo->ref_type != HF_REF_TYPE_DIRECT) \
114 && (hfinfo->type!=FT_PROTOCOL || \
115 PTREE_DATA(tree)->fake_protocols)){ \
116 /* just return tree back to the caller */\
121 /** See inlined comments.
122 @param tree the tree to append this item to
123 @param pi the created protocol item we're about to return */
125 #define TRY_TO_FAKE_THIS_REPR(tree, pi) \
126 DISSECTOR_ASSERT(tree); \
127 if(!(PTREE_DATA(tree)->visible)) { \
128 /* If the tree (GUI) isn't visible it's pointless for us to generate the protocol \
129 * items string representation */ \
133 #define TRY_TO_FAKE_THIS_REPR(tree, pi)
137 proto_tree_free_node(proto_node *node, gpointer data);
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(header_field_info *hfinfo);
147 static const char* hfinfo_uint_format(header_field_info *hfinfo);
148 static const char* hfinfo_uint_value_format(header_field_info *hfinfo);
149 static const char* hfinfo_uint64_format(header_field_info *hfinfo);
150 static const char* hfinfo_int_vals_format(header_field_info *hfinfo);
151 static const char* hfinfo_int_format(header_field_info *hfinfo);
152 static const char* hfinfo_int_value_format(header_field_info *hfinfo);
153 static const char* hfinfo_int64_format(header_field_info *hfinfo);
156 proto_tree_add_node(proto_tree *tree, field_info *fi);
158 static header_field_info *
159 get_hfi_and_length(int hfindex, tvbuff_t *tvb, gint start, gint *length,
163 new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
164 gint start, gint item_length);
167 alloc_field_info(proto_tree *tree, int hfindex, tvbuff_t *tvb,
168 gint start, gint *length);
171 proto_tree_add_pi(proto_tree *tree, int hfindex, tvbuff_t *tvb,
172 gint start, gint *length, field_info **pfi);
175 proto_tree_set_representation_value(proto_item *pi, const char *format, va_list ap);
177 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap);
180 proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb);
182 proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length);
184 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length);
186 proto_tree_set_time(field_info *fi, nstime_t *value_ptr);
188 proto_tree_set_string(field_info *fi, const char* value);
190 proto_tree_set_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
192 proto_tree_set_ebcdic_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
194 proto_tree_set_ether(field_info *fi, const guint8* value);
196 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start);
198 proto_tree_set_ipxnet(field_info *fi, guint32 value);
200 proto_tree_set_ipv4(field_info *fi, guint32 value);
202 proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr);
204 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
206 proto_tree_set_guid(field_info *fi, const e_guid_t *value_ptr);
208 proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gboolean little_endian);
210 proto_tree_set_oid(field_info *fi, const guint8* value_ptr, gint length);
212 proto_tree_set_oid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
214 proto_tree_set_boolean(field_info *fi, guint32 value);
216 proto_tree_set_float(field_info *fi, float value);
218 proto_tree_set_double(field_info *fi, double value);
220 proto_tree_set_uint(field_info *fi, guint32 value);
222 proto_tree_set_int(field_info *fi, gint32 value);
224 proto_tree_set_uint64(field_info *fi, guint64 value);
226 proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start, guint length, gboolean little_endian);
228 proto_item_add_bitmask_tree(proto_item *item, tvbuff_t *tvb, int offset, int len, gint ett,
229 const gint **fields, gboolean little_endian, int flags, gboolean first);
231 static int proto_register_field_init(header_field_info *hfinfo, int parent);
233 /* special-case header field used within proto.c */
234 int hf_text_only = -1;
236 /* Structure for information about a protocol */
238 const char *name; /* long description */
239 const char *short_name; /* short description */
240 const char *filter_name; /* name of this protocol in filters */
241 int proto_id; /* field ID for this protocol */
242 GList *fields; /* fields for this protocol */
243 GList *last_field; /* pointer to end of list of fields */
244 gboolean is_enabled; /* TRUE if protocol is enabled */
245 gboolean can_toggle; /* TRUE if is_enabled can be changed */
246 gboolean is_private; /* TRUE is protocol is private */
249 /* List of all protocols */
250 static GList *protocols = NULL;
252 #define INITIAL_NUM_PROTOCOL_HFINFO 1500
254 /* Contains information about protocols and header fields. Used when
255 * dissectors register their data */
256 #if GLIB_CHECK_VERSION(2,10,0)
258 static GMemChunk *gmc_hfinfo = NULL;
261 /* Contains information about a field when a dissector calls
262 * proto_tree_add_item. */
263 SLAB_ITEM_TYPE_DEFINE(field_info)
264 static SLAB_FREE_LIST_DEFINE(field_info)
265 static field_info *field_info_tmp=NULL;
266 #define FIELD_INFO_NEW(fi) \
267 SLAB_ALLOC(fi, field_info)
268 #define FIELD_INFO_FREE(fi) \
269 SLAB_FREE(fi, field_info)
271 /* Contains the space for proto_nodes. */
272 SLAB_ITEM_TYPE_DEFINE(proto_node)
273 static SLAB_FREE_LIST_DEFINE(proto_node)
274 #define PROTO_NODE_NEW(node) \
275 SLAB_ALLOC(node, proto_node) \
276 node->first_child = NULL; \
277 node->last_child = NULL; \
280 #define PROTO_NODE_FREE(node) \
281 SLAB_FREE(node, proto_node)
283 /* String space for protocol and field items for the GUI */
284 SLAB_ITEM_TYPE_DEFINE(item_label_t)
285 static SLAB_FREE_LIST_DEFINE(item_label_t)
286 #define ITEM_LABEL_NEW(il) \
287 SLAB_ALLOC(il, item_label_t)
288 #define ITEM_LABEL_FREE(il) \
289 SLAB_FREE(il, item_label_t)
291 #define PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo) \
292 DISSECTOR_ASSERT((guint)hfindex < gpa_hfinfo.len); \
293 hfinfo=gpa_hfinfo.hfi[hfindex];
295 /* List which stores protocols and fields that have been registered */
296 typedef struct _gpa_hfinfo_t {
298 guint32 allocated_len;
299 header_field_info **hfi;
301 gpa_hfinfo_t gpa_hfinfo;
303 /* Balanced tree of abbreviations and IDs */
304 static GTree *gpa_name_tree = NULL;
305 static header_field_info *same_name_hfinfo;
307 static void save_same_name_hfinfo(gpointer data)
309 same_name_hfinfo = (header_field_info*)data;
312 /* Points to the first element of an array of Booleans, indexed by
313 a subtree item type; that array element is TRUE if subtrees of
314 an item of that type are to be expanded. */
315 gboolean *tree_is_expanded;
317 /* Number of elements in that array. */
320 /* Name hashtables for fast detection of duplicate names */
321 static GHashTable* proto_names = NULL;
322 static GHashTable* proto_short_names = NULL;
323 static GHashTable* proto_filter_names = NULL;
326 proto_compare_name(gconstpointer p1_arg, gconstpointer p2_arg)
328 const protocol_t *p1 = p1_arg;
329 const protocol_t *p2 = p2_arg;
331 return g_ascii_strcasecmp(p1->short_name, p2->short_name);
335 /* initialize data structures and register protocols and fields */
337 proto_init(void (register_all_protocols_func)(register_cb cb, gpointer client_data),
338 void (register_all_handoffs_func)(register_cb cb, gpointer client_data),
340 gpointer client_data)
342 static hf_register_info hf[] = {
344 { "Text item", "text", FT_NONE, BASE_NONE, NULL, 0x0,
350 proto_names = g_hash_table_new_full(g_int_hash, g_int_equal, g_free, NULL);
351 proto_short_names = g_hash_table_new(wrs_str_hash, g_str_equal);
352 proto_filter_names = g_hash_table_new(wrs_str_hash, g_str_equal);
354 #if GLIB_CHECK_VERSION(2,10,0)
356 gmc_hfinfo = g_mem_chunk_new("gmc_hfinfo",
357 sizeof(header_field_info),
358 INITIAL_NUM_PROTOCOL_HFINFO * sizeof(header_field_info),
363 gpa_hfinfo.allocated_len=0;
365 gpa_name_tree = g_tree_new_full(wrs_strcmp_with_data, NULL, NULL, save_same_name_hfinfo);
367 /* Initialize the ftype subsystem */
370 /* Register one special-case FT_TEXT_ONLY field for use when
371 converting wireshark to new-style proto_tree. These fields
372 are merely strings on the GUI tree; they are not filterable */
373 proto_register_field_array(-1, hf, array_length(hf));
375 /* Have each built-in dissector register its protocols, fields,
376 dissector tables, and dissectors to be called through a
377 handle, and do whatever one-time initialization it needs to
379 register_all_protocols_func(cb, client_data);
381 /* Now scan for python protocols */
382 register_all_py_protocols_func(cb, client_data);
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 */
402 register_all_py_handoffs_func(cb, client_data);
406 /* Now do the same with plugins. */
408 (*cb)(RA_PLUGIN_HANDOFF, NULL, client_data);
409 register_all_plugin_handoffs();
412 /* sort the protocols by protocol name */
413 protocols = g_list_sort(protocols, proto_compare_name);
415 /* We've assigned all the subtree type values; allocate the array
416 for them, and zero it out. */
417 tree_is_expanded = g_new0(gboolean, num_tree_types);
423 /* Free the abbrev/ID GTree */
425 g_tree_destroy(gpa_name_tree);
426 gpa_name_tree = NULL;
430 protocol_t *protocol = protocols->data;
431 header_field_info *hfinfo;
432 PROTO_REGISTRAR_GET_NTH(protocol->proto_id, hfinfo);
433 DISSECTOR_ASSERT(protocol->proto_id == hfinfo->id);
435 #if GLIB_CHECK_VERSION(2,10,0)
436 g_slice_free(header_field_info, hfinfo);
438 g_mem_chunk_free(gmc_hfinfo, hfinfo);
441 g_list_free(protocol->fields);
442 protocols = g_list_remove(protocols, protocol);
447 g_hash_table_destroy(proto_names);
451 if (proto_short_names) {
452 g_hash_table_destroy(proto_short_names);
453 proto_short_names = NULL;
456 if (proto_filter_names) {
457 g_hash_table_destroy(proto_filter_names);
458 proto_filter_names = NULL;
461 #if GLIB_CHECK_VERSION(2,10,0)
464 g_mem_chunk_destroy(gmc_hfinfo);
469 if(gpa_hfinfo.allocated_len){
471 gpa_hfinfo.allocated_len=0;
472 g_free(gpa_hfinfo.hfi);
475 g_free(tree_is_expanded);
476 tree_is_expanded = NULL;
480 proto_tree_traverse_pre_order(proto_tree *tree, proto_tree_traverse_func func,
483 proto_node *pnode = tree;
487 if (func(pnode, data))
490 child = pnode->first_child;
491 while (child != NULL) {
493 * The routine we call might modify the child, e.g. by
494 * freeing it, so we get the child's successor before
495 * calling that routine.
498 child = current->next;
499 if (proto_tree_traverse_pre_order((proto_tree *)current, func,
508 proto_tree_traverse_post_order(proto_tree *tree, proto_tree_traverse_func func,
511 proto_node *pnode = tree;
515 child = pnode->first_child;
516 while (child != NULL) {
518 * The routine we call might modify the child, e.g. by
519 * freeing it, so we get the child's successor before
520 * calling that routine.
523 child = current->next;
524 if (proto_tree_traverse_post_order((proto_tree *)current, func,
528 if (func(pnode, data))
535 proto_tree_children_foreach(proto_tree *tree, proto_tree_foreach_func func,
538 proto_node *node = tree;
541 node = node->first_child;
542 while (node != NULL) {
544 node = current->next;
545 func((proto_tree *)current, data);
549 /* frees the resources that the dissection a proto_tree uses */
551 proto_tree_free(proto_tree *tree)
553 proto_tree_traverse_post_order(tree, proto_tree_free_node, NULL);
557 free_GPtrArray_value(gpointer key, gpointer value, gpointer user_data _U_)
559 GPtrArray *ptrs = value;
560 gint hfid = (gint)(long)key;
561 header_field_info *hfinfo;
563 PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
564 if(hfinfo->ref_type != HF_REF_TYPE_NONE) {
565 /* when a field is referenced by a filter this also
566 affects the refcount for the parent protocol so we need
567 to adjust the refcount for the parent as well
569 if( hfinfo->parent != -1 ) {
570 header_field_info *parent_hfinfo;
571 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
572 parent_hfinfo->ref_type = HF_REF_TYPE_NONE;
574 hfinfo->ref_type = HF_REF_TYPE_NONE;
577 g_ptr_array_free(ptrs, TRUE);
581 free_node_tree_data(tree_data_t *tree_data)
583 if (tree_data->interesting_hfids) {
584 /* Free all the GPtrArray's in the interesting_hfids hash. */
585 g_hash_table_foreach(tree_data->interesting_hfids,
586 free_GPtrArray_value, NULL);
588 /* And then destroy the hash. */
589 g_hash_table_destroy(tree_data->interesting_hfids);
592 /* And finally the tree_data_t itself. */
596 #define FREE_NODE_FIELD_INFO(finfo) \
598 ITEM_LABEL_FREE(finfo->rep); \
600 FVALUE_CLEANUP(&finfo->value); \
601 FIELD_INFO_FREE(finfo);
604 proto_tree_free_node(proto_node *node, gpointer data _U_)
606 field_info *finfo = PNODE_FINFO(node);
608 proto_node *parent = node->parent;
612 /* This is the root node. Destroy the per-tree data.
613 * There is no field_info to destroy. */
614 if (PTREE_DATA(node)) free_node_tree_data(PTREE_DATA(node));
617 /* This is a child node. Don't free the per-tree data, but
618 * do free the field_info data. */
619 FREE_NODE_FIELD_INFO(finfo);
623 /* NOTE: This code is required when this function is used to free individual
624 * nodes only. Current use is for the destruction of complete trees, so the
625 * inconsistancies have no ill effect.
627 /* Remove node from parent */
629 proto_item *prev_item = NULL;
630 if (parent->first_child == node) {
631 parent->first_child = node->next;
633 /* find previous and change its next */
634 for (prev_item = parent->first_child; prev_item; prev_item = prev_item->next) {
635 if (prev_item->next == node) {
639 DISSECTOR_ASSERT(prev_item);
640 prev_item->next = node->next;
642 /* fix last_child if required */
643 if (parent->last_child == node) {
644 parent->last_child = prev_item;
647 DISSECTOR_ASSERT(node->first_child == NULL && node->last_child == NULL);
649 /* Free the proto_node. */
650 PROTO_NODE_FREE(node);
652 return FALSE; /* FALSE = do not end traversal of protocol tree */
655 /* Is the parsing being done for a visible proto_tree or an invisible one?
656 * By setting this correctly, the proto_tree creation is sped up by not
657 * having to call g_vsnprintf and copy strings around.
660 proto_tree_set_visible(proto_tree *tree, gboolean visible)
662 gboolean old_visible = PTREE_DATA(tree)->visible;
664 PTREE_DATA(tree)->visible = visible;
670 proto_tree_set_fake_protocols(proto_tree *tree, gboolean fake_protocols)
672 PTREE_DATA(tree)->fake_protocols = fake_protocols;
675 /* Assume dissector set only its protocol fields.
676 This function is called by dissectors and allows the speeding up of filtering
677 in wireshark; if this function returns FALSE it is safe to reset tree to NULL
678 and thus skip calling most of the expensive proto_tree_add_...()
680 If the tree is visible we implicitly assume the field is referenced.
683 proto_field_is_referenced(proto_tree *tree, int proto_id)
685 register header_field_info *hfinfo;
691 if (PTREE_DATA(tree)->visible)
694 PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
695 if (hfinfo->ref_type != HF_REF_TYPE_NONE)
698 if (hfinfo->type == FT_PROTOCOL && !PTREE_DATA(tree)->fake_protocols)
705 /* Finds a record in the hf_info_records array by id. */
707 proto_registrar_get_nth(guint hfindex)
709 register header_field_info *hfinfo;
711 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
716 /* Prefix initialization
717 * this allows for a dissector to register a display filter name prefix
718 * so that it can delay the initialization of the hf array as long as
722 /* compute a hash for the part before the dot of a display filter */
724 prefix_hash (gconstpointer key) {
725 /* end the string at the dot and compute its hash */
726 gchar* copy = ep_strdup(key);
736 return g_str_hash(copy);
739 /* are both strings equal up to the end or the dot? */
741 prefix_equal (gconstpointer ap,gconstpointer bp) {
749 if ((ac == '.' || ac == '\0') && (bc == '.' || bc == '\0')) return TRUE;
751 if ( (ac == '.' || ac == '\0') && ! (bc == '.' || bc == '\0') ) return FALSE;
752 if ( (bc == '.' || bc == '\0') && ! (ac == '.' || ac == '\0') ) return FALSE;
754 if (ac != bc) return FALSE;
761 /* indexed by prefix, contains initializers */
762 static GHashTable* prefixes = NULL;
765 /* Register a new prefix for "delayed" initialization of field arrays */
767 proto_register_prefix(const char *prefix, prefix_initializer_t pi ) {
769 prefixes = g_hash_table_new(prefix_hash,prefix_equal);
772 g_hash_table_insert(prefixes,(gpointer)prefix,pi);
775 /* helper to call all prefix initializers */
777 initialize_prefix(gpointer k, gpointer v, gpointer u _U_) {
778 ((prefix_initializer_t)v)(k);
782 /** Initialize every remaining uninitialized prefix. */
784 proto_initialize_all_prefixes(void) {
785 g_hash_table_foreach_remove(prefixes, initialize_prefix, NULL);
788 /* Finds a record in the hf_info_records array by name.
789 * If it fails to find it in the already registered fields,
790 * it tries to find and call an initializer in the prefixes
791 * table and if so it looks again.
794 proto_registrar_get_byname(const char *field_name)
796 header_field_info* hfinfo;
797 prefix_initializer_t pi;
802 hfinfo = g_tree_lookup(gpa_name_tree, field_name);
804 if (hfinfo) return hfinfo;
806 if (!prefixes) return NULL;
808 if(( pi = g_hash_table_lookup(prefixes,field_name) )) {
810 g_hash_table_remove(prefixes,field_name);
815 return g_tree_lookup(gpa_name_tree, field_name);
820 ptvcursor_new_subtree_levels(ptvcursor_t * ptvc)
822 subtree_lvl * pushed_tree;
824 DISSECTOR_ASSERT(ptvc->pushed_tree_max <= SUBTREE_MAX_LEVELS-SUBTREE_ONCE_ALLOCATION_NUMBER);
825 ptvc->pushed_tree_max += SUBTREE_ONCE_ALLOCATION_NUMBER;
827 pushed_tree = ep_alloc(sizeof(subtree_lvl) * ptvc->pushed_tree_max);
828 DISSECTOR_ASSERT(pushed_tree != NULL);
829 if (ptvc->pushed_tree)
830 memcpy(pushed_tree, ptvc->pushed_tree, ptvc->pushed_tree_max - SUBTREE_ONCE_ALLOCATION_NUMBER);
831 ptvc->pushed_tree = pushed_tree;
835 ptvcursor_free_subtree_levels(ptvcursor_t * ptvc)
837 ptvc->pushed_tree = NULL;
838 ptvc->pushed_tree_max = 0;
839 DISSECTOR_ASSERT(ptvc->pushed_tree_index ==0);
840 ptvc->pushed_tree_index = 0;
843 /* Allocates an initializes a ptvcursor_t with 3 variables:
844 * proto_tree, tvbuff, and offset. */
846 ptvcursor_new(proto_tree *tree, tvbuff_t *tvb, gint offset)
850 ptvc = ep_alloc(sizeof(ptvcursor_t));
853 ptvc->offset = offset;
854 ptvc->pushed_tree= NULL;
855 ptvc->pushed_tree_max= 0;
856 ptvc->pushed_tree_index= 0;
861 /* Frees memory for ptvcursor_t, but nothing deeper than that. */
863 ptvcursor_free(ptvcursor_t *ptvc)
865 ptvcursor_free_subtree_levels(ptvc);
869 /* Returns tvbuff. */
871 ptvcursor_tvbuff(ptvcursor_t* ptvc)
876 /* Returns current offset. */
878 ptvcursor_current_offset(ptvcursor_t* ptvc)
884 ptvcursor_tree(ptvcursor_t* ptvc)
893 ptvcursor_set_tree(ptvcursor_t* ptvc, proto_tree *tree)
898 /* creates a subtree, sets it as the working tree and pushes the old working tree */
900 ptvcursor_push_subtree(ptvcursor_t *ptvc, proto_item *it, gint ett_subtree)
902 subtree_lvl * subtree;
903 if (ptvc->pushed_tree_index >= ptvc->pushed_tree_max)
904 ptvcursor_new_subtree_levels(ptvc);
906 subtree = ptvc->pushed_tree+ptvc->pushed_tree_index;
907 subtree->tree = ptvc->tree;
909 ptvc->pushed_tree_index++;
910 return ptvcursor_set_subtree(ptvc, it, ett_subtree);
915 ptvcursor_pop_subtree(ptvcursor_t *ptvc)
917 subtree_lvl * subtree;
918 if (ptvc->pushed_tree_index <= 0)
921 ptvc->pushed_tree_index--;
922 subtree = ptvc->pushed_tree+ptvc->pushed_tree_index;
923 if (subtree->it != NULL)
924 proto_item_set_len(subtree->it, ptvcursor_current_offset(ptvc) - subtree->cursor_offset);
926 ptvc->tree = subtree->tree;
929 /* saves the current tvb offset and the item in the current subtree level */
931 ptvcursor_subtree_set_item(ptvcursor_t * ptvc, proto_item * it)
933 subtree_lvl * subtree;
935 DISSECTOR_ASSERT(ptvc->pushed_tree_index > 0);
937 subtree = ptvc->pushed_tree+ptvc->pushed_tree_index-1;
939 subtree->cursor_offset = ptvcursor_current_offset(ptvc);
942 /* Creates a subtree and adds it to the cursor as the working tree but does not
943 * save the old working tree */
945 ptvcursor_set_subtree(ptvcursor_t *ptvc, proto_item *it, gint ett_subtree)
947 ptvc->tree = proto_item_add_subtree(it, ett_subtree);
952 ptvcursor_add_subtree_item(ptvcursor_t * ptvc, proto_item * it, gint ett_subtree, gint length)
954 ptvcursor_push_subtree(ptvc, it, ett_subtree);
955 if (length == SUBTREE_UNDEFINED_LENGTH)
956 ptvcursor_subtree_set_item(ptvc, it);
957 return ptvcursor_tree(ptvc);
960 /* Add an item to the tree and create a subtree
961 * If the length is unknown, length may be defined as SUBTREE_UNDEFINED_LENGTH.
962 * In this case, when the subtree will be closed, the parent item length will
963 * be equal to the advancement of the cursor since the creation of the subtree.
966 ptvcursor_add_with_subtree(ptvcursor_t * ptvc, int hfindex, gint length,
967 gboolean little_endian, gint ett_subtree)
971 it = ptvcursor_add_no_advance(ptvc, hfindex, length, little_endian);
972 return ptvcursor_add_subtree_item(ptvc, it, ett_subtree, length);
976 proto_tree_add_text_node(proto_tree *tree, tvbuff_t *tvb, gint start, gint length);
978 /* Add a text node to the tree and create a subtree
979 * If the length is unknown, length may be defined as SUBTREE_UNDEFINED_LENGTH.
980 * In this case, when the subtree will be closed, the item length will be equal
981 * to the advancement of the cursor since the creation of the subtree.
984 ptvcursor_add_text_with_subtree(ptvcursor_t * ptvc, gint length,
985 gint ett_subtree, const char *format, ...)
989 header_field_info *hfinfo;
991 TRY_TO_FAKE_THIS_ITEM(ptvcursor_tree(ptvc), hf_text_only, hfinfo);
993 it = proto_tree_add_text_node(ptvcursor_tree(ptvc), ptvcursor_tvbuff(ptvc),
994 ptvcursor_current_offset(ptvc), length);
999 va_start(ap, format);
1000 proto_tree_set_representation(it, format, ap);
1003 return ptvcursor_add_subtree_item(ptvc, it, ett_subtree, length);
1006 /* Add a text-only node, leaving it to our caller to fill the text in */
1008 proto_tree_add_text_node(proto_tree *tree, tvbuff_t *tvb, gint start, gint length)
1012 pi = proto_tree_add_pi(tree, hf_text_only, tvb, start, &length, NULL);
1019 /* Add a text-only node to the proto_tree */
1021 proto_tree_add_text(proto_tree *tree, tvbuff_t *tvb, gint start, gint length,
1022 const char *format, ...)
1026 header_field_info *hfinfo;
1028 TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
1030 pi = proto_tree_add_text_node(tree, tvb, start, length);
1034 TRY_TO_FAKE_THIS_REPR(tree, pi);
1036 va_start(ap, format);
1037 proto_tree_set_representation(pi, format, ap);
1043 /* Add a text-only node to the proto_tree (va_list version) */
1045 proto_tree_add_text_valist(proto_tree *tree, tvbuff_t *tvb, gint start,
1046 gint length, const char *format, va_list ap)
1049 header_field_info *hfinfo;
1051 TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
1053 pi = proto_tree_add_text_node(tree, tvb, start, length);
1057 TRY_TO_FAKE_THIS_REPR(tree, pi);
1059 proto_tree_set_representation(pi, format, ap);
1064 /* Add a text-only node for debugging purposes. The caller doesn't need
1065 * to worry about tvbuff, start, or length. Debug message gets sent to
1068 proto_tree_add_debug_text(proto_tree *tree, const char *format, ...)
1073 pi = proto_tree_add_text_node(tree, NULL, 0, 0);
1075 va_start(ap, format);
1077 proto_tree_set_representation(pi, format, ap);
1078 vprintf(format, ap);
1087 get_uint_value(tvbuff_t *tvb, gint offset, gint length, gboolean little_endian)
1094 value = tvb_get_guint8(tvb, offset);
1098 value = little_endian ? tvb_get_letohs(tvb, offset)
1099 : tvb_get_ntohs(tvb, offset);
1103 value = little_endian ? tvb_get_letoh24(tvb, offset)
1104 : tvb_get_ntoh24(tvb, offset);
1108 value = little_endian ? tvb_get_letohl(tvb, offset)
1109 : tvb_get_ntohl(tvb, offset);
1113 DISSECTOR_ASSERT_NOT_REACHED();
1121 get_int_value(tvbuff_t *tvb, gint offset, gint length, gboolean little_endian)
1128 value = (gint8)tvb_get_guint8(tvb, offset);
1132 value = (gint16) (little_endian ? tvb_get_letohs(tvb, offset)
1133 : tvb_get_ntohs(tvb, offset));
1137 value = little_endian ? tvb_get_letoh24(tvb, offset)
1138 : tvb_get_ntoh24(tvb, offset);
1139 if (value & 0x00800000) {
1140 /* Sign bit is set; sign-extend it. */
1141 value |= 0xFF000000;
1146 value = little_endian ? tvb_get_letohl(tvb, offset)
1147 : tvb_get_ntohl(tvb, offset);
1151 DISSECTOR_ASSERT_NOT_REACHED();
1158 static GPtrArray *proto_lookup_or_create_interesting_hfids(proto_tree *tree,
1159 header_field_info *hfinfo)
1161 GPtrArray *ptrs = NULL;
1163 DISSECTOR_ASSERT(tree);
1164 DISSECTOR_ASSERT(hfinfo);
1166 if (hfinfo->ref_type == HF_REF_TYPE_DIRECT) {
1167 if (PTREE_DATA(tree)->interesting_hfids == NULL) {
1168 /* Initialize the hash because we now know that it is needed */
1169 PTREE_DATA(tree)->interesting_hfids =
1170 g_hash_table_new(g_direct_hash, NULL /* g_direct_equal */);
1173 ptrs = g_hash_table_lookup(PTREE_DATA(tree)->interesting_hfids,
1174 GINT_TO_POINTER(hfinfo->id));
1176 /* First element triggers the creation of pointer array */
1177 ptrs = g_ptr_array_new();
1178 g_hash_table_insert(PTREE_DATA(tree)->interesting_hfids,
1179 GINT_TO_POINTER(hfinfo->id), ptrs);
1186 /* Add an item to a proto_tree, using the text label registered to that item;
1187 the item is extracted from the tvbuff handed to it. */
1189 proto_tree_new_item(field_info *new_fi, proto_tree *tree,
1190 tvbuff_t *tvb, gint start, gint length, gboolean little_endian)
1199 /* there is a possibility here that we might raise an exception
1200 * and thus would lose track of the field_info.
1201 * store it in a temp so that if we come here again we can reclaim
1202 * the field_info without leaking memory.
1204 /* XXX this only keeps track of one field_info struct,
1205 if we ever go multithreaded for calls to this function
1206 we have to change this code to use per thread variable.
1209 /* oops, last one we got must have been lost due
1211 * good thing we saved it, now we can reverse the
1212 * memory leak and reclaim it.
1214 SLAB_FREE(field_info_tmp, field_info);
1216 /* we might throw an exception, keep track of this one
1217 * across the "dangerous" section below.
1219 field_info_tmp=new_fi;
1221 switch(new_fi->hfinfo->type) {
1223 /* no value to set for FT_NONE */
1227 proto_tree_set_protocol_tvb(new_fi, tvb);
1231 proto_tree_set_bytes_tvb(new_fi, tvb, start, length);
1235 n = get_uint_value(tvb, start, length, little_endian);
1236 proto_tree_set_bytes_tvb(new_fi, tvb, start + length, n);
1238 /* Instead of calling proto_item_set_len(), since we don't yet
1239 * have a proto_item, we set the field_info's length ourselves. */
1240 new_fi->length = n + length;
1244 proto_tree_set_boolean(new_fi,
1245 get_uint_value(tvb, start, length, little_endian));
1248 /* XXX - make these just FT_UINT? */
1253 proto_tree_set_uint(new_fi,
1254 get_uint_value(tvb, start, length, little_endian));
1259 DISSECTOR_ASSERT( length <= 8 && length >= 1);
1260 proto_tree_set_uint64_tvb(new_fi, tvb, start, length, little_endian);
1263 /* XXX - make these just FT_INT? */
1268 proto_tree_set_int(new_fi,
1269 get_int_value(tvb, start, length, little_endian));
1273 DISSECTOR_ASSERT(length == FT_IPv4_LEN);
1274 value = tvb_get_ipv4(tvb, start);
1275 proto_tree_set_ipv4(new_fi, little_endian ? GUINT32_SWAP_LE_BE(value) : value);
1279 DISSECTOR_ASSERT(length == FT_IPXNET_LEN);
1280 proto_tree_set_ipxnet(new_fi,
1281 get_uint_value(tvb, start, 4, FALSE));
1285 DISSECTOR_ASSERT(length >=0 && length <= FT_IPv6_LEN);
1286 proto_tree_set_ipv6_tvb(new_fi, tvb, start, length);
1290 DISSECTOR_ASSERT(length == FT_ETHER_LEN);
1291 proto_tree_set_ether_tvb(new_fi, tvb, start);
1295 DISSECTOR_ASSERT(length == FT_GUID_LEN);
1296 proto_tree_set_guid_tvb(new_fi, tvb, start, little_endian);
1300 proto_tree_set_oid_tvb(new_fi, tvb, start, length);
1304 DISSECTOR_ASSERT(length == 4);
1306 floatval = tvb_get_letohieee_float(tvb, start);
1308 floatval = tvb_get_ntohieee_float(tvb, start);
1309 proto_tree_set_float(new_fi, floatval);
1313 DISSECTOR_ASSERT(length == 8);
1315 doubleval = tvb_get_letohieee_double(tvb, start);
1317 doubleval = tvb_get_ntohieee_double(tvb, start);
1318 proto_tree_set_double(new_fi, doubleval);
1322 proto_tree_set_string_tvb(new_fi, tvb, start, length);
1326 DISSECTOR_ASSERT(length >= -1);
1327 /* Instead of calling proto_item_set_len(),
1328 * since we don't yet have a proto_item, we
1329 * set the field_info's length ourselves.
1331 * XXX - our caller can't use that length to
1332 * advance an offset unless they arrange that
1333 * there always be a protocol tree into which
1334 * we're putting this item.
1337 /* This can throw an exception */
1338 length = tvb_strsize(tvb, start);
1340 string = ep_alloc(length);
1342 tvb_memcpy(tvb, string, start, length);
1343 } else if (length == 0) {
1346 /* In this case, length signifies
1347 * the length of the string.
1349 * This could either be a null-padded
1350 * string, which doesn't necessarily
1351 * have a '\0' at the end, or a
1352 * null-terminated string, with a
1353 * trailing '\0'. (Yes, there are
1354 * cases where you have a string
1355 * that's both counted and null-
1358 * In the first case, we must
1359 * allocate a buffer of length
1360 * "length+1", to make room for
1363 * In the second case, we don't
1364 * assume that there is a trailing
1365 * '\0' there, as the packet might
1366 * be malformed. (XXX - should we
1367 * throw an exception if there's no
1368 * trailing '\0'?) Therefore, we
1369 * allocate a buffer of length
1370 * "length+1", and put in a trailing
1371 * '\0', just to be safe.
1373 * (XXX - this would change if
1374 * we made string values counted
1375 * rather than null-terminated.)
1377 string = tvb_get_ephemeral_string(tvb,
1381 new_fi->length = length;
1382 proto_tree_set_string(new_fi, string);
1386 proto_tree_set_ebcdic_string_tvb(new_fi, tvb, start, length);
1389 case FT_UINT_STRING:
1390 n = get_uint_value(tvb, start, length, little_endian);
1391 proto_tree_set_string_tvb(new_fi, tvb, start + length, n);
1393 /* Instead of calling proto_item_set_len(), since we
1394 * don't yet have a proto_item, we set the
1395 * field_info's length ourselves.
1397 * XXX - our caller can't use that length to
1398 * advance an offset unless they arrange that
1399 * there always be a protocol tree into which
1400 * we're putting this item.
1402 new_fi->length = n + length;
1406 g_error("new_fi->hfinfo->type %d (%s) not handled\n",
1407 new_fi->hfinfo->type,
1408 ftype_name(new_fi->hfinfo->type));
1409 DISSECTOR_ASSERT_NOT_REACHED();
1413 /* Don't add new node to proto_tree until now so that any exceptions
1414 * raised by a tvbuff access method doesn't leave junk in the proto_tree. */
1415 pi = proto_tree_add_node(tree, new_fi);
1417 /* we did not raise an exception so we dont have to remember this
1418 * field_info struct any more.
1420 field_info_tmp=NULL;
1422 /* If the proto_tree wants to keep a record of this finfo
1423 * for quick lookup, then record it. */
1424 ptrs = proto_lookup_or_create_interesting_hfids(tree, new_fi->hfinfo);
1426 g_ptr_array_add(ptrs, new_fi);
1431 /* Gets data from tvbuff, adds it to proto_tree, increments offset,
1432 and returns proto_item* */
1434 ptvcursor_add(ptvcursor_t *ptvc, int hfindex, gint length,
1435 gboolean little_endian)
1438 header_field_info *hfinfo;
1443 /* We can't fake it just yet. We have to advance the cursor
1444 TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfindex, hfinfo); */
1446 offset = ptvc->offset;
1447 hfinfo = get_hfi_and_length(hfindex, ptvc->tvb, offset, &length,
1449 ptvc->offset += length;
1450 if (hfinfo->type == FT_UINT_BYTES || hfinfo->type == FT_UINT_STRING) {
1452 * The length of the rest of the item is in the first N
1453 * bytes of the item.
1455 n = get_uint_value(ptvc->tvb, offset, length, little_endian);
1459 /* Coast clear. Try and fake it */
1460 TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfindex, hfinfo);
1462 new_fi = new_field_info(ptvc->tree, hfinfo, ptvc->tvb, offset, item_length);
1466 return proto_tree_new_item(new_fi, ptvc->tree, ptvc->tvb,
1467 offset, length, little_endian);
1470 /* Add an item to a proto_tree, using the text label registered to that item;
1471 the item is extracted from the tvbuff handed to it. */
1473 proto_tree_add_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1474 gint start, gint length, gboolean little_endian)
1477 header_field_info *hfinfo;
1479 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1481 new_fi = alloc_field_info(tree, hfindex, tvb, start, &length);
1486 return proto_tree_new_item(new_fi, tree, tvb, start,
1487 length, little_endian);
1490 /* Add a FT_NONE to a proto_tree */
1492 proto_tree_add_none_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1493 gint length, const char *format, ...)
1497 header_field_info *hfinfo;
1499 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1501 DISSECTOR_ASSERT(hfinfo->type == FT_NONE);
1503 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, NULL);
1505 TRY_TO_FAKE_THIS_REPR(tree, pi);
1507 va_start(ap, format);
1508 proto_tree_set_representation(pi, format, ap);
1511 /* no value to set for FT_NONE */
1515 /* Gets data from tvbuff, adds it to proto_tree, *DOES NOT* increment
1516 * offset, and returns proto_item* */
1518 ptvcursor_add_no_advance(ptvcursor_t* ptvc, int hf, gint length,
1519 gboolean endianness)
1523 item = proto_tree_add_item(ptvc->tree, hf, ptvc->tvb, ptvc->offset,
1524 length, endianness);
1529 /* Advance the ptvcursor's offset within its tvbuff without
1530 * adding anything to the proto_tree. */
1532 ptvcursor_advance(ptvcursor_t* ptvc, gint length)
1534 ptvc->offset += length;
1539 proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb)
1541 fvalue_set(&fi->value, tvb, TRUE);
1544 /* Add a FT_PROTOCOL to a proto_tree */
1546 proto_tree_add_protocol_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1547 gint length, const char *format, ...)
1552 header_field_info *hfinfo;
1554 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1556 DISSECTOR_ASSERT(hfinfo->type == FT_PROTOCOL);
1558 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1560 proto_tree_set_protocol_tvb(new_fi, (start == 0 ? tvb : NULL));
1562 TRY_TO_FAKE_THIS_REPR(tree, pi);
1564 va_start(ap, format);
1565 proto_tree_set_representation(pi, format, ap);
1572 /* Add a FT_BYTES to a proto_tree */
1574 proto_tree_add_bytes(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1575 gint length, const guint8 *start_ptr)
1579 header_field_info *hfinfo;
1581 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1583 DISSECTOR_ASSERT(hfinfo->type == FT_BYTES);
1585 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1586 proto_tree_set_bytes(new_fi, start_ptr, length);
1592 proto_tree_add_bytes_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1593 gint start, gint length, const guint8 *start_ptr,
1594 const char *format, ...)
1598 header_field_info *hfinfo;
1600 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1602 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length, start_ptr);
1606 TRY_TO_FAKE_THIS_REPR(tree, pi);
1608 va_start(ap, format);
1609 proto_tree_set_representation_value(pi, format, ap);
1616 proto_tree_add_bytes_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1617 gint length, const guint8 *start_ptr, const char *format, ...)
1621 header_field_info *hfinfo;
1623 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1625 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length, start_ptr);
1629 TRY_TO_FAKE_THIS_REPR(tree, pi);
1631 va_start(ap, format);
1632 proto_tree_set_representation(pi, format, ap);
1639 proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length)
1643 bytes = g_byte_array_new();
1645 g_byte_array_append(bytes, start_ptr, length);
1647 fvalue_set(&fi->value, bytes, TRUE);
1652 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length)
1654 proto_tree_set_bytes(fi, tvb_get_ptr(tvb, offset, length), length);
1657 /* Add a FT_*TIME to a proto_tree */
1659 proto_tree_add_time(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1660 nstime_t *value_ptr)
1664 header_field_info *hfinfo;
1666 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1668 DISSECTOR_ASSERT(hfinfo->type == FT_ABSOLUTE_TIME ||
1669 hfinfo->type == FT_RELATIVE_TIME);
1671 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1672 proto_tree_set_time(new_fi, value_ptr);
1678 proto_tree_add_time_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1679 gint start, gint length, nstime_t *value_ptr,
1680 const char *format, ...)
1684 header_field_info *hfinfo;
1686 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1688 pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
1692 TRY_TO_FAKE_THIS_REPR(tree, pi);
1694 va_start(ap, format);
1695 proto_tree_set_representation_value(pi, format, ap);
1702 proto_tree_add_time_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1703 nstime_t *value_ptr, const char *format, ...)
1707 header_field_info *hfinfo;
1709 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1711 pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
1715 TRY_TO_FAKE_THIS_REPR(tree, pi);
1717 va_start(ap, format);
1718 proto_tree_set_representation(pi, format, ap);
1724 /* Set the FT_*TIME value */
1726 proto_tree_set_time(field_info *fi, nstime_t *value_ptr)
1728 DISSECTOR_ASSERT(value_ptr != NULL);
1730 fvalue_set(&fi->value, value_ptr, FALSE);
1733 /* Add a FT_IPXNET to a proto_tree */
1735 proto_tree_add_ipxnet(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1740 header_field_info *hfinfo;
1742 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1744 DISSECTOR_ASSERT(hfinfo->type == FT_IPXNET);
1746 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1747 proto_tree_set_ipxnet(new_fi, value);
1753 proto_tree_add_ipxnet_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1754 gint start, gint length, guint32 value, const char *format, ...)
1758 header_field_info *hfinfo;
1760 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1762 pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
1766 TRY_TO_FAKE_THIS_REPR(tree, pi);
1768 va_start(ap, format);
1769 proto_tree_set_representation_value(pi, format, ap);
1776 proto_tree_add_ipxnet_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1777 guint32 value, const char *format, ...)
1781 header_field_info *hfinfo;
1783 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1785 pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
1789 TRY_TO_FAKE_THIS_REPR(tree, pi);
1791 va_start(ap, format);
1792 proto_tree_set_representation(pi, format, ap);
1798 /* Set the FT_IPXNET value */
1800 proto_tree_set_ipxnet(field_info *fi, guint32 value)
1802 fvalue_set_uinteger(&fi->value, value);
1805 /* Add a FT_IPv4 to a proto_tree */
1807 proto_tree_add_ipv4(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1812 header_field_info *hfinfo;
1814 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1816 DISSECTOR_ASSERT(hfinfo->type == FT_IPv4);
1818 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1819 proto_tree_set_ipv4(new_fi, value);
1825 proto_tree_add_ipv4_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1826 gint start, gint length, guint32 value, const char *format, ...)
1830 header_field_info *hfinfo;
1832 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1834 pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
1838 TRY_TO_FAKE_THIS_REPR(tree, pi);
1840 va_start(ap, format);
1841 proto_tree_set_representation_value(pi, format, ap);
1848 proto_tree_add_ipv4_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1849 guint32 value, const char *format, ...)
1853 header_field_info *hfinfo;
1855 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1857 pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
1861 TRY_TO_FAKE_THIS_REPR(tree, pi);
1863 va_start(ap, format);
1864 proto_tree_set_representation(pi, format, ap);
1870 /* Set the FT_IPv4 value */
1872 proto_tree_set_ipv4(field_info *fi, guint32 value)
1874 fvalue_set_uinteger(&fi->value, value);
1877 /* Add a FT_IPv6 to a proto_tree */
1879 proto_tree_add_ipv6(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1880 const guint8* value_ptr)
1884 header_field_info *hfinfo;
1886 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1888 DISSECTOR_ASSERT(hfinfo->type == FT_IPv6);
1890 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1891 proto_tree_set_ipv6(new_fi, value_ptr);
1897 proto_tree_add_ipv6_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1898 gint start, gint length, const guint8* value_ptr,
1899 const char *format, ...)
1903 header_field_info *hfinfo;
1905 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1907 pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
1911 TRY_TO_FAKE_THIS_REPR(tree, pi);
1913 va_start(ap, format);
1914 proto_tree_set_representation_value(pi, format, ap);
1921 proto_tree_add_ipv6_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1922 const guint8* value_ptr, const char *format, ...)
1926 header_field_info *hfinfo;
1928 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1930 pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
1934 TRY_TO_FAKE_THIS_REPR(tree, pi);
1936 va_start(ap, format);
1937 proto_tree_set_representation(pi, format, ap);
1943 /* Set the FT_IPv6 value */
1945 proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr)
1947 DISSECTOR_ASSERT(value_ptr != NULL);
1948 fvalue_set(&fi->value, (gpointer) value_ptr, FALSE);
1952 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
1954 proto_tree_set_ipv6(fi, tvb_get_ptr(tvb, start, length));
1957 /* Add a FT_GUID to a proto_tree */
1959 proto_tree_add_guid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1960 const e_guid_t *value_ptr)
1964 header_field_info *hfinfo;
1966 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1968 DISSECTOR_ASSERT(hfinfo->type == FT_GUID);
1970 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1971 proto_tree_set_guid(new_fi, value_ptr);
1977 proto_tree_add_guid_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1978 gint start, gint length, const e_guid_t *value_ptr,
1979 const char *format, ...)
1983 header_field_info *hfinfo;
1985 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1987 pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
1991 TRY_TO_FAKE_THIS_REPR(tree, pi);
1993 va_start(ap, format);
1994 proto_tree_set_representation_value(pi, format, ap);
2001 proto_tree_add_guid_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2002 const e_guid_t *value_ptr, const char *format, ...)
2006 header_field_info *hfinfo;
2008 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2010 pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
2014 TRY_TO_FAKE_THIS_REPR(tree, pi);
2016 va_start(ap, format);
2017 proto_tree_set_representation(pi, format, ap);
2023 /* Set the FT_GUID value */
2025 proto_tree_set_guid(field_info *fi, const e_guid_t *value_ptr)
2027 DISSECTOR_ASSERT(value_ptr != NULL);
2028 fvalue_set(&fi->value, (gpointer) value_ptr, FALSE);
2032 proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gboolean little_endian)
2036 tvb_get_guid(tvb, start, &guid, little_endian);
2037 proto_tree_set_guid(fi, &guid);
2040 /* Add a FT_OID to a proto_tree */
2042 proto_tree_add_oid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2043 const guint8* value_ptr)
2047 header_field_info *hfinfo;
2049 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2051 DISSECTOR_ASSERT(hfinfo->type == FT_OID);
2053 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2054 proto_tree_set_oid(new_fi, value_ptr, length);
2060 proto_tree_add_oid_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2061 gint start, gint length, const guint8* value_ptr,
2062 const char *format, ...)
2066 header_field_info *hfinfo;
2068 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2070 pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
2074 TRY_TO_FAKE_THIS_REPR(tree, pi);
2076 va_start(ap, format);
2077 proto_tree_set_representation_value(pi, format, ap);
2084 proto_tree_add_oid_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2085 const guint8* value_ptr, const char *format, ...)
2089 header_field_info *hfinfo;
2091 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2093 pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
2097 TRY_TO_FAKE_THIS_REPR(tree, pi);
2099 va_start(ap, format);
2100 proto_tree_set_representation(pi, format, ap);
2106 /* Set the FT_OID value */
2108 proto_tree_set_oid(field_info *fi, const guint8* value_ptr, gint length)
2112 DISSECTOR_ASSERT(value_ptr != NULL);
2114 bytes = g_byte_array_new();
2116 g_byte_array_append(bytes, value_ptr, length);
2118 fvalue_set(&fi->value, bytes, TRUE);
2122 proto_tree_set_oid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
2124 proto_tree_set_oid(fi, tvb_get_ptr(tvb, start, length), length);
2128 proto_tree_set_uint64(field_info *fi, guint64 value)
2130 fvalue_set_integer64(&fi->value, value);
2134 proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start, guint length, gboolean little_endian)
2137 guint8* b = ep_tvb_memdup(tvb,start,length);
2142 default: DISSECTOR_ASSERT_NOT_REACHED();
2143 case 8: value <<= 8; value += *--b;
2144 case 7: value <<= 8; value += *--b;
2145 case 6: value <<= 8; value += *--b;
2146 case 5: value <<= 8; value += *--b;
2147 case 4: value <<= 8; value += *--b;
2148 case 3: value <<= 8; value += *--b;
2149 case 2: value <<= 8; value += *--b;
2150 case 1: value <<= 8; value += *--b;
2155 default: DISSECTOR_ASSERT_NOT_REACHED();
2156 case 8: value <<= 8; value += *b++;
2157 case 7: value <<= 8; value += *b++;
2158 case 6: value <<= 8; value += *b++;
2159 case 5: value <<= 8; value += *b++;
2160 case 4: value <<= 8; value += *b++;
2161 case 3: value <<= 8; value += *b++;
2162 case 2: value <<= 8; value += *b++;
2163 case 1: value <<= 8; value += *b++;
2168 proto_tree_set_uint64(fi, value);
2171 /* Add a FT_STRING or FT_STRINGZ to a proto_tree. Creates own copy of string,
2172 * and frees it when the proto_tree is destroyed. */
2174 proto_tree_add_string(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2175 gint length, const char* value)
2179 header_field_info *hfinfo;
2181 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2183 DISSECTOR_ASSERT(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ);
2185 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2186 DISSECTOR_ASSERT(length >= 0);
2187 proto_tree_set_string(new_fi, value);
2193 proto_tree_add_string_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2194 gint start, gint length, const char* value, const char *format,
2199 header_field_info *hfinfo;
2201 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2203 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
2207 TRY_TO_FAKE_THIS_REPR(tree, pi);
2209 va_start(ap, format);
2210 proto_tree_set_representation_value(pi, format, ap);
2217 proto_tree_add_string_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2218 gint length, const char* value, const char *format, ...)
2222 header_field_info *hfinfo;
2224 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2226 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
2230 TRY_TO_FAKE_THIS_REPR(tree, pi);
2232 va_start(ap, format);
2233 proto_tree_set_representation(pi, format, ap);
2239 /* Appends string data to a FT_STRING or FT_STRINGZ, allowing progressive
2240 * field info update instead of only updating the representation as does
2241 * proto_item_append_text()
2243 /* NOTE: this function will break with the TRY_TO_FAKE_THIS_ITEM()
2244 * speed optimization.
2245 * Currently only WSP use this function so it is not that bad but try to
2246 * avoid using this one if possible.
2247 * IF you must use this function you MUST also disable the
2248 * TRY_TO_FAKE_THIS_ITEM() optimization for your dissector/function
2249 * using proto_item_append_string().
2250 * Do that by faking that the tree is visible by calling
2251 * proto_tree_set_visible(tree, TRUE) (see packet-wsp.c)
2252 * BEFORE you create the item you are later going to use
2253 * proto_item_append_string() on.
2256 proto_item_append_string(proto_item *pi, const char *str)
2259 header_field_info *hfinfo;
2260 gchar *old_str, *new_str;
2267 fi = PITEM_FINFO(pi);
2268 DISSECTOR_ASSERT(fi && "proto_tree_set_visible(tree, TRUE) should have been called previously");
2270 hfinfo = fi->hfinfo;
2271 if (hfinfo->type == FT_PROTOCOL) {
2272 /* TRY_TO_FAKE_THIS_ITEM() speed optimization: silently skip */
2275 DISSECTOR_ASSERT(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ);
2276 old_str = fvalue_get(&fi->value);
2277 new_str = ep_strdup_printf("%s%s", old_str, str);
2278 fvalue_set(&fi->value, new_str, FALSE);
2281 /* Set the FT_STRING value */
2283 proto_tree_set_string(field_info *fi, const char* value)
2286 fvalue_set(&fi->value, (gpointer) value, FALSE);
2288 fvalue_set(&fi->value, (gpointer) "[ Null ]", FALSE);
2293 proto_tree_set_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
2298 length = tvb_ensure_length_remaining(tvb, start);
2301 string = tvb_get_ephemeral_string(tvb, start, length);
2302 proto_tree_set_string(fi, string);
2306 proto_tree_set_ebcdic_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
2311 length = tvb_ensure_length_remaining(tvb, start);
2314 string = tvb_get_ephemeral_string(tvb, start, length);
2315 EBCDIC_to_ASCII(string, length);
2316 proto_tree_set_string(fi, string);
2319 /* Add a FT_ETHER to a proto_tree */
2321 proto_tree_add_ether(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2322 const guint8* value)
2326 header_field_info *hfinfo;
2328 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2330 DISSECTOR_ASSERT(hfinfo->type == FT_ETHER);
2332 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2333 proto_tree_set_ether(new_fi, value);
2339 proto_tree_add_ether_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2340 gint start, gint length, const guint8* value,
2341 const char *format, ...)
2345 header_field_info *hfinfo;
2347 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2349 pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
2353 TRY_TO_FAKE_THIS_REPR(tree, pi);
2355 va_start(ap, format);
2356 proto_tree_set_representation_value(pi, format, ap);
2363 proto_tree_add_ether_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2364 const guint8* value, const char *format, ...)
2368 header_field_info *hfinfo;
2370 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2372 pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
2376 TRY_TO_FAKE_THIS_REPR(tree, pi);
2378 va_start(ap, format);
2379 proto_tree_set_representation(pi, format, ap);
2385 /* Set the FT_ETHER value */
2387 proto_tree_set_ether(field_info *fi, const guint8* value)
2389 fvalue_set(&fi->value, (gpointer) value, FALSE);
2393 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start)
2395 proto_tree_set_ether(fi, tvb_get_ptr(tvb, start, FT_ETHER_LEN));
2398 /* Add a FT_BOOLEAN to a proto_tree */
2400 proto_tree_add_boolean(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2405 header_field_info *hfinfo;
2407 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2409 DISSECTOR_ASSERT(hfinfo->type == FT_BOOLEAN);
2411 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2412 proto_tree_set_boolean(new_fi, value);
2418 proto_tree_add_boolean_format_value(proto_tree *tree, int hfindex,
2419 tvbuff_t *tvb, gint start, gint length, guint32 value,
2420 const char *format, ...)
2424 header_field_info *hfinfo;
2426 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2428 pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
2432 TRY_TO_FAKE_THIS_REPR(tree, pi);
2434 va_start(ap, format);
2435 proto_tree_set_representation_value(pi, format, ap);
2442 proto_tree_add_boolean_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2443 guint32 value, const char *format, ...)
2447 header_field_info *hfinfo;
2449 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2451 pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
2455 TRY_TO_FAKE_THIS_REPR(tree, pi);
2457 va_start(ap, format);
2458 proto_tree_set_representation(pi, format, ap);
2464 /* Set the FT_BOOLEAN value */
2466 proto_tree_set_boolean(field_info *fi, guint32 value)
2468 proto_tree_set_uint(fi, value);
2471 /* Add a FT_FLOAT to a proto_tree */
2473 proto_tree_add_float(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2478 header_field_info *hfinfo;
2480 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2482 DISSECTOR_ASSERT(hfinfo->type == FT_FLOAT);
2484 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2485 proto_tree_set_float(new_fi, value);
2491 proto_tree_add_float_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2492 gint start, gint length, float value, const char *format, ...)
2496 header_field_info *hfinfo;
2498 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2500 pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
2504 TRY_TO_FAKE_THIS_REPR(tree, pi);
2506 va_start(ap, format);
2507 proto_tree_set_representation_value(pi, format, ap);
2514 proto_tree_add_float_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2515 float value, const char *format, ...)
2519 header_field_info *hfinfo;
2521 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2523 pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
2527 TRY_TO_FAKE_THIS_REPR(tree, pi);
2529 va_start(ap, format);
2530 proto_tree_set_representation(pi, format, ap);
2536 /* Set the FT_FLOAT value */
2538 proto_tree_set_float(field_info *fi, float value)
2540 fvalue_set_floating(&fi->value, value);
2543 /* Add a FT_DOUBLE to a proto_tree */
2545 proto_tree_add_double(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2550 header_field_info *hfinfo;
2552 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2554 DISSECTOR_ASSERT(hfinfo->type == FT_DOUBLE);
2556 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2557 proto_tree_set_double(new_fi, value);
2563 proto_tree_add_double_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2564 gint start, gint length, double value, const char *format, ...)
2568 header_field_info *hfinfo;
2570 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2572 pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
2576 TRY_TO_FAKE_THIS_REPR(tree, pi);
2578 va_start(ap, format);
2579 proto_tree_set_representation_value(pi, format, ap);
2586 proto_tree_add_double_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2587 double value, const char *format, ...)
2591 header_field_info *hfinfo;
2593 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2595 pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
2599 TRY_TO_FAKE_THIS_REPR(tree, pi);
2601 va_start(ap, format);
2602 proto_tree_set_representation(pi, format, ap);
2608 /* Set the FT_DOUBLE value */
2610 proto_tree_set_double(field_info *fi, double value)
2612 fvalue_set_floating(&fi->value, value);
2615 /* Add FT_UINT{8,16,24,32} to a proto_tree */
2617 proto_tree_add_uint(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2620 proto_item *pi = NULL;
2622 header_field_info *hfinfo;
2624 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2626 switch(hfinfo->type) {
2632 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length,
2634 proto_tree_set_uint(new_fi, value);
2638 DISSECTOR_ASSERT_NOT_REACHED();
2645 proto_tree_add_uint_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2646 gint start, gint length, guint32 value, const char *format, ...)
2650 header_field_info *hfinfo;
2652 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2654 pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
2658 TRY_TO_FAKE_THIS_REPR(tree, pi);
2660 va_start(ap, format);
2661 proto_tree_set_representation_value(pi, format, ap);
2668 proto_tree_add_uint_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2669 guint32 value, const char *format, ...)
2673 header_field_info *hfinfo;
2675 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2677 pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
2681 TRY_TO_FAKE_THIS_REPR(tree, pi);
2683 va_start(ap, format);
2684 proto_tree_set_representation(pi, format, ap);
2690 /* Set the FT_UINT{8,16,24,32} value */
2692 proto_tree_set_uint(field_info *fi, guint32 value)
2694 header_field_info *hfinfo;
2697 hfinfo = fi->hfinfo;
2700 if (hfinfo->bitmask) {
2701 /* Mask out irrelevant portions */
2702 integer &= hfinfo->bitmask;
2705 if (hfinfo->bitshift > 0) {
2706 integer >>= hfinfo->bitshift;
2710 fvalue_set_uinteger(&fi->value, integer);
2713 /* Add FT_UINT64 to a proto_tree */
2715 proto_tree_add_uint64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2718 proto_item *pi = NULL;
2720 header_field_info *hfinfo;
2722 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2724 DISSECTOR_ASSERT(hfinfo->type == FT_UINT64);
2726 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2727 proto_tree_set_uint64(new_fi, value);
2733 proto_tree_add_uint64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2734 gint start, gint length, guint64 value, const char *format, ...)
2738 header_field_info *hfinfo;
2740 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2742 pi = proto_tree_add_uint64(tree, hfindex, tvb, start, length, value);
2746 TRY_TO_FAKE_THIS_REPR(tree, pi);
2748 va_start(ap, format);
2749 proto_tree_set_representation_value(pi, format, ap);
2756 proto_tree_add_uint64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2757 guint64 value, const char *format, ...)
2761 header_field_info *hfinfo;
2763 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2765 pi = proto_tree_add_uint64(tree, hfindex, tvb, start, length, value);
2769 TRY_TO_FAKE_THIS_REPR(tree, pi);
2771 va_start(ap, format);
2772 proto_tree_set_representation(pi, format, ap);
2778 /* Add FT_INT{8,16,24,32} to a proto_tree */
2780 proto_tree_add_int(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2783 proto_item *pi = NULL;
2785 header_field_info *hfinfo;
2787 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2789 switch(hfinfo->type) {
2794 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length,
2796 proto_tree_set_int(new_fi, value);
2800 DISSECTOR_ASSERT_NOT_REACHED();
2807 proto_tree_add_int_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2808 gint start, gint length, gint32 value, const char *format, ...)
2810 proto_item *pi = NULL;
2812 header_field_info *hfinfo;
2814 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2816 pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
2820 TRY_TO_FAKE_THIS_REPR(tree, pi);
2822 va_start(ap, format);
2823 proto_tree_set_representation_value(pi, format, ap);
2830 proto_tree_add_int_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2831 gint32 value, const char *format, ...)
2833 proto_item *pi = NULL;
2835 header_field_info *hfinfo;
2837 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2839 pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
2843 TRY_TO_FAKE_THIS_REPR(tree, pi);
2845 va_start(ap, format);
2846 proto_tree_set_representation(pi, format, ap);
2852 /* Set the FT_INT{8,16,24,32} value */
2854 proto_tree_set_int(field_info *fi, gint32 value)
2856 header_field_info *hfinfo;
2859 hfinfo = fi->hfinfo;
2860 integer = (guint32) value;
2862 if (hfinfo->bitmask) {
2863 /* Mask out irrelevant portions */
2864 integer &= hfinfo->bitmask;
2867 if (hfinfo->bitshift > 0) {
2868 integer >>= hfinfo->bitshift;
2872 fvalue_set_sinteger(&fi->value, integer);
2875 /* Add FT_INT64 to a proto_tree */
2877 proto_tree_add_int64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2880 proto_item *pi = NULL;
2882 header_field_info *hfinfo;
2884 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2886 DISSECTOR_ASSERT(hfinfo->type == FT_INT64);
2888 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2889 proto_tree_set_uint64(new_fi, (guint64)value);
2895 proto_tree_add_int64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2896 gint start, gint length, gint64 value, const char *format, ...)
2900 header_field_info *hfinfo;
2902 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2904 pi = proto_tree_add_int64(tree, hfindex, tvb, start, length, value);
2908 TRY_TO_FAKE_THIS_REPR(tree, pi);
2910 va_start(ap, format);
2911 proto_tree_set_representation_value(pi, format, ap);
2918 proto_tree_add_int64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2919 gint64 value, const char *format, ...)
2923 header_field_info *hfinfo;
2925 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2927 pi = proto_tree_add_int64(tree, hfindex, tvb, start, length, value);
2931 TRY_TO_FAKE_THIS_REPR(tree, pi);
2933 va_start(ap, format);
2934 proto_tree_set_representation(pi, format, ap);
2940 /* Add a field_info struct to the proto_tree, encapsulating it in a proto_node */
2942 proto_tree_add_node(proto_tree *tree, field_info *fi)
2944 proto_node *pnode, *tnode, *sibling;
2948 * Make sure "tree" is ready to have subtrees under it, by
2949 * checking whether it's been given an ett_ value.
2951 * "PNODE_FINFO(tnode)" may be null; that's the case for the root
2952 * node of the protocol tree. That node is not displayed,
2953 * so it doesn't need an ett_ value to remember whether it
2957 tfi = PNODE_FINFO(tnode);
2958 if (tfi != NULL && (tfi->tree_type < 0 || tfi->tree_type >= num_tree_types)) {
2959 REPORT_DISSECTOR_BUG(ep_strdup_printf("\"%s\" - \"%s\" tfi->tree_type: %u invalid (%s:%u)",
2960 fi->hfinfo->name, fi->hfinfo->abbrev, tfi->tree_type, __FILE__, __LINE__));
2961 /* XXX - is it safe to continue here? */
2964 DISSECTOR_ASSERT(tfi == NULL ||
2965 (tfi->tree_type >= 0 && tfi->tree_type < num_tree_types));
2967 PROTO_NODE_NEW(pnode);
2968 pnode->parent = tnode;
2969 PNODE_FINFO(pnode) = fi;
2970 pnode->tree_data = PTREE_DATA(tree);
2972 if (tnode->last_child != NULL) {
2973 sibling = tnode->last_child;
2974 DISSECTOR_ASSERT(sibling->next == NULL);
2975 sibling->next = pnode;
2977 tnode->first_child = pnode;
2978 tnode->last_child = pnode;
2980 return (proto_item*)pnode;
2984 /* Generic way to allocate field_info and add to proto_tree.
2985 * Sets *pfi to address of newly-allocated field_info struct, if pfi is
2988 proto_tree_add_pi(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2989 gint *length, field_info **pfi)
2998 fi = alloc_field_info(tree, hfindex, tvb, start, length);
2999 pi = proto_tree_add_node(tree, fi);
3001 /* If the proto_tree wants to keep a record of this finfo
3002 * for quick lookup, then record it. */
3003 ptrs = proto_lookup_or_create_interesting_hfids(tree, fi->hfinfo);
3005 g_ptr_array_add(ptrs, fi);
3007 /* Does the caller want to know the fi pointer? */
3016 static header_field_info *
3017 get_hfi_and_length(int hfindex, tvbuff_t *tvb, gint start, gint *length,
3020 header_field_info *hfinfo;
3021 gint length_remaining;
3024 * We only allow a null tvbuff if the item has a zero length,
3025 * i.e. if there's no data backing it.
3027 DISSECTOR_ASSERT(tvb != NULL || *length == 0);
3029 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
3032 * XXX - in some protocols, there are 32-bit unsigned length
3033 * fields, so lengths in protocol tree and tvbuff routines
3034 * should really be unsigned. We should have, for those
3035 * field types for which "to the end of the tvbuff" makes sense,
3036 * additional routines that take no length argument and
3037 * add fields that run to the end of the tvbuff.
3039 if (*length == -1) {
3041 * For FT_NONE, FT_PROTOCOL, FT_BYTES, and FT_STRING fields,
3042 * a length of -1 means "set the length to what remains in
3045 * The assumption is either that
3047 * 1) the length of the item can only be determined
3048 * by dissection (typically true of items with
3049 * subitems, which are probably FT_NONE or
3054 * 2) if the tvbuff is "short" (either due to a short
3055 * snapshot length or due to lack of reassembly of
3056 * fragments/segments/whatever), we want to display
3057 * what's available in the field (probably FT_BYTES
3058 * or FT_STRING) and then throw an exception later
3062 * 3) the field is defined to be "what's left in the
3065 * so we set the length to what remains in the tvbuff so
3066 * that, if we throw an exception while dissecting, it
3067 * has what is probably the right value.
3069 * For FT_STRINGZ, it means "the string is null-terminated,
3070 * not null-padded; set the length to the actual length
3071 * of the string", and if the tvbuff if short, we just
3072 * throw an exception.
3074 * It's not valid for any other type of field.
3076 switch (hfinfo->type) {
3080 * We allow this to be zero-length - for
3081 * example, an ONC RPC NULL procedure has
3082 * neither arguments nor reply, so the
3083 * payload for that protocol is empty.
3085 * However, if the length is negative, the
3086 * start offset is *past* the byte past the
3087 * end of the tvbuff, so we throw an
3090 *length = tvb_length_remaining(tvb, start);
3093 * Use "tvb_ensure_bytes_exist()"
3094 * to force the appropriate exception
3097 tvb_ensure_bytes_exist(tvb, start, 0);
3099 DISSECTOR_ASSERT(*length >= 0);
3105 *length = tvb_ensure_length_remaining(tvb, start);
3106 DISSECTOR_ASSERT(*length >= 0);
3111 * Leave the length as -1, so our caller knows
3117 DISSECTOR_ASSERT_NOT_REACHED();
3119 *item_length = *length;
3121 *item_length = *length;
3122 if (hfinfo->type == FT_PROTOCOL || hfinfo->type == FT_NONE) {
3124 * These types are for interior nodes of the
3125 * tree, and don't have data associated with
3126 * them; if the length is negative (XXX - see
3127 * above) or goes past the end of the tvbuff,
3128 * cut it short at the end of the tvbuff.
3129 * That way, if this field is selected in
3130 * Wireshark, we don't highlight stuff past
3131 * the end of the data.
3133 /* XXX - what to do, if we don't have a tvb? */
3135 length_remaining = tvb_length_remaining(tvb, start);
3136 if (*item_length < 0 ||
3137 (*item_length > 0 &&
3138 (length_remaining < *item_length)))
3139 *item_length = length_remaining;
3142 if (*item_length < 0) {
3143 THROW(ReportedBoundsError);
3151 new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
3152 gint start, gint item_length)
3158 fi->hfinfo = hfinfo;
3160 fi->start+=(tvb)?TVB_RAW_OFFSET(tvb):0;
3161 fi->length = item_length;
3164 if (!PTREE_DATA(tree)->visible)
3165 FI_SET_FLAG(fi, FI_HIDDEN);
3166 fvalue_init(&fi->value, fi->hfinfo->type);
3169 /* add the data source tvbuff */
3170 fi->ds_tvb=tvb?TVB_GET_DS_TVB(tvb):NULL;
3172 fi->appendix_start = 0;
3173 fi->appendix_length = 0;
3179 alloc_field_info(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3182 header_field_info *hfinfo;
3185 hfinfo = get_hfi_and_length(hfindex, tvb, start, length, &item_length);
3186 return new_field_info(tree, hfinfo, tvb, start, item_length);
3189 /* If the protocol tree is to be visible, set the representation of a
3190 proto_tree entry with the name of the field for the item and with
3191 the value formatted with the supplied printf-style format and
3194 proto_tree_set_representation_value(proto_item *pi, const char *format, va_list ap)
3196 int ret; /*tmp return value */
3197 field_info *fi = PITEM_FINFO(pi);
3198 header_field_info *hf;
3200 DISSECTOR_ASSERT(fi);
3204 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
3205 ITEM_LABEL_NEW(fi->rep);
3206 if (hf->bitmask && (hf->type == FT_BOOLEAN || IS_FT_UINT(hf->type))) {
3210 val = fvalue_get_uinteger(&fi->value);
3211 if (hf->bitshift > 0) {
3212 val <<= hf->bitshift;
3214 decode_bitfield_value(tmpbuf, val, hf->bitmask, hfinfo_bitwidth(hf));
3215 /* put in the hf name */
3216 ret = g_snprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
3217 "%s%s: ", tmpbuf, fi->hfinfo->name);
3219 /* put in the hf name */
3220 ret = g_snprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
3221 "%s: ", fi->hfinfo->name);
3224 /* If possible, Put in the value of the string */
3225 if (ret < ITEM_LABEL_LENGTH) {
3226 ret += g_vsnprintf(fi->rep->representation + ret,
3227 ITEM_LABEL_LENGTH - ret, format, ap);
3229 if (ret >= ITEM_LABEL_LENGTH) {
3230 /* Uh oh, we don't have enough room. Tell the user
3231 * that the field is truncated.
3235 /* Argh, we cannot reuse 'ap' here. So make a copy
3236 * of what we formatted for (re)use below.
3238 oldrep = g_strdup(fi->rep->representation);
3240 g_snprintf(fi->rep->representation,
3249 /* If the protocol tree is to be visible, set the representation of a
3250 proto_tree entry with the representation formatted with the supplied
3251 printf-style format and argument list. */
3253 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap)
3255 int ret; /*tmp return value */
3256 field_info *fi = PITEM_FINFO(pi);
3258 DISSECTOR_ASSERT(fi);
3260 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
3261 ITEM_LABEL_NEW(fi->rep);
3262 ret = g_vsnprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
3264 if (ret >= ITEM_LABEL_LENGTH) {
3265 /* Uh oh, we don't have enough room. Tell the user
3266 * that the field is truncated.
3270 /* Argh, we cannot reuse 'ap' here. So make a copy
3271 * of what we formatted for (re)use below.
3273 oldrep = g_strdup(fi->rep->representation);
3275 g_snprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
3276 "[truncated] %s", oldrep);
3282 /* -------------------------- */
3284 proto_custom_set(proto_tree* tree, int field_id,
3286 gchar *expr, int size )
3292 struct e_in6_addr *ipv6;
3294 guint32 n_addr; /* network-order IPv4 address */
3296 const true_false_string *tfstring;
3300 header_field_info* hfinfo;
3302 g_assert(field_id >= 0);
3304 hfinfo = proto_registrar_get_nth((guint)field_id);
3306 /* do we need to rewind ? */
3311 finfos = proto_get_finfo_ptr_array(tree, hfinfo->id);
3313 if (!finfos || !(len = g_ptr_array_len(finfos))) {
3314 hfinfo = hfinfo->same_name_next;
3317 /* get the last one */
3318 finfo = g_ptr_array_index(finfos, len -1);
3320 switch(hfinfo->type) {
3322 case FT_NONE: /* Nothing to add */
3327 g_strlcpy(result, "Yes", size);
3332 bytes = fvalue_get(&finfo->value);
3333 g_strlcpy(result, bytes_to_str(bytes, fvalue_length(&finfo->value)), size);
3336 case FT_ABSOLUTE_TIME:
3338 abs_time_to_str(fvalue_get(&finfo->value), (hfinfo->display == ABSOLUTE_TIME_UTC)),
3342 case FT_RELATIVE_TIME:
3343 g_strlcpy(result, rel_time_to_secs_str(fvalue_get(&finfo->value)), size);
3347 u_integer = fvalue_get_uinteger(&finfo->value);
3348 tfstring = (const true_false_string *)&tfs_true_false;
3349 if (hfinfo->strings) {
3350 tfstring = (const struct true_false_string*) hfinfo->strings;
3352 g_strlcpy(result, u_integer ? tfstring->true_string : tfstring->false_string, size);
3360 u_integer = fvalue_get_uinteger(&finfo->value);
3361 if (hfinfo->strings) {
3362 if (hfinfo->display & BASE_RANGE_STRING) {
3363 g_strlcpy(result, rval_to_str(u_integer, hfinfo->strings, "%u"), size);
3365 g_strlcpy(result, val_to_str(u_integer, cVALS(hfinfo->strings), "%u"), size);
3367 } else if (IS_BASE_DUAL(hfinfo->display)) {
3368 g_snprintf(result, size, hfinfo_uint_value_format(hfinfo), u_integer, u_integer);
3370 g_snprintf(result, size, hfinfo_uint_value_format(hfinfo), u_integer);
3376 g_snprintf(result, size, "%" G_GINT64_MODIFIER "u", fvalue_get_integer64(&finfo->value));
3379 /* XXX - make these just FT_INT? */
3384 integer = fvalue_get_sinteger(&finfo->value);
3385 if (hfinfo->strings) {
3386 if (hfinfo->display & BASE_RANGE_STRING) {
3387 g_strlcpy(result, rval_to_str(integer, hfinfo->strings, "%d"), size);
3389 g_strlcpy(result, val_to_str(integer, cVALS(hfinfo->strings), "%d"), size);
3391 } else if (IS_BASE_DUAL(hfinfo->display)) {
3392 g_snprintf(result, size, hfinfo_int_value_format(hfinfo), integer, integer);
3394 g_snprintf(result, size, hfinfo_int_value_format(hfinfo), integer);
3399 ipv4 = fvalue_get(&finfo->value);
3400 n_addr = ipv4_get_net_order_addr(ipv4);
3401 g_strlcpy(result, ip_to_str((guint8 *)&n_addr), size);
3405 ipv6 = fvalue_get(&finfo->value);
3406 SET_ADDRESS (&addr, AT_IPv6, sizeof(struct e_in6_addr), ipv6);
3407 address_to_str_buf(&addr, result, size);
3411 g_strlcpy(result, bytes_to_str_punct(fvalue_get(&finfo->value), 6, ':'), size);
3415 g_strlcpy(result, guid_to_str((e_guid_t *)fvalue_get(&finfo->value)), size);
3419 bytes = fvalue_get(&finfo->value);
3420 g_strlcpy(result, oid_resolved_from_encoded(bytes, fvalue_length(&finfo->value)), size);
3424 g_snprintf(result, size, "%." STRINGIFY(FLT_DIG) "f", fvalue_get_floating(&finfo->value));
3428 g_snprintf(result, size, "%." STRINGIFY(DBL_DIG) "g", fvalue_get_floating(&finfo->value));
3434 case FT_UINT_STRING:
3435 bytes = fvalue_get(&finfo->value);
3436 g_strlcpy(result, format_text(bytes, strlen(bytes)), size);
3439 case FT_IPXNET: /*XXX really No column custom ?*/
3442 g_error("hfinfo->type %d (%s) not handled\n",
3444 ftype_name(hfinfo->type));
3445 DISSECTOR_ASSERT_NOT_REACHED();
3449 switch(hfinfo->type) {
3453 case FT_UINT_STRING:
3454 g_snprintf(expr, size, "\"%s\"",result);
3456 g_strlcpy(expr, result, size);
3459 return hfinfo->abbrev;
3465 /* Set text of proto_item after having already been created. */
3467 proto_item_set_text(proto_item *pi, const char *format, ...)
3469 field_info *fi = NULL;
3476 fi = PITEM_FINFO(pi);
3481 ITEM_LABEL_FREE(fi->rep);
3484 va_start(ap, format);
3485 proto_tree_set_representation(pi, format, ap);
3489 /* Append to text of proto_item after having already been created. */
3491 proto_item_append_text(proto_item *pi, const char *format, ...)
3493 field_info *fi = NULL;
3501 fi = PITEM_FINFO(pi);
3506 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
3507 va_start(ap, format);
3510 * If we don't already have a representation,
3511 * generate the default representation.
3513 if (fi->rep == NULL) {
3514 ITEM_LABEL_NEW(fi->rep);
3515 proto_item_fill_label(fi, fi->rep->representation);
3518 curlen = strlen(fi->rep->representation);
3519 if (ITEM_LABEL_LENGTH > curlen) {
3520 g_vsnprintf(fi->rep->representation + curlen,
3521 ITEM_LABEL_LENGTH - (gulong) curlen, format, ap);
3528 proto_item_set_len(proto_item *pi, gint length)
3535 fi = PITEM_FINFO(pi);
3539 DISSECTOR_ASSERT(length >= 0);
3540 fi->length = length;
3542 if (fi->value.ftype->ftype == FT_BYTES)
3543 fi->value.value.bytes->len = length;
3547 * Sets the length of the item based on its start and on the specified
3548 * offset, which is the offset past the end of the item; as the start
3549 * in the item is relative to the beginning of the data source tvbuff,
3550 * we need to pass in a tvbuff - the end offset is relative to the beginning
3554 proto_item_set_end(proto_item *pi, tvbuff_t *tvb, gint end)
3561 fi = PITEM_FINFO(pi);
3565 end += TVB_RAW_OFFSET(tvb);
3566 DISSECTOR_ASSERT(end >= fi->start);
3567 fi->length = end - fi->start;
3571 proto_item_get_len(proto_item *pi)
3573 field_info *fi = PITEM_FINFO(pi);
3574 return fi ? fi->length : -1;
3578 /** clear flags according to the mask and set new flag values */
3579 #define FI_REPLACE_FLAGS(fi, mask, flags_in) { \
3580 (fi->flags = (fi)->flags & ~(mask)); \
3581 (fi->flags = (fi)->flags | (flags_in)); \
3585 proto_item_set_expert_flags(proto_item *pi, int group, guint severity)
3587 if(pi == NULL || PITEM_FINFO(pi) == NULL)
3590 /* only change things if severity is worse or at least equal than before */
3591 if(severity >= FI_GET_FLAG(PITEM_FINFO(pi), PI_SEVERITY_MASK)) {
3592 FI_REPLACE_FLAGS(PITEM_FINFO(pi), PI_GROUP_MASK, group);
3593 FI_REPLACE_FLAGS(PITEM_FINFO(pi), PI_SEVERITY_MASK, severity);
3602 proto_tree_create_root(void)
3606 /* Initialize the proto_node */
3607 PROTO_NODE_NEW(pnode);
3608 pnode->parent = NULL;
3609 PNODE_FINFO(pnode) = NULL;
3610 pnode->tree_data = g_new(tree_data_t, 1);
3612 /* Don't initialize the tree_data_t. Wait until we know we need it */
3613 pnode->tree_data->interesting_hfids = NULL;
3615 /* Set the default to FALSE so it's easier to
3616 * find errors; if we expect to see the protocol tree
3617 * but for some reason the default 'visible' is not
3618 * changed, then we'll find out very quickly. */
3619 pnode->tree_data->visible = FALSE;
3621 /* Make sure that we fake protocols (if possible) */
3622 pnode->tree_data->fake_protocols = TRUE;
3624 /* Keep track of the number of children */
3625 pnode->tree_data->count = 0;
3627 return (proto_tree*) pnode;
3631 /* "prime" a proto_tree with a single hfid that a dfilter
3632 * is interested in. */
3634 proto_tree_prime_hfid(proto_tree *tree _U_, gint hfid)
3636 header_field_info *hfinfo;
3638 PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
3639 /* this field is referenced by a filter so increase the refcount.
3640 also increase the refcount for the parent, i.e the protocol.
3642 hfinfo->ref_type = HF_REF_TYPE_DIRECT;
3643 /* only increase the refcount if there is a parent.
3644 if this is a protocol and not a field then parent will be -1
3645 and there is no parent to add any refcounting for.
3647 if (hfinfo->parent != -1) {
3648 header_field_info *parent_hfinfo;
3649 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
3651 /* Mark parent as indirectly referenced unless it is already directly
3652 * referenced, i.e. the user has specified the parent in a filter.
3654 if (parent_hfinfo->ref_type != HF_REF_TYPE_DIRECT)
3655 parent_hfinfo->ref_type = HF_REF_TYPE_INDIRECT;
3660 proto_item_add_subtree(proto_item *pi, gint idx) {
3666 DISSECTOR_ASSERT(idx >= 0 && idx < num_tree_types);
3668 fi = PITEM_FINFO(pi);
3670 return (proto_tree*) pi;
3672 fi->tree_type = idx;
3674 return (proto_tree*) pi;
3678 proto_item_get_subtree(proto_item *pi) {
3683 fi = PITEM_FINFO(pi);
3684 if ( (!fi) || (fi->tree_type == -1) )
3686 return (proto_tree*) pi;
3690 proto_item_get_parent(proto_item *ti) {
3697 proto_item_get_parent_nth(proto_item *ti, int gen) {
3710 proto_tree_get_parent(proto_tree *tree) {
3713 return (proto_item*) tree;
3717 proto_tree_get_root(proto_tree *tree) {
3720 while (tree->parent) {
3721 tree = tree->parent;
3727 proto_tree_move_item(proto_tree *tree, proto_item *fixed_item, proto_item *item_to_move)
3729 /* This function doesn't generate any values. It only reorganizes the prococol tree
3730 * so we can bail out immediately if it isn't visible. */
3731 if (!tree || !PTREE_DATA(tree)->visible)
3734 DISSECTOR_ASSERT(item_to_move->parent == tree);
3735 DISSECTOR_ASSERT(fixed_item->parent == tree);
3737 /*** cut item_to_move out ***/
3739 /* is item_to_move the first? */
3740 if(tree->first_child == item_to_move) {
3741 /* simply change first child to next */
3742 tree->first_child = item_to_move->next;
3744 DISSECTOR_ASSERT(tree->last_child != item_to_move);
3746 proto_item *curr_item;
3747 /* find previous and change it's next */
3748 for(curr_item = tree->first_child; curr_item != NULL; curr_item = curr_item->next) {
3749 if(curr_item->next == item_to_move) {
3754 DISSECTOR_ASSERT(curr_item);
3756 curr_item->next = item_to_move->next;
3758 /* fix last_child if required */
3759 if(tree->last_child == item_to_move) {
3760 tree->last_child = curr_item;
3764 /*** insert to_move after fixed ***/
3765 item_to_move->next = fixed_item->next;
3766 fixed_item->next = item_to_move;
3767 if(tree->last_child == fixed_item) {
3768 tree->last_child = item_to_move;
3773 proto_tree_set_appendix(proto_tree *tree, tvbuff_t *tvb, gint start, gint length)
3780 fi = PTREE_FINFO(tree);
3784 start += TVB_RAW_OFFSET(tvb);
3785 DISSECTOR_ASSERT(start >= 0);
3786 DISSECTOR_ASSERT(length >= 0);
3788 fi->appendix_start = start;
3789 fi->appendix_length = length;
3793 proto_register_protocol(const char *name, const char *short_name, const char *filter_name)
3795 protocol_t *protocol;
3796 header_field_info *hfinfo;
3798 char *existing_name;
3802 gboolean found_invalid;
3805 * Make sure there's not already a protocol with any of those
3806 * names. Crash if there is, as that's an error in the code
3807 * or an inappropriate plugin.
3808 * This situation has to be fixed to not register more than one
3809 * protocol with the same name.
3811 * This is done by reducing the number of strcmp (and alike) calls as much as possible,
3812 * as this significally slows down startup time.
3814 * Drawback: As a hash value is used to reduce insert time,
3815 * this might lead to a hash collision.
3816 * However, as we have around 500+ protocols and we're using a 32 bit int this is very,
3820 key = g_malloc (sizeof(gint));
3821 *key = wrs_str_hash(name);
3822 existing_name = g_hash_table_lookup(proto_names, key);
3823 if (existing_name != NULL) {
3824 /* g_error will terminate the program */
3825 g_error("Duplicate protocol name \"%s\"!"
3826 " This might be caused by an inappropriate plugin or a development error.", name);
3828 g_hash_table_insert(proto_names, key, (gpointer)name);
3830 existing_name = g_hash_table_lookup(proto_short_names, (gpointer)short_name);
3831 if (existing_name != NULL) {
3832 g_error("Duplicate protocol short_name \"%s\"!"
3833 " This might be caused by an inappropriate plugin or a development error.", short_name);
3835 g_hash_table_insert(proto_short_names, (gpointer)short_name, (gpointer)short_name);
3837 found_invalid = FALSE;
3838 for (i = 0; i < strlen(filter_name); i++) {
3840 if (!(islower(c) || isdigit(c) || c == '-' || c == '_' || c == '.')) {
3841 found_invalid = TRUE;
3844 if (found_invalid) {
3845 g_error("Protocol filter name \"%s\" has one or more invalid characters."
3846 " Allowed are lower characters, digits, '-', '_' and '.'."
3847 " This might be caused by an inappropriate plugin or a development error.", filter_name);
3849 existing_name = g_hash_table_lookup(proto_filter_names, (gpointer)filter_name);
3850 if (existing_name != NULL) {
3851 g_error("Duplicate protocol filter_name \"%s\"!"
3852 " This might be caused by an inappropriate plugin or a development error.", filter_name);
3854 g_hash_table_insert(proto_filter_names, (gpointer)filter_name, (gpointer)filter_name);
3856 /* Add this protocol to the list of known protocols; the list
3857 is sorted by protocol short name. */
3858 protocol = g_new(protocol_t, 1);
3859 protocol->name = name;
3860 protocol->short_name = short_name;
3861 protocol->filter_name = filter_name;
3862 protocol->fields = NULL;
3863 protocol->is_enabled = TRUE; /* protocol is enabled by default */
3864 protocol->can_toggle = TRUE;
3865 protocol->is_private = FALSE;
3866 /* list will be sorted later by name, when all protocols completed registering */
3867 protocols = g_list_prepend(protocols, protocol);
3869 /* Here we do allocate a new header_field_info struct */
3870 #if GLIB_CHECK_VERSION(2,10,0)
3871 hfinfo = g_slice_new(header_field_info);
3873 hfinfo = g_mem_chunk_alloc(gmc_hfinfo);
3875 hfinfo->name = name;
3876 hfinfo->abbrev = filter_name;
3877 hfinfo->type = FT_PROTOCOL;
3878 hfinfo->display = BASE_NONE;
3879 hfinfo->strings = protocol;
3880 hfinfo->bitmask = 0;
3881 hfinfo->bitshift = 0;
3882 hfinfo->ref_type = HF_REF_TYPE_NONE;
3883 hfinfo->blurb = NULL;
3884 hfinfo->parent = -1; /* this field differentiates protos and fields */
3886 proto_id = proto_register_field_init(hfinfo, hfinfo->parent);
3887 protocol->proto_id = proto_id;
3892 proto_mark_private(int proto_id)
3894 protocol_t *protocol = find_protocol_by_id(proto_id);
3896 protocol->is_private = TRUE;
3900 proto_is_private(int proto_id)
3902 protocol_t *protocol = find_protocol_by_id(proto_id);
3904 return protocol->is_private;
3910 * Routines to use to iterate over the protocols.
3911 * The argument passed to the iterator routines is an opaque cookie to
3912 * their callers; it's the GList pointer for the current element in
3914 * The ID of the protocol is returned, or -1 if there is no protocol.
3917 proto_get_first_protocol(void **cookie)
3919 protocol_t *protocol;
3921 if (protocols == NULL)
3923 *cookie = protocols;
3924 protocol = protocols->data;
3925 return protocol->proto_id;
3929 proto_get_next_protocol(void **cookie)
3931 GList *list_item = *cookie;
3932 protocol_t *protocol;
3934 list_item = g_list_next(list_item);
3935 if (list_item == NULL)
3937 *cookie = list_item;
3938 protocol = list_item->data;
3939 return protocol->proto_id;
3943 proto_get_first_protocol_field(int proto_id, void **cookie)
3945 protocol_t *protocol = find_protocol_by_id(proto_id);
3946 hf_register_info *ptr;
3948 if ((protocol == NULL) || (protocol->fields == NULL))
3951 *cookie = protocol->fields;
3952 ptr = protocol->fields->data;
3953 return &ptr->hfinfo;
3957 proto_get_next_protocol_field(void **cookie)
3959 GList *list_item = *cookie;
3960 hf_register_info *ptr;
3962 list_item = g_list_next(list_item);
3963 if (list_item == NULL)
3966 *cookie = list_item;
3967 ptr = list_item->data;
3968 return &ptr->hfinfo;
3972 find_protocol_by_id(int proto_id)
3974 header_field_info *hfinfo;
3979 PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
3980 DISSECTOR_ASSERT(hfinfo->type==FT_PROTOCOL);
3981 return (protocol_t *)hfinfo->strings;
3984 static gint compare_filter_name(gconstpointer proto_arg,
3985 gconstpointer filter_name)
3987 const protocol_t *protocol = proto_arg;
3988 const gchar* f_name = filter_name;
3990 return (strcmp(protocol->filter_name, f_name));
3994 proto_get_id(protocol_t *protocol)
3996 return protocol->proto_id;
3999 int proto_get_id_by_filter_name(const gchar* filter_name)
4002 protocol_t *protocol;
4004 list_entry = g_list_find_custom(protocols, filter_name,
4005 compare_filter_name);
4007 if (list_entry == NULL)
4009 protocol = list_entry->data;
4010 return protocol->proto_id;
4014 proto_get_protocol_name(int proto_id)
4016 protocol_t *protocol;
4018 protocol = find_protocol_by_id(proto_id);
4019 return protocol->name;
4023 proto_get_protocol_short_name(protocol_t *protocol)
4025 if (protocol == NULL)
4027 return protocol->short_name;
4031 proto_get_protocol_long_name(protocol_t *protocol)
4033 if (protocol == NULL)
4035 return protocol->name;
4039 proto_get_protocol_filter_name(int proto_id)
4041 protocol_t *protocol;
4043 protocol = find_protocol_by_id(proto_id);
4044 if (protocol == NULL)
4046 return protocol->filter_name;
4050 proto_is_protocol_enabled(protocol_t *protocol)
4052 return protocol->is_enabled;
4056 proto_can_toggle_protocol(int proto_id)
4058 protocol_t *protocol;
4060 protocol = find_protocol_by_id(proto_id);
4061 return protocol->can_toggle;
4065 proto_set_decoding(int proto_id, gboolean enabled)
4067 protocol_t *protocol;
4069 protocol = find_protocol_by_id(proto_id);
4070 DISSECTOR_ASSERT(protocol->can_toggle);
4071 protocol->is_enabled = enabled;
4075 proto_enable_all(void)
4077 protocol_t *protocol;
4078 GList *list_item = protocols;
4080 if (protocols == NULL)
4084 protocol = list_item->data;
4085 if (protocol->can_toggle)
4086 protocol->is_enabled = TRUE;
4087 list_item = g_list_next(list_item);
4092 proto_set_cant_toggle(int proto_id)
4094 protocol_t *protocol;
4096 protocol = find_protocol_by_id(proto_id);
4097 protocol->can_toggle = FALSE;
4100 /* for use with static arrays only, since we don't allocate our own copies
4101 of the header_field_info struct contained within the hf_register_info struct */
4103 proto_register_field_array(int parent, hf_register_info *hf, int num_records)
4106 hf_register_info *ptr = hf;
4109 proto = find_protocol_by_id(parent);
4110 for (i = 0; i < num_records; i++, ptr++) {
4112 * Make sure we haven't registered this yet.
4113 * Most fields have variables associated with them
4114 * that are initialized to -1; some have array elements,
4115 * or possibly uninitialized variables, so we also allow
4116 * 0 (which is unlikely to be the field ID we get back
4117 * from "proto_register_field_init()").
4119 if (*ptr->p_id != -1 && *ptr->p_id != 0) {
4121 "Duplicate field detected in call to proto_register_field_array: %s is already registered\n",
4122 ptr->hfinfo.abbrev);
4126 if (proto != NULL) {
4127 if (proto->fields == NULL) {
4128 proto->fields = g_list_append(NULL, ptr);
4129 proto->last_field = proto->fields;
4132 g_list_append(proto->last_field, ptr)->next;
4135 field_id = proto_register_field_init(&ptr->hfinfo, parent);
4136 *ptr->p_id = field_id;
4140 /* chars allowed in field abbrev */
4142 const guchar fld_abbrev_chars[256] = {
4143 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00-0x0F */
4144 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10-0x1F */
4145 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, /* 0x20-0x2F '-', '.' */
4146 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 0x30-0x3F '0'-'9' */
4147 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x40-0x4F 'A'-'O' */
4148 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 0x50-0x5F 'P'-'Z', '_' */
4149 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x60-0x6F 'a'-'o' */
4150 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 0x70-0x7F 'p'-'z' */
4151 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80-0x8F */
4152 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90-0x9F */
4153 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xA0-0xAF */
4154 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xB0-0xBF */
4155 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xC0-0xCF */
4156 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xD0-0xDF */
4157 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xE0-0xEF */
4158 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xF0-0xFF */
4161 /* temporary function containing assert part for easier profiling */
4162 static void tmp_fld_check_assert(header_field_info *hfinfo) {
4163 /* The field must have a name (with length > 0) */
4164 DISSECTOR_ASSERT(hfinfo->name && hfinfo->name[0]);
4166 /* fields with an empty string for an abbreviation aren't filterable */
4167 DISSECTOR_ASSERT(hfinfo->abbrev);
4169 /* These types of fields are allowed to have value_strings, true_false_strings or a protocol_t struct*/
4170 DISSECTOR_ASSERT((hfinfo->strings == NULL) || (
4171 (hfinfo->type == FT_UINT8) ||
4172 (hfinfo->type == FT_UINT16) ||
4173 (hfinfo->type == FT_UINT24) ||
4174 (hfinfo->type == FT_UINT32) ||
4175 (hfinfo->type == FT_INT8) ||
4176 (hfinfo->type == FT_INT16) ||
4177 (hfinfo->type == FT_INT24) ||
4178 (hfinfo->type == FT_INT32) ||
4179 (hfinfo->type == FT_BOOLEAN) ||
4180 (hfinfo->type == FT_PROTOCOL) ||
4181 (hfinfo->type == FT_FRAMENUM) ));
4183 switch (hfinfo->type) {
4190 /* Hexadecimal and octal are, in printf() and everywhere else,
4191 * unsigned so don't allow dissectors to register a signed
4192 * field to be displayed unsigned. (Else how would we
4193 * display values negative values?)
4195 * If you want to take out this check, be sure to fix
4196 * hfinfo_numeric_format() so that it does not assert out
4197 * when trying to construct a hexadecimal representation of
4200 DISSECTOR_ASSERT(hfinfo->display != BASE_HEX &&
4201 hfinfo->display != BASE_HEX_DEC &&
4202 hfinfo->display != BASE_DEC_HEX &&
4203 hfinfo->display != BASE_OCT);
4209 if (hfinfo->strings == NULL) {
4210 /* Require integral types (other than frame number, which is
4211 always displayed in decimal) to have a number base */
4212 DISSECTOR_ASSERT(hfinfo->display != BASE_NONE);
4217 DISSECTOR_ASSERT(hfinfo->display != BASE_NONE);
4222 DISSECTOR_ASSERT(hfinfo->display == BASE_NONE);
4223 DISSECTOR_ASSERT(hfinfo->bitmask == 0);
4229 case FT_ABSOLUTE_TIME:
4230 DISSECTOR_ASSERT(hfinfo->display == ABSOLUTE_TIME_LOCAL ||
4231 hfinfo->display == ABSOLUTE_TIME_UTC);
4232 DISSECTOR_ASSERT(hfinfo->bitmask == 0);
4233 DISSECTOR_ASSERT(hfinfo->strings == NULL);
4237 DISSECTOR_ASSERT(hfinfo->display == BASE_NONE);
4238 DISSECTOR_ASSERT(hfinfo->bitmask == 0);
4239 DISSECTOR_ASSERT(hfinfo->strings == NULL);
4245 proto_register_field_init(header_field_info *hfinfo, int parent)
4248 tmp_fld_check_assert(hfinfo);
4250 /* if this is a bitfield, compute bitshift */
4251 if (hfinfo->bitmask) {
4252 hfinfo->bitshift = wrs_count_bitshift(hfinfo->bitmask);
4255 hfinfo->parent = parent;
4256 hfinfo->same_name_next = NULL;
4257 hfinfo->same_name_prev = NULL;
4259 /* if we always add and never delete, then id == len - 1 is correct */
4260 if(gpa_hfinfo.len>=gpa_hfinfo.allocated_len){
4261 if(!gpa_hfinfo.hfi){
4262 gpa_hfinfo.allocated_len=1000;
4263 gpa_hfinfo.hfi=g_malloc(sizeof(header_field_info *)*1000);
4265 gpa_hfinfo.allocated_len+=1000;
4266 gpa_hfinfo.hfi=g_realloc(gpa_hfinfo.hfi, sizeof(header_field_info *)*gpa_hfinfo.allocated_len);
4269 gpa_hfinfo.hfi[gpa_hfinfo.len]=hfinfo;
4271 hfinfo->id = gpa_hfinfo.len - 1;
4273 /* if we have real names, enter this field in the name tree */
4274 if ((hfinfo->name[0] != 0) && (hfinfo->abbrev[0] != 0 )) {
4276 header_field_info *same_name_next_hfinfo;
4279 /* Check that the filter name (abbreviation) is legal;
4280 * it must contain only alphanumerics, '-', "_", and ".". */
4281 c = wrs_check_charset(fld_abbrev_chars, hfinfo->abbrev);
4283 fprintf(stderr, "OOPS: '%c' in '%s'\n", c, hfinfo->abbrev);
4284 DISSECTOR_ASSERT(!c);
4287 /* We allow multiple hfinfo's to be registered under the same
4288 * abbreviation. This was done for X.25, as, depending
4289 * on whether it's modulo-8 or modulo-128 operation,
4290 * some bitfield fields may be in different bits of
4291 * a byte, and we want to be able to refer to that field
4292 * with one name regardless of whether the packets
4293 * are modulo-8 or modulo-128 packets. */
4295 same_name_hfinfo = NULL;
4297 g_tree_insert(gpa_name_tree, (gpointer) (hfinfo->abbrev), hfinfo);
4298 /* GLIB 2.x - if it is already present
4299 * the previous hfinfo with the same name is saved
4300 * to same_name_hfinfo by value destroy callback */
4301 if (same_name_hfinfo) {
4302 /* There's already a field with this name.
4303 * Put it after that field in the list of
4304 * fields with this name, then allow the code
4305 * after this if{} block to replace the old
4306 * hfinfo with the new hfinfo in the GTree. Thus,
4307 * we end up with a linked-list of same-named hfinfo's,
4308 * with the root of the list being the hfinfo in the GTree */
4309 same_name_next_hfinfo =
4310 same_name_hfinfo->same_name_next;
4312 hfinfo->same_name_next = same_name_next_hfinfo;
4313 if (same_name_next_hfinfo)
4314 same_name_next_hfinfo->same_name_prev = hfinfo;
4316 same_name_hfinfo->same_name_next = hfinfo;
4317 hfinfo->same_name_prev = same_name_hfinfo;
4325 proto_register_subtree_array(gint *const *indices, int num_indices)
4328 gint *const *ptr = indices;
4331 * If we've already allocated the array of tree types, expand
4332 * it; this lets plugins such as mate add tree types after
4333 * the initial startup. (If we haven't already allocated it,
4334 * we don't allocate it; on the first pass, we just assign
4335 * ett values and keep track of how many we've assigned, and
4336 * when we're finished registering all dissectors we allocate
4337 * the array, so that we do only one allocation rather than
4338 * wasting CPU time and memory by growing the array for each
4339 * dissector that registers ett values.)
4341 if (tree_is_expanded != NULL) {
4343 g_realloc(tree_is_expanded,
4344 (num_tree_types+num_indices)*sizeof (gboolean));
4345 memset(tree_is_expanded + num_tree_types, 0,
4346 num_indices*sizeof (gboolean));
4350 * Assign "num_indices" subtree numbers starting at "num_tree_types",
4351 * returning the indices through the pointers in the array whose
4352 * first element is pointed to by "indices", and update
4353 * "num_tree_types" appropriately.
4355 for (i = 0; i < num_indices; i++, ptr++, num_tree_types++) {
4357 /* g_error will terminate the program */
4358 g_error("register_subtree_array: subtree item type (ett_...) not -1 !"
4359 " This is a development error:"
4360 " Either the subtree item type has already been assigned or"
4361 " was not initialized to -1.");
4363 **ptr = num_tree_types;
4368 proto_item_fill_label(field_info *fi, gchar *label_str)
4370 header_field_info *hfinfo;
4376 guint32 n_addr; /* network-order IPv4 address */
4378 int ret; /*tmp return value */
4383 /* XXX: Check validity of hfinfo->type */
4387 hfinfo = fi->hfinfo;
4389 switch(hfinfo->type) {
4392 g_strlcpy(label_str, hfinfo->name, ITEM_LABEL_LENGTH);
4396 fill_label_boolean(fi, label_str);
4401 bytes = fvalue_get(&fi->value);
4403 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4404 "%s: %s", hfinfo->name,
4405 bytes_to_str(bytes, fvalue_length(&fi->value)));
4406 if (ret >= ITEM_LABEL_LENGTH) {
4407 /* Uh oh, we don't have enough room. Tell the
4408 * user that the field is truncated.
4410 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4411 "%s [truncated]: %s",
4413 bytes_to_str(bytes, fvalue_length(&fi->value)));
4417 g_snprintf(label_str, ITEM_LABEL_LENGTH, "%s: <MISSING>", hfinfo->name);
4421 /* Four types of integers to take care of:
4422 * Bitfield, with val_string
4423 * Bitfield, w/o val_string
4424 * Non-bitfield, with val_string
4425 * Non-bitfield, w/o val_string
4431 if (hfinfo->bitmask) {
4432 fill_label_bitfield(fi, label_str);
4434 fill_label_uint(fi, label_str);
4439 fill_label_uint(fi, label_str);
4443 fill_label_uint64(fi, label_str);
4450 DISSECTOR_ASSERT(!hfinfo->bitmask);
4451 fill_label_int(fi, label_str);
4455 fill_label_int64(fi, label_str);
4459 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4460 "%s: %." STRINGIFY(FLT_DIG) "f",
4461 hfinfo->name, fvalue_get_floating(&fi->value));
4465 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4466 "%s: %." STRINGIFY(DBL_DIG) "g",
4467 hfinfo->name, fvalue_get_floating(&fi->value));
4470 case FT_ABSOLUTE_TIME:
4471 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4472 "%s: %s", hfinfo->name,
4473 abs_time_to_str(fvalue_get(&fi->value), (hfinfo->display == ABSOLUTE_TIME_UTC)));
4476 case FT_RELATIVE_TIME:
4477 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4478 "%s: %s seconds", hfinfo->name,
4479 rel_time_to_secs_str(fvalue_get(&fi->value)));
4483 integer = fvalue_get_uinteger(&fi->value);
4484 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4485 "%s: %s (0x%08X)", hfinfo->name,
4486 get_ipxnet_name(integer), integer);
4490 bytes = fvalue_get(&fi->value);
4491 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4492 "%s: %s (%s)", hfinfo->name,
4493 get_ether_name(bytes),
4494 ether_to_str(bytes));
4498 ipv4 = fvalue_get(&fi->value);
4499 n_addr = ipv4_get_net_order_addr(ipv4);
4500 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4501 "%s: %s (%s)", hfinfo->name,
4502 get_hostname(n_addr),
4503 ip_to_str((guint8*)&n_addr));
4507 bytes = fvalue_get(&fi->value);
4508 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4509 "%s: %s (%s)", hfinfo->name,
4510 get_hostname6((struct e_in6_addr *)bytes),
4511 ip6_to_str((struct e_in6_addr*)bytes));
4515 guid = fvalue_get(&fi->value);
4516 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4517 "%s: %s", hfinfo->name,
4522 bytes = fvalue_get(&fi->value);
4523 name = oid_resolved_from_encoded(bytes, fvalue_length(&fi->value));
4525 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4526 "%s: %s (%s)", hfinfo->name,
4527 oid_encoded2string(bytes, fvalue_length(&fi->value)), name);
4529 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4530 "%s: %s", hfinfo->name,
4531 oid_encoded2string(bytes, fvalue_length(&fi->value)));
4538 case FT_UINT_STRING:
4539 bytes = fvalue_get(&fi->value);
4540 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4541 "%s: %s", hfinfo->name,
4542 format_text(bytes, strlen(bytes)));
4543 if (ret >= ITEM_LABEL_LENGTH) {
4544 /* Uh oh, we don't have enough room. Tell the
4545 * user that the field is truncated.
4547 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4548 "%s [truncated]: %s",
4550 format_text(bytes, strlen(bytes)));
4555 g_error("hfinfo->type %d (%s) not handled\n",
4557 ftype_name(hfinfo->type));
4558 DISSECTOR_ASSERT_NOT_REACHED();
4564 fill_label_boolean(field_info *fi, gchar *label_str)
4566 char *p = label_str;
4567 int bitfield_byte_length = 0, bitwidth;
4568 guint32 unshifted_value;
4571 header_field_info *hfinfo = fi->hfinfo;
4572 const true_false_string *tfstring = (const true_false_string *)&tfs_true_false;
4574 if (hfinfo->strings) {
4575 tfstring = (const struct true_false_string*) hfinfo->strings;
4578 value = fvalue_get_uinteger(&fi->value);
4579 if (hfinfo->bitmask) {
4580 /* Figure out the bit width */
4581 bitwidth = hfinfo_bitwidth(hfinfo);
4584 unshifted_value = value;
4585 if (hfinfo->bitshift > 0) {
4586 unshifted_value <<= hfinfo->bitshift;
4589 /* Create the bitfield first */
4590 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
4591 bitfield_byte_length = (int) (p - label_str);
4594 /* Fill in the textual info */
4595 g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
4596 "%s: %s", hfinfo->name,
4597 value ? tfstring->true_string : tfstring->false_string);
4600 /* Fills data for bitfield ints with val_strings */
4602 fill_label_bitfield(field_info *fi, gchar *label_str)
4604 const char *format = NULL;
4606 int bitfield_byte_length, bitwidth;
4607 guint32 unshifted_value;
4610 header_field_info *hfinfo = fi->hfinfo;
4612 /* Figure out the bit width */
4613 bitwidth = hfinfo_bitwidth(hfinfo);
4616 unshifted_value = fvalue_get_uinteger(&fi->value);
4617 value = unshifted_value;
4618 if (hfinfo->bitshift > 0) {
4619 unshifted_value <<= hfinfo->bitshift;
4622 /* Create the bitfield first */
4623 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
4624 bitfield_byte_length = (int) (p - label_str);
4626 /* Fill in the textual info using stored (shifted) value */
4627 if (hfinfo->display == BASE_CUSTOM) {
4628 gchar tmp[ITEM_LABEL_LENGTH];
4629 custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hfinfo->strings;
4631 DISSECTOR_ASSERT(fmtfunc);
4632 fmtfunc(tmp, value);
4633 g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
4634 "%s: %s", hfinfo->name, tmp);
4636 else if (hfinfo->strings) {
4637 format = hfinfo_uint_vals_format(hfinfo);
4638 if (hfinfo->display & BASE_RANGE_STRING) {
4639 g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
4640 format, hfinfo->name,
4641 rval_to_str(value, hfinfo->strings, "Unknown"), value);
4643 g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
4644 format, hfinfo->name,
4645 val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
4649 format = hfinfo_uint_format(hfinfo);
4650 if (IS_BASE_DUAL(hfinfo->display)) {
4651 g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
4652 format, hfinfo->name, value, value);
4654 g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
4655 format, hfinfo->name, value);
4661 fill_label_uint(field_info *fi, gchar *label_str)
4663 const char *format = NULL;
4664 header_field_info *hfinfo = fi->hfinfo;
4667 value = fvalue_get_uinteger(&fi->value);
4669 /* Fill in the textual info */
4670 if (hfinfo->display == BASE_CUSTOM) {
4671 gchar tmp[ITEM_LABEL_LENGTH];
4672 custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hfinfo->strings;
4674 DISSECTOR_ASSERT(fmtfunc);
4675 fmtfunc(tmp, value);
4676 g_snprintf(label_str, ITEM_LABEL_LENGTH, "%s: %s", hfinfo->name, tmp);
4678 else if (hfinfo->strings) {
4679 format = hfinfo_uint_vals_format(hfinfo);
4680 if (hfinfo->display & BASE_RANGE_STRING) {
4681 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4682 format, hfinfo->name,
4683 rval_to_str(value, hfinfo->strings, "Unknown"), value);
4685 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4686 format, hfinfo->name,
4687 val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
4691 format = hfinfo_uint_format(hfinfo);
4692 if (IS_BASE_DUAL(hfinfo->display)) {
4693 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4694 format, hfinfo->name, value, value);
4696 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4697 format, hfinfo->name, value);
4703 fill_label_uint64(field_info *fi, gchar *label_str)
4705 const char *format = NULL;
4706 header_field_info *hfinfo = fi->hfinfo;
4709 /* Pick the proper format string */
4710 format = hfinfo_uint64_format(hfinfo);
4711 value = fvalue_get_integer64(&fi->value);
4713 /* Fill in the textual info */
4714 if (IS_BASE_DUAL(hfinfo->display)) {
4715 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4716 format, hfinfo->name, value, value);
4718 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4719 format, hfinfo->name, value);
4724 fill_label_int(field_info *fi, gchar *label_str)
4726 const char *format = NULL;
4727 header_field_info *hfinfo = fi->hfinfo;
4730 value = fvalue_get_sinteger(&fi->value);
4732 /* Fill in the textual info */
4733 if (hfinfo->display == BASE_CUSTOM) {
4734 gchar tmp[ITEM_LABEL_LENGTH];
4735 custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hfinfo->strings;
4737 DISSECTOR_ASSERT(fmtfunc);
4738 fmtfunc(tmp, value);
4739 g_snprintf(label_str, ITEM_LABEL_LENGTH, "%s: %s", hfinfo->name, tmp);
4741 else if (hfinfo->strings) {
4742 format = hfinfo_int_vals_format(hfinfo);
4743 if (hfinfo->display & BASE_RANGE_STRING) {
4744 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4745 format, hfinfo->name,
4746 rval_to_str(value, hfinfo->strings, "Unknown"), value);
4748 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4749 format, hfinfo->name,
4750 val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
4754 format = hfinfo_int_format(hfinfo);
4755 if (IS_BASE_DUAL(hfinfo->display)) {
4756 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4757 format, hfinfo->name, value, value);
4759 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4760 format, hfinfo->name, value);
4766 fill_label_int64(field_info *fi, gchar *label_str)
4768 const char *format = NULL;
4769 header_field_info *hfinfo = fi->hfinfo;
4772 /* Pick the proper format string */
4773 format = hfinfo_int64_format(hfinfo);
4774 value = fvalue_get_integer64(&fi->value);
4776 /* Fill in the textual info */
4777 if (IS_BASE_DUAL(hfinfo->display)) {
4778 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4779 format, hfinfo->name, value, value);
4781 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4782 format, hfinfo->name, value);
4787 hfinfo_bitwidth(header_field_info *hfinfo)
4791 if (!hfinfo->bitmask) {
4795 switch(hfinfo->type) {
4813 bitwidth = hfinfo->display; /* hacky? :) */
4816 DISSECTOR_ASSERT_NOT_REACHED();
4823 hfinfo_uint_vals_format(header_field_info *hfinfo)
4825 const char *format = NULL;
4827 /* Get the underlying BASE_ value */
4828 switch(hfinfo->display & BASE_DISPLAY_E_MASK) {
4834 format = "%s: %s (%u)";
4836 case BASE_OCT: /* I'm lazy */
4837 format = "%s: %s (%o)";
4841 switch(hfinfo->type) {
4843 format = "%s: %s (0x%02x)";
4846 format = "%s: %s (0x%04x)";
4849 format = "%s: %s (0x%06x)";
4852 format = "%s: %s (0x%08x)";
4855 DISSECTOR_ASSERT_NOT_REACHED();
4860 DISSECTOR_ASSERT_NOT_REACHED();
4867 hfinfo_uint_format(header_field_info *hfinfo)
4869 const char *format = NULL;
4871 /* Pick the proper format string */
4872 if (hfinfo->type == FT_FRAMENUM) {
4874 * Frame numbers are always displayed in decimal.
4878 switch(hfinfo->display) {
4883 switch(hfinfo->type) {
4885 format = "%s: %u (0x%02x)";
4888 format = "%s: %u (0x%04x)";
4891 format = "%s: %u (0x%06x)";
4894 format = "%s: %u (0x%08x)";
4897 DISSECTOR_ASSERT_NOT_REACHED();
4901 case BASE_OCT: /* I'm lazy */
4905 switch(hfinfo->type) {
4907 format = "%s: 0x%02x";
4910 format = "%s: 0x%04x";
4913 format = "%s: 0x%06x";
4916 format = "%s: 0x%08x";
4919 DISSECTOR_ASSERT_NOT_REACHED();
4924 switch(hfinfo->type) {
4926 format = "%s: 0x%02x (%u)";
4929 format = "%s: 0x%04x (%u)";
4932 format = "%s: 0x%06x (%u)";
4935 format = "%s: 0x%08x (%u)";
4938 DISSECTOR_ASSERT_NOT_REACHED();
4943 DISSECTOR_ASSERT_NOT_REACHED();
4951 hfinfo_uint_value_format(header_field_info *hfinfo)
4953 const char *format = NULL;
4955 /* Pick the proper format string */
4956 if (hfinfo->type == FT_FRAMENUM) {
4958 * Frame numbers are always displayed in decimal.
4962 switch(hfinfo->display) {
4967 switch(hfinfo->type) {
4969 format = "%u (0x%02x)";
4972 format = "%u (0x%04x)";
4975 format = "%u (0x%06x)";
4978 format = "%u (0x%08x)";
4981 DISSECTOR_ASSERT_NOT_REACHED();
4989 switch(hfinfo->type) {
5003 DISSECTOR_ASSERT_NOT_REACHED();
5008 switch(hfinfo->type) {
5010 format = "0x%02x (%u)";
5013 format = "0x%04x (%u)";
5016 format = "0x%06x (%u)";
5019 format = "0x%08x (%u)";
5022 DISSECTOR_ASSERT_NOT_REACHED();
5027 DISSECTOR_ASSERT_NOT_REACHED();
5035 hfinfo_int_vals_format(header_field_info *hfinfo)
5037 const char *format = NULL;
5039 /* Get the underlying BASE_ value */
5040 switch(hfinfo->display & BASE_DISPLAY_E_MASK) {
5046 format = "%s: %s (%d)";
5048 case BASE_OCT: /* I'm lazy */
5049 format = "%s: %s (%o)";
5053 switch(hfinfo->type) {
5055 format = "%s: %s (0x%02x)";
5058 format = "%s: %s (0x%04x)";
5061 format = "%s: %s (0x%06x)";
5064 format = "%s: %s (0x%08x)";
5067 DISSECTOR_ASSERT_NOT_REACHED();
5072 DISSECTOR_ASSERT_NOT_REACHED();
5079 hfinfo_uint64_format(header_field_info *hfinfo)
5081 const char *format = NULL;
5083 /* Pick the proper format string */
5084 switch(hfinfo->display) {
5086 format = "%s: %" G_GINT64_MODIFIER "u";
5089 format = "%s: %" G_GINT64_MODIFIER "u (%" G_GINT64_MODIFIER "x)";
5091 case BASE_OCT: /* I'm lazy */
5092 format = "%s: %" G_GINT64_MODIFIER "o";
5095 format = "%s: 0x%016" G_GINT64_MODIFIER "x";
5098 format = "%s: 0x%016" G_GINT64_MODIFIER "x (%" G_GINT64_MODIFIER "u)";
5101 DISSECTOR_ASSERT_NOT_REACHED();
5108 hfinfo_int_format(header_field_info *hfinfo)
5110 const char *format = NULL;
5112 /* Pick the proper format string */
5113 switch(hfinfo->display) {
5118 switch(hfinfo->type) {
5120 format = "%s: %d (0x%02x)";
5123 format = "%s: %d (0x%04x)";
5126 format = "%s: %d (0x%06x)";
5129 format = "%s: %d (0x%08x)";
5132 DISSECTOR_ASSERT_NOT_REACHED();
5136 case BASE_OCT: /* I'm lazy */
5140 switch(hfinfo->type) {
5142 format = "%s: 0x%02x";
5145 format = "%s: 0x%04x";
5148 format = "%s: 0x%06x";
5151 format = "%s: 0x%08x";
5154 DISSECTOR_ASSERT_NOT_REACHED();
5159 switch(hfinfo->type) {
5161 format = "%s: 0x%02x (%d)";
5164 format = "%s: 0x%04x (%d)";
5167 format = "%s: 0x%06x (%d)";
5170 format = "%s: 0x%08x (%d)";
5173 DISSECTOR_ASSERT_NOT_REACHED();
5178 DISSECTOR_ASSERT_NOT_REACHED();
5185 hfinfo_int_value_format(header_field_info *hfinfo)
5187 const char *format = NULL;
5189 /* Pick the proper format string */
5190 switch(hfinfo->display) {
5195 switch(hfinfo->type) {
5197 format = "%d (0x%02x)";
5200 format = "%d (0x%04x)";
5203 format = "%d (0x%06x)";
5206 format = "%d (0x%08x)";
5209 DISSECTOR_ASSERT_NOT_REACHED();
5217 switch(hfinfo->type) {
5231 DISSECTOR_ASSERT_NOT_REACHED();
5236 switch(hfinfo->type) {
5238 format = "0x%02x (%d)";
5241 format = "0x%04x (%d)";
5244 format = "0x%06x (%d)";
5247 format = "0x%08x (%d)";
5250 DISSECTOR_ASSERT_NOT_REACHED();
5255 DISSECTOR_ASSERT_NOT_REACHED();
5262 hfinfo_int64_format(header_field_info *hfinfo)
5264 const char *format = NULL;
5266 /* Pick the proper format string */
5267 switch(hfinfo->display) {
5269 format = "%s: %" G_GINT64_MODIFIER "d";
5272 format = "%s: %" G_GINT64_MODIFIER "d (%" G_GINT64_MODIFIER "x)";
5274 case BASE_OCT: /* I'm lazy */
5275 format = "%s: %" G_GINT64_MODIFIER "o";
5278 format = "%s: 0x%016" G_GINT64_MODIFIER "x";
5281 format = "%s: 0x%016" G_GINT64_MODIFIER "x (%" G_GINT64_MODIFIER "d)";
5284 DISSECTOR_ASSERT_NOT_REACHED();
5291 proto_registrar_n(void)
5293 return gpa_hfinfo.len;
5297 proto_registrar_get_name(int n)
5299 header_field_info *hfinfo;
5301 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
5302 return hfinfo->name;
5306 proto_registrar_get_abbrev(int n)
5308 header_field_info *hfinfo;
5310 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
5311 return hfinfo->abbrev;
5315 proto_registrar_get_ftype(int n)
5317 header_field_info *hfinfo;
5319 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
5320 return hfinfo->type;
5324 proto_registrar_get_parent(int n)
5326 header_field_info *hfinfo;
5328 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
5329 return hfinfo->parent;
5333 proto_registrar_is_protocol(int n)
5335 header_field_info *hfinfo;
5337 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
5338 return (hfinfo->parent == -1 ? TRUE : FALSE);
5341 /* Returns length of field in packet (not necessarily the length
5342 * in our internal representation, as in the case of IPv4).
5343 * 0 means undeterminable at time of registration
5344 * -1 means the field is not registered. */
5346 proto_registrar_get_length(int n)
5348 header_field_info *hfinfo;
5350 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
5351 return ftype_length(hfinfo->type);
5354 /* Looks for a protocol or a field in a proto_tree. Returns TRUE if
5355 * it exists anywhere, or FALSE if it exists nowhere. */
5357 proto_check_for_protocol_or_field(proto_tree* tree, int id)
5359 GPtrArray *ptrs = proto_get_finfo_ptr_array(tree, id);
5364 else if (g_ptr_array_len(ptrs) > 0) {
5372 /* Return GPtrArray* of field_info pointers for all hfindex that appear in tree.
5373 * This only works if the hfindex was "primed" before the dissection
5374 * took place, as we just pass back the already-created GPtrArray*.
5375 * The caller should *not* free the GPtrArray*; proto_tree_free_node()
5378 proto_get_finfo_ptr_array(proto_tree *tree, int id)
5383 if (PTREE_DATA(tree)->interesting_hfids != NULL)
5384 return g_hash_table_lookup(PTREE_DATA(tree)->interesting_hfids,
5385 GINT_TO_POINTER(id));
5391 proto_tracking_interesting_fields(proto_tree *tree)
5396 return (PTREE_DATA(tree)->interesting_hfids != NULL);
5399 /* Helper struct for proto_find_info() and proto_all_finfos() */
5405 /* Helper function for proto_find_info() */
5407 find_finfo(proto_node *node, gpointer data)
5409 field_info *fi = PNODE_FINFO(node);
5410 if (fi && fi->hfinfo) {
5411 if (fi->hfinfo->id == ((ffdata_t*)data)->id) {
5412 g_ptr_array_add(((ffdata_t*)data)->array, fi);
5416 /* Don't stop traversing. */
5420 /* Return GPtrArray* of field_info pointers for all hfindex that appear in a tree.
5421 * This works on any proto_tree, primed or unprimed, but actually searches
5422 * the tree, so it is slower than using proto_get_finfo_ptr_array on a primed tree.
5423 * The caller does need to free the returned GPtrArray with
5424 * g_ptr_array_free(<array>, TRUE).
5427 proto_find_finfo(proto_tree *tree, int id)
5431 ffdata.array = g_ptr_array_new();
5434 proto_tree_traverse_pre_order(tree, find_finfo, &ffdata);
5436 return ffdata.array;
5439 /* Helper function for proto_all_finfos() */
5441 every_finfo(proto_node *node, gpointer data)
5443 field_info *fi = PNODE_FINFO(node);
5444 if (fi && fi->hfinfo) {
5445 g_ptr_array_add(((ffdata_t*)data)->array, fi);
5448 /* Don't stop traversing. */
5452 /* Return GPtrArray* of field_info pointers containing all hfindexes that appear in a tree. */
5454 proto_all_finfos(proto_tree *tree)
5458 ffdata.array = g_ptr_array_new();
5461 proto_tree_traverse_pre_order(tree, every_finfo, &ffdata);
5463 return ffdata.array;
5474 check_for_offset(proto_node *node, gpointer data)
5476 field_info *fi = PNODE_FINFO(node);
5477 offset_search_t *offsearch = data;
5479 /* !fi == the top most container node which holds nothing */
5480 if (fi && !PROTO_ITEM_IS_HIDDEN(node) && fi->ds_tvb && offsearch->tvb == fi->ds_tvb) {
5481 if (offsearch->offset >= (guint) fi->start &&
5482 offsearch->offset < (guint) (fi->start + fi->length)) {
5484 offsearch->finfo = fi;
5485 return FALSE; /* keep traversing */
5488 return FALSE; /* keep traversing */
5491 /* Search a proto_tree backwards (from leaves to root) looking for the field
5492 * whose start/length occupies 'offset' */
5493 /* XXX - I couldn't find an easy way to search backwards, so I search
5494 * forwards, w/o stopping. Therefore, the last finfo I find will the be
5495 * the one I want to return to the user. This algorithm is inefficient
5496 * and could be re-done, but I'd have to handle all the children and
5497 * siblings of each node myself. When I have more time I'll do that.
5500 proto_find_field_from_offset(proto_tree *tree, guint offset, tvbuff_t *tvb)
5502 offset_search_t offsearch;
5504 offsearch.offset = offset;
5505 offsearch.finfo = NULL;
5506 offsearch.tvb = tvb;
5508 proto_tree_traverse_pre_order(tree, check_for_offset, &offsearch);
5510 return offsearch.finfo;
5513 /* Dumps the protocols in the registration database to stdout. An independent
5514 * program can take this output and format it into nice tables or HTML or
5517 * There is one record per line. The fields are tab-delimited.
5519 * Field 1 = protocol name
5520 * Field 2 = protocol short name
5521 * Field 3 = protocol filter name
5524 proto_registrar_dump_protocols(void)
5526 protocol_t *protocol;
5528 void *cookie = NULL;
5530 for (i = proto_get_first_protocol(&cookie); i != -1;
5531 i = proto_get_next_protocol(&cookie)) {
5532 protocol = find_protocol_by_id(i);
5533 printf("%s\t%s\t%s\n", protocol->name, protocol->short_name,
5534 protocol->filter_name);
5538 /* Dumps the value_strings, range_strings or true/false strings for fields
5539 * that have them. There is one record per line. Fields are tab-delimited.
5540 * There are three types of records: Value String, Range String
5541 * and True/False String. The first field, 'V', 'R' or 'T', indicates
5542 * the type of record.
5547 * Field 2 = field abbreviation to which this value string corresponds
5548 * Field 3 = Integer value
5554 * Field 2 = field abbreviation to which this range string corresponds
5555 * Field 3 = Integer value: lower bound
5556 * Field 4 = Integer value: upper bound
5559 * True/False Strings
5560 * ------------------
5562 * Field 2 = field abbreviation to which this true/false string corresponds
5563 * Field 3 = True String
5564 * Field 4 = False String
5567 proto_registrar_dump_values(void)
5569 header_field_info *hfinfo, *parent_hfinfo;
5571 const value_string *vals;
5572 const range_string *range;
5573 const true_false_string *tfs;
5575 len = gpa_hfinfo.len;
5576 for (i = 0; i < len ; i++) {
5577 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
5579 if (hfinfo->id == hf_text_only) {
5583 /* ignore protocols */
5584 if (proto_registrar_is_protocol(i)) {
5587 /* process header fields */
5590 * If this field isn't at the head of the list of
5591 * fields with this name, skip this field - all
5592 * fields with the same name are really just versions
5593 * of the same field stored in different bits, and
5594 * should have the same type/radix/value list, and
5595 * just differ in their bit masks. (If a field isn't
5596 * a bitfield, but can be, say, 1 or 2 bytes long,
5597 * it can just be made FT_UINT16, meaning the
5598 * *maximum* length is 2 bytes, and be used
5601 if (hfinfo->same_name_prev != NULL)
5604 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
5610 if ((hfinfo->display & BASE_DISPLAY_E_MASK) != BASE_CUSTOM &&
5611 (hfinfo->type == FT_UINT8 ||
5612 hfinfo->type == FT_UINT16 ||
5613 hfinfo->type == FT_UINT24 ||
5614 hfinfo->type == FT_UINT32 ||
5615 hfinfo->type == FT_UINT64 ||
5616 hfinfo->type == FT_INT8 ||
5617 hfinfo->type == FT_INT16 ||
5618 hfinfo->type == FT_INT24 ||
5619 hfinfo->type == FT_INT32 ||
5620 hfinfo->type == FT_INT64)) {
5622 if ((hfinfo->display & BASE_RANGE_STRING) == 0) {
5623 vals = hfinfo->strings;
5625 range = hfinfo->strings;
5628 else if (hfinfo->type == FT_BOOLEAN) {
5629 tfs = hfinfo->strings;
5632 /* Print value strings? */
5635 while (vals[vi].strptr) {
5636 /* Print in the proper base */
5637 if (hfinfo->display == BASE_HEX) {
5638 printf("V\t%s\t0x%x\t%s\n",
5644 printf("V\t%s\t%u\t%s\n",
5653 /* print range strings? */
5656 while (range[vi].strptr) {
5657 /* Print in the proper base */
5658 if ((hfinfo->display & BASE_DISPLAY_E_MASK) == BASE_HEX) {
5659 printf("R\t%s\t0x%x\t0x%x\t%s\n",
5661 range[vi].value_min,
5662 range[vi].value_max,
5666 printf("R\t%s\t%u\t%u\t%s\n",
5668 range[vi].value_min,
5669 range[vi].value_max,
5676 /* Print true/false strings? */
5678 printf("T\t%s\t%s\t%s\n", hfinfo->abbrev,
5679 tfs->true_string, tfs->false_string);
5685 /* Dumps the contents of the registration database to stdout. An independent
5686 * program can take this output and format it into nice tables or HTML or
5689 * There is one record per line. Each record is either a protocol or a header
5690 * field, differentiated by the first field. The fields are tab-delimited.
5695 * Field 2 = descriptive protocol name
5696 * Field 3 = protocol abbreviation
5702 * Field 2 = descriptive field name
5703 * Field 3 = field abbreviation
5704 * Field 4 = type ( textual representation of the the ftenum type )
5705 * Field 5 = parent protocol abbreviation
5706 * Field 6 = blurb describing field
5710 * Field 2 = descriptive field name
5711 * Field 3 = field abbreviation
5712 * Field 4 = type ( textual representation of the the ftenum type )
5713 * Field 5 = parent protocol abbreviation
5714 * Field 6 = blurb describing field
5715 * Field 7 = base for display (for integer types); "parent bitfield width" for FT_BOOLEAN
5716 * Field 8 = blurb describing field (yes, apparently we repeated this accidentally)
5720 * Field 2 = descriptive field name
5721 * Field 3 = field abbreviation
5722 * Field 4 = type ( textual representation of the the ftenum type )
5723 * Field 5 = parent protocol abbreviation
5724 * Field 6 = blurb describing field
5725 * Field 7 = base for display (for integer types); "parent bitfield width" for FT_BOOLEAN
5726 * Field 8 = bitmask: format: hex: 0x....
5729 proto_registrar_dump_fields(int format)
5731 header_field_info *hfinfo, *parent_hfinfo;
5733 const char *enum_name;
5734 const char *base_name;
5738 len = gpa_hfinfo.len;
5739 for (i = 0; i < len ; i++) {
5740 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
5743 * Skip the pseudo-field for "proto_tree_add_text()" since
5744 * we don't want it in the list of filterable fields.
5746 if (hfinfo->id == hf_text_only)
5749 /* format for protocols */
5750 if (proto_registrar_is_protocol(i)) {
5751 printf("P\t%s\t%s\n", hfinfo->name, hfinfo->abbrev);
5753 /* format for header fields */
5756 * If this field isn't at the head of the list of
5757 * fields with this name, skip this field - all
5758 * fields with the same name are really just versions
5759 * of the same field stored in different bits, and
5760 * should have the same type/radix/value list, and
5761 * just differ in their bit masks. (If a field isn't
5762 * a bitfield, but can be, say, 1 or 2 bytes long,
5763 * it can just be made FT_UINT16, meaning the
5764 * *maximum* length is 2 bytes, and be used
5767 if (hfinfo->same_name_prev != NULL)
5770 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
5772 enum_name = ftype_name(hfinfo->type);
5776 if (hfinfo->type == FT_UINT8 ||
5777 hfinfo->type == FT_UINT16 ||
5778 hfinfo->type == FT_UINT24 ||
5779 hfinfo->type == FT_UINT32 ||
5780 hfinfo->type == FT_UINT64 ||
5781 hfinfo->type == FT_INT8 ||
5782 hfinfo->type == FT_INT16 ||
5783 hfinfo->type == FT_INT24 ||
5784 hfinfo->type == FT_INT32 ||
5785 hfinfo->type == FT_INT64) {
5788 switch(hfinfo->display & BASE_DISPLAY_E_MASK) {
5790 base_name = "BASE_NONE";
5793 base_name = "BASE_DEC";
5796 base_name = "BASE_HEX";
5799 base_name = "BASE_OCT";
5802 base_name = "BASE_DEC_HEX";
5805 base_name = "BASE_HEX_DEC";
5808 base_name = "BASE_CUSTOM";
5814 } else if (hfinfo->type == FT_BOOLEAN) {
5815 /* For FT_BOOLEAN: 'display' can be "parent bitfield width" */
5816 g_snprintf(width, sizeof(width), "%d", hfinfo->display);
5821 blurb = hfinfo->blurb;
5825 printf("F\t%s\t%s\t%s\t%s\t%s\n",
5826 hfinfo->name, hfinfo->abbrev, enum_name,
5827 parent_hfinfo->abbrev, blurb);
5829 else if (format == 2) {
5830 printf("F\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n",
5831 hfinfo->name, hfinfo->abbrev, enum_name,
5832 parent_hfinfo->abbrev, blurb,
5835 else if (format == 3) {
5836 printf("F\t%s\t%s\t%s\t%s\t%s\t%s\t0x%x\n",
5837 hfinfo->name, hfinfo->abbrev, enum_name,
5838 parent_hfinfo->abbrev, blurb,
5839 base_name, hfinfo->bitmask);
5842 g_assert_not_reached();
5849 hfinfo_numeric_format(header_field_info *hfinfo)
5851 const char *format = NULL;
5853 /* Pick the proper format string */
5854 if (hfinfo->type == FT_FRAMENUM) {
5856 * Frame numbers are always displayed in decimal.
5858 format = "%s == %u";
5860 /* Get the underlying BASE_ value */
5861 switch(hfinfo->display & BASE_DISPLAY_E_MASK) {
5864 case BASE_OCT: /* I'm lazy */
5866 switch(hfinfo->type) {
5871 format = "%s == %u";
5874 format = "%s == %" G_GINT64_MODIFIER "u";
5880 format = "%s == %d";
5883 format = "%s == %" G_GINT64_MODIFIER "d";
5886 DISSECTOR_ASSERT_NOT_REACHED();
5892 switch(hfinfo->type) {
5894 format = "%s == 0x%02x";
5897 format = "%s == 0x%04x";
5900 format = "%s == 0x%06x";
5903 format = "%s == 0x%08x";
5906 format = "%s == 0x%016" G_GINT64_MODIFIER "x";
5909 DISSECTOR_ASSERT_NOT_REACHED();
5914 DISSECTOR_ASSERT_NOT_REACHED();
5921 /* This function indicates whether it's possible to construct a
5922 * "match selected" display filter string for the specified field,
5923 * returns an indication of whether it's possible, and, if it's
5924 * possible and "filter" is non-null, constructs the filter and
5925 * sets "*filter" to point to it.
5926 * You do not need to [g_]free() this string since it will be automatically
5927 * freed once the next packet is dissected.
5930 construct_match_selected_string(field_info *finfo, epan_dissect_t *edt,
5933 header_field_info *hfinfo;
5939 gint start, length, length_remaining;
5941 gchar is_signed_num = FALSE;
5943 hfinfo = finfo->hfinfo;
5944 DISSECTOR_ASSERT(hfinfo);
5945 abbrev_len = (int) strlen(hfinfo->abbrev);
5947 if (hfinfo->strings && (hfinfo->display & BASE_DISPLAY_E_MASK) == BASE_NONE) {
5948 const gchar *str = NULL;
5950 switch(hfinfo->type) {
5956 if (hfinfo->display & BASE_RANGE_STRING) {
5957 str = match_strrval(fvalue_get_sinteger(&finfo->value), hfinfo->strings);
5959 str = match_strval(fvalue_get_sinteger(&finfo->value), hfinfo->strings);
5967 if (hfinfo->display & BASE_RANGE_STRING) {
5968 str = match_strrval(fvalue_get_uinteger(&finfo->value), hfinfo->strings);
5970 str = match_strval(fvalue_get_uinteger(&finfo->value), hfinfo->strings);
5978 if (str != NULL && filter != NULL) {
5979 *filter = ep_strdup_printf("%s == \"%s\"", hfinfo->abbrev, str);
5985 * XXX - we can't use the "val_to_string_repr" and "string_repr_len"
5986 * functions for FT_UINT and FT_INT types, as we choose the base in
5987 * the string expression based on the display base of the field.
5989 * Note that the base does matter, as this is also used for
5990 * the protocolinfo tap.
5992 * It might be nice to use them in "proto_item_fill_label()"
5993 * as well, although, there, you'd have to deal with the base
5994 * *and* with resolved values for addresses.
5996 * Perhaps we need two different val_to_string routines, one
5997 * to generate items for display filters and one to generate
5998 * strings for display, and pass to both of them the
5999 * "display" and "strings" values in the header_field_info
6000 * structure for the field, so they can get the base and,
6001 * if the field is Boolean or an enumerated integer type,
6002 * the tables used to generate human-readable values.
6004 switch(hfinfo->type) {
6010 is_signed_num = TRUE;
6015 if (filter != NULL) {
6016 format = hfinfo_numeric_format(hfinfo);
6018 *filter = ep_strdup_printf(format,
6020 fvalue_get_sinteger(&finfo->value));
6022 *filter = ep_strdup_printf(format,
6024 fvalue_get_uinteger(&finfo->value));
6030 DISSECTOR_ASSERT(!is_signed_num);
6031 if (filter != NULL) {
6032 format = hfinfo_numeric_format(hfinfo);
6033 *filter = ep_strdup_printf(format,
6035 fvalue_get_uinteger(&finfo->value));
6041 if (filter != NULL) {
6042 format = hfinfo_numeric_format(hfinfo);
6043 *filter = ep_strdup_printf(format,
6045 fvalue_get_integer64(&finfo->value));
6051 *filter = ep_strdup(finfo->hfinfo->abbrev);
6056 * If the length is 0, just match the name of the
6059 * (Also check for negative values, just in case,
6060 * as we'll cast it to an unsigned value later.)
6062 length = finfo->length;
6065 *filter = ep_strdup(finfo->hfinfo->abbrev);
6072 * This doesn't have a value, so we'd match
6073 * on the raw bytes at this address.
6075 * Should we be allowed to access to the raw bytes?
6076 * If "edt" is NULL, the answer is "no".
6082 * Is this field part of the raw frame tvbuff?
6083 * If not, we can't use "frame[N:M]" to match
6086 * XXX - should this be frame-relative, or
6087 * protocol-relative?
6089 * XXX - does this fallback for non-registered
6090 * fields even make sense?
6092 if (finfo->ds_tvb != edt->tvb)
6093 return FALSE; /* you lose */
6096 * Don't go past the end of that tvbuff.
6098 length_remaining = tvb_length_remaining(finfo->ds_tvb, finfo->start);
6099 if (length > length_remaining)
6100 length = length_remaining;
6104 if (filter != NULL) {
6105 start = finfo->start;
6106 buf_len = 32 + length * 3;
6107 *filter = ep_alloc0(buf_len);
6110 ptr += g_snprintf(ptr, (gulong) (buf_len-(ptr-*filter)),
6111 "frame[%d:%d] == ", finfo->start, length);
6112 for (i=0;i<length; i++) {
6113 c = tvb_get_guint8(finfo->ds_tvb, start);
6116 ptr += g_snprintf(ptr, (gulong) (buf_len-(ptr-*filter)), "%02x", c);
6119 ptr += g_snprintf(ptr, (gulong) (buf_len-(ptr-*filter)), ":%02x", c);
6126 /* FT_PCRE never appears as a type for a registered field. It is
6127 * only used internally. */
6128 DISSECTOR_ASSERT_NOT_REACHED();
6131 /* By default, use the fvalue's "to_string_repr" method. */
6133 /* Figure out the string length needed.
6134 * The ft_repr length.
6135 * 4 bytes for " == ".
6136 * 1 byte for trailing NUL.
6138 if (filter != NULL) {
6139 dfilter_len = fvalue_string_repr_len(&finfo->value,
6141 dfilter_len += abbrev_len + 4 + 1;
6142 *filter = ep_alloc0(dfilter_len);
6144 /* Create the string */
6145 g_snprintf(*filter, dfilter_len, "%s == ",
6147 fvalue_to_string_repr(&finfo->value,
6149 &(*filter)[abbrev_len + 4]);
6158 * Returns TRUE if we can do a "match selected" on the field, FALSE
6162 proto_can_match_selected(field_info *finfo, epan_dissect_t *edt)
6164 return construct_match_selected_string(finfo, edt, NULL);
6167 /* This function attempts to construct a "match selected" display filter
6168 * string for the specified field; if it can do so, it returns a pointer
6169 * to the string, otherwise it returns NULL.
6171 * The string is allocated with packet lifetime scope.
6172 * You do not need to [g_]free() this string since it will be automatically
6173 * freed once the next packet is dissected.
6176 proto_construct_match_selected_string(field_info *finfo, epan_dissect_t *edt)
6180 if (!construct_match_selected_string(finfo, edt, &filter))
6185 /* This function is common code for both proto_tree_add_bitmask() and
6186 * proto_tree_add_bitmask_text() functions.
6189 proto_item_add_bitmask_tree(proto_item *item, tvbuff_t *tvb, int offset, int len, gint ett,
6190 const int **fields, gboolean little_endian, int flags, gboolean first)
6192 guint32 value = 0, tmpval;
6193 proto_tree *tree = NULL;
6194 header_field_info *hf;
6199 value = tvb_get_guint8(tvb, offset);
6202 value = little_endian ? tvb_get_letohs(tvb, offset) :
6203 tvb_get_ntohs(tvb, offset);
6206 value = little_endian ? tvb_get_letoh24(tvb, offset) :
6207 tvb_get_ntoh24(tvb, offset);
6210 value = little_endian ? tvb_get_letohl(tvb, offset) :
6211 tvb_get_ntohl(tvb, offset);
6214 g_assert_not_reached();
6217 tree = proto_item_add_subtree(item, ett);
6219 proto_tree_add_item(tree, **fields, tvb, offset, len, little_endian);
6220 if (flags & BMT_NO_APPEND) {
6224 hf = proto_registrar_get_nth(**fields);
6225 DISSECTOR_ASSERT(hf->bitmask != 0);
6226 tmpval = (value & hf->bitmask) >> hf->bitshift;
6237 DISSECTOR_ASSERT(len == ftype_length(hf->type));
6239 if (hf->display == BASE_CUSTOM) {
6240 gchar lbl[ITEM_LABEL_LENGTH];
6241 custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hf->strings;
6243 DISSECTOR_ASSERT(fmtfunc);
6244 fmtfunc(lbl, tmpval);
6245 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
6249 else if (hf->strings) {
6250 if (hf->display & BASE_RANGE_STRING) {
6251 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
6252 hf->name, rval_to_str(tmpval, hf->strings, "Unknown"));
6254 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
6255 hf->name, val_to_str(tmpval, cVALS(hf->strings), "Unknown"));
6259 else if (!(flags & BMT_NO_INT)) {
6261 proto_item_append_text(item, ", ");
6264 fmt = IS_FT_INT(hf->type) ? hfinfo_int_format(hf) : hfinfo_uint_format(hf);
6265 if (IS_BASE_DUAL(hf->display)) {
6266 proto_item_append_text(item, fmt, hf->name, tmpval, tmpval);
6268 proto_item_append_text(item, fmt, hf->name, tmpval);
6275 DISSECTOR_ASSERT(len * 8 == hf->display);
6277 if (hf->strings && !(flags & BMT_NO_TFS)) {
6278 /* If we have true/false strings, emit full - otherwise messages
6280 const struct true_false_string *tfs =
6281 (const struct true_false_string *)hf->strings;
6284 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
6285 hf->name, tfs->true_string);
6287 } else if (!(flags & BMT_NO_FALSE)) {
6288 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
6289 hf->name, tfs->false_string);
6292 } else if (hf->bitmask & value) {
6293 /* If the flag is set, show the name */
6294 proto_item_append_text(item, "%s%s", first ? "" : ", ", hf->name);
6299 g_assert_not_reached();
6308 /* This function will dissect a sequence of bytes that describe a
6310 * hf_hdr is a 8/16/24/32 bit integer that describes the bitmask to be dissected.
6311 * This field will form an expansion under which the individual fields of the
6312 * bitmask is dissected and displayed.
6313 * This field must be of the type FT_[U]INT{8|16|24|32}.
6315 * fields is an array of pointers to int that lists all the fields of the
6316 * bitmask. These fields can be either of the type FT_BOOLEAN for flags
6317 * or another integer of the same type/size as hf_hdr with a mask specified.
6318 * This array is terminated by a NULL entry.
6320 * FT_BOOLEAN bits that are set to 1 will have the name added to the expansion.
6321 * FT_integer fields that have a value_string attached will have the
6322 * matched string displayed on the expansion line.
6325 proto_tree_add_bitmask(proto_tree *parent_tree, tvbuff_t *tvb, guint offset, int hf_hdr,
6326 gint ett, const int **fields, gboolean little_endian)
6328 proto_item *item = NULL;
6329 header_field_info *hf;
6332 hf = proto_registrar_get_nth(hf_hdr);
6333 DISSECTOR_ASSERT(IS_FT_INT(hf->type) || IS_FT_UINT(hf->type));
6334 len = ftype_length(hf->type);
6337 item = proto_tree_add_item(parent_tree, hf_hdr, tvb, offset, len, little_endian);
6338 proto_item_add_bitmask_tree(item, tvb, offset, len, ett, fields, little_endian,
6339 BMT_NO_INT|BMT_NO_TFS, FALSE);
6345 /* The same as proto_tree_add_bitmask(), but using an arbitrary text as a top-level item */
6347 proto_tree_add_bitmask_text(proto_tree *parent_tree, tvbuff_t *tvb, guint offset, guint len,
6348 const char *name, const char *fallback,
6349 gint ett, const int **fields, gboolean little_endian, int flags)
6351 proto_item *item = NULL;
6354 item = proto_tree_add_text(parent_tree, tvb, offset, len, "%s", name ? name : "");
6355 if (proto_item_add_bitmask_tree(item, tvb, offset, len, ett, fields, little_endian,
6356 flags, TRUE) && fallback) {
6357 /* Still at first item - append 'fallback' text if any */
6358 proto_item_append_text(item, "%s", fallback);
6366 proto_tree_add_bits_item(proto_tree *tree, int hf_index, tvbuff_t *tvb, gint bit_offset, gint no_of_bits, gboolean little_endian)
6368 header_field_info *hfinfo;
6370 TRY_TO_FAKE_THIS_ITEM(tree, hf_index, hfinfo);
6372 return proto_tree_add_bits_ret_val(tree, hf_index, tvb, bit_offset, no_of_bits, NULL, little_endian);
6376 * This function will prepare a string showing how a certain value is broken down
6377 * in bits and also which parts of an octet are used. E.g. '..11 100.'
6380 prepare_bits_string(guint64 value, gint bit_offset, gint no_of_bits)
6387 mask = mask << (no_of_bits-1);
6389 /* prepare the string */
6392 for(bit=0;bit<((int)(bit_offset&0x07));bit++){
6393 if(bit&&(!(bit%4))){
6399 /* read the bits for the int */
6400 for(i=0;i<no_of_bits;i++){
6401 if(bit&&(!(bit%4))){
6404 if(bit&&(!(bit%8))){
6418 if(bit&&(!(bit%4))){
6428 * This function will dissect a sequence of bits that does not need to be byte aligned; the bits
6429 * set will be shown in the tree as ..10 10.. and the integer value returned if return_value is set.
6430 * Offset should be given in bits from the start of the tvb.
6434 proto_tree_add_bits_ret_val(proto_tree *tree, int hf_index, tvbuff_t *tvb, gint bit_offset, gint no_of_bits, guint64 *return_value, gboolean little_endian)
6436 const char *format = NULL;
6440 guint8 remaining_bits;
6442 header_field_info *hf_field;
6444 const true_false_string *tfstring;
6446 /* We can't fake it just yet. We have to fill in the 'return_value' parameter */
6447 PROTO_REGISTRAR_GET_NTH(hf_index, hf_field);
6449 if(hf_field -> bitmask != 0) {
6450 REPORT_DISSECTOR_BUG(ep_strdup_printf("Incompatible use of proto_tree_add_bits_ret_val with field '%s' (%s) with bitmask != 0",
6451 hf_field->abbrev, hf_field->name));
6454 DISSECTOR_ASSERT(bit_offset >= 0);
6455 DISSECTOR_ASSERT(no_of_bits > 0);
6457 /* Byte align offset */
6458 offset = bit_offset>>3;
6461 * Calculate the number of octets used to hold the bits
6463 tot_no_bits = ((bit_offset&0x7)+no_of_bits);
6464 length = tot_no_bits>>3;
6465 remaining_bits = tot_no_bits % 8;
6466 if ((remaining_bits)!=0)
6469 if (no_of_bits < 9){
6470 value = tvb_get_bits8(tvb, bit_offset, no_of_bits);
6471 }else if(no_of_bits < 17){
6472 value = tvb_get_bits16(tvb, bit_offset, no_of_bits, little_endian);
6473 }else if(no_of_bits < 33){
6474 value = tvb_get_bits32(tvb, bit_offset, no_of_bits, little_endian);
6475 }else if(no_of_bits < 65){
6476 value = tvb_get_bits64(tvb, bit_offset, no_of_bits, little_endian);
6478 DISSECTOR_ASSERT_NOT_REACHED();
6483 *return_value=value;
6486 /* Coast clear. Try and fake it */
6487 TRY_TO_FAKE_THIS_ITEM(tree, hf_index, hf_field);
6489 str = prepare_bits_string(value, bit_offset, no_of_bits);
6492 strcat(str,hf_field->name);
6494 switch(hf_field->type){
6497 tfstring = (const true_false_string *) &tfs_true_false;
6498 if (hf_field->strings)
6499 tfstring = (const true_false_string *) hf_field->strings;
6500 return proto_tree_add_boolean_format(tree, hf_index, tvb, offset, length, (guint32)value,
6503 (guint32)value ? tfstring->true_string : tfstring->false_string);
6510 /* 1 - 32 bits field */
6511 if (hf_field->strings) {
6512 return proto_tree_add_uint_format(tree, hf_index, tvb, offset, length, (guint32)value,
6514 str, (hf_field->display & BASE_RANGE_STRING) ?
6515 rval_to_str((guint32)value, hf_field->strings, "Unknown ") :
6516 val_to_str((guint32)value, cVALS(hf_field->strings), "Unknown "),
6520 /* Pick the proper format string */
6521 format = hfinfo_uint_format(hf_field);
6522 if (IS_BASE_DUAL(hf_field->display)) {
6523 return proto_tree_add_uint_format(tree, hf_index, tvb, offset, length, (guint32)value,
6524 format, str, (guint32)value, (guint32)value);
6526 return proto_tree_add_uint_format(tree, hf_index, tvb, offset, length, (guint32)value,
6527 format, str, (guint32)value);
6532 /* Pick the proper format string */
6533 format = hfinfo_uint64_format(hf_field);
6534 if (IS_BASE_DUAL(hf_field->display)) {
6535 return proto_tree_add_uint64_format(tree, hf_index, tvb, offset, length, value,
6536 format, str, value, value);
6538 return proto_tree_add_uint64_format(tree, hf_index, tvb, offset, length, value,
6539 format, str, value);
6544 DISSECTOR_ASSERT_NOT_REACHED();
6551 proto_tree_add_bits_format_value(proto_tree *tree, int hf_index, tvbuff_t *tvb, gint bit_offset, gint no_of_bits, void *value_ptr, gchar *value_str)
6556 guint8 remaining_bits;
6558 header_field_info *hf_field;
6561 /* We do not have to return a value, try to fake it as soon as possible */
6562 TRY_TO_FAKE_THIS_ITEM(tree, hf_index, hf_field);
6564 if(hf_field -> bitmask != 0) {
6565 REPORT_DISSECTOR_BUG(ep_strdup_printf("Incompatible use of proto_tree_add_bits_ret_val with field '%s' (%s) with bitmask != 0",
6566 hf_field->abbrev, hf_field->name));
6569 DISSECTOR_ASSERT(bit_offset >= 0);
6570 DISSECTOR_ASSERT(no_of_bits > 0);
6572 /* Byte align offset */
6573 offset = bit_offset>>3;
6576 * Calculate the number of octets used to hold the bits
6578 tot_no_bits = ((bit_offset&0x7)+no_of_bits);
6579 length = tot_no_bits>>3;
6580 remaining_bits = tot_no_bits % 8;
6581 if ((remaining_bits)!=0)
6584 if (no_of_bits < 9){
6585 value = tvb_get_bits8(tvb, bit_offset, no_of_bits);
6586 }else if(no_of_bits < 17){
6587 value = tvb_get_bits16(tvb, bit_offset, no_of_bits, FALSE);
6588 }else if(no_of_bits < 33){
6589 value = tvb_get_bits32(tvb, bit_offset, no_of_bits, FALSE);
6590 }else if(no_of_bits < 65){
6591 value = tvb_get_bits64(tvb, bit_offset, no_of_bits, FALSE);
6593 DISSECTOR_ASSERT_NOT_REACHED();
6597 str = prepare_bits_string(value, bit_offset, no_of_bits);
6600 strcat(str,hf_field->name);
6603 * This function does not receive an actual value but a dimensionless pointer to that value.
6604 * For this reason, the type of the header field is examined in order to determine
6605 * what kind of value we should read from this address.
6606 * The caller of this function must make sure that for the specific header field type the address of
6607 * a compatible value is provided.
6609 switch(hf_field->type){
6611 return proto_tree_add_boolean_format(tree, hf_index, tvb, offset, length, *(guint32 *)value_ptr,
6612 "%s: %s", str, value_str);
6619 return proto_tree_add_uint_format(tree, hf_index, tvb, offset, length, *(guint32 *)value_ptr,
6620 "%s: %s", str, value_str);
6624 return proto_tree_add_uint64_format(tree, hf_index, tvb, offset, length, *(guint64 *)value_ptr,
6625 "%s: %s", str, value_str);
6632 return proto_tree_add_int_format(tree, hf_index, tvb, offset, length, *(gint32 *)value_ptr,
6633 "%s: %s", str, value_str);
6637 return proto_tree_add_float_format(tree, hf_index, tvb, offset, length, *(float *)value_ptr,
6638 "%s: %s", str, value_str);
6642 DISSECTOR_ASSERT_NOT_REACHED();
6648 #define CREATE_VALUE_STRING(dst,format,ap) \
6649 va_start(ap,format); \
6650 dst = ep_strdup_vprintf(format, ap); \
6654 proto_tree_add_uint_bits_format_value(proto_tree *tree, int hf_index, tvbuff_t *tvb, gint bit_offset, gint no_of_bits,
6655 guint32 value, const char *format, ...)
6659 header_field_info *hf_field;
6661 TRY_TO_FAKE_THIS_ITEM(tree, hf_index, hf_field);
6663 switch(hf_field->type){
6671 DISSECTOR_ASSERT_NOT_REACHED();
6676 CREATE_VALUE_STRING(dst,format,ap);
6678 return proto_tree_add_bits_format_value(tree, hf_index, tvb, bit_offset, no_of_bits, &value, dst);
6682 proto_tree_add_float_bits_format_value(proto_tree *tree, int hf_index, tvbuff_t *tvb, gint bit_offset, gint no_of_bits,
6683 float value, const char *format, ...)
6687 header_field_info *hf_field;
6689 TRY_TO_FAKE_THIS_ITEM(tree, hf_index, hf_field);
6691 DISSECTOR_ASSERT(hf_field->type == FT_FLOAT);
6693 CREATE_VALUE_STRING(dst,format,ap);
6695 return proto_tree_add_bits_format_value(tree, hf_index, tvb, bit_offset, no_of_bits, &value, dst);
6699 proto_tree_add_int_bits_format_value(proto_tree *tree, int hf_index, tvbuff_t *tvb, gint bit_offset, gint no_of_bits,
6700 gint32 value, const char *format, ...)
6704 header_field_info *hf_field;
6706 TRY_TO_FAKE_THIS_ITEM(tree, hf_index, hf_field);
6708 switch(hf_field->type){
6716 DISSECTOR_ASSERT_NOT_REACHED();
6721 CREATE_VALUE_STRING(dst,format,ap);
6723 return proto_tree_add_bits_format_value(tree, hf_index, tvb, bit_offset, no_of_bits, &value, dst);
6727 proto_tree_add_boolean_bits_format_value(proto_tree *tree, int hf_index, tvbuff_t *tvb, gint bit_offset, gint no_of_bits,
6728 guint32 value, const char *format, ...)
6732 header_field_info *hf_field;
6734 TRY_TO_FAKE_THIS_ITEM(tree, hf_index, hf_field);
6736 DISSECTOR_ASSERT(hf_field->type == FT_BOOLEAN);
6738 CREATE_VALUE_STRING(dst,format,ap);
6740 return proto_tree_add_bits_format_value(tree, hf_index, tvb, bit_offset, no_of_bits, &value, dst);
6744 proto_check_field_name(const gchar *field_name)
6746 return wrs_check_charset(fld_abbrev_chars, field_name);