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 200
255 /* Contains information about protocols and header fields. Used when
256 * dissectors register their data */
257 static GMemChunk *gmc_hfinfo = NULL;
259 /* Contains information about a field when a dissector calls
260 * proto_tree_add_item. */
261 SLAB_ITEM_TYPE_DEFINE(field_info)
262 static SLAB_FREE_LIST_DEFINE(field_info)
263 static field_info *field_info_tmp=NULL;
264 #define FIELD_INFO_NEW(fi) \
265 SLAB_ALLOC(fi, field_info)
266 #define FIELD_INFO_FREE(fi) \
267 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)
285 /* String space for protocol and field items for the GUI */
286 SLAB_ITEM_TYPE_DEFINE(item_label_t)
287 static SLAB_FREE_LIST_DEFINE(item_label_t)
288 #define ITEM_LABEL_NEW(il) \
289 SLAB_ALLOC(il, item_label_t)
290 #define ITEM_LABEL_FREE(il) \
291 SLAB_FREE(il, item_label_t)
294 #define PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo) \
295 DISSECTOR_ASSERT((guint)hfindex < gpa_hfinfo.len); \
296 hfinfo=gpa_hfinfo.hfi[hfindex];
299 /* List which stores protocols and fields that have been registered */
300 typedef struct _gpa_hfinfo_t {
302 guint32 allocated_len;
303 header_field_info **hfi;
305 gpa_hfinfo_t gpa_hfinfo;
307 /* Balanced tree of abbreviations and IDs */
308 static GTree *gpa_name_tree = NULL;
309 static header_field_info *same_name_hfinfo;
311 static void save_same_name_hfinfo(gpointer data)
313 same_name_hfinfo = (header_field_info*)data;
316 /* Points to the first element of an array of Booleans, indexed by
317 a subtree item type; that array element is TRUE if subtrees of
318 an item of that type are to be expanded. */
319 gboolean *tree_is_expanded;
321 /* Number of elements in that array. */
324 /* Name hashtables for fast detection of duplicate names */
325 static GHashTable* proto_names = NULL;
326 static GHashTable* proto_short_names = NULL;
327 static GHashTable* proto_filter_names = NULL;
330 proto_compare_name(gconstpointer p1_arg, gconstpointer p2_arg)
332 const protocol_t *p1 = p1_arg;
333 const protocol_t *p2 = p2_arg;
335 return g_ascii_strcasecmp(p1->short_name, p2->short_name);
339 /* initialize data structures and register protocols and fields */
341 proto_init(void (register_all_protocols_func)(register_cb cb, gpointer client_data),
342 void (register_all_handoffs_func)(register_cb cb, gpointer client_data),
344 gpointer client_data)
346 static hf_register_info hf[] = {
348 { "Text item", "text", FT_NONE, BASE_NONE, NULL, 0x0,
354 proto_names = g_hash_table_new_full(g_int_hash, g_int_equal, g_free, NULL);
355 proto_short_names = g_hash_table_new(wrs_str_hash, g_str_equal);
356 proto_filter_names = g_hash_table_new(wrs_str_hash, g_str_equal);
358 gmc_hfinfo = g_mem_chunk_new("gmc_hfinfo",
359 sizeof(header_field_info),
360 INITIAL_NUM_PROTOCOL_HFINFO * sizeof(header_field_info),
364 gpa_hfinfo.allocated_len=0;
366 gpa_name_tree = g_tree_new_full(wrs_strcmp_with_data, NULL, NULL, save_same_name_hfinfo);
368 /* Initialize the ftype subsystem */
371 /* Register one special-case FT_TEXT_ONLY field for use when
372 converting wireshark to new-style proto_tree. These fields
373 are merely strings on the GUI tree; they are not filterable */
374 proto_register_field_array(-1, hf, array_length(hf));
376 /* Have each built-in dissector register its protocols, fields,
377 dissector tables, and dissectors to be called through a
378 handle, and do whatever one-time initialization it needs to
380 register_all_protocols_func(cb, client_data);
382 /* Now scan for python protocols */
383 register_all_py_protocols_func(cb, client_data);
387 /* Now scan for plugins and load all the ones we find, calling
388 their register routines to do the stuff described above. */
390 (*cb)(RA_PLUGIN_REGISTER, NULL, client_data);
392 register_all_plugin_registrations();
395 /* Now call the "handoff registration" routines of all built-in
396 dissectors; those routines register the dissector in other
397 dissectors' handoff tables, and fetch any dissector handles
399 register_all_handoffs_func(cb, client_data);
402 /* Now do the same with python dissectors */
403 register_all_py_handoffs_func(cb, client_data);
407 /* Now do the same with plugins. */
409 (*cb)(RA_PLUGIN_HANDOFF, NULL, client_data);
410 register_all_plugin_handoffs();
413 /* sort the protocols by protocol name */
414 protocols = g_list_sort(protocols, proto_compare_name);
416 /* We've assigned all the subtree type values; allocate the array
417 for them, and zero it out. */
418 tree_is_expanded = g_malloc(num_tree_types*sizeof (gboolean));
419 memset(tree_is_expanded, 0, num_tree_types*sizeof (gboolean));
425 /* Free the abbrev/ID GTree */
427 g_tree_destroy(gpa_name_tree);
428 gpa_name_tree = NULL;
432 protocol_t *protocol = protocols->data;
434 g_list_free(protocol->fields);
435 protocols = g_list_remove(protocols, protocol);
440 g_hash_table_destroy(proto_names);
444 if (proto_short_names) {
445 g_hash_table_destroy(proto_short_names);
446 proto_short_names = NULL;
449 if (proto_filter_names) {
450 g_hash_table_destroy(proto_filter_names);
451 proto_filter_names = NULL;
455 g_mem_chunk_destroy(gmc_hfinfo);
459 if(gpa_hfinfo.allocated_len){
461 gpa_hfinfo.allocated_len=0;
462 g_free(gpa_hfinfo.hfi);
465 g_free(tree_is_expanded);
470 proto_tree_traverse_pre_order(proto_tree *tree, proto_tree_traverse_func func,
473 proto_node *pnode = tree;
477 if (func(pnode, data))
480 child = pnode->first_child;
481 while (child != NULL) {
483 * The routine we call might modify the child, e.g. by
484 * freeing it, so we get the child's successor before
485 * calling that routine.
488 child = current->next;
489 if (proto_tree_traverse_pre_order((proto_tree *)current, func,
498 proto_tree_traverse_post_order(proto_tree *tree, proto_tree_traverse_func func,
501 proto_node *pnode = tree;
505 child = pnode->first_child;
506 while (child != NULL) {
508 * The routine we call might modify the child, e.g. by
509 * freeing it, so we get the child's successor before
510 * calling that routine.
513 child = current->next;
514 if (proto_tree_traverse_post_order((proto_tree *)current, func,
518 if (func(pnode, data))
525 proto_tree_children_foreach(proto_tree *tree, proto_tree_foreach_func func,
528 proto_node *node = tree;
531 node = node->first_child;
532 while (node != NULL) {
534 node = current->next;
535 func((proto_tree *)current, data);
539 /* frees the resources that the dissection a proto_tree uses */
541 proto_tree_free(proto_tree *tree)
543 proto_tree_traverse_post_order(tree, proto_tree_free_node, NULL);
547 free_GPtrArray_value(gpointer key, gpointer value, gpointer user_data _U_)
549 GPtrArray *ptrs = value;
550 gint hfid = (gint)(long)key;
551 header_field_info *hfinfo;
553 PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
554 if(hfinfo->ref_type != HF_REF_TYPE_NONE) {
555 /* when a field is referenced by a filter this also
556 affects the refcount for the parent protocol so we need
557 to adjust the refcount for the parent as well
559 if( hfinfo->parent != -1 ) {
560 header_field_info *parent_hfinfo;
561 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
562 parent_hfinfo->ref_type = HF_REF_TYPE_NONE;
564 hfinfo->ref_type = HF_REF_TYPE_NONE;
567 g_ptr_array_free(ptrs, TRUE);
571 free_node_tree_data(tree_data_t *tree_data)
573 if (tree_data->interesting_hfids) {
574 /* Free all the GPtrArray's in the interesting_hfids hash. */
575 g_hash_table_foreach(tree_data->interesting_hfids,
576 free_GPtrArray_value, NULL);
578 /* And then destroy the hash. */
579 g_hash_table_destroy(tree_data->interesting_hfids);
582 /* And finally the tree_data_t itself. */
586 #define FREE_NODE_FIELD_INFO(finfo) \
588 ITEM_LABEL_FREE(finfo->rep); \
590 FVALUE_CLEANUP(&finfo->value); \
591 FIELD_INFO_FREE(finfo);
594 proto_tree_free_node(proto_node *node, gpointer data _U_)
596 field_info *finfo = PNODE_FINFO(node);
598 proto_node *parent = node->parent;
602 /* This is the root node. Destroy the per-tree data.
603 * There is no field_info to destroy. */
604 if (PTREE_DATA(node)) free_node_tree_data(PTREE_DATA(node));
607 /* This is a child node. Don't free the per-tree data, but
608 * do free the field_info data. */
609 FREE_NODE_FIELD_INFO(finfo);
613 /* NOTE: This code is required when this function is used to free individual
614 * nodes only. Current use is for the destruction of complete trees, so the
615 * inconsistancies have no ill effect.
617 /* Remove node from parent */
619 proto_item *prev_item = NULL;
620 if (parent->first_child == node) {
621 parent->first_child = node->next;
623 /* find previous and change its next */
624 for (prev_item = parent->first_child; prev_item; prev_item = prev_item->next) {
625 if (prev_item->next == node) {
629 DISSECTOR_ASSERT(prev_item);
630 prev_item->next = node->next;
632 /* fix last_child if required */
633 if (parent->last_child == node) {
634 parent->last_child = prev_item;
637 DISSECTOR_ASSERT(node->first_child == NULL && node->last_child == NULL);
639 /* Free the proto_node. */
640 PROTO_NODE_FREE(node);
642 return FALSE; /* FALSE = do not end traversal of protocol tree */
645 /* Is the parsing being done for a visible proto_tree or an invisible one?
646 * By setting this correctly, the proto_tree creation is sped up by not
647 * having to call g_vsnprintf and copy strings around.
650 proto_tree_set_visible(proto_tree *tree, gboolean visible)
652 gboolean old_visible = PTREE_DATA(tree)->visible;
654 PTREE_DATA(tree)->visible = visible;
660 proto_tree_set_fake_protocols(proto_tree *tree, gboolean fake_protocols)
662 PTREE_DATA(tree)->fake_protocols = fake_protocols;
665 /* Assume dissector set only its protocol fields.
666 This function is called by dissectors and allows the speeding up of filtering
667 in wireshark; if this function returns FALSE it is safe to reset tree to NULL
668 and thus skip calling most of the expensive proto_tree_add_...()
670 If the tree is visible we implicitly assume the field is referenced.
673 proto_field_is_referenced(proto_tree *tree, int proto_id)
675 register header_field_info *hfinfo;
681 if (PTREE_DATA(tree)->visible)
684 PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
685 if (hfinfo->ref_type != HF_REF_TYPE_NONE)
688 if (hfinfo->type == FT_PROTOCOL && !PTREE_DATA(tree)->fake_protocols)
695 /* Finds a record in the hf_info_records array by id. */
697 proto_registrar_get_nth(guint hfindex)
699 register header_field_info *hfinfo;
701 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
706 /* Prefix initialization
707 * this allows for a dissector to register a display filter name prefix
708 * so that it can delay the initialization of the hf array as long as
712 /* compute a hash for the part before the dot of a display filter */
714 prefix_hash (gconstpointer key) {
715 /* end the string at the dot and compute its hash */
716 gchar* copy = ep_strdup(key);
726 return g_str_hash(copy);
729 /* are both strings equal up to the end or the dot? */
731 prefix_equal (gconstpointer ap,gconstpointer bp) {
739 if ((ac == '.' || ac == '\0') && (bc == '.' || bc == '\0')) return TRUE;
741 if ( (ac == '.' || ac == '\0') && ! (bc == '.' || bc == '\0') ) return FALSE;
742 if ( (bc == '.' || bc == '\0') && ! (ac == '.' || ac == '\0') ) return FALSE;
744 if (ac != bc) return FALSE;
751 /* indexed by prefix, contains initializers */
752 static GHashTable* prefixes = NULL;
755 /* Register a new prefix for "delayed" initialization of field arrays */
757 proto_register_prefix(const char *prefix, prefix_initializer_t pi ) {
759 prefixes = g_hash_table_new(prefix_hash,prefix_equal);
762 g_hash_table_insert(prefixes,(gpointer)prefix,pi);
765 /* helper to call all prefix initializers */
767 initialize_prefix(gpointer k, gpointer v, gpointer u _U_) {
768 ((prefix_initializer_t)v)(k);
772 /** Initialize every remaining uninitialized prefix. */
774 proto_initialize_all_prefixes(void) {
775 g_hash_table_foreach_remove(prefixes, initialize_prefix, NULL);
778 /* Finds a record in the hf_info_records array by name.
779 * If it fails to find it in the already registered fields,
780 * it tries to find and call an initializer in the prefixes
781 * table and if so it looks again.
784 proto_registrar_get_byname(const char *field_name)
786 header_field_info* hfinfo;
787 prefix_initializer_t pi;
792 hfinfo = g_tree_lookup(gpa_name_tree, field_name);
794 if (hfinfo) return hfinfo;
796 if (!prefixes) return NULL;
798 if(( pi = g_hash_table_lookup(prefixes,field_name) )) {
800 g_hash_table_remove(prefixes,field_name);
805 return g_tree_lookup(gpa_name_tree, field_name);
810 ptvcursor_new_subtree_levels(ptvcursor_t * ptvc)
812 subtree_lvl * pushed_tree;
814 DISSECTOR_ASSERT(ptvc->pushed_tree_max <= SUBTREE_MAX_LEVELS-SUBTREE_ONCE_ALLOCATION_NUMBER);
815 ptvc->pushed_tree_max += SUBTREE_ONCE_ALLOCATION_NUMBER;
817 pushed_tree = ep_alloc(sizeof(subtree_lvl) * ptvc->pushed_tree_max);
818 DISSECTOR_ASSERT(pushed_tree != NULL);
819 if (ptvc->pushed_tree)
820 memcpy(pushed_tree, ptvc->pushed_tree, ptvc->pushed_tree_max - SUBTREE_ONCE_ALLOCATION_NUMBER);
821 ptvc->pushed_tree = pushed_tree;
825 ptvcursor_free_subtree_levels(ptvcursor_t * ptvc)
827 ptvc->pushed_tree = NULL;
828 ptvc->pushed_tree_max = 0;
829 DISSECTOR_ASSERT(ptvc->pushed_tree_index ==0);
830 ptvc->pushed_tree_index = 0;
833 /* Allocates an initializes a ptvcursor_t with 3 variables:
834 * proto_tree, tvbuff, and offset. */
836 ptvcursor_new(proto_tree *tree, tvbuff_t *tvb, gint offset)
840 ptvc = ep_alloc(sizeof(ptvcursor_t));
843 ptvc->offset = offset;
844 ptvc->pushed_tree= NULL;
845 ptvc->pushed_tree_max= 0;
846 ptvc->pushed_tree_index= 0;
851 /* Frees memory for ptvcursor_t, but nothing deeper than that. */
853 ptvcursor_free(ptvcursor_t *ptvc)
855 ptvcursor_free_subtree_levels(ptvc);
859 /* Returns tvbuff. */
861 ptvcursor_tvbuff(ptvcursor_t* ptvc)
866 /* Returns current offset. */
868 ptvcursor_current_offset(ptvcursor_t* ptvc)
874 ptvcursor_tree(ptvcursor_t* ptvc)
883 ptvcursor_set_tree(ptvcursor_t* ptvc, proto_tree *tree)
888 /* creates a subtree, sets it as the working tree and pushes the old working tree */
890 ptvcursor_push_subtree(ptvcursor_t *ptvc, proto_item *it, gint ett_subtree)
892 subtree_lvl * subtree;
893 if (ptvc->pushed_tree_index >= ptvc->pushed_tree_max)
894 ptvcursor_new_subtree_levels(ptvc);
896 subtree = ptvc->pushed_tree+ptvc->pushed_tree_index;
897 subtree->tree = ptvc->tree;
899 ptvc->pushed_tree_index++;
900 return ptvcursor_set_subtree(ptvc, it, ett_subtree);
905 ptvcursor_pop_subtree(ptvcursor_t *ptvc)
907 subtree_lvl * subtree;
908 if (ptvc->pushed_tree_index <= 0)
911 ptvc->pushed_tree_index--;
912 subtree = ptvc->pushed_tree+ptvc->pushed_tree_index;
913 if (subtree->it != NULL)
914 proto_item_set_len(subtree->it, ptvcursor_current_offset(ptvc) - subtree->cursor_offset);
916 ptvc->tree = subtree->tree;
919 /* saves the current tvb offset and the item in the current subtree level */
921 ptvcursor_subtree_set_item(ptvcursor_t * ptvc, proto_item * it)
923 subtree_lvl * subtree;
925 DISSECTOR_ASSERT(ptvc->pushed_tree_index > 0);
927 subtree = ptvc->pushed_tree+ptvc->pushed_tree_index-1;
929 subtree->cursor_offset = ptvcursor_current_offset(ptvc);
932 /* Creates a subtree and adds it to the cursor as the working tree but does not
933 * save the old working tree */
935 ptvcursor_set_subtree(ptvcursor_t *ptvc, proto_item *it, gint ett_subtree)
937 ptvc->tree = proto_item_add_subtree(it, ett_subtree);
942 ptvcursor_add_subtree_item(ptvcursor_t * ptvc, proto_item * it, gint ett_subtree, gint length)
944 ptvcursor_push_subtree(ptvc, it, ett_subtree);
945 if (length == SUBTREE_UNDEFINED_LENGTH)
946 ptvcursor_subtree_set_item(ptvc, it);
947 return ptvcursor_tree(ptvc);
950 /* Add an item to the tree and create a subtree
951 * If the length is unknown, length may be defined as SUBTREE_UNDEFINED_LENGTH.
952 * In this case, when the subtree will be closed, the parent item length will
953 * be equal to the advancement of the cursor since the creation of the subtree.
956 ptvcursor_add_with_subtree(ptvcursor_t * ptvc, int hfindex, gint length,
957 gboolean little_endian, gint ett_subtree)
961 it = ptvcursor_add_no_advance(ptvc, hfindex, length, little_endian);
962 return ptvcursor_add_subtree_item(ptvc, it, ett_subtree, length);
966 proto_tree_add_text_node(proto_tree *tree, tvbuff_t *tvb, gint start, gint length);
968 /* Add a text node to the tree and create a subtree
969 * If the length is unknown, length may be defined as SUBTREE_UNDEFINED_LENGTH.
970 * In this case, when the subtree will be closed, the item length will be equal
971 * to the advancement of the cursor since the creation of the subtree.
974 ptvcursor_add_text_with_subtree(ptvcursor_t * ptvc, gint length,
975 gint ett_subtree, const char *format, ...)
979 header_field_info *hfinfo;
981 TRY_TO_FAKE_THIS_ITEM(ptvcursor_tree(ptvc), hf_text_only, hfinfo);
983 it = proto_tree_add_text_node(ptvcursor_tree(ptvc), ptvcursor_tvbuff(ptvc),
984 ptvcursor_current_offset(ptvc), length);
989 va_start(ap, format);
990 proto_tree_set_representation(it, format, ap);
993 return ptvcursor_add_subtree_item(ptvc, it, ett_subtree, length);
996 /* Add a text-only node, leaving it to our caller to fill the text in */
998 proto_tree_add_text_node(proto_tree *tree, tvbuff_t *tvb, gint start, gint length)
1002 pi = proto_tree_add_pi(tree, hf_text_only, tvb, start, &length, NULL);
1009 /* Add a text-only node to the proto_tree */
1011 proto_tree_add_text(proto_tree *tree, tvbuff_t *tvb, gint start, gint length,
1012 const char *format, ...)
1016 header_field_info *hfinfo;
1018 TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
1020 pi = proto_tree_add_text_node(tree, tvb, start, length);
1024 TRY_TO_FAKE_THIS_REPR(tree, pi);
1026 va_start(ap, format);
1027 proto_tree_set_representation(pi, format, ap);
1033 /* Add a text-only node to the proto_tree (va_list version) */
1035 proto_tree_add_text_valist(proto_tree *tree, tvbuff_t *tvb, gint start,
1036 gint length, const char *format, va_list ap)
1039 header_field_info *hfinfo;
1041 TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
1043 pi = proto_tree_add_text_node(tree, tvb, start, length);
1047 TRY_TO_FAKE_THIS_REPR(tree, pi);
1049 proto_tree_set_representation(pi, format, ap);
1054 /* Add a text-only node for debugging purposes. The caller doesn't need
1055 * to worry about tvbuff, start, or length. Debug message gets sent to
1058 proto_tree_add_debug_text(proto_tree *tree, const char *format, ...)
1063 pi = proto_tree_add_text_node(tree, NULL, 0, 0);
1065 va_start(ap, format);
1067 proto_tree_set_representation(pi, format, ap);
1068 vprintf(format, ap);
1077 get_uint_value(tvbuff_t *tvb, gint offset, gint length, gboolean little_endian)
1084 value = tvb_get_guint8(tvb, offset);
1088 value = little_endian ? tvb_get_letohs(tvb, offset)
1089 : tvb_get_ntohs(tvb, offset);
1093 value = little_endian ? tvb_get_letoh24(tvb, offset)
1094 : tvb_get_ntoh24(tvb, offset);
1098 value = little_endian ? tvb_get_letohl(tvb, offset)
1099 : tvb_get_ntohl(tvb, offset);
1103 DISSECTOR_ASSERT_NOT_REACHED();
1111 get_int_value(tvbuff_t *tvb, gint offset, gint length, gboolean little_endian)
1118 value = (gint8)tvb_get_guint8(tvb, offset);
1122 value = (gint16) (little_endian ? tvb_get_letohs(tvb, offset)
1123 : tvb_get_ntohs(tvb, offset));
1127 value = little_endian ? tvb_get_letoh24(tvb, offset)
1128 : tvb_get_ntoh24(tvb, offset);
1129 if (value & 0x00800000) {
1130 /* Sign bit is set; sign-extend it. */
1131 value |= 0xFF000000;
1136 value = little_endian ? tvb_get_letohl(tvb, offset)
1137 : tvb_get_ntohl(tvb, offset);
1141 DISSECTOR_ASSERT_NOT_REACHED();
1148 static GPtrArray *proto_lookup_or_create_interesting_hfids(proto_tree *tree,
1149 header_field_info *hfinfo)
1151 GPtrArray *ptrs = NULL;
1153 DISSECTOR_ASSERT(tree);
1154 DISSECTOR_ASSERT(hfinfo);
1156 if (hfinfo->ref_type == HF_REF_TYPE_DIRECT) {
1157 if (PTREE_DATA(tree)->interesting_hfids == NULL) {
1158 /* Initialize the hash because we now know that it is needed */
1159 PTREE_DATA(tree)->interesting_hfids =
1160 g_hash_table_new(g_direct_hash, NULL /* g_direct_equal */);
1163 ptrs = g_hash_table_lookup(PTREE_DATA(tree)->interesting_hfids,
1164 GINT_TO_POINTER(hfinfo->id));
1166 /* First element triggers the creation of pointer array */
1167 ptrs = g_ptr_array_new();
1168 g_hash_table_insert(PTREE_DATA(tree)->interesting_hfids,
1169 GINT_TO_POINTER(hfinfo->id), ptrs);
1176 /* Add an item to a proto_tree, using the text label registered to that item;
1177 the item is extracted from the tvbuff handed to it. */
1179 proto_tree_new_item(field_info *new_fi, proto_tree *tree,
1180 tvbuff_t *tvb, gint start, gint length, gboolean little_endian)
1189 /* there is a possibility here that we might raise an exception
1190 * and thus would lose track of the field_info.
1191 * store it in a temp so that if we come here again we can reclaim
1192 * the field_info without leaking memory.
1194 /* XXX this only keeps track of one field_info struct,
1195 if we ever go multithreaded for calls to this function
1196 we have to change this code to use per thread variable.
1199 /* oops, last one we got must have been lost due
1201 * good thing we saved it, now we can reverse the
1202 * memory leak and reclaim it.
1204 SLAB_FREE(field_info_tmp, field_info);
1206 /* we might throw an exception, keep track of this one
1207 * across the "dangerous" section below.
1209 field_info_tmp=new_fi;
1211 switch(new_fi->hfinfo->type) {
1213 /* no value to set for FT_NONE */
1217 proto_tree_set_protocol_tvb(new_fi, tvb);
1221 proto_tree_set_bytes_tvb(new_fi, tvb, start, length);
1225 n = get_uint_value(tvb, start, length, little_endian);
1226 proto_tree_set_bytes_tvb(new_fi, tvb, start + length, n);
1228 /* Instead of calling proto_item_set_len(), since we don't yet
1229 * have a proto_item, we set the field_info's length ourselves. */
1230 new_fi->length = n + length;
1234 proto_tree_set_boolean(new_fi,
1235 get_uint_value(tvb, start, length, little_endian));
1238 /* XXX - make these just FT_UINT? */
1243 proto_tree_set_uint(new_fi,
1244 get_uint_value(tvb, start, length, little_endian));
1249 DISSECTOR_ASSERT( length <= 8 && length >= 1);
1250 proto_tree_set_uint64_tvb(new_fi, tvb, start, length, little_endian);
1253 /* XXX - make these just FT_INT? */
1258 proto_tree_set_int(new_fi,
1259 get_int_value(tvb, start, length, little_endian));
1263 DISSECTOR_ASSERT(length == FT_IPv4_LEN);
1264 value = tvb_get_ipv4(tvb, start);
1265 proto_tree_set_ipv4(new_fi, little_endian ? GUINT32_SWAP_LE_BE(value) : value);
1269 DISSECTOR_ASSERT(length == FT_IPXNET_LEN);
1270 proto_tree_set_ipxnet(new_fi,
1271 get_uint_value(tvb, start, 4, FALSE));
1275 DISSECTOR_ASSERT(length >=0 && length <= FT_IPv6_LEN);
1276 proto_tree_set_ipv6_tvb(new_fi, tvb, start, length);
1280 DISSECTOR_ASSERT(length == FT_ETHER_LEN);
1281 proto_tree_set_ether_tvb(new_fi, tvb, start);
1285 DISSECTOR_ASSERT(length == FT_GUID_LEN);
1286 proto_tree_set_guid_tvb(new_fi, tvb, start, little_endian);
1290 proto_tree_set_oid_tvb(new_fi, tvb, start, length);
1294 DISSECTOR_ASSERT(length == 4);
1296 floatval = tvb_get_letohieee_float(tvb, start);
1298 floatval = tvb_get_ntohieee_float(tvb, start);
1299 proto_tree_set_float(new_fi, floatval);
1303 DISSECTOR_ASSERT(length == 8);
1305 doubleval = tvb_get_letohieee_double(tvb, start);
1307 doubleval = tvb_get_ntohieee_double(tvb, start);
1308 proto_tree_set_double(new_fi, doubleval);
1312 proto_tree_set_string_tvb(new_fi, tvb, start, length);
1316 DISSECTOR_ASSERT(length >= -1);
1317 /* Instead of calling proto_item_set_len(),
1318 * since we don't yet have a proto_item, we
1319 * set the field_info's length ourselves.
1321 * XXX - our caller can't use that length to
1322 * advance an offset unless they arrange that
1323 * there always be a protocol tree into which
1324 * we're putting this item.
1327 /* This can throw an exception */
1328 length = tvb_strsize(tvb, start);
1330 string = ep_alloc(length);
1332 tvb_memcpy(tvb, string, start, length);
1333 } else if (length == 0) {
1336 /* In this case, length signifies
1337 * the length of the string.
1339 * This could either be a null-padded
1340 * string, which doesn't necessarily
1341 * have a '\0' at the end, or a
1342 * null-terminated string, with a
1343 * trailing '\0'. (Yes, there are
1344 * cases where you have a string
1345 * that's both counted and null-
1348 * In the first case, we must
1349 * allocate a buffer of length
1350 * "length+1", to make room for
1353 * In the second case, we don't
1354 * assume that there is a trailing
1355 * '\0' there, as the packet might
1356 * be malformed. (XXX - should we
1357 * throw an exception if there's no
1358 * trailing '\0'?) Therefore, we
1359 * allocate a buffer of length
1360 * "length+1", and put in a trailing
1361 * '\0', just to be safe.
1363 * (XXX - this would change if
1364 * we made string values counted
1365 * rather than null-terminated.)
1367 string = tvb_get_ephemeral_string(tvb,
1371 new_fi->length = length;
1372 proto_tree_set_string(new_fi, string);
1376 proto_tree_set_ebcdic_string_tvb(new_fi, tvb, start, length);
1379 case FT_UINT_STRING:
1380 n = get_uint_value(tvb, start, length, little_endian);
1381 proto_tree_set_string_tvb(new_fi, tvb, start + length, n);
1383 /* Instead of calling proto_item_set_len(), since we
1384 * don't yet have a proto_item, we set the
1385 * field_info's length ourselves.
1387 * XXX - our caller can't use that length to
1388 * advance an offset unless they arrange that
1389 * there always be a protocol tree into which
1390 * we're putting this item.
1392 new_fi->length = n + length;
1396 g_error("new_fi->hfinfo->type %d (%s) not handled\n",
1397 new_fi->hfinfo->type,
1398 ftype_name(new_fi->hfinfo->type));
1399 DISSECTOR_ASSERT_NOT_REACHED();
1403 /* Don't add new node to proto_tree until now so that any exceptions
1404 * raised by a tvbuff access method doesn't leave junk in the proto_tree. */
1405 pi = proto_tree_add_node(tree, new_fi);
1407 /* we did not raise an exception so we dont have to remember this
1408 * field_info struct any more.
1410 field_info_tmp=NULL;
1412 /* If the proto_tree wants to keep a record of this finfo
1413 * for quick lookup, then record it. */
1414 ptrs = proto_lookup_or_create_interesting_hfids(tree, new_fi->hfinfo);
1416 g_ptr_array_add(ptrs, new_fi);
1421 /* Gets data from tvbuff, adds it to proto_tree, increments offset,
1422 and returns proto_item* */
1424 ptvcursor_add(ptvcursor_t *ptvc, int hfindex, gint length,
1425 gboolean little_endian)
1428 header_field_info *hfinfo;
1433 /* We can't fake it just yet. We have to advance the cursor
1434 TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfindex, hfinfo); */
1436 offset = ptvc->offset;
1437 hfinfo = get_hfi_and_length(hfindex, ptvc->tvb, offset, &length,
1439 ptvc->offset += length;
1440 if (hfinfo->type == FT_UINT_BYTES || hfinfo->type == FT_UINT_STRING) {
1442 * The length of the rest of the item is in the first N
1443 * bytes of the item.
1445 n = get_uint_value(ptvc->tvb, offset, length, little_endian);
1449 /* Coast clear. Try and fake it */
1450 TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfindex, hfinfo);
1452 new_fi = new_field_info(ptvc->tree, hfinfo, ptvc->tvb, offset, item_length);
1456 return proto_tree_new_item(new_fi, ptvc->tree, ptvc->tvb,
1457 offset, length, little_endian);
1460 /* Add an item to a proto_tree, using the text label registered to that item;
1461 the item is extracted from the tvbuff handed to it. */
1463 proto_tree_add_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1464 gint start, gint length, gboolean little_endian)
1467 header_field_info *hfinfo;
1469 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1471 new_fi = alloc_field_info(tree, hfindex, tvb, start, &length);
1476 return proto_tree_new_item(new_fi, tree, tvb, start,
1477 length, little_endian);
1480 /* Add a FT_NONE to a proto_tree */
1482 proto_tree_add_none_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1483 gint length, const char *format, ...)
1487 header_field_info *hfinfo;
1489 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1491 DISSECTOR_ASSERT(hfinfo->type == FT_NONE);
1493 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, NULL);
1495 TRY_TO_FAKE_THIS_REPR(tree, pi);
1497 va_start(ap, format);
1498 proto_tree_set_representation(pi, format, ap);
1501 /* no value to set for FT_NONE */
1505 /* Gets data from tvbuff, adds it to proto_tree, *DOES NOT* increment
1506 * offset, and returns proto_item* */
1508 ptvcursor_add_no_advance(ptvcursor_t* ptvc, int hf, gint length,
1509 gboolean endianness)
1513 item = proto_tree_add_item(ptvc->tree, hf, ptvc->tvb, ptvc->offset,
1514 length, endianness);
1519 /* Advance the ptvcursor's offset within its tvbuff without
1520 * adding anything to the proto_tree. */
1522 ptvcursor_advance(ptvcursor_t* ptvc, gint length)
1524 ptvc->offset += length;
1529 proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb)
1531 fvalue_set(&fi->value, tvb, TRUE);
1534 /* Add a FT_PROTOCOL to a proto_tree */
1536 proto_tree_add_protocol_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1537 gint length, const char *format, ...)
1542 header_field_info *hfinfo;
1544 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1546 DISSECTOR_ASSERT(hfinfo->type == FT_PROTOCOL);
1548 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1550 proto_tree_set_protocol_tvb(new_fi, (start == 0 ? tvb : NULL));
1552 TRY_TO_FAKE_THIS_REPR(tree, pi);
1554 va_start(ap, format);
1555 proto_tree_set_representation(pi, format, ap);
1562 /* Add a FT_BYTES to a proto_tree */
1564 proto_tree_add_bytes(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1565 gint length, const guint8 *start_ptr)
1569 header_field_info *hfinfo;
1571 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1573 DISSECTOR_ASSERT(hfinfo->type == FT_BYTES);
1575 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1576 proto_tree_set_bytes(new_fi, start_ptr, length);
1582 proto_tree_add_bytes_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1583 gint start, gint length, const guint8 *start_ptr,
1584 const char *format, ...)
1588 header_field_info *hfinfo;
1590 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1592 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length, start_ptr);
1596 TRY_TO_FAKE_THIS_REPR(tree, pi);
1598 va_start(ap, format);
1599 proto_tree_set_representation_value(pi, format, ap);
1606 proto_tree_add_bytes_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1607 gint length, const guint8 *start_ptr, const char *format, ...)
1611 header_field_info *hfinfo;
1613 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1615 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length, start_ptr);
1619 TRY_TO_FAKE_THIS_REPR(tree, pi);
1621 va_start(ap, format);
1622 proto_tree_set_representation(pi, format, ap);
1629 proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length)
1633 bytes = g_byte_array_new();
1635 g_byte_array_append(bytes, start_ptr, length);
1637 fvalue_set(&fi->value, bytes, TRUE);
1642 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length)
1644 proto_tree_set_bytes(fi, tvb_get_ptr(tvb, offset, length), length);
1647 /* Add a FT_*TIME to a proto_tree */
1649 proto_tree_add_time(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1650 nstime_t *value_ptr)
1654 header_field_info *hfinfo;
1656 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1658 DISSECTOR_ASSERT(hfinfo->type == FT_ABSOLUTE_TIME ||
1659 hfinfo->type == FT_RELATIVE_TIME);
1661 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1662 proto_tree_set_time(new_fi, value_ptr);
1668 proto_tree_add_time_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1669 gint start, gint length, nstime_t *value_ptr,
1670 const char *format, ...)
1674 header_field_info *hfinfo;
1676 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1678 pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
1682 TRY_TO_FAKE_THIS_REPR(tree, pi);
1684 va_start(ap, format);
1685 proto_tree_set_representation_value(pi, format, ap);
1692 proto_tree_add_time_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1693 nstime_t *value_ptr, const char *format, ...)
1697 header_field_info *hfinfo;
1699 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1701 pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
1705 TRY_TO_FAKE_THIS_REPR(tree, pi);
1707 va_start(ap, format);
1708 proto_tree_set_representation(pi, format, ap);
1714 /* Set the FT_*TIME value */
1716 proto_tree_set_time(field_info *fi, nstime_t *value_ptr)
1718 DISSECTOR_ASSERT(value_ptr != NULL);
1720 fvalue_set(&fi->value, value_ptr, FALSE);
1723 /* Add a FT_IPXNET to a proto_tree */
1725 proto_tree_add_ipxnet(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1730 header_field_info *hfinfo;
1732 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1734 DISSECTOR_ASSERT(hfinfo->type == FT_IPXNET);
1736 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1737 proto_tree_set_ipxnet(new_fi, value);
1743 proto_tree_add_ipxnet_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1744 gint start, gint length, guint32 value, const char *format, ...)
1748 header_field_info *hfinfo;
1750 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1752 pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
1756 TRY_TO_FAKE_THIS_REPR(tree, pi);
1758 va_start(ap, format);
1759 proto_tree_set_representation_value(pi, format, ap);
1766 proto_tree_add_ipxnet_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1767 guint32 value, const char *format, ...)
1771 header_field_info *hfinfo;
1773 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1775 pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
1779 TRY_TO_FAKE_THIS_REPR(tree, pi);
1781 va_start(ap, format);
1782 proto_tree_set_representation(pi, format, ap);
1788 /* Set the FT_IPXNET value */
1790 proto_tree_set_ipxnet(field_info *fi, guint32 value)
1792 fvalue_set_uinteger(&fi->value, value);
1795 /* Add a FT_IPv4 to a proto_tree */
1797 proto_tree_add_ipv4(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1802 header_field_info *hfinfo;
1804 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1806 DISSECTOR_ASSERT(hfinfo->type == FT_IPv4);
1808 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1809 proto_tree_set_ipv4(new_fi, value);
1815 proto_tree_add_ipv4_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1816 gint start, gint length, guint32 value, const char *format, ...)
1820 header_field_info *hfinfo;
1822 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1824 pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
1828 TRY_TO_FAKE_THIS_REPR(tree, pi);
1830 va_start(ap, format);
1831 proto_tree_set_representation_value(pi, format, ap);
1838 proto_tree_add_ipv4_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1839 guint32 value, const char *format, ...)
1843 header_field_info *hfinfo;
1845 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1847 pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
1851 TRY_TO_FAKE_THIS_REPR(tree, pi);
1853 va_start(ap, format);
1854 proto_tree_set_representation(pi, format, ap);
1860 /* Set the FT_IPv4 value */
1862 proto_tree_set_ipv4(field_info *fi, guint32 value)
1864 fvalue_set_uinteger(&fi->value, value);
1867 /* Add a FT_IPv6 to a proto_tree */
1869 proto_tree_add_ipv6(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1870 const guint8* value_ptr)
1874 header_field_info *hfinfo;
1876 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1878 DISSECTOR_ASSERT(hfinfo->type == FT_IPv6);
1880 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1881 proto_tree_set_ipv6(new_fi, value_ptr);
1887 proto_tree_add_ipv6_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1888 gint start, gint length, const guint8* value_ptr,
1889 const char *format, ...)
1893 header_field_info *hfinfo;
1895 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1897 pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
1901 TRY_TO_FAKE_THIS_REPR(tree, pi);
1903 va_start(ap, format);
1904 proto_tree_set_representation_value(pi, format, ap);
1911 proto_tree_add_ipv6_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1912 const guint8* value_ptr, const char *format, ...)
1916 header_field_info *hfinfo;
1918 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1920 pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
1924 TRY_TO_FAKE_THIS_REPR(tree, pi);
1926 va_start(ap, format);
1927 proto_tree_set_representation(pi, format, ap);
1933 /* Set the FT_IPv6 value */
1935 proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr)
1937 DISSECTOR_ASSERT(value_ptr != NULL);
1938 fvalue_set(&fi->value, (gpointer) value_ptr, FALSE);
1942 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
1944 proto_tree_set_ipv6(fi, tvb_get_ptr(tvb, start, length));
1947 /* Add a FT_GUID to a proto_tree */
1949 proto_tree_add_guid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1950 const e_guid_t *value_ptr)
1954 header_field_info *hfinfo;
1956 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1958 DISSECTOR_ASSERT(hfinfo->type == FT_GUID);
1960 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1961 proto_tree_set_guid(new_fi, value_ptr);
1967 proto_tree_add_guid_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1968 gint start, gint length, const e_guid_t *value_ptr,
1969 const char *format, ...)
1973 header_field_info *hfinfo;
1975 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1977 pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
1981 TRY_TO_FAKE_THIS_REPR(tree, pi);
1983 va_start(ap, format);
1984 proto_tree_set_representation_value(pi, format, ap);
1991 proto_tree_add_guid_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1992 const e_guid_t *value_ptr, const char *format, ...)
1996 header_field_info *hfinfo;
1998 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2000 pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
2004 TRY_TO_FAKE_THIS_REPR(tree, pi);
2006 va_start(ap, format);
2007 proto_tree_set_representation(pi, format, ap);
2013 /* Set the FT_GUID value */
2015 proto_tree_set_guid(field_info *fi, const e_guid_t *value_ptr)
2017 DISSECTOR_ASSERT(value_ptr != NULL);
2018 fvalue_set(&fi->value, (gpointer) value_ptr, FALSE);
2022 proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gboolean little_endian)
2026 tvb_get_guid(tvb, start, &guid, little_endian);
2027 proto_tree_set_guid(fi, &guid);
2030 /* Add a FT_OID to a proto_tree */
2032 proto_tree_add_oid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2033 const guint8* value_ptr)
2037 header_field_info *hfinfo;
2039 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2041 DISSECTOR_ASSERT(hfinfo->type == FT_OID);
2043 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2044 proto_tree_set_oid(new_fi, value_ptr, length);
2050 proto_tree_add_oid_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2051 gint start, gint length, const guint8* value_ptr,
2052 const char *format, ...)
2056 header_field_info *hfinfo;
2058 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2060 pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
2064 TRY_TO_FAKE_THIS_REPR(tree, pi);
2066 va_start(ap, format);
2067 proto_tree_set_representation_value(pi, format, ap);
2074 proto_tree_add_oid_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2075 const guint8* value_ptr, const char *format, ...)
2079 header_field_info *hfinfo;
2081 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2083 pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
2087 TRY_TO_FAKE_THIS_REPR(tree, pi);
2089 va_start(ap, format);
2090 proto_tree_set_representation(pi, format, ap);
2096 /* Set the FT_OID value */
2098 proto_tree_set_oid(field_info *fi, const guint8* value_ptr, gint length)
2102 DISSECTOR_ASSERT(value_ptr != NULL);
2104 bytes = g_byte_array_new();
2106 g_byte_array_append(bytes, value_ptr, length);
2108 fvalue_set(&fi->value, bytes, TRUE);
2112 proto_tree_set_oid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
2114 proto_tree_set_oid(fi, tvb_get_ptr(tvb, start, length), length);
2118 proto_tree_set_uint64(field_info *fi, guint64 value)
2120 fvalue_set_integer64(&fi->value, value);
2124 proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start, guint length, gboolean little_endian)
2127 guint8* b = ep_tvb_memdup(tvb,start,length);
2132 default: DISSECTOR_ASSERT_NOT_REACHED();
2133 case 8: value <<= 8; value += *--b;
2134 case 7: value <<= 8; value += *--b;
2135 case 6: value <<= 8; value += *--b;
2136 case 5: value <<= 8; value += *--b;
2137 case 4: value <<= 8; value += *--b;
2138 case 3: value <<= 8; value += *--b;
2139 case 2: value <<= 8; value += *--b;
2140 case 1: value <<= 8; value += *--b;
2145 default: DISSECTOR_ASSERT_NOT_REACHED();
2146 case 8: value <<= 8; value += *b++;
2147 case 7: value <<= 8; value += *b++;
2148 case 6: value <<= 8; value += *b++;
2149 case 5: value <<= 8; value += *b++;
2150 case 4: value <<= 8; value += *b++;
2151 case 3: value <<= 8; value += *b++;
2152 case 2: value <<= 8; value += *b++;
2153 case 1: value <<= 8; value += *b++;
2158 proto_tree_set_uint64(fi, value);
2161 /* Add a FT_STRING or FT_STRINGZ to a proto_tree. Creates own copy of string,
2162 * and frees it when the proto_tree is destroyed. */
2164 proto_tree_add_string(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2165 gint length, const char* value)
2169 header_field_info *hfinfo;
2171 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2173 DISSECTOR_ASSERT(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ);
2175 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2176 DISSECTOR_ASSERT(length >= 0);
2177 proto_tree_set_string(new_fi, value);
2183 proto_tree_add_string_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2184 gint start, gint length, const char* value, const char *format,
2189 header_field_info *hfinfo;
2191 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2193 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
2197 TRY_TO_FAKE_THIS_REPR(tree, pi);
2199 va_start(ap, format);
2200 proto_tree_set_representation_value(pi, format, ap);
2207 proto_tree_add_string_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2208 gint length, const char* value, const char *format, ...)
2212 header_field_info *hfinfo;
2214 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2216 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
2220 TRY_TO_FAKE_THIS_REPR(tree, pi);
2222 va_start(ap, format);
2223 proto_tree_set_representation(pi, format, ap);
2229 /* Appends string data to a FT_STRING or FT_STRINGZ, allowing progressive
2230 * field info update instead of only updating the representation as does
2231 * proto_item_append_text()
2233 /* NOTE: this function will break with the TRY_TO_FAKE_THIS_ITEM()
2234 * speed optimization.
2235 * Currently only WSP use this function so it is not that bad but try to
2236 * avoid using this one if possible.
2237 * IF you must use this function you MUST also disable the
2238 * TRY_TO_FAKE_THIS_ITEM() optimization for your dissector/function
2239 * using proto_item_append_string().
2240 * Do that by faking that the tree is visible by calling
2241 * proto_tree_set_visible(tree, TRUE) (see packet-wsp.c)
2242 * BEFORE you create the item you are later going to use
2243 * proto_item_append_string() on.
2246 proto_item_append_string(proto_item *pi, const char *str)
2249 header_field_info *hfinfo;
2250 gchar *old_str, *new_str;
2257 fi = PITEM_FINFO(pi);
2258 DISSECTOR_ASSERT(fi && "proto_tree_set_visible(tree, TRUE) should have been called previously");
2260 hfinfo = fi->hfinfo;
2261 if (hfinfo->type == FT_PROTOCOL) {
2262 /* TRY_TO_FAKE_THIS_ITEM() speed optimization: silently skip */
2265 DISSECTOR_ASSERT(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ);
2266 old_str = fvalue_get(&fi->value);
2267 new_str = ep_strdup_printf("%s%s", old_str, str);
2268 fvalue_set(&fi->value, new_str, FALSE);
2271 /* Set the FT_STRING value */
2273 proto_tree_set_string(field_info *fi, const char* value)
2276 fvalue_set(&fi->value, (gpointer) value, FALSE);
2278 fvalue_set(&fi->value, (gpointer) "[ Null ]", FALSE);
2283 proto_tree_set_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
2288 length = tvb_ensure_length_remaining(tvb, start);
2291 string = tvb_get_ephemeral_string(tvb, start, length);
2292 proto_tree_set_string(fi, string);
2296 proto_tree_set_ebcdic_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
2301 length = tvb_ensure_length_remaining(tvb, start);
2304 string = tvb_get_ephemeral_string(tvb, start, length);
2305 EBCDIC_to_ASCII(string, length);
2306 proto_tree_set_string(fi, string);
2309 /* Add a FT_ETHER to a proto_tree */
2311 proto_tree_add_ether(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2312 const guint8* value)
2316 header_field_info *hfinfo;
2318 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2320 DISSECTOR_ASSERT(hfinfo->type == FT_ETHER);
2322 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2323 proto_tree_set_ether(new_fi, value);
2329 proto_tree_add_ether_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2330 gint start, gint length, const guint8* value,
2331 const char *format, ...)
2335 header_field_info *hfinfo;
2337 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2339 pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
2343 TRY_TO_FAKE_THIS_REPR(tree, pi);
2345 va_start(ap, format);
2346 proto_tree_set_representation_value(pi, format, ap);
2353 proto_tree_add_ether_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2354 const guint8* value, const char *format, ...)
2358 header_field_info *hfinfo;
2360 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2362 pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
2366 TRY_TO_FAKE_THIS_REPR(tree, pi);
2368 va_start(ap, format);
2369 proto_tree_set_representation(pi, format, ap);
2375 /* Set the FT_ETHER value */
2377 proto_tree_set_ether(field_info *fi, const guint8* value)
2379 fvalue_set(&fi->value, (gpointer) value, FALSE);
2383 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start)
2385 proto_tree_set_ether(fi, tvb_get_ptr(tvb, start, FT_ETHER_LEN));
2388 /* Add a FT_BOOLEAN to a proto_tree */
2390 proto_tree_add_boolean(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2395 header_field_info *hfinfo;
2397 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2399 DISSECTOR_ASSERT(hfinfo->type == FT_BOOLEAN);
2401 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2402 proto_tree_set_boolean(new_fi, value);
2408 proto_tree_add_boolean_format_value(proto_tree *tree, int hfindex,
2409 tvbuff_t *tvb, gint start, gint length, guint32 value,
2410 const char *format, ...)
2414 header_field_info *hfinfo;
2416 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2418 pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
2422 TRY_TO_FAKE_THIS_REPR(tree, pi);
2424 va_start(ap, format);
2425 proto_tree_set_representation_value(pi, format, ap);
2432 proto_tree_add_boolean_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2433 guint32 value, const char *format, ...)
2437 header_field_info *hfinfo;
2439 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2441 pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
2445 TRY_TO_FAKE_THIS_REPR(tree, pi);
2447 va_start(ap, format);
2448 proto_tree_set_representation(pi, format, ap);
2454 /* Set the FT_BOOLEAN value */
2456 proto_tree_set_boolean(field_info *fi, guint32 value)
2458 proto_tree_set_uint(fi, value);
2461 /* Add a FT_FLOAT to a proto_tree */
2463 proto_tree_add_float(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2468 header_field_info *hfinfo;
2470 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2472 DISSECTOR_ASSERT(hfinfo->type == FT_FLOAT);
2474 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2475 proto_tree_set_float(new_fi, value);
2481 proto_tree_add_float_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2482 gint start, gint length, float value, const char *format, ...)
2486 header_field_info *hfinfo;
2488 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2490 pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
2494 TRY_TO_FAKE_THIS_REPR(tree, pi);
2496 va_start(ap, format);
2497 proto_tree_set_representation_value(pi, format, ap);
2504 proto_tree_add_float_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2505 float value, const char *format, ...)
2509 header_field_info *hfinfo;
2511 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2513 pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
2517 TRY_TO_FAKE_THIS_REPR(tree, pi);
2519 va_start(ap, format);
2520 proto_tree_set_representation(pi, format, ap);
2526 /* Set the FT_FLOAT value */
2528 proto_tree_set_float(field_info *fi, float value)
2530 fvalue_set_floating(&fi->value, value);
2533 /* Add a FT_DOUBLE to a proto_tree */
2535 proto_tree_add_double(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2540 header_field_info *hfinfo;
2542 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2544 DISSECTOR_ASSERT(hfinfo->type == FT_DOUBLE);
2546 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2547 proto_tree_set_double(new_fi, value);
2553 proto_tree_add_double_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2554 gint start, gint length, double value, const char *format, ...)
2558 header_field_info *hfinfo;
2560 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2562 pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
2566 TRY_TO_FAKE_THIS_REPR(tree, pi);
2568 va_start(ap, format);
2569 proto_tree_set_representation_value(pi, format, ap);
2576 proto_tree_add_double_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2577 double value, const char *format, ...)
2581 header_field_info *hfinfo;
2583 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2585 pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
2589 TRY_TO_FAKE_THIS_REPR(tree, pi);
2591 va_start(ap, format);
2592 proto_tree_set_representation(pi, format, ap);
2598 /* Set the FT_DOUBLE value */
2600 proto_tree_set_double(field_info *fi, double value)
2602 fvalue_set_floating(&fi->value, value);
2605 /* Add FT_UINT{8,16,24,32} to a proto_tree */
2607 proto_tree_add_uint(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2610 proto_item *pi = NULL;
2612 header_field_info *hfinfo;
2614 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2616 switch(hfinfo->type) {
2622 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length,
2624 proto_tree_set_uint(new_fi, value);
2628 DISSECTOR_ASSERT_NOT_REACHED();
2635 proto_tree_add_uint_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2636 gint start, gint length, guint32 value, const char *format, ...)
2640 header_field_info *hfinfo;
2642 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2644 pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
2648 TRY_TO_FAKE_THIS_REPR(tree, pi);
2650 va_start(ap, format);
2651 proto_tree_set_representation_value(pi, format, ap);
2658 proto_tree_add_uint_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2659 guint32 value, const char *format, ...)
2663 header_field_info *hfinfo;
2665 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2667 pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
2671 TRY_TO_FAKE_THIS_REPR(tree, pi);
2673 va_start(ap, format);
2674 proto_tree_set_representation(pi, format, ap);
2680 /* Set the FT_UINT{8,16,24,32} value */
2682 proto_tree_set_uint(field_info *fi, guint32 value)
2684 header_field_info *hfinfo;
2687 hfinfo = fi->hfinfo;
2690 if (hfinfo->bitmask) {
2691 /* Mask out irrelevant portions */
2692 integer &= hfinfo->bitmask;
2695 if (hfinfo->bitshift > 0) {
2696 integer >>= hfinfo->bitshift;
2700 fvalue_set_uinteger(&fi->value, integer);
2703 /* Add FT_UINT64 to a proto_tree */
2705 proto_tree_add_uint64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2708 proto_item *pi = NULL;
2710 header_field_info *hfinfo;
2712 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2714 DISSECTOR_ASSERT(hfinfo->type == FT_UINT64);
2716 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2717 proto_tree_set_uint64(new_fi, value);
2723 proto_tree_add_uint64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2724 gint start, gint length, guint64 value, const char *format, ...)
2728 header_field_info *hfinfo;
2730 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2732 pi = proto_tree_add_uint64(tree, hfindex, tvb, start, length, value);
2736 TRY_TO_FAKE_THIS_REPR(tree, pi);
2738 va_start(ap, format);
2739 proto_tree_set_representation_value(pi, format, ap);
2746 proto_tree_add_uint64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2747 guint64 value, const char *format, ...)
2751 header_field_info *hfinfo;
2753 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2755 pi = proto_tree_add_uint64(tree, hfindex, tvb, start, length, value);
2759 TRY_TO_FAKE_THIS_REPR(tree, pi);
2761 va_start(ap, format);
2762 proto_tree_set_representation(pi, format, ap);
2768 /* Add FT_INT{8,16,24,32} to a proto_tree */
2770 proto_tree_add_int(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2773 proto_item *pi = NULL;
2775 header_field_info *hfinfo;
2777 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2779 switch(hfinfo->type) {
2784 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length,
2786 proto_tree_set_int(new_fi, value);
2790 DISSECTOR_ASSERT_NOT_REACHED();
2797 proto_tree_add_int_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2798 gint start, gint length, gint32 value, const char *format, ...)
2800 proto_item *pi = NULL;
2802 header_field_info *hfinfo;
2804 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2806 pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
2810 TRY_TO_FAKE_THIS_REPR(tree, pi);
2812 va_start(ap, format);
2813 proto_tree_set_representation_value(pi, format, ap);
2820 proto_tree_add_int_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2821 gint32 value, const char *format, ...)
2823 proto_item *pi = NULL;
2825 header_field_info *hfinfo;
2827 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2829 pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
2833 TRY_TO_FAKE_THIS_REPR(tree, pi);
2835 va_start(ap, format);
2836 proto_tree_set_representation(pi, format, ap);
2842 /* Set the FT_INT{8,16,24,32} value */
2844 proto_tree_set_int(field_info *fi, gint32 value)
2846 header_field_info *hfinfo;
2849 hfinfo = fi->hfinfo;
2850 integer = (guint32) value;
2852 if (hfinfo->bitmask) {
2853 /* Mask out irrelevant portions */
2854 integer &= hfinfo->bitmask;
2857 if (hfinfo->bitshift > 0) {
2858 integer >>= hfinfo->bitshift;
2862 fvalue_set_sinteger(&fi->value, integer);
2865 /* Add FT_INT64 to a proto_tree */
2867 proto_tree_add_int64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2870 proto_item *pi = NULL;
2872 header_field_info *hfinfo;
2874 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2876 DISSECTOR_ASSERT(hfinfo->type == FT_INT64);
2878 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2879 proto_tree_set_uint64(new_fi, (guint64)value);
2885 proto_tree_add_int64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2886 gint start, gint length, gint64 value, const char *format, ...)
2890 header_field_info *hfinfo;
2892 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2894 pi = proto_tree_add_int64(tree, hfindex, tvb, start, length, value);
2898 TRY_TO_FAKE_THIS_REPR(tree, pi);
2900 va_start(ap, format);
2901 proto_tree_set_representation_value(pi, format, ap);
2908 proto_tree_add_int64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2909 gint64 value, const char *format, ...)
2913 header_field_info *hfinfo;
2915 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2917 pi = proto_tree_add_int64(tree, hfindex, tvb, start, length, value);
2921 TRY_TO_FAKE_THIS_REPR(tree, pi);
2923 va_start(ap, format);
2924 proto_tree_set_representation(pi, format, ap);
2930 /* Add a field_info struct to the proto_tree, encapsulating it in a proto_node */
2932 proto_tree_add_node(proto_tree *tree, field_info *fi)
2934 proto_node *pnode, *tnode, *sibling;
2938 * Make sure "tree" is ready to have subtrees under it, by
2939 * checking whether it's been given an ett_ value.
2941 * "PNODE_FINFO(tnode)" may be null; that's the case for the root
2942 * node of the protocol tree. That node is not displayed,
2943 * so it doesn't need an ett_ value to remember whether it
2947 tfi = PNODE_FINFO(tnode);
2948 if (tfi != NULL && (tfi->tree_type < 0 || tfi->tree_type >= num_tree_types)) {
2949 REPORT_DISSECTOR_BUG(ep_strdup_printf("\"%s\" - \"%s\" tfi->tree_type: %u invalid (%s:%u)",
2950 fi->hfinfo->name, fi->hfinfo->abbrev, tfi->tree_type, __FILE__, __LINE__));
2951 /* XXX - is it safe to continue here? */
2954 DISSECTOR_ASSERT(tfi == NULL ||
2955 (tfi->tree_type >= 0 && tfi->tree_type < num_tree_types));
2957 PROTO_NODE_NEW(pnode);
2958 pnode->parent = tnode;
2959 PNODE_FINFO(pnode) = fi;
2960 pnode->tree_data = PTREE_DATA(tree);
2962 if (tnode->last_child != NULL) {
2963 sibling = tnode->last_child;
2964 DISSECTOR_ASSERT(sibling->next == NULL);
2965 sibling->next = pnode;
2967 tnode->first_child = pnode;
2968 tnode->last_child = pnode;
2970 return (proto_item*)pnode;
2974 /* Generic way to allocate field_info and add to proto_tree.
2975 * Sets *pfi to address of newly-allocated field_info struct, if pfi is
2978 proto_tree_add_pi(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2979 gint *length, field_info **pfi)
2988 fi = alloc_field_info(tree, hfindex, tvb, start, length);
2989 pi = proto_tree_add_node(tree, fi);
2991 /* If the proto_tree wants to keep a record of this finfo
2992 * for quick lookup, then record it. */
2993 ptrs = proto_lookup_or_create_interesting_hfids(tree, fi->hfinfo);
2995 g_ptr_array_add(ptrs, fi);
2997 /* Does the caller want to know the fi pointer? */
3006 static header_field_info *
3007 get_hfi_and_length(int hfindex, tvbuff_t *tvb, gint start, gint *length,
3010 header_field_info *hfinfo;
3011 gint length_remaining;
3014 * We only allow a null tvbuff if the item has a zero length,
3015 * i.e. if there's no data backing it.
3017 DISSECTOR_ASSERT(tvb != NULL || *length == 0);
3019 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
3022 * XXX - in some protocols, there are 32-bit unsigned length
3023 * fields, so lengths in protocol tree and tvbuff routines
3024 * should really be unsigned. We should have, for those
3025 * field types for which "to the end of the tvbuff" makes sense,
3026 * additional routines that take no length argument and
3027 * add fields that run to the end of the tvbuff.
3029 if (*length == -1) {
3031 * For FT_NONE, FT_PROTOCOL, FT_BYTES, and FT_STRING fields,
3032 * a length of -1 means "set the length to what remains in
3035 * The assumption is either that
3037 * 1) the length of the item can only be determined
3038 * by dissection (typically true of items with
3039 * subitems, which are probably FT_NONE or
3044 * 2) if the tvbuff is "short" (either due to a short
3045 * snapshot length or due to lack of reassembly of
3046 * fragments/segments/whatever), we want to display
3047 * what's available in the field (probably FT_BYTES
3048 * or FT_STRING) and then throw an exception later
3052 * 3) the field is defined to be "what's left in the
3055 * so we set the length to what remains in the tvbuff so
3056 * that, if we throw an exception while dissecting, it
3057 * has what is probably the right value.
3059 * For FT_STRINGZ, it means "the string is null-terminated,
3060 * not null-padded; set the length to the actual length
3061 * of the string", and if the tvbuff if short, we just
3062 * throw an exception.
3064 * It's not valid for any other type of field.
3066 switch (hfinfo->type) {
3070 * We allow this to be zero-length - for
3071 * example, an ONC RPC NULL procedure has
3072 * neither arguments nor reply, so the
3073 * payload for that protocol is empty.
3075 * However, if the length is negative, the
3076 * start offset is *past* the byte past the
3077 * end of the tvbuff, so we throw an
3080 *length = tvb_length_remaining(tvb, start);
3083 * Use "tvb_ensure_bytes_exist()"
3084 * to force the appropriate exception
3087 tvb_ensure_bytes_exist(tvb, start, 0);
3089 DISSECTOR_ASSERT(*length >= 0);
3095 *length = tvb_ensure_length_remaining(tvb, start);
3096 DISSECTOR_ASSERT(*length >= 0);
3101 * Leave the length as -1, so our caller knows
3107 DISSECTOR_ASSERT_NOT_REACHED();
3109 *item_length = *length;
3111 *item_length = *length;
3112 if (hfinfo->type == FT_PROTOCOL || hfinfo->type == FT_NONE) {
3114 * These types are for interior nodes of the
3115 * tree, and don't have data associated with
3116 * them; if the length is negative (XXX - see
3117 * above) or goes past the end of the tvbuff,
3118 * cut it short at the end of the tvbuff.
3119 * That way, if this field is selected in
3120 * Wireshark, we don't highlight stuff past
3121 * the end of the data.
3123 /* XXX - what to do, if we don't have a tvb? */
3125 length_remaining = tvb_length_remaining(tvb, start);
3126 if (*item_length < 0 ||
3127 (*item_length > 0 &&
3128 (length_remaining < *item_length)))
3129 *item_length = length_remaining;
3132 if (*item_length < 0) {
3133 THROW(ReportedBoundsError);
3141 new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
3142 gint start, gint item_length)
3148 fi->hfinfo = hfinfo;
3150 fi->start+=(tvb)?TVB_RAW_OFFSET(tvb):0;
3151 fi->length = item_length;
3154 if (!PTREE_DATA(tree)->visible)
3155 FI_SET_FLAG(fi, FI_HIDDEN);
3156 fvalue_init(&fi->value, fi->hfinfo->type);
3159 /* add the data source tvbuff */
3160 fi->ds_tvb=tvb?TVB_GET_DS_TVB(tvb):NULL;
3162 fi->appendix_start = 0;
3163 fi->appendix_length = 0;
3169 alloc_field_info(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3172 header_field_info *hfinfo;
3175 hfinfo = get_hfi_and_length(hfindex, tvb, start, length, &item_length);
3176 return new_field_info(tree, hfinfo, tvb, start, item_length);
3179 /* If the protocol tree is to be visible, set the representation of a
3180 proto_tree entry with the name of the field for the item and with
3181 the value formatted with the supplied printf-style format and
3184 proto_tree_set_representation_value(proto_item *pi, const char *format, va_list ap)
3186 int ret; /*tmp return value */
3187 field_info *fi = PITEM_FINFO(pi);
3188 header_field_info *hf;
3190 DISSECTOR_ASSERT(fi);
3194 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
3195 ITEM_LABEL_NEW(fi->rep);
3196 if (hf->bitmask && (hf->type == FT_BOOLEAN || IS_FT_UINT(hf->type))) {
3200 val = fvalue_get_uinteger(&fi->value);
3201 if (hf->bitshift > 0) {
3202 val <<= hf->bitshift;
3204 decode_bitfield_value(tmpbuf, val, hf->bitmask, hfinfo_bitwidth(hf));
3205 /* put in the hf name */
3206 ret = g_snprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
3207 "%s%s: ", tmpbuf, fi->hfinfo->name);
3209 /* put in the hf name */
3210 ret = g_snprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
3211 "%s: ", fi->hfinfo->name);
3214 /* If possible, Put in the value of the string */
3215 if (ret < ITEM_LABEL_LENGTH) {
3216 ret += g_vsnprintf(fi->rep->representation + ret,
3217 ITEM_LABEL_LENGTH - ret, format, ap);
3219 if (ret >= ITEM_LABEL_LENGTH) {
3220 /* Uh oh, we don't have enough room. Tell the user
3221 * that the field is truncated.
3225 /* Argh, we cannot reuse 'ap' here. So make a copy
3226 * of what we formatted for (re)use below.
3228 oldrep = g_strdup(fi->rep->representation);
3230 g_snprintf(fi->rep->representation,
3239 /* If the protocol tree is to be visible, set the representation of a
3240 proto_tree entry with the representation formatted with the supplied
3241 printf-style format and argument list. */
3243 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap)
3245 int ret; /*tmp return value */
3246 field_info *fi = PITEM_FINFO(pi);
3248 DISSECTOR_ASSERT(fi);
3250 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
3251 ITEM_LABEL_NEW(fi->rep);
3252 ret = g_vsnprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
3254 if (ret >= ITEM_LABEL_LENGTH) {
3255 /* Uh oh, we don't have enough room. Tell the user
3256 * that the field is truncated.
3260 /* Argh, we cannot reuse 'ap' here. So make a copy
3261 * of what we formatted for (re)use below.
3263 oldrep = g_strdup(fi->rep->representation);
3265 g_snprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
3266 "[truncated] %s", oldrep);
3272 /* -------------------------- */
3274 proto_custom_set(proto_tree* tree, int field_id,
3276 gchar *expr, int size )
3282 guint32 n_addr; /* network-order IPv4 address */
3284 const true_false_string *tfstring;
3288 header_field_info* hfinfo;
3290 g_assert(field_id >= 0);
3292 hfinfo = proto_registrar_get_nth((guint)field_id);
3294 /* do we need to rewind ? */
3299 finfos = proto_get_finfo_ptr_array(tree, hfinfo->id);
3301 if (!finfos || !(len = g_ptr_array_len(finfos))) {
3302 hfinfo = hfinfo->same_name_next;
3305 /* get the last one */
3306 finfo = g_ptr_array_index(finfos, len -1);
3308 switch(hfinfo->type) {
3312 bytes = fvalue_get(&finfo->value);
3313 g_strlcpy(result, bytes_to_str(bytes, fvalue_length(&finfo->value)), size);
3316 case FT_ABSOLUTE_TIME:
3317 g_strlcpy(result, abs_time_to_str(fvalue_get(&finfo->value)), size);
3320 case FT_RELATIVE_TIME:
3321 g_strlcpy(result, rel_time_to_secs_str(fvalue_get(&finfo->value)), size);
3325 u_integer = fvalue_get_uinteger(&finfo->value);
3326 tfstring = (const true_false_string *)&tfs_true_false;
3327 if (hfinfo->strings) {
3328 tfstring = (const struct true_false_string*) hfinfo->strings;
3330 g_strlcpy(result, u_integer ? tfstring->true_string : tfstring->false_string, size);
3338 u_integer = fvalue_get_uinteger(&finfo->value);
3339 if (hfinfo->strings) {
3340 if (hfinfo->display & BASE_RANGE_STRING) {
3341 g_strlcpy(result, rval_to_str(u_integer, hfinfo->strings, "%u"), size);
3343 g_strlcpy(result, val_to_str(u_integer, cVALS(hfinfo->strings), "%u"), size);
3345 } else if (IS_BASE_DUAL(hfinfo->display)) {
3346 g_snprintf(result, size, hfinfo_uint_value_format(hfinfo), u_integer, u_integer);
3348 g_snprintf(result, size, hfinfo_uint_value_format(hfinfo), u_integer);
3354 g_snprintf(result, size, "%" G_GINT64_MODIFIER "u", fvalue_get_integer64(&finfo->value));
3357 /* XXX - make these just FT_INT? */
3362 integer = fvalue_get_sinteger(&finfo->value);
3363 if (hfinfo->strings) {
3364 if (hfinfo->display & BASE_RANGE_STRING) {
3365 g_strlcpy(result, rval_to_str(integer, hfinfo->strings, "%d"), size);
3367 g_strlcpy(result, val_to_str(integer, cVALS(hfinfo->strings), "%d"), size);
3369 } else if (IS_BASE_DUAL(hfinfo->display)) {
3370 g_snprintf(result, size, hfinfo_int_value_format(hfinfo), integer, integer);
3372 g_snprintf(result, size, hfinfo_int_value_format(hfinfo), integer);
3377 ipv4 = fvalue_get(&finfo->value);
3378 n_addr = ipv4_get_net_order_addr(ipv4);
3379 g_strlcpy(result, ip_to_str((guint8 *)&n_addr), size);
3383 g_strlcpy(result, bytes_to_str_punct(fvalue_get(&finfo->value), 6, ':'), size);
3387 g_strlcpy(result, guid_to_str((e_guid_t *)fvalue_get(&finfo->value)), size);
3391 bytes = fvalue_get(&finfo->value);
3392 g_strlcpy(result, oid_resolved_from_encoded(bytes, fvalue_length(&finfo->value)), size);
3396 g_snprintf(result, size, "%." STRINGIFY(FLT_DIG) "f", fvalue_get_floating(&finfo->value));
3400 g_snprintf(result, size, "%." STRINGIFY(DBL_DIG) "g", fvalue_get_floating(&finfo->value));
3406 case FT_UINT_STRING:
3407 bytes = fvalue_get(&finfo->value);
3408 g_strlcpy(result, format_text(bytes, strlen(bytes)), size);
3411 case FT_IPXNET: /*XXX really No column custom ?*/
3414 g_error("hfinfo->type %d (%s) not handled\n",
3416 ftype_name(hfinfo->type));
3417 DISSECTOR_ASSERT_NOT_REACHED();
3421 switch(hfinfo->type) {
3425 case FT_UINT_STRING:
3426 g_snprintf(expr, size, "\"%s\"",result);
3428 g_strlcpy(expr, result, size);
3431 return hfinfo->abbrev;
3437 /* Set text of proto_item after having already been created. */
3439 proto_item_set_text(proto_item *pi, const char *format, ...)
3441 field_info *fi = NULL;
3448 fi = PITEM_FINFO(pi);
3453 ITEM_LABEL_FREE(fi->rep);
3456 va_start(ap, format);
3457 proto_tree_set_representation(pi, format, ap);
3461 /* Append to text of proto_item after having already been created. */
3463 proto_item_append_text(proto_item *pi, const char *format, ...)
3465 field_info *fi = NULL;
3473 fi = PITEM_FINFO(pi);
3478 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
3479 va_start(ap, format);
3482 * If we don't already have a representation,
3483 * generate the default representation.
3485 if (fi->rep == NULL) {
3486 ITEM_LABEL_NEW(fi->rep);
3487 proto_item_fill_label(fi, fi->rep->representation);
3490 curlen = strlen(fi->rep->representation);
3491 if (ITEM_LABEL_LENGTH > curlen) {
3492 g_vsnprintf(fi->rep->representation + curlen,
3493 ITEM_LABEL_LENGTH - (gulong) curlen, format, ap);
3500 proto_item_set_len(proto_item *pi, gint length)
3507 fi = PITEM_FINFO(pi);
3511 DISSECTOR_ASSERT(length >= 0);
3512 fi->length = length;
3514 if (fi->value.ftype->ftype == FT_BYTES)
3515 fi->value.value.bytes->len = length;
3519 * Sets the length of the item based on its start and on the specified
3520 * offset, which is the offset past the end of the item; as the start
3521 * in the item is relative to the beginning of the data source tvbuff,
3522 * we need to pass in a tvbuff - the end offset is relative to the beginning
3526 proto_item_set_end(proto_item *pi, tvbuff_t *tvb, gint end)
3533 fi = PITEM_FINFO(pi);
3537 end += TVB_RAW_OFFSET(tvb);
3538 DISSECTOR_ASSERT(end >= fi->start);
3539 fi->length = end - fi->start;
3543 proto_item_get_len(proto_item *pi)
3545 field_info *fi = PITEM_FINFO(pi);
3546 return fi ? fi->length : -1;
3550 /** clear flags according to the mask and set new flag values */
3551 #define FI_REPLACE_FLAGS(fi, mask, flags_in) { \
3552 (fi->flags = (fi)->flags & ~(mask)); \
3553 (fi->flags = (fi)->flags | (flags_in)); \
3557 proto_item_set_expert_flags(proto_item *pi, int group, guint severity)
3559 if(pi == NULL || PITEM_FINFO(pi) == NULL)
3562 /* only change things if severity is worse or at least equal than before */
3563 if(severity >= FI_GET_FLAG(PITEM_FINFO(pi), PI_SEVERITY_MASK)) {
3564 FI_REPLACE_FLAGS(PITEM_FINFO(pi), PI_GROUP_MASK, group);
3565 FI_REPLACE_FLAGS(PITEM_FINFO(pi), PI_SEVERITY_MASK, severity);
3574 proto_tree_create_root(void)
3578 /* Initialize the proto_node */
3579 PROTO_NODE_NEW(pnode);
3580 pnode->parent = NULL;
3581 PNODE_FINFO(pnode) = NULL;
3582 pnode->tree_data = g_new(tree_data_t, 1);
3584 /* Don't initialize the tree_data_t. Wait until we know we need it */
3585 pnode->tree_data->interesting_hfids = NULL;
3587 /* Set the default to FALSE so it's easier to
3588 * find errors; if we expect to see the protocol tree
3589 * but for some reason the default 'visible' is not
3590 * changed, then we'll find out very quickly. */
3591 pnode->tree_data->visible = FALSE;
3593 /* Make sure that we fake protocols (if possible) */
3594 pnode->tree_data->fake_protocols = TRUE;
3596 /* Keep track of the number of children */
3597 pnode->tree_data->count = 0;
3599 return (proto_tree*) pnode;
3603 /* "prime" a proto_tree with a single hfid that a dfilter
3604 * is interested in. */
3606 proto_tree_prime_hfid(proto_tree *tree _U_, gint hfid)
3608 header_field_info *hfinfo;
3610 PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
3611 /* this field is referenced by a filter so increase the refcount.
3612 also increase the refcount for the parent, i.e the protocol.
3614 hfinfo->ref_type = HF_REF_TYPE_DIRECT;
3615 /* only increase the refcount if there is a parent.
3616 if this is a protocol and not a field then parent will be -1
3617 and there is no parent to add any refcounting for.
3619 if (hfinfo->parent != -1) {
3620 header_field_info *parent_hfinfo;
3621 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
3623 /* Mark parent as indirectly referenced unless it is already directly
3624 * referenced, i.e. the user has specified the parent in a filter.
3626 if (parent_hfinfo->ref_type != HF_REF_TYPE_DIRECT)
3627 parent_hfinfo->ref_type = HF_REF_TYPE_INDIRECT;
3632 proto_item_add_subtree(proto_item *pi, gint idx) {
3638 DISSECTOR_ASSERT(idx >= 0 && idx < num_tree_types);
3640 fi = PITEM_FINFO(pi);
3642 return (proto_tree*) pi;
3644 fi->tree_type = idx;
3646 return (proto_tree*) pi;
3650 proto_item_get_subtree(proto_item *pi) {
3655 fi = PITEM_FINFO(pi);
3656 if ( (!fi) || (fi->tree_type == -1) )
3658 return (proto_tree*) pi;
3662 proto_item_get_parent(proto_item *ti) {
3669 proto_item_get_parent_nth(proto_item *ti, int gen) {
3682 proto_tree_get_parent(proto_tree *tree) {
3685 return (proto_item*) tree;
3689 proto_tree_get_root(proto_tree *tree) {
3692 while (tree->parent) {
3693 tree = tree->parent;
3699 proto_tree_move_item(proto_tree *tree, proto_item *fixed_item, proto_item *item_to_move)
3701 /* This function doesn't generate any values. It only reorganizes the prococol tree
3702 * so we can bail out immediately if it isn't visible. */
3703 if (!tree || !PTREE_DATA(tree)->visible)
3706 DISSECTOR_ASSERT(item_to_move->parent == tree);
3707 DISSECTOR_ASSERT(fixed_item->parent == tree);
3709 /*** cut item_to_move out ***/
3711 /* is item_to_move the first? */
3712 if(tree->first_child == item_to_move) {
3713 /* simply change first child to next */
3714 tree->first_child = item_to_move->next;
3716 DISSECTOR_ASSERT(tree->last_child != item_to_move);
3718 proto_item *curr_item;
3719 /* find previous and change it's next */
3720 for(curr_item = tree->first_child; curr_item != NULL; curr_item = curr_item->next) {
3721 if(curr_item->next == item_to_move) {
3726 DISSECTOR_ASSERT(curr_item);
3728 curr_item->next = item_to_move->next;
3730 /* fix last_child if required */
3731 if(tree->last_child == item_to_move) {
3732 tree->last_child = curr_item;
3736 /*** insert to_move after fixed ***/
3737 item_to_move->next = fixed_item->next;
3738 fixed_item->next = item_to_move;
3739 if(tree->last_child == fixed_item) {
3740 tree->last_child = item_to_move;
3745 proto_tree_set_appendix(proto_tree *tree, tvbuff_t *tvb, gint start, gint length)
3752 fi = PTREE_FINFO(tree);
3756 start += TVB_RAW_OFFSET(tvb);
3757 DISSECTOR_ASSERT(start >= 0);
3758 DISSECTOR_ASSERT(length >= 0);
3760 fi->appendix_start = start;
3761 fi->appendix_length = length;
3765 proto_register_protocol(const char *name, const char *short_name, const char *filter_name)
3767 protocol_t *protocol;
3768 header_field_info *hfinfo;
3770 char *existing_name;
3774 gboolean found_invalid;
3777 * Make sure there's not already a protocol with any of those
3778 * names. Crash if there is, as that's an error in the code
3779 * or an inappropriate plugin.
3780 * This situation has to be fixed to not register more than one
3781 * protocol with the same name.
3783 * This is done by reducing the number of strcmp (and alike) calls as much as possible,
3784 * as this significally slows down startup time.
3786 * Drawback: As a hash value is used to reduce insert time,
3787 * this might lead to a hash collision.
3788 * However, as we have around 500+ protocols and we're using a 32 bit int this is very,
3792 key = g_malloc (sizeof(gint));
3793 *key = wrs_str_hash(name);
3794 existing_name = g_hash_table_lookup(proto_names, key);
3795 if (existing_name != NULL) {
3796 /* g_error will terminate the program */
3797 g_error("Duplicate protocol name \"%s\"!"
3798 " This might be caused by an inappropriate plugin or a development error.", name);
3800 g_hash_table_insert(proto_names, key, (gpointer)name);
3802 existing_name = g_hash_table_lookup(proto_short_names, (gpointer)short_name);
3803 if (existing_name != NULL) {
3804 g_error("Duplicate protocol short_name \"%s\"!"
3805 " This might be caused by an inappropriate plugin or a development error.", short_name);
3807 g_hash_table_insert(proto_short_names, (gpointer)short_name, (gpointer)short_name);
3809 found_invalid = FALSE;
3810 for (i = 0; i < strlen(filter_name); i++) {
3812 if (!(islower(c) || isdigit(c) || c == '-' || c == '_' || c == '.')) {
3813 found_invalid = TRUE;
3816 if (found_invalid) {
3817 g_error("Protocol filter name \"%s\" has one or more invalid characters."
3818 " Allowed are lower characters, digits, '-', '_' and '.'."
3819 " This might be caused by an inappropriate plugin or a development error.", filter_name);
3821 existing_name = g_hash_table_lookup(proto_filter_names, (gpointer)filter_name);
3822 if (existing_name != NULL) {
3823 g_error("Duplicate protocol filter_name \"%s\"!"
3824 " This might be caused by an inappropriate plugin or a development error.", filter_name);
3826 g_hash_table_insert(proto_filter_names, (gpointer)filter_name, (gpointer)filter_name);
3828 /* Add this protocol to the list of known protocols; the list
3829 is sorted by protocol short name. */
3830 protocol = g_malloc(sizeof (protocol_t));
3831 protocol->name = name;
3832 protocol->short_name = short_name;
3833 protocol->filter_name = filter_name;
3834 protocol->fields = NULL;
3835 protocol->is_enabled = TRUE; /* protocol is enabled by default */
3836 protocol->can_toggle = TRUE;
3837 protocol->is_private = FALSE;
3838 /* list will be sorted later by name, when all protocols completed registering */
3839 protocols = g_list_prepend(protocols, protocol);
3841 /* Here we do allocate a new header_field_info struct */
3842 hfinfo = g_mem_chunk_alloc(gmc_hfinfo);
3843 hfinfo->name = name;
3844 hfinfo->abbrev = filter_name;
3845 hfinfo->type = FT_PROTOCOL;
3846 hfinfo->display = BASE_NONE;
3847 hfinfo->strings = protocol;
3848 hfinfo->bitmask = 0;
3849 hfinfo->bitshift = 0;
3850 hfinfo->ref_type = HF_REF_TYPE_NONE;
3851 hfinfo->blurb = NULL;
3852 hfinfo->parent = -1; /* this field differentiates protos and fields */
3854 proto_id = proto_register_field_init(hfinfo, hfinfo->parent);
3855 protocol->proto_id = proto_id;
3860 proto_mark_private(int proto_id)
3862 protocol_t *protocol = find_protocol_by_id(proto_id);
3864 protocol->is_private = TRUE;
3868 proto_is_private(int proto_id)
3870 protocol_t *protocol = find_protocol_by_id(proto_id);
3872 return protocol->is_private;
3878 * Routines to use to iterate over the protocols.
3879 * The argument passed to the iterator routines is an opaque cookie to
3880 * their callers; it's the GList pointer for the current element in
3882 * The ID of the protocol is returned, or -1 if there is no protocol.
3885 proto_get_first_protocol(void **cookie)
3887 protocol_t *protocol;
3889 if (protocols == NULL)
3891 *cookie = protocols;
3892 protocol = protocols->data;
3893 return protocol->proto_id;
3897 proto_get_next_protocol(void **cookie)
3899 GList *list_item = *cookie;
3900 protocol_t *protocol;
3902 list_item = g_list_next(list_item);
3903 if (list_item == NULL)
3905 *cookie = list_item;
3906 protocol = list_item->data;
3907 return protocol->proto_id;
3911 proto_get_first_protocol_field(int proto_id, void **cookie)
3913 protocol_t *protocol = find_protocol_by_id(proto_id);
3914 hf_register_info *ptr;
3916 if ((protocol == NULL) || (protocol->fields == NULL))
3919 *cookie = protocol->fields;
3920 ptr = protocol->fields->data;
3921 return &ptr->hfinfo;
3925 proto_get_next_protocol_field(void **cookie)
3927 GList *list_item = *cookie;
3928 hf_register_info *ptr;
3930 list_item = g_list_next(list_item);
3931 if (list_item == NULL)
3934 *cookie = list_item;
3935 ptr = list_item->data;
3936 return &ptr->hfinfo;
3940 find_protocol_by_id(int proto_id)
3942 header_field_info *hfinfo;
3947 PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
3948 DISSECTOR_ASSERT(hfinfo->type==FT_PROTOCOL);
3949 return (protocol_t *)hfinfo->strings;
3952 static gint compare_filter_name(gconstpointer proto_arg,
3953 gconstpointer filter_name)
3955 const protocol_t *protocol = proto_arg;
3956 const gchar* f_name = filter_name;
3958 return (strcmp(protocol->filter_name, f_name));
3962 proto_get_id(protocol_t *protocol)
3964 return protocol->proto_id;
3967 int proto_get_id_by_filter_name(const gchar* filter_name)
3970 protocol_t *protocol;
3972 list_entry = g_list_find_custom(protocols, filter_name,
3973 compare_filter_name);
3975 if (list_entry == NULL)
3977 protocol = list_entry->data;
3978 return protocol->proto_id;
3982 proto_get_protocol_name(int proto_id)
3984 protocol_t *protocol;
3986 protocol = find_protocol_by_id(proto_id);
3987 return protocol->name;
3991 proto_get_protocol_short_name(protocol_t *protocol)
3993 if (protocol == NULL)
3995 return protocol->short_name;
3999 proto_get_protocol_long_name(protocol_t *protocol)
4001 if (protocol == NULL)
4003 return protocol->name;
4007 proto_get_protocol_filter_name(int proto_id)
4009 protocol_t *protocol;
4011 protocol = find_protocol_by_id(proto_id);
4012 if (protocol == NULL)
4014 return protocol->filter_name;
4018 proto_is_protocol_enabled(protocol_t *protocol)
4020 return protocol->is_enabled;
4024 proto_can_toggle_protocol(int proto_id)
4026 protocol_t *protocol;
4028 protocol = find_protocol_by_id(proto_id);
4029 return protocol->can_toggle;
4033 proto_set_decoding(int proto_id, gboolean enabled)
4035 protocol_t *protocol;
4037 protocol = find_protocol_by_id(proto_id);
4038 DISSECTOR_ASSERT(protocol->can_toggle);
4039 protocol->is_enabled = enabled;
4043 proto_enable_all(void)
4045 protocol_t *protocol;
4046 GList *list_item = protocols;
4048 if (protocols == NULL)
4052 protocol = list_item->data;
4053 if (protocol->can_toggle)
4054 protocol->is_enabled = TRUE;
4055 list_item = g_list_next(list_item);
4060 proto_set_cant_toggle(int proto_id)
4062 protocol_t *protocol;
4064 protocol = find_protocol_by_id(proto_id);
4065 protocol->can_toggle = FALSE;
4068 /* for use with static arrays only, since we don't allocate our own copies
4069 of the header_field_info struct contained within the hf_register_info struct */
4071 proto_register_field_array(int parent, hf_register_info *hf, int num_records)
4074 hf_register_info *ptr = hf;
4077 proto = find_protocol_by_id(parent);
4078 for (i = 0; i < num_records; i++, ptr++) {
4080 * Make sure we haven't registered this yet.
4081 * Most fields have variables associated with them
4082 * that are initialized to -1; some have array elements,
4083 * or possibly uninitialized variables, so we also allow
4084 * 0 (which is unlikely to be the field ID we get back
4085 * from "proto_register_field_init()").
4087 if (*ptr->p_id != -1 && *ptr->p_id != 0) {
4089 "Duplicate field detected in call to proto_register_field_array: %s is already registered\n",
4090 ptr->hfinfo.abbrev);
4094 if (proto != NULL) {
4095 if (proto->fields == NULL) {
4096 proto->fields = g_list_append(NULL, ptr);
4097 proto->last_field = proto->fields;
4100 g_list_append(proto->last_field, ptr)->next;
4103 field_id = proto_register_field_init(&ptr->hfinfo, parent);
4104 *ptr->p_id = field_id;
4108 /* chars allowed in field abbrev */
4110 const guchar fld_abbrev_chars[256] = {
4111 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00-0x0F */
4112 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10-0x1F */
4113 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, /* 0x20-0x2F '-', '.' */
4114 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 0x30-0x3F '0'-'9' */
4115 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x40-0x4F 'A'-'O' */
4116 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 0x50-0x5F 'P'-'Z', '_' */
4117 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x60-0x6F 'a'-'o' */
4118 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 0x70-0x7F 'p'-'z' */
4119 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80-0x8F */
4120 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90-0x9F */
4121 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xA0-0xAF */
4122 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xB0-0xBF */
4123 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xC0-0xCF */
4124 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xD0-0xDF */
4125 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xE0-0xEF */
4126 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xF0-0xFF */
4129 /* temporary function containing assert part for easier profiling */
4130 static void tmp_fld_check_assert(header_field_info *hfinfo) {
4131 /* The field must have a name (with length > 0) */
4132 DISSECTOR_ASSERT(hfinfo->name && hfinfo->name[0]);
4134 /* fields with an empty string for an abbreviation aren't filterable */
4135 DISSECTOR_ASSERT(hfinfo->abbrev);
4137 /* These types of fields are allowed to have value_strings, true_false_strings or a protocol_t struct*/
4138 DISSECTOR_ASSERT((hfinfo->strings == NULL) || (
4139 (hfinfo->type == FT_UINT8) ||
4140 (hfinfo->type == FT_UINT16) ||
4141 (hfinfo->type == FT_UINT24) ||
4142 (hfinfo->type == FT_UINT32) ||
4143 (hfinfo->type == FT_INT8) ||
4144 (hfinfo->type == FT_INT16) ||
4145 (hfinfo->type == FT_INT24) ||
4146 (hfinfo->type == FT_INT32) ||
4147 (hfinfo->type == FT_BOOLEAN) ||
4148 (hfinfo->type == FT_PROTOCOL) ||
4149 (hfinfo->type == FT_FRAMENUM) ));
4151 switch (hfinfo->type) {
4158 /* Hexadecimal and octal are, in printf() and everywhere else,
4159 * unsigned so don't allow dissectors to register a signed
4160 * field to be displayed unsigned. (Else how would we
4161 * display values negative values?)
4163 * If you want to take out this check, be sure to fix
4164 * hfinfo_numeric_format() so that it does not assert out
4165 * when trying to construct a hexadecimal representation of
4168 DISSECTOR_ASSERT(hfinfo->display != BASE_HEX &&
4169 hfinfo->display != BASE_HEX_DEC &&
4170 hfinfo->display != BASE_DEC_HEX &&
4171 hfinfo->display != BASE_OCT);
4177 if (hfinfo->strings == NULL) {
4178 /* Require integral types (other than frame number, which is
4179 always displayed in decimal) to have a number base */
4180 DISSECTOR_ASSERT(hfinfo->display != BASE_NONE);
4185 DISSECTOR_ASSERT(hfinfo->display != BASE_NONE);
4190 DISSECTOR_ASSERT(hfinfo->display == BASE_NONE);
4191 DISSECTOR_ASSERT(hfinfo->bitmask == 0);
4198 DISSECTOR_ASSERT(hfinfo->display == BASE_NONE);
4199 DISSECTOR_ASSERT(hfinfo->bitmask == 0);
4200 DISSECTOR_ASSERT(hfinfo->strings == NULL);
4206 proto_register_field_init(header_field_info *hfinfo, int parent)
4209 tmp_fld_check_assert(hfinfo);
4211 /* if this is a bitfield, compute bitshift */
4212 if (hfinfo->bitmask) {
4213 hfinfo->bitshift = wrs_count_bitshift(hfinfo->bitmask);
4216 hfinfo->parent = parent;
4217 hfinfo->same_name_next = NULL;
4218 hfinfo->same_name_prev = NULL;
4220 /* if we always add and never delete, then id == len - 1 is correct */
4221 if(gpa_hfinfo.len>=gpa_hfinfo.allocated_len){
4222 if(!gpa_hfinfo.hfi){
4223 gpa_hfinfo.allocated_len=1000;
4224 gpa_hfinfo.hfi=g_malloc(sizeof(header_field_info *)*1000);
4226 gpa_hfinfo.allocated_len+=1000;
4227 gpa_hfinfo.hfi=g_realloc(gpa_hfinfo.hfi, sizeof(header_field_info *)*gpa_hfinfo.allocated_len);
4230 gpa_hfinfo.hfi[gpa_hfinfo.len]=hfinfo;
4232 hfinfo->id = gpa_hfinfo.len - 1;
4234 /* if we have real names, enter this field in the name tree */
4235 if ((hfinfo->name[0] != 0) && (hfinfo->abbrev[0] != 0 )) {
4237 header_field_info *same_name_next_hfinfo;
4240 /* Check that the filter name (abbreviation) is legal;
4241 * it must contain only alphanumerics, '-', "_", and ".". */
4242 c = wrs_check_charset(fld_abbrev_chars, hfinfo->abbrev);
4244 fprintf(stderr, "OOPS: '%c' in '%s'\n", c, hfinfo->abbrev);
4245 DISSECTOR_ASSERT(!c);
4248 /* We allow multiple hfinfo's to be registered under the same
4249 * abbreviation. This was done for X.25, as, depending
4250 * on whether it's modulo-8 or modulo-128 operation,
4251 * some bitfield fields may be in different bits of
4252 * a byte, and we want to be able to refer to that field
4253 * with one name regardless of whether the packets
4254 * are modulo-8 or modulo-128 packets. */
4256 same_name_hfinfo = NULL;
4258 g_tree_insert(gpa_name_tree, (gpointer) (hfinfo->abbrev), hfinfo);
4259 /* GLIB 2.x - if it is already present
4260 * the previous hfinfo with the same name is saved
4261 * to same_name_hfinfo by value destroy callback */
4262 if (same_name_hfinfo) {
4263 /* There's already a field with this name.
4264 * Put it after that field in the list of
4265 * fields with this name, then allow the code
4266 * after this if{} block to replace the old
4267 * hfinfo with the new hfinfo in the GTree. Thus,
4268 * we end up with a linked-list of same-named hfinfo's,
4269 * with the root of the list being the hfinfo in the GTree */
4270 same_name_next_hfinfo =
4271 same_name_hfinfo->same_name_next;
4273 hfinfo->same_name_next = same_name_next_hfinfo;
4274 if (same_name_next_hfinfo)
4275 same_name_next_hfinfo->same_name_prev = hfinfo;
4277 same_name_hfinfo->same_name_next = hfinfo;
4278 hfinfo->same_name_prev = same_name_hfinfo;
4286 proto_register_subtree_array(gint *const *indices, int num_indices)
4289 gint *const *ptr = indices;
4292 * If we've already allocated the array of tree types, expand
4293 * it; this lets plugins such as mate add tree types after
4294 * the initial startup. (If we haven't already allocated it,
4295 * we don't allocate it; on the first pass, we just assign
4296 * ett values and keep track of how many we've assigned, and
4297 * when we're finished registering all dissectors we allocate
4298 * the array, so that we do only one allocation rather than
4299 * wasting CPU time and memory by growing the array for each
4300 * dissector that registers ett values.)
4302 if (tree_is_expanded != NULL) {
4304 g_realloc(tree_is_expanded,
4305 (num_tree_types+num_indices)*sizeof (gboolean));
4306 memset(tree_is_expanded + num_tree_types, 0,
4307 num_indices*sizeof (gboolean));
4311 * Assign "num_indices" subtree numbers starting at "num_tree_types",
4312 * returning the indices through the pointers in the array whose
4313 * first element is pointed to by "indices", and update
4314 * "num_tree_types" appropriately.
4316 for (i = 0; i < num_indices; i++, ptr++, num_tree_types++) {
4318 /* g_error will terminate the program */
4319 g_error("register_subtree_array: subtree item type (ett_...) not -1 !"
4320 " This is a development error:"
4321 " Either the subtree item type has already been assigned or"
4322 " was not initialized to -1.");
4324 **ptr = num_tree_types;
4329 proto_item_fill_label(field_info *fi, gchar *label_str)
4331 header_field_info *hfinfo;
4337 guint32 n_addr; /* network-order IPv4 address */
4339 int ret; /*tmp return value */
4344 /* XXX: Check validity of hfinfo->type */
4348 hfinfo = fi->hfinfo;
4350 switch(hfinfo->type) {
4353 g_strlcpy(label_str, hfinfo->name, ITEM_LABEL_LENGTH);
4357 fill_label_boolean(fi, label_str);
4362 bytes = fvalue_get(&fi->value);
4364 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4365 "%s: %s", hfinfo->name,
4366 bytes_to_str(bytes, fvalue_length(&fi->value)));
4367 if (ret >= ITEM_LABEL_LENGTH) {
4368 /* Uh oh, we don't have enough room. Tell the
4369 * user that the field is truncated.
4371 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4372 "%s [truncated]: %s",
4374 bytes_to_str(bytes, fvalue_length(&fi->value)));
4378 g_snprintf(label_str, ITEM_LABEL_LENGTH, "%s: <MISSING>", hfinfo->name);
4382 /* Four types of integers to take care of:
4383 * Bitfield, with val_string
4384 * Bitfield, w/o val_string
4385 * Non-bitfield, with val_string
4386 * Non-bitfield, w/o val_string
4392 if (hfinfo->bitmask) {
4393 fill_label_bitfield(fi, label_str);
4395 fill_label_uint(fi, label_str);
4400 fill_label_uint(fi, label_str);
4404 fill_label_uint64(fi, label_str);
4411 DISSECTOR_ASSERT(!hfinfo->bitmask);
4412 fill_label_int(fi, label_str);
4416 fill_label_int64(fi, label_str);
4420 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4421 "%s: %." STRINGIFY(FLT_DIG) "f",
4422 hfinfo->name, fvalue_get_floating(&fi->value));
4426 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4427 "%s: %." STRINGIFY(DBL_DIG) "g",
4428 hfinfo->name, fvalue_get_floating(&fi->value));
4431 case FT_ABSOLUTE_TIME:
4432 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4433 "%s: %s", hfinfo->name,
4434 abs_time_to_str(fvalue_get(&fi->value)));
4437 case FT_RELATIVE_TIME:
4438 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4439 "%s: %s seconds", hfinfo->name,
4440 rel_time_to_secs_str(fvalue_get(&fi->value)));
4444 integer = fvalue_get_uinteger(&fi->value);
4445 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4446 "%s: %s (0x%08X)", hfinfo->name,
4447 get_ipxnet_name(integer), integer);
4451 bytes = fvalue_get(&fi->value);
4452 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4453 "%s: %s (%s)", hfinfo->name,
4454 get_ether_name(bytes),
4455 ether_to_str(bytes));
4459 ipv4 = fvalue_get(&fi->value);
4460 n_addr = ipv4_get_net_order_addr(ipv4);
4461 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4462 "%s: %s (%s)", hfinfo->name,
4463 get_hostname(n_addr),
4464 ip_to_str((guint8*)&n_addr));
4468 bytes = fvalue_get(&fi->value);
4469 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4470 "%s: %s (%s)", hfinfo->name,
4471 get_hostname6((struct e_in6_addr *)bytes),
4472 ip6_to_str((struct e_in6_addr*)bytes));
4476 guid = fvalue_get(&fi->value);
4477 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4478 "%s: %s", hfinfo->name,
4483 bytes = fvalue_get(&fi->value);
4484 name = oid_resolved_from_encoded(bytes, fvalue_length(&fi->value));
4486 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4487 "%s: %s (%s)", hfinfo->name,
4488 oid_encoded2string(bytes, fvalue_length(&fi->value)), name);
4490 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4491 "%s: %s", hfinfo->name,
4492 oid_encoded2string(bytes, fvalue_length(&fi->value)));
4499 case FT_UINT_STRING:
4500 bytes = fvalue_get(&fi->value);
4501 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4502 "%s: %s", hfinfo->name,
4503 format_text(bytes, strlen(bytes)));
4504 if (ret >= ITEM_LABEL_LENGTH) {
4505 /* Uh oh, we don't have enough room. Tell the
4506 * user that the field is truncated.
4508 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4509 "%s [truncated]: %s",
4511 format_text(bytes, strlen(bytes)));
4516 g_error("hfinfo->type %d (%s) not handled\n",
4518 ftype_name(hfinfo->type));
4519 DISSECTOR_ASSERT_NOT_REACHED();
4525 fill_label_boolean(field_info *fi, gchar *label_str)
4527 char *p = label_str;
4528 int bitfield_byte_length = 0, bitwidth;
4529 guint32 unshifted_value;
4532 header_field_info *hfinfo = fi->hfinfo;
4533 const true_false_string *tfstring = (const true_false_string *)&tfs_true_false;
4535 if (hfinfo->strings) {
4536 tfstring = (const struct true_false_string*) hfinfo->strings;
4539 value = fvalue_get_uinteger(&fi->value);
4540 if (hfinfo->bitmask) {
4541 /* Figure out the bit width */
4542 bitwidth = hfinfo_bitwidth(hfinfo);
4545 unshifted_value = value;
4546 if (hfinfo->bitshift > 0) {
4547 unshifted_value <<= hfinfo->bitshift;
4550 /* Create the bitfield first */
4551 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
4552 bitfield_byte_length = (int) (p - label_str);
4555 /* Fill in the textual info */
4556 g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
4557 "%s: %s", hfinfo->name,
4558 value ? tfstring->true_string : tfstring->false_string);
4561 /* Fills data for bitfield ints with val_strings */
4563 fill_label_bitfield(field_info *fi, gchar *label_str)
4565 const char *format = NULL;
4567 int bitfield_byte_length, bitwidth;
4568 guint32 unshifted_value;
4571 header_field_info *hfinfo = fi->hfinfo;
4573 /* Figure out the bit width */
4574 bitwidth = hfinfo_bitwidth(hfinfo);
4577 unshifted_value = fvalue_get_uinteger(&fi->value);
4578 value = unshifted_value;
4579 if (hfinfo->bitshift > 0) {
4580 unshifted_value <<= hfinfo->bitshift;
4583 /* Create the bitfield first */
4584 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
4585 bitfield_byte_length = (int) (p - label_str);
4587 /* Fill in the textual info using stored (shifted) value */
4588 if (hfinfo->display == BASE_CUSTOM) {
4589 gchar tmp[ITEM_LABEL_LENGTH];
4590 custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hfinfo->strings;
4592 DISSECTOR_ASSERT(fmtfunc);
4593 fmtfunc(tmp, value);
4594 g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
4595 "%s: %s", hfinfo->name, tmp);
4597 else if (hfinfo->strings) {
4598 format = hfinfo_uint_vals_format(hfinfo);
4599 if (hfinfo->display & BASE_RANGE_STRING) {
4600 g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
4601 format, hfinfo->name,
4602 rval_to_str(value, hfinfo->strings, "Unknown"), value);
4604 g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
4605 format, hfinfo->name,
4606 val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
4610 format = hfinfo_uint_format(hfinfo);
4611 if (IS_BASE_DUAL(hfinfo->display)) {
4612 g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
4613 format, hfinfo->name, value, value);
4615 g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
4616 format, hfinfo->name, value);
4622 fill_label_uint(field_info *fi, gchar *label_str)
4624 const char *format = NULL;
4625 header_field_info *hfinfo = fi->hfinfo;
4628 value = fvalue_get_uinteger(&fi->value);
4630 /* Fill in the textual info */
4631 if (hfinfo->display == BASE_CUSTOM) {
4632 gchar tmp[ITEM_LABEL_LENGTH];
4633 custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hfinfo->strings;
4635 DISSECTOR_ASSERT(fmtfunc);
4636 fmtfunc(tmp, value);
4637 g_snprintf(label_str, ITEM_LABEL_LENGTH, "%s: %s", hfinfo->name, tmp);
4639 else if (hfinfo->strings) {
4640 format = hfinfo_uint_vals_format(hfinfo);
4641 if (hfinfo->display & BASE_RANGE_STRING) {
4642 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4643 format, hfinfo->name,
4644 rval_to_str(value, hfinfo->strings, "Unknown"), value);
4646 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4647 format, hfinfo->name,
4648 val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
4652 format = hfinfo_uint_format(hfinfo);
4653 if (IS_BASE_DUAL(hfinfo->display)) {
4654 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4655 format, hfinfo->name, value, value);
4657 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4658 format, hfinfo->name, value);
4664 fill_label_uint64(field_info *fi, gchar *label_str)
4666 const char *format = NULL;
4667 header_field_info *hfinfo = fi->hfinfo;
4670 /* Pick the proper format string */
4671 format = hfinfo_uint64_format(hfinfo);
4672 value = fvalue_get_integer64(&fi->value);
4674 /* Fill in the textual info */
4675 if (IS_BASE_DUAL(hfinfo->display)) {
4676 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4677 format, hfinfo->name, value, value);
4679 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4680 format, hfinfo->name, value);
4685 fill_label_int(field_info *fi, gchar *label_str)
4687 const char *format = NULL;
4688 header_field_info *hfinfo = fi->hfinfo;
4691 value = fvalue_get_sinteger(&fi->value);
4693 /* Fill in the textual info */
4694 if (hfinfo->display == BASE_CUSTOM) {
4695 gchar tmp[ITEM_LABEL_LENGTH];
4696 custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hfinfo->strings;
4698 DISSECTOR_ASSERT(fmtfunc);
4699 fmtfunc(tmp, value);
4700 g_snprintf(label_str, ITEM_LABEL_LENGTH, "%s: %s", hfinfo->name, tmp);
4702 else if (hfinfo->strings) {
4703 format = hfinfo_int_vals_format(hfinfo);
4704 if (hfinfo->display & BASE_RANGE_STRING) {
4705 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4706 format, hfinfo->name,
4707 rval_to_str(value, hfinfo->strings, "Unknown"), value);
4709 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4710 format, hfinfo->name,
4711 val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
4715 format = hfinfo_int_format(hfinfo);
4716 if (IS_BASE_DUAL(hfinfo->display)) {
4717 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4718 format, hfinfo->name, value, value);
4720 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4721 format, hfinfo->name, value);
4727 fill_label_int64(field_info *fi, gchar *label_str)
4729 const char *format = NULL;
4730 header_field_info *hfinfo = fi->hfinfo;
4733 /* Pick the proper format string */
4734 format = hfinfo_int64_format(hfinfo);
4735 value = fvalue_get_integer64(&fi->value);
4737 /* Fill in the textual info */
4738 if (IS_BASE_DUAL(hfinfo->display)) {
4739 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4740 format, hfinfo->name, value, value);
4742 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4743 format, hfinfo->name, value);
4748 hfinfo_bitwidth(header_field_info *hfinfo)
4752 if (!hfinfo->bitmask) {
4756 switch(hfinfo->type) {
4774 bitwidth = hfinfo->display; /* hacky? :) */
4777 DISSECTOR_ASSERT_NOT_REACHED();
4784 hfinfo_uint_vals_format(header_field_info *hfinfo)
4786 const char *format = NULL;
4788 /* bit operation to reset the potential BASE_RANGE_STRING (or others in
4790 switch(hfinfo->display & BASE_STRUCTURE_RESET) {
4796 format = "%s: %s (%u)";
4798 case BASE_OCT: /* I'm lazy */
4799 format = "%s: %s (%o)";
4803 switch(hfinfo->type) {
4805 format = "%s: %s (0x%02x)";
4808 format = "%s: %s (0x%04x)";
4811 format = "%s: %s (0x%06x)";
4814 format = "%s: %s (0x%08x)";
4817 DISSECTOR_ASSERT_NOT_REACHED();
4822 DISSECTOR_ASSERT_NOT_REACHED();
4829 hfinfo_uint_format(header_field_info *hfinfo)
4831 const char *format = NULL;
4833 /* Pick the proper format string */
4834 if (hfinfo->type == FT_FRAMENUM) {
4836 * Frame numbers are always displayed in decimal.
4840 switch(hfinfo->display) {
4845 switch(hfinfo->type) {
4847 format = "%s: %u (0x%02x)";
4850 format = "%s: %u (0x%04x)";
4853 format = "%s: %u (0x%06x)";
4856 format = "%s: %u (0x%08x)";
4859 DISSECTOR_ASSERT_NOT_REACHED();
4863 case BASE_OCT: /* I'm lazy */
4867 switch(hfinfo->type) {
4869 format = "%s: 0x%02x";
4872 format = "%s: 0x%04x";
4875 format = "%s: 0x%06x";
4878 format = "%s: 0x%08x";
4881 DISSECTOR_ASSERT_NOT_REACHED();
4886 switch(hfinfo->type) {
4888 format = "%s: 0x%02x (%u)";
4891 format = "%s: 0x%04x (%u)";
4894 format = "%s: 0x%06x (%u)";
4897 format = "%s: 0x%08x (%u)";
4900 DISSECTOR_ASSERT_NOT_REACHED();
4905 DISSECTOR_ASSERT_NOT_REACHED();
4913 hfinfo_uint_value_format(header_field_info *hfinfo)
4915 const char *format = NULL;
4917 /* Pick the proper format string */
4918 if (hfinfo->type == FT_FRAMENUM) {
4920 * Frame numbers are always displayed in decimal.
4924 switch(hfinfo->display) {
4929 switch(hfinfo->type) {
4931 format = "%u (0x%02x)";
4934 format = "%u (0x%04x)";
4937 format = "%u (0x%06x)";
4940 format = "%u (0x%08x)";
4943 DISSECTOR_ASSERT_NOT_REACHED();
4951 switch(hfinfo->type) {
4965 DISSECTOR_ASSERT_NOT_REACHED();
4970 switch(hfinfo->type) {
4972 format = "0x%02x (%u)";
4975 format = "0x%04x (%u)";
4978 format = "0x%06x (%u)";
4981 format = "0x%08x (%u)";
4984 DISSECTOR_ASSERT_NOT_REACHED();
4989 DISSECTOR_ASSERT_NOT_REACHED();
4997 hfinfo_int_vals_format(header_field_info *hfinfo)
4999 const char *format = NULL;
5001 /* bit operation to reset the potential BASE_RANGE_STRING (or others in
5003 switch(hfinfo->display & BASE_STRUCTURE_RESET) {
5009 format = "%s: %s (%d)";
5011 case BASE_OCT: /* I'm lazy */
5012 format = "%s: %s (%o)";
5016 switch(hfinfo->type) {
5018 format = "%s: %s (0x%02x)";
5021 format = "%s: %s (0x%04x)";
5024 format = "%s: %s (0x%06x)";
5027 format = "%s: %s (0x%08x)";
5030 DISSECTOR_ASSERT_NOT_REACHED();
5035 DISSECTOR_ASSERT_NOT_REACHED();
5042 hfinfo_uint64_format(header_field_info *hfinfo)
5044 const char *format = NULL;
5046 /* Pick the proper format string */
5047 switch(hfinfo->display) {
5049 format = "%s: %" G_GINT64_MODIFIER "u";
5052 format = "%s: %" G_GINT64_MODIFIER "u (%" G_GINT64_MODIFIER "x)";
5054 case BASE_OCT: /* I'm lazy */
5055 format = "%s: %" G_GINT64_MODIFIER "o";
5058 format = "%s: 0x%016" G_GINT64_MODIFIER "x";
5061 format = "%s: 0x%016" G_GINT64_MODIFIER "x (%" G_GINT64_MODIFIER "u)";
5064 DISSECTOR_ASSERT_NOT_REACHED();
5071 hfinfo_int_format(header_field_info *hfinfo)
5073 const char *format = NULL;
5075 /* Pick the proper format string */
5076 switch(hfinfo->display) {
5081 switch(hfinfo->type) {
5083 format = "%s: %d (0x%02x)";
5086 format = "%s: %d (0x%04x)";
5089 format = "%s: %d (0x%06x)";
5092 format = "%s: %d (0x%08x)";
5095 DISSECTOR_ASSERT_NOT_REACHED();
5099 case BASE_OCT: /* I'm lazy */
5103 switch(hfinfo->type) {
5105 format = "%s: 0x%02x";
5108 format = "%s: 0x%04x";
5111 format = "%s: 0x%06x";
5114 format = "%s: 0x%08x";
5117 DISSECTOR_ASSERT_NOT_REACHED();
5122 switch(hfinfo->type) {
5124 format = "%s: 0x%02x (%d)";
5127 format = "%s: 0x%04x (%d)";
5130 format = "%s: 0x%06x (%d)";
5133 format = "%s: 0x%08x (%d)";
5136 DISSECTOR_ASSERT_NOT_REACHED();
5141 DISSECTOR_ASSERT_NOT_REACHED();
5148 hfinfo_int_value_format(header_field_info *hfinfo)
5150 const char *format = NULL;
5152 /* Pick the proper format string */
5153 switch(hfinfo->display) {
5158 switch(hfinfo->type) {
5160 format = "%d (0x%02x)";
5163 format = "%d (0x%04x)";
5166 format = "%d (0x%06x)";
5169 format = "%d (0x%08x)";
5172 DISSECTOR_ASSERT_NOT_REACHED();
5180 switch(hfinfo->type) {
5194 DISSECTOR_ASSERT_NOT_REACHED();
5199 switch(hfinfo->type) {
5201 format = "0x%02x (%d)";
5204 format = "0x%04x (%d)";
5207 format = "0x%06x (%d)";
5210 format = "0x%08x (%d)";
5213 DISSECTOR_ASSERT_NOT_REACHED();
5218 DISSECTOR_ASSERT_NOT_REACHED();
5225 hfinfo_int64_format(header_field_info *hfinfo)
5227 const char *format = NULL;
5229 /* Pick the proper format string */
5230 switch(hfinfo->display) {
5232 format = "%s: %" G_GINT64_MODIFIER "d";
5235 format = "%s: %" G_GINT64_MODIFIER "d (%" G_GINT64_MODIFIER "x)";
5237 case BASE_OCT: /* I'm lazy */
5238 format = "%s: %" G_GINT64_MODIFIER "o";
5241 format = "%s: 0x%016" G_GINT64_MODIFIER "x";
5244 format = "%s: 0x%016" G_GINT64_MODIFIER "x (%" G_GINT64_MODIFIER "d)";
5247 DISSECTOR_ASSERT_NOT_REACHED();
5254 proto_registrar_n(void)
5256 return gpa_hfinfo.len;
5260 proto_registrar_get_name(int n)
5262 header_field_info *hfinfo;
5264 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
5265 return hfinfo->name;
5269 proto_registrar_get_abbrev(int n)
5271 header_field_info *hfinfo;
5273 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
5274 return hfinfo->abbrev;
5278 proto_registrar_get_ftype(int n)
5280 header_field_info *hfinfo;
5282 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
5283 return hfinfo->type;
5287 proto_registrar_get_parent(int n)
5289 header_field_info *hfinfo;
5291 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
5292 return hfinfo->parent;
5296 proto_registrar_is_protocol(int n)
5298 header_field_info *hfinfo;
5300 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
5301 return (hfinfo->parent == -1 ? TRUE : FALSE);
5304 /* Returns length of field in packet (not necessarily the length
5305 * in our internal representation, as in the case of IPv4).
5306 * 0 means undeterminable at time of registration
5307 * -1 means the field is not registered. */
5309 proto_registrar_get_length(int n)
5311 header_field_info *hfinfo;
5313 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
5314 return ftype_length(hfinfo->type);
5317 /* Looks for a protocol or a field in a proto_tree. Returns TRUE if
5318 * it exists anywhere, or FALSE if it exists nowhere. */
5320 proto_check_for_protocol_or_field(proto_tree* tree, int id)
5322 GPtrArray *ptrs = proto_get_finfo_ptr_array(tree, id);
5327 else if (g_ptr_array_len(ptrs) > 0) {
5335 /* Return GPtrArray* of field_info pointers for all hfindex that appear in tree.
5336 * This only works if the hfindex was "primed" before the dissection
5337 * took place, as we just pass back the already-created GPtrArray*.
5338 * The caller should *not* free the GPtrArray*; proto_tree_free_node()
5341 proto_get_finfo_ptr_array(proto_tree *tree, int id)
5343 if (PTREE_DATA(tree)->interesting_hfids != NULL)
5344 return g_hash_table_lookup(PTREE_DATA(tree)->interesting_hfids,
5345 GINT_TO_POINTER(id));
5351 proto_tracking_interesting_fields(proto_tree *tree)
5353 return (PTREE_DATA(tree)->interesting_hfids != NULL);
5356 /* Helper struct for proto_find_info() and proto_all_finfos() */
5362 /* Helper function for proto_find_info() */
5364 find_finfo(proto_node *node, gpointer data)
5366 field_info *fi = PNODE_FINFO(node);
5367 if (fi && fi->hfinfo) {
5368 if (fi->hfinfo->id == ((ffdata_t*)data)->id) {
5369 g_ptr_array_add(((ffdata_t*)data)->array, fi);
5373 /* Don't stop traversing. */
5377 /* Return GPtrArray* of field_info pointers for all hfindex that appear in a tree.
5378 * This works on any proto_tree, primed or unprimed, but actually searches
5379 * the tree, so it is slower than using proto_get_finfo_ptr_array on a primed tree.
5380 * The caller does need to free the returned GPtrArray with
5381 * g_ptr_array_free(<array>, TRUE).
5384 proto_find_finfo(proto_tree *tree, int id)
5388 ffdata.array = g_ptr_array_new();
5391 proto_tree_traverse_pre_order(tree, find_finfo, &ffdata);
5393 return ffdata.array;
5396 /* Helper function for proto_all_finfos() */
5398 every_finfo(proto_node *node, gpointer data)
5400 field_info *fi = PNODE_FINFO(node);
5401 if (fi && fi->hfinfo) {
5402 g_ptr_array_add(((ffdata_t*)data)->array, fi);
5405 /* Don't stop traversing. */
5409 /* Return GPtrArray* of field_info pointers containing all hfindexes that appear in a tree. */
5411 proto_all_finfos(proto_tree *tree)
5415 ffdata.array = g_ptr_array_new();
5418 proto_tree_traverse_pre_order(tree, every_finfo, &ffdata);
5420 return ffdata.array;
5431 check_for_offset(proto_node *node, gpointer data)
5433 field_info *fi = PNODE_FINFO(node);
5434 offset_search_t *offsearch = data;
5436 /* !fi == the top most container node which holds nothing */
5437 if (fi && !PROTO_ITEM_IS_HIDDEN(node) && fi->ds_tvb && offsearch->tvb == fi->ds_tvb) {
5438 if (offsearch->offset >= (guint) fi->start &&
5439 offsearch->offset < (guint) (fi->start + fi->length)) {
5441 offsearch->finfo = fi;
5442 return FALSE; /* keep traversing */
5445 return FALSE; /* keep traversing */
5448 /* Search a proto_tree backwards (from leaves to root) looking for the field
5449 * whose start/length occupies 'offset' */
5450 /* XXX - I couldn't find an easy way to search backwards, so I search
5451 * forwards, w/o stopping. Therefore, the last finfo I find will the be
5452 * the one I want to return to the user. This algorithm is inefficient
5453 * and could be re-done, but I'd have to handle all the children and
5454 * siblings of each node myself. When I have more time I'll do that.
5457 proto_find_field_from_offset(proto_tree *tree, guint offset, tvbuff_t *tvb)
5459 offset_search_t offsearch;
5461 offsearch.offset = offset;
5462 offsearch.finfo = NULL;
5463 offsearch.tvb = tvb;
5465 proto_tree_traverse_pre_order(tree, check_for_offset, &offsearch);
5467 return offsearch.finfo;
5470 /* Dumps the protocols in the registration database to stdout. An independent
5471 * program can take this output and format it into nice tables or HTML or
5474 * There is one record per line. The fields are tab-delimited.
5476 * Field 1 = protocol name
5477 * Field 2 = protocol short name
5478 * Field 3 = protocol filter name
5481 proto_registrar_dump_protocols(void)
5483 protocol_t *protocol;
5485 void *cookie = NULL;
5487 for (i = proto_get_first_protocol(&cookie); i != -1;
5488 i = proto_get_next_protocol(&cookie)) {
5489 protocol = find_protocol_by_id(i);
5490 printf("%s\t%s\t%s\n", protocol->name, protocol->short_name,
5491 protocol->filter_name);
5495 /* Dumps the value_strings, range_strings or true/false strings for fields
5496 * that have them. There is one record per line. Fields are tab-delimited.
5497 * There are three types of records: Value String, Range String
5498 * and True/False String. The first field, 'V', 'R' or 'T', indicates
5499 * the type of record.
5504 * Field 2 = field abbreviation to which this value string corresponds
5505 * Field 3 = Integer value
5511 * Field 2 = field abbreviation to which this range string corresponds
5512 * Field 3 = Integer value: lower bound
5513 * Field 4 = Integer value: upper bound
5516 * True/False Strings
5517 * ------------------
5519 * Field 2 = field abbreviation to which this true/false string corresponds
5520 * Field 3 = True String
5521 * Field 4 = False String
5524 proto_registrar_dump_values(void)
5526 header_field_info *hfinfo, *parent_hfinfo;
5528 const value_string *vals;
5529 const range_string *range;
5530 const true_false_string *tfs;
5532 len = gpa_hfinfo.len;
5533 for (i = 0; i < len ; i++) {
5534 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
5536 if (hfinfo->id == hf_text_only) {
5540 /* ignore protocols */
5541 if (proto_registrar_is_protocol(i)) {
5544 /* process header fields */
5547 * If this field isn't at the head of the list of
5548 * fields with this name, skip this field - all
5549 * fields with the same name are really just versions
5550 * of the same field stored in different bits, and
5551 * should have the same type/radix/value list, and
5552 * just differ in their bit masks. (If a field isn't
5553 * a bitfield, but can be, say, 1 or 2 bytes long,
5554 * it can just be made FT_UINT16, meaning the
5555 * *maximum* length is 2 bytes, and be used
5558 if (hfinfo->same_name_prev != NULL)
5561 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
5567 if ((hfinfo->display & BASE_STRUCTURE_RESET) != BASE_CUSTOM &&
5568 (hfinfo->type == FT_UINT8 ||
5569 hfinfo->type == FT_UINT16 ||
5570 hfinfo->type == FT_UINT24 ||
5571 hfinfo->type == FT_UINT32 ||
5572 hfinfo->type == FT_UINT64 ||
5573 hfinfo->type == FT_INT8 ||
5574 hfinfo->type == FT_INT16 ||
5575 hfinfo->type == FT_INT24 ||
5576 hfinfo->type == FT_INT32 ||
5577 hfinfo->type == FT_INT64)) {
5579 if ((hfinfo->display & BASE_RANGE_STRING) == 0) {
5580 vals = hfinfo->strings;
5582 range = hfinfo->strings;
5585 else if (hfinfo->type == FT_BOOLEAN) {
5586 tfs = hfinfo->strings;
5589 /* Print value strings? */
5592 while (vals[vi].strptr) {
5593 /* Print in the proper base */
5594 if (hfinfo->display == BASE_HEX) {
5595 printf("V\t%s\t0x%x\t%s\n",
5601 printf("V\t%s\t%u\t%s\n",
5610 /* print range strings? */
5613 while (range[vi].strptr) {
5614 /* Print in the proper base */
5615 if ((hfinfo->display & BASE_STRUCTURE_RESET) == BASE_HEX) {
5616 printf("R\t%s\t0x%x\t0x%x\t%s\n",
5618 range[vi].value_min,
5619 range[vi].value_max,
5623 printf("R\t%s\t%u\t%u\t%s\n",
5625 range[vi].value_min,
5626 range[vi].value_max,
5633 /* Print true/false strings? */
5635 printf("T\t%s\t%s\t%s\n", hfinfo->abbrev,
5636 tfs->true_string, tfs->false_string);
5642 /* Dumps the contents of the registration database to stdout. An independent
5643 * program can take this output and format it into nice tables or HTML or
5646 * There is one record per line. Each record is either a protocol or a header
5647 * field, differentiated by the first field. The fields are tab-delimited.
5652 * Field 2 = descriptive protocol name
5653 * Field 3 = protocol abbreviation
5659 * Field 2 = descriptive field name
5660 * Field 3 = field abbreviation
5661 * Field 4 = type ( textual representation of the the ftenum type )
5662 * Field 5 = parent protocol abbreviation
5663 * Field 6 = blurb describing field
5667 * Field 2 = descriptive field name
5668 * Field 3 = field abbreviation
5669 * Field 4 = type ( textual representation of the the ftenum type )
5670 * Field 5 = parent protocol abbreviation
5671 * Field 6 = blurb describing field
5672 * Field 7 = base for display (for integer types); "parent bitfield width" for FT_BOOLEAN
5673 * Field 8 = blurb describing field (yes, apparently we repeated this accidentally)
5677 * Field 2 = descriptive field name
5678 * Field 3 = field abbreviation
5679 * Field 4 = type ( textual representation of the the ftenum type )
5680 * Field 5 = parent protocol abbreviation
5681 * Field 6 = blurb describing field
5682 * Field 7 = base for display (for integer types); "parent bitfield width" for FT_BOOLEAN
5683 * Field 8 = bitmask: format: hex: 0x....
5686 proto_registrar_dump_fields(int format)
5688 header_field_info *hfinfo, *parent_hfinfo;
5690 const char *enum_name;
5691 const char *base_name;
5695 len = gpa_hfinfo.len;
5696 for (i = 0; i < len ; i++) {
5697 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
5700 * Skip the pseudo-field for "proto_tree_add_text()" since
5701 * we don't want it in the list of filterable fields.
5703 if (hfinfo->id == hf_text_only)
5706 /* format for protocols */
5707 if (proto_registrar_is_protocol(i)) {
5708 printf("P\t%s\t%s\n", hfinfo->name, hfinfo->abbrev);
5710 /* format for header fields */
5713 * If this field isn't at the head of the list of
5714 * fields with this name, skip this field - all
5715 * fields with the same name are really just versions
5716 * of the same field stored in different bits, and
5717 * should have the same type/radix/value list, and
5718 * just differ in their bit masks. (If a field isn't
5719 * a bitfield, but can be, say, 1 or 2 bytes long,
5720 * it can just be made FT_UINT16, meaning the
5721 * *maximum* length is 2 bytes, and be used
5724 if (hfinfo->same_name_prev != NULL)
5727 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
5729 enum_name = ftype_name(hfinfo->type);
5733 if (hfinfo->type == FT_UINT8 ||
5734 hfinfo->type == FT_UINT16 ||
5735 hfinfo->type == FT_UINT24 ||
5736 hfinfo->type == FT_UINT32 ||
5737 hfinfo->type == FT_UINT64 ||
5738 hfinfo->type == FT_INT8 ||
5739 hfinfo->type == FT_INT16 ||
5740 hfinfo->type == FT_INT24 ||
5741 hfinfo->type == FT_INT32 ||
5742 hfinfo->type == FT_INT64) {
5745 switch(hfinfo->display & BASE_STRUCTURE_RESET) {
5747 base_name = "BASE_NONE";
5750 base_name = "BASE_DEC";
5753 base_name = "BASE_HEX";
5756 base_name = "BASE_OCT";
5759 base_name = "BASE_DEC_HEX";
5762 base_name = "BASE_HEX_DEC";
5765 base_name = "BASE_CUSTOM";
5771 } else if (hfinfo->type == FT_BOOLEAN) {
5772 /* For FT_BOOLEAN: 'display' can be "parent bitfield width" */
5773 g_snprintf(width, sizeof(width), "%d", hfinfo->display);
5778 blurb = hfinfo->blurb;
5782 printf("F\t%s\t%s\t%s\t%s\t%s\n",
5783 hfinfo->name, hfinfo->abbrev, enum_name,
5784 parent_hfinfo->abbrev, blurb);
5786 else if (format == 2) {
5787 printf("F\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n",
5788 hfinfo->name, hfinfo->abbrev, enum_name,
5789 parent_hfinfo->abbrev, blurb,
5792 else if (format == 3) {
5793 printf("F\t%s\t%s\t%s\t%s\t%s\t%s\t0x%x\n",
5794 hfinfo->name, hfinfo->abbrev, enum_name,
5795 parent_hfinfo->abbrev, blurb,
5796 base_name, hfinfo->bitmask);
5799 g_assert_not_reached();
5806 hfinfo_numeric_format(header_field_info *hfinfo)
5808 const char *format = NULL;
5810 /* Pick the proper format string */
5811 if (hfinfo->type == FT_FRAMENUM) {
5813 * Frame numbers are always displayed in decimal.
5815 format = "%s == %u";
5817 /* Pick the proper format string, ignoring BASE_RANGE_STRING flag */
5818 switch(hfinfo->display & ~BASE_RANGE_STRING) {
5821 case BASE_OCT: /* I'm lazy */
5823 switch(hfinfo->type) {
5828 format = "%s == %u";
5831 format = "%s == %" G_GINT64_MODIFIER "u";
5837 format = "%s == %d";
5840 format = "%s == %" G_GINT64_MODIFIER "d";
5843 DISSECTOR_ASSERT_NOT_REACHED();
5849 switch(hfinfo->type) {
5851 format = "%s == 0x%02x";
5854 format = "%s == 0x%04x";
5857 format = "%s == 0x%06x";
5860 format = "%s == 0x%08x";
5863 format = "%s == 0x%016" G_GINT64_MODIFIER "x";
5866 DISSECTOR_ASSERT_NOT_REACHED();
5871 DISSECTOR_ASSERT_NOT_REACHED();
5878 /* This function indicates whether it's possible to construct a
5879 * "match selected" display filter string for the specified field,
5880 * returns an indication of whether it's possible, and, if it's
5881 * possible and "filter" is non-null, constructs the filter and
5882 * sets "*filter" to point to it.
5883 * You do not need to [g_]free() this string since it will be automatically
5884 * freed once the next packet is dissected.
5887 construct_match_selected_string(field_info *finfo, epan_dissect_t *edt,
5890 header_field_info *hfinfo;
5896 gint start, length, length_remaining;
5898 gchar is_signed_num = FALSE;
5900 hfinfo = finfo->hfinfo;
5901 DISSECTOR_ASSERT(hfinfo);
5902 abbrev_len = (int) strlen(hfinfo->abbrev);
5904 if (hfinfo->strings && (hfinfo->display & BASE_STRUCTURE_RESET) == BASE_NONE) {
5905 const gchar *str = NULL;
5907 switch(hfinfo->type) {
5913 if (hfinfo->display & BASE_RANGE_STRING) {
5914 str = match_strrval(fvalue_get_sinteger(&finfo->value), hfinfo->strings);
5916 str = match_strval(fvalue_get_sinteger(&finfo->value), hfinfo->strings);
5924 if (hfinfo->display & BASE_RANGE_STRING) {
5925 str = match_strrval(fvalue_get_uinteger(&finfo->value), hfinfo->strings);
5927 str = match_strval(fvalue_get_uinteger(&finfo->value), hfinfo->strings);
5935 if (str != NULL && filter != NULL) {
5936 *filter = ep_strdup_printf("%s == \"%s\"", hfinfo->abbrev, str);
5942 * XXX - we can't use the "val_to_string_repr" and "string_repr_len"
5943 * functions for FT_UINT and FT_INT types, as we choose the base in
5944 * the string expression based on the display base of the field.
5946 * Note that the base does matter, as this is also used for
5947 * the protocolinfo tap.
5949 * It might be nice to use them in "proto_item_fill_label()"
5950 * as well, although, there, you'd have to deal with the base
5951 * *and* with resolved values for addresses.
5953 * Perhaps we need two different val_to_string routines, one
5954 * to generate items for display filters and one to generate
5955 * strings for display, and pass to both of them the
5956 * "display" and "strings" values in the header_field_info
5957 * structure for the field, so they can get the base and,
5958 * if the field is Boolean or an enumerated integer type,
5959 * the tables used to generate human-readable values.
5961 switch(hfinfo->type) {
5967 is_signed_num = TRUE;
5972 if (filter != NULL) {
5973 format = hfinfo_numeric_format(hfinfo);
5975 *filter = ep_strdup_printf(format,
5977 fvalue_get_sinteger(&finfo->value));
5979 *filter = ep_strdup_printf(format,
5981 fvalue_get_uinteger(&finfo->value));
5987 DISSECTOR_ASSERT(!is_signed_num);
5988 if (filter != NULL) {
5989 format = hfinfo_numeric_format(hfinfo);
5990 *filter = ep_strdup_printf(format,
5992 fvalue_get_uinteger(&finfo->value));
5998 if (filter != NULL) {
5999 format = hfinfo_numeric_format(hfinfo);
6000 *filter = ep_strdup_printf(format,
6002 fvalue_get_integer64(&finfo->value));
6008 *filter = ep_strdup(finfo->hfinfo->abbrev);
6013 * If the length is 0, just match the name of the
6016 * (Also check for negative values, just in case,
6017 * as we'll cast it to an unsigned value later.)
6019 length = finfo->length;
6022 *filter = ep_strdup(finfo->hfinfo->abbrev);
6029 * This doesn't have a value, so we'd match
6030 * on the raw bytes at this address.
6032 * Should we be allowed to access to the raw bytes?
6033 * If "edt" is NULL, the answer is "no".
6039 * Is this field part of the raw frame tvbuff?
6040 * If not, we can't use "frame[N:M]" to match
6043 * XXX - should this be frame-relative, or
6044 * protocol-relative?
6046 * XXX - does this fallback for non-registered
6047 * fields even make sense?
6049 if (finfo->ds_tvb != edt->tvb)
6050 return FALSE; /* you lose */
6053 * Don't go past the end of that tvbuff.
6055 length_remaining = tvb_length_remaining(finfo->ds_tvb, finfo->start);
6056 if (length > length_remaining)
6057 length = length_remaining;
6061 if (filter != NULL) {
6062 start = finfo->start;
6063 buf_len = 32 + length * 3;
6064 *filter = ep_alloc0(buf_len);
6067 ptr += g_snprintf(ptr, (gulong) (buf_len-(ptr-*filter)),
6068 "frame[%d:%d] == ", finfo->start, length);
6069 for (i=0;i<length; i++) {
6070 c = tvb_get_guint8(finfo->ds_tvb, start);
6073 ptr += g_snprintf(ptr, (gulong) (buf_len-(ptr-*filter)), "%02x", c);
6076 ptr += g_snprintf(ptr, (gulong) (buf_len-(ptr-*filter)), ":%02x", c);
6083 /* FT_PCRE never appears as a type for a registered field. It is
6084 * only used internally. */
6085 DISSECTOR_ASSERT_NOT_REACHED();
6088 /* By default, use the fvalue's "to_string_repr" method. */
6090 /* Figure out the string length needed.
6091 * The ft_repr length.
6092 * 4 bytes for " == ".
6093 * 1 byte for trailing NUL.
6095 if (filter != NULL) {
6096 dfilter_len = fvalue_string_repr_len(&finfo->value,
6098 dfilter_len += abbrev_len + 4 + 1;
6099 *filter = ep_alloc0(dfilter_len);
6101 /* Create the string */
6102 g_snprintf(*filter, dfilter_len, "%s == ",
6104 fvalue_to_string_repr(&finfo->value,
6106 &(*filter)[abbrev_len + 4]);
6115 * Returns TRUE if we can do a "match selected" on the field, FALSE
6119 proto_can_match_selected(field_info *finfo, epan_dissect_t *edt)
6121 return construct_match_selected_string(finfo, edt, NULL);
6124 /* This function attempts to construct a "match selected" display filter
6125 * string for the specified field; if it can do so, it returns a pointer
6126 * to the string, otherwise it returns NULL.
6128 * The string is allocated with packet lifetime scope.
6129 * You do not need to [g_]free() this string since it will be automatically
6130 * freed once the next packet is dissected.
6133 proto_construct_match_selected_string(field_info *finfo, epan_dissect_t *edt)
6137 if (!construct_match_selected_string(finfo, edt, &filter))
6142 /* This function is common code for both proto_tree_add_bitmask() and
6143 * proto_tree_add_bitmask_text() functions.
6146 proto_item_add_bitmask_tree(proto_item *item, tvbuff_t *tvb, int offset, int len, gint ett,
6147 const int **fields, gboolean little_endian, int flags, gboolean first)
6149 guint32 value = 0, tmpval;
6150 proto_tree *tree = NULL;
6151 header_field_info *hf;
6156 value = tvb_get_guint8(tvb, offset);
6159 value = little_endian ? tvb_get_letohs(tvb, offset) :
6160 tvb_get_ntohs(tvb, offset);
6163 value = little_endian ? tvb_get_letoh24(tvb, offset) :
6164 tvb_get_ntoh24(tvb, offset);
6167 value = little_endian ? tvb_get_letohl(tvb, offset) :
6168 tvb_get_ntohl(tvb, offset);
6171 g_assert_not_reached();
6174 tree = proto_item_add_subtree(item, ett);
6176 proto_tree_add_item(tree, **fields, tvb, offset, len, little_endian);
6177 if (flags & BMT_NO_APPEND) {
6181 hf = proto_registrar_get_nth(**fields);
6182 DISSECTOR_ASSERT(hf->bitmask != 0);
6183 tmpval = (value & hf->bitmask) >> hf->bitshift;
6194 DISSECTOR_ASSERT(len == ftype_length(hf->type));
6196 if (hf->display == BASE_CUSTOM) {
6197 gchar lbl[ITEM_LABEL_LENGTH];
6198 custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hf->strings;
6200 DISSECTOR_ASSERT(fmtfunc);
6201 fmtfunc(lbl, tmpval);
6202 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
6206 else if (hf->strings) {
6207 if (hf->display & BASE_RANGE_STRING) {
6208 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
6209 hf->name, rval_to_str(tmpval, hf->strings, "Unknown"));
6211 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
6212 hf->name, val_to_str(tmpval, cVALS(hf->strings), "Unknown"));
6216 else if (!(flags & BMT_NO_INT)) {
6218 proto_item_append_text(item, ", ");
6221 fmt = IS_FT_INT(hf->type) ? hfinfo_int_format(hf) : hfinfo_uint_format(hf);
6222 if (IS_BASE_DUAL(hf->display)) {
6223 proto_item_append_text(item, fmt, hf->name, tmpval, tmpval);
6225 proto_item_append_text(item, fmt, hf->name, tmpval);
6232 DISSECTOR_ASSERT(len * 8 == hf->display);
6234 if (hf->strings && !(flags & BMT_NO_TFS)) {
6235 /* If we have true/false strings, emit full - otherwise messages
6237 const struct true_false_string *tfs =
6238 (const struct true_false_string *)hf->strings;
6241 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
6242 hf->name, tfs->true_string);
6244 } else if (!(flags & BMT_NO_FALSE)) {
6245 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
6246 hf->name, tfs->false_string);
6249 } else if (hf->bitmask & value) {
6250 /* If the flag is set, show the name */
6251 proto_item_append_text(item, "%s%s", first ? "" : ", ", hf->name);
6256 g_assert_not_reached();
6265 /* This function will dissect a sequence of bytes that describe a
6267 * hf_hdr is a 8/16/24/32 bit integer that describes the bitmask to be dissected.
6268 * This field will form an expansion under which the individual fields of the
6269 * bitmask is dissected and displayed.
6270 * This field must be of the type FT_[U]INT{8|16|24|32}.
6272 * fields is an array of pointers to int that lists all the fields of the
6273 * bitmask. These fields can be either of the type FT_BOOLEAN for flags
6274 * or another integer of the same type/size as hf_hdr with a mask specified.
6275 * This array is terminated by a NULL entry.
6277 * FT_BOOLEAN bits that are set to 1 will have the name added to the expansion.
6278 * FT_integer fields that have a value_string attached will have the
6279 * matched string displayed on the expansion line.
6282 proto_tree_add_bitmask(proto_tree *parent_tree, tvbuff_t *tvb, guint offset, int hf_hdr,
6283 gint ett, const int **fields, gboolean little_endian)
6285 proto_item *item = NULL;
6286 header_field_info *hf;
6289 hf = proto_registrar_get_nth(hf_hdr);
6290 DISSECTOR_ASSERT(IS_FT_INT(hf->type) || IS_FT_UINT(hf->type));
6291 len = ftype_length(hf->type);
6294 item = proto_tree_add_item(parent_tree, hf_hdr, tvb, offset, len, little_endian);
6295 proto_item_add_bitmask_tree(item, tvb, offset, len, ett, fields, little_endian,
6296 BMT_NO_INT|BMT_NO_TFS, FALSE);
6302 /* The same as proto_tree_add_bitmask(), but using an arbitrary text as a top-level item */
6304 proto_tree_add_bitmask_text(proto_tree *parent_tree, tvbuff_t *tvb, guint offset, guint len,
6305 const char *name, const char *fallback,
6306 gint ett, const int **fields, gboolean little_endian, int flags)
6308 proto_item *item = NULL;
6311 item = proto_tree_add_text(parent_tree, tvb, offset, len, "%s", name ? name : "");
6312 if (proto_item_add_bitmask_tree(item, tvb, offset, len, ett, fields, little_endian,
6313 flags, TRUE) && fallback) {
6314 /* Still at first item - append 'fallback' text if any */
6315 proto_item_append_text(item, "%s", fallback);
6323 proto_tree_add_bits_item(proto_tree *tree, int hf_index, tvbuff_t *tvb, gint bit_offset, gint no_of_bits, gboolean little_endian)
6325 header_field_info *hfinfo;
6327 TRY_TO_FAKE_THIS_ITEM(tree, hf_index, hfinfo);
6329 return proto_tree_add_bits_ret_val(tree, hf_index, tvb, bit_offset, no_of_bits, NULL, little_endian);
6332 * This function will dissect a sequence of bits that does not need to be byte aligned; the bits
6333 * set vill be shown in the tree as ..10 10.. and the integer value returned if return_value is set.
6334 * Offset should be given in bits from the start of the tvb.
6338 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)
6340 const char *format = NULL;
6344 guint8 remaining_bits;
6345 guint64 mask = 0,tmp;
6347 header_field_info *hf_field;
6352 /* We can't fake it just yet. We have to fill in the 'return_value' parameter */
6353 PROTO_REGISTRAR_GET_NTH(hf_index, hf_field);
6355 if(hf_field -> bitmask != 0) {
6356 REPORT_DISSECTOR_BUG(ep_strdup_printf("Incompatible use of proto_tree_add_bits_ret_val with field '%s' (%s) with bitmask != 0",
6357 hf_field->abbrev, hf_field->name));
6360 DISSECTOR_ASSERT(bit_offset >= 0);
6361 DISSECTOR_ASSERT(no_of_bits > 0);
6363 /* Byte align offset */
6364 offset = bit_offset>>3;
6367 * Calculate the number of octets used to hold the bits
6369 tot_no_bits = ((bit_offset&0x7)+no_of_bits);
6370 length = tot_no_bits>>3;
6371 remaining_bits = tot_no_bits % 8;
6372 if ((remaining_bits)!=0)
6375 if (no_of_bits < 9){
6376 value = tvb_get_bits8(tvb, bit_offset, no_of_bits);
6377 }else if(no_of_bits < 17){
6378 value = tvb_get_bits16(tvb, bit_offset, no_of_bits, little_endian);
6379 }else if(no_of_bits < 33){
6380 value = tvb_get_bits32(tvb, bit_offset, no_of_bits, little_endian);
6381 }else if(no_of_bits < 65){
6382 value = tvb_get_bits64(tvb, bit_offset, no_of_bits, little_endian);
6384 DISSECTOR_ASSERT_NOT_REACHED();
6389 *return_value=value;
6392 /* Coast clear. Try and fake it */
6393 TRY_TO_FAKE_THIS_ITEM(tree, hf_index, hf_field);
6396 mask = mask << (no_of_bits-1);
6398 /* prepare the string */
6401 for(bit=0;bit<((int)(bit_offset&0x07));bit++){
6402 if(bit&&(!(bit%4))){
6408 /* read the bits for the int */
6409 for(i=0;i<no_of_bits;i++){
6410 if(bit&&(!(bit%4))){
6413 if(bit&&(!(bit%8))){
6427 if(bit&&(!(bit%4))){
6434 strcat(str,hf_field->name);
6436 switch(hf_field->type){
6439 if (hf_field->strings) {
6440 const true_false_string *tfstring =
6441 (const true_false_string *) hf_field->strings;
6442 return proto_tree_add_boolean_format(tree, hf_index, tvb, offset, length, (guint32)value,
6445 (guint32)value ? tfstring->true_string : tfstring->false_string);
6447 return proto_tree_add_boolean_format(tree, hf_index, tvb, offset, length, (guint32)value,
6458 /* 1 - 32 bits field */
6459 if (hf_field->strings) {
6460 return proto_tree_add_uint_format(tree, hf_index, tvb, offset, length, (guint32)value,
6462 str, (hf_field->display & BASE_RANGE_STRING) ?
6463 rval_to_str((guint32)value, hf_field->strings, "Unknown ") :
6464 val_to_str((guint32)value, cVALS(hf_field->strings), "Unknown "),
6468 /* Pick the proper format string */
6469 format = hfinfo_uint_format(hf_field);
6470 if (IS_BASE_DUAL(hf_field->display)) {
6471 return proto_tree_add_uint_format(tree, hf_index, tvb, offset, length, (guint32)value,
6472 format, str, (guint32)value, (guint32)value);
6474 return proto_tree_add_uint_format(tree, hf_index, tvb, offset, length, (guint32)value,
6475 format, str, (guint32)value);
6480 /* Pick the proper format string */
6481 format = hfinfo_uint64_format(hf_field);
6482 if (IS_BASE_DUAL(hf_field->display)) {
6483 return proto_tree_add_uint64_format(tree, hf_index, tvb, offset, length, value,
6484 format, str, value, value);
6486 return proto_tree_add_uint64_format(tree, hf_index, tvb, offset, length, value,
6487 format, str, value);
6492 DISSECTOR_ASSERT_NOT_REACHED();
6499 proto_check_field_name(const gchar *field_name)
6501 return wrs_check_charset(fld_abbrev_chars, field_name);