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
56 typedef struct __subtree_lvl {
63 subtree_lvl *pushed_tree;
64 guint8 pushed_tree_index;
65 guint8 pushed_tree_max;
71 /* Candidates for assembler */
73 wrs_count_bitshift(guint32 bitmask)
77 while ((bitmask & (1 << bitshift)) == 0)
82 #define cVALS(x) (const value_string*)(x)
84 /** See inlined comments.
85 @param tree the tree to append this item to
86 @param hfindex field index
87 @param hfinfo header_field
88 @return the header field matching 'hfinfo' */
89 #define TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo) \
90 /* If this item is not referenced we dont have to do much work \
91 at all but we should still return a node so that \
92 field items below this node ( think proto_item_add_subtree() )\
93 will still have somewhere to attach to \
94 or else filtering will not work (they would be ignored since tree\
96 We fake FT_PROTOCOL unless some clients have requested us \
101 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo); \
102 if(!(PTREE_DATA(tree)->visible)){ \
103 if((hfinfo->ref_count == HF_REF_TYPE_NONE) \
104 && (hfinfo->type!=FT_PROTOCOL || \
105 PTREE_DATA(tree)->fake_protocols)){ \
106 /* just return tree back to the caller */\
112 proto_tree_free_node(proto_node *node, gpointer data);
114 static void fill_label_boolean(field_info *fi, gchar *label_str);
115 static void fill_label_uint(field_info *fi, gchar *label_str);
116 static void fill_label_uint64(field_info *fi, gchar *label_str);
117 static void fill_label_bitfield(field_info *fi, gchar *label_str);
118 static void fill_label_int(field_info *fi, gchar *label_str);
119 static void fill_label_int64(field_info *fi, gchar *label_str);
121 int hfinfo_bitwidth(header_field_info *hfinfo);
122 static const char* hfinfo_uint_vals_format(header_field_info *hfinfo);
123 static const char* hfinfo_uint_format(header_field_info *hfinfo);
124 static const char* hfinfo_uint_value_format(header_field_info *hfinfo);
125 static const char* hfinfo_uint64_format(header_field_info *hfinfo);
126 static const char* hfinfo_int_vals_format(header_field_info *hfinfo);
127 static const char* hfinfo_int_format(header_field_info *hfinfo);
128 static const char* hfinfo_int_value_format(header_field_info *hfinfo);
129 static const char* hfinfo_int64_format(header_field_info *hfinfo);
132 proto_tree_add_node(proto_tree *tree, field_info *fi);
134 static header_field_info *
135 get_hfi_and_length(int hfindex, tvbuff_t *tvb, gint start, gint *length,
139 new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
140 gint start, gint item_length);
143 alloc_field_info(proto_tree *tree, int hfindex, tvbuff_t *tvb,
144 gint start, gint *length);
147 proto_tree_add_pi(proto_tree *tree, int hfindex, tvbuff_t *tvb,
148 gint start, gint *length, field_info **pfi);
151 proto_tree_set_representation_value(proto_item *pi, const char *format, va_list ap);
153 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap);
156 proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb);
158 proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length);
160 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length);
162 proto_tree_set_time(field_info *fi, nstime_t *value_ptr);
164 proto_tree_set_string(field_info *fi, const char* value);
166 proto_tree_set_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
168 proto_tree_set_ebcdic_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
170 proto_tree_set_ether(field_info *fi, const guint8* value);
172 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start);
174 proto_tree_set_ipxnet(field_info *fi, guint32 value);
176 proto_tree_set_ipv4(field_info *fi, guint32 value);
178 proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr);
180 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start);
182 proto_tree_set_guid(field_info *fi, const e_guid_t *value_ptr);
184 proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gboolean little_endian);
186 proto_tree_set_oid(field_info *fi, const guint8* value_ptr, gint length);
188 proto_tree_set_oid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
190 proto_tree_set_boolean(field_info *fi, guint32 value);
192 proto_tree_set_float(field_info *fi, float value);
194 proto_tree_set_double(field_info *fi, double value);
196 proto_tree_set_uint(field_info *fi, guint32 value);
198 proto_tree_set_int(field_info *fi, gint32 value);
200 proto_tree_set_uint64(field_info *fi, guint64 value);
202 proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start, guint length, gboolean little_endian);
204 proto_item_add_bitmask_tree(proto_item *item, tvbuff_t *tvb, int offset, int len, gint ett,
205 const gint **fields, gboolean little_endian, int flags, gboolean first);
207 static int proto_register_field_init(header_field_info *hfinfo, int parent);
209 /* special-case header field used within proto.c */
210 int hf_text_only = -1;
212 /* Structure for information about a protocol */
214 const char *name; /* long description */
215 const char *short_name; /* short description */
216 const char *filter_name; /* name of this protocol in filters */
217 int proto_id; /* field ID for this protocol */
218 GList *fields; /* fields for this protocol */
219 GList *last_field; /* pointer to end of list of fields */
220 gboolean is_enabled; /* TRUE if protocol is enabled */
221 gboolean can_toggle; /* TRUE if is_enabled can be changed */
222 gboolean is_private; /* TRUE is protocol is private */
225 /* List of all protocols */
226 static GList *protocols = NULL;
228 #define INITIAL_NUM_PROTOCOL_HFINFO 200
231 /* Contains information about protocols and header fields. Used when
232 * dissectors register their data */
233 static GMemChunk *gmc_hfinfo = NULL;
235 /* Contains information about a field when a dissector calls
236 * proto_tree_add_item. */
237 SLAB_ITEM_TYPE_DEFINE(field_info)
238 static SLAB_FREE_LIST_DEFINE(field_info)
239 static field_info *field_info_tmp=NULL;
240 #define FIELD_INFO_NEW(fi) \
241 SLAB_ALLOC(fi, field_info)
242 #define FIELD_INFO_FREE(fi) \
243 SLAB_FREE(fi, field_info)
247 /* Contains the space for proto_nodes. */
248 SLAB_ITEM_TYPE_DEFINE(proto_node)
249 static SLAB_FREE_LIST_DEFINE(proto_node)
250 #define PROTO_NODE_NEW(node) \
251 SLAB_ALLOC(node, proto_node) \
252 node->first_child = NULL; \
253 node->last_child = NULL; \
256 #define PROTO_NODE_FREE(node) \
257 SLAB_FREE(node, proto_node)
261 /* String space for protocol and field items for the GUI */
262 SLAB_ITEM_TYPE_DEFINE(item_label_t)
263 static SLAB_FREE_LIST_DEFINE(item_label_t)
264 #define ITEM_LABEL_NEW(il) \
265 SLAB_ALLOC(il, item_label_t)
266 #define ITEM_LABEL_FREE(il) \
267 SLAB_FREE(il, item_label_t)
270 #define PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo) \
271 DISSECTOR_ASSERT((guint)hfindex < gpa_hfinfo.len); \
272 hfinfo=gpa_hfinfo.hfi[hfindex];
275 /* List which stores protocols and fields that have been registered */
276 typedef struct _gpa_hfinfo_t {
278 guint32 allocated_len;
279 header_field_info **hfi;
281 gpa_hfinfo_t gpa_hfinfo;
283 /* Balanced tree of abbreviations and IDs */
284 static GTree *gpa_name_tree = NULL;
285 static header_field_info *same_name_hfinfo;
287 static void save_same_name_hfinfo(gpointer data)
289 same_name_hfinfo = (header_field_info*)data;
292 /* Points to the first element of an array of Booleans, indexed by
293 a subtree item type; that array element is TRUE if subtrees of
294 an item of that type are to be expanded. */
295 gboolean *tree_is_expanded;
297 /* Number of elements in that array. */
300 /* Name hashtables for fast detection of duplicate names */
301 static GHashTable* proto_names = NULL;
302 static GHashTable* proto_short_names = NULL;
303 static GHashTable* proto_filter_names = NULL;
306 proto_compare_name(gconstpointer p1_arg, gconstpointer p2_arg)
308 const protocol_t *p1 = p1_arg;
309 const protocol_t *p2 = p2_arg;
311 return g_ascii_strcasecmp(p1->short_name, p2->short_name);
315 /* initialize data structures and register protocols and fields */
317 proto_init(void (register_all_protocols_func)(register_cb cb, gpointer client_data),
318 void (register_all_handoffs_func)(register_cb cb, gpointer client_data),
320 gpointer client_data)
322 static hf_register_info hf[] = {
324 { "Text item", "text", FT_NONE, BASE_NONE, NULL, 0x0,
329 proto_names = g_hash_table_new(g_int_hash, g_int_equal);
330 proto_short_names = g_hash_table_new(wrs_str_hash, g_str_equal);
331 proto_filter_names = g_hash_table_new(wrs_str_hash, g_str_equal);
335 gmc_hfinfo = g_mem_chunk_new("gmc_hfinfo",
336 sizeof(header_field_info),
337 INITIAL_NUM_PROTOCOL_HFINFO * sizeof(header_field_info),
341 gpa_hfinfo.allocated_len=0;
343 gpa_name_tree = g_tree_new_full(wrs_strcmp_with_data, NULL, NULL, save_same_name_hfinfo);
345 /* Initialize the ftype subsystem */
348 /* Register one special-case FT_TEXT_ONLY field for use when
349 converting wireshark to new-style proto_tree. These fields
350 are merely strings on the GUI tree; they are not filterable */
351 proto_register_field_array(-1, hf, array_length(hf));
353 /* Have each built-in dissector register its protocols, fields,
354 dissector tables, and dissectors to be called through a
355 handle, and do whatever one-time initialization it needs to
357 register_all_protocols_func(cb, client_data);
359 /* Now scan for python protocols */
360 register_all_py_protocols_func(cb, client_data);
364 /* Now scan for plugins and load all the ones we find, calling
365 their register routines to do the stuff described above. */
367 (*cb)(RA_PLUGIN_REGISTER, NULL, client_data);
369 register_all_plugin_registrations();
372 /* Now call the "handoff registration" routines of all built-in
373 dissectors; those routines register the dissector in other
374 dissectors' handoff tables, and fetch any dissector handles
376 register_all_handoffs_func(cb, client_data);
379 /* Now do the same with python dissectors */
380 register_all_py_handoffs_func(cb, client_data);
384 /* Now do the same with plugins. */
386 (*cb)(RA_PLUGIN_HANDOFF, NULL, client_data);
387 register_all_plugin_handoffs();
390 /* sort the protocols by protocol name */
391 protocols = g_list_sort(protocols, proto_compare_name);
393 /* We've assigned all the subtree type values; allocate the array
394 for them, and zero it out. */
395 tree_is_expanded = g_malloc(num_tree_types*sizeof (gboolean));
396 memset(tree_is_expanded, 0, num_tree_types*sizeof (gboolean));
402 /* Free the abbrev/ID GTree */
404 g_tree_destroy(gpa_name_tree);
405 gpa_name_tree = NULL;
409 g_mem_chunk_destroy(gmc_hfinfo);
411 if(gpa_hfinfo.allocated_len){
413 gpa_hfinfo.allocated_len=0;
414 g_free(gpa_hfinfo.hfi);
417 g_free(tree_is_expanded);
422 proto_tree_traverse_pre_order(proto_tree *tree, proto_tree_traverse_func func,
425 proto_node *pnode = tree;
429 if (func(pnode, data))
432 child = pnode->first_child;
433 while (child != NULL) {
435 * The routine we call might modify the child, e.g. by
436 * freeing it, so we get the child's successor before
437 * calling that routine.
440 child = current->next;
441 if (proto_tree_traverse_pre_order((proto_tree *)current, func,
450 proto_tree_traverse_post_order(proto_tree *tree, proto_tree_traverse_func func,
453 proto_node *pnode = tree;
457 child = pnode->first_child;
458 while (child != NULL) {
460 * The routine we call might modify the child, e.g. by
461 * freeing it, so we get the child's successor before
462 * calling that routine.
465 child = current->next;
466 if (proto_tree_traverse_post_order((proto_tree *)current, func,
470 if (func(pnode, data))
477 proto_tree_children_foreach(proto_tree *tree, proto_tree_foreach_func func,
480 proto_node *node = tree;
483 node = node->first_child;
484 while (node != NULL) {
486 node = current->next;
487 func((proto_tree *)current, data);
491 /* frees the resources that the dissection a proto_tree uses */
493 proto_tree_free(proto_tree *tree)
495 proto_tree_traverse_post_order(tree, proto_tree_free_node, NULL);
499 free_GPtrArray_value(gpointer key, gpointer value, gpointer user_data _U_)
501 GPtrArray *ptrs = value;
502 gint hfid = (gint)(long)key;
503 header_field_info *hfinfo;
505 PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
506 if(hfinfo->ref_count != HF_REF_TYPE_NONE) {
507 /* when a field is referenced by a filter this also
508 affects the refcount for the parent protocol so we need
509 to adjust the refcount for the parent as well
511 if( hfinfo->parent != -1 ) {
512 header_field_info *parent_hfinfo;
513 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
514 parent_hfinfo->ref_count = HF_REF_TYPE_NONE;
516 hfinfo->ref_count = HF_REF_TYPE_NONE;
519 g_ptr_array_free(ptrs, TRUE);
523 free_node_tree_data(tree_data_t *tree_data)
525 if (tree_data->interesting_hfids) {
526 /* Free all the GPtrArray's in the interesting_hfids hash. */
527 g_hash_table_foreach(tree_data->interesting_hfids,
528 free_GPtrArray_value, NULL);
530 /* And then destroy the hash. */
531 g_hash_table_destroy(tree_data->interesting_hfids);
534 /* And finally the tree_data_t itself. */
538 #define FREE_NODE_FIELD_INFO(finfo) \
540 ITEM_LABEL_FREE(finfo->rep); \
542 FVALUE_CLEANUP(&finfo->value); \
543 FIELD_INFO_FREE(finfo);
546 proto_tree_free_node(proto_node *node, gpointer data _U_)
548 field_info *finfo = PNODE_FINFO(node);
550 proto_node *parent = node->parent;
554 /* This is the root node. Destroy the per-tree data.
555 * There is no field_info to destroy. */
556 if (PTREE_DATA(node)) free_node_tree_data(PTREE_DATA(node));
559 /* This is a child node. Don't free the per-tree data, but
560 * do free the field_info data. */
561 FREE_NODE_FIELD_INFO(finfo);
565 /* NOTE: This code is required when this function is used to free individual
566 * nodes only. Current use is for the destruction of complete trees, so the
567 * inconsistancies have no ill effect.
569 /* Remove node from parent */
571 proto_item *prev_item = NULL;
572 if (parent->first_child == node) {
573 parent->first_child = node->next;
575 /* find previous and change its next */
576 for (prev_item = parent->first_child; prev_item; prev_item = prev_item->next) {
577 if (prev_item->next == node) {
581 DISSECTOR_ASSERT(prev_item);
582 prev_item->next = node->next;
584 /* fix last_child if required */
585 if (parent->last_child == node) {
586 parent->last_child = prev_item;
589 DISSECTOR_ASSERT(node->first_child == NULL && node->last_child == NULL);
591 /* Free the proto_node. */
592 PROTO_NODE_FREE(node);
594 return FALSE; /* FALSE = do not end traversal of protocol tree */
597 /* Is the parsing being done for a visible proto_tree or an invisible one?
598 * By setting this correctly, the proto_tree creation is sped up by not
599 * having to call g_vsnprintf and copy strings around.
602 proto_tree_set_visible(proto_tree *tree, gboolean visible)
604 PTREE_DATA(tree)->visible = visible;
608 proto_tree_set_fake_protocols(proto_tree *tree, gboolean fake_protocols)
610 PTREE_DATA(tree)->fake_protocols = fake_protocols;
613 /* Assume dissector set only its protocol fields.
614 This function is called by dissectors and allowes to speed up filtering
615 in wireshark, if this function returns FALSE it is safe to reset tree to NULL
616 and thus skip calling most of the expensive proto_tree_add_...()
618 If the tree is visible we implicitely assume the field is referenced.
621 proto_field_is_referenced(proto_tree *tree, int proto_id)
623 register header_field_info *hfinfo;
629 if (PTREE_DATA(tree)->visible)
632 PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
633 if (hfinfo->ref_count != HF_REF_TYPE_NONE)
636 if (hfinfo->type == FT_PROTOCOL && !PTREE_DATA(tree)->fake_protocols)
643 /* Finds a record in the hf_info_records array by id. */
645 proto_registrar_get_nth(guint hfindex)
647 register header_field_info *hfinfo;
649 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
654 /* Prefix initialization
655 * this allows for a dissector to register a display filter name prefix
656 * so that it can delay the initialization of the hf array as long as
660 /* compute a hash for the part before the dot of a display filter */
662 prefix_hash (gconstpointer key) {
663 /* end the string at the dot and compute its hash */
664 gchar* copy = ep_strdup(key);
674 return g_str_hash(copy);
677 /* are both strings equal up to the end or the dot? */
679 prefix_equal (gconstpointer ap,gconstpointer bp) {
687 if ((ac == '.' || ac == '\0') && (bc == '.' || bc == '\0')) return TRUE;
689 if ( (ac == '.' || ac == '\0') && ! (bc == '.' || bc == '\0') ) return FALSE;
690 if ( (bc == '.' || bc == '\0') && ! (ac == '.' || ac == '\0') ) return FALSE;
692 if (ac != bc) return FALSE;
699 /* indexed by prefix, contains initializers */
700 static GHashTable* prefixes = NULL;
703 /* Register a new prefix for "delayed" initialization of field arrays */
705 proto_register_prefix(const char *prefix, prefix_initializer_t pi ) {
707 prefixes = g_hash_table_new(prefix_hash,prefix_equal);
710 g_hash_table_insert(prefixes,(gpointer)prefix,pi);
713 /* helper to call all prefix initializers */
715 initialize_prefix(gpointer k, gpointer v, gpointer u _U_) {
716 ((prefix_initializer_t)v)(k);
720 /** Initialize every remaining uninitialized prefix. */
722 proto_initialize_all_prefixes(void) {
723 g_hash_table_foreach_remove(prefixes, initialize_prefix, NULL);
726 /* Finds a record in the hf_info_records array by name.
727 * If it fails to find it in the already registered fields,
728 * it tries to find and call an initializer in the prefixes
729 * table and if so it looks again.
732 proto_registrar_get_byname(const char *field_name)
734 header_field_info* hfinfo;
735 prefix_initializer_t pi;
740 hfinfo = g_tree_lookup(gpa_name_tree, field_name);
742 if (hfinfo) return hfinfo;
744 if (!prefixes) return NULL;
746 if(( pi = g_hash_table_lookup(prefixes,field_name) )) {
748 g_hash_table_remove(prefixes,field_name);
753 return g_tree_lookup(gpa_name_tree, field_name);
758 ptvcursor_new_subtree_levels(ptvcursor_t * ptvc)
760 subtree_lvl * pushed_tree;
762 DISSECTOR_ASSERT(ptvc->pushed_tree_max <= SUBTREE_MAX_LEVELS-SUBTREE_ONCE_ALLOCATION_NUMBER);
763 ptvc->pushed_tree_max += SUBTREE_ONCE_ALLOCATION_NUMBER;
765 pushed_tree = ep_alloc(sizeof(subtree_lvl) * ptvc->pushed_tree_max);
766 DISSECTOR_ASSERT(pushed_tree != NULL);
767 if (ptvc->pushed_tree)
768 memcpy(pushed_tree, ptvc->pushed_tree, ptvc->pushed_tree_max - SUBTREE_ONCE_ALLOCATION_NUMBER);
769 ptvc->pushed_tree = pushed_tree;
773 ptvcursor_free_subtree_levels(ptvcursor_t * ptvc)
775 ptvc->pushed_tree = NULL;
776 ptvc->pushed_tree_max = 0;
777 DISSECTOR_ASSERT(ptvc->pushed_tree_index ==0);
778 ptvc->pushed_tree_index = 0;
781 /* Allocates an initializes a ptvcursor_t with 3 variables:
782 * proto_tree, tvbuff, and offset. */
784 ptvcursor_new(proto_tree *tree, tvbuff_t *tvb, gint offset)
788 ptvc = ep_alloc(sizeof(ptvcursor_t));
791 ptvc->offset = offset;
792 ptvc->pushed_tree= NULL;
793 ptvc->pushed_tree_max= 0;
794 ptvc->pushed_tree_index= 0;
799 /* Frees memory for ptvcursor_t, but nothing deeper than that. */
801 ptvcursor_free(ptvcursor_t *ptvc)
803 ptvcursor_free_subtree_levels(ptvc);
807 /* Returns tvbuff. */
809 ptvcursor_tvbuff(ptvcursor_t* ptvc)
814 /* Returns current offset. */
816 ptvcursor_current_offset(ptvcursor_t* ptvc)
822 ptvcursor_tree(ptvcursor_t* ptvc)
831 ptvcursor_set_tree(ptvcursor_t* ptvc, proto_tree *tree)
836 /* creates a subtree, sets it as the working tree and pushes the old working tree */
838 ptvcursor_push_subtree(ptvcursor_t *ptvc, proto_item *it, gint ett_subtree)
840 subtree_lvl * subtree;
841 if (ptvc->pushed_tree_index >= ptvc->pushed_tree_max)
842 ptvcursor_new_subtree_levels(ptvc);
844 subtree = ptvc->pushed_tree+ptvc->pushed_tree_index;
845 subtree->tree = ptvc->tree;
847 ptvc->pushed_tree_index++;
848 return ptvcursor_set_subtree(ptvc, it, ett_subtree);
853 ptvcursor_pop_subtree(ptvcursor_t *ptvc)
855 subtree_lvl * subtree;
856 if (ptvc->pushed_tree_index <= 0)
859 ptvc->pushed_tree_index--;
860 subtree = ptvc->pushed_tree+ptvc->pushed_tree_index;
861 if (subtree->it != NULL)
862 proto_item_set_len(subtree->it, ptvcursor_current_offset(ptvc) - subtree->cursor_offset);
864 ptvc->tree = subtree->tree;
867 /* saves the current tvb offset and the item in the current subtree level */
869 ptvcursor_subtree_set_item(ptvcursor_t * ptvc, proto_item * it)
871 subtree_lvl * subtree;
873 DISSECTOR_ASSERT(ptvc->pushed_tree_index > 0);
875 subtree = ptvc->pushed_tree+ptvc->pushed_tree_index-1;
877 subtree->cursor_offset = ptvcursor_current_offset(ptvc);
880 /* Creates a subtree and adds it to the cursor as the working tree but does not
881 * save the old working tree */
883 ptvcursor_set_subtree(ptvcursor_t *ptvc, proto_item *it, gint ett_subtree)
885 ptvc->tree = proto_item_add_subtree(it, ett_subtree);
890 ptvcursor_add_subtree_item(ptvcursor_t * ptvc, proto_item * it, gint ett_subtree, gint length)
892 ptvcursor_push_subtree(ptvc, it, ett_subtree);
893 if (length == SUBTREE_UNDEFINED_LENGTH)
894 ptvcursor_subtree_set_item(ptvc, it);
895 return ptvcursor_tree(ptvc);
898 /* Add an item to the tree and create a subtree
899 * If the length is unknown, length may be defined as SUBTREE_UNDEFINED_LENGTH.
900 * In this case, when the subtree will be closed, the parent item length will
901 * be equal to the advancement of the cursor since the creation of the subtree.
904 ptvcursor_add_with_subtree(ptvcursor_t * ptvc, int hfindex, gint length,
905 gboolean little_endian, gint ett_subtree)
909 it = ptvcursor_add_no_advance(ptvc, hfindex, length, little_endian);
910 return ptvcursor_add_subtree_item(ptvc, it, ett_subtree, length);
914 proto_tree_add_text_node(proto_tree *tree, tvbuff_t *tvb, gint start, gint length);
916 /* Add a text node to the tree and create a subtree
917 * If the length is unknown, length may be defined as SUBTREE_UNDEFINED_LENGTH.
918 * In this case, when the subtree will be closed, the item length will be equal
919 * to the advancement of the cursor since the creation of the subtree.
922 ptvcursor_add_text_with_subtree(ptvcursor_t * ptvc, gint length,
923 gint ett_subtree, const char *format, ...)
927 header_field_info *hfinfo;
929 TRY_TO_FAKE_THIS_ITEM(ptvcursor_tree(ptvc), hf_text_only, hfinfo);
931 it = proto_tree_add_text_node(ptvcursor_tree(ptvc), ptvcursor_tvbuff(ptvc),
932 ptvcursor_current_offset(ptvc), length);
937 va_start(ap, format);
938 proto_tree_set_representation(it, format, ap);
941 return ptvcursor_add_subtree_item(ptvc, it, ett_subtree, length);
944 /* Add a text-only node, leaving it to our caller to fill the text in */
946 proto_tree_add_text_node(proto_tree *tree, tvbuff_t *tvb, gint start, gint length)
950 pi = proto_tree_add_pi(tree, hf_text_only, tvb, start, &length, NULL);
957 /* Add a text-only node to the proto_tree */
959 proto_tree_add_text(proto_tree *tree, tvbuff_t *tvb, gint start, gint length,
960 const char *format, ...)
964 header_field_info *hfinfo;
966 TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
968 pi = proto_tree_add_text_node(tree, tvb, start, length);
972 va_start(ap, format);
973 proto_tree_set_representation(pi, format, ap);
979 /* Add a text-only node to the proto_tree (va_list version) */
981 proto_tree_add_text_valist(proto_tree *tree, tvbuff_t *tvb, gint start,
982 gint length, const char *format, va_list ap)
985 header_field_info *hfinfo;
987 TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
989 pi = proto_tree_add_text_node(tree, tvb, start, length);
993 proto_tree_set_representation(pi, format, ap);
998 /* Add a text-only node for debugging purposes. The caller doesn't need
999 * to worry about tvbuff, start, or length. Debug message gets sent to
1002 proto_tree_add_debug_text(proto_tree *tree, const char *format, ...)
1007 pi = proto_tree_add_text_node(tree, NULL, 0, 0);
1009 va_start(ap, format);
1011 proto_tree_set_representation(pi, format, ap);
1012 vprintf(format, ap);
1021 get_uint_value(tvbuff_t *tvb, gint offset, gint length, gboolean little_endian)
1028 value = tvb_get_guint8(tvb, offset);
1032 value = little_endian ? tvb_get_letohs(tvb, offset)
1033 : tvb_get_ntohs(tvb, offset);
1037 value = little_endian ? tvb_get_letoh24(tvb, offset)
1038 : tvb_get_ntoh24(tvb, offset);
1042 value = little_endian ? tvb_get_letohl(tvb, offset)
1043 : tvb_get_ntohl(tvb, offset);
1047 DISSECTOR_ASSERT_NOT_REACHED();
1055 get_int_value(tvbuff_t *tvb, gint offset, gint length, gboolean little_endian)
1062 value = (gint8)tvb_get_guint8(tvb, offset);
1066 value = (gint16) (little_endian ? tvb_get_letohs(tvb, offset)
1067 : tvb_get_ntohs(tvb, offset));
1071 value = little_endian ? tvb_get_letoh24(tvb, offset)
1072 : tvb_get_ntoh24(tvb, offset);
1073 if (value & 0x00800000) {
1074 /* Sign bit is set; sign-extend it. */
1075 value |= 0xFF000000;
1080 value = little_endian ? tvb_get_letohl(tvb, offset)
1081 : tvb_get_ntohl(tvb, offset);
1085 DISSECTOR_ASSERT_NOT_REACHED();
1092 static GPtrArray *proto_lookup_or_create_interesting_hfids(proto_tree *tree,
1093 header_field_info *hfinfo)
1095 GPtrArray *ptrs = NULL;
1097 DISSECTOR_ASSERT(tree);
1098 DISSECTOR_ASSERT(hfinfo);
1100 if (hfinfo->ref_count == HF_REF_TYPE_DIRECT) {
1101 if (PTREE_DATA(tree)->interesting_hfids == NULL) {
1102 /* Initialize the hash because we now know that it is needed */
1103 PTREE_DATA(tree)->interesting_hfids =
1104 g_hash_table_new(g_direct_hash, NULL /* g_direct_equal */);
1107 ptrs = g_hash_table_lookup(PTREE_DATA(tree)->interesting_hfids,
1108 GINT_TO_POINTER(hfinfo->id));
1110 /* First element triggers the creation of pointer array */
1111 ptrs = g_ptr_array_new();
1112 g_hash_table_insert(PTREE_DATA(tree)->interesting_hfids,
1113 GINT_TO_POINTER(hfinfo->id), ptrs);
1120 /* Add an item to a proto_tree, using the text label registered to that item;
1121 the item is extracted from the tvbuff handed to it. */
1123 proto_tree_new_item(field_info *new_fi, proto_tree *tree,
1124 tvbuff_t *tvb, gint start, gint length, gboolean little_endian)
1133 /* there is a possibility here that we might raise an exception
1134 * and thus would lose track of the field_info.
1135 * store it in a temp so that if we come here again we can reclaim
1136 * the field_info without leaking memory.
1138 /* XXX this only keeps track of one field_info struct,
1139 if we ever go multithreaded for calls to this function
1140 we have to change this code to use per thread variable.
1143 /* oops, last one we got must have been lost due
1145 * good thing we saved it, now we can reverse the
1146 * memory leak and reclaim it.
1148 SLAB_FREE(field_info_tmp, field_info);
1150 /* we might throw an exception, keep track of this one
1151 * across the "dangerous" section below.
1153 field_info_tmp=new_fi;
1155 switch(new_fi->hfinfo->type) {
1157 /* no value to set for FT_NONE */
1161 proto_tree_set_protocol_tvb(new_fi, tvb);
1165 proto_tree_set_bytes_tvb(new_fi, tvb, start, length);
1169 n = get_uint_value(tvb, start, length, little_endian);
1170 proto_tree_set_bytes_tvb(new_fi, tvb, start + length, n);
1172 /* Instead of calling proto_item_set_len(), since we don't yet
1173 * have a proto_item, we set the field_info's length ourselves. */
1174 new_fi->length = n + length;
1178 proto_tree_set_boolean(new_fi,
1179 get_uint_value(tvb, start, length, little_endian));
1182 /* XXX - make these just FT_UINT? */
1187 proto_tree_set_uint(new_fi,
1188 get_uint_value(tvb, start, length, little_endian));
1193 DISSECTOR_ASSERT( length <= 8 && length >= 1);
1194 proto_tree_set_uint64_tvb(new_fi, tvb, start, length, little_endian);
1197 /* XXX - make these just FT_INT? */
1202 proto_tree_set_int(new_fi,
1203 get_int_value(tvb, start, length, little_endian));
1207 DISSECTOR_ASSERT(length == 4);
1208 value = tvb_get_ipv4(tvb, start);
1209 proto_tree_set_ipv4(new_fi, little_endian ? GUINT32_SWAP_LE_BE(value) : value);
1213 DISSECTOR_ASSERT(length == 4);
1214 proto_tree_set_ipxnet(new_fi,
1215 get_uint_value(tvb, start, 4, FALSE));
1219 DISSECTOR_ASSERT(length == 16);
1220 proto_tree_set_ipv6_tvb(new_fi, tvb, start);
1224 DISSECTOR_ASSERT(length == 6);
1225 proto_tree_set_ether_tvb(new_fi, tvb, start);
1229 DISSECTOR_ASSERT(length == 16);
1230 proto_tree_set_guid_tvb(new_fi, tvb, start, little_endian);
1234 proto_tree_set_oid_tvb(new_fi, tvb, start, length);
1238 DISSECTOR_ASSERT(length == 4);
1240 floatval = tvb_get_letohieee_float(tvb, start);
1242 floatval = tvb_get_ntohieee_float(tvb, start);
1243 proto_tree_set_float(new_fi, floatval);
1247 DISSECTOR_ASSERT(length == 8);
1249 doubleval = tvb_get_letohieee_double(tvb, start);
1251 doubleval = tvb_get_ntohieee_double(tvb, start);
1252 proto_tree_set_double(new_fi, doubleval);
1256 proto_tree_set_string_tvb(new_fi, tvb, start, length);
1260 DISSECTOR_ASSERT(length >= -1);
1261 /* Instead of calling proto_item_set_len(),
1262 * since we don't yet have a proto_item, we
1263 * set the field_info's length ourselves.
1265 * XXX - our caller can't use that length to
1266 * advance an offset unless they arrange that
1267 * there always be a protocol tree into which
1268 * we're putting this item.
1271 /* This can throw an exception */
1272 length = tvb_strsize(tvb, start);
1274 string = ep_alloc(length);
1276 tvb_memcpy(tvb, string, start, length);
1277 } else if (length == 0) {
1280 /* In this case, length signifies
1281 * the length of the string.
1283 * This could either be a null-padded
1284 * string, which doesn't necessarily
1285 * have a '\0' at the end, or a
1286 * null-terminated string, with a
1287 * trailing '\0'. (Yes, there are
1288 * cases where you have a string
1289 * that's both counted and null-
1292 * In the first case, we must
1293 * allocate a buffer of length
1294 * "length+1", to make room for
1297 * In the second case, we don't
1298 * assume that there is a trailing
1299 * '\0' there, as the packet might
1300 * be malformed. (XXX - should we
1301 * throw an exception if there's no
1302 * trailing '\0'?) Therefore, we
1303 * allocate a buffer of length
1304 * "length+1", and put in a trailing
1305 * '\0', just to be safe.
1307 * (XXX - this would change if
1308 * we made string values counted
1309 * rather than null-terminated.)
1311 string = tvb_get_ephemeral_string(tvb,
1315 new_fi->length = length;
1316 proto_tree_set_string(new_fi, string);
1320 proto_tree_set_ebcdic_string_tvb(new_fi, tvb, start, length);
1323 case FT_UINT_STRING:
1324 n = get_uint_value(tvb, start, length, little_endian);
1325 proto_tree_set_string_tvb(new_fi, tvb, start + length, n);
1327 /* Instead of calling proto_item_set_len(), since we
1328 * don't yet have a proto_item, we set the
1329 * field_info's length ourselves.
1331 * XXX - our caller can't use that length to
1332 * advance an offset unless they arrange that
1333 * there always be a protocol tree into which
1334 * we're putting this item.
1336 new_fi->length = n + length;
1340 g_error("new_fi->hfinfo->type %d (%s) not handled\n",
1341 new_fi->hfinfo->type,
1342 ftype_name(new_fi->hfinfo->type));
1343 DISSECTOR_ASSERT_NOT_REACHED();
1347 /* Don't add new node to proto_tree until now so that any exceptions
1348 * raised by a tvbuff access method doesn't leave junk in the proto_tree. */
1349 pi = proto_tree_add_node(tree, new_fi);
1351 /* we did not raise an exception so we dont have to remember this
1352 * field_info struct any more.
1354 field_info_tmp=NULL;
1356 /* If the proto_tree wants to keep a record of this finfo
1357 * for quick lookup, then record it. */
1358 ptrs = proto_lookup_or_create_interesting_hfids(tree, new_fi->hfinfo);
1360 g_ptr_array_add(ptrs, new_fi);
1365 /* Gets data from tvbuff, adds it to proto_tree, increments offset,
1366 and returns proto_item* */
1368 ptvcursor_add(ptvcursor_t *ptvc, int hfindex, gint length,
1369 gboolean little_endian)
1372 header_field_info *hfinfo;
1377 /* We can't fake it just yet. We have to advance the cursor
1378 TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfindex, hfinfo); */
1380 offset = ptvc->offset;
1381 hfinfo = get_hfi_and_length(hfindex, ptvc->tvb, offset, &length,
1383 ptvc->offset += length;
1384 if (hfinfo->type == FT_UINT_BYTES || hfinfo->type == FT_UINT_STRING) {
1386 * The length of the rest of the item is in the first N
1387 * bytes of the item.
1389 n = get_uint_value(ptvc->tvb, offset, length, little_endian);
1393 /* Coast clear. Try and fake it */
1394 TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfindex, hfinfo);
1396 new_fi = new_field_info(ptvc->tree, hfinfo, ptvc->tvb, offset,
1401 return proto_tree_new_item(new_fi, ptvc->tree, ptvc->tvb,
1402 offset, length, little_endian);
1405 /* Add an item to a proto_tree, using the text label registered to that item;
1406 the item is extracted from the tvbuff handed to it. */
1408 proto_tree_add_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1409 gint start, gint length, gboolean little_endian)
1412 header_field_info *hfinfo;
1414 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1416 new_fi = alloc_field_info(tree, hfindex, tvb, start, &length);
1421 return proto_tree_new_item(new_fi, tree, tvb, start,
1422 length, little_endian);
1425 /* Add a FT_NONE to a proto_tree */
1427 proto_tree_add_none_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1428 gint length, const char *format, ...)
1432 header_field_info *hfinfo;
1434 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1436 DISSECTOR_ASSERT(hfinfo->type == FT_NONE);
1438 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, NULL);
1440 va_start(ap, format);
1441 proto_tree_set_representation(pi, format, ap);
1444 /* no value to set for FT_NONE */
1448 /* Gets data from tvbuff, adds it to proto_tree, *DOES NOT* increment
1449 * offset, and returns proto_item* */
1451 ptvcursor_add_no_advance(ptvcursor_t* ptvc, int hf, gint length,
1452 gboolean endianness)
1456 item = proto_tree_add_item(ptvc->tree, hf, ptvc->tvb, ptvc->offset,
1457 length, endianness);
1462 /* Advance the ptvcursor's offset within its tvbuff without
1463 * adding anything to the proto_tree. */
1465 ptvcursor_advance(ptvcursor_t* ptvc, gint length)
1467 ptvc->offset += length;
1472 proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb)
1474 fvalue_set(&fi->value, tvb, TRUE);
1477 /* Add a FT_PROTOCOL to a proto_tree */
1479 proto_tree_add_protocol_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1480 gint length, const char *format, ...)
1485 header_field_info *hfinfo;
1487 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1489 DISSECTOR_ASSERT(hfinfo->type == FT_PROTOCOL);
1491 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1493 va_start(ap, format);
1494 proto_tree_set_representation(pi, format, ap);
1498 proto_tree_set_protocol_tvb(new_fi, tvb);
1501 proto_tree_set_protocol_tvb(new_fi, NULL);
1507 /* Add a FT_BYTES to a proto_tree */
1509 proto_tree_add_bytes(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1510 gint length, const guint8 *start_ptr)
1514 header_field_info *hfinfo;
1516 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1518 DISSECTOR_ASSERT(hfinfo->type == FT_BYTES);
1520 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1521 proto_tree_set_bytes(new_fi, start_ptr, length);
1527 proto_tree_add_bytes_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1528 gint start, gint length, const guint8 *start_ptr,
1529 const char *format, ...)
1533 header_field_info *hfinfo;
1535 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1537 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length, start_ptr);
1541 va_start(ap, format);
1542 proto_tree_set_representation_value(pi, format, ap);
1549 proto_tree_add_bytes_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1550 gint length, const guint8 *start_ptr, const char *format, ...)
1554 header_field_info *hfinfo;
1556 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1558 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length, start_ptr);
1562 va_start(ap, format);
1563 proto_tree_set_representation(pi, format, ap);
1570 proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length)
1574 bytes = g_byte_array_new();
1576 g_byte_array_append(bytes, start_ptr, length);
1578 col_custom_set_fstr(fi->hfinfo, "%s", bytes_to_str(bytes->data,
1580 fvalue_set(&fi->value, bytes, TRUE);
1585 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length)
1587 proto_tree_set_bytes(fi, tvb_get_ptr(tvb, offset, length), length);
1590 /* Add a FT_*TIME to a proto_tree */
1592 proto_tree_add_time(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1593 nstime_t *value_ptr)
1597 header_field_info *hfinfo;
1599 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1601 DISSECTOR_ASSERT(hfinfo->type == FT_ABSOLUTE_TIME ||
1602 hfinfo->type == FT_RELATIVE_TIME);
1604 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1605 proto_tree_set_time(new_fi, value_ptr);
1611 proto_tree_add_time_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1612 gint start, gint length, nstime_t *value_ptr,
1613 const char *format, ...)
1617 header_field_info *hfinfo;
1619 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1621 pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
1625 va_start(ap, format);
1626 proto_tree_set_representation_value(pi, format, ap);
1633 proto_tree_add_time_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1634 nstime_t *value_ptr, const char *format, ...)
1638 header_field_info *hfinfo;
1640 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1642 pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
1646 va_start(ap, format);
1647 proto_tree_set_representation(pi, format, ap);
1653 /* Set the FT_*TIME value */
1655 proto_tree_set_time(field_info *fi, nstime_t *value_ptr)
1657 header_field_info *hfinfo;
1659 DISSECTOR_ASSERT(value_ptr != NULL);
1660 hfinfo = fi->hfinfo;
1662 if (hfinfo->type == FT_ABSOLUTE_TIME) {
1663 col_custom_set_fstr(fi->hfinfo, "%s", abs_time_to_str(value_ptr));
1664 } else if (hfinfo->type == FT_RELATIVE_TIME) {
1665 col_custom_set_fstr(fi->hfinfo, "%s", rel_time_to_secs_str(value_ptr));
1667 fvalue_set(&fi->value, value_ptr, FALSE);
1670 /* Add a FT_IPXNET to a proto_tree */
1672 proto_tree_add_ipxnet(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1677 header_field_info *hfinfo;
1679 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1681 DISSECTOR_ASSERT(hfinfo->type == FT_IPXNET);
1683 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1684 proto_tree_set_ipxnet(new_fi, value);
1690 proto_tree_add_ipxnet_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1691 gint start, gint length, guint32 value, const char *format, ...)
1695 header_field_info *hfinfo;
1697 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1699 pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
1703 va_start(ap, format);
1704 proto_tree_set_representation_value(pi, format, ap);
1711 proto_tree_add_ipxnet_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1712 guint32 value, const char *format, ...)
1716 header_field_info *hfinfo;
1718 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1720 pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
1724 va_start(ap, format);
1725 proto_tree_set_representation(pi, format, ap);
1731 /* Set the FT_IPXNET value */
1733 proto_tree_set_ipxnet(field_info *fi, guint32 value)
1735 fvalue_set_uinteger(&fi->value, value);
1738 /* Add a FT_IPv4 to a proto_tree */
1740 proto_tree_add_ipv4(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1745 header_field_info *hfinfo;
1747 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1749 DISSECTOR_ASSERT(hfinfo->type == FT_IPv4);
1751 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1752 proto_tree_set_ipv4(new_fi, value);
1758 proto_tree_add_ipv4_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1759 gint start, gint length, guint32 value, const char *format, ...)
1763 header_field_info *hfinfo;
1765 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1767 pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
1771 va_start(ap, format);
1772 proto_tree_set_representation_value(pi, format, ap);
1779 proto_tree_add_ipv4_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1780 guint32 value, const char *format, ...)
1784 header_field_info *hfinfo;
1786 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1788 pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
1792 va_start(ap, format);
1793 proto_tree_set_representation(pi, format, ap);
1799 /* Set the FT_IPv4 value */
1801 proto_tree_set_ipv4(field_info *fi, guint32 value)
1803 col_custom_set_fstr(fi->hfinfo, "%s",
1804 ip_to_str((guint8 *)&value));
1805 fvalue_set_uinteger(&fi->value, value);
1808 /* Add a FT_IPv6 to a proto_tree */
1810 proto_tree_add_ipv6(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1811 const guint8* value_ptr)
1815 header_field_info *hfinfo;
1817 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1819 DISSECTOR_ASSERT(hfinfo->type == FT_IPv6);
1821 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1822 proto_tree_set_ipv6(new_fi, value_ptr);
1828 proto_tree_add_ipv6_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1829 gint start, gint length, const guint8* value_ptr,
1830 const char *format, ...)
1834 header_field_info *hfinfo;
1836 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1838 pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
1842 va_start(ap, format);
1843 proto_tree_set_representation_value(pi, format, ap);
1850 proto_tree_add_ipv6_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1851 const guint8* value_ptr, const char *format, ...)
1855 header_field_info *hfinfo;
1857 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1859 pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
1863 va_start(ap, format);
1864 proto_tree_set_representation(pi, format, ap);
1870 /* Set the FT_IPv6 value */
1872 proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr)
1874 DISSECTOR_ASSERT(value_ptr != NULL);
1875 fvalue_set(&fi->value, (gpointer) value_ptr, FALSE);
1879 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start)
1881 proto_tree_set_ipv6(fi, tvb_get_ptr(tvb, start, 16));
1884 /* Add a FT_GUID to a proto_tree */
1886 proto_tree_add_guid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1887 const e_guid_t *value_ptr)
1891 header_field_info *hfinfo;
1893 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1895 DISSECTOR_ASSERT(hfinfo->type == FT_GUID);
1897 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1898 proto_tree_set_guid(new_fi, value_ptr);
1904 proto_tree_add_guid_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1905 gint start, gint length, const e_guid_t *value_ptr,
1906 const char *format, ...)
1910 header_field_info *hfinfo;
1912 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1914 pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
1918 va_start(ap, format);
1919 proto_tree_set_representation_value(pi, format, ap);
1926 proto_tree_add_guid_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1927 const e_guid_t *value_ptr, const char *format, ...)
1931 header_field_info *hfinfo;
1933 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1935 pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
1939 va_start(ap, format);
1940 proto_tree_set_representation(pi, format, ap);
1946 /* Set the FT_GUID value */
1948 proto_tree_set_guid(field_info *fi, const e_guid_t *value_ptr)
1950 DISSECTOR_ASSERT(value_ptr != NULL);
1951 col_custom_set_fstr(fi->hfinfo, "%s",
1952 guid_to_str(value_ptr));
1953 fvalue_set(&fi->value, (gpointer) value_ptr, FALSE);
1957 proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gboolean little_endian)
1961 tvb_get_guid(tvb, start, &guid, little_endian);
1962 proto_tree_set_guid(fi, &guid);
1965 /* Add a FT_OID to a proto_tree */
1967 proto_tree_add_oid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1968 const guint8* value_ptr)
1972 header_field_info *hfinfo;
1974 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1976 DISSECTOR_ASSERT(hfinfo->type == FT_OID);
1978 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1979 proto_tree_set_oid(new_fi, value_ptr, length);
1985 proto_tree_add_oid_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1986 gint start, gint length, const guint8* value_ptr,
1987 const char *format, ...)
1991 header_field_info *hfinfo;
1993 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1995 pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
1999 va_start(ap, format);
2000 proto_tree_set_representation_value(pi, format, ap);
2007 proto_tree_add_oid_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2008 const guint8* value_ptr, const char *format, ...)
2012 header_field_info *hfinfo;
2014 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2016 pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
2020 va_start(ap, format);
2021 proto_tree_set_representation(pi, format, ap);
2027 /* Set the FT_OID value */
2029 proto_tree_set_oid(field_info *fi, const guint8* value_ptr, gint length)
2033 DISSECTOR_ASSERT(value_ptr != NULL);
2035 bytes = g_byte_array_new();
2037 g_byte_array_append(bytes, value_ptr, length);
2039 col_custom_set_fstr(fi->hfinfo, "%s",
2040 oid_resolved_from_encoded(value_ptr, length));
2041 fvalue_set(&fi->value, bytes, TRUE);
2045 proto_tree_set_oid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
2047 proto_tree_set_oid(fi, tvb_get_ptr(tvb, start, length), length);
2051 proto_tree_set_uint64(field_info *fi, guint64 value)
2053 col_custom_set_fstr(fi->hfinfo, "%" G_GINT64_MODIFIER "u",
2055 fvalue_set_integer64(&fi->value, value);
2059 proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start, guint length, gboolean little_endian)
2062 guint8* b = ep_tvb_memdup(tvb,start,length);
2067 default: DISSECTOR_ASSERT_NOT_REACHED();
2068 case 8: value <<= 8; value += *--b;
2069 case 7: value <<= 8; value += *--b;
2070 case 6: value <<= 8; value += *--b;
2071 case 5: value <<= 8; value += *--b;
2072 case 4: value <<= 8; value += *--b;
2073 case 3: value <<= 8; value += *--b;
2074 case 2: value <<= 8; value += *--b;
2075 case 1: value <<= 8; value += *--b;
2080 default: DISSECTOR_ASSERT_NOT_REACHED();
2081 case 8: value <<= 8; value += *b++;
2082 case 7: value <<= 8; value += *b++;
2083 case 6: value <<= 8; value += *b++;
2084 case 5: value <<= 8; value += *b++;
2085 case 4: value <<= 8; value += *b++;
2086 case 3: value <<= 8; value += *b++;
2087 case 2: value <<= 8; value += *b++;
2088 case 1: value <<= 8; value += *b++;
2093 proto_tree_set_uint64(fi, value);
2096 /* Add a FT_STRING or FT_STRINGZ to a proto_tree. Creates own copy of string,
2097 * and frees it when the proto_tree is destroyed. */
2099 proto_tree_add_string(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2100 gint length, const char* value)
2104 header_field_info *hfinfo;
2106 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2108 DISSECTOR_ASSERT(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ);
2110 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2111 DISSECTOR_ASSERT(length >= 0);
2112 proto_tree_set_string(new_fi, value);
2118 proto_tree_add_string_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2119 gint start, gint length, const char* value, const char *format,
2124 header_field_info *hfinfo;
2126 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2128 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
2132 va_start(ap, format);
2133 proto_tree_set_representation_value(pi, format, ap);
2140 proto_tree_add_string_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2141 gint length, const char* value, const char *format, ...)
2145 header_field_info *hfinfo;
2147 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2149 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
2153 va_start(ap, format);
2154 proto_tree_set_representation(pi, format, ap);
2160 /* Appends string data to a FT_STRING or FT_STRINGZ, allowing progressive
2161 * field info update instead of only updating the representation as does
2162 * proto_item_append_text()
2164 /* NOTE: this function will break with the TRY_TO_FAKE_THIS_ITEM()
2165 * speed optimization.
2166 * Currently only WSP use this function so it is not that bad but try to
2167 * avoid using this one if possible.
2168 * IF you must use this function you MUST also disable the
2169 * TRY_TO_FAKE_THIS_ITEM() optimization for your dissector/function
2170 * using proto_item_append_string().
2171 * Do that by faking that the tree is visible by calling
2172 * proto_tree_set_visible(tree, TRUE) (see packet-wsp.c)
2173 * BEFORE you create the item you are later going to use
2174 * proto_item_append_string() on.
2177 proto_item_append_string(proto_item *pi, const char *str)
2180 header_field_info *hfinfo;
2181 gchar *old_str, *new_str;
2188 fi = PITEM_FINFO(pi);
2189 DISSECTOR_ASSERT(fi && "proto_tree_set_visible(tree, TRUE) should have been called previously");
2191 hfinfo = fi->hfinfo;
2192 if (hfinfo->type == FT_PROTOCOL) {
2193 /* TRY_TO_FAKE_THIS_ITEM() speed optimization: silently skip */
2196 DISSECTOR_ASSERT(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ);
2197 old_str = fvalue_get(&fi->value);
2198 new_str = ep_strdup_printf("%s%s", old_str, str);
2199 fvalue_set(&fi->value, new_str, FALSE);
2202 /* Set the FT_STRING value */
2204 proto_tree_set_string(field_info *fi, const char* value)
2207 col_custom_set_fstr(fi->hfinfo, "%s",
2208 format_text(value, strlen(value)));
2209 fvalue_set(&fi->value, (gpointer) value, FALSE);
2211 col_custom_set_fstr(fi->hfinfo, "[ Null ]");
2212 fvalue_set(&fi->value, (gpointer) "[ Null ]", FALSE);
2217 proto_tree_set_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
2222 length = tvb_ensure_length_remaining(tvb, start);
2225 string = tvb_get_ephemeral_string(tvb, start, length);
2226 proto_tree_set_string(fi, string);
2230 proto_tree_set_ebcdic_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
2235 length = tvb_ensure_length_remaining(tvb, start);
2238 string = tvb_get_ephemeral_string(tvb, start, length);
2239 EBCDIC_to_ASCII(string, length);
2240 proto_tree_set_string(fi, string);
2243 /* Add a FT_ETHER to a proto_tree */
2245 proto_tree_add_ether(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2246 const guint8* value)
2250 header_field_info *hfinfo;
2252 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2254 DISSECTOR_ASSERT(hfinfo->type == FT_ETHER);
2256 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2257 proto_tree_set_ether(new_fi, value);
2263 proto_tree_add_ether_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2264 gint start, gint length, const guint8* value,
2265 const char *format, ...)
2269 header_field_info *hfinfo;
2271 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2273 pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
2277 va_start(ap, format);
2278 proto_tree_set_representation_value(pi, format, ap);
2285 proto_tree_add_ether_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2286 const guint8* value, const char *format, ...)
2290 header_field_info *hfinfo;
2292 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2294 pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
2298 va_start(ap, format);
2299 proto_tree_set_representation(pi, format, ap);
2305 /* Set the FT_ETHER value */
2307 proto_tree_set_ether(field_info *fi, const guint8* value)
2309 col_custom_set_fstr(fi->hfinfo, "%s", bytes_to_str_punct(value, 6, ':'));
2310 fvalue_set(&fi->value, (gpointer) value, FALSE);
2314 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start)
2316 proto_tree_set_ether(fi, tvb_get_ptr(tvb, start, 6));
2319 /* Add a FT_BOOLEAN to a proto_tree */
2321 proto_tree_add_boolean(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2326 header_field_info *hfinfo;
2328 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2330 DISSECTOR_ASSERT(hfinfo->type == FT_BOOLEAN);
2332 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2333 proto_tree_set_boolean(new_fi, value);
2339 proto_tree_add_boolean_format_value(proto_tree *tree, int hfindex,
2340 tvbuff_t *tvb, gint start, gint length, guint32 value,
2341 const char *format, ...)
2345 header_field_info *hfinfo;
2347 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2349 pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
2353 va_start(ap, format);
2354 proto_tree_set_representation_value(pi, format, ap);
2361 proto_tree_add_boolean_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2362 guint32 value, const char *format, ...)
2366 header_field_info *hfinfo;
2368 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2370 pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
2374 va_start(ap, format);
2375 proto_tree_set_representation(pi, format, ap);
2381 /* Set the FT_BOOLEAN value */
2383 proto_tree_set_boolean(field_info *fi, guint32 value)
2385 proto_tree_set_uint(fi, value);
2388 /* Add a FT_FLOAT to a proto_tree */
2390 proto_tree_add_float(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_FLOAT);
2401 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2402 proto_tree_set_float(new_fi, value);
2408 proto_tree_add_float_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2409 gint start, gint length, float value, const char *format, ...)
2413 header_field_info *hfinfo;
2415 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2417 pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
2421 va_start(ap, format);
2422 proto_tree_set_representation_value(pi, format, ap);
2429 proto_tree_add_float_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2430 float value, const char *format, ...)
2434 header_field_info *hfinfo;
2436 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2438 pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
2442 va_start(ap, format);
2443 proto_tree_set_representation(pi, format, ap);
2449 /* Set the FT_FLOAT value */
2451 proto_tree_set_float(field_info *fi, float value)
2453 col_custom_set_fstr(fi->hfinfo, "%." STRINGIFY(FLT_DIG) "f",
2455 fvalue_set_floating(&fi->value, value);
2458 /* Add a FT_DOUBLE to a proto_tree */
2460 proto_tree_add_double(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2465 header_field_info *hfinfo;
2467 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2469 DISSECTOR_ASSERT(hfinfo->type == FT_DOUBLE);
2471 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2472 proto_tree_set_double(new_fi, value);
2478 proto_tree_add_double_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2479 gint start, gint length, double value, const char *format, ...)
2483 header_field_info *hfinfo;
2485 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2487 pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
2491 va_start(ap, format);
2492 proto_tree_set_representation_value(pi, format, ap);
2499 proto_tree_add_double_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2500 double value, const char *format, ...)
2504 header_field_info *hfinfo;
2506 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2508 pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
2512 va_start(ap, format);
2513 proto_tree_set_representation(pi, format, ap);
2519 /* Set the FT_DOUBLE value */
2521 proto_tree_set_double(field_info *fi, double value)
2523 col_custom_set_fstr(fi->hfinfo, "%." STRINGIFY(DBL_DIG) "g",
2525 fvalue_set_floating(&fi->value, value);
2528 /* Add FT_UINT{8,16,24,32} to a proto_tree */
2530 proto_tree_add_uint(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2533 proto_item *pi = NULL;
2535 header_field_info *hfinfo;
2537 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2539 switch(hfinfo->type) {
2545 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length,
2547 proto_tree_set_uint(new_fi, value);
2551 DISSECTOR_ASSERT_NOT_REACHED();
2558 proto_tree_add_uint_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2559 gint start, gint length, guint32 value, const char *format, ...)
2563 header_field_info *hfinfo;
2565 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2567 pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
2571 va_start(ap, format);
2572 proto_tree_set_representation_value(pi, format, ap);
2579 proto_tree_add_uint_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2580 guint32 value, const char *format, ...)
2584 header_field_info *hfinfo;
2586 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2588 pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
2592 va_start(ap, format);
2593 proto_tree_set_representation(pi, format, ap);
2599 /* Set the FT_UINT{8,16,24,32} value */
2601 proto_tree_set_uint(field_info *fi, guint32 value)
2603 header_field_info *hfinfo;
2606 hfinfo = fi->hfinfo;
2609 if (hfinfo->bitmask) {
2610 /* Mask out irrelevant portions */
2611 integer &= hfinfo->bitmask;
2614 if (hfinfo->bitshift > 0) {
2615 integer >>= hfinfo->bitshift;
2619 if (hfinfo->type == FT_BOOLEAN) {
2620 const true_false_string *tfstring = (const true_false_string *)&tfs_true_false;
2621 if (hfinfo->strings) {
2622 tfstring = (const struct true_false_string*) hfinfo->strings;
2624 col_custom_set_fstr(fi->hfinfo, "%s", integer ? tfstring->true_string : tfstring->false_string);
2625 } else if (hfinfo->strings) {
2626 if (hfinfo->display & BASE_RANGE_STRING) {
2627 col_custom_set_fstr(fi->hfinfo, "%s", rval_to_str(integer, hfinfo->strings, "%u"));
2629 col_custom_set_fstr(fi->hfinfo, "%s", val_to_str(integer, cVALS(hfinfo->strings), "%u"));
2631 } else if (IS_BASE_DUAL(hfinfo->display)) {
2632 col_custom_set_fstr(fi->hfinfo, hfinfo_uint_value_format(hfinfo), integer, integer);
2634 col_custom_set_fstr(fi->hfinfo, hfinfo_uint_value_format(hfinfo), integer);
2636 fvalue_set_uinteger(&fi->value, integer);
2639 /* Add FT_UINT64 to a proto_tree */
2641 proto_tree_add_uint64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2644 proto_item *pi = NULL;
2646 header_field_info *hfinfo;
2648 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2650 DISSECTOR_ASSERT(hfinfo->type == FT_UINT64);
2652 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2653 proto_tree_set_uint64(new_fi, value);
2659 proto_tree_add_uint64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2660 gint start, gint length, guint64 value, const char *format, ...)
2664 header_field_info *hfinfo;
2666 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2668 pi = proto_tree_add_uint64(tree, hfindex, tvb, start, length, value);
2672 va_start(ap, format);
2673 proto_tree_set_representation_value(pi, format, ap);
2680 proto_tree_add_uint64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2681 guint64 value, const char *format, ...)
2685 header_field_info *hfinfo;
2687 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2689 pi = proto_tree_add_uint64(tree, hfindex, tvb, start, length, value);
2693 va_start(ap, format);
2694 proto_tree_set_representation(pi, format, ap);
2700 /* Add FT_INT{8,16,24,32} to a proto_tree */
2702 proto_tree_add_int(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2705 proto_item *pi = NULL;
2707 header_field_info *hfinfo;
2709 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2711 switch(hfinfo->type) {
2716 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length,
2718 proto_tree_set_int(new_fi, value);
2722 DISSECTOR_ASSERT_NOT_REACHED();
2729 proto_tree_add_int_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2730 gint start, gint length, gint32 value, const char *format, ...)
2732 proto_item *pi = NULL;
2734 header_field_info *hfinfo;
2736 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2738 pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
2742 va_start(ap, format);
2743 proto_tree_set_representation_value(pi, format, ap);
2750 proto_tree_add_int_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2751 gint32 value, const char *format, ...)
2753 proto_item *pi = NULL;
2755 header_field_info *hfinfo;
2757 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2759 pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
2763 va_start(ap, format);
2764 proto_tree_set_representation(pi, format, ap);
2770 /* Set the FT_INT{8,16,24,32} value */
2772 proto_tree_set_int(field_info *fi, gint32 value)
2774 header_field_info *hfinfo;
2777 hfinfo = fi->hfinfo;
2778 integer = (guint32) value;
2780 if (hfinfo->bitmask) {
2781 /* Mask out irrelevant portions */
2782 integer &= hfinfo->bitmask;
2785 if (hfinfo->bitshift > 0) {
2786 integer >>= hfinfo->bitshift;
2790 if (hfinfo->strings) {
2791 if (hfinfo->display & BASE_RANGE_STRING) {
2792 col_custom_set_fstr(fi->hfinfo, "%s", rval_to_str(integer, hfinfo->strings, "%d"));
2794 col_custom_set_fstr(fi->hfinfo, "%s", val_to_str(integer, cVALS(hfinfo->strings), "%d"));
2796 } else if (IS_BASE_DUAL(hfinfo->display)) {
2797 col_custom_set_fstr(fi->hfinfo, hfinfo_int_value_format(hfinfo), integer, integer);
2799 col_custom_set_fstr(fi->hfinfo, hfinfo_int_value_format(hfinfo), integer);
2801 fvalue_set_sinteger(&fi->value, integer);
2804 /* Add FT_INT64 to a proto_tree */
2806 proto_tree_add_int64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2809 proto_item *pi = NULL;
2811 header_field_info *hfinfo;
2813 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2815 DISSECTOR_ASSERT(hfinfo->type == FT_INT64);
2817 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2818 proto_tree_set_uint64(new_fi, (guint64)value);
2824 proto_tree_add_int64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2825 gint start, gint length, gint64 value, const char *format, ...)
2829 header_field_info *hfinfo;
2831 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2833 pi = proto_tree_add_int64(tree, hfindex, tvb, start, length, value);
2837 va_start(ap, format);
2838 proto_tree_set_representation_value(pi, format, ap);
2845 proto_tree_add_int64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2846 gint64 value, const char *format, ...)
2850 header_field_info *hfinfo;
2852 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2854 pi = proto_tree_add_int64(tree, hfindex, tvb, start, length, value);
2858 va_start(ap, format);
2859 proto_tree_set_representation(pi, format, ap);
2865 /* Throw an exception if we exceed this many tree items. */
2866 /* XXX - This should probably be a preference */
2867 #define MAX_TREE_ITEMS (1 * 1000 * 1000)
2868 /* Add a field_info struct to the proto_tree, encapsulating it in a proto_node */
2870 proto_tree_add_node(proto_tree *tree, field_info *fi)
2872 proto_node *pnode, *tnode, *sibling;
2876 * Make sure "tree" is ready to have subtrees under it, by
2877 * checking whether it's been given an ett_ value.
2879 * "PNODE_FINFO(tnode)" may be null; that's the case for the root
2880 * node of the protocol tree. That node is not displayed,
2881 * so it doesn't need an ett_ value to remember whether it
2885 tfi = PNODE_FINFO(tnode);
2886 if (tfi != NULL && (tfi->tree_type < 0 || tfi->tree_type >= num_tree_types)) {
2887 REPORT_DISSECTOR_BUG(ep_strdup_printf("\"%s\" - \"%s\" tfi->tree_type: %u invalid (%s:%u)",
2888 fi->hfinfo->name, fi->hfinfo->abbrev, tfi->tree_type, __FILE__, __LINE__));
2889 /* XXX - is it safe to continue here? */
2892 DISSECTOR_ASSERT(tfi == NULL ||
2893 (tfi->tree_type >= 0 && tfi->tree_type < num_tree_types));
2895 PTREE_DATA(tree)->count++;
2896 if (PTREE_DATA(tree)->count > MAX_TREE_ITEMS) {
2897 /* Let the exception handler add items to the tree */
2898 PTREE_DATA(tree)->count = 0;
2899 THROW_MESSAGE(DissectorError,
2900 ep_strdup_printf("More than %d items in the tree -- possible infinite loop", MAX_TREE_ITEMS));
2903 PROTO_NODE_NEW(pnode);
2904 pnode->parent = tnode;
2905 PNODE_FINFO(pnode) = fi;
2906 pnode->tree_data = PTREE_DATA(tree);
2908 if (tnode->last_child != NULL) {
2909 sibling = tnode->last_child;
2910 DISSECTOR_ASSERT(sibling->next == NULL);
2911 sibling->next = pnode;
2913 tnode->first_child = pnode;
2914 tnode->last_child = pnode;
2916 return (proto_item*)pnode;
2920 /* Generic way to allocate field_info and add to proto_tree.
2921 * Sets *pfi to address of newly-allocated field_info struct, if pfi is
2924 proto_tree_add_pi(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2925 gint *length, field_info **pfi)
2934 fi = alloc_field_info(tree, hfindex, tvb, start, length);
2935 pi = proto_tree_add_node(tree, fi);
2937 /* If the proto_tree wants to keep a record of this finfo
2938 * for quick lookup, then record it. */
2939 ptrs = proto_lookup_or_create_interesting_hfids(tree, fi->hfinfo);
2941 g_ptr_array_add(ptrs, fi);
2943 /* Does the caller want to know the fi pointer? */
2952 static header_field_info *
2953 get_hfi_and_length(int hfindex, tvbuff_t *tvb, gint start, gint *length,
2956 header_field_info *hfinfo;
2957 gint length_remaining;
2960 * We only allow a null tvbuff if the item has a zero length,
2961 * i.e. if there's no data backing it.
2963 DISSECTOR_ASSERT(tvb != NULL || *length == 0);
2965 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2968 * XXX - in some protocols, there are 32-bit unsigned length
2969 * fields, so lengths in protocol tree and tvbuff routines
2970 * should really be unsigned. We should have, for those
2971 * field types for which "to the end of the tvbuff" makes sense,
2972 * additional routines that take no length argument and
2973 * add fields that run to the end of the tvbuff.
2975 if (*length == -1) {
2977 * For FT_NONE, FT_PROTOCOL, FT_BYTES, and FT_STRING fields,
2978 * a length of -1 means "set the length to what remains in
2981 * The assumption is either that
2983 * 1) the length of the item can only be determined
2984 * by dissection (typically true of items with
2985 * subitems, which are probably FT_NONE or
2990 * 2) if the tvbuff is "short" (either due to a short
2991 * snapshot length or due to lack of reassembly of
2992 * fragments/segments/whatever), we want to display
2993 * what's available in the field (probably FT_BYTES
2994 * or FT_STRING) and then throw an exception later
2998 * 3) the field is defined to be "what's left in the
3001 * so we set the length to what remains in the tvbuff so
3002 * that, if we throw an exception while dissecting, it
3003 * has what is probably the right value.
3005 * For FT_STRINGZ, it means "the string is null-terminated,
3006 * not null-padded; set the length to the actual length
3007 * of the string", and if the tvbuff if short, we just
3008 * throw an exception.
3010 * It's not valid for any other type of field.
3012 switch (hfinfo->type) {
3016 * We allow this to be zero-length - for
3017 * example, an ONC RPC NULL procedure has
3018 * neither arguments nor reply, so the
3019 * payload for that protocol is empty.
3021 * However, if the length is negative, the
3022 * start offset is *past* the byte past the
3023 * end of the tvbuff, so we throw an
3026 *length = tvb_length_remaining(tvb, start);
3029 * Use "tvb_ensure_bytes_exist()"
3030 * to force the appropriate exception
3033 tvb_ensure_bytes_exist(tvb, start, 0);
3035 DISSECTOR_ASSERT(*length >= 0);
3041 *length = tvb_ensure_length_remaining(tvb, start);
3042 DISSECTOR_ASSERT(*length >= 0);
3047 * Leave the length as -1, so our caller knows
3053 DISSECTOR_ASSERT_NOT_REACHED();
3055 *item_length = *length;
3057 *item_length = *length;
3058 if (hfinfo->type == FT_PROTOCOL || hfinfo->type == FT_NONE) {
3060 * These types are for interior nodes of the
3061 * tree, and don't have data associated with
3062 * them; if the length is negative (XXX - see
3063 * above) or goes past the end of the tvbuff,
3064 * cut it short at the end of the tvbuff.
3065 * That way, if this field is selected in
3066 * Wireshark, we don't highlight stuff past
3067 * the end of the data.
3069 /* XXX - what to do, if we don't have a tvb? */
3071 length_remaining = tvb_length_remaining(tvb, start);
3072 if (*item_length < 0 ||
3073 (*item_length > 0 &&
3074 (length_remaining < *item_length)))
3075 *item_length = length_remaining;
3078 if (*item_length < 0) {
3079 THROW(ReportedBoundsError);
3087 new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
3088 gint start, gint item_length)
3094 fi->hfinfo = hfinfo;
3096 fi->start+=(tvb)?TVB_RAW_OFFSET(tvb):0;
3097 fi->length = item_length;
3100 if (!PTREE_DATA(tree)->visible)
3101 FI_SET_FLAG(fi, FI_HIDDEN);
3102 fvalue_init(&fi->value, fi->hfinfo->type);
3105 /* add the data source tvbuff */
3106 fi->ds_tvb=tvb?TVB_GET_DS_TVB(tvb):NULL;
3108 fi->appendix_start = 0;
3109 fi->appendix_length = 0;
3115 alloc_field_info(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3118 header_field_info *hfinfo;
3121 hfinfo = get_hfi_and_length(hfindex, tvb, start, length, &item_length);
3122 return new_field_info(tree, hfinfo, tvb, start, item_length);
3125 /* If the protocol tree is to be visible, set the representation of a
3126 proto_tree entry with the name of the field for the item and with
3127 the value formatted with the supplied printf-style format and
3130 proto_tree_set_representation_value(proto_item *pi, const char *format, va_list ap)
3132 int ret; /*tmp return value */
3133 field_info *fi = PITEM_FINFO(pi);
3134 header_field_info *hf;
3136 DISSECTOR_ASSERT(fi);
3140 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
3141 ITEM_LABEL_NEW(fi->rep);
3142 if (hf->bitmask && (hf->type == FT_BOOLEAN || IS_FT_UINT(hf->type))) {
3146 val = fvalue_get_uinteger(&fi->value);
3147 if (hf->bitshift > 0) {
3148 val <<= hf->bitshift;
3150 decode_bitfield_value(tmpbuf, val, hf->bitmask, hfinfo_bitwidth(hf));
3151 /* put in the hf name */
3152 ret = g_snprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
3153 "%s%s: ", tmpbuf, fi->hfinfo->name);
3155 /* put in the hf name */
3156 ret = g_snprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
3157 "%s: ", fi->hfinfo->name);
3160 /* If possible, Put in the value of the string */
3161 if (ret < ITEM_LABEL_LENGTH) {
3162 ret += g_vsnprintf(fi->rep->representation + ret,
3163 ITEM_LABEL_LENGTH - ret, format, ap);
3165 if (ret >= ITEM_LABEL_LENGTH) {
3166 /* Uh oh, we don't have enough room. Tell the user
3167 * that the field is truncated.
3171 /* Argh, we cannot reuse 'ap' here. So make a copy
3172 * of what we formatted for (re)use below.
3174 oldrep = g_strdup(fi->rep->representation);
3176 g_snprintf(fi->rep->representation,
3185 /* If the protocol tree is to be visible, set the representation of a
3186 proto_tree entry with the representation formatted with the supplied
3187 printf-style format and argument list. */
3189 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap)
3191 int ret; /*tmp return value */
3192 field_info *fi = PITEM_FINFO(pi);
3194 DISSECTOR_ASSERT(fi);
3196 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
3197 ITEM_LABEL_NEW(fi->rep);
3198 ret = g_vsnprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
3200 if (ret >= ITEM_LABEL_LENGTH) {
3201 /* Uh oh, we don't have enough room. Tell the user
3202 * that the field is truncated.
3206 /* Argh, we cannot reuse 'ap' here. So make a copy
3207 * of what we formatted for (re)use below.
3209 oldrep = g_strdup(fi->rep->representation);
3211 g_snprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
3212 "[truncated] %s", oldrep);
3218 /* Set text of proto_item after having already been created. */
3220 proto_item_set_text(proto_item *pi, const char *format, ...)
3222 field_info *fi = NULL;
3229 fi = PITEM_FINFO(pi);
3234 ITEM_LABEL_FREE(fi->rep);
3237 va_start(ap, format);
3238 proto_tree_set_representation(pi, format, ap);
3242 /* Append to text of proto_item after having already been created. */
3244 proto_item_append_text(proto_item *pi, const char *format, ...)
3246 field_info *fi = NULL;
3254 fi = PITEM_FINFO(pi);
3259 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
3260 va_start(ap, format);
3263 * If we don't already have a representation,
3264 * generate the default representation.
3266 if (fi->rep == NULL) {
3267 ITEM_LABEL_NEW(fi->rep);
3268 proto_item_fill_label(fi, fi->rep->representation);
3271 curlen = strlen(fi->rep->representation);
3272 if (ITEM_LABEL_LENGTH > curlen) {
3273 g_vsnprintf(fi->rep->representation + curlen,
3274 ITEM_LABEL_LENGTH - (gulong) curlen, format, ap);
3281 proto_item_set_len(proto_item *pi, gint length)
3288 fi = PITEM_FINFO(pi);
3292 DISSECTOR_ASSERT(length >= 0);
3293 fi->length = length;
3295 if (fi->value.ftype->ftype == FT_BYTES)
3296 fi->value.value.bytes->len = length;
3300 * Sets the length of the item based on its start and on the specified
3301 * offset, which is the offset past the end of the item; as the start
3302 * in the item is relative to the beginning of the data source tvbuff,
3303 * we need to pass in a tvbuff - the end offset is relative to the beginning
3307 proto_item_set_end(proto_item *pi, tvbuff_t *tvb, gint end)
3314 fi = PITEM_FINFO(pi);
3318 end += TVB_RAW_OFFSET(tvb);
3319 DISSECTOR_ASSERT(end >= fi->start);
3320 fi->length = end - fi->start;
3324 proto_item_get_len(proto_item *pi)
3326 field_info *fi = PITEM_FINFO(pi);
3327 return fi ? fi->length : -1;
3331 /** clear flags according to the mask and set new flag values */
3332 #define FI_REPLACE_FLAGS(fi, mask, flags_in) { \
3333 (fi->flags = (fi)->flags & ~(mask)); \
3334 (fi->flags = (fi)->flags | (flags_in)); \
3338 proto_item_set_expert_flags(proto_item *pi, int group, guint severity)
3340 if(pi == NULL || PITEM_FINFO(pi) == NULL)
3343 /* only change things if severity is worse or at least equal than before */
3344 if(severity >= FI_GET_FLAG(PITEM_FINFO(pi), PI_SEVERITY_MASK)) {
3345 FI_REPLACE_FLAGS(PITEM_FINFO(pi), PI_GROUP_MASK, group);
3346 FI_REPLACE_FLAGS(PITEM_FINFO(pi), PI_SEVERITY_MASK, severity);
3355 proto_tree_create_root(void)
3359 /* Initialize the proto_node */
3360 PROTO_NODE_NEW(pnode);
3361 pnode->parent = NULL;
3362 PNODE_FINFO(pnode) = NULL;
3363 pnode->tree_data = g_new(tree_data_t, 1);
3365 /* Don't initialize the tree_data_t. Wait until we know we need it */
3366 pnode->tree_data->interesting_hfids = NULL;
3368 /* Set the default to FALSE so it's easier to
3369 * find errors; if we expect to see the protocol tree
3370 * but for some reason the default 'visible' is not
3371 * changed, then we'll find out very quickly. */
3372 pnode->tree_data->visible = FALSE;
3374 /* Make sure that we fake protocols (if possible) */
3375 pnode->tree_data->fake_protocols = TRUE;
3377 /* Keep track of the number of children */
3378 pnode->tree_data->count = 0;
3380 return (proto_tree*) pnode;
3384 /* "prime" a proto_tree with a single hfid that a dfilter
3385 * is interested in. */
3387 proto_tree_prime_hfid(proto_tree *tree _U_, gint hfid)
3389 header_field_info *hfinfo;
3391 PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
3392 /* this field is referenced by a filter so increase the refcount.
3393 also increase the refcount for the parent, i.e the protocol.
3395 hfinfo->ref_count = HF_REF_TYPE_DIRECT;
3396 /* only increase the refcount if there is a parent.
3397 if this is a protocol and not a field then parent will be -1
3398 and there is no parent to add any refcounting for.
3400 if (hfinfo->parent != -1) {
3401 header_field_info *parent_hfinfo;
3402 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
3404 /* Mark parent as indirectly referenced unless it is already directly
3405 * referenced, i.e. the user has specified the parent in a filter.
3407 if (parent_hfinfo->ref_count != HF_REF_TYPE_DIRECT)
3408 parent_hfinfo->ref_count = HF_REF_TYPE_INDIRECT;
3413 proto_item_add_subtree(proto_item *pi, gint idx) {
3419 DISSECTOR_ASSERT(idx >= 0 && idx < num_tree_types);
3421 fi = PITEM_FINFO(pi);
3423 return (proto_tree*) pi;
3425 fi->tree_type = idx;
3427 return (proto_tree*) pi;
3431 proto_item_get_subtree(proto_item *pi) {
3436 fi = PITEM_FINFO(pi);
3437 if ( (!fi) || (fi->tree_type == -1) )
3439 return (proto_tree*) pi;
3443 proto_item_get_parent(proto_item *ti) {
3450 proto_item_get_parent_nth(proto_item *ti, int gen) {
3463 proto_tree_get_parent(proto_tree *tree) {
3466 return (proto_item*) tree;
3470 proto_tree_get_root(proto_tree *tree) {
3473 while (tree->parent) {
3474 tree = tree->parent;
3480 proto_tree_move_item(proto_tree *tree, proto_item *fixed_item, proto_item *item_to_move)
3482 /* This function doesn't generate any values. It only reorganizes the prococol tree
3483 * so we can bail out immediately if it isn't visible. */
3484 if (!tree || !PTREE_DATA(tree)->visible)
3487 DISSECTOR_ASSERT(item_to_move->parent == tree);
3488 DISSECTOR_ASSERT(fixed_item->parent == tree);
3490 /*** cut item_to_move out ***/
3492 /* is item_to_move the first? */
3493 if(tree->first_child == item_to_move) {
3494 /* simply change first child to next */
3495 tree->first_child = item_to_move->next;
3497 DISSECTOR_ASSERT(tree->last_child != item_to_move);
3499 proto_item *curr_item;
3500 /* find previous and change it's next */
3501 for(curr_item = tree->first_child; curr_item != NULL; curr_item = curr_item->next) {
3502 if(curr_item->next == item_to_move) {
3507 DISSECTOR_ASSERT(curr_item);
3509 curr_item->next = item_to_move->next;
3511 /* fix last_child if required */
3512 if(tree->last_child == item_to_move) {
3513 tree->last_child = curr_item;
3517 /*** insert to_move after fixed ***/
3518 item_to_move->next = fixed_item->next;
3519 fixed_item->next = item_to_move;
3520 if(tree->last_child == fixed_item) {
3521 tree->last_child = item_to_move;
3526 proto_tree_set_appendix(proto_tree *tree, tvbuff_t *tvb, gint start, gint length)
3533 fi = PTREE_FINFO(tree);
3537 start += TVB_RAW_OFFSET(tvb);
3538 DISSECTOR_ASSERT(start >= 0);
3539 DISSECTOR_ASSERT(length >= 0);
3541 fi->appendix_start = start;
3542 fi->appendix_length = length;
3546 proto_register_protocol(const char *name, const char *short_name, const char *filter_name)
3548 protocol_t *protocol;
3549 header_field_info *hfinfo;
3551 char *existing_name;
3555 gboolean found_invalid;
3558 * Make sure there's not already a protocol with any of those
3559 * names. Crash if there is, as that's an error in the code
3560 * or an inappropriate plugin.
3561 * This situation has to be fixed to not register more than one
3562 * protocol with the same name.
3564 * This is done by reducing the number of strcmp (and alike) calls as much as possible,
3565 * as this significally slows down startup time.
3567 * Drawback: As a hash value is used to reduce insert time,
3568 * this might lead to a hash collision.
3569 * However, as we have around 500+ protocols and we're using a 32 bit int this is very,
3573 key = g_malloc (sizeof(gint));
3574 *key = wrs_str_hash(name);
3575 existing_name = g_hash_table_lookup(proto_names, key);
3576 if (existing_name != NULL) {
3577 /* g_error will terminate the program */
3578 g_error("Duplicate protocol name \"%s\"!"
3579 " This might be caused by an inappropriate plugin or a development error.", name);
3581 g_hash_table_insert(proto_names, key, (gpointer)name);
3583 existing_name = g_hash_table_lookup(proto_short_names, (gpointer)short_name);
3584 if (existing_name != NULL) {
3585 g_error("Duplicate protocol short_name \"%s\"!"
3586 " This might be caused by an inappropriate plugin or a development error.", short_name);
3588 g_hash_table_insert(proto_short_names, (gpointer)short_name, (gpointer)short_name);
3590 found_invalid = FALSE;
3591 for (i = 0; i < strlen(filter_name); i++) {
3593 if (!(islower(c) || isdigit(c) || c == '-' || c == '_' || c == '.')) {
3594 found_invalid = TRUE;
3597 if (found_invalid) {
3598 g_error("Protocol filter name \"%s\" has one or more invalid characters."
3599 " Allowed are lower characters, digits, '-', '_' and '.'."
3600 " This might be caused by an inappropriate plugin or a development error.", filter_name);
3602 existing_name = g_hash_table_lookup(proto_filter_names, (gpointer)filter_name);
3603 if (existing_name != NULL) {
3604 g_error("Duplicate protocol filter_name \"%s\"!"
3605 " This might be caused by an inappropriate plugin or a development error.", filter_name);
3607 g_hash_table_insert(proto_filter_names, (gpointer)filter_name, (gpointer)filter_name);
3609 /* Add this protocol to the list of known protocols; the list
3610 is sorted by protocol short name. */
3611 protocol = g_malloc(sizeof (protocol_t));
3612 protocol->name = name;
3613 protocol->short_name = short_name;
3614 protocol->filter_name = filter_name;
3615 protocol->fields = NULL;
3616 protocol->is_enabled = TRUE; /* protocol is enabled by default */
3617 protocol->can_toggle = TRUE;
3618 protocol->is_private = FALSE;
3619 /* list will be sorted later by name, when all protocols completed registering */
3620 protocols = g_list_prepend(protocols, protocol);
3622 /* Here we do allocate a new header_field_info struct */
3623 hfinfo = g_mem_chunk_alloc(gmc_hfinfo);
3624 hfinfo->name = name;
3625 hfinfo->abbrev = filter_name;
3626 hfinfo->type = FT_PROTOCOL;
3627 hfinfo->display = BASE_NONE;
3628 hfinfo->strings = protocol;
3629 hfinfo->bitmask = 0;
3630 hfinfo->bitshift = 0;
3631 hfinfo->ref_count = HF_REF_TYPE_NONE;
3632 hfinfo->blurb = NULL;
3633 hfinfo->parent = -1; /* this field differentiates protos and fields */
3635 proto_id = proto_register_field_init(hfinfo, hfinfo->parent);
3636 protocol->proto_id = proto_id;
3641 proto_mark_private(int proto_id)
3643 protocol_t *protocol = find_protocol_by_id(proto_id);
3645 protocol->is_private = TRUE;
3649 proto_is_private(int proto_id)
3651 protocol_t *protocol = find_protocol_by_id(proto_id);
3653 return protocol->is_private;
3659 * Routines to use to iterate over the protocols.
3660 * The argument passed to the iterator routines is an opaque cookie to
3661 * their callers; it's the GList pointer for the current element in
3663 * The ID of the protocol is returned, or -1 if there is no protocol.
3666 proto_get_first_protocol(void **cookie)
3668 protocol_t *protocol;
3670 if (protocols == NULL)
3672 *cookie = protocols;
3673 protocol = protocols->data;
3674 return protocol->proto_id;
3678 proto_get_next_protocol(void **cookie)
3680 GList *list_item = *cookie;
3681 protocol_t *protocol;
3683 list_item = g_list_next(list_item);
3684 if (list_item == NULL)
3686 *cookie = list_item;
3687 protocol = list_item->data;
3688 return protocol->proto_id;
3692 proto_get_first_protocol_field(int proto_id, void **cookie)
3694 protocol_t *protocol = find_protocol_by_id(proto_id);
3695 hf_register_info *ptr;
3697 if ((protocol == NULL) || (protocol->fields == NULL))
3700 *cookie = protocol->fields;
3701 ptr = protocol->fields->data;
3702 return &ptr->hfinfo;
3706 proto_get_next_protocol_field(void **cookie)
3708 GList *list_item = *cookie;
3709 hf_register_info *ptr;
3711 list_item = g_list_next(list_item);
3712 if (list_item == NULL)
3715 *cookie = list_item;
3716 ptr = list_item->data;
3717 return &ptr->hfinfo;
3721 find_protocol_by_id(int proto_id)
3723 header_field_info *hfinfo;
3728 PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
3729 DISSECTOR_ASSERT(hfinfo->type==FT_PROTOCOL);
3730 return (protocol_t *)hfinfo->strings;
3733 static gint compare_filter_name(gconstpointer proto_arg,
3734 gconstpointer filter_name)
3736 const protocol_t *protocol = proto_arg;
3737 const gchar* f_name = filter_name;
3739 return (strcmp(protocol->filter_name, f_name));
3743 proto_get_id(protocol_t *protocol)
3745 return protocol->proto_id;
3748 int proto_get_id_by_filter_name(const gchar* filter_name)
3751 protocol_t *protocol;
3753 list_entry = g_list_find_custom(protocols, filter_name,
3754 compare_filter_name);
3756 if (list_entry == NULL)
3758 protocol = list_entry->data;
3759 return protocol->proto_id;
3763 proto_get_protocol_name(int proto_id)
3765 protocol_t *protocol;
3767 protocol = find_protocol_by_id(proto_id);
3768 return protocol->name;
3772 proto_get_protocol_short_name(protocol_t *protocol)
3774 if (protocol == NULL)
3776 return protocol->short_name;
3780 proto_get_protocol_long_name(protocol_t *protocol)
3782 if (protocol == NULL)
3784 return protocol->name;
3788 proto_get_protocol_filter_name(int proto_id)
3790 protocol_t *protocol;
3792 protocol = find_protocol_by_id(proto_id);
3793 if (protocol == NULL)
3795 return protocol->filter_name;
3799 proto_is_protocol_enabled(protocol_t *protocol)
3801 return protocol->is_enabled;
3805 proto_can_toggle_protocol(int proto_id)
3807 protocol_t *protocol;
3809 protocol = find_protocol_by_id(proto_id);
3810 return protocol->can_toggle;
3814 proto_set_decoding(int proto_id, gboolean enabled)
3816 protocol_t *protocol;
3818 protocol = find_protocol_by_id(proto_id);
3819 DISSECTOR_ASSERT(protocol->can_toggle);
3820 protocol->is_enabled = enabled;
3824 proto_enable_all(void)
3826 protocol_t *protocol;
3827 GList *list_item = protocols;
3829 if (protocols == NULL)
3833 protocol = list_item->data;
3834 if (protocol->can_toggle)
3835 protocol->is_enabled = TRUE;
3836 list_item = g_list_next(list_item);
3841 proto_set_cant_toggle(int proto_id)
3843 protocol_t *protocol;
3845 protocol = find_protocol_by_id(proto_id);
3846 protocol->can_toggle = FALSE;
3849 /* for use with static arrays only, since we don't allocate our own copies
3850 of the header_field_info struct contained within the hf_register_info struct */
3852 proto_register_field_array(int parent, hf_register_info *hf, int num_records)
3855 hf_register_info *ptr = hf;
3858 proto = find_protocol_by_id(parent);
3859 for (i = 0; i < num_records; i++, ptr++) {
3861 * Make sure we haven't registered this yet.
3862 * Most fields have variables associated with them
3863 * that are initialized to -1; some have array elements,
3864 * or possibly uninitialized variables, so we also allow
3865 * 0 (which is unlikely to be the field ID we get back
3866 * from "proto_register_field_init()").
3868 if (*ptr->p_id != -1 && *ptr->p_id != 0) {
3870 "Duplicate field detected in call to proto_register_field_array: %s is already registered\n",
3871 ptr->hfinfo.abbrev);
3875 if (proto != NULL) {
3876 if (proto->fields == NULL) {
3877 proto->fields = g_list_append(NULL, ptr);
3878 proto->last_field = proto->fields;
3881 g_list_append(proto->last_field, ptr)->next;
3884 field_id = proto_register_field_init(&ptr->hfinfo, parent);
3885 *ptr->p_id = field_id;
3889 /* chars allowed in field abbrev */
3891 const guchar fld_abbrev_chars[256] = {
3892 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00-0x0F */
3893 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10-0x1F */
3894 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, /* 0x20-0x2F '-', '.' */
3895 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 0x30-0x3F '0'-'9' */
3896 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x40-0x4F 'A'-'O' */
3897 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 0x50-0x5F 'P'-'Z', '_' */
3898 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x60-0x6F 'a'-'o' */
3899 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 0x70-0x7F 'p'-'z' */
3900 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80-0x8F */
3901 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90-0x9F */
3902 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xA0-0xAF */
3903 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xB0-0xBF */
3904 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xC0-0xCF */
3905 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xD0-0xDF */
3906 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xE0-0xEF */
3907 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xF0-0xFF */
3910 /* temporary function containing assert part for easier profiling */
3911 static void tmp_fld_check_assert(header_field_info *hfinfo) {
3912 /* The field must have a name (with length > 0) */
3913 DISSECTOR_ASSERT(hfinfo->name && hfinfo->name[0]);
3915 /* fields with an empty string for an abbreviation aren't filterable */
3916 DISSECTOR_ASSERT(hfinfo->abbrev);
3918 /* These types of fields are allowed to have value_strings, true_false_strings or a protocol_t struct*/
3919 DISSECTOR_ASSERT((hfinfo->strings == NULL) || (
3920 (hfinfo->type == FT_UINT8) ||
3921 (hfinfo->type == FT_UINT16) ||
3922 (hfinfo->type == FT_UINT24) ||
3923 (hfinfo->type == FT_UINT32) ||
3924 (hfinfo->type == FT_INT8) ||
3925 (hfinfo->type == FT_INT16) ||
3926 (hfinfo->type == FT_INT24) ||
3927 (hfinfo->type == FT_INT32) ||
3928 (hfinfo->type == FT_BOOLEAN) ||
3929 (hfinfo->type == FT_PROTOCOL) ||
3930 (hfinfo->type == FT_FRAMENUM) ));
3932 switch (hfinfo->type) {
3939 /* Hexadecimal and octal are, in printf() and everywhere else,
3940 * unsigned so don't allow dissectors to register a signed
3941 * field to be displayed unsigned. (Else how would we
3942 * display values negative values?)
3944 * If you want to take out this check, be sure to fix
3945 * hfinfo_numeric_format() so that it does not assert out
3946 * when trying to construct a hexadecimal representation of
3949 DISSECTOR_ASSERT(hfinfo->display != BASE_HEX &&
3950 hfinfo->display != BASE_HEX_DEC &&
3951 hfinfo->display != BASE_DEC_HEX &&
3952 hfinfo->display != BASE_OCT);
3958 if (hfinfo->strings == NULL) {
3959 /* Require integral types (other than frame number, which is
3960 always displayed in decimal) to have a number base */
3961 DISSECTOR_ASSERT(hfinfo->display != BASE_NONE);
3966 DISSECTOR_ASSERT(hfinfo->display != BASE_NONE);
3973 /* Don't allow bitfields or value strings for frame numbers and strings */
3974 DISSECTOR_ASSERT(hfinfo->bitmask == 0);
3975 DISSECTOR_ASSERT(hfinfo->strings == NULL);
3984 proto_register_field_init(header_field_info *hfinfo, int parent)
3987 tmp_fld_check_assert(hfinfo);
3989 /* if this is a bitfield, compute bitshift */
3990 if (hfinfo->bitmask) {
3991 hfinfo->bitshift = wrs_count_bitshift(hfinfo->bitmask);
3994 hfinfo->parent = parent;
3995 hfinfo->same_name_next = NULL;
3996 hfinfo->same_name_prev = NULL;
3998 /* if we always add and never delete, then id == len - 1 is correct */
3999 if(gpa_hfinfo.len>=gpa_hfinfo.allocated_len){
4000 if(!gpa_hfinfo.hfi){
4001 gpa_hfinfo.allocated_len=1000;
4002 gpa_hfinfo.hfi=g_malloc(sizeof(header_field_info *)*1000);
4004 gpa_hfinfo.allocated_len+=1000;
4005 gpa_hfinfo.hfi=g_realloc(gpa_hfinfo.hfi, sizeof(header_field_info *)*gpa_hfinfo.allocated_len);
4008 gpa_hfinfo.hfi[gpa_hfinfo.len]=hfinfo;
4010 hfinfo->id = gpa_hfinfo.len - 1;
4012 /* if we have real names, enter this field in the name tree */
4013 if ((hfinfo->name[0] != 0) && (hfinfo->abbrev[0] != 0 )) {
4015 header_field_info *same_name_next_hfinfo;
4018 /* Check that the filter name (abbreviation) is legal;
4019 * it must contain only alphanumerics, '-', "_", and ".". */
4020 c = wrs_check_charset(fld_abbrev_chars, hfinfo->abbrev);
4022 fprintf(stderr, "OOPS: '%c' in '%s'\n", c, hfinfo->abbrev);
4023 DISSECTOR_ASSERT(!c);
4026 /* We allow multiple hfinfo's to be registered under the same
4027 * abbreviation. This was done for X.25, as, depending
4028 * on whether it's modulo-8 or modulo-128 operation,
4029 * some bitfield fields may be in different bits of
4030 * a byte, and we want to be able to refer to that field
4031 * with one name regardless of whether the packets
4032 * are modulo-8 or modulo-128 packets. */
4034 same_name_hfinfo = NULL;
4036 g_tree_insert(gpa_name_tree, (gpointer) (hfinfo->abbrev), hfinfo);
4037 /* GLIB 2.x - if it is already present
4038 * the previous hfinfo with the same name is saved
4039 * to same_name_hfinfo by value destroy callback */
4040 if (same_name_hfinfo) {
4041 /* There's already a field with this name.
4042 * Put it after that field in the list of
4043 * fields with this name, then allow the code
4044 * after this if{} block to replace the old
4045 * hfinfo with the new hfinfo in the GTree. Thus,
4046 * we end up with a linked-list of same-named hfinfo's,
4047 * with the root of the list being the hfinfo in the GTree */
4048 same_name_next_hfinfo =
4049 same_name_hfinfo->same_name_next;
4051 hfinfo->same_name_next = same_name_next_hfinfo;
4052 if (same_name_next_hfinfo)
4053 same_name_next_hfinfo->same_name_prev = hfinfo;
4055 same_name_hfinfo->same_name_next = hfinfo;
4056 hfinfo->same_name_prev = same_name_hfinfo;
4064 proto_register_subtree_array(gint *const *indices, int num_indices)
4067 gint *const *ptr = indices;
4070 * If we've already allocated the array of tree types, expand
4071 * it; this lets plugins such as mate add tree types after
4072 * the initial startup. (If we haven't already allocated it,
4073 * we don't allocate it; on the first pass, we just assign
4074 * ett values and keep track of how many we've assigned, and
4075 * when we're finished registering all dissectors we allocate
4076 * the array, so that we do only one allocation rather than
4077 * wasting CPU time and memory by growing the array for each
4078 * dissector that registers ett values.)
4080 if (tree_is_expanded != NULL) {
4082 g_realloc(tree_is_expanded,
4083 (num_tree_types+num_indices)*sizeof (gboolean));
4084 memset(tree_is_expanded + num_tree_types, 0,
4085 num_indices*sizeof (gboolean));
4089 * Assign "num_indices" subtree numbers starting at "num_tree_types",
4090 * returning the indices through the pointers in the array whose
4091 * first element is pointed to by "indices", and update
4092 * "num_tree_types" appropriately.
4094 for (i = 0; i < num_indices; i++, ptr++, num_tree_types++) {
4096 /* g_error will terminate the program */
4097 g_error("register_subtree_array: subtree item type (ett_...) not -1 !"
4098 " This is a development error:"
4099 " Either the subtree item type has already been assigned or"
4100 " was not initialized to -1.");
4102 **ptr = num_tree_types;
4107 proto_item_fill_label(field_info *fi, gchar *label_str)
4109 header_field_info *hfinfo = fi->hfinfo;
4115 guint32 n_addr; /* network-order IPv4 address */
4117 int ret; /*tmp return value */
4122 /* XXX: Check validity of hfinfo->type */
4126 switch(hfinfo->type) {
4129 g_strlcpy(label_str, hfinfo->name, ITEM_LABEL_LENGTH);
4133 fill_label_boolean(fi, label_str);
4138 bytes = fvalue_get(&fi->value);
4140 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4141 "%s: %s", hfinfo->name,
4142 bytes_to_str(bytes, fvalue_length(&fi->value)));
4143 if (ret >= ITEM_LABEL_LENGTH) {
4144 /* Uh oh, we don't have enough room. Tell the
4145 * user that the field is truncated.
4147 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4148 "%s [truncated]: %s",
4150 bytes_to_str(bytes, fvalue_length(&fi->value)));
4154 g_snprintf(label_str, ITEM_LABEL_LENGTH, "%s: <MISSING>", hfinfo->name);
4158 /* Four types of integers to take care of:
4159 * Bitfield, with val_string
4160 * Bitfield, w/o val_string
4161 * Non-bitfield, with val_string
4162 * Non-bitfield, w/o val_string
4168 if (hfinfo->bitmask) {
4169 fill_label_bitfield(fi, label_str);
4171 fill_label_uint(fi, label_str);
4176 fill_label_uint(fi, label_str);
4180 fill_label_uint64(fi, label_str);
4187 DISSECTOR_ASSERT(!hfinfo->bitmask);
4188 fill_label_int(fi, label_str);
4192 fill_label_int64(fi, label_str);
4196 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4197 "%s: %." STRINGIFY(FLT_DIG) "f",
4198 hfinfo->name, fvalue_get_floating(&fi->value));
4202 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4203 "%s: %." STRINGIFY(DBL_DIG) "g",
4204 hfinfo->name, fvalue_get_floating(&fi->value));
4207 case FT_ABSOLUTE_TIME:
4208 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4209 "%s: %s", hfinfo->name,
4210 abs_time_to_str(fvalue_get(&fi->value)));
4213 case FT_RELATIVE_TIME:
4214 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4215 "%s: %s seconds", hfinfo->name,
4216 rel_time_to_secs_str(fvalue_get(&fi->value)));
4220 integer = fvalue_get_uinteger(&fi->value);
4221 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4222 "%s: %s (0x%08X)", hfinfo->name,
4223 get_ipxnet_name(integer), integer);
4227 bytes = fvalue_get(&fi->value);
4228 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4229 "%s: %s (%s)", hfinfo->name,
4230 get_ether_name(bytes),
4231 ether_to_str(bytes));
4235 ipv4 = fvalue_get(&fi->value);
4236 n_addr = ipv4_get_net_order_addr(ipv4);
4237 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4238 "%s: %s (%s)", hfinfo->name,
4239 get_hostname(n_addr),
4240 ip_to_str((guint8*)&n_addr));
4244 bytes = fvalue_get(&fi->value);
4245 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4246 "%s: %s (%s)", hfinfo->name,
4247 get_hostname6((struct e_in6_addr *)bytes),
4248 ip6_to_str((struct e_in6_addr*)bytes));
4252 guid = fvalue_get(&fi->value);
4253 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4254 "%s: %s", hfinfo->name,
4259 bytes = fvalue_get(&fi->value);
4260 name = oid_resolved_from_encoded(bytes, fvalue_length(&fi->value));
4262 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4263 "%s: %s (%s)", hfinfo->name,
4264 oid_encoded2string(bytes, fvalue_length(&fi->value)), name);
4266 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4267 "%s: %s", hfinfo->name,
4268 oid_encoded2string(bytes, fvalue_length(&fi->value)));
4275 case FT_UINT_STRING:
4276 bytes = fvalue_get(&fi->value);
4277 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4278 "%s: %s", hfinfo->name,
4279 format_text(bytes, strlen(bytes)));
4280 if (ret >= ITEM_LABEL_LENGTH) {
4281 /* Uh oh, we don't have enough room. Tell the
4282 * user that the field is truncated.
4284 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4285 "%s [truncated]: %s",
4287 format_text(bytes, strlen(bytes)));
4292 g_error("hfinfo->type %d (%s) not handled\n",
4294 ftype_name(hfinfo->type));
4295 DISSECTOR_ASSERT_NOT_REACHED();
4301 fill_label_boolean(field_info *fi, gchar *label_str)
4303 char *p = label_str;
4304 int bitfield_byte_length = 0, bitwidth;
4305 guint32 unshifted_value;
4308 header_field_info *hfinfo = fi->hfinfo;
4309 const true_false_string *tfstring = (const true_false_string *)&tfs_true_false;
4311 if (hfinfo->strings) {
4312 tfstring = (const struct true_false_string*) hfinfo->strings;
4315 value = fvalue_get_uinteger(&fi->value);
4316 if (hfinfo->bitmask) {
4317 /* Figure out the bit width */
4318 bitwidth = hfinfo_bitwidth(hfinfo);
4321 unshifted_value = value;
4322 if (hfinfo->bitshift > 0) {
4323 unshifted_value <<= hfinfo->bitshift;
4326 /* Create the bitfield first */
4327 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
4328 bitfield_byte_length = (int) (p - label_str);
4331 /* Fill in the textual info */
4332 g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
4333 "%s: %s", hfinfo->name,
4334 value ? tfstring->true_string : tfstring->false_string);
4337 /* Fills data for bitfield ints with val_strings */
4339 fill_label_bitfield(field_info *fi, gchar *label_str)
4341 const char *format = NULL;
4343 int bitfield_byte_length, bitwidth;
4344 guint32 unshifted_value;
4347 header_field_info *hfinfo = fi->hfinfo;
4349 /* Figure out the bit width */
4350 bitwidth = hfinfo_bitwidth(hfinfo);
4353 unshifted_value = fvalue_get_uinteger(&fi->value);
4354 value = unshifted_value;
4355 if (hfinfo->bitshift > 0) {
4356 unshifted_value <<= hfinfo->bitshift;
4359 /* Create the bitfield first */
4360 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
4361 bitfield_byte_length = (int) (p - label_str);
4363 /* Fill in the textual info using stored (shifted) value */
4364 if (hfinfo->display == BASE_CUSTOM) {
4365 gchar tmp[ITEM_LABEL_LENGTH];
4366 custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hfinfo->strings;
4368 DISSECTOR_ASSERT(fmtfunc);
4369 fmtfunc(tmp, value);
4370 g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
4371 "%s: %s", hfinfo->name, tmp);
4373 else if (hfinfo->strings) {
4374 format = hfinfo_uint_vals_format(hfinfo);
4375 if (hfinfo->display & BASE_RANGE_STRING) {
4376 g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
4377 format, hfinfo->name,
4378 rval_to_str(value, hfinfo->strings, "Unknown"), value);
4380 g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
4381 format, hfinfo->name,
4382 val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
4386 format = hfinfo_uint_format(hfinfo);
4387 if (IS_BASE_DUAL(hfinfo->display)) {
4388 g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
4389 format, hfinfo->name, value, value);
4391 g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
4392 format, hfinfo->name, value);
4398 fill_label_uint(field_info *fi, gchar *label_str)
4400 const char *format = NULL;
4401 header_field_info *hfinfo = fi->hfinfo;
4404 value = fvalue_get_uinteger(&fi->value);
4406 /* Fill in the textual info */
4407 if (hfinfo->display == BASE_CUSTOM) {
4408 gchar tmp[ITEM_LABEL_LENGTH];
4409 custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hfinfo->strings;
4411 DISSECTOR_ASSERT(fmtfunc);
4412 fmtfunc(tmp, value);
4413 g_snprintf(label_str, ITEM_LABEL_LENGTH, "%s: %s", hfinfo->name, tmp);
4415 else if (hfinfo->strings) {
4416 format = hfinfo_uint_vals_format(hfinfo);
4417 if (hfinfo->display & BASE_RANGE_STRING) {
4418 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4419 format, hfinfo->name,
4420 rval_to_str(value, hfinfo->strings, "Unknown"), value);
4422 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4423 format, hfinfo->name,
4424 val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
4428 format = hfinfo_uint_format(hfinfo);
4429 if (IS_BASE_DUAL(hfinfo->display)) {
4430 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4431 format, hfinfo->name, value, value);
4433 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4434 format, hfinfo->name, value);
4440 fill_label_uint64(field_info *fi, gchar *label_str)
4442 const char *format = NULL;
4443 header_field_info *hfinfo = fi->hfinfo;
4446 /* Pick the proper format string */
4447 format = hfinfo_uint64_format(hfinfo);
4448 value = fvalue_get_integer64(&fi->value);
4450 /* Fill in the textual info */
4451 if (IS_BASE_DUAL(hfinfo->display)) {
4452 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4453 format, hfinfo->name, value, value);
4455 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4456 format, hfinfo->name, value);
4461 fill_label_int(field_info *fi, gchar *label_str)
4463 const char *format = NULL;
4464 header_field_info *hfinfo = fi->hfinfo;
4467 value = fvalue_get_sinteger(&fi->value);
4469 /* Fill in the textual info */
4470 if (hfinfo->display == BASE_CUSTOM) {
4471 gchar tmp[ITEM_LABEL_LENGTH];
4472 custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hfinfo->strings;
4474 DISSECTOR_ASSERT(fmtfunc);
4475 fmtfunc(tmp, value);
4476 g_snprintf(label_str, ITEM_LABEL_LENGTH, "%s: %s", hfinfo->name, tmp);
4478 else if (hfinfo->strings) {
4479 format = hfinfo_int_vals_format(hfinfo);
4480 if (hfinfo->display & BASE_RANGE_STRING) {
4481 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4482 format, hfinfo->name,
4483 rval_to_str(value, hfinfo->strings, "Unknown"), value);
4485 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4486 format, hfinfo->name,
4487 val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
4491 format = hfinfo_int_format(hfinfo);
4492 if (IS_BASE_DUAL(hfinfo->display)) {
4493 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4494 format, hfinfo->name, value, value);
4496 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4497 format, hfinfo->name, value);
4503 fill_label_int64(field_info *fi, gchar *label_str)
4505 const char *format = NULL;
4506 header_field_info *hfinfo = fi->hfinfo;
4509 /* Pick the proper format string */
4510 format = hfinfo_int64_format(hfinfo);
4511 value = fvalue_get_integer64(&fi->value);
4513 /* Fill in the textual info */
4514 if (IS_BASE_DUAL(hfinfo->display)) {
4515 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4516 format, hfinfo->name, value, value);
4518 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4519 format, hfinfo->name, value);
4524 hfinfo_bitwidth(header_field_info *hfinfo)
4528 if (!hfinfo->bitmask) {
4532 switch(hfinfo->type) {
4550 bitwidth = hfinfo->display; /* hacky? :) */
4553 DISSECTOR_ASSERT_NOT_REACHED();
4560 hfinfo_uint_vals_format(header_field_info *hfinfo)
4562 const char *format = NULL;
4564 /* bit operation to reset the potential BASE_RANGE_STRING (or others in
4566 switch(hfinfo->display & BASE_STRUCTURE_RESET) {
4572 format = "%s: %s (%u)";
4574 case BASE_OCT: /* I'm lazy */
4575 format = "%s: %s (%o)";
4579 switch(hfinfo->type) {
4581 format = "%s: %s (0x%02x)";
4584 format = "%s: %s (0x%04x)";
4587 format = "%s: %s (0x%06x)";
4590 format = "%s: %s (0x%08x)";
4593 DISSECTOR_ASSERT_NOT_REACHED();
4598 DISSECTOR_ASSERT_NOT_REACHED();
4605 hfinfo_uint_format(header_field_info *hfinfo)
4607 const char *format = NULL;
4609 /* Pick the proper format string */
4610 if (hfinfo->type == FT_FRAMENUM) {
4612 * Frame numbers are always displayed in decimal.
4616 switch(hfinfo->display) {
4621 switch(hfinfo->type) {
4623 format = "%s: %u (0x%02x)";
4626 format = "%s: %u (0x%04x)";
4629 format = "%s: %u (0x%06x)";
4632 format = "%s: %u (0x%08x)";
4635 DISSECTOR_ASSERT_NOT_REACHED();
4639 case BASE_OCT: /* I'm lazy */
4643 switch(hfinfo->type) {
4645 format = "%s: 0x%02x";
4648 format = "%s: 0x%04x";
4651 format = "%s: 0x%06x";
4654 format = "%s: 0x%08x";
4657 DISSECTOR_ASSERT_NOT_REACHED();
4662 switch(hfinfo->type) {
4664 format = "%s: 0x%02x (%u)";
4667 format = "%s: 0x%04x (%u)";
4670 format = "%s: 0x%06x (%u)";
4673 format = "%s: 0x%08x (%u)";
4676 DISSECTOR_ASSERT_NOT_REACHED();
4681 DISSECTOR_ASSERT_NOT_REACHED();
4689 hfinfo_uint_value_format(header_field_info *hfinfo)
4691 const char *format = NULL;
4693 /* Pick the proper format string */
4694 if (hfinfo->type == FT_FRAMENUM) {
4696 * Frame numbers are always displayed in decimal.
4700 switch(hfinfo->display) {
4705 switch(hfinfo->type) {
4707 format = "%u (0x%02x)";
4710 format = "%u (0x%04x)";
4713 format = "%u (0x%06x)";
4716 format = "%u (0x%08x)";
4719 DISSECTOR_ASSERT_NOT_REACHED();
4727 switch(hfinfo->type) {
4741 DISSECTOR_ASSERT_NOT_REACHED();
4746 switch(hfinfo->type) {
4748 format = "0x%02x (%u)";
4751 format = "0x%04x (%u)";
4754 format = "0x%06x (%u)";
4757 format = "0x%08x (%u)";
4760 DISSECTOR_ASSERT_NOT_REACHED();
4765 DISSECTOR_ASSERT_NOT_REACHED();
4773 hfinfo_int_vals_format(header_field_info *hfinfo)
4775 const char *format = NULL;
4777 /* bit operation to reset the potential BASE_RANGE_STRING (or others in
4779 switch(hfinfo->display & BASE_STRUCTURE_RESET) {
4785 format = "%s: %s (%d)";
4787 case BASE_OCT: /* I'm lazy */
4788 format = "%s: %s (%o)";
4792 switch(hfinfo->type) {
4794 format = "%s: %s (0x%02x)";
4797 format = "%s: %s (0x%04x)";
4800 format = "%s: %s (0x%06x)";
4803 format = "%s: %s (0x%08x)";
4806 DISSECTOR_ASSERT_NOT_REACHED();
4811 DISSECTOR_ASSERT_NOT_REACHED();
4818 hfinfo_uint64_format(header_field_info *hfinfo)
4820 const char *format = NULL;
4822 /* Pick the proper format string */
4823 switch(hfinfo->display) {
4825 format = "%s: %" G_GINT64_MODIFIER "u";
4828 format = "%s: %" G_GINT64_MODIFIER "u (%" G_GINT64_MODIFIER "x)";
4830 case BASE_OCT: /* I'm lazy */
4831 format = "%s: %" G_GINT64_MODIFIER "o";
4834 format = "%s: 0x%016" G_GINT64_MODIFIER "x";
4837 format = "%s: 0x%016" G_GINT64_MODIFIER "x (%" G_GINT64_MODIFIER "u)";
4840 DISSECTOR_ASSERT_NOT_REACHED();
4847 hfinfo_int_format(header_field_info *hfinfo)
4849 const char *format = NULL;
4851 /* Pick the proper format string */
4852 switch(hfinfo->display) {
4857 switch(hfinfo->type) {
4859 format = "%s: %d (0x%02x)";
4862 format = "%s: %d (0x%04x)";
4865 format = "%s: %d (0x%06x)";
4868 format = "%s: %d (0x%08x)";
4871 DISSECTOR_ASSERT_NOT_REACHED();
4875 case BASE_OCT: /* I'm lazy */
4879 switch(hfinfo->type) {
4881 format = "%s: 0x%02x";
4884 format = "%s: 0x%04x";
4887 format = "%s: 0x%06x";
4890 format = "%s: 0x%08x";
4893 DISSECTOR_ASSERT_NOT_REACHED();
4898 switch(hfinfo->type) {
4900 format = "%s: 0x%02x (%d)";
4903 format = "%s: 0x%04x (%d)";
4906 format = "%s: 0x%06x (%d)";
4909 format = "%s: 0x%08x (%d)";
4912 DISSECTOR_ASSERT_NOT_REACHED();
4917 DISSECTOR_ASSERT_NOT_REACHED();
4924 hfinfo_int_value_format(header_field_info *hfinfo)
4926 const char *format = NULL;
4928 /* Pick the proper format string */
4929 switch(hfinfo->display) {
4934 switch(hfinfo->type) {
4936 format = "%d (0x%02x)";
4939 format = "%d (0x%04x)";
4942 format = "%d (0x%06x)";
4945 format = "%d (0x%08x)";
4948 DISSECTOR_ASSERT_NOT_REACHED();
4956 switch(hfinfo->type) {
4970 DISSECTOR_ASSERT_NOT_REACHED();
4975 switch(hfinfo->type) {
4977 format = "0x%02x (%d)";
4980 format = "0x%04x (%d)";
4983 format = "0x%06x (%d)";
4986 format = "0x%08x (%d)";
4989 DISSECTOR_ASSERT_NOT_REACHED();
4994 DISSECTOR_ASSERT_NOT_REACHED();
5001 hfinfo_int64_format(header_field_info *hfinfo)
5003 const char *format = NULL;
5005 /* Pick the proper format string */
5006 switch(hfinfo->display) {
5008 format = "%s: %" G_GINT64_MODIFIER "d";
5011 format = "%s: %" G_GINT64_MODIFIER "d (%" G_GINT64_MODIFIER "x)";
5013 case BASE_OCT: /* I'm lazy */
5014 format = "%s: %" G_GINT64_MODIFIER "o";
5017 format = "%s: 0x%016" G_GINT64_MODIFIER "x";
5020 format = "%s: 0x%016" G_GINT64_MODIFIER "x (%" G_GINT64_MODIFIER "d)";
5023 DISSECTOR_ASSERT_NOT_REACHED();
5032 proto_registrar_n(void)
5034 return gpa_hfinfo.len;
5038 proto_registrar_get_name(int n)
5040 header_field_info *hfinfo;
5042 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
5043 return hfinfo->name;
5047 proto_registrar_get_abbrev(int n)
5049 header_field_info *hfinfo;
5051 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
5052 return hfinfo->abbrev;
5056 proto_registrar_get_ftype(int n)
5058 header_field_info *hfinfo;
5060 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
5061 return hfinfo->type;
5065 proto_registrar_get_parent(int n)
5067 header_field_info *hfinfo;
5069 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
5070 return hfinfo->parent;
5074 proto_registrar_is_protocol(int n)
5076 header_field_info *hfinfo;
5078 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
5079 return (hfinfo->parent == -1 ? TRUE : FALSE);
5082 /* Returns length of field in packet (not necessarily the length
5083 * in our internal representation, as in the case of IPv4).
5084 * 0 means undeterminable at time of registration
5085 * -1 means the field is not registered. */
5087 proto_registrar_get_length(int n)
5089 header_field_info *hfinfo;
5091 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
5092 return ftype_length(hfinfo->type);
5097 /* Looks for a protocol or a field in a proto_tree. Returns TRUE if
5098 * it exists anywhere, or FALSE if it exists nowhere. */
5100 proto_check_for_protocol_or_field(proto_tree* tree, int id)
5102 GPtrArray *ptrs = proto_get_finfo_ptr_array(tree, id);
5107 else if (g_ptr_array_len(ptrs) > 0) {
5115 /* Return GPtrArray* of field_info pointers for all hfindex that appear in tree.
5116 * This only works if the hfindex was "primed" before the dissection
5117 * took place, as we just pass back the already-created GPtrArray*.
5118 * The caller should *not* free the GPtrArray*; proto_tree_free_node()
5121 proto_get_finfo_ptr_array(proto_tree *tree, int id)
5123 if (PTREE_DATA(tree)->interesting_hfids != NULL)
5124 return g_hash_table_lookup(PTREE_DATA(tree)->interesting_hfids,
5125 GINT_TO_POINTER(id));
5131 proto_tracking_interesting_fields(proto_tree *tree)
5133 return (PTREE_DATA(tree)->interesting_hfids != NULL);
5136 /* Helper struct for proto_find_info() and proto_all_finfos() */
5142 /* Helper function for proto_find_info() */
5144 find_finfo(proto_node *node, gpointer data)
5146 field_info *fi = PNODE_FINFO(node);
5147 if (fi && fi->hfinfo) {
5148 if (fi->hfinfo->id == ((ffdata_t*)data)->id) {
5149 g_ptr_array_add(((ffdata_t*)data)->array, fi);
5153 /* Don't stop traversing. */
5157 /* Return GPtrArray* of field_info pointers for all hfindex that appear in a tree.
5158 * This works on any proto_tree, primed or unprimed, but actually searches
5159 * the tree, so it is slower than using proto_get_finfo_ptr_array on a primed tree.
5160 * The caller does need to free the returned GPtrArray with
5161 * g_ptr_array_free(<array>, FALSE).
5164 proto_find_finfo(proto_tree *tree, int id)
5168 ffdata.array = g_ptr_array_new();
5171 proto_tree_traverse_pre_order(tree, find_finfo, &ffdata);
5173 return ffdata.array;
5176 /* Helper function for proto_all_finfos() */
5178 every_finfo(proto_node *node, gpointer data)
5180 field_info *fi = PNODE_FINFO(node);
5181 if (fi && fi->hfinfo) {
5182 g_ptr_array_add(((ffdata_t*)data)->array, fi);
5185 /* Don't stop traversing. */
5189 /* Return GPtrArray* of field_info pointers containing all hfindexes that appear in a tree. */
5191 proto_all_finfos(proto_tree *tree)
5195 ffdata.array = g_ptr_array_new();
5198 proto_tree_traverse_pre_order(tree, every_finfo, &ffdata);
5200 return ffdata.array;
5211 check_for_offset(proto_node *node, gpointer data)
5213 field_info *fi = PNODE_FINFO(node);
5214 offset_search_t *offsearch = data;
5216 /* !fi == the top most container node which holds nothing */
5217 if (fi && !PROTO_ITEM_IS_HIDDEN(node) && fi->ds_tvb && offsearch->tvb == fi->ds_tvb) {
5218 if (offsearch->offset >= (guint) fi->start &&
5219 offsearch->offset < (guint) (fi->start + fi->length)) {
5221 offsearch->finfo = fi;
5222 return FALSE; /* keep traversing */
5225 return FALSE; /* keep traversing */
5228 /* Search a proto_tree backwards (from leaves to root) looking for the field
5229 * whose start/length occupies 'offset' */
5230 /* XXX - I couldn't find an easy way to search backwards, so I search
5231 * forwards, w/o stopping. Therefore, the last finfo I find will the be
5232 * the one I want to return to the user. This algorithm is inefficient
5233 * and could be re-done, but I'd have to handle all the children and
5234 * siblings of each node myself. When I have more time I'll do that.
5237 proto_find_field_from_offset(proto_tree *tree, guint offset, tvbuff_t *tvb)
5239 offset_search_t offsearch;
5241 offsearch.offset = offset;
5242 offsearch.finfo = NULL;
5243 offsearch.tvb = tvb;
5245 proto_tree_traverse_pre_order(tree, check_for_offset, &offsearch);
5247 return offsearch.finfo;
5250 /* Dumps the protocols in the registration database to stdout. An independent
5251 * program can take this output and format it into nice tables or HTML or
5254 * There is one record per line. The fields are tab-delimited.
5256 * Field 1 = protocol name
5257 * Field 2 = protocol short name
5258 * Field 3 = protocol filter name
5261 proto_registrar_dump_protocols(void)
5263 protocol_t *protocol;
5265 void *cookie = NULL;
5267 for (i = proto_get_first_protocol(&cookie); i != -1;
5268 i = proto_get_next_protocol(&cookie)) {
5269 protocol = find_protocol_by_id(i);
5270 printf("%s\t%s\t%s\n", protocol->name, protocol->short_name,
5271 protocol->filter_name);
5275 /* Dumps the value_strings, range_strings or true/false strings for fields
5276 * that have them. There is one record per line. Fields are tab-delimited.
5277 * There are three types of records: Value String, Range String
5278 * and True/False String. The first field, 'V', 'R' or 'T', indicates
5279 * the type of record.
5284 * Field 2 = field abbreviation to which this value string corresponds
5285 * Field 3 = Integer value
5291 * Field 2 = field abbreviation to which this range string corresponds
5292 * Field 3 = Integer value: lower bound
5293 * Field 4 = Integer value: upper bound
5296 * True/False Strings
5297 * ------------------
5299 * Field 2 = field abbreviation to which this true/false string corresponds
5300 * Field 3 = True String
5301 * Field 4 = False String
5304 proto_registrar_dump_values(void)
5306 header_field_info *hfinfo, *parent_hfinfo;
5308 const value_string *vals;
5309 const range_string *range;
5310 const true_false_string *tfs;
5312 len = gpa_hfinfo.len;
5313 for (i = 0; i < len ; i++) {
5314 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
5316 if (hfinfo->id == hf_text_only) {
5320 /* ignore protocols */
5321 if (proto_registrar_is_protocol(i)) {
5324 /* process header fields */
5327 * If this field isn't at the head of the list of
5328 * fields with this name, skip this field - all
5329 * fields with the same name are really just versions
5330 * of the same field stored in different bits, and
5331 * should have the same type/radix/value list, and
5332 * just differ in their bit masks. (If a field isn't
5333 * a bitfield, but can be, say, 1 or 2 bytes long,
5334 * it can just be made FT_UINT16, meaning the
5335 * *maximum* length is 2 bytes, and be used
5338 if (hfinfo->same_name_prev != NULL)
5341 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
5347 if ((hfinfo->display & BASE_STRUCTURE_RESET) != BASE_CUSTOM &&
5348 (hfinfo->type == FT_UINT8 ||
5349 hfinfo->type == FT_UINT16 ||
5350 hfinfo->type == FT_UINT24 ||
5351 hfinfo->type == FT_UINT32 ||
5352 hfinfo->type == FT_UINT64 ||
5353 hfinfo->type == FT_INT8 ||
5354 hfinfo->type == FT_INT16 ||
5355 hfinfo->type == FT_INT24 ||
5356 hfinfo->type == FT_INT32 ||
5357 hfinfo->type == FT_INT64)) {
5359 if ((hfinfo->display & BASE_RANGE_STRING) == 0) {
5360 vals = hfinfo->strings;
5362 range = hfinfo->strings;
5365 else if (hfinfo->type == FT_BOOLEAN) {
5366 tfs = hfinfo->strings;
5369 /* Print value strings? */
5372 while (vals[vi].strptr) {
5373 /* Print in the proper base */
5374 if (hfinfo->display == BASE_HEX) {
5375 printf("V\t%s\t0x%x\t%s\n",
5381 printf("V\t%s\t%u\t%s\n",
5390 /* print range strings? */
5393 while (range[vi].strptr) {
5394 /* Print in the proper base */
5395 if ((hfinfo->display & BASE_STRUCTURE_RESET) == BASE_HEX) {
5396 printf("R\t%s\t0x%x\t0x%x\t%s\n",
5398 range[vi].value_min,
5399 range[vi].value_max,
5403 printf("R\t%s\t%u\t%u\t%s\n",
5405 range[vi].value_min,
5406 range[vi].value_max,
5413 /* Print true/false strings? */
5415 printf("T\t%s\t%s\t%s\n", hfinfo->abbrev,
5416 tfs->true_string, tfs->false_string);
5422 /* Dumps the contents of the registration database to stdout. An independent
5423 * program can take this output and format it into nice tables or HTML or
5426 * There is one record per line. Each record is either a protocol or a header
5427 * field, differentiated by the first field. The fields are tab-delimited.
5432 * Field 2 = descriptive protocol name
5433 * Field 3 = protocol abbreviation
5439 * Field 2 = descriptive field name
5440 * Field 3 = field abbreviation
5441 * Field 4 = type ( textual representation of the the ftenum type )
5442 * Field 5 = parent protocol abbreviation
5443 * Field 6 = blurb describing field
5447 * Field 2 = descriptive field name
5448 * Field 3 = field abbreviation
5449 * Field 4 = type ( textual representation of the the ftenum type )
5450 * Field 5 = parent protocol abbreviation
5451 * Field 6 = blurb describing field
5452 * Field 7 = base for display (for integer types); "parent bitfield width" for FT_BOOLEAN
5453 * Field 8 = blurb describing field (yes, apparently we repeated this accidentally)
5457 * Field 2 = descriptive field name
5458 * Field 3 = field abbreviation
5459 * Field 4 = type ( textual representation of the the ftenum type )
5460 * Field 5 = parent protocol abbreviation
5461 * Field 6 = blurb describing field
5462 * Field 7 = base for display (for integer types); "parent bitfield width" for FT_BOOLEAN
5463 * Field 8 = bitmask: format: hex: 0x....
5467 proto_registrar_dump_fields(int format)
5469 header_field_info *hfinfo, *parent_hfinfo;
5471 const char *enum_name;
5472 const char *base_name;
5476 len = gpa_hfinfo.len;
5477 for (i = 0; i < len ; i++) {
5478 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
5481 * Skip the pseudo-field for "proto_tree_add_text()" since
5482 * we don't want it in the list of filterable fields.
5484 if (hfinfo->id == hf_text_only)
5487 /* format for protocols */
5488 if (proto_registrar_is_protocol(i)) {
5489 printf("P\t%s\t%s\n", hfinfo->name, hfinfo->abbrev);
5491 /* format for header fields */
5494 * If this field isn't at the head of the list of
5495 * fields with this name, skip this field - all
5496 * fields with the same name are really just versions
5497 * of the same field stored in different bits, and
5498 * should have the same type/radix/value list, and
5499 * just differ in their bit masks. (If a field isn't
5500 * a bitfield, but can be, say, 1 or 2 bytes long,
5501 * it can just be made FT_UINT16, meaning the
5502 * *maximum* length is 2 bytes, and be used
5505 if (hfinfo->same_name_prev != NULL)
5508 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
5510 enum_name = ftype_name(hfinfo->type);
5514 if (hfinfo->type == FT_UINT8 ||
5515 hfinfo->type == FT_UINT16 ||
5516 hfinfo->type == FT_UINT24 ||
5517 hfinfo->type == FT_UINT32 ||
5518 hfinfo->type == FT_UINT64 ||
5519 hfinfo->type == FT_INT8 ||
5520 hfinfo->type == FT_INT16 ||
5521 hfinfo->type == FT_INT24 ||
5522 hfinfo->type == FT_INT32 ||
5523 hfinfo->type == FT_INT64) {
5526 switch(hfinfo->display & BASE_STRUCTURE_RESET) {
5528 base_name = "BASE_NONE";
5531 base_name = "BASE_DEC";
5534 base_name = "BASE_HEX";
5537 base_name = "BASE_OCT";
5540 base_name = "BASE_DEC_HEX";
5543 base_name = "BASE_HEX_DEC";
5546 base_name = "BASE_CUSTOM";
5552 } else if (hfinfo->type == FT_BOOLEAN) {
5553 /* For FT_BOOLEAN: 'display' can be "parent bitfield width" */
5554 g_snprintf(width, sizeof(width), "%d", hfinfo->display);
5559 blurb = hfinfo->blurb;
5563 printf("F\t%s\t%s\t%s\t%s\t%s\n",
5564 hfinfo->name, hfinfo->abbrev, enum_name,
5565 parent_hfinfo->abbrev, blurb);
5567 else if (format == 2) {
5568 printf("F\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n",
5569 hfinfo->name, hfinfo->abbrev, enum_name,
5570 parent_hfinfo->abbrev, blurb,
5573 else if (format == 3) {
5574 printf("F\t%s\t%s\t%s\t%s\t%s\t%s\t0x%x\n",
5575 hfinfo->name, hfinfo->abbrev, enum_name,
5576 parent_hfinfo->abbrev, blurb,
5577 base_name, hfinfo->bitmask);
5580 g_assert_not_reached();
5587 hfinfo_numeric_format(header_field_info *hfinfo)
5589 const char *format = NULL;
5591 /* Pick the proper format string */
5592 if (hfinfo->type == FT_FRAMENUM) {
5594 * Frame numbers are always displayed in decimal.
5596 format = "%s == %u";
5598 /* Pick the proper format string, ignoring BASE_RANGE_STRING flag */
5599 switch(hfinfo->display & ~BASE_RANGE_STRING) {
5602 case BASE_OCT: /* I'm lazy */
5604 switch(hfinfo->type) {
5609 format = "%s == %u";
5612 format = "%s == %" G_GINT64_MODIFIER "u";
5618 format = "%s == %d";
5621 format = "%s == %" G_GINT64_MODIFIER "d";
5624 DISSECTOR_ASSERT_NOT_REACHED();
5630 switch(hfinfo->type) {
5632 format = "%s == 0x%02x";
5635 format = "%s == 0x%04x";
5638 format = "%s == 0x%06x";
5641 format = "%s == 0x%08x";
5644 format = "%s == 0x%016" G_GINT64_MODIFIER "x";
5647 DISSECTOR_ASSERT_NOT_REACHED();
5652 DISSECTOR_ASSERT_NOT_REACHED();
5659 /* This function indicates whether it's possible to construct a
5660 * "match selected" display filter string for the specified field,
5661 * returns an indication of whether it's possible, and, if it's
5662 * possible and "filter" is non-null, constructs the filter and
5663 * sets "*filter" to point to it.
5664 * You do not need to [g_]free() this string since it will be automatically
5665 * freed once the next packet is dissected.
5668 construct_match_selected_string(field_info *finfo, epan_dissect_t *edt,
5671 header_field_info *hfinfo;
5677 gint start, length, length_remaining;
5679 gchar is_signed_num = FALSE;
5681 hfinfo = finfo->hfinfo;
5682 DISSECTOR_ASSERT(hfinfo);
5683 abbrev_len = (int) strlen(hfinfo->abbrev);
5685 if (hfinfo->strings && (hfinfo->display & BASE_STRUCTURE_RESET) == BASE_NONE) {
5686 const gchar *str = NULL;
5688 switch(hfinfo->type) {
5694 if (hfinfo->display & BASE_RANGE_STRING) {
5695 str = match_strrval(fvalue_get_sinteger(&finfo->value), hfinfo->strings);
5697 str = match_strval(fvalue_get_sinteger(&finfo->value), hfinfo->strings);
5705 if (hfinfo->display & BASE_RANGE_STRING) {
5706 str = match_strrval(fvalue_get_uinteger(&finfo->value), hfinfo->strings);
5708 str = match_strval(fvalue_get_uinteger(&finfo->value), hfinfo->strings);
5716 if (str != NULL && filter != NULL) {
5717 *filter = ep_strdup_printf("%s == \"%s\"", hfinfo->abbrev, str);
5723 * XXX - we can't use the "val_to_string_repr" and "string_repr_len"
5724 * functions for FT_UINT and FT_INT types, as we choose the base in
5725 * the string expression based on the display base of the field.
5727 * Note that the base does matter, as this is also used for
5728 * the protocolinfo tap.
5730 * It might be nice to use them in "proto_item_fill_label()"
5731 * as well, although, there, you'd have to deal with the base
5732 * *and* with resolved values for addresses.
5734 * Perhaps we need two different val_to_string routines, one
5735 * to generate items for display filters and one to generate
5736 * strings for display, and pass to both of them the
5737 * "display" and "strings" values in the header_field_info
5738 * structure for the field, so they can get the base and,
5739 * if the field is Boolean or an enumerated integer type,
5740 * the tables used to generate human-readable values.
5742 switch(hfinfo->type) {
5748 is_signed_num = TRUE;
5753 if (filter != NULL) {
5754 format = hfinfo_numeric_format(hfinfo);
5756 *filter = ep_strdup_printf(format,
5758 fvalue_get_sinteger(&finfo->value));
5760 *filter = ep_strdup_printf(format,
5762 fvalue_get_uinteger(&finfo->value));
5768 DISSECTOR_ASSERT(!is_signed_num);
5769 if (filter != NULL) {
5770 format = hfinfo_numeric_format(hfinfo);
5771 *filter = ep_strdup_printf(format,
5773 fvalue_get_uinteger(&finfo->value));
5779 if (filter != NULL) {
5780 format = hfinfo_numeric_format(hfinfo);
5781 *filter = ep_strdup_printf(format,
5783 fvalue_get_integer64(&finfo->value));
5789 *filter = ep_strdup(finfo->hfinfo->abbrev);
5794 * If the length is 0, just match the name of the
5797 * (Also check for negative values, just in case,
5798 * as we'll cast it to an unsigned value later.)
5800 length = finfo->length;
5803 *filter = ep_strdup(finfo->hfinfo->abbrev);
5810 * This doesn't have a value, so we'd match
5811 * on the raw bytes at this address.
5813 * Should we be allowed to access to the raw bytes?
5814 * If "edt" is NULL, the answer is "no".
5820 * Is this field part of the raw frame tvbuff?
5821 * If not, we can't use "frame[N:M]" to match
5824 * XXX - should this be frame-relative, or
5825 * protocol-relative?
5827 * XXX - does this fallback for non-registered
5828 * fields even make sense?
5830 if (finfo->ds_tvb != edt->tvb)
5831 return FALSE; /* you lose */
5834 * Don't go past the end of that tvbuff.
5836 length_remaining = tvb_length_remaining(finfo->ds_tvb, finfo->start);
5837 if (length > length_remaining)
5838 length = length_remaining;
5842 if (filter != NULL) {
5843 start = finfo->start;
5844 buf_len = 32 + length * 3;
5845 *filter = ep_alloc0(buf_len);
5848 ptr += g_snprintf(ptr, (gulong) (buf_len-(ptr-*filter)),
5849 "frame[%d:%d] == ", finfo->start, length);
5850 for (i=0;i<length; i++) {
5851 c = tvb_get_guint8(finfo->ds_tvb, start);
5854 ptr += g_snprintf(ptr, (gulong) (buf_len-(ptr-*filter)), "%02x", c);
5857 ptr += g_snprintf(ptr, (gulong) (buf_len-(ptr-*filter)), ":%02x", c);
5864 /* FT_PCRE never appears as a type for a registered field. It is
5865 * only used internally. */
5866 DISSECTOR_ASSERT_NOT_REACHED();
5869 /* By default, use the fvalue's "to_string_repr" method. */
5871 /* Figure out the string length needed.
5872 * The ft_repr length.
5873 * 4 bytes for " == ".
5874 * 1 byte for trailing NUL.
5876 if (filter != NULL) {
5877 dfilter_len = fvalue_string_repr_len(&finfo->value,
5879 dfilter_len += abbrev_len + 4 + 1;
5880 *filter = ep_alloc0(dfilter_len);
5882 /* Create the string */
5883 g_snprintf(*filter, dfilter_len, "%s == ",
5885 fvalue_to_string_repr(&finfo->value,
5887 &(*filter)[abbrev_len + 4]);
5896 * Returns TRUE if we can do a "match selected" on the field, FALSE
5900 proto_can_match_selected(field_info *finfo, epan_dissect_t *edt)
5902 return construct_match_selected_string(finfo, edt, NULL);
5905 /* This function attempts to construct a "match selected" display filter
5906 * string for the specified field; if it can do so, it returns a pointer
5907 * to the string, otherwise it returns NULL.
5909 * The string is allocated with packet lifetime scope.
5910 * You do not need to [g_]free() this string since it will be automatically
5911 * freed once the next packet is dissected.
5914 proto_construct_match_selected_string(field_info *finfo, epan_dissect_t *edt)
5918 if (!construct_match_selected_string(finfo, edt, &filter))
5924 /* This function is common code for both proto_tree_add_bitmask() and
5925 * proto_tree_add_bitmask_text() functions.
5928 proto_item_add_bitmask_tree(proto_item *item, tvbuff_t *tvb, int offset, int len, gint ett,
5929 const int **fields, gboolean little_endian, int flags, gboolean first)
5931 guint32 value = 0, tmpval;
5932 proto_tree *tree = NULL;
5933 header_field_info *hf;
5938 value = tvb_get_guint8(tvb, offset);
5941 value = little_endian ? tvb_get_letohs(tvb, offset) :
5942 tvb_get_ntohs(tvb, offset);
5945 value = little_endian ? tvb_get_letoh24(tvb, offset) :
5946 tvb_get_ntoh24(tvb, offset);
5949 value = little_endian ? tvb_get_letohl(tvb, offset) :
5950 tvb_get_ntohl(tvb, offset);
5953 g_assert_not_reached();
5956 tree = proto_item_add_subtree(item, ett);
5958 proto_tree_add_item(tree, **fields, tvb, offset, len, little_endian);
5959 if (flags & BMT_NO_APPEND) {
5963 hf = proto_registrar_get_nth(**fields);
5964 DISSECTOR_ASSERT(hf->bitmask != 0);
5965 tmpval = (value & hf->bitmask) >> hf->bitshift;
5976 DISSECTOR_ASSERT(len == ftype_length(hf->type));
5978 if (hf->display == BASE_CUSTOM) {
5979 gchar lbl[ITEM_LABEL_LENGTH];
5980 custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hf->strings;
5982 DISSECTOR_ASSERT(fmtfunc);
5983 fmtfunc(lbl, tmpval);
5984 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
5988 else if (hf->strings) {
5989 if (hf->display & BASE_RANGE_STRING) {
5990 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
5991 hf->name, rval_to_str(tmpval, hf->strings, "Unknown"));
5993 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
5994 hf->name, val_to_str(tmpval, cVALS(hf->strings), "Unknown"));
5998 else if (!(flags & BMT_NO_INT)) {
6000 proto_item_append_text(item, ", ");
6003 fmt = IS_FT_INT(hf->type) ? hfinfo_int_format(hf) : hfinfo_uint_format(hf);
6004 if (IS_BASE_DUAL(hf->display)) {
6005 proto_item_append_text(item, fmt, hf->name, tmpval, tmpval);
6007 proto_item_append_text(item, fmt, hf->name, tmpval);
6014 DISSECTOR_ASSERT(len * 8 == hf->display);
6016 if (hf->strings && !(flags & BMT_NO_TFS)) {
6017 /* If we have true/false strings, emit full - otherwise messages
6019 const struct true_false_string *tfs =
6020 (const struct true_false_string *)hf->strings;
6023 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
6024 hf->name, tfs->true_string);
6026 } else if (!(flags & BMT_NO_FALSE)) {
6027 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
6028 hf->name, tfs->false_string);
6031 } else if (hf->bitmask & value) {
6032 /* If the flag is set, show the name */
6033 proto_item_append_text(item, "%s%s", first ? "" : ", ", hf->name);
6038 g_assert_not_reached();
6047 /* This function will dissect a sequence of bytes that describe a
6049 * hf_hdr is a 8/16/24/32 bit integer that describes the bitmask to be dissected.
6050 * This field will form an expansion under which the individual fields of the
6051 * bitmask is dissected and displayed.
6052 * This field must be of the type FT_[U]INT{8|16|24|32}.
6054 * fields is an array of pointers to int that lists all the fields of the
6055 * bitmask. These fields can be either of the type FT_BOOLEAN for flags
6056 * or another integer of the same type/size as hf_hdr with a mask specified.
6057 * This array is terminated by a NULL entry.
6059 * FT_BOOLEAN bits that are set to 1 will have the name added to the expansion.
6060 * FT_integer fields that have a value_string attached will have the
6061 * matched string displayed on the expansion line.
6064 proto_tree_add_bitmask(proto_tree *parent_tree, tvbuff_t *tvb, guint offset, int hf_hdr,
6065 gint ett, const int **fields, gboolean little_endian)
6067 proto_item *item = NULL;
6068 header_field_info *hf;
6071 hf = proto_registrar_get_nth(hf_hdr);
6072 DISSECTOR_ASSERT(IS_FT_INT(hf->type) || IS_FT_UINT(hf->type));
6073 len = ftype_length(hf->type);
6076 item = proto_tree_add_item(parent_tree, hf_hdr, tvb, offset, len, little_endian);
6077 proto_item_add_bitmask_tree(item, tvb, offset, len, ett, fields, little_endian,
6078 BMT_NO_INT|BMT_NO_TFS, FALSE);
6084 /* The same as proto_tree_add_bitmask(), but using an arbitrary text as a top-level item */
6086 proto_tree_add_bitmask_text(proto_tree *parent_tree, tvbuff_t *tvb, guint offset, guint len,
6087 const char *name, const char *fallback,
6088 gint ett, const int **fields, gboolean little_endian, int flags)
6090 proto_item *item = NULL;
6093 item = proto_tree_add_text(parent_tree, tvb, offset, len, "%s", name ? name : "");
6094 if (proto_item_add_bitmask_tree(item, tvb, offset, len, ett, fields, little_endian,
6095 flags, TRUE) && fallback) {
6096 /* Still at first item - append 'fallback' text if any */
6097 proto_item_append_text(item, "%s", fallback);
6105 proto_tree_add_bits_item(proto_tree *tree, int hf_index, tvbuff_t *tvb, gint bit_offset, gint no_of_bits, gboolean little_endian)
6107 header_field_info *hfinfo;
6109 TRY_TO_FAKE_THIS_ITEM(tree, hf_index, hfinfo);
6111 return proto_tree_add_bits_ret_val(tree, hf_index, tvb, bit_offset, no_of_bits, NULL, little_endian);
6114 * This function will dissect a sequence of bits that does not need to be byte aligned; the bits
6115 * set vill be shown in the tree as ..10 10.. and the integer value returned if return_value is set.
6116 * Offset should be given in bits from the start of the tvb.
6120 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)
6122 const char *format = NULL;
6126 guint8 remaining_bits;
6127 guint64 mask = 0,tmp;
6129 header_field_info *hf_field;
6134 /* We can't fake it just yet. We have to fill in the 'return_value' parameter */
6135 PROTO_REGISTRAR_GET_NTH(hf_index, hf_field);
6137 if(hf_field -> bitmask != 0) {
6138 REPORT_DISSECTOR_BUG(ep_strdup_printf("Incompatible use of proto_tree_add_bits_ret_val with field '%s' (%s) with bitmask != 0",
6139 hf_field->abbrev, hf_field->name));
6142 DISSECTOR_ASSERT(bit_offset >= 0);
6143 DISSECTOR_ASSERT(no_of_bits > 0);
6145 /* Byte align offset */
6146 offset = bit_offset>>3;
6149 * Calculate the number of octets used to hold the bits
6151 tot_no_bits = ((bit_offset&0x7)+no_of_bits);
6152 length = tot_no_bits>>3;
6153 remaining_bits = tot_no_bits % 8;
6154 if ((remaining_bits)!=0)
6157 if (no_of_bits < 9){
6158 value = tvb_get_bits8(tvb, bit_offset, no_of_bits);
6159 }else if(no_of_bits < 17){
6160 value = tvb_get_bits16(tvb, bit_offset, no_of_bits, little_endian);
6161 }else if(no_of_bits < 33){
6162 value = tvb_get_bits32(tvb, bit_offset, no_of_bits, little_endian);
6163 }else if(no_of_bits < 65){
6164 value = tvb_get_bits64(tvb, bit_offset, no_of_bits, little_endian);
6166 DISSECTOR_ASSERT_NOT_REACHED();
6171 *return_value=value;
6174 /* Coast clear. Try and fake it */
6175 TRY_TO_FAKE_THIS_ITEM(tree, hf_index, hf_field);
6178 mask = mask << (no_of_bits-1);
6180 /* prepare the string */
6183 for(bit=0;bit<((int)(bit_offset&0x07));bit++){
6184 if(bit&&(!(bit%4))){
6190 /* read the bits for the int */
6191 for(i=0;i<no_of_bits;i++){
6192 if(bit&&(!(bit%4))){
6195 if(bit&&(!(bit%8))){
6209 if(bit&&(!(bit%4))){
6216 strcat(str,hf_field->name);
6218 switch(hf_field->type){
6221 if (hf_field->strings) {
6222 const true_false_string *tfstring =
6223 (const true_false_string *) hf_field->strings;
6224 return proto_tree_add_boolean_format(tree, hf_index, tvb, offset, length, (guint32)value,
6227 (guint32)value ? tfstring->true_string : tfstring->false_string);
6229 return proto_tree_add_boolean_format(tree, hf_index, tvb, offset, length, (guint32)value,
6240 /* 1 - 32 bits field */
6241 if (hf_field->strings) {
6242 return proto_tree_add_uint_format(tree, hf_index, tvb, offset, length, (guint32)value,
6244 str, (hf_field->display & BASE_RANGE_STRING) ?
6245 rval_to_str((guint32)value, hf_field->strings, "Unknown ") :
6246 val_to_str((guint32)value, cVALS(hf_field->strings), "Unknown "),
6250 /* Pick the proper format string */
6251 format = hfinfo_uint_format(hf_field);
6252 if (IS_BASE_DUAL(hf_field->display)) {
6253 return proto_tree_add_uint_format(tree, hf_index, tvb, offset, length, (guint32)value,
6254 format, str, (guint32)value, (guint32)value);
6256 return proto_tree_add_uint_format(tree, hf_index, tvb, offset, length, (guint32)value,
6257 format, str, (guint32)value);
6262 /* Pick the proper format string */
6263 format = hfinfo_uint64_format(hf_field);
6264 if (IS_BASE_DUAL(hf_field->display)) {
6265 return proto_tree_add_uint64_format(tree, hf_index, tvb, offset, length, value,
6266 format, str, value, value);
6268 return proto_tree_add_uint64_format(tree, hf_index, tvb, offset, length, value,
6269 format, str, value);
6274 DISSECTOR_ASSERT_NOT_REACHED();
6281 proto_check_field_name(const gchar *field_name)
6283 return wrs_check_charset(fld_abbrev_chars, field_name);