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 #define SUBTREE_ONCE_ALLOCATION_NUMBER 8
51 #define SUBTREE_MAX_LEVELS 256
54 typedef struct __subtree_lvl {
61 subtree_lvl *pushed_tree;
62 guint8 pushed_tree_index;
63 guint8 pushed_tree_max;
69 /* Candidates for assembler */
71 wrs_count_bitshift(guint32 bitmask)
75 while ((bitmask & (1 << bitshift)) == 0)
82 #define cVALS(x) (const value_string*)(x)
85 #define TRY_TO_FAKE_THIS_ITEM(tree, hfindex) \
86 /* If this item is not referenced we dont have to do much work \
87 at all but we should still return a node so that \
88 field items below this node ( think proto_item_add_subtree() )\
89 will still have somewhere to attach to \
90 or else filtering will not work (they would be ignored since tree\
92 DONT try to fake a node where PITEM_FINFO(pi) is NULL \
93 since dissectors that want to do proto_item_set_len() or \
94 other operations that dereference this would crash. \
95 We dont fake FT_PROTOCOL either since these are cheap and \
96 some stuff (proto hier stat) assumes they always exist. \
98 if(!(PTREE_DATA(tree)->visible)){ \
99 if(PITEM_FINFO(tree)){ \
100 register header_field_info *hfinfo; \
101 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo); \
102 if((hfinfo->ref_count == 0) \
103 && (hfinfo->type!=FT_PROTOCOL)){ \
104 /* just return tree back to the caller */\
110 #define TRY_TO_FAKE_THIS_ITEM(tree, hfindex) ;
114 proto_tree_free_node(proto_node *node, gpointer data);
116 static void fill_label_boolean(field_info *fi, gchar *label_str);
117 static void fill_label_uint(field_info *fi, gchar *label_str);
118 static void fill_label_uint64(field_info *fi, gchar *label_str);
119 static void fill_label_enumerated_uint(field_info *fi, gchar *label_str);
120 static void fill_label_enumerated_bitfield(field_info *fi, gchar *label_str);
121 static void fill_label_numeric_bitfield(field_info *fi, gchar *label_str);
122 static void fill_label_int(field_info *fi, gchar *label_str);
123 static void fill_label_int64(field_info *fi, gchar *label_str);
124 static void fill_label_enumerated_int(field_info *fi, gchar *label_str);
126 int hfinfo_bitwidth(header_field_info *hfinfo);
127 static const char* hfinfo_uint_vals_format(header_field_info *hfinfo);
128 static const char* hfinfo_uint_format(header_field_info *hfinfo);
129 static const char* hfinfo_uint_value_format(header_field_info *hfinfo);
130 static const char* hfinfo_uint64_format(header_field_info *hfinfo);
131 static const char* hfinfo_int_vals_format(header_field_info *hfinfo);
132 static const char* hfinfo_int_format(header_field_info *hfinfo);
133 static const char* hfinfo_int_value_format(header_field_info *hfinfo);
134 static const char* hfinfo_int64_format(header_field_info *hfinfo);
137 proto_tree_add_node(proto_tree *tree, field_info *fi);
139 static header_field_info *
140 get_hfi_and_length(int hfindex, tvbuff_t *tvb, gint start, gint *length,
144 new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
145 gint start, gint item_length);
148 alloc_field_info(proto_tree *tree, int hfindex, tvbuff_t *tvb,
149 gint start, gint *length);
152 proto_tree_add_pi(proto_tree *tree, int hfindex, tvbuff_t *tvb,
153 gint start, gint *length, field_info **pfi);
156 proto_tree_set_representation_value(proto_item *pi, const char *format, va_list ap);
158 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap);
161 proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb);
163 proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length);
165 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length);
167 proto_tree_set_time(field_info *fi, nstime_t *value_ptr);
169 proto_tree_set_string(field_info *fi, const char* value);
171 proto_tree_set_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
173 proto_tree_set_ebcdic_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
175 proto_tree_set_ether(field_info *fi, const guint8* value);
177 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start);
179 proto_tree_set_ipxnet(field_info *fi, guint32 value);
181 proto_tree_set_ipv4(field_info *fi, guint32 value);
183 proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr);
185 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start);
187 proto_tree_set_guid(field_info *fi, const e_guid_t *value_ptr);
189 proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gboolean little_endian);
191 proto_tree_set_oid(field_info *fi, const guint8* value_ptr, gint length);
193 proto_tree_set_oid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
195 proto_tree_set_boolean(field_info *fi, guint32 value);
197 proto_tree_set_float(field_info *fi, float value);
199 proto_tree_set_double(field_info *fi, double value);
201 proto_tree_set_uint(field_info *fi, guint32 value);
203 proto_tree_set_int(field_info *fi, gint32 value);
205 proto_tree_set_uint64(field_info *fi, guint64 value);
207 proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start, guint length, gboolean little_endian);
209 static int proto_register_field_init(header_field_info *hfinfo, int parent);
211 /* special-case header field used within proto.c */
212 int hf_text_only = -1;
214 /* Structure for information about a protocol */
216 const char *name; /* long description */
217 const char *short_name; /* short description */
218 const char *filter_name; /* name of this protocol in filters */
219 int proto_id; /* field ID for this protocol */
220 GList *fields; /* fields for this protocol */
221 GList *last_field; /* pointer to end of list of fields */
222 gboolean is_enabled; /* TRUE if protocol is enabled */
223 gboolean can_toggle; /* TRUE if is_enabled can be changed */
226 /* List of all protocols */
227 static GList *protocols = NULL;
229 #define INITIAL_NUM_PROTOCOL_HFINFO 200
232 /* Contains information about protocols and header fields. Used when
233 * dissectors register their data */
234 static GMemChunk *gmc_hfinfo = NULL;
236 /* Contains information about a field when a dissector calls
237 * proto_tree_add_item. */
238 SLAB_ITEM_TYPE_DEFINE(field_info)
239 static SLAB_FREE_LIST_DEFINE(field_info)
240 static field_info *field_info_tmp=NULL;
241 #define FIELD_INFO_NEW(fi) \
242 SLAB_ALLOC(fi, field_info)
243 #define FIELD_INFO_FREE(fi) \
244 SLAB_FREE(fi, field_info)
248 /* Contains the space for proto_nodes. */
249 SLAB_ITEM_TYPE_DEFINE(proto_node)
250 static SLAB_FREE_LIST_DEFINE(proto_node)
251 #define PROTO_NODE_NEW(node) \
252 SLAB_ALLOC(node, proto_node) \
253 node->first_child = NULL; \
254 node->last_child = NULL; \
257 #define PROTO_NODE_FREE(node) \
258 SLAB_FREE(node, proto_node)
262 /* String space for protocol and field items for the GUI */
263 SLAB_ITEM_TYPE_DEFINE(item_label_t)
264 static SLAB_FREE_LIST_DEFINE(item_label_t)
265 #define ITEM_LABEL_NEW(il) \
266 SLAB_ALLOC(il, item_label_t)
267 #define ITEM_LABEL_FREE(il) \
268 SLAB_FREE(il, item_label_t)
271 #define PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo) \
272 DISSECTOR_ASSERT((guint)hfindex < gpa_hfinfo.len); \
273 hfinfo=gpa_hfinfo.hfi[hfindex];
276 /* List which stores protocols and fields that have been registered */
277 typedef struct _gpa_hfinfo_t {
279 guint32 allocated_len;
280 header_field_info **hfi;
282 gpa_hfinfo_t gpa_hfinfo;
284 /* Balanced tree of abbreviations and IDs */
285 static GTree *gpa_name_tree = NULL;
286 static header_field_info *same_name_hfinfo;
288 static void save_same_name_hfinfo(gpointer data)
290 same_name_hfinfo = (header_field_info*)data;
293 /* Points to the first element of an array of Booleans, indexed by
294 a subtree item type; that array element is TRUE if subtrees of
295 an item of that type are to be expanded. */
296 gboolean *tree_is_expanded;
298 /* Number of elements in that array. */
301 /* Name hashtables for fast detection of duplicate names */
302 static GHashTable* proto_names = NULL;
303 static GHashTable* proto_short_names = NULL;
304 static GHashTable* proto_filter_names = NULL;
307 proto_compare_name(gconstpointer p1_arg, gconstpointer p2_arg)
309 const protocol_t *p1 = p1_arg;
310 const protocol_t *p2 = p2_arg;
312 return g_ascii_strcasecmp(p1->short_name, p2->short_name);
316 /* initialize data structures and register protocols and fields */
318 proto_init(void (register_all_protocols_func)(register_cb cb, gpointer client_data),
319 void (register_all_handoffs_func)(register_cb cb, gpointer client_data),
321 gpointer client_data)
323 static hf_register_info hf[] = {
325 { "Text item", "", FT_NONE, BASE_NONE, NULL, 0x0,
330 proto_names = g_hash_table_new(g_int_hash, g_int_equal);
331 proto_short_names = g_hash_table_new(wrs_str_hash, g_str_equal);
332 proto_filter_names = g_hash_table_new(wrs_str_hash, g_str_equal);
336 gmc_hfinfo = g_mem_chunk_new("gmc_hfinfo",
337 sizeof(header_field_info),
338 INITIAL_NUM_PROTOCOL_HFINFO * sizeof(header_field_info),
342 gpa_hfinfo.allocated_len=0;
344 gpa_name_tree = g_tree_new_full(wrs_strcmp_with_data, NULL, NULL, save_same_name_hfinfo);
346 /* Initialize the ftype subsystem */
349 /* Register one special-case FT_TEXT_ONLY field for use when
350 converting wireshark to new-style proto_tree. These fields
351 are merely strings on the GUI tree; they are not filterable */
352 proto_register_field_array(-1, hf, array_length(hf));
354 /* Have each built-in dissector register its protocols, fields,
355 dissector tables, and dissectors to be called through a
356 handle, and do whatever one-time initialization it needs to
358 register_all_protocols_func(cb, client_data);
361 /* Now scan for plugins and load all the ones we find, calling
362 their register routines to do the stuff described above. */
364 (*cb)(RA_PLUGIN_REGISTER, NULL, client_data);
366 register_all_plugin_registrations();
369 /* Now call the "handoff registration" routines of all built-in
370 dissectors; those routines register the dissector in other
371 dissectors' handoff tables, and fetch any dissector handles
373 register_all_handoffs_func(cb, client_data);
376 /* Now do the same with plugins. */
378 (*cb)(RA_PLUGIN_HANDOFF, NULL, client_data);
379 register_all_plugin_handoffs();
382 /* sort the protocols by protocol name */
383 protocols = g_list_sort(protocols, proto_compare_name);
385 /* We've assigned all the subtree type values; allocate the array
386 for them, and zero it out. */
387 tree_is_expanded = g_malloc(num_tree_types*sizeof (gboolean));
388 memset(tree_is_expanded, 0, num_tree_types*sizeof (gboolean));
394 /* Free the abbrev/ID GTree */
396 g_tree_destroy(gpa_name_tree);
397 gpa_name_tree = NULL;
401 g_mem_chunk_destroy(gmc_hfinfo);
403 if(gpa_hfinfo.allocated_len){
405 gpa_hfinfo.allocated_len=0;
406 g_free(gpa_hfinfo.hfi);
409 if (tree_is_expanded != NULL)
410 g_free(tree_is_expanded);
415 proto_tree_traverse_pre_order(proto_tree *tree, proto_tree_traverse_func func,
418 proto_node *pnode = tree;
422 if (func(pnode, data))
425 child = pnode->first_child;
426 while (child != NULL) {
428 * The routine we call might modify the child, e.g. by
429 * freeing it, so we get the child's successor before
430 * calling that routine.
433 child = current->next;
434 if (proto_tree_traverse_pre_order((proto_tree *)current, func,
443 proto_tree_traverse_in_order(proto_tree *tree, proto_tree_traverse_func func,
446 proto_node *pnode = tree;
450 child = pnode->first_child;
453 * The routine we call might modify the child, e.g. by
454 * freeing it, so we get the child's successor before
455 * calling that routine.
458 child = current->next;
460 if (proto_tree_traverse_in_order((proto_tree *)current, func,
464 if (func(pnode, data))
467 while (child != NULL) {
469 * The routine we call might modify the child, e.g. by
470 * freeing it, so we get the child's successor before
471 * calling that routine.
474 child = current->next;
475 if (proto_tree_traverse_in_order((proto_tree *)current,
480 if (func(pnode, data))
488 proto_tree_children_foreach(proto_tree *tree, proto_tree_foreach_func func,
491 proto_node *node = tree;
494 node = node->first_child;
495 while (node != NULL) {
497 node = current->next;
498 func((proto_tree *)current, data);
502 /* frees the resources that the dissection a proto_tree uses */
504 proto_tree_free(proto_tree *tree)
506 proto_tree_traverse_in_order(tree, proto_tree_free_node, NULL);
510 free_GPtrArray_value(gpointer key, gpointer value, gpointer user_data _U_)
512 GPtrArray *ptrs = value;
513 gint hfid = (gint)(long)key;
514 header_field_info *hfinfo;
517 PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
518 if(hfinfo->ref_count){
519 /* when a field is referenced by a filter this also
520 affects the refcount for the parent protocol so we need
521 to adjust the refcount for the parent as well
523 if( (hfinfo->parent != -1) && (hfinfo->ref_count) ){
524 header_field_info *parent_hfinfo;
525 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
526 parent_hfinfo->ref_count -= hfinfo->ref_count;
528 hfinfo->ref_count = 0;
531 g_ptr_array_free(ptrs, TRUE);
535 free_node_tree_data(tree_data_t *tree_data)
537 /* Free all the GPtrArray's in the interesting_hfids hash. */
538 g_hash_table_foreach(tree_data->interesting_hfids,
539 free_GPtrArray_value, NULL);
541 /* And then destroy the hash. */
542 g_hash_table_destroy(tree_data->interesting_hfids);
544 /* And finally the tree_data_t itself. */
548 #define FREE_NODE_FIELD_INFO(finfo) \
550 ITEM_LABEL_FREE(finfo->rep); \
552 FVALUE_CLEANUP(&finfo->value); \
553 FIELD_INFO_FREE(finfo);
556 proto_tree_free_node(proto_node *node, gpointer data _U_)
558 field_info *finfo = PITEM_FINFO(node);
561 /* This is the root node. Destroy the per-tree data.
562 * There is no field_info to destroy. */
563 free_node_tree_data(PTREE_DATA(node));
566 /* This is a child node. Don't free the per-tree data, but
567 * do free the field_info data. */
568 FREE_NODE_FIELD_INFO(finfo);
571 /* Free the proto_node. */
572 PROTO_NODE_FREE(node);
574 return FALSE; /* FALSE = do not end traversal of protocol tree */
577 /* Is the parsing being done for a visible proto_tree or an invisible one?
578 * By setting this correctly, the proto_tree creation is sped up by not
579 * having to call g_vsnprintf and copy strings around.
582 proto_tree_set_visible(proto_tree *tree, gboolean visible)
584 PTREE_DATA(tree)->visible = visible;
587 /* Assume dissector set only its protocol fields.
588 This function is called by dissectors and allowes to speed up filtering
589 in wireshark, if this function returns FALSE it is safe to reset tree to NULL
590 and thus skip calling most of the expensive proto_tree_add_...()
592 If the tree is visible we implicitely assume the field is referenced.
595 proto_field_is_referenced(proto_tree *tree, int proto_id)
597 register header_field_info *hfinfo;
603 if (PTREE_DATA(tree)->visible)
606 PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
607 if (hfinfo->ref_count != 0)
614 /* Finds a record in the hf_info_records array by id. */
616 proto_registrar_get_nth(guint hfindex)
618 register header_field_info *hfinfo;
620 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
625 /* Prefix initialization
626 * this allows for a dissector to register a display filter name prefix
627 * so that it can delay the initialization of the hf array as long as
631 /* compute a hash for the part before the dot of a display filter */
632 static guint prefix_hash (gconstpointer key) {
633 /* end the string at the dot and compute its hash */
634 gchar* copy = ep_strdup(key);
644 return g_str_hash(copy);
647 /* are both strings equal up to the end or the dot? */
648 static gboolean prefix_equal (gconstpointer ap,gconstpointer bp) {
656 if ((ac == '.' || ac == '\0') && (bc == '.' || bc == '\0')) return TRUE;
658 if ( (ac == '.' || ac == '\0') && ! (bc == '.' || bc == '\0') ) return FALSE;
659 if ( (bc == '.' || bc == '\0') && ! (ac == '.' || ac == '\0') ) return FALSE;
661 if (ac != bc) return FALSE;
668 /* indexed by prefix, contains initializers */
669 static GHashTable* prefixes = NULL;
672 /* Register a new prefix for "delayed" initialization of field arrays */
674 proto_register_prefix(const char *prefix, prefix_initializer_t pi ) {
676 prefixes = g_hash_table_new(prefix_hash,prefix_equal);
679 g_hash_table_insert(prefixes,(gpointer)prefix,pi);
682 /* helper to call all prefix initializers */
683 static gboolean initialize_prefix(gpointer k, gpointer v, gpointer u _U_) {
684 ((prefix_initializer_t)v)(k);
688 /** Initialize every remaining uninitialized prefix. */
689 void proto_initialize_all_prefixes(void) {
690 g_hash_table_foreach_remove(prefixes, initialize_prefix, NULL);
693 /* Finds a record in the hf_info_records array by name.
694 * If it fails to find it in the already registered fields,
695 * it tries to find and call an initializer in the prefixes
696 * table and if so it looks again.
699 proto_registrar_get_byname(const char *field_name)
701 header_field_info* hfinfo;
702 prefix_initializer_t pi;
704 DISSECTOR_ASSERT(field_name != NULL);
706 hfinfo = g_tree_lookup(gpa_name_tree, field_name);
708 if (hfinfo) return hfinfo;
710 if (!prefixes) return NULL;
712 if(( pi = g_hash_table_lookup(prefixes,field_name) )) {
714 g_hash_table_remove(prefixes,field_name);
719 return g_tree_lookup(gpa_name_tree, field_name);
723 void ptvcursor_new_subtree_levels(ptvcursor_t * ptvc)
725 subtree_lvl * pushed_tree;
727 DISSECTOR_ASSERT(ptvc->pushed_tree_max <= SUBTREE_MAX_LEVELS-SUBTREE_ONCE_ALLOCATION_NUMBER);
728 ptvc->pushed_tree_max += SUBTREE_ONCE_ALLOCATION_NUMBER;
730 pushed_tree = ep_alloc(sizeof(subtree_lvl) * ptvc->pushed_tree_max);
731 DISSECTOR_ASSERT(pushed_tree != NULL);
732 if (ptvc->pushed_tree)
733 memcpy(pushed_tree, ptvc->pushed_tree, ptvc->pushed_tree_max - SUBTREE_ONCE_ALLOCATION_NUMBER);
734 ptvc->pushed_tree = pushed_tree;
737 void ptvcursor_free_subtree_levels(ptvcursor_t * ptvc)
739 ptvc->pushed_tree = NULL;
740 ptvc->pushed_tree_max = 0;
741 DISSECTOR_ASSERT(ptvc->pushed_tree_index ==0);
742 ptvc->pushed_tree_index = 0;
745 /* Allocates an initializes a ptvcursor_t with 3 variables:
746 * proto_tree, tvbuff, and offset. */
748 ptvcursor_new(proto_tree *tree, tvbuff_t *tvb, gint offset)
752 ptvc = ep_alloc(sizeof(ptvcursor_t));
755 ptvc->offset = offset;
756 ptvc->pushed_tree= NULL;
757 ptvc->pushed_tree_max= 0;
758 ptvc->pushed_tree_index= 0;
763 /* Frees memory for ptvcursor_t, but nothing deeper than that. */
765 ptvcursor_free(ptvcursor_t *ptvc)
767 ptvcursor_free_subtree_levels(ptvc);
771 /* Returns tvbuff. */
773 ptvcursor_tvbuff(ptvcursor_t* ptvc)
778 /* Returns current offset. */
780 ptvcursor_current_offset(ptvcursor_t* ptvc)
786 ptvcursor_tree(ptvcursor_t* ptvc)
795 ptvcursor_set_tree(ptvcursor_t* ptvc, proto_tree *tree)
800 /* creates a subtree, sets it as the working tree and pushes the old working tree */
802 ptvcursor_push_subtree(ptvcursor_t *ptvc, proto_item *it, gint ett_subtree)
804 subtree_lvl * subtree;
805 if (ptvc->pushed_tree_index >= ptvc->pushed_tree_max)
806 ptvcursor_new_subtree_levels(ptvc);
808 subtree = ptvc->pushed_tree+ptvc->pushed_tree_index;
809 subtree->tree = ptvc->tree;
811 ptvc->pushed_tree_index++;
812 return ptvcursor_set_subtree(ptvc, it, ett_subtree);
817 ptvcursor_pop_subtree(ptvcursor_t *ptvc)
819 subtree_lvl * subtree;
820 if (ptvc->pushed_tree_index <= 0)
823 ptvc->pushed_tree_index--;
824 subtree = ptvc->pushed_tree+ptvc->pushed_tree_index;
825 if (subtree->it != NULL)
826 proto_item_set_len(subtree->it, ptvcursor_current_offset(ptvc) - subtree->cursor_offset);
827 ptvc->tree = subtree->tree;
830 /* saves the current tvb offset and the item in the current subtree level */
832 ptvcursor_subtree_set_item(ptvcursor_t * ptvc, proto_item * it)
834 subtree_lvl * subtree;
836 DISSECTOR_ASSERT(ptvc->pushed_tree_index > 0);
838 subtree = ptvc->pushed_tree+ptvc->pushed_tree_index-1;
840 subtree->cursor_offset = ptvcursor_current_offset(ptvc);
843 /* Creates a subtree and adds it to the cursor as the working tree but does not
844 * save the old working tree */
846 ptvcursor_set_subtree(ptvcursor_t *ptvc, proto_item *it, gint ett_subtree)
848 ptvc->tree = proto_item_add_subtree(it, ett_subtree);
852 proto_tree* ptvcursor_add_subtree_item(ptvcursor_t * ptvc, proto_item * it, gint ett_subtree, gint length)
854 ptvcursor_push_subtree(ptvc, it, ett_subtree);
855 if (length == SUBTREE_UNDEFINED_LENGTH)
856 ptvcursor_subtree_set_item(ptvc, it);
857 return ptvcursor_tree(ptvc);
860 /* Add an item to the tree and create a subtree
861 * If the length is unknown, length may be defined as SUBTREE_UNDEFINED_LENGTH.
862 * In this case, when the subtree will be closed, the parent item length will
863 * be equal to the advancement of the cursor since the creation of the subtree.
865 proto_tree* ptvcursor_add_with_subtree(ptvcursor_t * ptvc, int hfindex, gint length,
866 gboolean little_endian, gint ett_subtree)
869 it = ptvcursor_add_no_advance(ptvc, hfindex, length, little_endian);
870 return ptvcursor_add_subtree_item(ptvc, it, ett_subtree, length);
874 proto_tree_add_text_node(proto_tree *tree, tvbuff_t *tvb, gint start, gint length);
876 /* Add a text node to the tree and create a subtree
877 * If the length is unknown, length may be defined as SUBTREE_UNDEFINED_LENGTH.
878 * In this case, when the subtree will be closed, the item length will be equal
879 * to the advancement of the cursor since the creation of the subtree.
881 proto_tree * ptvcursor_add_text_with_subtree(ptvcursor_t * ptvc, gint length,
882 gint ett_subtree, const char *format, ...)
887 it = proto_tree_add_text_node(ptvcursor_tree(ptvc), ptvcursor_tvbuff(ptvc),
888 ptvcursor_current_offset(ptvc), length);
890 va_start(ap, format);
891 proto_tree_set_representation(it, format, ap);
894 return ptvcursor_add_subtree_item(ptvc, it, ett_subtree, length);
897 /* Add a text-only node, leaving it to our caller to fill the text in */
899 proto_tree_add_text_node(proto_tree *tree, tvbuff_t *tvb, gint start, gint length)
903 pi = proto_tree_add_pi(tree, hf_text_only, tvb, start, &length, NULL);
910 /* Add a text-only node to the proto_tree */
912 proto_tree_add_text(proto_tree *tree, tvbuff_t *tvb, gint start, gint length,
913 const char *format, ...)
918 pi = proto_tree_add_text_node(tree, tvb, start, length);
922 va_start(ap, format);
923 proto_tree_set_representation(pi, format, ap);
929 /* Add a text-only node to the proto_tree (va_list version) */
931 proto_tree_add_text_valist(proto_tree *tree, tvbuff_t *tvb, gint start,
932 gint length, const char *format, va_list ap)
936 pi = proto_tree_add_text_node(tree, tvb, start, length);
940 proto_tree_set_representation(pi, format, ap);
945 /* Add a text-only node for debugging purposes. The caller doesn't need
946 * to worry about tvbuff, start, or length. Debug message gets sent to
949 proto_tree_add_debug_text(proto_tree *tree, const char *format, ...)
954 pi = proto_tree_add_text_node(tree, NULL, 0, 0);
956 va_start(ap, format);
958 proto_tree_set_representation(pi, format, ap);
968 get_uint_value(tvbuff_t *tvb, gint offset, gint length, gboolean little_endian)
975 value = tvb_get_guint8(tvb, offset);
979 value = little_endian ? tvb_get_letohs(tvb, offset)
980 : tvb_get_ntohs(tvb, offset);
984 value = little_endian ? tvb_get_letoh24(tvb, offset)
985 : tvb_get_ntoh24(tvb, offset);
989 value = little_endian ? tvb_get_letohl(tvb, offset)
990 : tvb_get_ntohl(tvb, offset);
994 DISSECTOR_ASSERT_NOT_REACHED();
1002 get_int_value(tvbuff_t *tvb, gint offset, gint length, gboolean little_endian)
1009 value = (gint8)tvb_get_guint8(tvb, offset);
1013 value = (gint16) (little_endian ? tvb_get_letohs(tvb, offset)
1014 : tvb_get_ntohs(tvb, offset));
1018 value = little_endian ? tvb_get_letoh24(tvb, offset)
1019 : tvb_get_ntoh24(tvb, offset);
1020 if (value & 0x00800000) {
1021 /* Sign bit is set; sign-extend it. */
1022 value |= 0xFF000000;
1027 value = little_endian ? tvb_get_letohl(tvb, offset)
1028 : tvb_get_ntohl(tvb, offset);
1032 DISSECTOR_ASSERT_NOT_REACHED();
1039 /* Add an item to a proto_tree, using the text label registered to that item;
1040 the item is extracted from the tvbuff handed to it. */
1042 proto_tree_new_item(field_info *new_fi, proto_tree *tree, int hfindex,
1043 tvbuff_t *tvb, gint start, gint length, gboolean little_endian)
1053 /* there is a possibility here that we might raise an exception
1054 * and thus would lose track of the field_info.
1055 * store it in a temp so that if we come here again we can reclaim
1056 * the field_info without leaking memory.
1058 /* XXX this only keeps track of one field_info struct,
1059 if we ever go multithreaded for calls to this function
1060 we have to change this code to use per thread variable.
1063 /* oops, last one we got must have been lost due
1065 * good thing we saved it, now we can reverse the
1066 * memory leak and reclaim it.
1068 SLAB_FREE(field_info_tmp, field_info);
1070 /* we might throw an exception, keep track of this one
1071 * across the "dangerous" section below.
1073 field_info_tmp=new_fi;
1075 switch(new_fi->hfinfo->type) {
1077 /* no value to set for FT_NONE */
1081 proto_tree_set_protocol_tvb(new_fi, tvb);
1085 proto_tree_set_bytes_tvb(new_fi, tvb, start, length);
1089 n = get_uint_value(tvb, start, length, little_endian);
1090 proto_tree_set_bytes_tvb(new_fi, tvb, start + length, n);
1092 /* Instead of calling proto_item_set_len(), since we don't yet
1093 * have a proto_item, we set the field_info's length ourselves. */
1094 new_fi->length = n + length;
1098 proto_tree_set_boolean(new_fi,
1099 get_uint_value(tvb, start, length, little_endian));
1102 /* XXX - make these just FT_UINT? */
1107 proto_tree_set_uint(new_fi,
1108 get_uint_value(tvb, start, length, little_endian));
1113 DISSECTOR_ASSERT( length <= 8 && length >= 1);
1114 proto_tree_set_uint64_tvb(new_fi, tvb, start, length, little_endian);
1117 /* XXX - make these just FT_INT? */
1122 proto_tree_set_int(new_fi,
1123 get_int_value(tvb, start, length, little_endian));
1127 DISSECTOR_ASSERT(length == 4);
1128 value = tvb_get_ipv4(tvb, start);
1129 proto_tree_set_ipv4(new_fi, little_endian ? GUINT32_SWAP_LE_BE(value) : value);
1133 DISSECTOR_ASSERT(length == 4);
1134 proto_tree_set_ipxnet(new_fi,
1135 get_uint_value(tvb, start, 4, FALSE));
1139 DISSECTOR_ASSERT(length == 16);
1140 proto_tree_set_ipv6_tvb(new_fi, tvb, start);
1144 DISSECTOR_ASSERT(length == 6);
1145 proto_tree_set_ether_tvb(new_fi, tvb, start);
1149 DISSECTOR_ASSERT(length == 16);
1150 proto_tree_set_guid_tvb(new_fi, tvb, start, little_endian);
1154 proto_tree_set_oid_tvb(new_fi, tvb, start, length);
1158 DISSECTOR_ASSERT(length == 4);
1160 floatval = tvb_get_letohieee_float(tvb, start);
1162 floatval = tvb_get_ntohieee_float(tvb, start);
1163 proto_tree_set_float(new_fi, floatval);
1167 DISSECTOR_ASSERT(length == 8);
1169 doubleval = tvb_get_letohieee_double(tvb, start);
1171 doubleval = tvb_get_ntohieee_double(tvb, start);
1172 proto_tree_set_double(new_fi, doubleval);
1176 proto_tree_set_string_tvb(new_fi, tvb, start, length);
1180 DISSECTOR_ASSERT(length >= -1);
1181 /* Instead of calling proto_item_set_len(),
1182 * since we don't yet have a proto_item, we
1183 * set the field_info's length ourselves.
1185 * XXX - our caller can't use that length to
1186 * advance an offset unless they arrange that
1187 * there always be a protocol tree into which
1188 * we're putting this item.
1191 /* This can throw an exception */
1192 length = tvb_strsize(tvb, start);
1194 string = ep_alloc(length);
1196 tvb_memcpy(tvb, string, start, length);
1197 } else if (length == 0) {
1200 /* In this case, length signifies
1201 * the length of the string.
1203 * This could either be a null-padded
1204 * string, which doesn't necessarily
1205 * have a '\0' at the end, or a
1206 * null-terminated string, with a
1207 * trailing '\0'. (Yes, there are
1208 * cases where you have a string
1209 * that's both counted and null-
1212 * In the first case, we must
1213 * allocate a buffer of length
1214 * "length+1", to make room for
1217 * In the second case, we don't
1218 * assume that there is a trailing
1219 * '\0' there, as the packet might
1220 * be malformed. (XXX - should we
1221 * throw an exception if there's no
1222 * trailing '\0'?) Therefore, we
1223 * allocate a buffer of length
1224 * "length+1", and put in a trailing
1225 * '\0', just to be safe.
1227 * (XXX - this would change if
1228 * we made string values counted
1229 * rather than null-terminated.)
1231 string = tvb_get_ephemeral_string(tvb,
1235 new_fi->length = length;
1236 proto_tree_set_string(new_fi, string);
1240 proto_tree_set_ebcdic_string_tvb(new_fi, tvb, start, length);
1243 case FT_UINT_STRING:
1244 n = get_uint_value(tvb, start, length, little_endian);
1245 proto_tree_set_string_tvb(new_fi, tvb, start + length, n);
1247 /* Instead of calling proto_item_set_len(), since we
1248 * don't yet have a proto_item, we set the
1249 * field_info's length ourselves.
1251 * XXX - our caller can't use that length to
1252 * advance an offset unless they arrange that
1253 * there always be a protocol tree into which
1254 * we're putting this item.
1256 new_fi->length = n + length;
1260 g_error("new_fi->hfinfo->type %d (%s) not handled\n",
1261 new_fi->hfinfo->type,
1262 ftype_name(new_fi->hfinfo->type));
1263 DISSECTOR_ASSERT_NOT_REACHED();
1267 /* Don't add new node to proto_tree until now so that any exceptions
1268 * raised by a tvbuff access method doesn't leave junk in the proto_tree. */
1269 pi = proto_tree_add_node(tree, new_fi);
1271 /* we did not raise an exception so we dont have to remember this
1272 * field_info struct any more.
1274 field_info_tmp=NULL;
1276 /* If the proto_tree wants to keep a record of this finfo
1277 * for quick lookup, then record it. */
1278 if (new_fi->hfinfo->ref_count) {
1280 hash = PTREE_DATA(tree)->interesting_hfids;
1281 ptrs = g_hash_table_lookup(hash, GINT_TO_POINTER(hfindex));
1283 g_ptr_array_add(ptrs, new_fi);
1290 /* Gets data from tvbuff, adds it to proto_tree, increments offset,
1291 and returns proto_item* */
1293 ptvcursor_add(ptvcursor_t *ptvc, int hfindex, gint length,
1294 gboolean little_endian)
1297 header_field_info *hfinfo;
1302 offset = ptvc->offset;
1303 hfinfo = get_hfi_and_length(hfindex, ptvc->tvb, offset, &length,
1305 ptvc->offset += length;
1306 if (hfinfo->type == FT_UINT_BYTES || hfinfo->type == FT_UINT_STRING) {
1308 * The length of the rest of the item is in the first N
1309 * bytes of the item.
1311 n = get_uint_value(ptvc->tvb, offset, length, little_endian);
1314 if (ptvc->tree == NULL)
1317 TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfindex);
1319 new_fi = new_field_info(ptvc->tree, hfinfo, ptvc->tvb, offset,
1324 return proto_tree_new_item(new_fi, ptvc->tree, hfindex, ptvc->tvb,
1325 offset, length, little_endian);
1328 /* Add an item to a proto_tree, using the text label registered to that item;
1329 the item is extracted from the tvbuff handed to it. */
1331 proto_tree_add_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1332 gint start, gint length, gboolean little_endian)
1339 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1341 new_fi = alloc_field_info(tree, hfindex, tvb, start, &length);
1346 return proto_tree_new_item(new_fi, tree, hfindex, tvb, start,
1347 length, little_endian);
1351 proto_tree_add_item_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1352 gint start, gint length, gboolean little_endian)
1356 pi = proto_tree_add_item(tree, hfindex, tvb, start, length, little_endian);
1360 PROTO_ITEM_SET_HIDDEN(pi);
1366 /* Add a FT_NONE to a proto_tree */
1368 proto_tree_add_none_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1369 gint length, const char *format, ...)
1373 header_field_info *hfinfo;
1378 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1379 DISSECTOR_ASSERT(hfinfo->type == FT_NONE);
1381 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, NULL);
1383 va_start(ap, format);
1384 proto_tree_set_representation(pi, format, ap);
1387 /* no value to set for FT_NONE */
1391 /* Gets data from tvbuff, adds it to proto_tree, *DOES NOT* increment
1392 * offset, and returns proto_item* */
1394 ptvcursor_add_no_advance(ptvcursor_t* ptvc, int hf, gint length,
1395 gboolean endianness)
1399 item = proto_tree_add_item(ptvc->tree, hf, ptvc->tvb, ptvc->offset,
1400 length, endianness);
1405 /* Advance the ptvcursor's offset within its tvbuff without
1406 * adding anything to the proto_tree. */
1408 ptvcursor_advance(ptvcursor_t* ptvc, gint length)
1410 ptvc->offset += length;
1415 proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb)
1417 fvalue_set(&fi->value, tvb, TRUE);
1420 /* Add a FT_PROTOCOL to a proto_tree */
1422 proto_tree_add_protocol_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1423 gint length, const char *format, ...)
1427 header_field_info *hfinfo;
1433 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1434 DISSECTOR_ASSERT(hfinfo->type == FT_PROTOCOL);
1436 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1438 va_start(ap, format);
1439 proto_tree_set_representation(pi, format, ap);
1443 proto_tree_set_protocol_tvb(new_fi, tvb);
1446 proto_tree_set_protocol_tvb(new_fi, NULL);
1452 /* Add a FT_BYTES to a proto_tree */
1454 proto_tree_add_bytes(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1455 gint length, const guint8 *start_ptr)
1459 header_field_info *hfinfo;
1464 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1466 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1467 DISSECTOR_ASSERT(hfinfo->type == FT_BYTES);
1469 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1470 proto_tree_set_bytes(new_fi, start_ptr, length);
1476 proto_tree_add_bytes_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1477 gint length, const guint8 *start_ptr)
1481 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length, start_ptr);
1485 PROTO_ITEM_SET_HIDDEN(pi);
1491 proto_tree_add_bytes_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1492 gint start, gint length, const guint8 *start_ptr,
1493 const char *format, ...)
1498 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length, start_ptr);
1502 va_start(ap, format);
1503 proto_tree_set_representation_value(pi, format, ap);
1510 proto_tree_add_bytes_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1511 gint length, const guint8 *start_ptr, const char *format, ...)
1516 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length, start_ptr);
1520 va_start(ap, format);
1521 proto_tree_set_representation(pi, format, ap);
1528 proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length)
1532 bytes = g_byte_array_new();
1534 g_byte_array_append(bytes, start_ptr, length);
1536 col_custom_set_fstr(fi->hfinfo, "%s", bytes_to_str(bytes->data,
1538 fvalue_set(&fi->value, bytes, TRUE);
1543 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length)
1545 proto_tree_set_bytes(fi, tvb_get_ptr(tvb, offset, length), length);
1548 /* Add a FT_*TIME to a proto_tree */
1550 proto_tree_add_time(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1551 nstime_t *value_ptr)
1555 header_field_info *hfinfo;
1560 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1562 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1563 DISSECTOR_ASSERT(hfinfo->type == FT_ABSOLUTE_TIME ||
1564 hfinfo->type == FT_RELATIVE_TIME);
1566 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1567 proto_tree_set_time(new_fi, value_ptr);
1573 proto_tree_add_time_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1574 nstime_t *value_ptr)
1578 pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
1582 PROTO_ITEM_SET_HIDDEN(pi);
1588 proto_tree_add_time_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1589 gint start, gint length, nstime_t *value_ptr,
1590 const char *format, ...)
1595 pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
1599 va_start(ap, format);
1600 proto_tree_set_representation_value(pi, format, ap);
1607 proto_tree_add_time_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1608 nstime_t *value_ptr, const char *format, ...)
1613 pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
1617 va_start(ap, format);
1618 proto_tree_set_representation(pi, format, ap);
1624 /* Set the FT_*TIME value */
1626 proto_tree_set_time(field_info *fi, nstime_t *value_ptr)
1628 header_field_info *hfinfo;
1630 DISSECTOR_ASSERT(value_ptr != NULL);
1631 hfinfo = fi->hfinfo;
1633 if (hfinfo->type == FT_ABSOLUTE_TIME) {
1634 col_custom_set_fstr(fi->hfinfo, "%s", abs_time_to_str(value_ptr));
1635 } else if (hfinfo->type == FT_RELATIVE_TIME) {
1636 col_custom_set_fstr(fi->hfinfo, "%s", rel_time_to_secs_str(value_ptr));
1638 fvalue_set(&fi->value, value_ptr, FALSE);
1641 /* Add a FT_IPXNET to a proto_tree */
1643 proto_tree_add_ipxnet(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1648 header_field_info *hfinfo;
1653 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1655 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1656 DISSECTOR_ASSERT(hfinfo->type == FT_IPXNET);
1658 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1659 proto_tree_set_ipxnet(new_fi, value);
1665 proto_tree_add_ipxnet_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1670 pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
1674 PROTO_ITEM_SET_HIDDEN(pi);
1680 proto_tree_add_ipxnet_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1681 gint start, gint length, guint32 value, const char *format, ...)
1686 pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
1690 va_start(ap, format);
1691 proto_tree_set_representation_value(pi, format, ap);
1698 proto_tree_add_ipxnet_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1699 guint32 value, const char *format, ...)
1704 pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
1708 va_start(ap, format);
1709 proto_tree_set_representation(pi, format, ap);
1715 /* Set the FT_IPXNET value */
1717 proto_tree_set_ipxnet(field_info *fi, guint32 value)
1719 fvalue_set_uinteger(&fi->value, value);
1722 /* Add a FT_IPv4 to a proto_tree */
1724 proto_tree_add_ipv4(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1729 header_field_info *hfinfo;
1734 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1736 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1737 DISSECTOR_ASSERT(hfinfo->type == FT_IPv4);
1739 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1740 proto_tree_set_ipv4(new_fi, value);
1746 proto_tree_add_ipv4_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1751 pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
1755 PROTO_ITEM_SET_HIDDEN(pi);
1761 proto_tree_add_ipv4_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1762 gint start, gint length, guint32 value, const char *format, ...)
1767 pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
1771 va_start(ap, format);
1772 proto_tree_set_representation_value(pi, format, ap);
1779 proto_tree_add_ipv4_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1780 guint32 value, const char *format, ...)
1785 pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
1789 va_start(ap, format);
1790 proto_tree_set_representation(pi, format, ap);
1796 /* Set the FT_IPv4 value */
1798 proto_tree_set_ipv4(field_info *fi, guint32 value)
1800 col_custom_set_fstr(fi->hfinfo, "%s",
1801 ip_to_str((guint8 *)&value));
1802 fvalue_set_uinteger(&fi->value, value);
1805 /* Add a FT_IPv6 to a proto_tree */
1807 proto_tree_add_ipv6(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1808 const guint8* value_ptr)
1812 header_field_info *hfinfo;
1817 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1819 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1820 DISSECTOR_ASSERT(hfinfo->type == FT_IPv6);
1822 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1823 proto_tree_set_ipv6(new_fi, value_ptr);
1829 proto_tree_add_ipv6_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1830 const guint8* value_ptr)
1834 pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
1838 PROTO_ITEM_SET_HIDDEN(pi);
1844 proto_tree_add_ipv6_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1845 gint start, gint length, const guint8* value_ptr,
1846 const char *format, ...)
1851 pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
1855 va_start(ap, format);
1856 proto_tree_set_representation_value(pi, format, ap);
1863 proto_tree_add_ipv6_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1864 const guint8* value_ptr, const char *format, ...)
1869 pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
1873 va_start(ap, format);
1874 proto_tree_set_representation(pi, format, ap);
1880 /* Set the FT_IPv6 value */
1882 proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr)
1884 DISSECTOR_ASSERT(value_ptr != NULL);
1885 fvalue_set(&fi->value, (gpointer) value_ptr, FALSE);
1889 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start)
1891 proto_tree_set_ipv6(fi, tvb_get_ptr(tvb, start, 16));
1894 /* Add a FT_GUID to a proto_tree */
1896 proto_tree_add_guid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1897 const e_guid_t *value_ptr)
1901 header_field_info *hfinfo;
1906 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1908 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1909 DISSECTOR_ASSERT(hfinfo->type == FT_GUID);
1911 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1912 proto_tree_set_guid(new_fi, value_ptr);
1918 proto_tree_add_guid_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1919 const e_guid_t *value_ptr)
1923 pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
1927 PROTO_ITEM_SET_HIDDEN(pi);
1933 proto_tree_add_guid_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1934 gint start, gint length, const e_guid_t *value_ptr,
1935 const char *format, ...)
1940 pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
1944 va_start(ap, format);
1945 proto_tree_set_representation_value(pi, format, ap);
1952 proto_tree_add_guid_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1953 const e_guid_t *value_ptr, const char *format, ...)
1958 pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
1962 va_start(ap, format);
1963 proto_tree_set_representation(pi, format, ap);
1969 /* Set the FT_GUID value */
1971 proto_tree_set_guid(field_info *fi, const e_guid_t *value_ptr)
1973 DISSECTOR_ASSERT(value_ptr != NULL);
1974 col_custom_set_fstr(fi->hfinfo, "%s",
1975 guid_to_str(value_ptr));
1976 fvalue_set(&fi->value, (gpointer) value_ptr, FALSE);
1980 proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gboolean little_endian)
1984 tvb_get_guid(tvb, start, &guid, little_endian);
1985 proto_tree_set_guid(fi, &guid);
1988 /* Add a FT_OID to a proto_tree */
1990 proto_tree_add_oid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1991 const guint8* value_ptr)
1995 header_field_info *hfinfo;
2000 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
2002 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2003 DISSECTOR_ASSERT(hfinfo->type == FT_OID);
2005 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2006 proto_tree_set_oid(new_fi, value_ptr, length);
2012 proto_tree_add_oid_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2013 const guint8* value_ptr)
2017 pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
2021 PROTO_ITEM_SET_HIDDEN(pi);
2027 proto_tree_add_oid_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2028 gint start, gint length, const guint8* value_ptr,
2029 const char *format, ...)
2034 pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
2038 va_start(ap, format);
2039 proto_tree_set_representation_value(pi, format, ap);
2046 proto_tree_add_oid_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2047 const guint8* value_ptr, const char *format, ...)
2052 pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
2056 va_start(ap, format);
2057 proto_tree_set_representation(pi, format, ap);
2063 /* Set the FT_OID value */
2065 proto_tree_set_oid(field_info *fi, const guint8* value_ptr, gint length)
2069 DISSECTOR_ASSERT(value_ptr != NULL);
2071 bytes = g_byte_array_new();
2073 g_byte_array_append(bytes, value_ptr, length);
2075 col_custom_set_fstr(fi->hfinfo, "%s",
2076 oid_resolved_from_encoded(value_ptr, length));
2077 fvalue_set(&fi->value, bytes, TRUE);
2081 proto_tree_set_oid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
2083 proto_tree_set_oid(fi, tvb_get_ptr(tvb, start, length), length);
2087 proto_tree_set_uint64(field_info *fi, guint64 value)
2089 col_custom_set_fstr(fi->hfinfo, "%" G_GINT64_MODIFIER "u",
2091 fvalue_set_integer64(&fi->value, value);
2095 proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start, guint length, gboolean little_endian)
2098 guint8* b = ep_tvb_memdup(tvb,start,length);
2103 default: DISSECTOR_ASSERT_NOT_REACHED();
2104 case 8: value <<= 8; value += *--b;
2105 case 7: value <<= 8; value += *--b;
2106 case 6: value <<= 8; value += *--b;
2107 case 5: value <<= 8; value += *--b;
2108 case 4: value <<= 8; value += *--b;
2109 case 3: value <<= 8; value += *--b;
2110 case 2: value <<= 8; value += *--b;
2111 case 1: value <<= 8; value += *--b;
2116 default: DISSECTOR_ASSERT_NOT_REACHED();
2117 case 8: value <<= 8; value += *b++;
2118 case 7: value <<= 8; value += *b++;
2119 case 6: value <<= 8; value += *b++;
2120 case 5: value <<= 8; value += *b++;
2121 case 4: value <<= 8; value += *b++;
2122 case 3: value <<= 8; value += *b++;
2123 case 2: value <<= 8; value += *b++;
2124 case 1: value <<= 8; value += *b++;
2129 proto_tree_set_uint64(fi, value);
2132 /* Add a FT_STRING or FT_STRINGZ to a proto_tree. Creates own copy of string,
2133 * and frees it when the proto_tree is destroyed. */
2135 proto_tree_add_string(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2136 gint length, const char* value)
2140 header_field_info *hfinfo;
2145 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
2147 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2148 DISSECTOR_ASSERT(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ);
2150 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2151 DISSECTOR_ASSERT(length >= 0);
2152 proto_tree_set_string(new_fi, value);
2158 proto_tree_add_string_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2159 gint length, const char* value)
2163 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
2167 PROTO_ITEM_SET_HIDDEN(pi);
2173 proto_tree_add_string_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2174 gint start, gint length, const char* value, const char *format,
2180 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
2184 va_start(ap, format);
2185 proto_tree_set_representation_value(pi, format, ap);
2192 proto_tree_add_string_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2193 gint length, const char* value, const char *format, ...)
2198 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
2202 va_start(ap, format);
2203 proto_tree_set_representation(pi, format, ap);
2209 /* Appends string data to a FT_STRING or FT_STRINGZ, allowing progressive
2210 * field info update instead of only updating the representation as does
2211 * proto_item_append_text()
2213 /* NOTE: this function will break with the TRY_TO_FAKE_THIS_ITEM()
2214 * speed optimization.
2215 * Currently only WSP use this function so it is not that bad but try to
2216 * avoid using this one if possible.
2217 * IF you must use this function you MUST also disable the
2218 * TRY_TO_FAKE_THIS_ITEM() optimization for your dissector/function
2219 * using proto_item_append_string().
2220 * Do that by faking that the tree is visible by calling
2221 * proto_tree_set_visible(tree, TRUE) (see packet-wsp.c)
2222 * BEFORE you create the item you are later going to use
2223 * proto_item_append_string() on.
2226 proto_item_append_string(proto_item *pi, const char *str)
2229 header_field_info *hfinfo;
2230 gchar *old_str, *new_str;
2237 fi = PITEM_FINFO(pi);
2238 hfinfo = fi->hfinfo;
2239 if (hfinfo->type == FT_PROTOCOL) {
2240 /* TRY_TO_FAKE_THIS_ITEM() speed optimization: silently skip */
2243 DISSECTOR_ASSERT(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ);
2244 old_str = fvalue_get(&fi->value);
2245 new_str = ep_strdup_printf("%s%s", old_str, str);
2246 fvalue_set(&fi->value, new_str, FALSE);
2249 /* Set the FT_STRING value */
2251 proto_tree_set_string(field_info *fi, const char* value)
2254 col_custom_set_fstr(fi->hfinfo, "%s",
2255 format_text(value, strlen(value)));
2256 fvalue_set(&fi->value, (gpointer) value, FALSE);
2258 col_custom_set_fstr(fi->hfinfo, "[ Null ]");
2259 fvalue_set(&fi->value, (gpointer) "[ Null ]", FALSE);
2264 proto_tree_set_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
2269 length = tvb_ensure_length_remaining(tvb, start);
2272 string = tvb_get_ephemeral_string(tvb, start, length);
2273 proto_tree_set_string(fi, string);
2277 proto_tree_set_ebcdic_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
2282 length = tvb_ensure_length_remaining(tvb, start);
2285 string = tvb_get_ephemeral_string(tvb, start, length);
2286 EBCDIC_to_ASCII(string, length);
2287 proto_tree_set_string(fi, string);
2290 /* Add a FT_ETHER to a proto_tree */
2292 proto_tree_add_ether(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2293 const guint8* value)
2297 header_field_info *hfinfo;
2302 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
2304 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2305 DISSECTOR_ASSERT(hfinfo->type == FT_ETHER);
2307 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2308 proto_tree_set_ether(new_fi, value);
2314 proto_tree_add_ether_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2315 const guint8* value)
2319 pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
2323 PROTO_ITEM_SET_HIDDEN(pi);
2329 proto_tree_add_ether_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2330 gint start, gint length, const guint8* value,
2331 const char *format, ...)
2336 pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
2340 va_start(ap, format);
2341 proto_tree_set_representation_value(pi, format, ap);
2348 proto_tree_add_ether_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2349 const guint8* value, const char *format, ...)
2354 pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
2358 va_start(ap, format);
2359 proto_tree_set_representation(pi, format, ap);
2365 /* Set the FT_ETHER value */
2367 proto_tree_set_ether(field_info *fi, const guint8* value)
2369 col_custom_set_fstr(fi->hfinfo, "%s", bytes_to_str_punct(value, 6, ':'));
2370 fvalue_set(&fi->value, (gpointer) value, FALSE);
2374 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start)
2376 proto_tree_set_ether(fi, tvb_get_ptr(tvb, start, 6));
2379 /* Add a FT_BOOLEAN to a proto_tree */
2381 proto_tree_add_boolean(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2386 header_field_info *hfinfo;
2391 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
2393 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2394 DISSECTOR_ASSERT(hfinfo->type == FT_BOOLEAN);
2396 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2397 proto_tree_set_boolean(new_fi, value);
2403 proto_tree_add_boolean_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2408 pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
2412 PROTO_ITEM_SET_HIDDEN(pi);
2418 proto_tree_add_boolean_format_value(proto_tree *tree, int hfindex,
2419 tvbuff_t *tvb, gint start, gint length, guint32 value,
2420 const char *format, ...)
2425 pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
2429 va_start(ap, format);
2430 proto_tree_set_representation_value(pi, format, ap);
2437 proto_tree_add_boolean_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2438 guint32 value, const char *format, ...)
2443 pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
2447 va_start(ap, format);
2448 proto_tree_set_representation(pi, format, ap);
2454 /* Set the FT_BOOLEAN value */
2456 proto_tree_set_boolean(field_info *fi, guint32 value)
2458 proto_tree_set_uint(fi, value);
2461 /* Add a FT_FLOAT to a proto_tree */
2463 proto_tree_add_float(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2468 header_field_info *hfinfo;
2473 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
2475 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2476 DISSECTOR_ASSERT(hfinfo->type == FT_FLOAT);
2478 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2479 proto_tree_set_float(new_fi, value);
2485 proto_tree_add_float_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2490 pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
2494 PROTO_ITEM_SET_HIDDEN(pi);
2500 proto_tree_add_float_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2501 gint start, gint length, float value, const char *format, ...)
2506 pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
2510 va_start(ap, format);
2511 proto_tree_set_representation_value(pi, format, ap);
2518 proto_tree_add_float_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2519 float value, const char *format, ...)
2524 pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
2528 va_start(ap, format);
2529 proto_tree_set_representation(pi, format, ap);
2535 /* Set the FT_FLOAT value */
2537 proto_tree_set_float(field_info *fi, float value)
2539 col_custom_set_fstr(fi->hfinfo, "%." STRINGIFY(FLT_DIG) "f",
2541 fvalue_set_floating(&fi->value, value);
2544 /* Add a FT_DOUBLE to a proto_tree */
2546 proto_tree_add_double(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2551 header_field_info *hfinfo;
2556 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
2558 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2559 DISSECTOR_ASSERT(hfinfo->type == FT_DOUBLE);
2561 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2562 proto_tree_set_double(new_fi, value);
2568 proto_tree_add_double_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2573 pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
2577 PROTO_ITEM_SET_HIDDEN(pi);
2583 proto_tree_add_double_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2584 gint start, gint length, double value, const char *format, ...)
2589 pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
2593 va_start(ap, format);
2594 proto_tree_set_representation_value(pi, format, ap);
2601 proto_tree_add_double_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2602 double value, const char *format, ...)
2607 pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
2611 va_start(ap, format);
2612 proto_tree_set_representation(pi, format, ap);
2618 /* Set the FT_DOUBLE value */
2620 proto_tree_set_double(field_info *fi, double value)
2622 col_custom_set_fstr(fi->hfinfo, "%." STRINGIFY(DBL_DIG) "g",
2624 fvalue_set_floating(&fi->value, value);
2627 /* Add FT_UINT{8,16,24,32} to a proto_tree */
2629 proto_tree_add_uint(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2632 proto_item *pi = NULL;
2634 header_field_info *hfinfo;
2639 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
2641 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2642 switch(hfinfo->type) {
2648 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length,
2650 proto_tree_set_uint(new_fi, value);
2654 DISSECTOR_ASSERT_NOT_REACHED();
2661 proto_tree_add_uint_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2666 pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
2670 PROTO_ITEM_SET_HIDDEN(pi);
2676 proto_tree_add_uint_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2677 gint start, gint length, guint32 value, const char *format, ...)
2682 pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
2686 va_start(ap, format);
2687 proto_tree_set_representation_value(pi, format, ap);
2694 proto_tree_add_uint_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2695 guint32 value, const char *format, ...)
2700 pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
2704 va_start(ap, format);
2705 proto_tree_set_representation(pi, format, ap);
2711 /* Set the FT_UINT{8,16,24,32} value */
2713 proto_tree_set_uint(field_info *fi, guint32 value)
2715 header_field_info *hfinfo;
2718 hfinfo = fi->hfinfo;
2721 if (hfinfo->bitmask) {
2722 /* Mask out irrelevant portions */
2723 integer &= hfinfo->bitmask;
2726 if (hfinfo->bitshift > 0) {
2727 integer >>= hfinfo->bitshift;
2731 if (hfinfo->type == FT_BOOLEAN) {
2732 const true_false_string *tfstring = &tfs_true_false;
2733 if (hfinfo->strings) {
2734 tfstring = (const struct true_false_string*) hfinfo->strings;
2736 col_custom_set_fstr(fi->hfinfo, "%s", integer ? tfstring->true_string : tfstring->false_string);
2737 } else if (hfinfo->strings) {
2738 col_custom_set_fstr(fi->hfinfo, "%s", val_to_str(integer, cVALS(hfinfo->strings), "%d"));
2739 } else if (IS_BASE_DUAL(hfinfo->display)) {
2740 col_custom_set_fstr(fi->hfinfo, hfinfo_uint_value_format(hfinfo), integer, integer);
2742 col_custom_set_fstr(fi->hfinfo, hfinfo_uint_value_format(hfinfo), integer);
2744 fvalue_set_uinteger(&fi->value, integer);
2747 /* Add FT_UINT64 to a proto_tree */
2749 proto_tree_add_uint64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2752 proto_item *pi = NULL;
2754 header_field_info *hfinfo;
2759 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
2761 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2762 DISSECTOR_ASSERT(hfinfo->type == FT_UINT64);
2764 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2765 proto_tree_set_uint64(new_fi, value);
2771 proto_tree_add_uint64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2772 gint start, gint length, guint64 value, const char *format, ...)
2777 pi = proto_tree_add_uint64(tree, hfindex, tvb, start, length, value);
2781 va_start(ap, format);
2782 proto_tree_set_representation_value(pi, format, ap);
2789 proto_tree_add_uint64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2790 guint64 value, const char *format, ...)
2795 pi = proto_tree_add_uint64(tree, hfindex, tvb, start, length, value);
2799 va_start(ap, format);
2800 proto_tree_set_representation(pi, format, ap);
2806 /* Add FT_INT{8,16,24,32} to a proto_tree */
2808 proto_tree_add_int(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2811 proto_item *pi = NULL;
2813 header_field_info *hfinfo;
2818 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
2820 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2821 switch(hfinfo->type) {
2826 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length,
2828 proto_tree_set_int(new_fi, value);
2832 DISSECTOR_ASSERT_NOT_REACHED();
2839 proto_tree_add_int_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2844 pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
2848 PROTO_ITEM_SET_HIDDEN(pi);
2854 proto_tree_add_int_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2855 gint start, gint length, gint32 value, const char *format, ...)
2857 proto_item *pi = NULL;
2860 pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
2864 va_start(ap, format);
2865 proto_tree_set_representation_value(pi, format, ap);
2872 proto_tree_add_int_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2873 gint32 value, const char *format, ...)
2875 proto_item *pi = NULL;
2878 pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
2882 va_start(ap, format);
2883 proto_tree_set_representation(pi, format, ap);
2889 /* Set the FT_INT{8,16,24,32} value */
2891 proto_tree_set_int(field_info *fi, gint32 value)
2893 header_field_info *hfinfo;
2896 hfinfo = fi->hfinfo;
2897 integer = (guint32) value;
2899 if (hfinfo->bitmask) {
2900 /* Mask out irrelevant portions */
2901 integer &= hfinfo->bitmask;
2904 if (hfinfo->bitshift > 0) {
2905 integer >>= hfinfo->bitshift;
2909 if (hfinfo->strings) {
2910 col_custom_set_fstr(fi->hfinfo, "%s", val_to_str(integer, cVALS(hfinfo->strings), "%d"));
2911 } else if (IS_BASE_DUAL(hfinfo->display)) {
2912 col_custom_set_fstr(fi->hfinfo, hfinfo_int_value_format(hfinfo), integer, integer);
2914 col_custom_set_fstr(fi->hfinfo, hfinfo_int_value_format(hfinfo), integer);
2916 fvalue_set_sinteger(&fi->value, integer);
2919 /* Add FT_INT64 to a proto_tree */
2921 proto_tree_add_int64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2924 proto_item *pi = NULL;
2926 header_field_info *hfinfo;
2931 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
2933 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2934 DISSECTOR_ASSERT(hfinfo->type == FT_INT64);
2936 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2937 proto_tree_set_uint64(new_fi, (guint64)value);
2943 proto_tree_add_int64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2944 gint start, gint length, gint64 value, const char *format, ...)
2949 pi = proto_tree_add_int64(tree, hfindex, tvb, start, length, value);
2953 va_start(ap, format);
2954 proto_tree_set_representation_value(pi, format, ap);
2961 proto_tree_add_int64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2962 gint64 value, const char *format, ...)
2967 pi = proto_tree_add_int64(tree, hfindex, tvb, start, length, value);
2971 va_start(ap, format);
2972 proto_tree_set_representation(pi, format, ap);
2978 /* Throw an exception if we exceed this many tree items. */
2979 /* XXX - This should probably be a preference */
2980 #define MAX_TREE_ITEMS (1 * 1000 * 1000)
2981 /* Add a field_info struct to the proto_tree, encapsulating it in a proto_node */
2983 proto_tree_add_node(proto_tree *tree, field_info *fi)
2985 proto_node *pnode, *tnode, *sibling;
2989 * Make sure "tree" is ready to have subtrees under it, by
2990 * checking whether it's been given an ett_ value.
2992 * "tnode->finfo" may be null; that's the case for the root
2993 * node of the protocol tree. That node is not displayed,
2994 * so it doesn't need an ett_ value to remember whether it
2999 if (tfi != NULL && (tfi->tree_type < 0 || tfi->tree_type >= num_tree_types)) {
3000 REPORT_DISSECTOR_BUG(ep_strdup_printf("\"%s\" - \"%s\" tfi->tree_type: %u invalid (%s:%u)",
3001 fi->hfinfo->name, fi->hfinfo->abbrev, tfi->tree_type, __FILE__, __LINE__));
3002 /* XXX - is it safe to continue here? */
3005 DISSECTOR_ASSERT(tfi == NULL ||
3006 (tfi->tree_type >= 0 && tfi->tree_type < num_tree_types));
3008 PTREE_DATA(tree)->count++;
3009 if (PTREE_DATA(tree)->count > MAX_TREE_ITEMS) {
3010 /* Let the exception handler add items to the tree */
3011 PTREE_DATA(tree)->count = 0;
3012 THROW_MESSAGE(DissectorError,
3013 ep_strdup_printf("More than %d items in the tree -- possible infinite loop", MAX_TREE_ITEMS));
3016 PROTO_NODE_NEW(pnode);
3017 pnode->parent = tnode;
3019 pnode->tree_data = PTREE_DATA(tree);
3021 if (tnode->last_child != NULL) {
3022 sibling = tnode->last_child;
3023 DISSECTOR_ASSERT(sibling->next == NULL);
3024 sibling->next = pnode;
3026 tnode->first_child = pnode;
3027 tnode->last_child = pnode;
3029 return (proto_item*)pnode;
3033 /* Generic way to allocate field_info and add to proto_tree.
3034 * Sets *pfi to address of newly-allocated field_info struct, if pfi is
3037 proto_tree_add_pi(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3038 gint *length, field_info **pfi)
3048 fi = alloc_field_info(tree, hfindex, tvb, start, length);
3049 pi = proto_tree_add_node(tree, fi);
3051 /* If the proto_tree wants to keep a record of this finfo
3052 * for quick lookup, then record it. */
3053 if (fi->hfinfo->ref_count) {
3055 hash = PTREE_DATA(tree)->interesting_hfids;
3056 ptrs = g_hash_table_lookup(hash, GINT_TO_POINTER(hfindex));
3058 g_ptr_array_add(ptrs, fi);
3062 /* Does the caller want to know the fi pointer? */
3071 static header_field_info *
3072 get_hfi_and_length(int hfindex, tvbuff_t *tvb, gint start, gint *length,
3075 header_field_info *hfinfo;
3076 gint length_remaining;
3079 * We only allow a null tvbuff if the item has a zero length,
3080 * i.e. if there's no data backing it.
3082 DISSECTOR_ASSERT(tvb != NULL || *length == 0);
3084 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
3087 * XXX - in some protocols, there are 32-bit unsigned length
3088 * fields, so lengths in protocol tree and tvbuff routines
3089 * should really be unsigned. We should have, for those
3090 * field types for which "to the end of the tvbuff" makes sense,
3091 * additional routines that take no length argument and
3092 * add fields that run to the end of the tvbuff.
3094 if (*length == -1) {
3096 * For FT_NONE, FT_PROTOCOL, FT_BYTES, and FT_STRING fields,
3097 * a length of -1 means "set the length to what remains in
3100 * The assumption is either that
3102 * 1) the length of the item can only be determined
3103 * by dissection (typically true of items with
3104 * subitems, which are probably FT_NONE or
3109 * 2) if the tvbuff is "short" (either due to a short
3110 * snapshot length or due to lack of reassembly of
3111 * fragments/segments/whatever), we want to display
3112 * what's available in the field (probably FT_BYTES
3113 * or FT_STRING) and then throw an exception later
3117 * 3) the field is defined to be "what's left in the
3120 * so we set the length to what remains in the tvbuff so
3121 * that, if we throw an exception while dissecting, it
3122 * has what is probably the right value.
3124 * For FT_STRINGZ, it means "the string is null-terminated,
3125 * not null-padded; set the length to the actual length
3126 * of the string", and if the tvbuff if short, we just
3127 * throw an exception.
3129 * It's not valid for any other type of field.
3131 switch (hfinfo->type) {
3135 * We allow this to be zero-length - for
3136 * example, an ONC RPC NULL procedure has
3137 * neither arguments nor reply, so the
3138 * payload for that protocol is empty.
3140 * However, if the length is negative, the
3141 * start offset is *past* the byte past the
3142 * end of the tvbuff, so we throw an
3145 *length = tvb_length_remaining(tvb, start);
3148 * Use "tvb_ensure_bytes_exist()"
3149 * to force the appropriate exception
3152 tvb_ensure_bytes_exist(tvb, start, 0);
3154 DISSECTOR_ASSERT(*length >= 0);
3160 *length = tvb_ensure_length_remaining(tvb, start);
3161 DISSECTOR_ASSERT(*length >= 0);
3166 * Leave the length as -1, so our caller knows
3172 DISSECTOR_ASSERT_NOT_REACHED();
3174 *item_length = *length;
3176 *item_length = *length;
3177 if (hfinfo->type == FT_PROTOCOL || hfinfo->type == FT_NONE) {
3179 * These types are for interior nodes of the
3180 * tree, and don't have data associated with
3181 * them; if the length is negative (XXX - see
3182 * above) or goes past the end of the tvbuff,
3183 * cut it short at the end of the tvbuff.
3184 * That way, if this field is selected in
3185 * Wireshark, we don't highlight stuff past
3186 * the end of the data.
3188 /* XXX - what to do, if we don't have a tvb? */
3190 length_remaining = tvb_length_remaining(tvb, start);
3191 if (*item_length < 0 ||
3192 (*item_length > 0 &&
3193 (length_remaining < *item_length)))
3194 *item_length = length_remaining;
3197 if (*item_length < 0) {
3198 THROW(ReportedBoundsError);
3206 new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
3207 gint start, gint item_length)
3213 fi->hfinfo = hfinfo;
3215 fi->start+=(tvb)?TVB_RAW_OFFSET(tvb):0;
3216 fi->length = item_length;
3219 if (!PTREE_DATA(tree)->visible)
3220 FI_SET_FLAG(fi, FI_HIDDEN);
3221 fvalue_init(&fi->value, fi->hfinfo->type);
3224 /* add the data source tvbuff */
3225 fi->ds_tvb=tvb?TVB_GET_DS_TVB(tvb):NULL;
3227 fi->appendix_start = 0;
3228 fi->appendix_length = 0;
3234 alloc_field_info(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3237 header_field_info *hfinfo;
3240 hfinfo = get_hfi_and_length(hfindex, tvb, start, length, &item_length);
3241 return new_field_info(tree, hfinfo, tvb, start, item_length);
3244 /* If the protocol tree is to be visible, set the representation of a
3245 proto_tree entry with the name of the field for the item and with
3246 the value formatted with the supplied printf-style format and
3249 proto_tree_set_representation_value(proto_item *pi, const char *format, va_list ap)
3251 int ret; /*tmp return value */
3253 field_info *fi = PITEM_FINFO(pi);
3255 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
3256 ITEM_LABEL_NEW(fi->rep);
3259 /* put in the hf name */
3260 ret = g_snprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
3261 "%s: ", fi->hfinfo->name);
3262 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH)) {
3263 /* That's all we can put in the representation. */
3264 fi->rep->representation[ITEM_LABEL_LENGTH - 1] = '\0';
3269 /* Put in the value of the string */
3270 ret = g_vsnprintf(fi->rep->representation + replen,
3271 ITEM_LABEL_LENGTH - replen, format, ap);
3272 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH - replen)) {
3273 /* Uh oh, we don't have enough room. Tell the user
3274 * that the field is truncated.
3278 fi->rep->representation[ITEM_LABEL_LENGTH - 1] = '\0';
3280 /* Argh, we cannot reuse 'ap' here. So make a copy
3281 * of what we formatted for (re)use below.
3283 oldrep = g_strdup(fi->rep->representation);
3285 ret = g_snprintf(fi->rep->representation,
3289 fi->rep->representation[ITEM_LABEL_LENGTH - 1] = '\0';
3295 /* If the protocol tree is to be visible, set the representation of a
3296 proto_tree entry with the representation formatted with the supplied
3297 printf-style format and argument list. */
3299 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap)
3301 int ret; /*tmp return value */
3302 field_info *fi = PITEM_FINFO(pi);
3304 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
3305 ITEM_LABEL_NEW(fi->rep);
3306 ret = g_vsnprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
3308 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH)) {
3309 /* Uh oh, we don't have enough room. Tell the user
3310 * that the field is truncated.
3314 fi->rep->representation[ITEM_LABEL_LENGTH - 1] = '\0';
3316 /* Argh, we cannot reuse 'ap' here. So make a copy
3317 * of what we formatted for (re)use below.
3319 oldrep = g_strdup(fi->rep->representation);
3321 g_snprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
3322 "[truncated] %s", oldrep);
3323 fi->rep->representation[ITEM_LABEL_LENGTH - 1] = '\0';
3329 /* Set text of proto_item after having already been created. */
3331 proto_item_set_text(proto_item *pi, const char *format, ...)
3333 field_info *fi = NULL;
3340 fi = PITEM_FINFO(pi);
3343 ITEM_LABEL_FREE(fi->rep);
3346 va_start(ap, format);
3347 proto_tree_set_representation(pi, format, ap);
3351 /* Append to text of proto_item after having already been created. */
3353 proto_item_append_text(proto_item *pi, const char *format, ...)
3355 field_info *fi = NULL;
3358 int ret; /*tmp return value */
3364 fi = PITEM_FINFO(pi);
3369 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
3370 va_start(ap, format);
3373 * If we don't already have a representation,
3374 * generate the default representation.
3376 if (fi->rep == NULL) {
3377 ITEM_LABEL_NEW(fi->rep);
3378 proto_item_fill_label(fi, fi->rep->representation);
3381 curlen = strlen(fi->rep->representation);
3382 if (ITEM_LABEL_LENGTH > curlen) {
3383 ret = g_vsnprintf(fi->rep->representation + curlen,
3384 ITEM_LABEL_LENGTH - curlen, format, ap);
3385 if ((ret == -1) || (ret >= (int)(ITEM_LABEL_LENGTH - curlen)))
3386 fi->rep->representation[ITEM_LABEL_LENGTH - 1] = '\0';
3393 proto_item_set_len(proto_item *pi, gint length)
3399 fi = PITEM_FINFO(pi);
3400 DISSECTOR_ASSERT(length >= 0);
3401 fi->length = length;
3403 if (fi->value.ftype->ftype == FT_BYTES)
3404 fi->value.value.bytes->len = length;
3408 * Sets the length of the item based on its start and on the specified
3409 * offset, which is the offset past the end of the item; as the start
3410 * in the item is relative to the beginning of the data source tvbuff,
3411 * we need to pass in a tvbuff - the end offset is relative to the beginning
3415 proto_item_set_end(proto_item *pi, tvbuff_t *tvb, gint end)
3421 fi = PITEM_FINFO(pi);
3422 end += TVB_RAW_OFFSET(tvb);
3423 DISSECTOR_ASSERT(end >= fi->start);
3424 fi->length = end - fi->start;
3428 proto_item_get_len(proto_item *pi)
3430 field_info *fi = PITEM_FINFO(pi);
3435 /** clear flags according to the mask and set new flag values */
3436 #define FI_REPLACE_FLAGS(fi, mask, flags_in) { \
3437 (fi->flags = (fi)->flags & ~(mask)); \
3438 (fi->flags = (fi)->flags | (flags_in)); \
3442 proto_item_set_expert_flags(proto_item *pi, int group, guint severity)
3444 if(pi == NULL || pi->finfo == NULL)
3447 /* only change things if severity is worse or at least equal than before */
3448 if(severity >= FI_GET_FLAG(pi->finfo, PI_SEVERITY_MASK)) {
3449 FI_REPLACE_FLAGS(pi->finfo, PI_GROUP_MASK, group);
3450 FI_REPLACE_FLAGS(pi->finfo, PI_SEVERITY_MASK, severity);
3461 proto_tree_create_root(void)
3465 /* Initialize the proto_node */
3466 PROTO_NODE_NEW(pnode);
3467 pnode->parent = NULL;
3468 pnode->finfo = NULL;
3469 pnode->tree_data = g_new(tree_data_t, 1);
3471 /* Initialize the tree_data_t */
3472 pnode->tree_data->interesting_hfids =
3473 g_hash_table_new(g_direct_hash, g_direct_equal);
3475 /* Set the default to FALSE so it's easier to
3476 * find errors; if we expect to see the protocol tree
3477 * but for some reason the default 'visible' is not
3478 * changed, then we'll find out very quickly. */
3479 pnode->tree_data->visible = FALSE;
3481 /* Keep track of the number of children */
3482 pnode->tree_data->count = 0;
3484 return (proto_tree*) pnode;
3488 /* "prime" a proto_tree with a single hfid that a dfilter
3489 * is interested in. */
3491 proto_tree_prime_hfid(proto_tree *tree, gint hfid)
3493 header_field_info *hfinfo;
3495 g_hash_table_insert(PTREE_DATA(tree)->interesting_hfids,
3496 GINT_TO_POINTER(hfid), g_ptr_array_new());
3498 PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
3499 /* this field is referenced by a filter so increase the refcount.
3500 also increase the refcount for the parent, i.e the protocol.
3502 hfinfo->ref_count++;
3503 /* only increase the refcount if there is a parent.
3504 if this is a protocol and not a field then parent will be -1
3505 and there is no parent to add any refcounting for.
3507 if (hfinfo->parent != -1) {
3508 header_field_info *parent_hfinfo;
3509 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
3510 parent_hfinfo->ref_count++;
3515 proto_item_add_subtree(proto_item *pi, gint idx) {
3521 fi = PITEM_FINFO(pi);
3522 DISSECTOR_ASSERT(idx >= 0 && idx < num_tree_types);
3523 fi->tree_type = idx;
3525 return (proto_tree*) pi;
3529 proto_item_get_subtree(proto_item *pi) {
3534 fi = PITEM_FINFO(pi);
3535 if ( (!fi) || (fi->tree_type == -1) )
3537 return (proto_tree*) pi;
3541 proto_item_get_parent(proto_item *ti) {
3548 proto_item_get_parent_nth(proto_item *ti, int gen) {
3561 proto_tree_get_parent(proto_tree *tree) {
3564 return (proto_item*) tree;
3568 proto_tree_get_root(proto_tree *tree) {
3571 while (tree->parent) {
3572 tree = tree->parent;
3578 proto_tree_move_item(proto_tree *tree, proto_item *fixed_item, proto_item *item_to_move)
3580 proto_item *curr_item;
3583 /*** cut item_to_move out ***/
3585 /* is item_to_move the first? */
3586 if(tree->first_child == item_to_move) {
3587 /* simply change first child to next */
3588 tree->first_child = item_to_move->next;
3590 /* find previous and change it's next */
3591 for(curr_item = tree->first_child; curr_item != NULL; curr_item = curr_item->next) {
3592 if(curr_item->next == item_to_move) {
3597 DISSECTOR_ASSERT(curr_item);
3599 curr_item->next = item_to_move->next;
3601 /* fix last_child if required */
3602 if(tree->last_child == item_to_move) {
3603 tree->last_child = curr_item;
3607 /*** insert to_move after fixed ***/
3608 item_to_move->next = fixed_item->next;
3609 fixed_item->next = item_to_move;
3610 if(tree->last_child == fixed_item) {
3611 tree->last_child = item_to_move;
3616 proto_tree_set_appendix(proto_tree *tree, tvbuff_t *tvb, gint start, gint length)
3624 start += TVB_RAW_OFFSET(tvb);
3625 DISSECTOR_ASSERT(start >= 0);
3626 DISSECTOR_ASSERT(length >= 0);
3628 fi->appendix_start = start;
3629 fi->appendix_length = length;
3633 proto_register_protocol(const char *name, const char *short_name, const char *filter_name)
3635 protocol_t *protocol;
3636 header_field_info *hfinfo;
3638 char *existing_name;
3642 gboolean found_invalid;
3645 * Make sure there's not already a protocol with any of those
3646 * names. Crash if there is, as that's an error in the code
3647 * or an inappropriate plugin.
3648 * This situation has to be fixed to not register more than one
3649 * protocol with the same name.
3651 * This is done by reducing the number of strcmp (and alike) calls as much as possible,
3652 * as this significally slows down startup time.
3654 * Drawback: As a hash value is used to reduce insert time,
3655 * this might lead to a hash collision.
3656 * However, as we have around 500+ protocols and we're using a 32 bit int this is very,
3660 key = g_malloc (sizeof(gint));
3661 *key = wrs_str_hash(name);
3662 existing_name = g_hash_table_lookup(proto_names, key);
3663 if (existing_name != NULL) {
3664 /* g_error will terminate the program */
3665 g_error("Duplicate protocol name \"%s\"!"
3666 " This might be caused by an inappropriate plugin or a development error.", name);
3668 g_hash_table_insert(proto_names, key, (gpointer)name);
3670 existing_name = g_hash_table_lookup(proto_short_names, (gpointer)short_name);
3671 if (existing_name != NULL) {
3672 g_error("Duplicate protocol short_name \"%s\"!"
3673 " This might be caused by an inappropriate plugin or a development error.", short_name);
3675 g_hash_table_insert(proto_short_names, (gpointer)short_name, (gpointer)short_name);
3677 found_invalid = FALSE;
3678 for (i = 0; i < strlen(filter_name); i++) {
3680 if (!(islower(c) || isdigit(c) || c == '-' || c == '_' || c == '.')) {
3681 found_invalid = TRUE;
3684 if (found_invalid) {
3685 g_error("Protocol filter name \"%s\" has one or more invalid characters."
3686 " Allowed are lower characters, digits, '-', '_' and '.'."
3687 " This might be caused by an inappropriate plugin or a development error.", filter_name);
3689 existing_name = g_hash_table_lookup(proto_filter_names, (gpointer)filter_name);
3690 if (existing_name != NULL) {
3691 g_error("Duplicate protocol filter_name \"%s\"!"
3692 " This might be caused by an inappropriate plugin or a development error.", filter_name);
3694 g_hash_table_insert(proto_filter_names, (gpointer)filter_name, (gpointer)filter_name);
3696 /* Add this protocol to the list of known protocols; the list
3697 is sorted by protocol short name. */
3698 protocol = g_malloc(sizeof (protocol_t));
3699 protocol->name = name;
3700 protocol->short_name = short_name;
3701 protocol->filter_name = filter_name;
3702 protocol->fields = NULL;
3703 protocol->is_enabled = TRUE; /* protocol is enabled by default */
3704 protocol->can_toggle = TRUE;
3705 /* list will be sorted later by name, when all protocols completed registering */
3706 protocols = g_list_prepend(protocols, protocol);
3708 /* Here we do allocate a new header_field_info struct */
3709 hfinfo = g_mem_chunk_alloc(gmc_hfinfo);
3710 hfinfo->name = name;
3711 hfinfo->abbrev = filter_name;
3712 hfinfo->type = FT_PROTOCOL;
3713 hfinfo->strings = protocol;
3714 hfinfo->bitmask = 0;
3715 hfinfo->bitshift = 0;
3716 hfinfo->ref_count = 0;
3717 hfinfo->blurb = NULL;
3718 hfinfo->parent = -1; /* this field differentiates protos and fields */
3720 proto_id = proto_register_field_init(hfinfo, hfinfo->parent);
3721 protocol->proto_id = proto_id;
3726 * Routines to use to iterate over the protocols.
3727 * The argument passed to the iterator routines is an opaque cookie to
3728 * their callers; it's the GList pointer for the current element in
3730 * The ID of the protocol is returned, or -1 if there is no protocol.
3733 proto_get_first_protocol(void **cookie)
3735 protocol_t *protocol;
3737 if (protocols == NULL)
3739 *cookie = protocols;
3740 protocol = protocols->data;
3741 return protocol->proto_id;
3745 proto_get_next_protocol(void **cookie)
3747 GList *list_item = *cookie;
3748 protocol_t *protocol;
3750 list_item = g_list_next(list_item);
3751 if (list_item == NULL)
3753 *cookie = list_item;
3754 protocol = list_item->data;
3755 return protocol->proto_id;
3759 proto_get_first_protocol_field(int proto_id, void **cookie)
3761 protocol_t *protocol = find_protocol_by_id(proto_id);
3762 hf_register_info *ptr;
3764 if ((protocol == NULL) || (protocol->fields == NULL))
3767 *cookie = protocol->fields;
3768 ptr = protocol->fields->data;
3769 return &ptr->hfinfo;
3773 proto_get_next_protocol_field(void **cookie)
3775 GList *list_item = *cookie;
3776 hf_register_info *ptr;
3778 list_item = g_list_next(list_item);
3779 if (list_item == NULL)
3782 *cookie = list_item;
3783 ptr = list_item->data;
3784 return &ptr->hfinfo;
3788 find_protocol_by_id(int proto_id)
3790 header_field_info *hfinfo;
3795 PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
3796 DISSECTOR_ASSERT(hfinfo->type==FT_PROTOCOL);
3797 return (protocol_t *)hfinfo->strings;
3800 static gint compare_filter_name(gconstpointer proto_arg,
3801 gconstpointer filter_name)
3803 const protocol_t *protocol = proto_arg;
3804 const gchar* f_name = filter_name;
3806 return (strcmp(protocol->filter_name, f_name));
3810 proto_get_id(protocol_t *protocol)
3812 return protocol->proto_id;
3815 int proto_get_id_by_filter_name(const gchar* filter_name)
3818 protocol_t *protocol;
3820 list_entry = g_list_find_custom(protocols, filter_name,
3821 compare_filter_name);
3823 if (list_entry == NULL)
3825 protocol = list_entry->data;
3826 return protocol->proto_id;
3830 proto_get_protocol_name(int proto_id)
3832 protocol_t *protocol;
3834 protocol = find_protocol_by_id(proto_id);
3835 return protocol->name;
3839 proto_get_protocol_short_name(protocol_t *protocol)
3841 if (protocol == NULL)
3843 return protocol->short_name;
3847 proto_get_protocol_filter_name(int proto_id)
3849 protocol_t *protocol;
3851 protocol = find_protocol_by_id(proto_id);
3852 if (protocol == NULL)
3854 return protocol->filter_name;
3858 proto_is_protocol_enabled(protocol_t *protocol)
3860 return protocol->is_enabled;
3864 proto_can_toggle_protocol(int proto_id)
3866 protocol_t *protocol;
3868 protocol = find_protocol_by_id(proto_id);
3869 return protocol->can_toggle;
3873 proto_set_decoding(int proto_id, gboolean enabled)
3875 protocol_t *protocol;
3877 protocol = find_protocol_by_id(proto_id);
3878 DISSECTOR_ASSERT(protocol->can_toggle);
3879 protocol->is_enabled = enabled;
3883 proto_enable_all(void)
3885 protocol_t *protocol;
3886 GList *list_item = protocols;
3888 if (protocols == NULL)
3892 protocol = list_item->data;
3893 if (protocol->can_toggle)
3894 protocol->is_enabled = TRUE;
3895 list_item = g_list_next(list_item);
3900 proto_set_cant_toggle(int proto_id)
3902 protocol_t *protocol;
3904 protocol = find_protocol_by_id(proto_id);
3905 protocol->can_toggle = FALSE;
3908 /* for use with static arrays only, since we don't allocate our own copies
3909 of the header_field_info struct contained within the hf_register_info struct */
3911 proto_register_field_array(int parent, hf_register_info *hf, int num_records)
3914 hf_register_info *ptr = hf;
3917 proto = find_protocol_by_id(parent);
3918 for (i = 0; i < num_records; i++, ptr++) {
3920 * Make sure we haven't registered this yet.
3921 * Most fields have variables associated with them
3922 * that are initialized to -1; some have array elements,
3923 * or possibly uninitialized variables, so we also allow
3924 * 0 (which is unlikely to be the field ID we get back
3925 * from "proto_register_field_init()").
3927 if (*ptr->p_id != -1 && *ptr->p_id != 0) {
3929 "Duplicate field detected in call to proto_register_field_array: %s is already registered\n",
3930 ptr->hfinfo.abbrev);
3934 if (proto != NULL) {
3935 if (proto->fields == NULL) {
3936 proto->fields = g_list_append(NULL, ptr);
3937 proto->last_field = proto->fields;
3940 g_list_append(proto->last_field, ptr)->next;
3943 field_id = proto_register_field_init(&ptr->hfinfo, parent);
3944 *ptr->p_id = field_id;
3948 /* chars allowed in field abbrev */
3950 const guchar fld_abbrev_chars[256] = {
3951 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00-0x0F */
3952 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10-0x1F */
3953 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, /* 0x20-0x2F '-', '.' */
3954 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 0x30-0x3F '0'-'9' */
3955 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x40-0x4F 'A'-'O' */
3956 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 0x50-0x5F 'P'-'Z', '_' */
3957 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x60-0x6F 'a'-'o' */
3958 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 0x70-0x7F 'p'-'z' */
3959 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80-0x8F */
3960 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90-0x9F */
3961 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xA0-0xAF */
3962 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xB0-0xBF */
3963 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xC0-0xCF */
3964 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xD0-0xDF */
3965 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xE0-0xEF */
3966 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xF0-0xFF */
3969 /* temporary function containing assert part for easier profiling */
3970 static void tmp_fld_check_assert(header_field_info *hfinfo) {
3971 /* The field must have a name (with length > 0) */
3972 DISSECTOR_ASSERT(hfinfo->name && hfinfo->name[0]);
3974 /* fields with an empty string for an abbreviation aren't filterable */
3975 DISSECTOR_ASSERT(hfinfo->abbrev);
3977 /* These types of fields are allowed to have value_strings, true_false_strings or a protocol_t struct*/
3978 DISSECTOR_ASSERT((hfinfo->strings == NULL) || (
3979 (hfinfo->type == FT_UINT8) ||
3980 (hfinfo->type == FT_UINT16) ||
3981 (hfinfo->type == FT_UINT24) ||
3982 (hfinfo->type == FT_UINT32) ||
3983 (hfinfo->type == FT_INT8) ||
3984 (hfinfo->type == FT_INT16) ||
3985 (hfinfo->type == FT_INT24) ||
3986 (hfinfo->type == FT_INT32) ||
3987 (hfinfo->type == FT_BOOLEAN) ||
3988 (hfinfo->type == FT_PROTOCOL) ||
3989 (hfinfo->type == FT_FRAMENUM) ));
3991 switch (hfinfo->type) {
3998 /* Hexadecimal and octal are, in printf() and everywhere else,
3999 * unsigned so don't allow dissectors to register a signed
4000 * field to be displayed unsigned. (Else how would we
4001 * display values negative values?)
4003 * If you want to take out this check, be sure to fix
4004 * hfinfo_numeric_format() so that it does not assert out
4005 * when trying to construct a hexadecimal representation of
4008 DISSECTOR_ASSERT(hfinfo->display != BASE_HEX &&
4009 hfinfo->display != BASE_HEX_DEC &&
4010 hfinfo->display != BASE_DEC_HEX &&
4011 hfinfo->display != BASE_OCT);
4018 /* Require integral types (other than frame number, which is
4019 always displayed in decimal) to have a number base */
4020 DISSECTOR_ASSERT(hfinfo->display != BASE_NONE);
4024 /* Don't allow bitfields or value strings for frame numbers */
4025 DISSECTOR_ASSERT(hfinfo->bitmask == 0);
4026 DISSECTOR_ASSERT(hfinfo->strings == NULL);
4035 proto_register_field_init(header_field_info *hfinfo, int parent)
4038 tmp_fld_check_assert(hfinfo);
4040 /* if this is a bitfield, compute bitshift */
4041 if (hfinfo->bitmask) {
4042 hfinfo->bitshift = wrs_count_bitshift(hfinfo->bitmask);
4045 hfinfo->parent = parent;
4046 hfinfo->same_name_next = NULL;
4047 hfinfo->same_name_prev = NULL;
4049 /* if we always add and never delete, then id == len - 1 is correct */
4050 if(gpa_hfinfo.len>=gpa_hfinfo.allocated_len){
4051 if(!gpa_hfinfo.hfi){
4052 gpa_hfinfo.allocated_len=1000;
4053 gpa_hfinfo.hfi=g_malloc(sizeof(header_field_info *)*1000);
4055 gpa_hfinfo.allocated_len+=1000;
4056 gpa_hfinfo.hfi=g_realloc(gpa_hfinfo.hfi, sizeof(header_field_info *)*gpa_hfinfo.allocated_len);
4059 gpa_hfinfo.hfi[gpa_hfinfo.len]=hfinfo;
4061 hfinfo->id = gpa_hfinfo.len - 1;
4063 /* if we have real names, enter this field in the name tree */
4064 if ((hfinfo->name[0] != 0) && (hfinfo->abbrev[0] != 0 )) {
4066 header_field_info *same_name_next_hfinfo;
4069 /* Check that the filter name (abbreviation) is legal;
4070 * it must contain only alphanumerics, '-', "_", and ".". */
4071 c = wrs_check_charset(fld_abbrev_chars, hfinfo->abbrev);
4073 fprintf(stderr, "OOPS: '%c' in '%s'\n", c, hfinfo->abbrev);
4074 DISSECTOR_ASSERT(!c);
4077 /* We allow multiple hfinfo's to be registered under the same
4078 * abbreviation. This was done for X.25, as, depending
4079 * on whether it's modulo-8 or modulo-128 operation,
4080 * some bitfield fields may be in different bits of
4081 * a byte, and we want to be able to refer to that field
4082 * with one name regardless of whether the packets
4083 * are modulo-8 or modulo-128 packets. */
4085 same_name_hfinfo = NULL;
4087 g_tree_insert(gpa_name_tree, (gpointer) (hfinfo->abbrev), hfinfo);
4088 /* GLIB 2.x - if it is already present
4089 * the previous hfinfo with the same name is saved
4090 * to same_name_hfinfo by value destroy callback */
4091 if (same_name_hfinfo) {
4092 /* There's already a field with this name.
4093 * Put it after that field in the list of
4094 * fields with this name, then allow the code
4095 * after this if{} block to replace the old
4096 * hfinfo with the new hfinfo in the GTree. Thus,
4097 * we end up with a linked-list of same-named hfinfo's,
4098 * with the root of the list being the hfinfo in the GTree */
4099 same_name_next_hfinfo =
4100 same_name_hfinfo->same_name_next;
4102 hfinfo->same_name_next = same_name_next_hfinfo;
4103 if (same_name_next_hfinfo)
4104 same_name_next_hfinfo->same_name_prev = hfinfo;
4106 same_name_hfinfo->same_name_next = hfinfo;
4107 hfinfo->same_name_prev = same_name_hfinfo;
4115 proto_register_subtree_array(gint *const *indices, int num_indices)
4118 gint *const *ptr = indices;
4121 * If we've already allocated the array of tree types, expand
4122 * it; this lets plugins such as mate add tree types after
4123 * the initial startup. (If we haven't already allocated it,
4124 * we don't allocate it; on the first pass, we just assign
4125 * ett values and keep track of how many we've assigned, and
4126 * when we're finished registering all dissectors we allocate
4127 * the array, so that we do only one allocation rather than
4128 * wasting CPU time and memory by growing the array for each
4129 * dissector that registers ett values.)
4131 if (tree_is_expanded != NULL) {
4133 g_realloc(tree_is_expanded,
4134 (num_tree_types+num_indices)*sizeof (gboolean));
4135 memset(tree_is_expanded + num_tree_types, 0,
4136 num_indices*sizeof (gboolean));
4140 * Assign "num_indices" subtree numbers starting at "num_tree_types",
4141 * returning the indices through the pointers in the array whose
4142 * first element is pointed to by "indices", and update
4143 * "num_tree_types" appropriately.
4145 for (i = 0; i < num_indices; i++, ptr++, num_tree_types++)
4146 **ptr = num_tree_types;
4150 proto_item_fill_label(field_info *fi, gchar *label_str)
4152 header_field_info *hfinfo = fi->hfinfo;
4158 guint32 n_addr; /* network-order IPv4 address */
4160 int ret; /*tmp return value */
4162 switch(hfinfo->type) {
4165 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4166 "%s", hfinfo->name);
4167 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4168 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4172 fill_label_boolean(fi, label_str);
4177 bytes = fvalue_get(&fi->value);
4179 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4180 "%s: %s", hfinfo->name,
4181 bytes_to_str(bytes, fvalue_length(&fi->value)));
4182 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH)) {
4183 /* Uh oh, we don't have enough room. Tell the
4184 * user that the field is truncated.
4186 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4187 "%s [truncated]: %s",
4189 bytes_to_str(bytes, fvalue_length(&fi->value)));
4190 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4194 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4195 "%s: <MISSING>", hfinfo->name);
4196 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4197 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4201 /* Four types of integers to take care of:
4202 * Bitfield, with val_string
4203 * Bitfield, w/o val_string
4204 * Non-bitfield, with val_string
4205 * Non-bitfield, w/o val_string
4212 if (hfinfo->bitmask) {
4213 if (hfinfo->strings) {
4214 fill_label_enumerated_bitfield(fi, label_str);
4217 fill_label_numeric_bitfield(fi, label_str);
4221 if (hfinfo->strings) {
4222 fill_label_enumerated_uint(fi, label_str);
4225 fill_label_uint(fi, label_str);
4231 fill_label_uint64(fi, label_str);
4238 DISSECTOR_ASSERT(!hfinfo->bitmask);
4239 if (hfinfo->strings) {
4240 fill_label_enumerated_int(fi, label_str);
4243 fill_label_int(fi, label_str);
4248 fill_label_int64(fi, label_str);
4252 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4253 "%s: %." STRINGIFY(FLT_DIG) "f",
4254 hfinfo->name, fvalue_get_floating(&fi->value));
4255 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4256 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4260 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4261 "%s: %." STRINGIFY(DBL_DIG) "g",
4262 hfinfo->name, fvalue_get_floating(&fi->value));
4263 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4264 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4267 case FT_ABSOLUTE_TIME:
4268 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4269 "%s: %s", hfinfo->name,
4270 abs_time_to_str(fvalue_get(&fi->value)));
4271 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4272 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4275 case FT_RELATIVE_TIME:
4276 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4277 "%s: %s seconds", hfinfo->name,
4278 rel_time_to_secs_str(fvalue_get(&fi->value)));
4279 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4280 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4284 integer = fvalue_get_uinteger(&fi->value);
4285 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4286 "%s: %s (0x%08X)", hfinfo->name,
4287 get_ipxnet_name(integer), integer);
4288 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4289 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4293 bytes = fvalue_get(&fi->value);
4294 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4295 "%s: %s (%s)", hfinfo->name,
4296 get_ether_name(bytes),
4297 ether_to_str(bytes));
4298 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4299 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4303 ipv4 = fvalue_get(&fi->value);
4304 n_addr = ipv4_get_net_order_addr(ipv4);
4305 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4306 "%s: %s (%s)", hfinfo->name,
4307 get_hostname(n_addr),
4308 ip_to_str((guint8*)&n_addr));
4309 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4310 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4314 bytes = fvalue_get(&fi->value);
4315 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4316 "%s: %s (%s)", hfinfo->name,
4317 get_hostname6((struct e_in6_addr *)bytes),
4318 ip6_to_str((struct e_in6_addr*)bytes));
4319 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4320 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4324 guid = fvalue_get(&fi->value);
4325 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4326 "%s: %s", hfinfo->name,
4328 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4329 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4333 bytes = fvalue_get(&fi->value);
4334 name = oid_resolved_from_encoded(bytes, fvalue_length(&fi->value));
4336 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4337 "%s: %s (%s)", hfinfo->name,
4338 oid_encoded2string(bytes, fvalue_length(&fi->value)), name);
4340 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4341 "%s: %s", hfinfo->name,
4342 oid_encoded2string(bytes, fvalue_length(&fi->value)));
4344 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4345 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4351 case FT_UINT_STRING:
4352 bytes = fvalue_get(&fi->value);
4353 if(strlen(bytes) > ITEM_LABEL_LENGTH) {
4354 /* Uh oh, we don't have enough room. Tell the
4355 * user that the field is truncated.
4357 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4358 "%s [truncated]: %s",
4360 format_text(bytes, strlen(bytes)));
4362 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4363 "%s: %s", hfinfo->name,
4364 format_text(bytes, strlen(bytes)));
4366 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4367 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4371 g_error("hfinfo->type %d (%s) not handled\n",
4373 ftype_name(hfinfo->type));
4374 DISSECTOR_ASSERT_NOT_REACHED();
4380 fill_label_boolean(field_info *fi, gchar *label_str)
4382 char *p = label_str;
4383 int bitfield_byte_length = 0, bitwidth;
4384 guint32 unshifted_value;
4386 int ret; /*tmp return value */
4388 header_field_info *hfinfo = fi->hfinfo;
4389 const true_false_string *tfstring = &tfs_true_false;
4391 if (hfinfo->strings) {
4392 tfstring = (const struct true_false_string*) hfinfo->strings;
4395 value = fvalue_get_uinteger(&fi->value);
4396 if (hfinfo->bitmask) {
4397 /* Figure out the bit width */
4398 bitwidth = hfinfo_bitwidth(hfinfo);
4401 unshifted_value = value;
4402 if (hfinfo->bitshift > 0) {
4403 unshifted_value <<= hfinfo->bitshift;
4406 /* Create the bitfield first */
4407 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
4408 bitfield_byte_length = p - label_str;
4411 /* Fill in the textual info */
4412 ret = g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
4413 "%s: %s", hfinfo->name,
4414 value ? tfstring->true_string : tfstring->false_string);
4415 if ((ret == -1) || (ret >= (ITEM_LABEL_LENGTH - bitfield_byte_length)))
4416 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4420 /* Fills data for bitfield ints with val_strings */
4422 fill_label_enumerated_bitfield(field_info *fi, gchar *label_str)
4424 const char *format = NULL;
4426 int bitfield_byte_length, bitwidth;
4427 guint32 unshifted_value;
4429 int ret; /*tmp return value */
4431 header_field_info *hfinfo = fi->hfinfo;
4433 /* Figure out the bit width */
4434 bitwidth = hfinfo_bitwidth(hfinfo);
4436 /* Pick the proper format string */
4437 format = hfinfo_uint_vals_format(hfinfo);
4440 unshifted_value = fvalue_get_uinteger(&fi->value);
4441 value = unshifted_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 = p - label_str;
4450 /* Fill in the textual info using stored (shifted) value */
4451 ret = g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
4452 format, hfinfo->name,
4453 val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
4454 if ((ret == -1) || (ret >= (ITEM_LABEL_LENGTH - bitfield_byte_length)))
4455 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4459 fill_label_numeric_bitfield(field_info *fi, gchar *label_str)
4461 const char *format = NULL;
4463 int bitfield_byte_length, bitwidth;
4464 guint32 unshifted_value;
4466 int ret; /*tmp return value */
4468 header_field_info *hfinfo = fi->hfinfo;
4470 /* Figure out the bit width */
4471 bitwidth = hfinfo_bitwidth(hfinfo);
4473 /* Pick the proper format string */
4474 format = hfinfo_uint_format(hfinfo);
4477 unshifted_value = fvalue_get_uinteger(&fi->value);
4478 value = unshifted_value;
4479 if (hfinfo->bitshift > 0) {
4480 unshifted_value <<= hfinfo->bitshift;
4483 /* Create the bitfield using */
4484 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
4485 bitfield_byte_length = p - label_str;
4487 /* Fill in the textual info using stored (shifted) value */
4488 if (IS_BASE_DUAL(hfinfo->display)) {
4489 ret = g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
4490 format, hfinfo->name, value, value);
4492 ret = g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
4493 format, hfinfo->name, value);
4495 if ((ret == -1) || (ret >= (ITEM_LABEL_LENGTH - bitfield_byte_length)))
4496 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4501 fill_label_enumerated_uint(field_info *fi, gchar *label_str)
4503 const char *format = NULL;
4504 header_field_info *hfinfo = fi->hfinfo;
4506 int ret; /*tmp return value */
4508 /* Pick the proper format string */
4509 format = hfinfo_uint_vals_format(hfinfo);
4511 value = fvalue_get_uinteger(&fi->value);
4513 /* Fill in the textual info */
4514 if (hfinfo->display & BASE_RANGE_STRING) {
4515 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4516 format, hfinfo->name,
4517 rval_to_str(value, hfinfo->strings, "Unknown"), value);
4519 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4520 format, hfinfo->name,
4521 val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
4523 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4524 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4528 fill_label_uint(field_info *fi, gchar *label_str)
4530 const char *format = NULL;
4531 header_field_info *hfinfo = fi->hfinfo;
4533 int ret; /*tmp return value */
4535 /* Pick the proper format string */
4536 format = hfinfo_uint_format(hfinfo);
4537 value = fvalue_get_uinteger(&fi->value);
4539 /* Fill in the textual info */
4540 if (IS_BASE_DUAL(hfinfo->display)) {
4541 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4542 format, hfinfo->name, value, value);
4544 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4545 format, hfinfo->name, value);
4547 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4548 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4552 fill_label_uint64(field_info *fi, gchar *label_str)
4554 const char *format = NULL;
4555 header_field_info *hfinfo = fi->hfinfo;
4557 int ret; /*tmp return value */
4559 /* Pick the proper format string */
4560 format = hfinfo_uint64_format(hfinfo);
4561 value = fvalue_get_integer64(&fi->value);
4563 /* Fill in the textual info */
4564 if (IS_BASE_DUAL(hfinfo->display)) {
4565 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4566 format, hfinfo->name, value, value);
4568 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4569 format, hfinfo->name, value);
4571 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4572 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4576 fill_label_enumerated_int(field_info *fi, gchar *label_str)
4578 const char *format = NULL;
4579 header_field_info *hfinfo = fi->hfinfo;
4581 int ret; /*tmp return value */
4583 /* Pick the proper format string */
4584 format = hfinfo_int_vals_format(hfinfo);
4585 value = fvalue_get_sinteger(&fi->value);
4587 /* Fill in the textual info */
4588 if (hfinfo->display & BASE_RANGE_STRING) {
4589 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4590 format, hfinfo->name,
4591 rval_to_str(value, hfinfo->strings, "Unknown"), value);
4593 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4594 format, hfinfo->name,
4595 val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
4597 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4598 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4602 fill_label_int(field_info *fi, gchar *label_str)
4604 const char *format = NULL;
4605 header_field_info *hfinfo = fi->hfinfo;
4607 int ret; /*tmp return value */
4609 /* Pick the proper format string */
4610 format = hfinfo_int_format(hfinfo);
4611 value = fvalue_get_sinteger(&fi->value);
4613 /* Fill in the textual info */
4614 if (IS_BASE_DUAL(hfinfo->display)) {
4615 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4616 format, hfinfo->name, value, value);
4618 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4619 format, hfinfo->name, value);
4621 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4622 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4626 fill_label_int64(field_info *fi, gchar *label_str)
4628 const char *format = NULL;
4629 header_field_info *hfinfo = fi->hfinfo;
4631 int ret; /*tmp return value */
4633 /* Pick the proper format string */
4634 format = hfinfo_int64_format(hfinfo);
4635 value = fvalue_get_integer64(&fi->value);
4637 /* Fill in the textual info */
4638 if (IS_BASE_DUAL(hfinfo->display)) {
4639 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4640 format, hfinfo->name, value, value);
4642 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4643 format, hfinfo->name, value);
4645 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4646 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4650 hfinfo_bitwidth(header_field_info *hfinfo)
4654 if (!hfinfo->bitmask) {
4658 switch(hfinfo->type) {
4676 bitwidth = hfinfo->display; /* hacky? :) */
4679 DISSECTOR_ASSERT_NOT_REACHED();
4686 hfinfo_uint_vals_format(header_field_info *hfinfo)
4688 const char *format = NULL;
4690 /* bit operation to reset the potential BASE_RANGE_STRING (or others in
4692 switch(hfinfo->display & BASE_STRUCTURE_RESET) {
4695 format = "%s: %s (%u)";
4697 case BASE_OCT: /* I'm lazy */
4698 format = "%s: %s (%o)";
4702 switch(hfinfo->type) {
4704 format = "%s: %s (0x%02x)";
4707 format = "%s: %s (0x%04x)";
4710 format = "%s: %s (0x%06x)";
4713 format = "%s: %s (0x%08x)";
4716 DISSECTOR_ASSERT_NOT_REACHED();
4721 DISSECTOR_ASSERT_NOT_REACHED();
4728 hfinfo_uint_format(header_field_info *hfinfo)
4730 const char *format = NULL;
4732 /* Pick the proper format string */
4733 if (hfinfo->type == FT_FRAMENUM) {
4735 * Frame numbers are always displayed in decimal.
4739 switch(hfinfo->display) {
4744 switch(hfinfo->type) {
4746 format = "%s: %u (0x%02x)";
4749 format = "%s: %u (0x%04x)";
4752 format = "%s: %u (0x%06x)";
4755 format = "%s: %u (0x%08x)";
4758 DISSECTOR_ASSERT_NOT_REACHED();
4762 case BASE_OCT: /* I'm lazy */
4766 switch(hfinfo->type) {
4768 format = "%s: 0x%02x";
4771 format = "%s: 0x%04x";
4774 format = "%s: 0x%06x";
4777 format = "%s: 0x%08x";
4780 DISSECTOR_ASSERT_NOT_REACHED();
4785 switch(hfinfo->type) {
4787 format = "%s: 0x%02x (%u)";
4790 format = "%s: 0x%04x (%u)";
4793 format = "%s: 0x%06x (%u)";
4796 format = "%s: 0x%08x (%u)";
4799 DISSECTOR_ASSERT_NOT_REACHED();
4804 DISSECTOR_ASSERT_NOT_REACHED();
4812 hfinfo_uint_value_format(header_field_info *hfinfo)
4814 const char *format = NULL;
4816 /* Pick the proper format string */
4817 if (hfinfo->type == FT_FRAMENUM) {
4819 * Frame numbers are always displayed in decimal.
4823 switch(hfinfo->display) {
4828 switch(hfinfo->type) {
4830 format = "%u (0x%02x)";
4833 format = "%u (0x%04x)";
4836 format = "%u (0x%06x)";
4839 format = "%u (0x%08x)";
4842 DISSECTOR_ASSERT_NOT_REACHED();
4850 switch(hfinfo->type) {
4864 DISSECTOR_ASSERT_NOT_REACHED();
4869 switch(hfinfo->type) {
4871 format = "0x%02x (%u)";
4874 format = "0x%04x (%u)";
4877 format = "0x%06x (%u)";
4880 format = "0x%08x (%u)";
4883 DISSECTOR_ASSERT_NOT_REACHED();
4888 DISSECTOR_ASSERT_NOT_REACHED();
4896 hfinfo_int_vals_format(header_field_info *hfinfo)
4898 const char *format = NULL;
4900 /* bit operation to reset the potential BASE_RANGE_STRING (or others in
4902 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 return g_hash_table_lookup(PTREE_DATA(tree)->interesting_hfids,
5244 GINT_TO_POINTER(id));
5248 /* Helper struct for proto_find_info() and proto_all_finfos() */
5254 /* Helper function for proto_find_info() */
5256 find_finfo(proto_node *node, gpointer data)
5258 field_info *fi = PITEM_FINFO(node);
5259 if (fi && fi->hfinfo) {
5260 if (fi->hfinfo->id == ((ffdata_t*)data)->id) {
5261 g_ptr_array_add(((ffdata_t*)data)->array, fi);
5265 /* Don't stop traversing. */
5269 /* Return GPtrArray* of field_info pointers for all hfindex that appear in a tree.
5270 * This works on any proto_tree, primed or unprimed, but actually searches
5271 * the tree, so it is slower than using proto_get_finfo_ptr_array on a primed tree.
5272 * The caller does need to free the returned GPtrArray with
5273 * g_ptr_array_free(<array>, FALSE).
5276 proto_find_finfo(proto_tree *tree, int id)
5280 ffdata.array = g_ptr_array_new();
5283 proto_tree_traverse_pre_order(tree, find_finfo, &ffdata);
5285 return ffdata.array;
5288 /* Helper function for proto_all_finfos() */
5290 every_finfo(proto_node *node, gpointer data)
5292 field_info *fi = PITEM_FINFO(node);
5293 if (fi && fi->hfinfo) {
5294 g_ptr_array_add(((ffdata_t*)data)->array, fi);
5297 /* Don't stop traversing. */
5301 /* Return GPtrArray* of field_info pointers containing all hfindexes that appear in a tree. */
5303 proto_all_finfos(proto_tree *tree)
5307 ffdata.array = g_ptr_array_new();
5310 proto_tree_traverse_pre_order(tree, every_finfo, &ffdata);
5312 return ffdata.array;
5323 check_for_offset(proto_node *node, gpointer data)
5325 field_info *fi = PITEM_FINFO(node);
5326 offset_search_t *offsearch = data;
5328 /* !fi == the top most container node which holds nothing */
5329 if (fi && !PROTO_ITEM_IS_HIDDEN(node) && fi->ds_tvb && offsearch->tvb == fi->ds_tvb) {
5330 if (offsearch->offset >= (guint) fi->start &&
5331 offsearch->offset < (guint) (fi->start + fi->length)) {
5333 offsearch->finfo = fi;
5334 return FALSE; /* keep traversing */
5337 return FALSE; /* keep traversing */
5340 /* Search a proto_tree backwards (from leaves to root) looking for the field
5341 * whose start/length occupies 'offset' */
5342 /* XXX - I couldn't find an easy way to search backwards, so I search
5343 * forwards, w/o stopping. Therefore, the last finfo I find will the be
5344 * the one I want to return to the user. This algorithm is inefficient
5345 * and could be re-done, but I'd have to handle all the children and
5346 * siblings of each node myself. When I have more time I'll do that.
5349 proto_find_field_from_offset(proto_tree *tree, guint offset, tvbuff_t *tvb)
5351 offset_search_t offsearch;
5353 offsearch.offset = offset;
5354 offsearch.finfo = NULL;
5355 offsearch.tvb = tvb;
5357 proto_tree_traverse_pre_order(tree, check_for_offset, &offsearch);
5359 return offsearch.finfo;
5362 /* Dumps the protocols in the registration database to stdout. An independent
5363 * program can take this output and format it into nice tables or HTML or
5366 * There is one record per line. The fields are tab-delimited.
5368 * Field 1 = protocol name
5369 * Field 2 = protocol short name
5370 * Field 3 = protocol filter name
5373 proto_registrar_dump_protocols(void)
5375 protocol_t *protocol;
5377 void *cookie = NULL;
5379 for (i = proto_get_first_protocol(&cookie); i != -1;
5380 i = proto_get_next_protocol(&cookie)) {
5381 protocol = find_protocol_by_id(i);
5382 printf("%s\t%s\t%s\n", protocol->name, protocol->short_name,
5383 protocol->filter_name);
5387 /* Dumps the value_string and true/false strings for fields that have
5388 * them. There is one record per line. Fields are tab-delimited.
5389 * There are two types of records, Value String records and True/False
5390 * String records. The first field, 'V' or 'T', indicates the type
5396 * Field 2 = field abbreviation to which this value string corresponds
5397 * Field 3 = Integer value
5400 * True/False Strings
5401 * ------------------
5403 * Field 2 = field abbreviation to which this true/false string corresponds
5404 * Field 3 = True String
5405 * Field 4 = False String
5408 proto_registrar_dump_values(void)
5410 header_field_info *hfinfo, *parent_hfinfo;
5412 const value_string *vals;
5413 const true_false_string *tfs;
5415 len = gpa_hfinfo.len;
5416 for (i = 0; i < len ; i++) {
5417 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
5419 if (hfinfo->id == hf_text_only) {
5423 /* ignore protocols */
5424 if (proto_registrar_is_protocol(i)) {
5427 /* process header fields */
5430 * If this field isn't at the head of the list of
5431 * fields with this name, skip this field - all
5432 * fields with the same name are really just versions
5433 * of the same field stored in different bits, and
5434 * should have the same type/radix/value list, and
5435 * just differ in their bit masks. (If a field isn't
5436 * a bitfield, but can be, say, 1 or 2 bytes long,
5437 * it can just be made FT_UINT16, meaning the
5438 * *maximum* length is 2 bytes, and be used
5441 if (hfinfo->same_name_prev != NULL)
5444 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
5449 if (hfinfo->type == FT_UINT8 ||
5450 hfinfo->type == FT_UINT16 ||
5451 hfinfo->type == FT_UINT24 ||
5452 hfinfo->type == FT_UINT32 ||
5453 hfinfo->type == FT_UINT64 ||
5454 hfinfo->type == FT_INT8 ||
5455 hfinfo->type == FT_INT16 ||
5456 hfinfo->type == FT_INT24 ||
5457 hfinfo->type == FT_INT32 ||
5458 hfinfo->type == FT_INT64) {
5460 vals = hfinfo->strings;
5462 else if (hfinfo->type == FT_BOOLEAN) {
5463 tfs = hfinfo->strings;
5466 /* Print value strings? */
5469 while (vals[vi].strptr) {
5470 /* Print in the proper base */
5471 if (hfinfo->display == BASE_HEX) {
5472 printf("V\t%s\t0x%x\t%s\n",
5478 printf("V\t%s\t%u\t%s\n",
5487 /* Print true/false strings? */
5489 printf("T\t%s\t%s\t%s\n", hfinfo->abbrev,
5490 tfs->true_string, tfs->false_string);
5496 /* Dumps the contents of the registration database to stdout. An indepedent
5497 * program can take this output and format it into nice tables or HTML or
5500 * There is one record per line. Each record is either a protocol or a header
5501 * field, differentiated by the first field. The fields are tab-delimited.
5506 * Field 2 = descriptive protocol name
5507 * Field 3 = protocol abbreviation
5513 * Field 2 = descriptive field name
5514 * Field 3 = field abbreviation
5515 * Field 4 = type ( textual representation of the the ftenum type )
5516 * Field 5 = parent protocol abbreviation
5517 * Field 6 = blurb describing field
5521 * Field 2 = descriptive field name
5522 * Field 3 = field abbreviation
5523 * Field 4 = type ( textual representation of the the ftenum type )
5524 * Field 5 = parent protocol abbreviation
5525 * Field 6 = blurb describing field
5526 * Field 7 = base for display (for integer types)
5527 * Field 8 = blurb describing field (yes, apparently we repeated this accidentally)
5531 * Field 2 = descriptive field name
5532 * Field 3 = field abbreviation
5533 * Field 4 = type ( textual representation of the the ftenum type )
5534 * Field 5 = parent protocol abbreviation
5535 * Field 6 = blurb describing field
5536 * Field 7 = base for display (for integer types)
5540 proto_registrar_dump_fields(int format)
5542 header_field_info *hfinfo, *parent_hfinfo;
5544 const char *enum_name;
5545 const char *base_name;
5548 len = gpa_hfinfo.len;
5549 for (i = 0; i < len ; i++) {
5550 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
5553 * Skip the pseudo-field for "proto_tree_add_text()" since
5554 * we don't want it in the list of filterable fields.
5556 if (hfinfo->id == hf_text_only)
5559 /* format for protocols */
5560 if (proto_registrar_is_protocol(i)) {
5561 printf("P\t%s\t%s\n", hfinfo->name, hfinfo->abbrev);
5563 /* format for header fields */
5566 * If this field isn't at the head of the list of
5567 * fields with this name, skip this field - all
5568 * fields with the same name are really just versions
5569 * of the same field stored in different bits, and
5570 * should have the same type/radix/value list, and
5571 * just differ in their bit masks. (If a field isn't
5572 * a bitfield, but can be, say, 1 or 2 bytes long,
5573 * it can just be made FT_UINT16, meaning the
5574 * *maximum* length is 2 bytes, and be used
5577 if (hfinfo->same_name_prev != NULL)
5580 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
5582 enum_name = ftype_name(hfinfo->type);
5586 if (hfinfo->type == FT_UINT8 ||
5587 hfinfo->type == FT_UINT16 ||
5588 hfinfo->type == FT_UINT24 ||
5589 hfinfo->type == FT_UINT32 ||
5590 hfinfo->type == FT_UINT64 ||
5591 hfinfo->type == FT_INT8 ||
5592 hfinfo->type == FT_INT16 ||
5593 hfinfo->type == FT_INT24 ||
5594 hfinfo->type == FT_INT32 ||
5595 hfinfo->type == FT_INT64) {
5598 switch(hfinfo->display) {
5600 base_name = "BASE_NONE";
5603 base_name = "BASE_DEC";
5606 base_name = "BASE_HEX";
5609 base_name = "BASE_OCT";
5612 base_name = "BASE_DEC_HEX";
5615 base_name = "BASE_HEX_DEC";
5621 blurb = hfinfo->blurb;
5625 printf("F\t%s\t%s\t%s\t%s\t%s\n",
5626 hfinfo->name, hfinfo->abbrev, enum_name,
5627 parent_hfinfo->abbrev, blurb);
5629 else if (format == 2) {
5630 printf("F\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n",
5631 hfinfo->name, hfinfo->abbrev, enum_name,
5632 parent_hfinfo->abbrev, blurb,
5635 else if (format == 3) {
5636 printf("F\t%s\t%s\t%s\t%s\t%s\t%s\t%u\n",
5637 hfinfo->name, hfinfo->abbrev, enum_name,
5638 parent_hfinfo->abbrev, blurb,
5639 base_name, hfinfo->bitmask);
5642 g_assert_not_reached();
5649 hfinfo_numeric_format(header_field_info *hfinfo)
5651 const char *format = NULL;
5653 /* Pick the proper format string */
5654 if (hfinfo->type == FT_FRAMENUM) {
5656 * Frame numbers are always displayed in decimal.
5658 format = "%s == %u";
5660 /* Pick the proper format string, ignoring BASE_RANGE_STRING flag */
5661 switch(hfinfo->display & ~BASE_RANGE_STRING) {
5664 case BASE_OCT: /* I'm lazy */
5665 switch(hfinfo->type) {
5670 format = "%s == %u";
5673 format = "%s == %" G_GINT64_MODIFIER "u";
5679 format = "%s == %d";
5682 format = "%s == %" G_GINT64_MODIFIER "d";
5685 DISSECTOR_ASSERT_NOT_REACHED();
5691 switch(hfinfo->type) {
5693 format = "%s == 0x%02x";
5696 format = "%s == 0x%04x";
5699 format = "%s == 0x%06x";
5702 format = "%s == 0x%08x";
5705 format = "%s == 0x%016" G_GINT64_MODIFIER "x";
5708 DISSECTOR_ASSERT_NOT_REACHED();
5713 DISSECTOR_ASSERT_NOT_REACHED();
5720 /* This function indicates whether it's possible to construct a
5721 * "match selected" display filter string for the specified field,
5722 * returns an indication of whether it's possible, and, if it's
5723 * possible and "filter" is non-null, constructs the filter and
5724 * sets "*filter" to point to it.
5725 * You do not need to [g_]free() this string since it will be automatically
5726 * freed once the next packet is dissected.
5729 construct_match_selected_string(field_info *finfo, epan_dissect_t *edt,
5732 header_field_info *hfinfo;
5738 gint start, length, length_remaining;
5740 gchar is_signed_num = FALSE;
5742 hfinfo = finfo->hfinfo;
5743 DISSECTOR_ASSERT(hfinfo);
5744 abbrev_len = strlen(hfinfo->abbrev);
5747 * XXX - we can't use the "val_to_string_repr" and "string_repr_len"
5748 * functions for FT_UINT and FT_INT types, as we choose the base in
5749 * the string expression based on the display base of the field.
5751 * Note that the base does matter, as this is also used for
5752 * the protocolinfo tap.
5754 * It might be nice to use them in "proto_item_fill_label()"
5755 * as well, although, there, you'd have to deal with the base
5756 * *and* with resolved values for addresses.
5758 * Perhaps we need two different val_to_string routines, one
5759 * to generate items for display filters and one to generate
5760 * strings for display, and pass to both of them the
5761 * "display" and "strings" values in the header_field_info
5762 * structure for the field, so they can get the base and,
5763 * if the field is Boolean or an enumerated integer type,
5764 * the tables used to generate human-readable values.
5766 switch(hfinfo->type) {
5772 is_signed_num = TRUE;
5779 * 4 bytes for " == ".
5782 * a sign + up to 10 digits of 32-bit integer,
5785 * "0x" + 8 digits of 32-bit integer, in hex;
5787 * 11 digits of 32-bit integer, in octal.
5788 * (No, we don't do octal, but this way,
5789 * we know that if we do, this will still
5792 * 1 byte for the trailing '\0'.
5794 if (filter != NULL) {
5795 dfilter_len = abbrev_len + 4 + 11 + 1;
5796 *filter = ep_alloc0(dfilter_len);
5797 format = hfinfo_numeric_format(hfinfo);
5799 g_snprintf(*filter, dfilter_len, format,
5801 fvalue_get_sinteger(&finfo->value));
5803 g_snprintf(*filter, dfilter_len, format,
5805 fvalue_get_uinteger(&finfo->value));
5813 * 4 bytes for " == ".
5816 * a sign + up to 20 digits of 32-bit integer,
5819 * "0x" + 16 digits of 32-bit integer, in hex;
5821 * 22 digits of 32-bit integer, in octal.
5822 * (No, we don't do octal, but this way,
5823 * we know that if we do, this will still
5826 * 1 byte for the trailing '\0'.
5828 if (filter != NULL) {
5829 dfilter_len = abbrev_len + 4 + 22 + 1;
5830 *filter = ep_alloc0(dfilter_len);
5831 format = hfinfo_numeric_format(hfinfo);
5832 g_snprintf(*filter, dfilter_len, format,
5834 fvalue_get_integer64(&finfo->value));
5840 *filter = ep_strdup(finfo->hfinfo->abbrev);
5846 * If the length is 0, just match the name of the
5849 * (Also check for negative values, just in case,
5850 * as we'll cast it to an unsigned value later.)
5852 length = finfo->length;
5855 *filter = ep_strdup(finfo->hfinfo->abbrev);
5862 * This doesn't have a value, so we'd match
5863 * on the raw bytes at this address.
5865 * Should we be allowed to access to the raw bytes?
5866 * If "edt" is NULL, the answer is "no".
5872 * Is this field part of the raw frame tvbuff?
5873 * If not, we can't use "frame[N:M]" to match
5876 * XXX - should this be frame-relative, or
5877 * protocol-relative?
5879 * XXX - does this fallback for non-registered
5880 * fields even make sense?
5882 if (finfo->ds_tvb != edt->tvb)
5883 return FALSE; /* you lose */
5886 * Don't go past the end of that tvbuff.
5888 length_remaining = tvb_length_remaining(finfo->ds_tvb, finfo->start);
5889 if (length > length_remaining)
5890 length = length_remaining;
5894 if (filter != NULL) {
5895 start = finfo->start;
5896 buf_len = 32 + length * 3;
5897 *filter = ep_alloc0(buf_len);
5900 ptr += g_snprintf(ptr, buf_len-(ptr-*filter),
5901 "frame[%d:%d] == ", finfo->start, length);
5902 for (i=0;i<length; i++) {
5903 c = tvb_get_guint8(finfo->ds_tvb, start);
5906 ptr += g_snprintf(ptr, buf_len-(ptr-*filter), "%02x", c);
5909 ptr += g_snprintf(ptr, buf_len-(ptr-*filter), ":%02x", c);
5915 /* By default, use the fvalue's "to_string_repr" method. */
5917 /* Figure out the string length needed.
5918 * The ft_repr length.
5919 * 4 bytes for " == ".
5920 * 1 byte for trailing NUL.
5922 if (filter != NULL) {
5923 dfilter_len = fvalue_string_repr_len(&finfo->value,
5925 dfilter_len += abbrev_len + 4 + 1;
5926 *filter = ep_alloc0(dfilter_len);
5928 /* Create the string */
5929 g_snprintf(*filter, dfilter_len, "%s == ",
5931 fvalue_to_string_repr(&finfo->value,
5933 &(*filter)[abbrev_len + 4]);
5942 * Returns TRUE if we can do a "match selected" on the field, FALSE
5946 proto_can_match_selected(field_info *finfo, epan_dissect_t *edt)
5948 return construct_match_selected_string(finfo, edt, NULL);
5951 /* This function attempts to construct a "match selected" display filter
5952 * string for the specified field; if it can do so, it returns a pointer
5953 * to the string, otherwise it returns NULL.
5955 * The string is allocated with packet lifetime scope.
5956 * You do not need to [g_]free() this string since it will be automatically
5957 * freed once the next packet is dissected.
5960 proto_construct_match_selected_string(field_info *finfo, epan_dissect_t *edt)
5964 if (!construct_match_selected_string(finfo, edt, &filter))
5970 /* This function will dissect a sequence of bytes that describe a
5972 * hf_hdr is a 8/16/24/32 bit integer that describes the bitmask to be dissected.
5973 * This field will form an expansion under which the individual fields of the
5974 * bitmask is dissected and displayed.
5975 * This field must be of the type FT_[U]INT{8|16|24|32}.
5977 * fields is an array of pointers to int that lists all the fields of the
5978 * bitmask. These fields can be either of the type FT_BOOLEAN for flags
5979 * or another integer of the same type/size as hf_hdr with a mask specified.
5980 * This array is terminated by a NULL entry.
5982 * FT_BOOLEAN bits that are set to 1 will have the name added to the expansion.
5983 * FT_integer fields that have a value_string attached will have the
5984 * matched string displayed on the expansion line.
5987 proto_tree_add_bitmask(proto_tree *parent_tree, tvbuff_t *tvb, int offset, int hf_hdr, gint ett, const int **fields, gboolean little_endian)
5989 proto_tree *tree=NULL;
5990 proto_item *item=NULL;
5991 header_field_info *hf_info;
5995 hf_info=proto_registrar_get_nth(hf_hdr);
5996 switch(hf_info->type){
6000 value=tvb_get_guint8(tvb, offset);
6006 value=tvb_get_letohs(tvb, offset);
6008 value=tvb_get_ntohs(tvb, offset);
6015 value=tvb_get_letoh24(tvb, offset);
6017 value=tvb_get_ntoh24(tvb, offset);
6024 value=tvb_get_letohl(tvb, offset);
6026 value=tvb_get_ntohl(tvb, offset);
6030 g_assert_not_reached();
6034 item=proto_tree_add_item(parent_tree, hf_hdr, tvb, offset, len, little_endian);
6035 tree=proto_item_add_subtree(item, ett);
6039 header_field_info *hf_field;
6040 guint32 tmpval, tmpmask;
6042 hf_field=proto_registrar_get_nth(**fields);
6043 switch(hf_field->type){
6052 proto_tree_add_item(tree, **fields, tvb, offset, len, little_endian);
6054 /* Mask and shift out the value */
6055 tmpmask=hf_field->bitmask;
6059 while(!(tmpmask&0x00000001)){
6064 /* Show the value_string content (if there is one) */
6065 if(hf_field->strings){
6066 proto_item_append_text(item, ", %s", val_to_str(tmpval, hf_field->strings, "Unknown"));
6071 proto_tree_add_item(tree, **fields, tvb, offset, len, little_endian);
6072 /* if the flag is set, show the name */
6073 if(hf_field->bitmask&value){
6074 proto_item_append_text(item, ", %s", hf_field->name);
6078 g_assert_not_reached();
6088 proto_tree_add_bits_item(proto_tree *tree, int hf_index, tvbuff_t *tvb, gint bit_offset, gint no_of_bits, gboolean little_endian)
6090 return proto_tree_add_bits_ret_val(tree, hf_index, tvb, bit_offset, no_of_bits, NULL, little_endian);
6094 * This function will dissect a sequence of bits that does not need to be byte aligned the bits
6095 * set vill be shown in the tree as ..10 10.. and the integer value returned if return_value is set.
6096 * Offset should be given in bits from the start of the tvb.
6100 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)
6105 guint8 remaining_bits;
6106 guint64 mask = 0,tmp;
6108 header_field_info *hf_field;
6113 hf_field = proto_registrar_get_nth(hf_index);
6115 if(hf_field -> bitmask != 0) {
6116 REPORT_DISSECTOR_BUG(ep_strdup_printf("Incompatible use of proto_tree_add_bits_ret_val with field '%s' (%s) with bitmask != 0",
6117 hf_field->abbrev, hf_field->name));
6120 /* Byte align offset */
6121 offset = bit_offset>>3;
6125 * Calculate the number of octets used to hold the bits
6127 tot_no_bits = ((bit_offset&0x7)+no_of_bits);
6128 length = tot_no_bits>>3;
6129 remaining_bits = tot_no_bits % 8;
6130 if ((remaining_bits)!=0)
6133 if (no_of_bits < 9){
6134 value = tvb_get_bits8(tvb, bit_offset, no_of_bits);
6135 }else if(no_of_bits < 17){
6136 value = tvb_get_bits16(tvb, bit_offset, no_of_bits, little_endian);
6137 }else if(no_of_bits < 33){
6138 value = tvb_get_bits32(tvb, bit_offset, no_of_bits, little_endian);
6139 }else if(no_of_bits < 65){
6140 value = tvb_get_bits64(tvb, bit_offset, no_of_bits, little_endian);
6141 }else if(no_of_bits>64){
6142 DISSECTOR_ASSERT_NOT_REACHED();
6148 mask = mask << (no_of_bits-1);
6150 /* prepare the string */
6153 for(bit=0;bit<((int)(bit_offset&0x07));bit++){
6154 if(bit&&(!(bit%4))){
6159 /* read the bits for the int */
6160 for(i=0;i<no_of_bits;i++){
6161 if(bit&&(!(bit%4))){
6164 if(bit&&(!(bit%8))){
6177 if(bit&&(!(bit%4))){
6184 *return_value=value;
6190 strcat(str,hf_field->name);
6192 switch(hf_field->type){
6195 if (hf_field->strings) {
6196 const true_false_string *tfstring = &tfs_true_false;
6197 tfstring = (const struct true_false_string*) hf_field->strings;
6199 return proto_tree_add_boolean_format(tree, hf_index, tvb, offset, length, (guint32)value,
6202 (guint32)value ? tfstring->true_string : tfstring->false_string);
6204 return proto_tree_add_boolean_format(tree, hf_index, tvb, offset, length, (guint32)value,
6214 /* 1 - 32 bits field */
6215 if (hf_field->strings) {
6216 return proto_tree_add_uint_format(tree, hf_index, tvb, offset, length, (guint32)value,
6219 val_to_str((guint32)value, cVALS(hf_field->strings), "Unknown "),
6223 switch(hf_field->display){
6225 return proto_tree_add_uint_format(tree, hf_index, tvb, offset, length, (guint32)value,
6231 return proto_tree_add_uint_format(tree, hf_index, tvb, offset, length, (guint32)value,
6237 DISSECTOR_ASSERT_NOT_REACHED();
6243 switch(hf_field->display){
6245 return proto_tree_add_uint64_format(tree, hf_index, tvb, offset, length, value,
6246 "%s: %" G_GINT64_MODIFIER "u",
6250 return proto_tree_add_uint64_format(tree, hf_index, tvb, offset, length, value,
6251 "%s: 0x%" G_GINT64_MODIFIER "x",
6255 DISSECTOR_ASSERT_NOT_REACHED();
6261 DISSECTOR_ASSERT_NOT_REACHED();