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 fvalue_set(&fi->value, bytes, TRUE);
1583 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length)
1585 proto_tree_set_bytes(fi, tvb_get_ptr(tvb, offset, length), length);
1588 /* Add a FT_*TIME to a proto_tree */
1590 proto_tree_add_time(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1591 nstime_t *value_ptr)
1595 header_field_info *hfinfo;
1597 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1599 DISSECTOR_ASSERT(hfinfo->type == FT_ABSOLUTE_TIME ||
1600 hfinfo->type == FT_RELATIVE_TIME);
1602 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1603 proto_tree_set_time(new_fi, value_ptr);
1609 proto_tree_add_time_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1610 gint start, gint length, nstime_t *value_ptr,
1611 const char *format, ...)
1615 header_field_info *hfinfo;
1617 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1619 pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
1623 va_start(ap, format);
1624 proto_tree_set_representation_value(pi, format, ap);
1631 proto_tree_add_time_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1632 nstime_t *value_ptr, const char *format, ...)
1636 header_field_info *hfinfo;
1638 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1640 pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
1644 va_start(ap, format);
1645 proto_tree_set_representation(pi, format, ap);
1651 /* Set the FT_*TIME value */
1653 proto_tree_set_time(field_info *fi, nstime_t *value_ptr)
1655 header_field_info *hfinfo;
1657 DISSECTOR_ASSERT(value_ptr != NULL);
1658 hfinfo = fi->hfinfo;
1660 fvalue_set(&fi->value, value_ptr, FALSE);
1663 /* Add a FT_IPXNET to a proto_tree */
1665 proto_tree_add_ipxnet(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1670 header_field_info *hfinfo;
1672 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1674 DISSECTOR_ASSERT(hfinfo->type == FT_IPXNET);
1676 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1677 proto_tree_set_ipxnet(new_fi, value);
1683 proto_tree_add_ipxnet_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1684 gint start, gint length, guint32 value, const char *format, ...)
1688 header_field_info *hfinfo;
1690 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1692 pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
1696 va_start(ap, format);
1697 proto_tree_set_representation_value(pi, format, ap);
1704 proto_tree_add_ipxnet_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1705 guint32 value, const char *format, ...)
1709 header_field_info *hfinfo;
1711 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1713 pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
1717 va_start(ap, format);
1718 proto_tree_set_representation(pi, format, ap);
1724 /* Set the FT_IPXNET value */
1726 proto_tree_set_ipxnet(field_info *fi, guint32 value)
1728 fvalue_set_uinteger(&fi->value, value);
1731 /* Add a FT_IPv4 to a proto_tree */
1733 proto_tree_add_ipv4(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1738 header_field_info *hfinfo;
1740 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1742 DISSECTOR_ASSERT(hfinfo->type == FT_IPv4);
1744 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1745 proto_tree_set_ipv4(new_fi, value);
1751 proto_tree_add_ipv4_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1752 gint start, gint length, guint32 value, const char *format, ...)
1756 header_field_info *hfinfo;
1758 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1760 pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
1764 va_start(ap, format);
1765 proto_tree_set_representation_value(pi, format, ap);
1772 proto_tree_add_ipv4_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1773 guint32 value, const char *format, ...)
1777 header_field_info *hfinfo;
1779 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1781 pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
1785 va_start(ap, format);
1786 proto_tree_set_representation(pi, format, ap);
1792 /* Set the FT_IPv4 value */
1794 proto_tree_set_ipv4(field_info *fi, guint32 value)
1796 fvalue_set_uinteger(&fi->value, value);
1799 /* Add a FT_IPv6 to a proto_tree */
1801 proto_tree_add_ipv6(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1802 const guint8* value_ptr)
1806 header_field_info *hfinfo;
1808 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1810 DISSECTOR_ASSERT(hfinfo->type == FT_IPv6);
1812 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1813 proto_tree_set_ipv6(new_fi, value_ptr);
1819 proto_tree_add_ipv6_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1820 gint start, gint length, const guint8* value_ptr,
1821 const char *format, ...)
1825 header_field_info *hfinfo;
1827 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1829 pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
1833 va_start(ap, format);
1834 proto_tree_set_representation_value(pi, format, ap);
1841 proto_tree_add_ipv6_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1842 const guint8* value_ptr, const char *format, ...)
1846 header_field_info *hfinfo;
1848 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1850 pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
1854 va_start(ap, format);
1855 proto_tree_set_representation(pi, format, ap);
1861 /* Set the FT_IPv6 value */
1863 proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr)
1865 DISSECTOR_ASSERT(value_ptr != NULL);
1866 fvalue_set(&fi->value, (gpointer) value_ptr, FALSE);
1870 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start)
1872 proto_tree_set_ipv6(fi, tvb_get_ptr(tvb, start, 16));
1875 /* Add a FT_GUID to a proto_tree */
1877 proto_tree_add_guid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1878 const e_guid_t *value_ptr)
1882 header_field_info *hfinfo;
1884 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1886 DISSECTOR_ASSERT(hfinfo->type == FT_GUID);
1888 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1889 proto_tree_set_guid(new_fi, value_ptr);
1895 proto_tree_add_guid_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1896 gint start, gint length, const e_guid_t *value_ptr,
1897 const char *format, ...)
1901 header_field_info *hfinfo;
1903 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1905 pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
1909 va_start(ap, format);
1910 proto_tree_set_representation_value(pi, format, ap);
1917 proto_tree_add_guid_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1918 const e_guid_t *value_ptr, const char *format, ...)
1922 header_field_info *hfinfo;
1924 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1926 pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
1930 va_start(ap, format);
1931 proto_tree_set_representation(pi, format, ap);
1937 /* Set the FT_GUID value */
1939 proto_tree_set_guid(field_info *fi, const e_guid_t *value_ptr)
1941 DISSECTOR_ASSERT(value_ptr != NULL);
1942 fvalue_set(&fi->value, (gpointer) value_ptr, FALSE);
1946 proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gboolean little_endian)
1950 tvb_get_guid(tvb, start, &guid, little_endian);
1951 proto_tree_set_guid(fi, &guid);
1954 /* Add a FT_OID to a proto_tree */
1956 proto_tree_add_oid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1957 const guint8* value_ptr)
1961 header_field_info *hfinfo;
1963 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1965 DISSECTOR_ASSERT(hfinfo->type == FT_OID);
1967 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1968 proto_tree_set_oid(new_fi, value_ptr, length);
1974 proto_tree_add_oid_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1975 gint start, gint length, const guint8* value_ptr,
1976 const char *format, ...)
1980 header_field_info *hfinfo;
1982 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1984 pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
1988 va_start(ap, format);
1989 proto_tree_set_representation_value(pi, format, ap);
1996 proto_tree_add_oid_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1997 const guint8* value_ptr, const char *format, ...)
2001 header_field_info *hfinfo;
2003 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2005 pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
2009 va_start(ap, format);
2010 proto_tree_set_representation(pi, format, ap);
2016 /* Set the FT_OID value */
2018 proto_tree_set_oid(field_info *fi, const guint8* value_ptr, gint length)
2022 DISSECTOR_ASSERT(value_ptr != NULL);
2024 bytes = g_byte_array_new();
2026 g_byte_array_append(bytes, value_ptr, length);
2028 fvalue_set(&fi->value, bytes, TRUE);
2032 proto_tree_set_oid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
2034 proto_tree_set_oid(fi, tvb_get_ptr(tvb, start, length), length);
2038 proto_tree_set_uint64(field_info *fi, guint64 value)
2040 fvalue_set_integer64(&fi->value, value);
2044 proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start, guint length, gboolean little_endian)
2047 guint8* b = ep_tvb_memdup(tvb,start,length);
2052 default: DISSECTOR_ASSERT_NOT_REACHED();
2053 case 8: value <<= 8; value += *--b;
2054 case 7: value <<= 8; value += *--b;
2055 case 6: value <<= 8; value += *--b;
2056 case 5: value <<= 8; value += *--b;
2057 case 4: value <<= 8; value += *--b;
2058 case 3: value <<= 8; value += *--b;
2059 case 2: value <<= 8; value += *--b;
2060 case 1: value <<= 8; value += *--b;
2065 default: DISSECTOR_ASSERT_NOT_REACHED();
2066 case 8: value <<= 8; value += *b++;
2067 case 7: value <<= 8; value += *b++;
2068 case 6: value <<= 8; value += *b++;
2069 case 5: value <<= 8; value += *b++;
2070 case 4: value <<= 8; value += *b++;
2071 case 3: value <<= 8; value += *b++;
2072 case 2: value <<= 8; value += *b++;
2073 case 1: value <<= 8; value += *b++;
2078 proto_tree_set_uint64(fi, value);
2081 /* Add a FT_STRING or FT_STRINGZ to a proto_tree. Creates own copy of string,
2082 * and frees it when the proto_tree is destroyed. */
2084 proto_tree_add_string(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2085 gint length, const char* value)
2089 header_field_info *hfinfo;
2091 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2093 DISSECTOR_ASSERT(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ);
2095 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2096 DISSECTOR_ASSERT(length >= 0);
2097 proto_tree_set_string(new_fi, value);
2103 proto_tree_add_string_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2104 gint start, gint length, const char* value, const char *format,
2109 header_field_info *hfinfo;
2111 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2113 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
2117 va_start(ap, format);
2118 proto_tree_set_representation_value(pi, format, ap);
2125 proto_tree_add_string_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2126 gint length, const char* value, const char *format, ...)
2130 header_field_info *hfinfo;
2132 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2134 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
2138 va_start(ap, format);
2139 proto_tree_set_representation(pi, format, ap);
2145 /* Appends string data to a FT_STRING or FT_STRINGZ, allowing progressive
2146 * field info update instead of only updating the representation as does
2147 * proto_item_append_text()
2149 /* NOTE: this function will break with the TRY_TO_FAKE_THIS_ITEM()
2150 * speed optimization.
2151 * Currently only WSP use this function so it is not that bad but try to
2152 * avoid using this one if possible.
2153 * IF you must use this function you MUST also disable the
2154 * TRY_TO_FAKE_THIS_ITEM() optimization for your dissector/function
2155 * using proto_item_append_string().
2156 * Do that by faking that the tree is visible by calling
2157 * proto_tree_set_visible(tree, TRUE) (see packet-wsp.c)
2158 * BEFORE you create the item you are later going to use
2159 * proto_item_append_string() on.
2162 proto_item_append_string(proto_item *pi, const char *str)
2165 header_field_info *hfinfo;
2166 gchar *old_str, *new_str;
2173 fi = PITEM_FINFO(pi);
2174 DISSECTOR_ASSERT(fi && "proto_tree_set_visible(tree, TRUE) should have been called previously");
2176 hfinfo = fi->hfinfo;
2177 if (hfinfo->type == FT_PROTOCOL) {
2178 /* TRY_TO_FAKE_THIS_ITEM() speed optimization: silently skip */
2181 DISSECTOR_ASSERT(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ);
2182 old_str = fvalue_get(&fi->value);
2183 new_str = ep_strdup_printf("%s%s", old_str, str);
2184 fvalue_set(&fi->value, new_str, FALSE);
2187 /* Set the FT_STRING value */
2189 proto_tree_set_string(field_info *fi, const char* value)
2192 fvalue_set(&fi->value, (gpointer) value, FALSE);
2194 fvalue_set(&fi->value, (gpointer) "[ Null ]", FALSE);
2199 proto_tree_set_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
2204 length = tvb_ensure_length_remaining(tvb, start);
2207 string = tvb_get_ephemeral_string(tvb, start, length);
2208 proto_tree_set_string(fi, string);
2212 proto_tree_set_ebcdic_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
2217 length = tvb_ensure_length_remaining(tvb, start);
2220 string = tvb_get_ephemeral_string(tvb, start, length);
2221 EBCDIC_to_ASCII(string, length);
2222 proto_tree_set_string(fi, string);
2225 /* Add a FT_ETHER to a proto_tree */
2227 proto_tree_add_ether(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2228 const guint8* value)
2232 header_field_info *hfinfo;
2234 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2236 DISSECTOR_ASSERT(hfinfo->type == FT_ETHER);
2238 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2239 proto_tree_set_ether(new_fi, value);
2245 proto_tree_add_ether_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2246 gint start, gint length, const guint8* value,
2247 const char *format, ...)
2251 header_field_info *hfinfo;
2253 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2255 pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
2259 va_start(ap, format);
2260 proto_tree_set_representation_value(pi, format, ap);
2267 proto_tree_add_ether_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2268 const guint8* value, const char *format, ...)
2272 header_field_info *hfinfo;
2274 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2276 pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
2280 va_start(ap, format);
2281 proto_tree_set_representation(pi, format, ap);
2287 /* Set the FT_ETHER value */
2289 proto_tree_set_ether(field_info *fi, const guint8* value)
2291 fvalue_set(&fi->value, (gpointer) value, FALSE);
2295 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start)
2297 proto_tree_set_ether(fi, tvb_get_ptr(tvb, start, 6));
2300 /* Add a FT_BOOLEAN to a proto_tree */
2302 proto_tree_add_boolean(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2307 header_field_info *hfinfo;
2309 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2311 DISSECTOR_ASSERT(hfinfo->type == FT_BOOLEAN);
2313 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2314 proto_tree_set_boolean(new_fi, value);
2320 proto_tree_add_boolean_format_value(proto_tree *tree, int hfindex,
2321 tvbuff_t *tvb, gint start, gint length, guint32 value,
2322 const char *format, ...)
2326 header_field_info *hfinfo;
2328 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2330 pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
2334 va_start(ap, format);
2335 proto_tree_set_representation_value(pi, format, ap);
2342 proto_tree_add_boolean_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2343 guint32 value, const char *format, ...)
2347 header_field_info *hfinfo;
2349 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2351 pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
2355 va_start(ap, format);
2356 proto_tree_set_representation(pi, format, ap);
2362 /* Set the FT_BOOLEAN value */
2364 proto_tree_set_boolean(field_info *fi, guint32 value)
2366 proto_tree_set_uint(fi, value);
2369 /* Add a FT_FLOAT to a proto_tree */
2371 proto_tree_add_float(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2376 header_field_info *hfinfo;
2378 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2380 DISSECTOR_ASSERT(hfinfo->type == FT_FLOAT);
2382 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2383 proto_tree_set_float(new_fi, value);
2389 proto_tree_add_float_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2390 gint start, gint length, float value, const char *format, ...)
2394 header_field_info *hfinfo;
2396 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2398 pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
2402 va_start(ap, format);
2403 proto_tree_set_representation_value(pi, format, ap);
2410 proto_tree_add_float_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2411 float value, const char *format, ...)
2415 header_field_info *hfinfo;
2417 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2419 pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
2423 va_start(ap, format);
2424 proto_tree_set_representation(pi, format, ap);
2430 /* Set the FT_FLOAT value */
2432 proto_tree_set_float(field_info *fi, float value)
2434 fvalue_set_floating(&fi->value, value);
2437 /* Add a FT_DOUBLE to a proto_tree */
2439 proto_tree_add_double(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2444 header_field_info *hfinfo;
2446 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2448 DISSECTOR_ASSERT(hfinfo->type == FT_DOUBLE);
2450 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2451 proto_tree_set_double(new_fi, value);
2457 proto_tree_add_double_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2458 gint start, gint length, double value, const char *format, ...)
2462 header_field_info *hfinfo;
2464 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2466 pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
2470 va_start(ap, format);
2471 proto_tree_set_representation_value(pi, format, ap);
2478 proto_tree_add_double_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2479 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(pi, format, ap);
2498 /* Set the FT_DOUBLE value */
2500 proto_tree_set_double(field_info *fi, double value)
2502 fvalue_set_floating(&fi->value, value);
2505 /* Add FT_UINT{8,16,24,32} to a proto_tree */
2507 proto_tree_add_uint(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2510 proto_item *pi = NULL;
2512 header_field_info *hfinfo;
2514 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2516 switch(hfinfo->type) {
2522 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length,
2524 proto_tree_set_uint(new_fi, value);
2528 DISSECTOR_ASSERT_NOT_REACHED();
2535 proto_tree_add_uint_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2536 gint start, gint length, guint32 value, const char *format, ...)
2540 header_field_info *hfinfo;
2542 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2544 pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
2548 va_start(ap, format);
2549 proto_tree_set_representation_value(pi, format, ap);
2556 proto_tree_add_uint_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2557 guint32 value, const char *format, ...)
2561 header_field_info *hfinfo;
2563 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2565 pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
2569 va_start(ap, format);
2570 proto_tree_set_representation(pi, format, ap);
2576 /* Set the FT_UINT{8,16,24,32} value */
2578 proto_tree_set_uint(field_info *fi, guint32 value)
2580 header_field_info *hfinfo;
2583 hfinfo = fi->hfinfo;
2586 if (hfinfo->bitmask) {
2587 /* Mask out irrelevant portions */
2588 integer &= hfinfo->bitmask;
2591 if (hfinfo->bitshift > 0) {
2592 integer >>= hfinfo->bitshift;
2596 fvalue_set_uinteger(&fi->value, integer);
2599 /* Add FT_UINT64 to a proto_tree */
2601 proto_tree_add_uint64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2604 proto_item *pi = NULL;
2606 header_field_info *hfinfo;
2608 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2610 DISSECTOR_ASSERT(hfinfo->type == FT_UINT64);
2612 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2613 proto_tree_set_uint64(new_fi, value);
2619 proto_tree_add_uint64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2620 gint start, gint length, guint64 value, const char *format, ...)
2624 header_field_info *hfinfo;
2626 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2628 pi = proto_tree_add_uint64(tree, hfindex, tvb, start, length, value);
2632 va_start(ap, format);
2633 proto_tree_set_representation_value(pi, format, ap);
2640 proto_tree_add_uint64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2641 guint64 value, const char *format, ...)
2645 header_field_info *hfinfo;
2647 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2649 pi = proto_tree_add_uint64(tree, hfindex, tvb, start, length, value);
2653 va_start(ap, format);
2654 proto_tree_set_representation(pi, format, ap);
2660 /* Add FT_INT{8,16,24,32} to a proto_tree */
2662 proto_tree_add_int(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2665 proto_item *pi = NULL;
2667 header_field_info *hfinfo;
2669 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2671 switch(hfinfo->type) {
2676 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length,
2678 proto_tree_set_int(new_fi, value);
2682 DISSECTOR_ASSERT_NOT_REACHED();
2689 proto_tree_add_int_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2690 gint start, gint length, gint32 value, const char *format, ...)
2692 proto_item *pi = NULL;
2694 header_field_info *hfinfo;
2696 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2698 pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
2702 va_start(ap, format);
2703 proto_tree_set_representation_value(pi, format, ap);
2710 proto_tree_add_int_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2711 gint32 value, const char *format, ...)
2713 proto_item *pi = NULL;
2715 header_field_info *hfinfo;
2717 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2719 pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
2723 va_start(ap, format);
2724 proto_tree_set_representation(pi, format, ap);
2730 /* Set the FT_INT{8,16,24,32} value */
2732 proto_tree_set_int(field_info *fi, gint32 value)
2734 header_field_info *hfinfo;
2737 hfinfo = fi->hfinfo;
2738 integer = (guint32) value;
2740 if (hfinfo->bitmask) {
2741 /* Mask out irrelevant portions */
2742 integer &= hfinfo->bitmask;
2745 if (hfinfo->bitshift > 0) {
2746 integer >>= hfinfo->bitshift;
2750 fvalue_set_sinteger(&fi->value, integer);
2753 /* Add FT_INT64 to a proto_tree */
2755 proto_tree_add_int64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2758 proto_item *pi = NULL;
2760 header_field_info *hfinfo;
2762 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2764 DISSECTOR_ASSERT(hfinfo->type == FT_INT64);
2766 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2767 proto_tree_set_uint64(new_fi, (guint64)value);
2773 proto_tree_add_int64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2774 gint start, gint length, gint64 value, const char *format, ...)
2778 header_field_info *hfinfo;
2780 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2782 pi = proto_tree_add_int64(tree, hfindex, tvb, start, length, value);
2786 va_start(ap, format);
2787 proto_tree_set_representation_value(pi, format, ap);
2794 proto_tree_add_int64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2795 gint64 value, const char *format, ...)
2799 header_field_info *hfinfo;
2801 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2803 pi = proto_tree_add_int64(tree, hfindex, tvb, start, length, value);
2807 va_start(ap, format);
2808 proto_tree_set_representation(pi, format, ap);
2814 /* Throw an exception if we exceed this many tree items. */
2815 /* XXX - This should probably be a preference */
2816 #define MAX_TREE_ITEMS (1 * 1000 * 1000)
2817 /* Add a field_info struct to the proto_tree, encapsulating it in a proto_node */
2819 proto_tree_add_node(proto_tree *tree, field_info *fi)
2821 proto_node *pnode, *tnode, *sibling;
2825 * Make sure "tree" is ready to have subtrees under it, by
2826 * checking whether it's been given an ett_ value.
2828 * "PNODE_FINFO(tnode)" may be null; that's the case for the root
2829 * node of the protocol tree. That node is not displayed,
2830 * so it doesn't need an ett_ value to remember whether it
2834 tfi = PNODE_FINFO(tnode);
2835 if (tfi != NULL && (tfi->tree_type < 0 || tfi->tree_type >= num_tree_types)) {
2836 REPORT_DISSECTOR_BUG(ep_strdup_printf("\"%s\" - \"%s\" tfi->tree_type: %u invalid (%s:%u)",
2837 fi->hfinfo->name, fi->hfinfo->abbrev, tfi->tree_type, __FILE__, __LINE__));
2838 /* XXX - is it safe to continue here? */
2841 DISSECTOR_ASSERT(tfi == NULL ||
2842 (tfi->tree_type >= 0 && tfi->tree_type < num_tree_types));
2844 PTREE_DATA(tree)->count++;
2845 if (PTREE_DATA(tree)->count > MAX_TREE_ITEMS) {
2846 /* Let the exception handler add items to the tree */
2847 PTREE_DATA(tree)->count = 0;
2848 THROW_MESSAGE(DissectorError,
2849 ep_strdup_printf("More than %d items in the tree -- possible infinite loop", MAX_TREE_ITEMS));
2852 PROTO_NODE_NEW(pnode);
2853 pnode->parent = tnode;
2854 PNODE_FINFO(pnode) = fi;
2855 pnode->tree_data = PTREE_DATA(tree);
2857 if (tnode->last_child != NULL) {
2858 sibling = tnode->last_child;
2859 DISSECTOR_ASSERT(sibling->next == NULL);
2860 sibling->next = pnode;
2862 tnode->first_child = pnode;
2863 tnode->last_child = pnode;
2865 return (proto_item*)pnode;
2869 /* Generic way to allocate field_info and add to proto_tree.
2870 * Sets *pfi to address of newly-allocated field_info struct, if pfi is
2873 proto_tree_add_pi(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2874 gint *length, field_info **pfi)
2883 fi = alloc_field_info(tree, hfindex, tvb, start, length);
2884 pi = proto_tree_add_node(tree, fi);
2886 /* If the proto_tree wants to keep a record of this finfo
2887 * for quick lookup, then record it. */
2888 ptrs = proto_lookup_or_create_interesting_hfids(tree, fi->hfinfo);
2890 g_ptr_array_add(ptrs, fi);
2892 /* Does the caller want to know the fi pointer? */
2901 static header_field_info *
2902 get_hfi_and_length(int hfindex, tvbuff_t *tvb, gint start, gint *length,
2905 header_field_info *hfinfo;
2906 gint length_remaining;
2909 * We only allow a null tvbuff if the item has a zero length,
2910 * i.e. if there's no data backing it.
2912 DISSECTOR_ASSERT(tvb != NULL || *length == 0);
2914 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2917 * XXX - in some protocols, there are 32-bit unsigned length
2918 * fields, so lengths in protocol tree and tvbuff routines
2919 * should really be unsigned. We should have, for those
2920 * field types for which "to the end of the tvbuff" makes sense,
2921 * additional routines that take no length argument and
2922 * add fields that run to the end of the tvbuff.
2924 if (*length == -1) {
2926 * For FT_NONE, FT_PROTOCOL, FT_BYTES, and FT_STRING fields,
2927 * a length of -1 means "set the length to what remains in
2930 * The assumption is either that
2932 * 1) the length of the item can only be determined
2933 * by dissection (typically true of items with
2934 * subitems, which are probably FT_NONE or
2939 * 2) if the tvbuff is "short" (either due to a short
2940 * snapshot length or due to lack of reassembly of
2941 * fragments/segments/whatever), we want to display
2942 * what's available in the field (probably FT_BYTES
2943 * or FT_STRING) and then throw an exception later
2947 * 3) the field is defined to be "what's left in the
2950 * so we set the length to what remains in the tvbuff so
2951 * that, if we throw an exception while dissecting, it
2952 * has what is probably the right value.
2954 * For FT_STRINGZ, it means "the string is null-terminated,
2955 * not null-padded; set the length to the actual length
2956 * of the string", and if the tvbuff if short, we just
2957 * throw an exception.
2959 * It's not valid for any other type of field.
2961 switch (hfinfo->type) {
2965 * We allow this to be zero-length - for
2966 * example, an ONC RPC NULL procedure has
2967 * neither arguments nor reply, so the
2968 * payload for that protocol is empty.
2970 * However, if the length is negative, the
2971 * start offset is *past* the byte past the
2972 * end of the tvbuff, so we throw an
2975 *length = tvb_length_remaining(tvb, start);
2978 * Use "tvb_ensure_bytes_exist()"
2979 * to force the appropriate exception
2982 tvb_ensure_bytes_exist(tvb, start, 0);
2984 DISSECTOR_ASSERT(*length >= 0);
2990 *length = tvb_ensure_length_remaining(tvb, start);
2991 DISSECTOR_ASSERT(*length >= 0);
2996 * Leave the length as -1, so our caller knows
3002 DISSECTOR_ASSERT_NOT_REACHED();
3004 *item_length = *length;
3006 *item_length = *length;
3007 if (hfinfo->type == FT_PROTOCOL || hfinfo->type == FT_NONE) {
3009 * These types are for interior nodes of the
3010 * tree, and don't have data associated with
3011 * them; if the length is negative (XXX - see
3012 * above) or goes past the end of the tvbuff,
3013 * cut it short at the end of the tvbuff.
3014 * That way, if this field is selected in
3015 * Wireshark, we don't highlight stuff past
3016 * the end of the data.
3018 /* XXX - what to do, if we don't have a tvb? */
3020 length_remaining = tvb_length_remaining(tvb, start);
3021 if (*item_length < 0 ||
3022 (*item_length > 0 &&
3023 (length_remaining < *item_length)))
3024 *item_length = length_remaining;
3027 if (*item_length < 0) {
3028 THROW(ReportedBoundsError);
3036 new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
3037 gint start, gint item_length)
3043 fi->hfinfo = hfinfo;
3045 fi->start+=(tvb)?TVB_RAW_OFFSET(tvb):0;
3046 fi->length = item_length;
3049 if (!PTREE_DATA(tree)->visible)
3050 FI_SET_FLAG(fi, FI_HIDDEN);
3051 fvalue_init(&fi->value, fi->hfinfo->type);
3054 /* add the data source tvbuff */
3055 fi->ds_tvb=tvb?TVB_GET_DS_TVB(tvb):NULL;
3057 fi->appendix_start = 0;
3058 fi->appendix_length = 0;
3064 alloc_field_info(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3067 header_field_info *hfinfo;
3070 hfinfo = get_hfi_and_length(hfindex, tvb, start, length, &item_length);
3071 return new_field_info(tree, hfinfo, tvb, start, item_length);
3074 /* If the protocol tree is to be visible, set the representation of a
3075 proto_tree entry with the name of the field for the item and with
3076 the value formatted with the supplied printf-style format and
3079 proto_tree_set_representation_value(proto_item *pi, const char *format, va_list ap)
3081 int ret; /*tmp return value */
3082 field_info *fi = PITEM_FINFO(pi);
3083 header_field_info *hf;
3085 DISSECTOR_ASSERT(fi);
3089 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
3090 ITEM_LABEL_NEW(fi->rep);
3091 if (hf->bitmask && (hf->type == FT_BOOLEAN || IS_FT_UINT(hf->type))) {
3095 val = fvalue_get_uinteger(&fi->value);
3096 if (hf->bitshift > 0) {
3097 val <<= hf->bitshift;
3099 decode_bitfield_value(tmpbuf, val, hf->bitmask, hfinfo_bitwidth(hf));
3100 /* put in the hf name */
3101 ret = g_snprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
3102 "%s%s: ", tmpbuf, fi->hfinfo->name);
3104 /* put in the hf name */
3105 ret = g_snprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
3106 "%s: ", fi->hfinfo->name);
3109 /* If possible, Put in the value of the string */
3110 if (ret < ITEM_LABEL_LENGTH) {
3111 ret += g_vsnprintf(fi->rep->representation + ret,
3112 ITEM_LABEL_LENGTH - ret, format, ap);
3114 if (ret >= ITEM_LABEL_LENGTH) {
3115 /* Uh oh, we don't have enough room. Tell the user
3116 * that the field is truncated.
3120 /* Argh, we cannot reuse 'ap' here. So make a copy
3121 * of what we formatted for (re)use below.
3123 oldrep = g_strdup(fi->rep->representation);
3125 g_snprintf(fi->rep->representation,
3134 /* If the protocol tree is to be visible, set the representation of a
3135 proto_tree entry with the representation formatted with the supplied
3136 printf-style format and argument list. */
3138 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap)
3140 int ret; /*tmp return value */
3141 field_info *fi = PITEM_FINFO(pi);
3143 DISSECTOR_ASSERT(fi);
3145 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
3146 ITEM_LABEL_NEW(fi->rep);
3147 ret = g_vsnprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
3149 if (ret >= ITEM_LABEL_LENGTH) {
3150 /* Uh oh, we don't have enough room. Tell the user
3151 * that the field is truncated.
3155 /* Argh, we cannot reuse 'ap' here. So make a copy
3156 * of what we formatted for (re)use below.
3158 oldrep = g_strdup(fi->rep->representation);
3160 g_snprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
3161 "[truncated] %s", oldrep);
3167 /* -------------------------- */
3169 proto_custom_set(proto_tree* tree, const gchar *field,
3171 gchar *expr, int size )
3177 guint32 n_addr; /* network-order IPv4 address */
3179 const true_false_string *tfstring;
3183 header_field_info* hfinfo;
3188 /* speed up by storing field id in column info ? they
3189 are already in the filter.
3191 hfinfo = g_tree_lookup(gpa_name_tree, field);
3193 /* do we need to rewind ? */
3198 finfos = proto_get_finfo_ptr_array(tree, hfinfo->id);
3200 if (!finfos || !(len = g_ptr_array_len(finfos))) {
3201 hfinfo = hfinfo->same_name_next;
3204 /* get the last one */
3205 finfo = g_ptr_array_index(finfos, len -1);
3207 switch(hfinfo->type) {
3211 bytes = fvalue_get(&finfo->value);
3212 g_snprintf(result, size, "%s", bytes_to_str(bytes, fvalue_length(&finfo->value)));
3215 case FT_ABSOLUTE_TIME:
3216 g_snprintf(result, size, "%s", abs_time_to_str(fvalue_get(&finfo->value)));
3219 case FT_RELATIVE_TIME:
3220 g_snprintf(result, size, "%s", rel_time_to_secs_str(fvalue_get(&finfo->value)));
3224 u_integer = fvalue_get_uinteger(&finfo->value);
3225 tfstring = (const true_false_string *)&tfs_true_false;
3226 if (hfinfo->strings) {
3227 tfstring = (const struct true_false_string*) hfinfo->strings;
3229 g_snprintf(result, size, "%s", u_integer ? tfstring->true_string : tfstring->false_string);
3237 u_integer = fvalue_get_uinteger(&finfo->value);
3238 if (hfinfo->strings) {
3239 if (hfinfo->display & BASE_RANGE_STRING) {
3240 g_snprintf(result, size, "%s", rval_to_str(u_integer, hfinfo->strings, "%u"));
3242 g_snprintf(result, size, "%s", val_to_str(u_integer, cVALS(hfinfo->strings), "%u"));
3244 } else if (IS_BASE_DUAL(hfinfo->display)) {
3245 g_snprintf(result, size, hfinfo_uint_value_format(hfinfo), u_integer, u_integer);
3247 g_snprintf(result, size, hfinfo_uint_value_format(hfinfo), u_integer);
3253 g_snprintf(result, size, "%" G_GINT64_MODIFIER "u", fvalue_get_integer64(&finfo->value));
3256 /* XXX - make these just FT_INT? */
3261 integer = fvalue_get_sinteger(&finfo->value);
3262 if (hfinfo->strings) {
3263 if (hfinfo->display & BASE_RANGE_STRING) {
3264 g_snprintf(result, size, "%s", rval_to_str(integer, hfinfo->strings, "%d"));
3266 g_snprintf(result, size, "%s", val_to_str(integer, cVALS(hfinfo->strings), "%d"));
3268 } else if (IS_BASE_DUAL(hfinfo->display)) {
3269 g_snprintf(result, size, hfinfo_int_value_format(hfinfo), integer, integer);
3271 g_snprintf(result, size, hfinfo_int_value_format(hfinfo), integer);
3276 ipv4 = fvalue_get(&finfo->value);
3277 n_addr = ipv4_get_net_order_addr(ipv4);
3278 g_snprintf(result, size, "%s", ip_to_str((guint8 *)&n_addr));
3282 g_snprintf(result, size, "%s", bytes_to_str_punct(fvalue_get(&finfo->value), 6, ':'));
3286 g_snprintf(result, size, "%s", guid_to_str((e_guid_t *)fvalue_get(&finfo->value)));
3290 bytes = fvalue_get(&finfo->value);
3291 g_snprintf(result, size, "%s", oid_resolved_from_encoded(bytes, fvalue_length(&finfo->value)));
3295 g_snprintf(result, size, "%." STRINGIFY(FLT_DIG) "f", fvalue_get_floating(&finfo->value));
3299 g_snprintf(result, size, "%." STRINGIFY(DBL_DIG) "g", fvalue_get_floating(&finfo->value));
3305 case FT_UINT_STRING:
3306 bytes = fvalue_get(&finfo->value);
3307 g_snprintf(result, size, "%s", format_text(bytes, strlen(bytes)));
3310 case FT_IPXNET: /*XXX really No column custom ?*/
3313 g_error("hfinfo->type %d (%s) not handled\n",
3315 ftype_name(hfinfo->type));
3316 DISSECTOR_ASSERT_NOT_REACHED();
3320 switch(hfinfo->type) {
3324 case FT_UINT_STRING:
3325 g_snprintf(expr, size, "\"%s\"",result);
3327 g_strlcpy(expr, result, size);
3330 return hfinfo->abbrev;
3336 /* Set text of proto_item after having already been created. */
3338 proto_item_set_text(proto_item *pi, const char *format, ...)
3340 field_info *fi = NULL;
3347 fi = PITEM_FINFO(pi);
3352 ITEM_LABEL_FREE(fi->rep);
3355 va_start(ap, format);
3356 proto_tree_set_representation(pi, format, ap);
3360 /* Append to text of proto_item after having already been created. */
3362 proto_item_append_text(proto_item *pi, const char *format, ...)
3364 field_info *fi = NULL;
3372 fi = PITEM_FINFO(pi);
3377 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
3378 va_start(ap, format);
3381 * If we don't already have a representation,
3382 * generate the default representation.
3384 if (fi->rep == NULL) {
3385 ITEM_LABEL_NEW(fi->rep);
3386 proto_item_fill_label(fi, fi->rep->representation);
3389 curlen = strlen(fi->rep->representation);
3390 if (ITEM_LABEL_LENGTH > curlen) {
3391 g_vsnprintf(fi->rep->representation + curlen,
3392 ITEM_LABEL_LENGTH - (gulong) curlen, format, ap);
3399 proto_item_set_len(proto_item *pi, gint length)
3406 fi = PITEM_FINFO(pi);
3410 DISSECTOR_ASSERT(length >= 0);
3411 fi->length = length;
3413 if (fi->value.ftype->ftype == FT_BYTES)
3414 fi->value.value.bytes->len = length;
3418 * Sets the length of the item based on its start and on the specified
3419 * offset, which is the offset past the end of the item; as the start
3420 * in the item is relative to the beginning of the data source tvbuff,
3421 * we need to pass in a tvbuff - the end offset is relative to the beginning
3425 proto_item_set_end(proto_item *pi, tvbuff_t *tvb, gint end)
3432 fi = PITEM_FINFO(pi);
3436 end += TVB_RAW_OFFSET(tvb);
3437 DISSECTOR_ASSERT(end >= fi->start);
3438 fi->length = end - fi->start;
3442 proto_item_get_len(proto_item *pi)
3444 field_info *fi = PITEM_FINFO(pi);
3445 return fi ? fi->length : -1;
3449 /** clear flags according to the mask and set new flag values */
3450 #define FI_REPLACE_FLAGS(fi, mask, flags_in) { \
3451 (fi->flags = (fi)->flags & ~(mask)); \
3452 (fi->flags = (fi)->flags | (flags_in)); \
3456 proto_item_set_expert_flags(proto_item *pi, int group, guint severity)
3458 if(pi == NULL || PITEM_FINFO(pi) == NULL)
3461 /* only change things if severity is worse or at least equal than before */
3462 if(severity >= FI_GET_FLAG(PITEM_FINFO(pi), PI_SEVERITY_MASK)) {
3463 FI_REPLACE_FLAGS(PITEM_FINFO(pi), PI_GROUP_MASK, group);
3464 FI_REPLACE_FLAGS(PITEM_FINFO(pi), PI_SEVERITY_MASK, severity);
3473 proto_tree_create_root(void)
3477 /* Initialize the proto_node */
3478 PROTO_NODE_NEW(pnode);
3479 pnode->parent = NULL;
3480 PNODE_FINFO(pnode) = NULL;
3481 pnode->tree_data = g_new(tree_data_t, 1);
3483 /* Don't initialize the tree_data_t. Wait until we know we need it */
3484 pnode->tree_data->interesting_hfids = NULL;
3486 /* Set the default to FALSE so it's easier to
3487 * find errors; if we expect to see the protocol tree
3488 * but for some reason the default 'visible' is not
3489 * changed, then we'll find out very quickly. */
3490 pnode->tree_data->visible = FALSE;
3492 /* Make sure that we fake protocols (if possible) */
3493 pnode->tree_data->fake_protocols = TRUE;
3495 /* Keep track of the number of children */
3496 pnode->tree_data->count = 0;
3498 return (proto_tree*) pnode;
3502 /* "prime" a proto_tree with a single hfid that a dfilter
3503 * is interested in. */
3505 proto_tree_prime_hfid(proto_tree *tree _U_, gint hfid)
3507 header_field_info *hfinfo;
3509 PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
3510 /* this field is referenced by a filter so increase the refcount.
3511 also increase the refcount for the parent, i.e the protocol.
3513 hfinfo->ref_count = HF_REF_TYPE_DIRECT;
3514 /* only increase the refcount if there is a parent.
3515 if this is a protocol and not a field then parent will be -1
3516 and there is no parent to add any refcounting for.
3518 if (hfinfo->parent != -1) {
3519 header_field_info *parent_hfinfo;
3520 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
3522 /* Mark parent as indirectly referenced unless it is already directly
3523 * referenced, i.e. the user has specified the parent in a filter.
3525 if (parent_hfinfo->ref_count != HF_REF_TYPE_DIRECT)
3526 parent_hfinfo->ref_count = HF_REF_TYPE_INDIRECT;
3531 proto_item_add_subtree(proto_item *pi, gint idx) {
3537 DISSECTOR_ASSERT(idx >= 0 && idx < num_tree_types);
3539 fi = PITEM_FINFO(pi);
3541 return (proto_tree*) pi;
3543 fi->tree_type = idx;
3545 return (proto_tree*) pi;
3549 proto_item_get_subtree(proto_item *pi) {
3554 fi = PITEM_FINFO(pi);
3555 if ( (!fi) || (fi->tree_type == -1) )
3557 return (proto_tree*) pi;
3561 proto_item_get_parent(proto_item *ti) {
3568 proto_item_get_parent_nth(proto_item *ti, int gen) {
3581 proto_tree_get_parent(proto_tree *tree) {
3584 return (proto_item*) tree;
3588 proto_tree_get_root(proto_tree *tree) {
3591 while (tree->parent) {
3592 tree = tree->parent;
3598 proto_tree_move_item(proto_tree *tree, proto_item *fixed_item, proto_item *item_to_move)
3600 /* This function doesn't generate any values. It only reorganizes the prococol tree
3601 * so we can bail out immediately if it isn't visible. */
3602 if (!tree || !PTREE_DATA(tree)->visible)
3605 DISSECTOR_ASSERT(item_to_move->parent == tree);
3606 DISSECTOR_ASSERT(fixed_item->parent == tree);
3608 /*** cut item_to_move out ***/
3610 /* is item_to_move the first? */
3611 if(tree->first_child == item_to_move) {
3612 /* simply change first child to next */
3613 tree->first_child = item_to_move->next;
3615 DISSECTOR_ASSERT(tree->last_child != item_to_move);
3617 proto_item *curr_item;
3618 /* find previous and change it's next */
3619 for(curr_item = tree->first_child; curr_item != NULL; curr_item = curr_item->next) {
3620 if(curr_item->next == item_to_move) {
3625 DISSECTOR_ASSERT(curr_item);
3627 curr_item->next = item_to_move->next;
3629 /* fix last_child if required */
3630 if(tree->last_child == item_to_move) {
3631 tree->last_child = curr_item;
3635 /*** insert to_move after fixed ***/
3636 item_to_move->next = fixed_item->next;
3637 fixed_item->next = item_to_move;
3638 if(tree->last_child == fixed_item) {
3639 tree->last_child = item_to_move;
3644 proto_tree_set_appendix(proto_tree *tree, tvbuff_t *tvb, gint start, gint length)
3651 fi = PTREE_FINFO(tree);
3655 start += TVB_RAW_OFFSET(tvb);
3656 DISSECTOR_ASSERT(start >= 0);
3657 DISSECTOR_ASSERT(length >= 0);
3659 fi->appendix_start = start;
3660 fi->appendix_length = length;
3664 proto_register_protocol(const char *name, const char *short_name, const char *filter_name)
3666 protocol_t *protocol;
3667 header_field_info *hfinfo;
3669 char *existing_name;
3673 gboolean found_invalid;
3676 * Make sure there's not already a protocol with any of those
3677 * names. Crash if there is, as that's an error in the code
3678 * or an inappropriate plugin.
3679 * This situation has to be fixed to not register more than one
3680 * protocol with the same name.
3682 * This is done by reducing the number of strcmp (and alike) calls as much as possible,
3683 * as this significally slows down startup time.
3685 * Drawback: As a hash value is used to reduce insert time,
3686 * this might lead to a hash collision.
3687 * However, as we have around 500+ protocols and we're using a 32 bit int this is very,
3691 key = g_malloc (sizeof(gint));
3692 *key = wrs_str_hash(name);
3693 existing_name = g_hash_table_lookup(proto_names, key);
3694 if (existing_name != NULL) {
3695 /* g_error will terminate the program */
3696 g_error("Duplicate protocol name \"%s\"!"
3697 " This might be caused by an inappropriate plugin or a development error.", name);
3699 g_hash_table_insert(proto_names, key, (gpointer)name);
3701 existing_name = g_hash_table_lookup(proto_short_names, (gpointer)short_name);
3702 if (existing_name != NULL) {
3703 g_error("Duplicate protocol short_name \"%s\"!"
3704 " This might be caused by an inappropriate plugin or a development error.", short_name);
3706 g_hash_table_insert(proto_short_names, (gpointer)short_name, (gpointer)short_name);
3708 found_invalid = FALSE;
3709 for (i = 0; i < strlen(filter_name); i++) {
3711 if (!(islower(c) || isdigit(c) || c == '-' || c == '_' || c == '.')) {
3712 found_invalid = TRUE;
3715 if (found_invalid) {
3716 g_error("Protocol filter name \"%s\" has one or more invalid characters."
3717 " Allowed are lower characters, digits, '-', '_' and '.'."
3718 " This might be caused by an inappropriate plugin or a development error.", filter_name);
3720 existing_name = g_hash_table_lookup(proto_filter_names, (gpointer)filter_name);
3721 if (existing_name != NULL) {
3722 g_error("Duplicate protocol filter_name \"%s\"!"
3723 " This might be caused by an inappropriate plugin or a development error.", filter_name);
3725 g_hash_table_insert(proto_filter_names, (gpointer)filter_name, (gpointer)filter_name);
3727 /* Add this protocol to the list of known protocols; the list
3728 is sorted by protocol short name. */
3729 protocol = g_malloc(sizeof (protocol_t));
3730 protocol->name = name;
3731 protocol->short_name = short_name;
3732 protocol->filter_name = filter_name;
3733 protocol->fields = NULL;
3734 protocol->is_enabled = TRUE; /* protocol is enabled by default */
3735 protocol->can_toggle = TRUE;
3736 protocol->is_private = FALSE;
3737 /* list will be sorted later by name, when all protocols completed registering */
3738 protocols = g_list_prepend(protocols, protocol);
3740 /* Here we do allocate a new header_field_info struct */
3741 hfinfo = g_mem_chunk_alloc(gmc_hfinfo);
3742 hfinfo->name = name;
3743 hfinfo->abbrev = filter_name;
3744 hfinfo->type = FT_PROTOCOL;
3745 hfinfo->display = BASE_NONE;
3746 hfinfo->strings = protocol;
3747 hfinfo->bitmask = 0;
3748 hfinfo->bitshift = 0;
3749 hfinfo->ref_count = HF_REF_TYPE_NONE;
3750 hfinfo->blurb = NULL;
3751 hfinfo->parent = -1; /* this field differentiates protos and fields */
3753 proto_id = proto_register_field_init(hfinfo, hfinfo->parent);
3754 protocol->proto_id = proto_id;
3759 proto_mark_private(int proto_id)
3761 protocol_t *protocol = find_protocol_by_id(proto_id);
3763 protocol->is_private = TRUE;
3767 proto_is_private(int proto_id)
3769 protocol_t *protocol = find_protocol_by_id(proto_id);
3771 return protocol->is_private;
3777 * Routines to use to iterate over the protocols.
3778 * The argument passed to the iterator routines is an opaque cookie to
3779 * their callers; it's the GList pointer for the current element in
3781 * The ID of the protocol is returned, or -1 if there is no protocol.
3784 proto_get_first_protocol(void **cookie)
3786 protocol_t *protocol;
3788 if (protocols == NULL)
3790 *cookie = protocols;
3791 protocol = protocols->data;
3792 return protocol->proto_id;
3796 proto_get_next_protocol(void **cookie)
3798 GList *list_item = *cookie;
3799 protocol_t *protocol;
3801 list_item = g_list_next(list_item);
3802 if (list_item == NULL)
3804 *cookie = list_item;
3805 protocol = list_item->data;
3806 return protocol->proto_id;
3810 proto_get_first_protocol_field(int proto_id, void **cookie)
3812 protocol_t *protocol = find_protocol_by_id(proto_id);
3813 hf_register_info *ptr;
3815 if ((protocol == NULL) || (protocol->fields == NULL))
3818 *cookie = protocol->fields;
3819 ptr = protocol->fields->data;
3820 return &ptr->hfinfo;
3824 proto_get_next_protocol_field(void **cookie)
3826 GList *list_item = *cookie;
3827 hf_register_info *ptr;
3829 list_item = g_list_next(list_item);
3830 if (list_item == NULL)
3833 *cookie = list_item;
3834 ptr = list_item->data;
3835 return &ptr->hfinfo;
3839 find_protocol_by_id(int proto_id)
3841 header_field_info *hfinfo;
3846 PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
3847 DISSECTOR_ASSERT(hfinfo->type==FT_PROTOCOL);
3848 return (protocol_t *)hfinfo->strings;
3851 static gint compare_filter_name(gconstpointer proto_arg,
3852 gconstpointer filter_name)
3854 const protocol_t *protocol = proto_arg;
3855 const gchar* f_name = filter_name;
3857 return (strcmp(protocol->filter_name, f_name));
3861 proto_get_id(protocol_t *protocol)
3863 return protocol->proto_id;
3866 int proto_get_id_by_filter_name(const gchar* filter_name)
3869 protocol_t *protocol;
3871 list_entry = g_list_find_custom(protocols, filter_name,
3872 compare_filter_name);
3874 if (list_entry == NULL)
3876 protocol = list_entry->data;
3877 return protocol->proto_id;
3881 proto_get_protocol_name(int proto_id)
3883 protocol_t *protocol;
3885 protocol = find_protocol_by_id(proto_id);
3886 return protocol->name;
3890 proto_get_protocol_short_name(protocol_t *protocol)
3892 if (protocol == NULL)
3894 return protocol->short_name;
3898 proto_get_protocol_long_name(protocol_t *protocol)
3900 if (protocol == NULL)
3902 return protocol->name;
3906 proto_get_protocol_filter_name(int proto_id)
3908 protocol_t *protocol;
3910 protocol = find_protocol_by_id(proto_id);
3911 if (protocol == NULL)
3913 return protocol->filter_name;
3917 proto_is_protocol_enabled(protocol_t *protocol)
3919 return protocol->is_enabled;
3923 proto_can_toggle_protocol(int proto_id)
3925 protocol_t *protocol;
3927 protocol = find_protocol_by_id(proto_id);
3928 return protocol->can_toggle;
3932 proto_set_decoding(int proto_id, gboolean enabled)
3934 protocol_t *protocol;
3936 protocol = find_protocol_by_id(proto_id);
3937 DISSECTOR_ASSERT(protocol->can_toggle);
3938 protocol->is_enabled = enabled;
3942 proto_enable_all(void)
3944 protocol_t *protocol;
3945 GList *list_item = protocols;
3947 if (protocols == NULL)
3951 protocol = list_item->data;
3952 if (protocol->can_toggle)
3953 protocol->is_enabled = TRUE;
3954 list_item = g_list_next(list_item);
3959 proto_set_cant_toggle(int proto_id)
3961 protocol_t *protocol;
3963 protocol = find_protocol_by_id(proto_id);
3964 protocol->can_toggle = FALSE;
3967 /* for use with static arrays only, since we don't allocate our own copies
3968 of the header_field_info struct contained within the hf_register_info struct */
3970 proto_register_field_array(int parent, hf_register_info *hf, int num_records)
3973 hf_register_info *ptr = hf;
3976 proto = find_protocol_by_id(parent);
3977 for (i = 0; i < num_records; i++, ptr++) {
3979 * Make sure we haven't registered this yet.
3980 * Most fields have variables associated with them
3981 * that are initialized to -1; some have array elements,
3982 * or possibly uninitialized variables, so we also allow
3983 * 0 (which is unlikely to be the field ID we get back
3984 * from "proto_register_field_init()").
3986 if (*ptr->p_id != -1 && *ptr->p_id != 0) {
3988 "Duplicate field detected in call to proto_register_field_array: %s is already registered\n",
3989 ptr->hfinfo.abbrev);
3993 if (proto != NULL) {
3994 if (proto->fields == NULL) {
3995 proto->fields = g_list_append(NULL, ptr);
3996 proto->last_field = proto->fields;
3999 g_list_append(proto->last_field, ptr)->next;
4002 field_id = proto_register_field_init(&ptr->hfinfo, parent);
4003 *ptr->p_id = field_id;
4007 /* chars allowed in field abbrev */
4009 const guchar fld_abbrev_chars[256] = {
4010 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00-0x0F */
4011 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10-0x1F */
4012 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, /* 0x20-0x2F '-', '.' */
4013 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 0x30-0x3F '0'-'9' */
4014 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x40-0x4F 'A'-'O' */
4015 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 0x50-0x5F 'P'-'Z', '_' */
4016 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x60-0x6F 'a'-'o' */
4017 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 0x70-0x7F 'p'-'z' */
4018 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80-0x8F */
4019 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90-0x9F */
4020 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xA0-0xAF */
4021 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xB0-0xBF */
4022 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xC0-0xCF */
4023 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xD0-0xDF */
4024 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xE0-0xEF */
4025 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xF0-0xFF */
4028 /* temporary function containing assert part for easier profiling */
4029 static void tmp_fld_check_assert(header_field_info *hfinfo) {
4030 /* The field must have a name (with length > 0) */
4031 DISSECTOR_ASSERT(hfinfo->name && hfinfo->name[0]);
4033 /* fields with an empty string for an abbreviation aren't filterable */
4034 DISSECTOR_ASSERT(hfinfo->abbrev);
4036 /* These types of fields are allowed to have value_strings, true_false_strings or a protocol_t struct*/
4037 DISSECTOR_ASSERT((hfinfo->strings == NULL) || (
4038 (hfinfo->type == FT_UINT8) ||
4039 (hfinfo->type == FT_UINT16) ||
4040 (hfinfo->type == FT_UINT24) ||
4041 (hfinfo->type == FT_UINT32) ||
4042 (hfinfo->type == FT_INT8) ||
4043 (hfinfo->type == FT_INT16) ||
4044 (hfinfo->type == FT_INT24) ||
4045 (hfinfo->type == FT_INT32) ||
4046 (hfinfo->type == FT_BOOLEAN) ||
4047 (hfinfo->type == FT_PROTOCOL) ||
4048 (hfinfo->type == FT_FRAMENUM) ));
4050 switch (hfinfo->type) {
4057 /* Hexadecimal and octal are, in printf() and everywhere else,
4058 * unsigned so don't allow dissectors to register a signed
4059 * field to be displayed unsigned. (Else how would we
4060 * display values negative values?)
4062 * If you want to take out this check, be sure to fix
4063 * hfinfo_numeric_format() so that it does not assert out
4064 * when trying to construct a hexadecimal representation of
4067 DISSECTOR_ASSERT(hfinfo->display != BASE_HEX &&
4068 hfinfo->display != BASE_HEX_DEC &&
4069 hfinfo->display != BASE_DEC_HEX &&
4070 hfinfo->display != BASE_OCT);
4076 if (hfinfo->strings == NULL) {
4077 /* Require integral types (other than frame number, which is
4078 always displayed in decimal) to have a number base */
4079 DISSECTOR_ASSERT(hfinfo->display != BASE_NONE);
4084 DISSECTOR_ASSERT(hfinfo->display != BASE_NONE);
4091 /* Don't allow bitfields or value strings for frame numbers and strings */
4092 DISSECTOR_ASSERT(hfinfo->bitmask == 0);
4093 DISSECTOR_ASSERT(hfinfo->strings == NULL);
4102 proto_register_field_init(header_field_info *hfinfo, int parent)
4105 tmp_fld_check_assert(hfinfo);
4107 /* if this is a bitfield, compute bitshift */
4108 if (hfinfo->bitmask) {
4109 hfinfo->bitshift = wrs_count_bitshift(hfinfo->bitmask);
4112 hfinfo->parent = parent;
4113 hfinfo->same_name_next = NULL;
4114 hfinfo->same_name_prev = NULL;
4116 /* if we always add and never delete, then id == len - 1 is correct */
4117 if(gpa_hfinfo.len>=gpa_hfinfo.allocated_len){
4118 if(!gpa_hfinfo.hfi){
4119 gpa_hfinfo.allocated_len=1000;
4120 gpa_hfinfo.hfi=g_malloc(sizeof(header_field_info *)*1000);
4122 gpa_hfinfo.allocated_len+=1000;
4123 gpa_hfinfo.hfi=g_realloc(gpa_hfinfo.hfi, sizeof(header_field_info *)*gpa_hfinfo.allocated_len);
4126 gpa_hfinfo.hfi[gpa_hfinfo.len]=hfinfo;
4128 hfinfo->id = gpa_hfinfo.len - 1;
4130 /* if we have real names, enter this field in the name tree */
4131 if ((hfinfo->name[0] != 0) && (hfinfo->abbrev[0] != 0 )) {
4133 header_field_info *same_name_next_hfinfo;
4136 /* Check that the filter name (abbreviation) is legal;
4137 * it must contain only alphanumerics, '-', "_", and ".". */
4138 c = wrs_check_charset(fld_abbrev_chars, hfinfo->abbrev);
4140 fprintf(stderr, "OOPS: '%c' in '%s'\n", c, hfinfo->abbrev);
4141 DISSECTOR_ASSERT(!c);
4144 /* We allow multiple hfinfo's to be registered under the same
4145 * abbreviation. This was done for X.25, as, depending
4146 * on whether it's modulo-8 or modulo-128 operation,
4147 * some bitfield fields may be in different bits of
4148 * a byte, and we want to be able to refer to that field
4149 * with one name regardless of whether the packets
4150 * are modulo-8 or modulo-128 packets. */
4152 same_name_hfinfo = NULL;
4154 g_tree_insert(gpa_name_tree, (gpointer) (hfinfo->abbrev), hfinfo);
4155 /* GLIB 2.x - if it is already present
4156 * the previous hfinfo with the same name is saved
4157 * to same_name_hfinfo by value destroy callback */
4158 if (same_name_hfinfo) {
4159 /* There's already a field with this name.
4160 * Put it after that field in the list of
4161 * fields with this name, then allow the code
4162 * after this if{} block to replace the old
4163 * hfinfo with the new hfinfo in the GTree. Thus,
4164 * we end up with a linked-list of same-named hfinfo's,
4165 * with the root of the list being the hfinfo in the GTree */
4166 same_name_next_hfinfo =
4167 same_name_hfinfo->same_name_next;
4169 hfinfo->same_name_next = same_name_next_hfinfo;
4170 if (same_name_next_hfinfo)
4171 same_name_next_hfinfo->same_name_prev = hfinfo;
4173 same_name_hfinfo->same_name_next = hfinfo;
4174 hfinfo->same_name_prev = same_name_hfinfo;
4182 proto_register_subtree_array(gint *const *indices, int num_indices)
4185 gint *const *ptr = indices;
4188 * If we've already allocated the array of tree types, expand
4189 * it; this lets plugins such as mate add tree types after
4190 * the initial startup. (If we haven't already allocated it,
4191 * we don't allocate it; on the first pass, we just assign
4192 * ett values and keep track of how many we've assigned, and
4193 * when we're finished registering all dissectors we allocate
4194 * the array, so that we do only one allocation rather than
4195 * wasting CPU time and memory by growing the array for each
4196 * dissector that registers ett values.)
4198 if (tree_is_expanded != NULL) {
4200 g_realloc(tree_is_expanded,
4201 (num_tree_types+num_indices)*sizeof (gboolean));
4202 memset(tree_is_expanded + num_tree_types, 0,
4203 num_indices*sizeof (gboolean));
4207 * Assign "num_indices" subtree numbers starting at "num_tree_types",
4208 * returning the indices through the pointers in the array whose
4209 * first element is pointed to by "indices", and update
4210 * "num_tree_types" appropriately.
4212 for (i = 0; i < num_indices; i++, ptr++, num_tree_types++) {
4214 /* g_error will terminate the program */
4215 g_error("register_subtree_array: subtree item type (ett_...) not -1 !"
4216 " This is a development error:"
4217 " Either the subtree item type has already been assigned or"
4218 " was not initialized to -1.");
4220 **ptr = num_tree_types;
4225 proto_item_fill_label(field_info *fi, gchar *label_str)
4227 header_field_info *hfinfo;
4233 guint32 n_addr; /* network-order IPv4 address */
4235 int ret; /*tmp return value */
4240 /* XXX: Check validity of hfinfo->type */
4244 hfinfo = fi->hfinfo;
4246 switch(hfinfo->type) {
4249 g_strlcpy(label_str, hfinfo->name, ITEM_LABEL_LENGTH);
4253 fill_label_boolean(fi, label_str);
4258 bytes = fvalue_get(&fi->value);
4260 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4261 "%s: %s", hfinfo->name,
4262 bytes_to_str(bytes, fvalue_length(&fi->value)));
4263 if (ret >= ITEM_LABEL_LENGTH) {
4264 /* Uh oh, we don't have enough room. Tell the
4265 * user that the field is truncated.
4267 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4268 "%s [truncated]: %s",
4270 bytes_to_str(bytes, fvalue_length(&fi->value)));
4274 g_snprintf(label_str, ITEM_LABEL_LENGTH, "%s: <MISSING>", hfinfo->name);
4278 /* Four types of integers to take care of:
4279 * Bitfield, with val_string
4280 * Bitfield, w/o val_string
4281 * Non-bitfield, with val_string
4282 * Non-bitfield, w/o val_string
4288 if (hfinfo->bitmask) {
4289 fill_label_bitfield(fi, label_str);
4291 fill_label_uint(fi, label_str);
4296 fill_label_uint(fi, label_str);
4300 fill_label_uint64(fi, label_str);
4307 DISSECTOR_ASSERT(!hfinfo->bitmask);
4308 fill_label_int(fi, label_str);
4312 fill_label_int64(fi, label_str);
4316 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4317 "%s: %." STRINGIFY(FLT_DIG) "f",
4318 hfinfo->name, fvalue_get_floating(&fi->value));
4322 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4323 "%s: %." STRINGIFY(DBL_DIG) "g",
4324 hfinfo->name, fvalue_get_floating(&fi->value));
4327 case FT_ABSOLUTE_TIME:
4328 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4329 "%s: %s", hfinfo->name,
4330 abs_time_to_str(fvalue_get(&fi->value)));
4333 case FT_RELATIVE_TIME:
4334 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4335 "%s: %s seconds", hfinfo->name,
4336 rel_time_to_secs_str(fvalue_get(&fi->value)));
4340 integer = fvalue_get_uinteger(&fi->value);
4341 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4342 "%s: %s (0x%08X)", hfinfo->name,
4343 get_ipxnet_name(integer), integer);
4347 bytes = fvalue_get(&fi->value);
4348 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4349 "%s: %s (%s)", hfinfo->name,
4350 get_ether_name(bytes),
4351 ether_to_str(bytes));
4355 ipv4 = fvalue_get(&fi->value);
4356 n_addr = ipv4_get_net_order_addr(ipv4);
4357 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4358 "%s: %s (%s)", hfinfo->name,
4359 get_hostname(n_addr),
4360 ip_to_str((guint8*)&n_addr));
4364 bytes = fvalue_get(&fi->value);
4365 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4366 "%s: %s (%s)", hfinfo->name,
4367 get_hostname6((struct e_in6_addr *)bytes),
4368 ip6_to_str((struct e_in6_addr*)bytes));
4372 guid = fvalue_get(&fi->value);
4373 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4374 "%s: %s", hfinfo->name,
4379 bytes = fvalue_get(&fi->value);
4380 name = oid_resolved_from_encoded(bytes, fvalue_length(&fi->value));
4382 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4383 "%s: %s (%s)", hfinfo->name,
4384 oid_encoded2string(bytes, fvalue_length(&fi->value)), name);
4386 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4387 "%s: %s", hfinfo->name,
4388 oid_encoded2string(bytes, fvalue_length(&fi->value)));
4395 case FT_UINT_STRING:
4396 bytes = fvalue_get(&fi->value);
4397 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4398 "%s: %s", hfinfo->name,
4399 format_text(bytes, strlen(bytes)));
4400 if (ret >= ITEM_LABEL_LENGTH) {
4401 /* Uh oh, we don't have enough room. Tell the
4402 * user that the field is truncated.
4404 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4405 "%s [truncated]: %s",
4407 format_text(bytes, strlen(bytes)));
4412 g_error("hfinfo->type %d (%s) not handled\n",
4414 ftype_name(hfinfo->type));
4415 DISSECTOR_ASSERT_NOT_REACHED();
4421 fill_label_boolean(field_info *fi, gchar *label_str)
4423 char *p = label_str;
4424 int bitfield_byte_length = 0, bitwidth;
4425 guint32 unshifted_value;
4428 header_field_info *hfinfo = fi->hfinfo;
4429 const true_false_string *tfstring = (const true_false_string *)&tfs_true_false;
4431 if (hfinfo->strings) {
4432 tfstring = (const struct true_false_string*) hfinfo->strings;
4435 value = fvalue_get_uinteger(&fi->value);
4436 if (hfinfo->bitmask) {
4437 /* Figure out the bit width */
4438 bitwidth = hfinfo_bitwidth(hfinfo);
4441 unshifted_value = value;
4442 if (hfinfo->bitshift > 0) {
4443 unshifted_value <<= hfinfo->bitshift;
4446 /* Create the bitfield first */
4447 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
4448 bitfield_byte_length = (int) (p - label_str);
4451 /* Fill in the textual info */
4452 g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
4453 "%s: %s", hfinfo->name,
4454 value ? tfstring->true_string : tfstring->false_string);
4457 /* Fills data for bitfield ints with val_strings */
4459 fill_label_bitfield(field_info *fi, gchar *label_str)
4461 const char *format = NULL;
4463 int bitfield_byte_length, bitwidth;
4464 guint32 unshifted_value;
4467 header_field_info *hfinfo = fi->hfinfo;
4469 /* Figure out the bit width */
4470 bitwidth = hfinfo_bitwidth(hfinfo);
4473 unshifted_value = fvalue_get_uinteger(&fi->value);
4474 value = unshifted_value;
4475 if (hfinfo->bitshift > 0) {
4476 unshifted_value <<= hfinfo->bitshift;
4479 /* Create the bitfield first */
4480 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
4481 bitfield_byte_length = (int) (p - label_str);
4483 /* Fill in the textual info using stored (shifted) value */
4484 if (hfinfo->display == BASE_CUSTOM) {
4485 gchar tmp[ITEM_LABEL_LENGTH];
4486 custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hfinfo->strings;
4488 DISSECTOR_ASSERT(fmtfunc);
4489 fmtfunc(tmp, value);
4490 g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
4491 "%s: %s", hfinfo->name, tmp);
4493 else if (hfinfo->strings) {
4494 format = hfinfo_uint_vals_format(hfinfo);
4495 if (hfinfo->display & BASE_RANGE_STRING) {
4496 g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
4497 format, hfinfo->name,
4498 rval_to_str(value, hfinfo->strings, "Unknown"), value);
4500 g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
4501 format, hfinfo->name,
4502 val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
4506 format = hfinfo_uint_format(hfinfo);
4507 if (IS_BASE_DUAL(hfinfo->display)) {
4508 g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
4509 format, hfinfo->name, value, value);
4511 g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
4512 format, hfinfo->name, value);
4518 fill_label_uint(field_info *fi, gchar *label_str)
4520 const char *format = NULL;
4521 header_field_info *hfinfo = fi->hfinfo;
4524 value = fvalue_get_uinteger(&fi->value);
4526 /* Fill in the textual info */
4527 if (hfinfo->display == BASE_CUSTOM) {
4528 gchar tmp[ITEM_LABEL_LENGTH];
4529 custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hfinfo->strings;
4531 DISSECTOR_ASSERT(fmtfunc);
4532 fmtfunc(tmp, value);
4533 g_snprintf(label_str, ITEM_LABEL_LENGTH, "%s: %s", hfinfo->name, tmp);
4535 else if (hfinfo->strings) {
4536 format = hfinfo_uint_vals_format(hfinfo);
4537 if (hfinfo->display & BASE_RANGE_STRING) {
4538 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4539 format, hfinfo->name,
4540 rval_to_str(value, hfinfo->strings, "Unknown"), value);
4542 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4543 format, hfinfo->name,
4544 val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
4548 format = hfinfo_uint_format(hfinfo);
4549 if (IS_BASE_DUAL(hfinfo->display)) {
4550 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4551 format, hfinfo->name, value, value);
4553 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4554 format, hfinfo->name, value);
4560 fill_label_uint64(field_info *fi, gchar *label_str)
4562 const char *format = NULL;
4563 header_field_info *hfinfo = fi->hfinfo;
4566 /* Pick the proper format string */
4567 format = hfinfo_uint64_format(hfinfo);
4568 value = fvalue_get_integer64(&fi->value);
4570 /* Fill in the textual info */
4571 if (IS_BASE_DUAL(hfinfo->display)) {
4572 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4573 format, hfinfo->name, value, value);
4575 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4576 format, hfinfo->name, value);
4581 fill_label_int(field_info *fi, gchar *label_str)
4583 const char *format = NULL;
4584 header_field_info *hfinfo = fi->hfinfo;
4587 value = fvalue_get_sinteger(&fi->value);
4589 /* Fill in the textual info */
4590 if (hfinfo->display == BASE_CUSTOM) {
4591 gchar tmp[ITEM_LABEL_LENGTH];
4592 custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hfinfo->strings;
4594 DISSECTOR_ASSERT(fmtfunc);
4595 fmtfunc(tmp, value);
4596 g_snprintf(label_str, ITEM_LABEL_LENGTH, "%s: %s", hfinfo->name, tmp);
4598 else if (hfinfo->strings) {
4599 format = hfinfo_int_vals_format(hfinfo);
4600 if (hfinfo->display & BASE_RANGE_STRING) {
4601 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4602 format, hfinfo->name,
4603 rval_to_str(value, hfinfo->strings, "Unknown"), value);
4605 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4606 format, hfinfo->name,
4607 val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
4611 format = hfinfo_int_format(hfinfo);
4612 if (IS_BASE_DUAL(hfinfo->display)) {
4613 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4614 format, hfinfo->name, value, value);
4616 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4617 format, hfinfo->name, value);
4623 fill_label_int64(field_info *fi, gchar *label_str)
4625 const char *format = NULL;
4626 header_field_info *hfinfo = fi->hfinfo;
4629 /* Pick the proper format string */
4630 format = hfinfo_int64_format(hfinfo);
4631 value = fvalue_get_integer64(&fi->value);
4633 /* Fill in the textual info */
4634 if (IS_BASE_DUAL(hfinfo->display)) {
4635 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4636 format, hfinfo->name, value, value);
4638 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4639 format, hfinfo->name, value);
4644 hfinfo_bitwidth(header_field_info *hfinfo)
4648 if (!hfinfo->bitmask) {
4652 switch(hfinfo->type) {
4670 bitwidth = hfinfo->display; /* hacky? :) */
4673 DISSECTOR_ASSERT_NOT_REACHED();
4680 hfinfo_uint_vals_format(header_field_info *hfinfo)
4682 const char *format = NULL;
4684 /* bit operation to reset the potential BASE_RANGE_STRING (or others in
4686 switch(hfinfo->display & BASE_STRUCTURE_RESET) {
4692 format = "%s: %s (%u)";
4694 case BASE_OCT: /* I'm lazy */
4695 format = "%s: %s (%o)";
4699 switch(hfinfo->type) {
4701 format = "%s: %s (0x%02x)";
4704 format = "%s: %s (0x%04x)";
4707 format = "%s: %s (0x%06x)";
4710 format = "%s: %s (0x%08x)";
4713 DISSECTOR_ASSERT_NOT_REACHED();
4718 DISSECTOR_ASSERT_NOT_REACHED();
4725 hfinfo_uint_format(header_field_info *hfinfo)
4727 const char *format = NULL;
4729 /* Pick the proper format string */
4730 if (hfinfo->type == FT_FRAMENUM) {
4732 * Frame numbers are always displayed in decimal.
4736 switch(hfinfo->display) {
4741 switch(hfinfo->type) {
4743 format = "%s: %u (0x%02x)";
4746 format = "%s: %u (0x%04x)";
4749 format = "%s: %u (0x%06x)";
4752 format = "%s: %u (0x%08x)";
4755 DISSECTOR_ASSERT_NOT_REACHED();
4759 case BASE_OCT: /* I'm lazy */
4763 switch(hfinfo->type) {
4765 format = "%s: 0x%02x";
4768 format = "%s: 0x%04x";
4771 format = "%s: 0x%06x";
4774 format = "%s: 0x%08x";
4777 DISSECTOR_ASSERT_NOT_REACHED();
4782 switch(hfinfo->type) {
4784 format = "%s: 0x%02x (%u)";
4787 format = "%s: 0x%04x (%u)";
4790 format = "%s: 0x%06x (%u)";
4793 format = "%s: 0x%08x (%u)";
4796 DISSECTOR_ASSERT_NOT_REACHED();
4801 DISSECTOR_ASSERT_NOT_REACHED();
4809 hfinfo_uint_value_format(header_field_info *hfinfo)
4811 const char *format = NULL;
4813 /* Pick the proper format string */
4814 if (hfinfo->type == FT_FRAMENUM) {
4816 * Frame numbers are always displayed in decimal.
4820 switch(hfinfo->display) {
4825 switch(hfinfo->type) {
4827 format = "%u (0x%02x)";
4830 format = "%u (0x%04x)";
4833 format = "%u (0x%06x)";
4836 format = "%u (0x%08x)";
4839 DISSECTOR_ASSERT_NOT_REACHED();
4847 switch(hfinfo->type) {
4861 DISSECTOR_ASSERT_NOT_REACHED();
4866 switch(hfinfo->type) {
4868 format = "0x%02x (%u)";
4871 format = "0x%04x (%u)";
4874 format = "0x%06x (%u)";
4877 format = "0x%08x (%u)";
4880 DISSECTOR_ASSERT_NOT_REACHED();
4885 DISSECTOR_ASSERT_NOT_REACHED();
4893 hfinfo_int_vals_format(header_field_info *hfinfo)
4895 const char *format = NULL;
4897 /* bit operation to reset the potential BASE_RANGE_STRING (or others in
4899 switch(hfinfo->display & BASE_STRUCTURE_RESET) {
4905 format = "%s: %s (%d)";
4907 case BASE_OCT: /* I'm lazy */
4908 format = "%s: %s (%o)";
4912 switch(hfinfo->type) {
4914 format = "%s: %s (0x%02x)";
4917 format = "%s: %s (0x%04x)";
4920 format = "%s: %s (0x%06x)";
4923 format = "%s: %s (0x%08x)";
4926 DISSECTOR_ASSERT_NOT_REACHED();
4931 DISSECTOR_ASSERT_NOT_REACHED();
4938 hfinfo_uint64_format(header_field_info *hfinfo)
4940 const char *format = NULL;
4942 /* Pick the proper format string */
4943 switch(hfinfo->display) {
4945 format = "%s: %" G_GINT64_MODIFIER "u";
4948 format = "%s: %" G_GINT64_MODIFIER "u (%" G_GINT64_MODIFIER "x)";
4950 case BASE_OCT: /* I'm lazy */
4951 format = "%s: %" G_GINT64_MODIFIER "o";
4954 format = "%s: 0x%016" G_GINT64_MODIFIER "x";
4957 format = "%s: 0x%016" G_GINT64_MODIFIER "x (%" G_GINT64_MODIFIER "u)";
4960 DISSECTOR_ASSERT_NOT_REACHED();
4967 hfinfo_int_format(header_field_info *hfinfo)
4969 const char *format = NULL;
4971 /* Pick the proper format string */
4972 switch(hfinfo->display) {
4977 switch(hfinfo->type) {
4979 format = "%s: %d (0x%02x)";
4982 format = "%s: %d (0x%04x)";
4985 format = "%s: %d (0x%06x)";
4988 format = "%s: %d (0x%08x)";
4991 DISSECTOR_ASSERT_NOT_REACHED();
4995 case BASE_OCT: /* I'm lazy */
4999 switch(hfinfo->type) {
5001 format = "%s: 0x%02x";
5004 format = "%s: 0x%04x";
5007 format = "%s: 0x%06x";
5010 format = "%s: 0x%08x";
5013 DISSECTOR_ASSERT_NOT_REACHED();
5018 switch(hfinfo->type) {
5020 format = "%s: 0x%02x (%d)";
5023 format = "%s: 0x%04x (%d)";
5026 format = "%s: 0x%06x (%d)";
5029 format = "%s: 0x%08x (%d)";
5032 DISSECTOR_ASSERT_NOT_REACHED();
5037 DISSECTOR_ASSERT_NOT_REACHED();
5044 hfinfo_int_value_format(header_field_info *hfinfo)
5046 const char *format = NULL;
5048 /* Pick the proper format string */
5049 switch(hfinfo->display) {
5054 switch(hfinfo->type) {
5056 format = "%d (0x%02x)";
5059 format = "%d (0x%04x)";
5062 format = "%d (0x%06x)";
5065 format = "%d (0x%08x)";
5068 DISSECTOR_ASSERT_NOT_REACHED();
5076 switch(hfinfo->type) {
5090 DISSECTOR_ASSERT_NOT_REACHED();
5095 switch(hfinfo->type) {
5097 format = "0x%02x (%d)";
5100 format = "0x%04x (%d)";
5103 format = "0x%06x (%d)";
5106 format = "0x%08x (%d)";
5109 DISSECTOR_ASSERT_NOT_REACHED();
5114 DISSECTOR_ASSERT_NOT_REACHED();
5121 hfinfo_int64_format(header_field_info *hfinfo)
5123 const char *format = NULL;
5125 /* Pick the proper format string */
5126 switch(hfinfo->display) {
5128 format = "%s: %" G_GINT64_MODIFIER "d";
5131 format = "%s: %" G_GINT64_MODIFIER "d (%" G_GINT64_MODIFIER "x)";
5133 case BASE_OCT: /* I'm lazy */
5134 format = "%s: %" G_GINT64_MODIFIER "o";
5137 format = "%s: 0x%016" G_GINT64_MODIFIER "x";
5140 format = "%s: 0x%016" G_GINT64_MODIFIER "x (%" G_GINT64_MODIFIER "d)";
5143 DISSECTOR_ASSERT_NOT_REACHED();
5152 proto_registrar_n(void)
5154 return gpa_hfinfo.len;
5158 proto_registrar_get_name(int n)
5160 header_field_info *hfinfo;
5162 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
5163 return hfinfo->name;
5167 proto_registrar_get_abbrev(int n)
5169 header_field_info *hfinfo;
5171 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
5172 return hfinfo->abbrev;
5176 proto_registrar_get_ftype(int n)
5178 header_field_info *hfinfo;
5180 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
5181 return hfinfo->type;
5185 proto_registrar_get_parent(int n)
5187 header_field_info *hfinfo;
5189 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
5190 return hfinfo->parent;
5194 proto_registrar_is_protocol(int n)
5196 header_field_info *hfinfo;
5198 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
5199 return (hfinfo->parent == -1 ? TRUE : FALSE);
5202 /* Returns length of field in packet (not necessarily the length
5203 * in our internal representation, as in the case of IPv4).
5204 * 0 means undeterminable at time of registration
5205 * -1 means the field is not registered. */
5207 proto_registrar_get_length(int n)
5209 header_field_info *hfinfo;
5211 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
5212 return ftype_length(hfinfo->type);
5217 /* Looks for a protocol or a field in a proto_tree. Returns TRUE if
5218 * it exists anywhere, or FALSE if it exists nowhere. */
5220 proto_check_for_protocol_or_field(proto_tree* tree, int id)
5222 GPtrArray *ptrs = proto_get_finfo_ptr_array(tree, id);
5227 else if (g_ptr_array_len(ptrs) > 0) {
5235 /* Return GPtrArray* of field_info pointers for all hfindex that appear in tree.
5236 * This only works if the hfindex was "primed" before the dissection
5237 * took place, as we just pass back the already-created GPtrArray*.
5238 * The caller should *not* free the GPtrArray*; proto_tree_free_node()
5241 proto_get_finfo_ptr_array(proto_tree *tree, int id)
5243 if (PTREE_DATA(tree)->interesting_hfids != NULL)
5244 return g_hash_table_lookup(PTREE_DATA(tree)->interesting_hfids,
5245 GINT_TO_POINTER(id));
5251 proto_tracking_interesting_fields(proto_tree *tree)
5253 return (PTREE_DATA(tree)->interesting_hfids != NULL);
5256 /* Helper struct for proto_find_info() and proto_all_finfos() */
5262 /* Helper function for proto_find_info() */
5264 find_finfo(proto_node *node, gpointer data)
5266 field_info *fi = PNODE_FINFO(node);
5267 if (fi && fi->hfinfo) {
5268 if (fi->hfinfo->id == ((ffdata_t*)data)->id) {
5269 g_ptr_array_add(((ffdata_t*)data)->array, fi);
5273 /* Don't stop traversing. */
5277 /* Return GPtrArray* of field_info pointers for all hfindex that appear in a tree.
5278 * This works on any proto_tree, primed or unprimed, but actually searches
5279 * the tree, so it is slower than using proto_get_finfo_ptr_array on a primed tree.
5280 * The caller does need to free the returned GPtrArray with
5281 * g_ptr_array_free(<array>, FALSE).
5284 proto_find_finfo(proto_tree *tree, int id)
5288 ffdata.array = g_ptr_array_new();
5291 proto_tree_traverse_pre_order(tree, find_finfo, &ffdata);
5293 return ffdata.array;
5296 /* Helper function for proto_all_finfos() */
5298 every_finfo(proto_node *node, gpointer data)
5300 field_info *fi = PNODE_FINFO(node);
5301 if (fi && fi->hfinfo) {
5302 g_ptr_array_add(((ffdata_t*)data)->array, fi);
5305 /* Don't stop traversing. */
5309 /* Return GPtrArray* of field_info pointers containing all hfindexes that appear in a tree. */
5311 proto_all_finfos(proto_tree *tree)
5315 ffdata.array = g_ptr_array_new();
5318 proto_tree_traverse_pre_order(tree, every_finfo, &ffdata);
5320 return ffdata.array;
5331 check_for_offset(proto_node *node, gpointer data)
5333 field_info *fi = PNODE_FINFO(node);
5334 offset_search_t *offsearch = data;
5336 /* !fi == the top most container node which holds nothing */
5337 if (fi && !PROTO_ITEM_IS_HIDDEN(node) && fi->ds_tvb && offsearch->tvb == fi->ds_tvb) {
5338 if (offsearch->offset >= (guint) fi->start &&
5339 offsearch->offset < (guint) (fi->start + fi->length)) {
5341 offsearch->finfo = fi;
5342 return FALSE; /* keep traversing */
5345 return FALSE; /* keep traversing */
5348 /* Search a proto_tree backwards (from leaves to root) looking for the field
5349 * whose start/length occupies 'offset' */
5350 /* XXX - I couldn't find an easy way to search backwards, so I search
5351 * forwards, w/o stopping. Therefore, the last finfo I find will the be
5352 * the one I want to return to the user. This algorithm is inefficient
5353 * and could be re-done, but I'd have to handle all the children and
5354 * siblings of each node myself. When I have more time I'll do that.
5357 proto_find_field_from_offset(proto_tree *tree, guint offset, tvbuff_t *tvb)
5359 offset_search_t offsearch;
5361 offsearch.offset = offset;
5362 offsearch.finfo = NULL;
5363 offsearch.tvb = tvb;
5365 proto_tree_traverse_pre_order(tree, check_for_offset, &offsearch);
5367 return offsearch.finfo;
5370 /* Dumps the protocols in the registration database to stdout. An independent
5371 * program can take this output and format it into nice tables or HTML or
5374 * There is one record per line. The fields are tab-delimited.
5376 * Field 1 = protocol name
5377 * Field 2 = protocol short name
5378 * Field 3 = protocol filter name
5381 proto_registrar_dump_protocols(void)
5383 protocol_t *protocol;
5385 void *cookie = NULL;
5387 for (i = proto_get_first_protocol(&cookie); i != -1;
5388 i = proto_get_next_protocol(&cookie)) {
5389 protocol = find_protocol_by_id(i);
5390 printf("%s\t%s\t%s\n", protocol->name, protocol->short_name,
5391 protocol->filter_name);
5395 /* Dumps the value_strings, range_strings or true/false strings for fields
5396 * that have them. There is one record per line. Fields are tab-delimited.
5397 * There are three types of records: Value String, Range String
5398 * and True/False String. The first field, 'V', 'R' or 'T', indicates
5399 * the type of record.
5404 * Field 2 = field abbreviation to which this value string corresponds
5405 * Field 3 = Integer value
5411 * Field 2 = field abbreviation to which this range string corresponds
5412 * Field 3 = Integer value: lower bound
5413 * Field 4 = Integer value: upper bound
5416 * True/False Strings
5417 * ------------------
5419 * Field 2 = field abbreviation to which this true/false string corresponds
5420 * Field 3 = True String
5421 * Field 4 = False String
5424 proto_registrar_dump_values(void)
5426 header_field_info *hfinfo, *parent_hfinfo;
5428 const value_string *vals;
5429 const range_string *range;
5430 const true_false_string *tfs;
5432 len = gpa_hfinfo.len;
5433 for (i = 0; i < len ; i++) {
5434 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
5436 if (hfinfo->id == hf_text_only) {
5440 /* ignore protocols */
5441 if (proto_registrar_is_protocol(i)) {
5444 /* process header fields */
5447 * If this field isn't at the head of the list of
5448 * fields with this name, skip this field - all
5449 * fields with the same name are really just versions
5450 * of the same field stored in different bits, and
5451 * should have the same type/radix/value list, and
5452 * just differ in their bit masks. (If a field isn't
5453 * a bitfield, but can be, say, 1 or 2 bytes long,
5454 * it can just be made FT_UINT16, meaning the
5455 * *maximum* length is 2 bytes, and be used
5458 if (hfinfo->same_name_prev != NULL)
5461 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
5467 if ((hfinfo->display & BASE_STRUCTURE_RESET) != BASE_CUSTOM &&
5468 (hfinfo->type == FT_UINT8 ||
5469 hfinfo->type == FT_UINT16 ||
5470 hfinfo->type == FT_UINT24 ||
5471 hfinfo->type == FT_UINT32 ||
5472 hfinfo->type == FT_UINT64 ||
5473 hfinfo->type == FT_INT8 ||
5474 hfinfo->type == FT_INT16 ||
5475 hfinfo->type == FT_INT24 ||
5476 hfinfo->type == FT_INT32 ||
5477 hfinfo->type == FT_INT64)) {
5479 if ((hfinfo->display & BASE_RANGE_STRING) == 0) {
5480 vals = hfinfo->strings;
5482 range = hfinfo->strings;
5485 else if (hfinfo->type == FT_BOOLEAN) {
5486 tfs = hfinfo->strings;
5489 /* Print value strings? */
5492 while (vals[vi].strptr) {
5493 /* Print in the proper base */
5494 if (hfinfo->display == BASE_HEX) {
5495 printf("V\t%s\t0x%x\t%s\n",
5501 printf("V\t%s\t%u\t%s\n",
5510 /* print range strings? */
5513 while (range[vi].strptr) {
5514 /* Print in the proper base */
5515 if ((hfinfo->display & BASE_STRUCTURE_RESET) == BASE_HEX) {
5516 printf("R\t%s\t0x%x\t0x%x\t%s\n",
5518 range[vi].value_min,
5519 range[vi].value_max,
5523 printf("R\t%s\t%u\t%u\t%s\n",
5525 range[vi].value_min,
5526 range[vi].value_max,
5533 /* Print true/false strings? */
5535 printf("T\t%s\t%s\t%s\n", hfinfo->abbrev,
5536 tfs->true_string, tfs->false_string);
5542 /* Dumps the contents of the registration database to stdout. An independent
5543 * program can take this output and format it into nice tables or HTML or
5546 * There is one record per line. Each record is either a protocol or a header
5547 * field, differentiated by the first field. The fields are tab-delimited.
5552 * Field 2 = descriptive protocol name
5553 * Field 3 = protocol abbreviation
5559 * Field 2 = descriptive field name
5560 * Field 3 = field abbreviation
5561 * Field 4 = type ( textual representation of the the ftenum type )
5562 * Field 5 = parent protocol abbreviation
5563 * Field 6 = blurb describing field
5567 * Field 2 = descriptive field name
5568 * Field 3 = field abbreviation
5569 * Field 4 = type ( textual representation of the the ftenum type )
5570 * Field 5 = parent protocol abbreviation
5571 * Field 6 = blurb describing field
5572 * Field 7 = base for display (for integer types); "parent bitfield width" for FT_BOOLEAN
5573 * Field 8 = blurb describing field (yes, apparently we repeated this accidentally)
5577 * Field 2 = descriptive field name
5578 * Field 3 = field abbreviation
5579 * Field 4 = type ( textual representation of the the ftenum type )
5580 * Field 5 = parent protocol abbreviation
5581 * Field 6 = blurb describing field
5582 * Field 7 = base for display (for integer types); "parent bitfield width" for FT_BOOLEAN
5583 * Field 8 = bitmask: format: hex: 0x....
5587 proto_registrar_dump_fields(int format)
5589 header_field_info *hfinfo, *parent_hfinfo;
5591 const char *enum_name;
5592 const char *base_name;
5596 len = gpa_hfinfo.len;
5597 for (i = 0; i < len ; i++) {
5598 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
5601 * Skip the pseudo-field for "proto_tree_add_text()" since
5602 * we don't want it in the list of filterable fields.
5604 if (hfinfo->id == hf_text_only)
5607 /* format for protocols */
5608 if (proto_registrar_is_protocol(i)) {
5609 printf("P\t%s\t%s\n", hfinfo->name, hfinfo->abbrev);
5611 /* format for header fields */
5614 * If this field isn't at the head of the list of
5615 * fields with this name, skip this field - all
5616 * fields with the same name are really just versions
5617 * of the same field stored in different bits, and
5618 * should have the same type/radix/value list, and
5619 * just differ in their bit masks. (If a field isn't
5620 * a bitfield, but can be, say, 1 or 2 bytes long,
5621 * it can just be made FT_UINT16, meaning the
5622 * *maximum* length is 2 bytes, and be used
5625 if (hfinfo->same_name_prev != NULL)
5628 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
5630 enum_name = ftype_name(hfinfo->type);
5634 if (hfinfo->type == FT_UINT8 ||
5635 hfinfo->type == FT_UINT16 ||
5636 hfinfo->type == FT_UINT24 ||
5637 hfinfo->type == FT_UINT32 ||
5638 hfinfo->type == FT_UINT64 ||
5639 hfinfo->type == FT_INT8 ||
5640 hfinfo->type == FT_INT16 ||
5641 hfinfo->type == FT_INT24 ||
5642 hfinfo->type == FT_INT32 ||
5643 hfinfo->type == FT_INT64) {
5646 switch(hfinfo->display & BASE_STRUCTURE_RESET) {
5648 base_name = "BASE_NONE";
5651 base_name = "BASE_DEC";
5654 base_name = "BASE_HEX";
5657 base_name = "BASE_OCT";
5660 base_name = "BASE_DEC_HEX";
5663 base_name = "BASE_HEX_DEC";
5666 base_name = "BASE_CUSTOM";
5672 } else if (hfinfo->type == FT_BOOLEAN) {
5673 /* For FT_BOOLEAN: 'display' can be "parent bitfield width" */
5674 g_snprintf(width, sizeof(width), "%d", hfinfo->display);
5679 blurb = hfinfo->blurb;
5683 printf("F\t%s\t%s\t%s\t%s\t%s\n",
5684 hfinfo->name, hfinfo->abbrev, enum_name,
5685 parent_hfinfo->abbrev, blurb);
5687 else if (format == 2) {
5688 printf("F\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n",
5689 hfinfo->name, hfinfo->abbrev, enum_name,
5690 parent_hfinfo->abbrev, blurb,
5693 else if (format == 3) {
5694 printf("F\t%s\t%s\t%s\t%s\t%s\t%s\t0x%x\n",
5695 hfinfo->name, hfinfo->abbrev, enum_name,
5696 parent_hfinfo->abbrev, blurb,
5697 base_name, hfinfo->bitmask);
5700 g_assert_not_reached();
5707 hfinfo_numeric_format(header_field_info *hfinfo)
5709 const char *format = NULL;
5711 /* Pick the proper format string */
5712 if (hfinfo->type == FT_FRAMENUM) {
5714 * Frame numbers are always displayed in decimal.
5716 format = "%s == %u";
5718 /* Pick the proper format string, ignoring BASE_RANGE_STRING flag */
5719 switch(hfinfo->display & ~BASE_RANGE_STRING) {
5722 case BASE_OCT: /* I'm lazy */
5724 switch(hfinfo->type) {
5729 format = "%s == %u";
5732 format = "%s == %" G_GINT64_MODIFIER "u";
5738 format = "%s == %d";
5741 format = "%s == %" G_GINT64_MODIFIER "d";
5744 DISSECTOR_ASSERT_NOT_REACHED();
5750 switch(hfinfo->type) {
5752 format = "%s == 0x%02x";
5755 format = "%s == 0x%04x";
5758 format = "%s == 0x%06x";
5761 format = "%s == 0x%08x";
5764 format = "%s == 0x%016" G_GINT64_MODIFIER "x";
5767 DISSECTOR_ASSERT_NOT_REACHED();
5772 DISSECTOR_ASSERT_NOT_REACHED();
5779 /* This function indicates whether it's possible to construct a
5780 * "match selected" display filter string for the specified field,
5781 * returns an indication of whether it's possible, and, if it's
5782 * possible and "filter" is non-null, constructs the filter and
5783 * sets "*filter" to point to it.
5784 * You do not need to [g_]free() this string since it will be automatically
5785 * freed once the next packet is dissected.
5788 construct_match_selected_string(field_info *finfo, epan_dissect_t *edt,
5791 header_field_info *hfinfo;
5797 gint start, length, length_remaining;
5799 gchar is_signed_num = FALSE;
5801 hfinfo = finfo->hfinfo;
5802 DISSECTOR_ASSERT(hfinfo);
5803 abbrev_len = (int) strlen(hfinfo->abbrev);
5805 if (hfinfo->strings && (hfinfo->display & BASE_STRUCTURE_RESET) == BASE_NONE) {
5806 const gchar *str = NULL;
5808 switch(hfinfo->type) {
5814 if (hfinfo->display & BASE_RANGE_STRING) {
5815 str = match_strrval(fvalue_get_sinteger(&finfo->value), hfinfo->strings);
5817 str = match_strval(fvalue_get_sinteger(&finfo->value), hfinfo->strings);
5825 if (hfinfo->display & BASE_RANGE_STRING) {
5826 str = match_strrval(fvalue_get_uinteger(&finfo->value), hfinfo->strings);
5828 str = match_strval(fvalue_get_uinteger(&finfo->value), hfinfo->strings);
5836 if (str != NULL && filter != NULL) {
5837 *filter = ep_strdup_printf("%s == \"%s\"", hfinfo->abbrev, str);
5843 * XXX - we can't use the "val_to_string_repr" and "string_repr_len"
5844 * functions for FT_UINT and FT_INT types, as we choose the base in
5845 * the string expression based on the display base of the field.
5847 * Note that the base does matter, as this is also used for
5848 * the protocolinfo tap.
5850 * It might be nice to use them in "proto_item_fill_label()"
5851 * as well, although, there, you'd have to deal with the base
5852 * *and* with resolved values for addresses.
5854 * Perhaps we need two different val_to_string routines, one
5855 * to generate items for display filters and one to generate
5856 * strings for display, and pass to both of them the
5857 * "display" and "strings" values in the header_field_info
5858 * structure for the field, so they can get the base and,
5859 * if the field is Boolean or an enumerated integer type,
5860 * the tables used to generate human-readable values.
5862 switch(hfinfo->type) {
5868 is_signed_num = TRUE;
5873 if (filter != NULL) {
5874 format = hfinfo_numeric_format(hfinfo);
5876 *filter = ep_strdup_printf(format,
5878 fvalue_get_sinteger(&finfo->value));
5880 *filter = ep_strdup_printf(format,
5882 fvalue_get_uinteger(&finfo->value));
5888 DISSECTOR_ASSERT(!is_signed_num);
5889 if (filter != NULL) {
5890 format = hfinfo_numeric_format(hfinfo);
5891 *filter = ep_strdup_printf(format,
5893 fvalue_get_uinteger(&finfo->value));
5899 if (filter != NULL) {
5900 format = hfinfo_numeric_format(hfinfo);
5901 *filter = ep_strdup_printf(format,
5903 fvalue_get_integer64(&finfo->value));
5909 *filter = ep_strdup(finfo->hfinfo->abbrev);
5914 * If the length is 0, just match the name of the
5917 * (Also check for negative values, just in case,
5918 * as we'll cast it to an unsigned value later.)
5920 length = finfo->length;
5923 *filter = ep_strdup(finfo->hfinfo->abbrev);
5930 * This doesn't have a value, so we'd match
5931 * on the raw bytes at this address.
5933 * Should we be allowed to access to the raw bytes?
5934 * If "edt" is NULL, the answer is "no".
5940 * Is this field part of the raw frame tvbuff?
5941 * If not, we can't use "frame[N:M]" to match
5944 * XXX - should this be frame-relative, or
5945 * protocol-relative?
5947 * XXX - does this fallback for non-registered
5948 * fields even make sense?
5950 if (finfo->ds_tvb != edt->tvb)
5951 return FALSE; /* you lose */
5954 * Don't go past the end of that tvbuff.
5956 length_remaining = tvb_length_remaining(finfo->ds_tvb, finfo->start);
5957 if (length > length_remaining)
5958 length = length_remaining;
5962 if (filter != NULL) {
5963 start = finfo->start;
5964 buf_len = 32 + length * 3;
5965 *filter = ep_alloc0(buf_len);
5968 ptr += g_snprintf(ptr, (gulong) (buf_len-(ptr-*filter)),
5969 "frame[%d:%d] == ", finfo->start, length);
5970 for (i=0;i<length; i++) {
5971 c = tvb_get_guint8(finfo->ds_tvb, start);
5974 ptr += g_snprintf(ptr, (gulong) (buf_len-(ptr-*filter)), "%02x", c);
5977 ptr += g_snprintf(ptr, (gulong) (buf_len-(ptr-*filter)), ":%02x", c);
5984 /* FT_PCRE never appears as a type for a registered field. It is
5985 * only used internally. */
5986 DISSECTOR_ASSERT_NOT_REACHED();
5989 /* By default, use the fvalue's "to_string_repr" method. */
5991 /* Figure out the string length needed.
5992 * The ft_repr length.
5993 * 4 bytes for " == ".
5994 * 1 byte for trailing NUL.
5996 if (filter != NULL) {
5997 dfilter_len = fvalue_string_repr_len(&finfo->value,
5999 dfilter_len += abbrev_len + 4 + 1;
6000 *filter = ep_alloc0(dfilter_len);
6002 /* Create the string */
6003 g_snprintf(*filter, dfilter_len, "%s == ",
6005 fvalue_to_string_repr(&finfo->value,
6007 &(*filter)[abbrev_len + 4]);
6016 * Returns TRUE if we can do a "match selected" on the field, FALSE
6020 proto_can_match_selected(field_info *finfo, epan_dissect_t *edt)
6022 return construct_match_selected_string(finfo, edt, NULL);
6025 /* This function attempts to construct a "match selected" display filter
6026 * string for the specified field; if it can do so, it returns a pointer
6027 * to the string, otherwise it returns NULL.
6029 * The string is allocated with packet lifetime scope.
6030 * You do not need to [g_]free() this string since it will be automatically
6031 * freed once the next packet is dissected.
6034 proto_construct_match_selected_string(field_info *finfo, epan_dissect_t *edt)
6038 if (!construct_match_selected_string(finfo, edt, &filter))
6044 /* This function is common code for both proto_tree_add_bitmask() and
6045 * proto_tree_add_bitmask_text() functions.
6048 proto_item_add_bitmask_tree(proto_item *item, tvbuff_t *tvb, int offset, int len, gint ett,
6049 const int **fields, gboolean little_endian, int flags, gboolean first)
6051 guint32 value = 0, tmpval;
6052 proto_tree *tree = NULL;
6053 header_field_info *hf;
6058 value = tvb_get_guint8(tvb, offset);
6061 value = little_endian ? tvb_get_letohs(tvb, offset) :
6062 tvb_get_ntohs(tvb, offset);
6065 value = little_endian ? tvb_get_letoh24(tvb, offset) :
6066 tvb_get_ntoh24(tvb, offset);
6069 value = little_endian ? tvb_get_letohl(tvb, offset) :
6070 tvb_get_ntohl(tvb, offset);
6073 g_assert_not_reached();
6076 tree = proto_item_add_subtree(item, ett);
6078 proto_tree_add_item(tree, **fields, tvb, offset, len, little_endian);
6079 if (flags & BMT_NO_APPEND) {
6083 hf = proto_registrar_get_nth(**fields);
6084 DISSECTOR_ASSERT(hf->bitmask != 0);
6085 tmpval = (value & hf->bitmask) >> hf->bitshift;
6096 DISSECTOR_ASSERT(len == ftype_length(hf->type));
6098 if (hf->display == BASE_CUSTOM) {
6099 gchar lbl[ITEM_LABEL_LENGTH];
6100 custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hf->strings;
6102 DISSECTOR_ASSERT(fmtfunc);
6103 fmtfunc(lbl, tmpval);
6104 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
6108 else if (hf->strings) {
6109 if (hf->display & BASE_RANGE_STRING) {
6110 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
6111 hf->name, rval_to_str(tmpval, hf->strings, "Unknown"));
6113 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
6114 hf->name, val_to_str(tmpval, cVALS(hf->strings), "Unknown"));
6118 else if (!(flags & BMT_NO_INT)) {
6120 proto_item_append_text(item, ", ");
6123 fmt = IS_FT_INT(hf->type) ? hfinfo_int_format(hf) : hfinfo_uint_format(hf);
6124 if (IS_BASE_DUAL(hf->display)) {
6125 proto_item_append_text(item, fmt, hf->name, tmpval, tmpval);
6127 proto_item_append_text(item, fmt, hf->name, tmpval);
6134 DISSECTOR_ASSERT(len * 8 == hf->display);
6136 if (hf->strings && !(flags & BMT_NO_TFS)) {
6137 /* If we have true/false strings, emit full - otherwise messages
6139 const struct true_false_string *tfs =
6140 (const struct true_false_string *)hf->strings;
6143 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
6144 hf->name, tfs->true_string);
6146 } else if (!(flags & BMT_NO_FALSE)) {
6147 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
6148 hf->name, tfs->false_string);
6151 } else if (hf->bitmask & value) {
6152 /* If the flag is set, show the name */
6153 proto_item_append_text(item, "%s%s", first ? "" : ", ", hf->name);
6158 g_assert_not_reached();
6167 /* This function will dissect a sequence of bytes that describe a
6169 * hf_hdr is a 8/16/24/32 bit integer that describes the bitmask to be dissected.
6170 * This field will form an expansion under which the individual fields of the
6171 * bitmask is dissected and displayed.
6172 * This field must be of the type FT_[U]INT{8|16|24|32}.
6174 * fields is an array of pointers to int that lists all the fields of the
6175 * bitmask. These fields can be either of the type FT_BOOLEAN for flags
6176 * or another integer of the same type/size as hf_hdr with a mask specified.
6177 * This array is terminated by a NULL entry.
6179 * FT_BOOLEAN bits that are set to 1 will have the name added to the expansion.
6180 * FT_integer fields that have a value_string attached will have the
6181 * matched string displayed on the expansion line.
6184 proto_tree_add_bitmask(proto_tree *parent_tree, tvbuff_t *tvb, guint offset, int hf_hdr,
6185 gint ett, const int **fields, gboolean little_endian)
6187 proto_item *item = NULL;
6188 header_field_info *hf;
6191 hf = proto_registrar_get_nth(hf_hdr);
6192 DISSECTOR_ASSERT(IS_FT_INT(hf->type) || IS_FT_UINT(hf->type));
6193 len = ftype_length(hf->type);
6196 item = proto_tree_add_item(parent_tree, hf_hdr, tvb, offset, len, little_endian);
6197 proto_item_add_bitmask_tree(item, tvb, offset, len, ett, fields, little_endian,
6198 BMT_NO_INT|BMT_NO_TFS, FALSE);
6204 /* The same as proto_tree_add_bitmask(), but using an arbitrary text as a top-level item */
6206 proto_tree_add_bitmask_text(proto_tree *parent_tree, tvbuff_t *tvb, guint offset, guint len,
6207 const char *name, const char *fallback,
6208 gint ett, const int **fields, gboolean little_endian, int flags)
6210 proto_item *item = NULL;
6213 item = proto_tree_add_text(parent_tree, tvb, offset, len, "%s", name ? name : "");
6214 if (proto_item_add_bitmask_tree(item, tvb, offset, len, ett, fields, little_endian,
6215 flags, TRUE) && fallback) {
6216 /* Still at first item - append 'fallback' text if any */
6217 proto_item_append_text(item, "%s", fallback);
6225 proto_tree_add_bits_item(proto_tree *tree, int hf_index, tvbuff_t *tvb, gint bit_offset, gint no_of_bits, gboolean little_endian)
6227 header_field_info *hfinfo;
6229 TRY_TO_FAKE_THIS_ITEM(tree, hf_index, hfinfo);
6231 return proto_tree_add_bits_ret_val(tree, hf_index, tvb, bit_offset, no_of_bits, NULL, little_endian);
6234 * This function will dissect a sequence of bits that does not need to be byte aligned; the bits
6235 * set vill be shown in the tree as ..10 10.. and the integer value returned if return_value is set.
6236 * Offset should be given in bits from the start of the tvb.
6240 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)
6242 const char *format = NULL;
6246 guint8 remaining_bits;
6247 guint64 mask = 0,tmp;
6249 header_field_info *hf_field;
6254 /* We can't fake it just yet. We have to fill in the 'return_value' parameter */
6255 PROTO_REGISTRAR_GET_NTH(hf_index, hf_field);
6257 if(hf_field -> bitmask != 0) {
6258 REPORT_DISSECTOR_BUG(ep_strdup_printf("Incompatible use of proto_tree_add_bits_ret_val with field '%s' (%s) with bitmask != 0",
6259 hf_field->abbrev, hf_field->name));
6262 DISSECTOR_ASSERT(bit_offset >= 0);
6263 DISSECTOR_ASSERT(no_of_bits > 0);
6265 /* Byte align offset */
6266 offset = bit_offset>>3;
6269 * Calculate the number of octets used to hold the bits
6271 tot_no_bits = ((bit_offset&0x7)+no_of_bits);
6272 length = tot_no_bits>>3;
6273 remaining_bits = tot_no_bits % 8;
6274 if ((remaining_bits)!=0)
6277 if (no_of_bits < 9){
6278 value = tvb_get_bits8(tvb, bit_offset, no_of_bits);
6279 }else if(no_of_bits < 17){
6280 value = tvb_get_bits16(tvb, bit_offset, no_of_bits, little_endian);
6281 }else if(no_of_bits < 33){
6282 value = tvb_get_bits32(tvb, bit_offset, no_of_bits, little_endian);
6283 }else if(no_of_bits < 65){
6284 value = tvb_get_bits64(tvb, bit_offset, no_of_bits, little_endian);
6286 DISSECTOR_ASSERT_NOT_REACHED();
6291 *return_value=value;
6294 /* Coast clear. Try and fake it */
6295 TRY_TO_FAKE_THIS_ITEM(tree, hf_index, hf_field);
6298 mask = mask << (no_of_bits-1);
6300 /* prepare the string */
6303 for(bit=0;bit<((int)(bit_offset&0x07));bit++){
6304 if(bit&&(!(bit%4))){
6310 /* read the bits for the int */
6311 for(i=0;i<no_of_bits;i++){
6312 if(bit&&(!(bit%4))){
6315 if(bit&&(!(bit%8))){
6329 if(bit&&(!(bit%4))){
6336 strcat(str,hf_field->name);
6338 switch(hf_field->type){
6341 if (hf_field->strings) {
6342 const true_false_string *tfstring =
6343 (const true_false_string *) hf_field->strings;
6344 return proto_tree_add_boolean_format(tree, hf_index, tvb, offset, length, (guint32)value,
6347 (guint32)value ? tfstring->true_string : tfstring->false_string);
6349 return proto_tree_add_boolean_format(tree, hf_index, tvb, offset, length, (guint32)value,
6360 /* 1 - 32 bits field */
6361 if (hf_field->strings) {
6362 return proto_tree_add_uint_format(tree, hf_index, tvb, offset, length, (guint32)value,
6364 str, (hf_field->display & BASE_RANGE_STRING) ?
6365 rval_to_str((guint32)value, hf_field->strings, "Unknown ") :
6366 val_to_str((guint32)value, cVALS(hf_field->strings), "Unknown "),
6370 /* Pick the proper format string */
6371 format = hfinfo_uint_format(hf_field);
6372 if (IS_BASE_DUAL(hf_field->display)) {
6373 return proto_tree_add_uint_format(tree, hf_index, tvb, offset, length, (guint32)value,
6374 format, str, (guint32)value, (guint32)value);
6376 return proto_tree_add_uint_format(tree, hf_index, tvb, offset, length, (guint32)value,
6377 format, str, (guint32)value);
6382 /* Pick the proper format string */
6383 format = hfinfo_uint64_format(hf_field);
6384 if (IS_BASE_DUAL(hf_field->display)) {
6385 return proto_tree_add_uint64_format(tree, hf_index, tvb, offset, length, value,
6386 format, str, value, value);
6388 return proto_tree_add_uint64_format(tree, hf_index, tvb, offset, length, value,
6389 format, str, value);
6394 DISSECTOR_ASSERT_NOT_REACHED();
6401 proto_check_field_name(const gchar *field_name)
6403 return wrs_check_charset(fld_abbrev_chars, field_name);