2 * Routines for protocol tree
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
36 #include "ptvcursor.h"
38 #include "addr_resolv.h"
42 #include "epan_dissect.h"
47 #include "asm_utils.h"
48 #include "column-utils.h"
50 #include "wspython/wspy_register.h"
52 #define SUBTREE_ONCE_ALLOCATION_NUMBER 8
53 #define SUBTREE_MAX_LEVELS 256
56 typedef struct __subtree_lvl {
63 subtree_lvl *pushed_tree;
64 guint8 pushed_tree_index;
65 guint8 pushed_tree_max;
71 /* Candidates for assembler */
73 wrs_count_bitshift(guint32 bitmask)
77 while ((bitmask & (1 << bitshift)) == 0)
82 #define cVALS(x) (const value_string*)(x)
84 /** See inlined comments.
85 @param tree the tree to append this item to
86 @param hfindex field index
87 @param hfinfo header_field
88 @return the header field matching 'hfinfo' */
89 #define TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo) \
90 /* If this item is not referenced we dont have to do much work \
91 at all but we should still return a node so that \
92 field items below this node ( think proto_item_add_subtree() )\
93 will still have somewhere to attach to \
94 or else filtering will not work (they would be ignored since tree\
96 DONT try to fake a node where PTREE_FINFO(tree) is NULL \
97 since dissectors that want to do proto_item_set_len() or \
98 other operations that dereference this would crash. \
99 We fake FT_PROTOCOL unless some clients have requested us \
104 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo); \
105 if(!(PTREE_DATA(tree)->visible)){ \
106 if(PTREE_FINFO(tree)){ \
107 if((hfinfo->ref_count == HF_REF_TYPE_NONE) \
108 && (hfinfo->type!=FT_PROTOCOL || \
109 PTREE_DATA(tree)->fake_protocols)){ \
110 /* just return tree back to the caller */\
117 proto_tree_free_node(proto_node *node, gpointer data);
119 static void fill_label_boolean(field_info *fi, gchar *label_str);
120 static void fill_label_uint(field_info *fi, gchar *label_str);
121 static void fill_label_uint64(field_info *fi, gchar *label_str);
122 static void fill_label_bitfield(field_info *fi, gchar *label_str);
123 static void fill_label_int(field_info *fi, gchar *label_str);
124 static void fill_label_int64(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 proto_item_add_bitmask_tree(proto_item *item, tvbuff_t *tvb, int offset, int len, gint ett,
210 const gint **fields, gboolean little_endian, int flags, gboolean first);
212 static int proto_register_field_init(header_field_info *hfinfo, int parent);
214 /* special-case header field used within proto.c */
215 int hf_text_only = -1;
217 /* Structure for information about a protocol */
219 const char *name; /* long description */
220 const char *short_name; /* short description */
221 const char *filter_name; /* name of this protocol in filters */
222 int proto_id; /* field ID for this protocol */
223 GList *fields; /* fields for this protocol */
224 GList *last_field; /* pointer to end of list of fields */
225 gboolean is_enabled; /* TRUE if protocol is enabled */
226 gboolean can_toggle; /* TRUE if is_enabled can be changed */
227 gboolean is_private; /* TRUE is protocol is private */
230 /* List of all protocols */
231 static GList *protocols = NULL;
233 #define INITIAL_NUM_PROTOCOL_HFINFO 200
236 /* Contains information about protocols and header fields. Used when
237 * dissectors register their data */
238 static GMemChunk *gmc_hfinfo = NULL;
240 /* Contains information about a field when a dissector calls
241 * proto_tree_add_item. */
242 SLAB_ITEM_TYPE_DEFINE(field_info)
243 static SLAB_FREE_LIST_DEFINE(field_info)
244 static field_info *field_info_tmp=NULL;
245 #define FIELD_INFO_NEW(fi) \
246 SLAB_ALLOC(fi, field_info)
247 #define FIELD_INFO_FREE(fi) \
248 SLAB_FREE(fi, field_info)
252 /* Contains the space for proto_nodes. */
253 SLAB_ITEM_TYPE_DEFINE(proto_node)
254 static SLAB_FREE_LIST_DEFINE(proto_node)
255 #define PROTO_NODE_NEW(node) \
256 SLAB_ALLOC(node, proto_node) \
257 node->first_child = NULL; \
258 node->last_child = NULL; \
261 #define PROTO_NODE_FREE(node) \
262 SLAB_FREE(node, proto_node)
266 /* String space for protocol and field items for the GUI */
267 SLAB_ITEM_TYPE_DEFINE(item_label_t)
268 static SLAB_FREE_LIST_DEFINE(item_label_t)
269 #define ITEM_LABEL_NEW(il) \
270 SLAB_ALLOC(il, item_label_t)
271 #define ITEM_LABEL_FREE(il) \
272 SLAB_FREE(il, item_label_t)
275 #define PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo) \
276 DISSECTOR_ASSERT((guint)hfindex < gpa_hfinfo.len); \
277 hfinfo=gpa_hfinfo.hfi[hfindex];
280 /* List which stores protocols and fields that have been registered */
281 typedef struct _gpa_hfinfo_t {
283 guint32 allocated_len;
284 header_field_info **hfi;
286 gpa_hfinfo_t gpa_hfinfo;
288 /* Balanced tree of abbreviations and IDs */
289 static GTree *gpa_name_tree = NULL;
290 static header_field_info *same_name_hfinfo;
292 static void save_same_name_hfinfo(gpointer data)
294 same_name_hfinfo = (header_field_info*)data;
297 /* Points to the first element of an array of Booleans, indexed by
298 a subtree item type; that array element is TRUE if subtrees of
299 an item of that type are to be expanded. */
300 gboolean *tree_is_expanded;
302 /* Number of elements in that array. */
305 /* Name hashtables for fast detection of duplicate names */
306 static GHashTable* proto_names = NULL;
307 static GHashTable* proto_short_names = NULL;
308 static GHashTable* proto_filter_names = NULL;
311 proto_compare_name(gconstpointer p1_arg, gconstpointer p2_arg)
313 const protocol_t *p1 = p1_arg;
314 const protocol_t *p2 = p2_arg;
316 return g_ascii_strcasecmp(p1->short_name, p2->short_name);
320 /* initialize data structures and register protocols and fields */
322 proto_init(void (register_all_protocols_func)(register_cb cb, gpointer client_data),
323 void (register_all_handoffs_func)(register_cb cb, gpointer client_data),
325 gpointer client_data)
327 static hf_register_info hf[] = {
329 { "Text item", "text", FT_NONE, BASE_NONE, NULL, 0x0,
334 proto_names = g_hash_table_new(g_int_hash, g_int_equal);
335 proto_short_names = g_hash_table_new(wrs_str_hash, g_str_equal);
336 proto_filter_names = g_hash_table_new(wrs_str_hash, g_str_equal);
340 gmc_hfinfo = g_mem_chunk_new("gmc_hfinfo",
341 sizeof(header_field_info),
342 INITIAL_NUM_PROTOCOL_HFINFO * sizeof(header_field_info),
346 gpa_hfinfo.allocated_len=0;
348 gpa_name_tree = g_tree_new_full(wrs_strcmp_with_data, NULL, NULL, save_same_name_hfinfo);
350 /* Initialize the ftype subsystem */
353 /* Register one special-case FT_TEXT_ONLY field for use when
354 converting wireshark to new-style proto_tree. These fields
355 are merely strings on the GUI tree; they are not filterable */
356 proto_register_field_array(-1, hf, array_length(hf));
358 /* Have each built-in dissector register its protocols, fields,
359 dissector tables, and dissectors to be called through a
360 handle, and do whatever one-time initialization it needs to
362 register_all_protocols_func(cb, client_data);
364 /* Now scan for python protocols */
365 register_all_py_protocols_func(cb, client_data);
369 /* Now scan for plugins and load all the ones we find, calling
370 their register routines to do the stuff described above. */
372 (*cb)(RA_PLUGIN_REGISTER, NULL, client_data);
374 register_all_plugin_registrations();
377 /* Now call the "handoff registration" routines of all built-in
378 dissectors; those routines register the dissector in other
379 dissectors' handoff tables, and fetch any dissector handles
381 register_all_handoffs_func(cb, client_data);
384 /* Now do the same with python dissectors */
385 register_all_py_handoffs_func(cb, client_data);
389 /* Now do the same with plugins. */
391 (*cb)(RA_PLUGIN_HANDOFF, NULL, client_data);
392 register_all_plugin_handoffs();
395 /* sort the protocols by protocol name */
396 protocols = g_list_sort(protocols, proto_compare_name);
398 /* We've assigned all the subtree type values; allocate the array
399 for them, and zero it out. */
400 tree_is_expanded = g_malloc(num_tree_types*sizeof (gboolean));
401 memset(tree_is_expanded, 0, num_tree_types*sizeof (gboolean));
407 /* Free the abbrev/ID GTree */
409 g_tree_destroy(gpa_name_tree);
410 gpa_name_tree = NULL;
414 g_mem_chunk_destroy(gmc_hfinfo);
416 if(gpa_hfinfo.allocated_len){
418 gpa_hfinfo.allocated_len=0;
419 g_free(gpa_hfinfo.hfi);
422 g_free(tree_is_expanded);
427 proto_tree_traverse_pre_order(proto_tree *tree, proto_tree_traverse_func func,
430 proto_node *pnode = tree;
434 if (func(pnode, data))
437 child = pnode->first_child;
438 while (child != NULL) {
440 * The routine we call might modify the child, e.g. by
441 * freeing it, so we get the child's successor before
442 * calling that routine.
445 child = current->next;
446 if (proto_tree_traverse_pre_order((proto_tree *)current, func,
455 proto_tree_traverse_post_order(proto_tree *tree, proto_tree_traverse_func func,
458 proto_node *pnode = tree;
462 child = pnode->first_child;
463 while (child != NULL) {
465 * The routine we call might modify the child, e.g. by
466 * freeing it, so we get the child's successor before
467 * calling that routine.
470 child = current->next;
471 if (proto_tree_traverse_post_order((proto_tree *)current, func,
475 if (func(pnode, data))
482 proto_tree_children_foreach(proto_tree *tree, proto_tree_foreach_func func,
485 proto_node *node = tree;
488 node = node->first_child;
489 while (node != NULL) {
491 node = current->next;
492 func((proto_tree *)current, data);
496 /* frees the resources that the dissection a proto_tree uses */
498 proto_tree_free(proto_tree *tree)
500 proto_tree_traverse_post_order(tree, proto_tree_free_node, NULL);
504 free_GPtrArray_value(gpointer key, gpointer value, gpointer user_data _U_)
506 GPtrArray *ptrs = value;
507 gint hfid = (gint)(long)key;
508 header_field_info *hfinfo;
510 PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
511 if(hfinfo->ref_count != HF_REF_TYPE_NONE) {
512 /* when a field is referenced by a filter this also
513 affects the refcount for the parent protocol so we need
514 to adjust the refcount for the parent as well
516 if( hfinfo->parent != -1 ) {
517 header_field_info *parent_hfinfo;
518 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
519 parent_hfinfo->ref_count = HF_REF_TYPE_NONE;
521 hfinfo->ref_count = HF_REF_TYPE_NONE;
524 g_ptr_array_free(ptrs, TRUE);
528 free_node_tree_data(tree_data_t *tree_data)
530 if (tree_data->interesting_hfids) {
531 /* Free all the GPtrArray's in the interesting_hfids hash. */
532 g_hash_table_foreach(tree_data->interesting_hfids,
533 free_GPtrArray_value, NULL);
535 /* And then destroy the hash. */
536 g_hash_table_destroy(tree_data->interesting_hfids);
539 /* And finally the tree_data_t itself. */
543 #define FREE_NODE_FIELD_INFO(finfo) \
545 ITEM_LABEL_FREE(finfo->rep); \
547 FVALUE_CLEANUP(&finfo->value); \
548 FIELD_INFO_FREE(finfo);
551 proto_tree_free_node(proto_node *node, gpointer data _U_)
553 field_info *finfo = PNODE_FINFO(node);
555 proto_node *parent = node->parent;
559 /* This is the root node. Destroy the per-tree data.
560 * There is no field_info to destroy. */
561 if (PTREE_DATA(node)) free_node_tree_data(PTREE_DATA(node));
564 /* This is a child node. Don't free the per-tree data, but
565 * do free the field_info data. */
566 FREE_NODE_FIELD_INFO(finfo);
570 /* NOTE: This code is required when this function is used to free individual
571 * nodes only. Current use is for the destruction of complete trees, so the
572 * inconsistancies have no ill effect.
574 /* Remove node from parent */
576 proto_item *prev_item = NULL;
577 if (parent->first_child == node) {
578 parent->first_child = node->next;
580 /* find previous and change its next */
581 for (prev_item = parent->first_child; prev_item; prev_item = prev_item->next) {
582 if (prev_item->next == node) {
586 DISSECTOR_ASSERT(prev_item);
587 prev_item->next = node->next;
589 /* fix last_child if required */
590 if (parent->last_child == node) {
591 parent->last_child = prev_item;
594 DISSECTOR_ASSERT(node->first_child == NULL && node->last_child == NULL);
596 /* Free the proto_node. */
597 PROTO_NODE_FREE(node);
599 return FALSE; /* FALSE = do not end traversal of protocol tree */
602 /* Is the parsing being done for a visible proto_tree or an invisible one?
603 * By setting this correctly, the proto_tree creation is sped up by not
604 * having to call g_vsnprintf and copy strings around.
607 proto_tree_set_visible(proto_tree *tree, gboolean visible)
609 PTREE_DATA(tree)->visible = visible;
613 proto_tree_set_fake_protocols(proto_tree *tree, gboolean fake_protocols)
615 PTREE_DATA(tree)->fake_protocols = fake_protocols;
618 /* Assume dissector set only its protocol fields.
619 This function is called by dissectors and allowes to speed up filtering
620 in wireshark, if this function returns FALSE it is safe to reset tree to NULL
621 and thus skip calling most of the expensive proto_tree_add_...()
623 If the tree is visible we implicitely assume the field is referenced.
626 proto_field_is_referenced(proto_tree *tree, int proto_id)
628 register header_field_info *hfinfo;
634 if (PTREE_DATA(tree)->visible)
637 PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
638 if (hfinfo->ref_count != HF_REF_TYPE_NONE)
641 if (hfinfo->type == FT_PROTOCOL && !PTREE_DATA(tree)->fake_protocols)
648 /* Finds a record in the hf_info_records array by id. */
650 proto_registrar_get_nth(guint hfindex)
652 register header_field_info *hfinfo;
654 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
659 /* Prefix initialization
660 * this allows for a dissector to register a display filter name prefix
661 * so that it can delay the initialization of the hf array as long as
665 /* compute a hash for the part before the dot of a display filter */
667 prefix_hash (gconstpointer key) {
668 /* end the string at the dot and compute its hash */
669 gchar* copy = ep_strdup(key);
679 return g_str_hash(copy);
682 /* are both strings equal up to the end or the dot? */
684 prefix_equal (gconstpointer ap,gconstpointer bp) {
692 if ((ac == '.' || ac == '\0') && (bc == '.' || bc == '\0')) return TRUE;
694 if ( (ac == '.' || ac == '\0') && ! (bc == '.' || bc == '\0') ) return FALSE;
695 if ( (bc == '.' || bc == '\0') && ! (ac == '.' || ac == '\0') ) return FALSE;
697 if (ac != bc) return FALSE;
704 /* indexed by prefix, contains initializers */
705 static GHashTable* prefixes = NULL;
708 /* Register a new prefix for "delayed" initialization of field arrays */
710 proto_register_prefix(const char *prefix, prefix_initializer_t pi ) {
712 prefixes = g_hash_table_new(prefix_hash,prefix_equal);
715 g_hash_table_insert(prefixes,(gpointer)prefix,pi);
718 /* helper to call all prefix initializers */
720 initialize_prefix(gpointer k, gpointer v, gpointer u _U_) {
721 ((prefix_initializer_t)v)(k);
725 /** Initialize every remaining uninitialized prefix. */
727 proto_initialize_all_prefixes(void) {
728 g_hash_table_foreach_remove(prefixes, initialize_prefix, NULL);
731 /* Finds a record in the hf_info_records array by name.
732 * If it fails to find it in the already registered fields,
733 * it tries to find and call an initializer in the prefixes
734 * table and if so it looks again.
737 proto_registrar_get_byname(const char *field_name)
739 header_field_info* hfinfo;
740 prefix_initializer_t pi;
745 hfinfo = g_tree_lookup(gpa_name_tree, field_name);
747 if (hfinfo) return hfinfo;
749 if (!prefixes) return NULL;
751 if(( pi = g_hash_table_lookup(prefixes,field_name) )) {
753 g_hash_table_remove(prefixes,field_name);
758 return g_tree_lookup(gpa_name_tree, field_name);
763 ptvcursor_new_subtree_levels(ptvcursor_t * ptvc)
765 subtree_lvl * pushed_tree;
767 DISSECTOR_ASSERT(ptvc->pushed_tree_max <= SUBTREE_MAX_LEVELS-SUBTREE_ONCE_ALLOCATION_NUMBER);
768 ptvc->pushed_tree_max += SUBTREE_ONCE_ALLOCATION_NUMBER;
770 pushed_tree = ep_alloc(sizeof(subtree_lvl) * ptvc->pushed_tree_max);
771 DISSECTOR_ASSERT(pushed_tree != NULL);
772 if (ptvc->pushed_tree)
773 memcpy(pushed_tree, ptvc->pushed_tree, ptvc->pushed_tree_max - SUBTREE_ONCE_ALLOCATION_NUMBER);
774 ptvc->pushed_tree = pushed_tree;
778 ptvcursor_free_subtree_levels(ptvcursor_t * ptvc)
780 ptvc->pushed_tree = NULL;
781 ptvc->pushed_tree_max = 0;
782 DISSECTOR_ASSERT(ptvc->pushed_tree_index ==0);
783 ptvc->pushed_tree_index = 0;
786 /* Allocates an initializes a ptvcursor_t with 3 variables:
787 * proto_tree, tvbuff, and offset. */
789 ptvcursor_new(proto_tree *tree, tvbuff_t *tvb, gint offset)
793 ptvc = ep_alloc(sizeof(ptvcursor_t));
796 ptvc->offset = offset;
797 ptvc->pushed_tree= NULL;
798 ptvc->pushed_tree_max= 0;
799 ptvc->pushed_tree_index= 0;
804 /* Frees memory for ptvcursor_t, but nothing deeper than that. */
806 ptvcursor_free(ptvcursor_t *ptvc)
808 ptvcursor_free_subtree_levels(ptvc);
812 /* Returns tvbuff. */
814 ptvcursor_tvbuff(ptvcursor_t* ptvc)
819 /* Returns current offset. */
821 ptvcursor_current_offset(ptvcursor_t* ptvc)
827 ptvcursor_tree(ptvcursor_t* ptvc)
836 ptvcursor_set_tree(ptvcursor_t* ptvc, proto_tree *tree)
841 /* creates a subtree, sets it as the working tree and pushes the old working tree */
843 ptvcursor_push_subtree(ptvcursor_t *ptvc, proto_item *it, gint ett_subtree)
845 subtree_lvl * subtree;
846 if (ptvc->pushed_tree_index >= ptvc->pushed_tree_max)
847 ptvcursor_new_subtree_levels(ptvc);
849 subtree = ptvc->pushed_tree+ptvc->pushed_tree_index;
850 subtree->tree = ptvc->tree;
852 ptvc->pushed_tree_index++;
853 return ptvcursor_set_subtree(ptvc, it, ett_subtree);
858 ptvcursor_pop_subtree(ptvcursor_t *ptvc)
860 subtree_lvl * subtree;
861 if (ptvc->pushed_tree_index <= 0)
864 ptvc->pushed_tree_index--;
865 subtree = ptvc->pushed_tree+ptvc->pushed_tree_index;
866 if (subtree->it != NULL)
867 proto_item_set_len(subtree->it, ptvcursor_current_offset(ptvc) - subtree->cursor_offset);
869 ptvc->tree = subtree->tree;
872 /* saves the current tvb offset and the item in the current subtree level */
874 ptvcursor_subtree_set_item(ptvcursor_t * ptvc, proto_item * it)
876 subtree_lvl * subtree;
878 DISSECTOR_ASSERT(ptvc->pushed_tree_index > 0);
880 subtree = ptvc->pushed_tree+ptvc->pushed_tree_index-1;
882 subtree->cursor_offset = ptvcursor_current_offset(ptvc);
885 /* Creates a subtree and adds it to the cursor as the working tree but does not
886 * save the old working tree */
888 ptvcursor_set_subtree(ptvcursor_t *ptvc, proto_item *it, gint ett_subtree)
890 ptvc->tree = proto_item_add_subtree(it, ett_subtree);
895 ptvcursor_add_subtree_item(ptvcursor_t * ptvc, proto_item * it, gint ett_subtree, gint length)
897 ptvcursor_push_subtree(ptvc, it, ett_subtree);
898 if (length == SUBTREE_UNDEFINED_LENGTH)
899 ptvcursor_subtree_set_item(ptvc, it);
900 return ptvcursor_tree(ptvc);
903 /* Add an item to the tree and create a subtree
904 * If the length is unknown, length may be defined as SUBTREE_UNDEFINED_LENGTH.
905 * In this case, when the subtree will be closed, the parent item length will
906 * be equal to the advancement of the cursor since the creation of the subtree.
909 ptvcursor_add_with_subtree(ptvcursor_t * ptvc, int hfindex, gint length,
910 gboolean little_endian, gint ett_subtree)
914 it = ptvcursor_add_no_advance(ptvc, hfindex, length, little_endian);
915 return ptvcursor_add_subtree_item(ptvc, it, ett_subtree, length);
919 proto_tree_add_text_node(proto_tree *tree, tvbuff_t *tvb, gint start, gint length);
921 /* Add a text node to the tree and create a subtree
922 * If the length is unknown, length may be defined as SUBTREE_UNDEFINED_LENGTH.
923 * In this case, when the subtree will be closed, the item length will be equal
924 * to the advancement of the cursor since the creation of the subtree.
927 ptvcursor_add_text_with_subtree(ptvcursor_t * ptvc, gint length,
928 gint ett_subtree, const char *format, ...)
933 it = proto_tree_add_text_node(ptvcursor_tree(ptvc), ptvcursor_tvbuff(ptvc),
934 ptvcursor_current_offset(ptvc), length);
939 va_start(ap, format);
940 proto_tree_set_representation(it, format, ap);
943 return ptvcursor_add_subtree_item(ptvc, it, ett_subtree, length);
946 /* Add a text-only node, leaving it to our caller to fill the text in */
948 proto_tree_add_text_node(proto_tree *tree, tvbuff_t *tvb, gint start, gint length)
951 header_field_info *hfinfo;
953 TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
955 pi = proto_tree_add_pi(tree, hf_text_only, tvb, start, &length, NULL);
962 /* Add a text-only node to the proto_tree */
964 proto_tree_add_text(proto_tree *tree, tvbuff_t *tvb, gint start, gint length,
965 const char *format, ...)
970 pi = proto_tree_add_text_node(tree, tvb, start, length);
974 va_start(ap, format);
975 proto_tree_set_representation(pi, format, ap);
981 /* Add a text-only node to the proto_tree (va_list version) */
983 proto_tree_add_text_valist(proto_tree *tree, tvbuff_t *tvb, gint start,
984 gint length, const char *format, va_list ap)
988 pi = proto_tree_add_text_node(tree, tvb, start, length);
992 proto_tree_set_representation(pi, format, ap);
997 /* Add a text-only node for debugging purposes. The caller doesn't need
998 * to worry about tvbuff, start, or length. Debug message gets sent to
1001 proto_tree_add_debug_text(proto_tree *tree, const char *format, ...)
1006 pi = proto_tree_add_text_node(tree, NULL, 0, 0);
1008 va_start(ap, format);
1010 proto_tree_set_representation(pi, format, ap);
1011 vprintf(format, ap);
1020 get_uint_value(tvbuff_t *tvb, gint offset, gint length, gboolean little_endian)
1027 value = tvb_get_guint8(tvb, offset);
1031 value = little_endian ? tvb_get_letohs(tvb, offset)
1032 : tvb_get_ntohs(tvb, offset);
1036 value = little_endian ? tvb_get_letoh24(tvb, offset)
1037 : tvb_get_ntoh24(tvb, offset);
1041 value = little_endian ? tvb_get_letohl(tvb, offset)
1042 : tvb_get_ntohl(tvb, offset);
1046 DISSECTOR_ASSERT_NOT_REACHED();
1054 get_int_value(tvbuff_t *tvb, gint offset, gint length, gboolean little_endian)
1061 value = (gint8)tvb_get_guint8(tvb, offset);
1065 value = (gint16) (little_endian ? tvb_get_letohs(tvb, offset)
1066 : tvb_get_ntohs(tvb, offset));
1070 value = little_endian ? tvb_get_letoh24(tvb, offset)
1071 : tvb_get_ntoh24(tvb, offset);
1072 if (value & 0x00800000) {
1073 /* Sign bit is set; sign-extend it. */
1074 value |= 0xFF000000;
1079 value = little_endian ? tvb_get_letohl(tvb, offset)
1080 : tvb_get_ntohl(tvb, offset);
1084 DISSECTOR_ASSERT_NOT_REACHED();
1091 static GPtrArray *proto_lookup_or_create_interesting_hfids(proto_tree *tree,
1092 header_field_info *hfinfo)
1094 GPtrArray *ptrs = NULL;
1096 DISSECTOR_ASSERT(tree);
1097 DISSECTOR_ASSERT(hfinfo);
1099 if (hfinfo->ref_count == HF_REF_TYPE_DIRECT) {
1100 if (PTREE_DATA(tree)->interesting_hfids == NULL) {
1101 /* Initialize the hash because we now know that it is needed */
1102 PTREE_DATA(tree)->interesting_hfids =
1103 g_hash_table_new(g_direct_hash, NULL /* g_direct_equal */);
1106 ptrs = g_hash_table_lookup(PTREE_DATA(tree)->interesting_hfids,
1107 GINT_TO_POINTER(hfinfo->id));
1109 /* First element triggers the creation of pointer array */
1110 ptrs = g_ptr_array_new();
1111 g_hash_table_insert(PTREE_DATA(tree)->interesting_hfids,
1112 GINT_TO_POINTER(hfinfo->id), ptrs);
1119 /* Add an item to a proto_tree, using the text label registered to that item;
1120 the item is extracted from the tvbuff handed to it. */
1122 proto_tree_new_item(field_info *new_fi, proto_tree *tree,
1123 tvbuff_t *tvb, gint start, gint length, gboolean little_endian)
1132 /* there is a possibility here that we might raise an exception
1133 * and thus would lose track of the field_info.
1134 * store it in a temp so that if we come here again we can reclaim
1135 * the field_info without leaking memory.
1137 /* XXX this only keeps track of one field_info struct,
1138 if we ever go multithreaded for calls to this function
1139 we have to change this code to use per thread variable.
1142 /* oops, last one we got must have been lost due
1144 * good thing we saved it, now we can reverse the
1145 * memory leak and reclaim it.
1147 SLAB_FREE(field_info_tmp, field_info);
1149 /* we might throw an exception, keep track of this one
1150 * across the "dangerous" section below.
1152 field_info_tmp=new_fi;
1154 switch(new_fi->hfinfo->type) {
1156 /* no value to set for FT_NONE */
1160 proto_tree_set_protocol_tvb(new_fi, tvb);
1164 proto_tree_set_bytes_tvb(new_fi, tvb, start, length);
1168 n = get_uint_value(tvb, start, length, little_endian);
1169 proto_tree_set_bytes_tvb(new_fi, tvb, start + length, n);
1171 /* Instead of calling proto_item_set_len(), since we don't yet
1172 * have a proto_item, we set the field_info's length ourselves. */
1173 new_fi->length = n + length;
1177 proto_tree_set_boolean(new_fi,
1178 get_uint_value(tvb, start, length, little_endian));
1181 /* XXX - make these just FT_UINT? */
1186 proto_tree_set_uint(new_fi,
1187 get_uint_value(tvb, start, length, little_endian));
1192 DISSECTOR_ASSERT( length <= 8 && length >= 1);
1193 proto_tree_set_uint64_tvb(new_fi, tvb, start, length, little_endian);
1196 /* XXX - make these just FT_INT? */
1201 proto_tree_set_int(new_fi,
1202 get_int_value(tvb, start, length, little_endian));
1206 DISSECTOR_ASSERT(length == 4);
1207 value = tvb_get_ipv4(tvb, start);
1208 proto_tree_set_ipv4(new_fi, little_endian ? GUINT32_SWAP_LE_BE(value) : value);
1212 DISSECTOR_ASSERT(length == 4);
1213 proto_tree_set_ipxnet(new_fi,
1214 get_uint_value(tvb, start, 4, FALSE));
1218 DISSECTOR_ASSERT(length == 16);
1219 proto_tree_set_ipv6_tvb(new_fi, tvb, start);
1223 DISSECTOR_ASSERT(length == 6);
1224 proto_tree_set_ether_tvb(new_fi, tvb, start);
1228 DISSECTOR_ASSERT(length == 16);
1229 proto_tree_set_guid_tvb(new_fi, tvb, start, little_endian);
1233 proto_tree_set_oid_tvb(new_fi, tvb, start, length);
1237 DISSECTOR_ASSERT(length == 4);
1239 floatval = tvb_get_letohieee_float(tvb, start);
1241 floatval = tvb_get_ntohieee_float(tvb, start);
1242 proto_tree_set_float(new_fi, floatval);
1246 DISSECTOR_ASSERT(length == 8);
1248 doubleval = tvb_get_letohieee_double(tvb, start);
1250 doubleval = tvb_get_ntohieee_double(tvb, start);
1251 proto_tree_set_double(new_fi, doubleval);
1255 proto_tree_set_string_tvb(new_fi, tvb, start, length);
1259 DISSECTOR_ASSERT(length >= -1);
1260 /* Instead of calling proto_item_set_len(),
1261 * since we don't yet have a proto_item, we
1262 * set the field_info's length ourselves.
1264 * XXX - our caller can't use that length to
1265 * advance an offset unless they arrange that
1266 * there always be a protocol tree into which
1267 * we're putting this item.
1270 /* This can throw an exception */
1271 length = tvb_strsize(tvb, start);
1273 string = ep_alloc(length);
1275 tvb_memcpy(tvb, string, start, length);
1276 } else if (length == 0) {
1279 /* In this case, length signifies
1280 * the length of the string.
1282 * This could either be a null-padded
1283 * string, which doesn't necessarily
1284 * have a '\0' at the end, or a
1285 * null-terminated string, with a
1286 * trailing '\0'. (Yes, there are
1287 * cases where you have a string
1288 * that's both counted and null-
1291 * In the first case, we must
1292 * allocate a buffer of length
1293 * "length+1", to make room for
1296 * In the second case, we don't
1297 * assume that there is a trailing
1298 * '\0' there, as the packet might
1299 * be malformed. (XXX - should we
1300 * throw an exception if there's no
1301 * trailing '\0'?) Therefore, we
1302 * allocate a buffer of length
1303 * "length+1", and put in a trailing
1304 * '\0', just to be safe.
1306 * (XXX - this would change if
1307 * we made string values counted
1308 * rather than null-terminated.)
1310 string = tvb_get_ephemeral_string(tvb,
1314 new_fi->length = length;
1315 proto_tree_set_string(new_fi, string);
1319 proto_tree_set_ebcdic_string_tvb(new_fi, tvb, start, length);
1322 case FT_UINT_STRING:
1323 n = get_uint_value(tvb, start, length, little_endian);
1324 proto_tree_set_string_tvb(new_fi, tvb, start + length, n);
1326 /* Instead of calling proto_item_set_len(), since we
1327 * don't yet have a proto_item, we set the
1328 * field_info's length ourselves.
1330 * XXX - our caller can't use that length to
1331 * advance an offset unless they arrange that
1332 * there always be a protocol tree into which
1333 * we're putting this item.
1335 new_fi->length = n + length;
1339 g_error("new_fi->hfinfo->type %d (%s) not handled\n",
1340 new_fi->hfinfo->type,
1341 ftype_name(new_fi->hfinfo->type));
1342 DISSECTOR_ASSERT_NOT_REACHED();
1346 /* Don't add new node to proto_tree until now so that any exceptions
1347 * raised by a tvbuff access method doesn't leave junk in the proto_tree. */
1348 pi = proto_tree_add_node(tree, new_fi);
1350 /* we did not raise an exception so we dont have to remember this
1351 * field_info struct any more.
1353 field_info_tmp=NULL;
1355 /* If the proto_tree wants to keep a record of this finfo
1356 * for quick lookup, then record it. */
1357 ptrs = proto_lookup_or_create_interesting_hfids(tree, new_fi->hfinfo);
1359 g_ptr_array_add(ptrs, new_fi);
1364 /* Gets data from tvbuff, adds it to proto_tree, increments offset,
1365 and returns proto_item* */
1367 ptvcursor_add(ptvcursor_t *ptvc, int hfindex, gint length,
1368 gboolean little_endian)
1371 header_field_info *hfinfo;
1376 offset = ptvc->offset;
1377 hfinfo = get_hfi_and_length(hfindex, ptvc->tvb, offset, &length,
1379 ptvc->offset += length;
1380 if (hfinfo->type == FT_UINT_BYTES || hfinfo->type == FT_UINT_STRING) {
1382 * The length of the rest of the item is in the first N
1383 * bytes of the item.
1385 n = get_uint_value(ptvc->tvb, offset, length, little_endian);
1389 TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfindex, hfinfo);
1391 new_fi = new_field_info(ptvc->tree, hfinfo, ptvc->tvb, offset,
1396 return proto_tree_new_item(new_fi, ptvc->tree, ptvc->tvb,
1397 offset, length, little_endian);
1400 /* Add an item to a proto_tree, using the text label registered to that item;
1401 the item is extracted from the tvbuff handed to it. */
1403 proto_tree_add_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1404 gint start, gint length, gboolean little_endian)
1407 header_field_info *hfinfo;
1409 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1411 new_fi = alloc_field_info(tree, hfindex, tvb, start, &length);
1416 return proto_tree_new_item(new_fi, tree, tvb, start,
1417 length, little_endian);
1420 /* Add a FT_NONE to a proto_tree */
1422 proto_tree_add_none_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1423 gint length, const char *format, ...)
1427 header_field_info *hfinfo;
1429 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1431 DISSECTOR_ASSERT(hfinfo->type == FT_NONE);
1433 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, NULL);
1435 va_start(ap, format);
1436 proto_tree_set_representation(pi, format, ap);
1439 /* no value to set for FT_NONE */
1443 /* Gets data from tvbuff, adds it to proto_tree, *DOES NOT* increment
1444 * offset, and returns proto_item* */
1446 ptvcursor_add_no_advance(ptvcursor_t* ptvc, int hf, gint length,
1447 gboolean endianness)
1451 item = proto_tree_add_item(ptvc->tree, hf, ptvc->tvb, ptvc->offset,
1452 length, endianness);
1457 /* Advance the ptvcursor's offset within its tvbuff without
1458 * adding anything to the proto_tree. */
1460 ptvcursor_advance(ptvcursor_t* ptvc, gint length)
1462 ptvc->offset += length;
1467 proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb)
1469 fvalue_set(&fi->value, tvb, TRUE);
1472 /* Add a FT_PROTOCOL to a proto_tree */
1474 proto_tree_add_protocol_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1475 gint length, const char *format, ...)
1480 header_field_info *hfinfo;
1482 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1484 DISSECTOR_ASSERT(hfinfo->type == FT_PROTOCOL);
1486 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1488 va_start(ap, format);
1489 proto_tree_set_representation(pi, format, ap);
1493 proto_tree_set_protocol_tvb(new_fi, tvb);
1496 proto_tree_set_protocol_tvb(new_fi, NULL);
1502 /* Add a FT_BYTES to a proto_tree */
1504 proto_tree_add_bytes(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1505 gint length, const guint8 *start_ptr)
1509 header_field_info *hfinfo;
1511 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1513 DISSECTOR_ASSERT(hfinfo->type == FT_BYTES);
1515 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1516 proto_tree_set_bytes(new_fi, start_ptr, length);
1522 proto_tree_add_bytes_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1523 gint start, gint length, const guint8 *start_ptr,
1524 const char *format, ...)
1529 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length, start_ptr);
1533 va_start(ap, format);
1534 proto_tree_set_representation_value(pi, format, ap);
1541 proto_tree_add_bytes_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1542 gint length, const guint8 *start_ptr, const char *format, ...)
1547 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length, start_ptr);
1551 va_start(ap, format);
1552 proto_tree_set_representation(pi, format, ap);
1559 proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length)
1563 bytes = g_byte_array_new();
1565 g_byte_array_append(bytes, start_ptr, length);
1567 col_custom_set_fstr(fi->hfinfo, "%s", bytes_to_str(bytes->data,
1569 fvalue_set(&fi->value, bytes, TRUE);
1574 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length)
1576 proto_tree_set_bytes(fi, tvb_get_ptr(tvb, offset, length), length);
1579 /* Add a FT_*TIME to a proto_tree */
1581 proto_tree_add_time(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1582 nstime_t *value_ptr)
1586 header_field_info *hfinfo;
1588 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1590 DISSECTOR_ASSERT(hfinfo->type == FT_ABSOLUTE_TIME ||
1591 hfinfo->type == FT_RELATIVE_TIME);
1593 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1594 proto_tree_set_time(new_fi, value_ptr);
1600 proto_tree_add_time_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1601 gint start, gint length, nstime_t *value_ptr,
1602 const char *format, ...)
1607 pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
1611 va_start(ap, format);
1612 proto_tree_set_representation_value(pi, format, ap);
1619 proto_tree_add_time_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1620 nstime_t *value_ptr, const char *format, ...)
1625 pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
1629 va_start(ap, format);
1630 proto_tree_set_representation(pi, format, ap);
1636 /* Set the FT_*TIME value */
1638 proto_tree_set_time(field_info *fi, nstime_t *value_ptr)
1640 header_field_info *hfinfo;
1642 DISSECTOR_ASSERT(value_ptr != NULL);
1643 hfinfo = fi->hfinfo;
1645 if (hfinfo->type == FT_ABSOLUTE_TIME) {
1646 col_custom_set_fstr(fi->hfinfo, "%s", abs_time_to_str(value_ptr));
1647 } else if (hfinfo->type == FT_RELATIVE_TIME) {
1648 col_custom_set_fstr(fi->hfinfo, "%s", rel_time_to_secs_str(value_ptr));
1650 fvalue_set(&fi->value, value_ptr, FALSE);
1653 /* Add a FT_IPXNET to a proto_tree */
1655 proto_tree_add_ipxnet(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1660 header_field_info *hfinfo;
1662 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1664 DISSECTOR_ASSERT(hfinfo->type == FT_IPXNET);
1666 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1667 proto_tree_set_ipxnet(new_fi, value);
1673 proto_tree_add_ipxnet_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1674 gint start, gint length, guint32 value, const char *format, ...)
1679 pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
1683 va_start(ap, format);
1684 proto_tree_set_representation_value(pi, format, ap);
1691 proto_tree_add_ipxnet_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1692 guint32 value, const char *format, ...)
1697 pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
1701 va_start(ap, format);
1702 proto_tree_set_representation(pi, format, ap);
1708 /* Set the FT_IPXNET value */
1710 proto_tree_set_ipxnet(field_info *fi, guint32 value)
1712 fvalue_set_uinteger(&fi->value, value);
1715 /* Add a FT_IPv4 to a proto_tree */
1717 proto_tree_add_ipv4(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1722 header_field_info *hfinfo;
1724 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1726 DISSECTOR_ASSERT(hfinfo->type == FT_IPv4);
1728 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1729 proto_tree_set_ipv4(new_fi, value);
1735 proto_tree_add_ipv4_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1736 gint start, gint length, guint32 value, const char *format, ...)
1741 pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
1745 va_start(ap, format);
1746 proto_tree_set_representation_value(pi, format, ap);
1753 proto_tree_add_ipv4_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1754 guint32 value, const char *format, ...)
1759 pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
1763 va_start(ap, format);
1764 proto_tree_set_representation(pi, format, ap);
1770 /* Set the FT_IPv4 value */
1772 proto_tree_set_ipv4(field_info *fi, guint32 value)
1774 col_custom_set_fstr(fi->hfinfo, "%s",
1775 ip_to_str((guint8 *)&value));
1776 fvalue_set_uinteger(&fi->value, value);
1779 /* Add a FT_IPv6 to a proto_tree */
1781 proto_tree_add_ipv6(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1782 const guint8* value_ptr)
1786 header_field_info *hfinfo;
1788 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1790 DISSECTOR_ASSERT(hfinfo->type == FT_IPv6);
1792 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1793 proto_tree_set_ipv6(new_fi, value_ptr);
1799 proto_tree_add_ipv6_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1800 gint start, gint length, const guint8* value_ptr,
1801 const char *format, ...)
1806 pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
1810 va_start(ap, format);
1811 proto_tree_set_representation_value(pi, format, ap);
1818 proto_tree_add_ipv6_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1819 const guint8* value_ptr, const char *format, ...)
1824 pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
1828 va_start(ap, format);
1829 proto_tree_set_representation(pi, format, ap);
1835 /* Set the FT_IPv6 value */
1837 proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr)
1839 DISSECTOR_ASSERT(value_ptr != NULL);
1840 fvalue_set(&fi->value, (gpointer) value_ptr, FALSE);
1844 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start)
1846 proto_tree_set_ipv6(fi, tvb_get_ptr(tvb, start, 16));
1849 /* Add a FT_GUID to a proto_tree */
1851 proto_tree_add_guid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1852 const e_guid_t *value_ptr)
1856 header_field_info *hfinfo;
1858 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1860 DISSECTOR_ASSERT(hfinfo->type == FT_GUID);
1862 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1863 proto_tree_set_guid(new_fi, value_ptr);
1869 proto_tree_add_guid_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1870 gint start, gint length, const e_guid_t *value_ptr,
1871 const char *format, ...)
1876 pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
1880 va_start(ap, format);
1881 proto_tree_set_representation_value(pi, format, ap);
1888 proto_tree_add_guid_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1889 const e_guid_t *value_ptr, const char *format, ...)
1894 pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
1898 va_start(ap, format);
1899 proto_tree_set_representation(pi, format, ap);
1905 /* Set the FT_GUID value */
1907 proto_tree_set_guid(field_info *fi, const e_guid_t *value_ptr)
1909 DISSECTOR_ASSERT(value_ptr != NULL);
1910 col_custom_set_fstr(fi->hfinfo, "%s",
1911 guid_to_str(value_ptr));
1912 fvalue_set(&fi->value, (gpointer) value_ptr, FALSE);
1916 proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gboolean little_endian)
1920 tvb_get_guid(tvb, start, &guid, little_endian);
1921 proto_tree_set_guid(fi, &guid);
1924 /* Add a FT_OID to a proto_tree */
1926 proto_tree_add_oid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1927 const guint8* value_ptr)
1931 header_field_info *hfinfo;
1933 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1935 DISSECTOR_ASSERT(hfinfo->type == FT_OID);
1937 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1938 proto_tree_set_oid(new_fi, value_ptr, length);
1944 proto_tree_add_oid_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1945 gint start, gint length, const guint8* value_ptr,
1946 const char *format, ...)
1951 pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
1955 va_start(ap, format);
1956 proto_tree_set_representation_value(pi, format, ap);
1963 proto_tree_add_oid_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1964 const guint8* value_ptr, const char *format, ...)
1969 pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
1973 va_start(ap, format);
1974 proto_tree_set_representation(pi, format, ap);
1980 /* Set the FT_OID value */
1982 proto_tree_set_oid(field_info *fi, const guint8* value_ptr, gint length)
1986 DISSECTOR_ASSERT(value_ptr != NULL);
1988 bytes = g_byte_array_new();
1990 g_byte_array_append(bytes, value_ptr, length);
1992 col_custom_set_fstr(fi->hfinfo, "%s",
1993 oid_resolved_from_encoded(value_ptr, length));
1994 fvalue_set(&fi->value, bytes, TRUE);
1998 proto_tree_set_oid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
2000 proto_tree_set_oid(fi, tvb_get_ptr(tvb, start, length), length);
2004 proto_tree_set_uint64(field_info *fi, guint64 value)
2006 col_custom_set_fstr(fi->hfinfo, "%" G_GINT64_MODIFIER "u",
2008 fvalue_set_integer64(&fi->value, value);
2012 proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start, guint length, gboolean little_endian)
2015 guint8* b = ep_tvb_memdup(tvb,start,length);
2020 default: DISSECTOR_ASSERT_NOT_REACHED();
2021 case 8: value <<= 8; value += *--b;
2022 case 7: value <<= 8; value += *--b;
2023 case 6: value <<= 8; value += *--b;
2024 case 5: value <<= 8; value += *--b;
2025 case 4: value <<= 8; value += *--b;
2026 case 3: value <<= 8; value += *--b;
2027 case 2: value <<= 8; value += *--b;
2028 case 1: value <<= 8; value += *--b;
2033 default: DISSECTOR_ASSERT_NOT_REACHED();
2034 case 8: value <<= 8; value += *b++;
2035 case 7: value <<= 8; value += *b++;
2036 case 6: value <<= 8; value += *b++;
2037 case 5: value <<= 8; value += *b++;
2038 case 4: value <<= 8; value += *b++;
2039 case 3: value <<= 8; value += *b++;
2040 case 2: value <<= 8; value += *b++;
2041 case 1: value <<= 8; value += *b++;
2046 proto_tree_set_uint64(fi, value);
2049 /* Add a FT_STRING or FT_STRINGZ to a proto_tree. Creates own copy of string,
2050 * and frees it when the proto_tree is destroyed. */
2052 proto_tree_add_string(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2053 gint length, const char* value)
2057 header_field_info *hfinfo;
2059 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2061 DISSECTOR_ASSERT(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ);
2063 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2064 DISSECTOR_ASSERT(length >= 0);
2065 proto_tree_set_string(new_fi, value);
2071 proto_tree_add_string_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2072 gint start, gint length, const char* value, const char *format,
2078 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
2082 va_start(ap, format);
2083 proto_tree_set_representation_value(pi, format, ap);
2090 proto_tree_add_string_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2091 gint length, const char* value, const char *format, ...)
2096 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
2100 va_start(ap, format);
2101 proto_tree_set_representation(pi, format, ap);
2107 /* Appends string data to a FT_STRING or FT_STRINGZ, allowing progressive
2108 * field info update instead of only updating the representation as does
2109 * proto_item_append_text()
2111 /* NOTE: this function will break with the TRY_TO_FAKE_THIS_ITEM()
2112 * speed optimization.
2113 * Currently only WSP use this function so it is not that bad but try to
2114 * avoid using this one if possible.
2115 * IF you must use this function you MUST also disable the
2116 * TRY_TO_FAKE_THIS_ITEM() optimization for your dissector/function
2117 * using proto_item_append_string().
2118 * Do that by faking that the tree is visible by calling
2119 * proto_tree_set_visible(tree, TRUE) (see packet-wsp.c)
2120 * BEFORE you create the item you are later going to use
2121 * proto_item_append_string() on.
2124 proto_item_append_string(proto_item *pi, const char *str)
2127 header_field_info *hfinfo;
2128 gchar *old_str, *new_str;
2135 fi = PITEM_FINFO(pi);
2136 hfinfo = fi->hfinfo;
2137 if (hfinfo->type == FT_PROTOCOL) {
2138 /* TRY_TO_FAKE_THIS_ITEM() speed optimization: silently skip */
2141 DISSECTOR_ASSERT(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ);
2142 old_str = fvalue_get(&fi->value);
2143 new_str = ep_strdup_printf("%s%s", old_str, str);
2144 fvalue_set(&fi->value, new_str, FALSE);
2147 /* Set the FT_STRING value */
2149 proto_tree_set_string(field_info *fi, const char* value)
2152 col_custom_set_fstr(fi->hfinfo, "%s",
2153 format_text(value, strlen(value)));
2154 fvalue_set(&fi->value, (gpointer) value, FALSE);
2156 col_custom_set_fstr(fi->hfinfo, "[ Null ]");
2157 fvalue_set(&fi->value, (gpointer) "[ Null ]", FALSE);
2162 proto_tree_set_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
2167 length = tvb_ensure_length_remaining(tvb, start);
2170 string = tvb_get_ephemeral_string(tvb, start, length);
2171 proto_tree_set_string(fi, string);
2175 proto_tree_set_ebcdic_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
2180 length = tvb_ensure_length_remaining(tvb, start);
2183 string = tvb_get_ephemeral_string(tvb, start, length);
2184 EBCDIC_to_ASCII(string, length);
2185 proto_tree_set_string(fi, string);
2188 /* Add a FT_ETHER to a proto_tree */
2190 proto_tree_add_ether(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2191 const guint8* value)
2195 header_field_info *hfinfo;
2197 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2199 DISSECTOR_ASSERT(hfinfo->type == FT_ETHER);
2201 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2202 proto_tree_set_ether(new_fi, value);
2208 proto_tree_add_ether_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2209 gint start, gint length, const guint8* value,
2210 const char *format, ...)
2215 pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
2219 va_start(ap, format);
2220 proto_tree_set_representation_value(pi, format, ap);
2227 proto_tree_add_ether_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2228 const guint8* value, const char *format, ...)
2233 pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
2237 va_start(ap, format);
2238 proto_tree_set_representation(pi, format, ap);
2244 /* Set the FT_ETHER value */
2246 proto_tree_set_ether(field_info *fi, const guint8* value)
2248 col_custom_set_fstr(fi->hfinfo, "%s", bytes_to_str_punct(value, 6, ':'));
2249 fvalue_set(&fi->value, (gpointer) value, FALSE);
2253 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start)
2255 proto_tree_set_ether(fi, tvb_get_ptr(tvb, start, 6));
2258 /* Add a FT_BOOLEAN to a proto_tree */
2260 proto_tree_add_boolean(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2265 header_field_info *hfinfo;
2267 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2269 DISSECTOR_ASSERT(hfinfo->type == FT_BOOLEAN);
2271 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2272 proto_tree_set_boolean(new_fi, value);
2278 proto_tree_add_boolean_format_value(proto_tree *tree, int hfindex,
2279 tvbuff_t *tvb, gint start, gint length, guint32 value,
2280 const char *format, ...)
2285 pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
2289 va_start(ap, format);
2290 proto_tree_set_representation_value(pi, format, ap);
2297 proto_tree_add_boolean_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2298 guint32 value, const char *format, ...)
2303 pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
2307 va_start(ap, format);
2308 proto_tree_set_representation(pi, format, ap);
2314 /* Set the FT_BOOLEAN value */
2316 proto_tree_set_boolean(field_info *fi, guint32 value)
2318 proto_tree_set_uint(fi, value);
2321 /* Add a FT_FLOAT to a proto_tree */
2323 proto_tree_add_float(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2328 header_field_info *hfinfo;
2330 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2332 DISSECTOR_ASSERT(hfinfo->type == FT_FLOAT);
2334 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2335 proto_tree_set_float(new_fi, value);
2341 proto_tree_add_float_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2342 gint start, gint length, float value, const char *format, ...)
2347 pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
2351 va_start(ap, format);
2352 proto_tree_set_representation_value(pi, format, ap);
2359 proto_tree_add_float_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2360 float value, const char *format, ...)
2365 pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
2369 va_start(ap, format);
2370 proto_tree_set_representation(pi, format, ap);
2376 /* Set the FT_FLOAT value */
2378 proto_tree_set_float(field_info *fi, float value)
2380 col_custom_set_fstr(fi->hfinfo, "%." STRINGIFY(FLT_DIG) "f",
2382 fvalue_set_floating(&fi->value, value);
2385 /* Add a FT_DOUBLE to a proto_tree */
2387 proto_tree_add_double(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2392 header_field_info *hfinfo;
2394 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2396 DISSECTOR_ASSERT(hfinfo->type == FT_DOUBLE);
2398 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2399 proto_tree_set_double(new_fi, value);
2405 proto_tree_add_double_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2406 gint start, gint length, double value, const char *format, ...)
2411 pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
2415 va_start(ap, format);
2416 proto_tree_set_representation_value(pi, format, ap);
2423 proto_tree_add_double_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2424 double value, const char *format, ...)
2429 pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
2433 va_start(ap, format);
2434 proto_tree_set_representation(pi, format, ap);
2440 /* Set the FT_DOUBLE value */
2442 proto_tree_set_double(field_info *fi, double value)
2444 col_custom_set_fstr(fi->hfinfo, "%." STRINGIFY(DBL_DIG) "g",
2446 fvalue_set_floating(&fi->value, value);
2449 /* Add FT_UINT{8,16,24,32} to a proto_tree */
2451 proto_tree_add_uint(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2454 proto_item *pi = NULL;
2456 header_field_info *hfinfo;
2458 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2460 switch(hfinfo->type) {
2466 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length,
2468 proto_tree_set_uint(new_fi, value);
2472 DISSECTOR_ASSERT_NOT_REACHED();
2479 proto_tree_add_uint_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2480 gint start, gint length, guint32 value, const char *format, ...)
2485 pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
2489 va_start(ap, format);
2490 proto_tree_set_representation_value(pi, format, ap);
2497 proto_tree_add_uint_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2498 guint32 value, const char *format, ...)
2503 pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
2507 va_start(ap, format);
2508 proto_tree_set_representation(pi, format, ap);
2514 /* Set the FT_UINT{8,16,24,32} value */
2516 proto_tree_set_uint(field_info *fi, guint32 value)
2518 header_field_info *hfinfo;
2521 hfinfo = fi->hfinfo;
2524 if (hfinfo->bitmask) {
2525 /* Mask out irrelevant portions */
2526 integer &= hfinfo->bitmask;
2529 if (hfinfo->bitshift > 0) {
2530 integer >>= hfinfo->bitshift;
2534 if (hfinfo->type == FT_BOOLEAN) {
2535 const true_false_string *tfstring = (const true_false_string *)&tfs_true_false;
2536 if (hfinfo->strings) {
2537 tfstring = (const struct true_false_string*) hfinfo->strings;
2539 col_custom_set_fstr(fi->hfinfo, "%s", integer ? tfstring->true_string : tfstring->false_string);
2540 } else if (hfinfo->strings) {
2541 if (hfinfo->display & BASE_RANGE_STRING) {
2542 col_custom_set_fstr(fi->hfinfo, "%s", rval_to_str(integer, hfinfo->strings, "%u"));
2544 col_custom_set_fstr(fi->hfinfo, "%s", val_to_str(integer, cVALS(hfinfo->strings), "%u"));
2546 } else if (IS_BASE_DUAL(hfinfo->display)) {
2547 col_custom_set_fstr(fi->hfinfo, hfinfo_uint_value_format(hfinfo), integer, integer);
2549 col_custom_set_fstr(fi->hfinfo, hfinfo_uint_value_format(hfinfo), integer);
2551 fvalue_set_uinteger(&fi->value, integer);
2554 /* Add FT_UINT64 to a proto_tree */
2556 proto_tree_add_uint64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2559 proto_item *pi = NULL;
2561 header_field_info *hfinfo;
2563 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2565 DISSECTOR_ASSERT(hfinfo->type == FT_UINT64);
2567 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2568 proto_tree_set_uint64(new_fi, value);
2574 proto_tree_add_uint64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2575 gint start, gint length, guint64 value, const char *format, ...)
2580 pi = proto_tree_add_uint64(tree, hfindex, tvb, start, length, value);
2584 va_start(ap, format);
2585 proto_tree_set_representation_value(pi, format, ap);
2592 proto_tree_add_uint64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2593 guint64 value, const char *format, ...)
2598 pi = proto_tree_add_uint64(tree, hfindex, tvb, start, length, value);
2602 va_start(ap, format);
2603 proto_tree_set_representation(pi, format, ap);
2609 /* Add FT_INT{8,16,24,32} to a proto_tree */
2611 proto_tree_add_int(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2614 proto_item *pi = NULL;
2616 header_field_info *hfinfo;
2618 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2620 switch(hfinfo->type) {
2625 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length,
2627 proto_tree_set_int(new_fi, value);
2631 DISSECTOR_ASSERT_NOT_REACHED();
2638 proto_tree_add_int_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2639 gint start, gint length, gint32 value, const char *format, ...)
2641 proto_item *pi = NULL;
2644 pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
2648 va_start(ap, format);
2649 proto_tree_set_representation_value(pi, format, ap);
2656 proto_tree_add_int_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2657 gint32 value, const char *format, ...)
2659 proto_item *pi = NULL;
2662 pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
2666 va_start(ap, format);
2667 proto_tree_set_representation(pi, format, ap);
2673 /* Set the FT_INT{8,16,24,32} value */
2675 proto_tree_set_int(field_info *fi, gint32 value)
2677 header_field_info *hfinfo;
2680 hfinfo = fi->hfinfo;
2681 integer = (guint32) value;
2683 if (hfinfo->bitmask) {
2684 /* Mask out irrelevant portions */
2685 integer &= hfinfo->bitmask;
2688 if (hfinfo->bitshift > 0) {
2689 integer >>= hfinfo->bitshift;
2693 if (hfinfo->strings) {
2694 if (hfinfo->display & BASE_RANGE_STRING) {
2695 col_custom_set_fstr(fi->hfinfo, "%s", rval_to_str(integer, hfinfo->strings, "%d"));
2697 col_custom_set_fstr(fi->hfinfo, "%s", val_to_str(integer, cVALS(hfinfo->strings), "%d"));
2699 } else if (IS_BASE_DUAL(hfinfo->display)) {
2700 col_custom_set_fstr(fi->hfinfo, hfinfo_int_value_format(hfinfo), integer, integer);
2702 col_custom_set_fstr(fi->hfinfo, hfinfo_int_value_format(hfinfo), integer);
2704 fvalue_set_sinteger(&fi->value, integer);
2707 /* Add FT_INT64 to a proto_tree */
2709 proto_tree_add_int64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2712 proto_item *pi = NULL;
2714 header_field_info *hfinfo;
2716 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2718 DISSECTOR_ASSERT(hfinfo->type == FT_INT64);
2720 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2721 proto_tree_set_uint64(new_fi, (guint64)value);
2727 proto_tree_add_int64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2728 gint start, gint length, gint64 value, const char *format, ...)
2733 pi = proto_tree_add_int64(tree, hfindex, tvb, start, length, value);
2737 va_start(ap, format);
2738 proto_tree_set_representation_value(pi, format, ap);
2745 proto_tree_add_int64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2746 gint64 value, const char *format, ...)
2751 pi = proto_tree_add_int64(tree, hfindex, tvb, start, length, value);
2755 va_start(ap, format);
2756 proto_tree_set_representation(pi, format, ap);
2762 /* Throw an exception if we exceed this many tree items. */
2763 /* XXX - This should probably be a preference */
2764 #define MAX_TREE_ITEMS (1 * 1000 * 1000)
2765 /* Add a field_info struct to the proto_tree, encapsulating it in a proto_node */
2767 proto_tree_add_node(proto_tree *tree, field_info *fi)
2769 proto_node *pnode, *tnode, *sibling;
2773 * Make sure "tree" is ready to have subtrees under it, by
2774 * checking whether it's been given an ett_ value.
2776 * "PNODE_FINFO(tnode)" may be null; that's the case for the root
2777 * node of the protocol tree. That node is not displayed,
2778 * so it doesn't need an ett_ value to remember whether it
2782 tfi = PNODE_FINFO(tnode);
2783 if (tfi != NULL && (tfi->tree_type < 0 || tfi->tree_type >= num_tree_types)) {
2784 REPORT_DISSECTOR_BUG(ep_strdup_printf("\"%s\" - \"%s\" tfi->tree_type: %u invalid (%s:%u)",
2785 fi->hfinfo->name, fi->hfinfo->abbrev, tfi->tree_type, __FILE__, __LINE__));
2786 /* XXX - is it safe to continue here? */
2789 DISSECTOR_ASSERT(tfi == NULL ||
2790 (tfi->tree_type >= 0 && tfi->tree_type < num_tree_types));
2792 PTREE_DATA(tree)->count++;
2793 if (PTREE_DATA(tree)->count > MAX_TREE_ITEMS) {
2794 /* Let the exception handler add items to the tree */
2795 PTREE_DATA(tree)->count = 0;
2796 THROW_MESSAGE(DissectorError,
2797 ep_strdup_printf("More than %d items in the tree -- possible infinite loop", MAX_TREE_ITEMS));
2800 PROTO_NODE_NEW(pnode);
2801 pnode->parent = tnode;
2802 PNODE_FINFO(pnode) = fi;
2803 pnode->tree_data = PTREE_DATA(tree);
2805 if (tnode->last_child != NULL) {
2806 sibling = tnode->last_child;
2807 DISSECTOR_ASSERT(sibling->next == NULL);
2808 sibling->next = pnode;
2810 tnode->first_child = pnode;
2811 tnode->last_child = pnode;
2813 return (proto_item*)pnode;
2817 /* Generic way to allocate field_info and add to proto_tree.
2818 * Sets *pfi to address of newly-allocated field_info struct, if pfi is
2821 proto_tree_add_pi(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2822 gint *length, field_info **pfi)
2831 fi = alloc_field_info(tree, hfindex, tvb, start, length);
2832 pi = proto_tree_add_node(tree, fi);
2834 /* If the proto_tree wants to keep a record of this finfo
2835 * for quick lookup, then record it. */
2836 ptrs = proto_lookup_or_create_interesting_hfids(tree, fi->hfinfo);
2838 g_ptr_array_add(ptrs, fi);
2840 /* Does the caller want to know the fi pointer? */
2849 static header_field_info *
2850 get_hfi_and_length(int hfindex, tvbuff_t *tvb, gint start, gint *length,
2853 header_field_info *hfinfo;
2854 gint length_remaining;
2857 * We only allow a null tvbuff if the item has a zero length,
2858 * i.e. if there's no data backing it.
2860 DISSECTOR_ASSERT(tvb != NULL || *length == 0);
2862 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2865 * XXX - in some protocols, there are 32-bit unsigned length
2866 * fields, so lengths in protocol tree and tvbuff routines
2867 * should really be unsigned. We should have, for those
2868 * field types for which "to the end of the tvbuff" makes sense,
2869 * additional routines that take no length argument and
2870 * add fields that run to the end of the tvbuff.
2872 if (*length == -1) {
2874 * For FT_NONE, FT_PROTOCOL, FT_BYTES, and FT_STRING fields,
2875 * a length of -1 means "set the length to what remains in
2878 * The assumption is either that
2880 * 1) the length of the item can only be determined
2881 * by dissection (typically true of items with
2882 * subitems, which are probably FT_NONE or
2887 * 2) if the tvbuff is "short" (either due to a short
2888 * snapshot length or due to lack of reassembly of
2889 * fragments/segments/whatever), we want to display
2890 * what's available in the field (probably FT_BYTES
2891 * or FT_STRING) and then throw an exception later
2895 * 3) the field is defined to be "what's left in the
2898 * so we set the length to what remains in the tvbuff so
2899 * that, if we throw an exception while dissecting, it
2900 * has what is probably the right value.
2902 * For FT_STRINGZ, it means "the string is null-terminated,
2903 * not null-padded; set the length to the actual length
2904 * of the string", and if the tvbuff if short, we just
2905 * throw an exception.
2907 * It's not valid for any other type of field.
2909 switch (hfinfo->type) {
2913 * We allow this to be zero-length - for
2914 * example, an ONC RPC NULL procedure has
2915 * neither arguments nor reply, so the
2916 * payload for that protocol is empty.
2918 * However, if the length is negative, the
2919 * start offset is *past* the byte past the
2920 * end of the tvbuff, so we throw an
2923 *length = tvb_length_remaining(tvb, start);
2926 * Use "tvb_ensure_bytes_exist()"
2927 * to force the appropriate exception
2930 tvb_ensure_bytes_exist(tvb, start, 0);
2932 DISSECTOR_ASSERT(*length >= 0);
2938 *length = tvb_ensure_length_remaining(tvb, start);
2939 DISSECTOR_ASSERT(*length >= 0);
2944 * Leave the length as -1, so our caller knows
2950 DISSECTOR_ASSERT_NOT_REACHED();
2952 *item_length = *length;
2954 *item_length = *length;
2955 if (hfinfo->type == FT_PROTOCOL || hfinfo->type == FT_NONE) {
2957 * These types are for interior nodes of the
2958 * tree, and don't have data associated with
2959 * them; if the length is negative (XXX - see
2960 * above) or goes past the end of the tvbuff,
2961 * cut it short at the end of the tvbuff.
2962 * That way, if this field is selected in
2963 * Wireshark, we don't highlight stuff past
2964 * the end of the data.
2966 /* XXX - what to do, if we don't have a tvb? */
2968 length_remaining = tvb_length_remaining(tvb, start);
2969 if (*item_length < 0 ||
2970 (*item_length > 0 &&
2971 (length_remaining < *item_length)))
2972 *item_length = length_remaining;
2975 if (*item_length < 0) {
2976 THROW(ReportedBoundsError);
2984 new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
2985 gint start, gint item_length)
2991 fi->hfinfo = hfinfo;
2993 fi->start+=(tvb)?TVB_RAW_OFFSET(tvb):0;
2994 fi->length = item_length;
2997 if (!PTREE_DATA(tree)->visible)
2998 FI_SET_FLAG(fi, FI_HIDDEN);
2999 fvalue_init(&fi->value, fi->hfinfo->type);
3002 /* add the data source tvbuff */
3003 fi->ds_tvb=tvb?TVB_GET_DS_TVB(tvb):NULL;
3005 fi->appendix_start = 0;
3006 fi->appendix_length = 0;
3012 alloc_field_info(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3015 header_field_info *hfinfo;
3018 hfinfo = get_hfi_and_length(hfindex, tvb, start, length, &item_length);
3019 return new_field_info(tree, hfinfo, tvb, start, item_length);
3022 /* If the protocol tree is to be visible, set the representation of a
3023 proto_tree entry with the name of the field for the item and with
3024 the value formatted with the supplied printf-style format and
3027 proto_tree_set_representation_value(proto_item *pi, const char *format, va_list ap)
3029 int ret; /*tmp return value */
3030 field_info *fi = PITEM_FINFO(pi);
3031 header_field_info *hf = fi->hfinfo;
3033 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
3034 ITEM_LABEL_NEW(fi->rep);
3035 if (hf->bitmask && (hf->type == FT_BOOLEAN || IS_FT_UINT(hf->type))) {
3039 val = fvalue_get_uinteger(&fi->value);
3040 if (hf->bitshift > 0) {
3041 val <<= hf->bitshift;
3043 decode_bitfield_value(tmpbuf, val, hf->bitmask, hfinfo_bitwidth(hf));
3044 /* put in the hf name */
3045 ret = g_snprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
3046 "%s%s: ", tmpbuf, fi->hfinfo->name);
3048 /* put in the hf name */
3049 ret = g_snprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
3050 "%s: ", fi->hfinfo->name);
3053 /* If possible, Put in the value of the string */
3054 if (ret < ITEM_LABEL_LENGTH) {
3055 ret += g_vsnprintf(fi->rep->representation + ret,
3056 ITEM_LABEL_LENGTH - ret, format, ap);
3058 if (ret >= ITEM_LABEL_LENGTH) {
3059 /* Uh oh, we don't have enough room. Tell the user
3060 * that the field is truncated.
3064 /* Argh, we cannot reuse 'ap' here. So make a copy
3065 * of what we formatted for (re)use below.
3067 oldrep = g_strdup(fi->rep->representation);
3069 g_snprintf(fi->rep->representation,
3078 /* If the protocol tree is to be visible, set the representation of a
3079 proto_tree entry with the representation formatted with the supplied
3080 printf-style format and argument list. */
3082 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap)
3084 int ret; /*tmp return value */
3085 field_info *fi = PITEM_FINFO(pi);
3087 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
3088 ITEM_LABEL_NEW(fi->rep);
3089 ret = g_vsnprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
3091 if (ret >= ITEM_LABEL_LENGTH) {
3092 /* Uh oh, we don't have enough room. Tell the user
3093 * that the field is truncated.
3097 /* Argh, we cannot reuse 'ap' here. So make a copy
3098 * of what we formatted for (re)use below.
3100 oldrep = g_strdup(fi->rep->representation);
3102 g_snprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
3103 "[truncated] %s", oldrep);
3109 /* Set text of proto_item after having already been created. */
3111 proto_item_set_text(proto_item *pi, const char *format, ...)
3113 field_info *fi = NULL;
3120 fi = PITEM_FINFO(pi);
3123 ITEM_LABEL_FREE(fi->rep);
3126 va_start(ap, format);
3127 proto_tree_set_representation(pi, format, ap);
3131 /* Append to text of proto_item after having already been created. */
3133 proto_item_append_text(proto_item *pi, const char *format, ...)
3135 field_info *fi = NULL;
3143 fi = PITEM_FINFO(pi);
3148 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
3149 va_start(ap, format);
3152 * If we don't already have a representation,
3153 * generate the default representation.
3155 if (fi->rep == NULL) {
3156 ITEM_LABEL_NEW(fi->rep);
3157 proto_item_fill_label(fi, fi->rep->representation);
3160 curlen = strlen(fi->rep->representation);
3161 if (ITEM_LABEL_LENGTH > curlen) {
3162 g_vsnprintf(fi->rep->representation + curlen,
3163 ITEM_LABEL_LENGTH - (gulong) curlen, format, ap);
3170 proto_item_set_len(proto_item *pi, gint length)
3176 fi = PITEM_FINFO(pi);
3177 DISSECTOR_ASSERT(length >= 0);
3178 fi->length = length;
3180 if (fi->value.ftype->ftype == FT_BYTES)
3181 fi->value.value.bytes->len = length;
3185 * Sets the length of the item based on its start and on the specified
3186 * offset, which is the offset past the end of the item; as the start
3187 * in the item is relative to the beginning of the data source tvbuff,
3188 * we need to pass in a tvbuff - the end offset is relative to the beginning
3192 proto_item_set_end(proto_item *pi, tvbuff_t *tvb, gint end)
3198 fi = PITEM_FINFO(pi);
3199 end += TVB_RAW_OFFSET(tvb);
3200 DISSECTOR_ASSERT(end >= fi->start);
3201 fi->length = end - fi->start;
3205 proto_item_get_len(proto_item *pi)
3207 field_info *fi = PITEM_FINFO(pi);
3212 /** clear flags according to the mask and set new flag values */
3213 #define FI_REPLACE_FLAGS(fi, mask, flags_in) { \
3214 (fi->flags = (fi)->flags & ~(mask)); \
3215 (fi->flags = (fi)->flags | (flags_in)); \
3219 proto_item_set_expert_flags(proto_item *pi, int group, guint severity)
3221 if(pi == NULL || PITEM_FINFO(pi) == NULL)
3224 /* only change things if severity is worse or at least equal than before */
3225 if(severity >= FI_GET_FLAG(PITEM_FINFO(pi), PI_SEVERITY_MASK)) {
3226 FI_REPLACE_FLAGS(PITEM_FINFO(pi), PI_GROUP_MASK, group);
3227 FI_REPLACE_FLAGS(PITEM_FINFO(pi), PI_SEVERITY_MASK, severity);
3238 proto_tree_create_root(void)
3242 /* Initialize the proto_node */
3243 PROTO_NODE_NEW(pnode);
3244 pnode->parent = NULL;
3245 PNODE_FINFO(pnode) = NULL;
3246 pnode->tree_data = g_new(tree_data_t, 1);
3248 /* Don't initialize the tree_data_t. Wait until we know we need it */
3249 pnode->tree_data->interesting_hfids = NULL;
3251 /* Set the default to FALSE so it's easier to
3252 * find errors; if we expect to see the protocol tree
3253 * but for some reason the default 'visible' is not
3254 * changed, then we'll find out very quickly. */
3255 pnode->tree_data->visible = FALSE;
3257 /* Make sure that we fake protocols (if possible) */
3258 pnode->tree_data->fake_protocols = TRUE;
3260 /* Keep track of the number of children */
3261 pnode->tree_data->count = 0;
3263 return (proto_tree*) pnode;
3267 /* "prime" a proto_tree with a single hfid that a dfilter
3268 * is interested in. */
3270 proto_tree_prime_hfid(proto_tree *tree _U_, gint hfid)
3272 header_field_info *hfinfo;
3274 PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
3275 /* this field is referenced by a filter so increase the refcount.
3276 also increase the refcount for the parent, i.e the protocol.
3278 hfinfo->ref_count = HF_REF_TYPE_DIRECT;
3279 /* only increase the refcount if there is a parent.
3280 if this is a protocol and not a field then parent will be -1
3281 and there is no parent to add any refcounting for.
3283 if (hfinfo->parent != -1) {
3284 header_field_info *parent_hfinfo;
3285 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
3287 /* Mark parent as indirectly referenced unless it is already directly
3288 * referenced, i.e. the user has specified the parent in a filter.
3290 if (parent_hfinfo->ref_count != HF_REF_TYPE_DIRECT)
3291 parent_hfinfo->ref_count = HF_REF_TYPE_INDIRECT;
3296 proto_item_add_subtree(proto_item *pi, gint idx) {
3302 fi = PITEM_FINFO(pi);
3303 DISSECTOR_ASSERT(idx >= 0 && idx < num_tree_types);
3304 fi->tree_type = idx;
3306 return (proto_tree*) pi;
3310 proto_item_get_subtree(proto_item *pi) {
3315 fi = PITEM_FINFO(pi);
3316 if ( (!fi) || (fi->tree_type == -1) )
3318 return (proto_tree*) pi;
3322 proto_item_get_parent(proto_item *ti) {
3329 proto_item_get_parent_nth(proto_item *ti, int gen) {
3342 proto_tree_get_parent(proto_tree *tree) {
3345 return (proto_item*) tree;
3349 proto_tree_get_root(proto_tree *tree) {
3352 while (tree->parent) {
3353 tree = tree->parent;
3359 proto_tree_move_item(proto_tree *tree, proto_item *fixed_item, proto_item *item_to_move)
3361 DISSECTOR_ASSERT(item_to_move->parent == tree);
3362 DISSECTOR_ASSERT(fixed_item->parent == tree);
3364 /*** cut item_to_move out ***/
3366 /* is item_to_move the first? */
3367 if(tree->first_child == item_to_move) {
3368 /* simply change first child to next */
3369 tree->first_child = item_to_move->next;
3371 DISSECTOR_ASSERT(tree->last_child != item_to_move);
3373 proto_item *curr_item;
3374 /* find previous and change it's next */
3375 for(curr_item = tree->first_child; curr_item != NULL; curr_item = curr_item->next) {
3376 if(curr_item->next == item_to_move) {
3381 DISSECTOR_ASSERT(curr_item);
3383 curr_item->next = item_to_move->next;
3385 /* fix last_child if required */
3386 if(tree->last_child == item_to_move) {
3387 tree->last_child = curr_item;
3391 /*** insert to_move after fixed ***/
3392 item_to_move->next = fixed_item->next;
3393 fixed_item->next = item_to_move;
3394 if(tree->last_child == fixed_item) {
3395 tree->last_child = item_to_move;
3400 proto_tree_set_appendix(proto_tree *tree, tvbuff_t *tvb, gint start, gint length)
3407 fi = PTREE_FINFO(tree);
3408 start += TVB_RAW_OFFSET(tvb);
3409 DISSECTOR_ASSERT(start >= 0);
3410 DISSECTOR_ASSERT(length >= 0);
3412 fi->appendix_start = start;
3413 fi->appendix_length = length;
3417 proto_register_protocol(const char *name, const char *short_name, const char *filter_name)
3419 protocol_t *protocol;
3420 header_field_info *hfinfo;
3422 char *existing_name;
3426 gboolean found_invalid;
3429 * Make sure there's not already a protocol with any of those
3430 * names. Crash if there is, as that's an error in the code
3431 * or an inappropriate plugin.
3432 * This situation has to be fixed to not register more than one
3433 * protocol with the same name.
3435 * This is done by reducing the number of strcmp (and alike) calls as much as possible,
3436 * as this significally slows down startup time.
3438 * Drawback: As a hash value is used to reduce insert time,
3439 * this might lead to a hash collision.
3440 * However, as we have around 500+ protocols and we're using a 32 bit int this is very,
3444 key = g_malloc (sizeof(gint));
3445 *key = wrs_str_hash(name);
3446 existing_name = g_hash_table_lookup(proto_names, key);
3447 if (existing_name != NULL) {
3448 /* g_error will terminate the program */
3449 g_error("Duplicate protocol name \"%s\"!"
3450 " This might be caused by an inappropriate plugin or a development error.", name);
3452 g_hash_table_insert(proto_names, key, (gpointer)name);
3454 existing_name = g_hash_table_lookup(proto_short_names, (gpointer)short_name);
3455 if (existing_name != NULL) {
3456 g_error("Duplicate protocol short_name \"%s\"!"
3457 " This might be caused by an inappropriate plugin or a development error.", short_name);
3459 g_hash_table_insert(proto_short_names, (gpointer)short_name, (gpointer)short_name);
3461 found_invalid = FALSE;
3462 for (i = 0; i < strlen(filter_name); i++) {
3464 if (!(islower(c) || isdigit(c) || c == '-' || c == '_' || c == '.')) {
3465 found_invalid = TRUE;
3468 if (found_invalid) {
3469 g_error("Protocol filter name \"%s\" has one or more invalid characters."
3470 " Allowed are lower characters, digits, '-', '_' and '.'."
3471 " This might be caused by an inappropriate plugin or a development error.", filter_name);
3473 existing_name = g_hash_table_lookup(proto_filter_names, (gpointer)filter_name);
3474 if (existing_name != NULL) {
3475 g_error("Duplicate protocol filter_name \"%s\"!"
3476 " This might be caused by an inappropriate plugin or a development error.", filter_name);
3478 g_hash_table_insert(proto_filter_names, (gpointer)filter_name, (gpointer)filter_name);
3480 /* Add this protocol to the list of known protocols; the list
3481 is sorted by protocol short name. */
3482 protocol = g_malloc(sizeof (protocol_t));
3483 protocol->name = name;
3484 protocol->short_name = short_name;
3485 protocol->filter_name = filter_name;
3486 protocol->fields = NULL;
3487 protocol->is_enabled = TRUE; /* protocol is enabled by default */
3488 protocol->can_toggle = TRUE;
3489 protocol->is_private = FALSE;
3490 /* list will be sorted later by name, when all protocols completed registering */
3491 protocols = g_list_prepend(protocols, protocol);
3493 /* Here we do allocate a new header_field_info struct */
3494 hfinfo = g_mem_chunk_alloc(gmc_hfinfo);
3495 hfinfo->name = name;
3496 hfinfo->abbrev = filter_name;
3497 hfinfo->type = FT_PROTOCOL;
3498 hfinfo->display = BASE_NONE;
3499 hfinfo->strings = protocol;
3500 hfinfo->bitmask = 0;
3501 hfinfo->bitshift = 0;
3502 hfinfo->ref_count = HF_REF_TYPE_NONE;
3503 hfinfo->blurb = NULL;
3504 hfinfo->parent = -1; /* this field differentiates protos and fields */
3506 proto_id = proto_register_field_init(hfinfo, hfinfo->parent);
3507 protocol->proto_id = proto_id;
3512 proto_mark_private(int proto_id)
3514 protocol_t *protocol = find_protocol_by_id(proto_id);
3516 protocol->is_private = TRUE;
3520 proto_is_private(int proto_id)
3522 protocol_t *protocol = find_protocol_by_id(proto_id);
3524 return protocol->is_private;
3530 * Routines to use to iterate over the protocols.
3531 * The argument passed to the iterator routines is an opaque cookie to
3532 * their callers; it's the GList pointer for the current element in
3534 * The ID of the protocol is returned, or -1 if there is no protocol.
3537 proto_get_first_protocol(void **cookie)
3539 protocol_t *protocol;
3541 if (protocols == NULL)
3543 *cookie = protocols;
3544 protocol = protocols->data;
3545 return protocol->proto_id;
3549 proto_get_next_protocol(void **cookie)
3551 GList *list_item = *cookie;
3552 protocol_t *protocol;
3554 list_item = g_list_next(list_item);
3555 if (list_item == NULL)
3557 *cookie = list_item;
3558 protocol = list_item->data;
3559 return protocol->proto_id;
3563 proto_get_first_protocol_field(int proto_id, void **cookie)
3565 protocol_t *protocol = find_protocol_by_id(proto_id);
3566 hf_register_info *ptr;
3568 if ((protocol == NULL) || (protocol->fields == NULL))
3571 *cookie = protocol->fields;
3572 ptr = protocol->fields->data;
3573 return &ptr->hfinfo;
3577 proto_get_next_protocol_field(void **cookie)
3579 GList *list_item = *cookie;
3580 hf_register_info *ptr;
3582 list_item = g_list_next(list_item);
3583 if (list_item == NULL)
3586 *cookie = list_item;
3587 ptr = list_item->data;
3588 return &ptr->hfinfo;
3592 find_protocol_by_id(int proto_id)
3594 header_field_info *hfinfo;
3599 PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
3600 DISSECTOR_ASSERT(hfinfo->type==FT_PROTOCOL);
3601 return (protocol_t *)hfinfo->strings;
3604 static gint compare_filter_name(gconstpointer proto_arg,
3605 gconstpointer filter_name)
3607 const protocol_t *protocol = proto_arg;
3608 const gchar* f_name = filter_name;
3610 return (strcmp(protocol->filter_name, f_name));
3614 proto_get_id(protocol_t *protocol)
3616 return protocol->proto_id;
3619 int proto_get_id_by_filter_name(const gchar* filter_name)
3622 protocol_t *protocol;
3624 list_entry = g_list_find_custom(protocols, filter_name,
3625 compare_filter_name);
3627 if (list_entry == NULL)
3629 protocol = list_entry->data;
3630 return protocol->proto_id;
3634 proto_get_protocol_name(int proto_id)
3636 protocol_t *protocol;
3638 protocol = find_protocol_by_id(proto_id);
3639 return protocol->name;
3643 proto_get_protocol_short_name(protocol_t *protocol)
3645 if (protocol == NULL)
3647 return protocol->short_name;
3651 proto_get_protocol_long_name(protocol_t *protocol)
3653 if (protocol == NULL)
3655 return protocol->name;
3659 proto_get_protocol_filter_name(int proto_id)
3661 protocol_t *protocol;
3663 protocol = find_protocol_by_id(proto_id);
3664 if (protocol == NULL)
3666 return protocol->filter_name;
3670 proto_is_protocol_enabled(protocol_t *protocol)
3672 return protocol->is_enabled;
3676 proto_can_toggle_protocol(int proto_id)
3678 protocol_t *protocol;
3680 protocol = find_protocol_by_id(proto_id);
3681 return protocol->can_toggle;
3685 proto_set_decoding(int proto_id, gboolean enabled)
3687 protocol_t *protocol;
3689 protocol = find_protocol_by_id(proto_id);
3690 DISSECTOR_ASSERT(protocol->can_toggle);
3691 protocol->is_enabled = enabled;
3695 proto_enable_all(void)
3697 protocol_t *protocol;
3698 GList *list_item = protocols;
3700 if (protocols == NULL)
3704 protocol = list_item->data;
3705 if (protocol->can_toggle)
3706 protocol->is_enabled = TRUE;
3707 list_item = g_list_next(list_item);
3712 proto_set_cant_toggle(int proto_id)
3714 protocol_t *protocol;
3716 protocol = find_protocol_by_id(proto_id);
3717 protocol->can_toggle = FALSE;
3720 /* for use with static arrays only, since we don't allocate our own copies
3721 of the header_field_info struct contained within the hf_register_info struct */
3723 proto_register_field_array(int parent, hf_register_info *hf, int num_records)
3726 hf_register_info *ptr = hf;
3729 proto = find_protocol_by_id(parent);
3730 for (i = 0; i < num_records; i++, ptr++) {
3732 * Make sure we haven't registered this yet.
3733 * Most fields have variables associated with them
3734 * that are initialized to -1; some have array elements,
3735 * or possibly uninitialized variables, so we also allow
3736 * 0 (which is unlikely to be the field ID we get back
3737 * from "proto_register_field_init()").
3739 if (*ptr->p_id != -1 && *ptr->p_id != 0) {
3741 "Duplicate field detected in call to proto_register_field_array: %s is already registered\n",
3742 ptr->hfinfo.abbrev);
3746 if (proto != NULL) {
3747 if (proto->fields == NULL) {
3748 proto->fields = g_list_append(NULL, ptr);
3749 proto->last_field = proto->fields;
3752 g_list_append(proto->last_field, ptr)->next;
3755 field_id = proto_register_field_init(&ptr->hfinfo, parent);
3756 *ptr->p_id = field_id;
3760 /* chars allowed in field abbrev */
3762 const guchar fld_abbrev_chars[256] = {
3763 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00-0x0F */
3764 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10-0x1F */
3765 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, /* 0x20-0x2F '-', '.' */
3766 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 0x30-0x3F '0'-'9' */
3767 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x40-0x4F 'A'-'O' */
3768 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 0x50-0x5F 'P'-'Z', '_' */
3769 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x60-0x6F 'a'-'o' */
3770 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 0x70-0x7F 'p'-'z' */
3771 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80-0x8F */
3772 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90-0x9F */
3773 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xA0-0xAF */
3774 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xB0-0xBF */
3775 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xC0-0xCF */
3776 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xD0-0xDF */
3777 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xE0-0xEF */
3778 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xF0-0xFF */
3781 /* temporary function containing assert part for easier profiling */
3782 static void tmp_fld_check_assert(header_field_info *hfinfo) {
3783 /* The field must have a name (with length > 0) */
3784 DISSECTOR_ASSERT(hfinfo->name && hfinfo->name[0]);
3786 /* fields with an empty string for an abbreviation aren't filterable */
3787 DISSECTOR_ASSERT(hfinfo->abbrev);
3789 /* These types of fields are allowed to have value_strings, true_false_strings or a protocol_t struct*/
3790 DISSECTOR_ASSERT((hfinfo->strings == NULL) || (
3791 (hfinfo->type == FT_UINT8) ||
3792 (hfinfo->type == FT_UINT16) ||
3793 (hfinfo->type == FT_UINT24) ||
3794 (hfinfo->type == FT_UINT32) ||
3795 (hfinfo->type == FT_INT8) ||
3796 (hfinfo->type == FT_INT16) ||
3797 (hfinfo->type == FT_INT24) ||
3798 (hfinfo->type == FT_INT32) ||
3799 (hfinfo->type == FT_BOOLEAN) ||
3800 (hfinfo->type == FT_PROTOCOL) ||
3801 (hfinfo->type == FT_FRAMENUM) ));
3803 switch (hfinfo->type) {
3810 /* Hexadecimal and octal are, in printf() and everywhere else,
3811 * unsigned so don't allow dissectors to register a signed
3812 * field to be displayed unsigned. (Else how would we
3813 * display values negative values?)
3815 * If you want to take out this check, be sure to fix
3816 * hfinfo_numeric_format() so that it does not assert out
3817 * when trying to construct a hexadecimal representation of
3820 DISSECTOR_ASSERT(hfinfo->display != BASE_HEX &&
3821 hfinfo->display != BASE_HEX_DEC &&
3822 hfinfo->display != BASE_DEC_HEX &&
3823 hfinfo->display != BASE_OCT);
3829 if (hfinfo->strings == NULL) {
3830 /* Require integral types (other than frame number, which is
3831 always displayed in decimal) to have a number base */
3832 DISSECTOR_ASSERT(hfinfo->display != BASE_NONE);
3837 DISSECTOR_ASSERT(hfinfo->display != BASE_NONE);
3844 /* Don't allow bitfields or value strings for frame numbers and strings */
3845 DISSECTOR_ASSERT(hfinfo->bitmask == 0);
3846 DISSECTOR_ASSERT(hfinfo->strings == NULL);
3855 proto_register_field_init(header_field_info *hfinfo, int parent)
3858 tmp_fld_check_assert(hfinfo);
3860 /* if this is a bitfield, compute bitshift */
3861 if (hfinfo->bitmask) {
3862 hfinfo->bitshift = wrs_count_bitshift(hfinfo->bitmask);
3865 hfinfo->parent = parent;
3866 hfinfo->same_name_next = NULL;
3867 hfinfo->same_name_prev = NULL;
3869 /* if we always add and never delete, then id == len - 1 is correct */
3870 if(gpa_hfinfo.len>=gpa_hfinfo.allocated_len){
3871 if(!gpa_hfinfo.hfi){
3872 gpa_hfinfo.allocated_len=1000;
3873 gpa_hfinfo.hfi=g_malloc(sizeof(header_field_info *)*1000);
3875 gpa_hfinfo.allocated_len+=1000;
3876 gpa_hfinfo.hfi=g_realloc(gpa_hfinfo.hfi, sizeof(header_field_info *)*gpa_hfinfo.allocated_len);
3879 gpa_hfinfo.hfi[gpa_hfinfo.len]=hfinfo;
3881 hfinfo->id = gpa_hfinfo.len - 1;
3883 /* if we have real names, enter this field in the name tree */
3884 if ((hfinfo->name[0] != 0) && (hfinfo->abbrev[0] != 0 )) {
3886 header_field_info *same_name_next_hfinfo;
3889 /* Check that the filter name (abbreviation) is legal;
3890 * it must contain only alphanumerics, '-', "_", and ".". */
3891 c = wrs_check_charset(fld_abbrev_chars, hfinfo->abbrev);
3893 fprintf(stderr, "OOPS: '%c' in '%s'\n", c, hfinfo->abbrev);
3894 DISSECTOR_ASSERT(!c);
3897 /* We allow multiple hfinfo's to be registered under the same
3898 * abbreviation. This was done for X.25, as, depending
3899 * on whether it's modulo-8 or modulo-128 operation,
3900 * some bitfield fields may be in different bits of
3901 * a byte, and we want to be able to refer to that field
3902 * with one name regardless of whether the packets
3903 * are modulo-8 or modulo-128 packets. */
3905 same_name_hfinfo = NULL;
3907 g_tree_insert(gpa_name_tree, (gpointer) (hfinfo->abbrev), hfinfo);
3908 /* GLIB 2.x - if it is already present
3909 * the previous hfinfo with the same name is saved
3910 * to same_name_hfinfo by value destroy callback */
3911 if (same_name_hfinfo) {
3912 /* There's already a field with this name.
3913 * Put it after that field in the list of
3914 * fields with this name, then allow the code
3915 * after this if{} block to replace the old
3916 * hfinfo with the new hfinfo in the GTree. Thus,
3917 * we end up with a linked-list of same-named hfinfo's,
3918 * with the root of the list being the hfinfo in the GTree */
3919 same_name_next_hfinfo =
3920 same_name_hfinfo->same_name_next;
3922 hfinfo->same_name_next = same_name_next_hfinfo;
3923 if (same_name_next_hfinfo)
3924 same_name_next_hfinfo->same_name_prev = hfinfo;
3926 same_name_hfinfo->same_name_next = hfinfo;
3927 hfinfo->same_name_prev = same_name_hfinfo;
3935 proto_register_subtree_array(gint *const *indices, int num_indices)
3938 gint *const *ptr = indices;
3941 * If we've already allocated the array of tree types, expand
3942 * it; this lets plugins such as mate add tree types after
3943 * the initial startup. (If we haven't already allocated it,
3944 * we don't allocate it; on the first pass, we just assign
3945 * ett values and keep track of how many we've assigned, and
3946 * when we're finished registering all dissectors we allocate
3947 * the array, so that we do only one allocation rather than
3948 * wasting CPU time and memory by growing the array for each
3949 * dissector that registers ett values.)
3951 if (tree_is_expanded != NULL) {
3953 g_realloc(tree_is_expanded,
3954 (num_tree_types+num_indices)*sizeof (gboolean));
3955 memset(tree_is_expanded + num_tree_types, 0,
3956 num_indices*sizeof (gboolean));
3960 * Assign "num_indices" subtree numbers starting at "num_tree_types",
3961 * returning the indices through the pointers in the array whose
3962 * first element is pointed to by "indices", and update
3963 * "num_tree_types" appropriately.
3965 for (i = 0; i < num_indices; i++, ptr++, num_tree_types++) {
3967 /* g_error will terminate the program */
3968 g_error("register_subtree_array: subtree item type (ett_...) not -1 !"
3969 " This is a development error:"
3970 " Either the subtree item type has already been assigned or"
3971 " was not initialized to -1.");
3973 **ptr = num_tree_types;
3978 proto_item_fill_label(field_info *fi, gchar *label_str)
3980 header_field_info *hfinfo = fi->hfinfo;
3986 guint32 n_addr; /* network-order IPv4 address */
3988 int ret; /*tmp return value */
3990 switch(hfinfo->type) {
3993 g_strlcpy(label_str, hfinfo->name, ITEM_LABEL_LENGTH);
3997 fill_label_boolean(fi, label_str);
4002 bytes = fvalue_get(&fi->value);
4004 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4005 "%s: %s", hfinfo->name,
4006 bytes_to_str(bytes, fvalue_length(&fi->value)));
4007 if (ret >= ITEM_LABEL_LENGTH) {
4008 /* Uh oh, we don't have enough room. Tell the
4009 * user that the field is truncated.
4011 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4012 "%s [truncated]: %s",
4014 bytes_to_str(bytes, fvalue_length(&fi->value)));
4018 g_snprintf(label_str, ITEM_LABEL_LENGTH, "%s: <MISSING>", hfinfo->name);
4022 /* Four types of integers to take care of:
4023 * Bitfield, with val_string
4024 * Bitfield, w/o val_string
4025 * Non-bitfield, with val_string
4026 * Non-bitfield, w/o val_string
4032 if (hfinfo->bitmask) {
4033 fill_label_bitfield(fi, label_str);
4035 fill_label_uint(fi, label_str);
4040 fill_label_uint(fi, label_str);
4044 fill_label_uint64(fi, label_str);
4051 DISSECTOR_ASSERT(!hfinfo->bitmask);
4052 fill_label_int(fi, label_str);
4056 fill_label_int64(fi, label_str);
4060 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4061 "%s: %." STRINGIFY(FLT_DIG) "f",
4062 hfinfo->name, fvalue_get_floating(&fi->value));
4066 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4067 "%s: %." STRINGIFY(DBL_DIG) "g",
4068 hfinfo->name, fvalue_get_floating(&fi->value));
4071 case FT_ABSOLUTE_TIME:
4072 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4073 "%s: %s", hfinfo->name,
4074 abs_time_to_str(fvalue_get(&fi->value)));
4077 case FT_RELATIVE_TIME:
4078 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4079 "%s: %s seconds", hfinfo->name,
4080 rel_time_to_secs_str(fvalue_get(&fi->value)));
4084 integer = fvalue_get_uinteger(&fi->value);
4085 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4086 "%s: %s (0x%08X)", hfinfo->name,
4087 get_ipxnet_name(integer), integer);
4091 bytes = fvalue_get(&fi->value);
4092 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4093 "%s: %s (%s)", hfinfo->name,
4094 get_ether_name(bytes),
4095 ether_to_str(bytes));
4099 ipv4 = fvalue_get(&fi->value);
4100 n_addr = ipv4_get_net_order_addr(ipv4);
4101 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4102 "%s: %s (%s)", hfinfo->name,
4103 get_hostname(n_addr),
4104 ip_to_str((guint8*)&n_addr));
4108 bytes = fvalue_get(&fi->value);
4109 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4110 "%s: %s (%s)", hfinfo->name,
4111 get_hostname6((struct e_in6_addr *)bytes),
4112 ip6_to_str((struct e_in6_addr*)bytes));
4116 guid = fvalue_get(&fi->value);
4117 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4118 "%s: %s", hfinfo->name,
4123 bytes = fvalue_get(&fi->value);
4124 name = oid_resolved_from_encoded(bytes, fvalue_length(&fi->value));
4126 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4127 "%s: %s (%s)", hfinfo->name,
4128 oid_encoded2string(bytes, fvalue_length(&fi->value)), name);
4130 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4131 "%s: %s", hfinfo->name,
4132 oid_encoded2string(bytes, fvalue_length(&fi->value)));
4139 case FT_UINT_STRING:
4140 bytes = fvalue_get(&fi->value);
4141 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4142 "%s: %s", hfinfo->name,
4143 format_text(bytes, strlen(bytes)));
4144 if (ret >= ITEM_LABEL_LENGTH) {
4145 /* Uh oh, we don't have enough room. Tell the
4146 * user that the field is truncated.
4148 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4149 "%s [truncated]: %s",
4151 format_text(bytes, strlen(bytes)));
4156 g_error("hfinfo->type %d (%s) not handled\n",
4158 ftype_name(hfinfo->type));
4159 DISSECTOR_ASSERT_NOT_REACHED();
4165 fill_label_boolean(field_info *fi, gchar *label_str)
4167 char *p = label_str;
4168 int bitfield_byte_length = 0, bitwidth;
4169 guint32 unshifted_value;
4172 header_field_info *hfinfo = fi->hfinfo;
4173 const true_false_string *tfstring = (const true_false_string *)&tfs_true_false;
4175 if (hfinfo->strings) {
4176 tfstring = (const struct true_false_string*) hfinfo->strings;
4179 value = fvalue_get_uinteger(&fi->value);
4180 if (hfinfo->bitmask) {
4181 /* Figure out the bit width */
4182 bitwidth = hfinfo_bitwidth(hfinfo);
4185 unshifted_value = value;
4186 if (hfinfo->bitshift > 0) {
4187 unshifted_value <<= hfinfo->bitshift;
4190 /* Create the bitfield first */
4191 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
4192 bitfield_byte_length = (int) (p - label_str);
4195 /* Fill in the textual info */
4196 g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
4197 "%s: %s", hfinfo->name,
4198 value ? tfstring->true_string : tfstring->false_string);
4201 /* Fills data for bitfield ints with val_strings */
4203 fill_label_bitfield(field_info *fi, gchar *label_str)
4205 const char *format = NULL;
4207 int bitfield_byte_length, bitwidth;
4208 guint32 unshifted_value;
4211 header_field_info *hfinfo = fi->hfinfo;
4213 /* Figure out the bit width */
4214 bitwidth = hfinfo_bitwidth(hfinfo);
4217 unshifted_value = fvalue_get_uinteger(&fi->value);
4218 value = unshifted_value;
4219 if (hfinfo->bitshift > 0) {
4220 unshifted_value <<= hfinfo->bitshift;
4223 /* Create the bitfield first */
4224 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
4225 bitfield_byte_length = (int) (p - label_str);
4227 /* Fill in the textual info using stored (shifted) value */
4228 if (hfinfo->display == BASE_CUSTOM) {
4229 gchar tmp[ITEM_LABEL_LENGTH];
4230 custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hfinfo->strings;
4232 DISSECTOR_ASSERT(fmtfunc);
4233 fmtfunc(tmp, value);
4234 g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
4235 "%s: %s", hfinfo->name, tmp);
4237 else if (hfinfo->strings) {
4238 format = hfinfo_uint_vals_format(hfinfo);
4239 if (hfinfo->display & BASE_RANGE_STRING) {
4240 g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
4241 format, hfinfo->name,
4242 rval_to_str(value, hfinfo->strings, "Unknown"), value);
4244 g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
4245 format, hfinfo->name,
4246 val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
4250 format = hfinfo_uint_format(hfinfo);
4251 if (IS_BASE_DUAL(hfinfo->display)) {
4252 g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
4253 format, hfinfo->name, value, value);
4255 g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
4256 format, hfinfo->name, value);
4262 fill_label_uint(field_info *fi, gchar *label_str)
4264 const char *format = NULL;
4265 header_field_info *hfinfo = fi->hfinfo;
4268 value = fvalue_get_uinteger(&fi->value);
4270 /* Fill in the textual info */
4271 if (hfinfo->display == BASE_CUSTOM) {
4272 gchar tmp[ITEM_LABEL_LENGTH];
4273 custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hfinfo->strings;
4275 DISSECTOR_ASSERT(fmtfunc);
4276 fmtfunc(tmp, value);
4277 g_snprintf(label_str, ITEM_LABEL_LENGTH, "%s: %s", hfinfo->name, tmp);
4279 else if (hfinfo->strings) {
4280 format = hfinfo_uint_vals_format(hfinfo);
4281 if (hfinfo->display & BASE_RANGE_STRING) {
4282 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4283 format, hfinfo->name,
4284 rval_to_str(value, hfinfo->strings, "Unknown"), value);
4286 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4287 format, hfinfo->name,
4288 val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
4292 format = hfinfo_uint_format(hfinfo);
4293 if (IS_BASE_DUAL(hfinfo->display)) {
4294 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4295 format, hfinfo->name, value, value);
4297 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4298 format, hfinfo->name, value);
4304 fill_label_uint64(field_info *fi, gchar *label_str)
4306 const char *format = NULL;
4307 header_field_info *hfinfo = fi->hfinfo;
4310 /* Pick the proper format string */
4311 format = hfinfo_uint64_format(hfinfo);
4312 value = fvalue_get_integer64(&fi->value);
4314 /* Fill in the textual info */
4315 if (IS_BASE_DUAL(hfinfo->display)) {
4316 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4317 format, hfinfo->name, value, value);
4319 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4320 format, hfinfo->name, value);
4325 fill_label_int(field_info *fi, gchar *label_str)
4327 const char *format = NULL;
4328 header_field_info *hfinfo = fi->hfinfo;
4331 value = fvalue_get_sinteger(&fi->value);
4333 /* Fill in the textual info */
4334 if (hfinfo->display == BASE_CUSTOM) {
4335 gchar tmp[ITEM_LABEL_LENGTH];
4336 custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hfinfo->strings;
4338 DISSECTOR_ASSERT(fmtfunc);
4339 fmtfunc(tmp, value);
4340 g_snprintf(label_str, ITEM_LABEL_LENGTH, "%s: %s", hfinfo->name, tmp);
4342 else if (hfinfo->strings) {
4343 format = hfinfo_int_vals_format(hfinfo);
4344 if (hfinfo->display & BASE_RANGE_STRING) {
4345 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4346 format, hfinfo->name,
4347 rval_to_str(value, hfinfo->strings, "Unknown"), value);
4349 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4350 format, hfinfo->name,
4351 val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
4355 format = hfinfo_int_format(hfinfo);
4356 if (IS_BASE_DUAL(hfinfo->display)) {
4357 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4358 format, hfinfo->name, value, value);
4360 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4361 format, hfinfo->name, value);
4367 fill_label_int64(field_info *fi, gchar *label_str)
4369 const char *format = NULL;
4370 header_field_info *hfinfo = fi->hfinfo;
4373 /* Pick the proper format string */
4374 format = hfinfo_int64_format(hfinfo);
4375 value = fvalue_get_integer64(&fi->value);
4377 /* Fill in the textual info */
4378 if (IS_BASE_DUAL(hfinfo->display)) {
4379 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4380 format, hfinfo->name, value, value);
4382 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4383 format, hfinfo->name, value);
4388 hfinfo_bitwidth(header_field_info *hfinfo)
4392 if (!hfinfo->bitmask) {
4396 switch(hfinfo->type) {
4414 bitwidth = hfinfo->display; /* hacky? :) */
4417 DISSECTOR_ASSERT_NOT_REACHED();
4424 hfinfo_uint_vals_format(header_field_info *hfinfo)
4426 const char *format = NULL;
4428 /* bit operation to reset the potential BASE_RANGE_STRING (or others in
4430 switch(hfinfo->display & BASE_STRUCTURE_RESET) {
4436 format = "%s: %s (%u)";
4438 case BASE_OCT: /* I'm lazy */
4439 format = "%s: %s (%o)";
4443 switch(hfinfo->type) {
4445 format = "%s: %s (0x%02x)";
4448 format = "%s: %s (0x%04x)";
4451 format = "%s: %s (0x%06x)";
4454 format = "%s: %s (0x%08x)";
4457 DISSECTOR_ASSERT_NOT_REACHED();
4462 DISSECTOR_ASSERT_NOT_REACHED();
4469 hfinfo_uint_format(header_field_info *hfinfo)
4471 const char *format = NULL;
4473 /* Pick the proper format string */
4474 if (hfinfo->type == FT_FRAMENUM) {
4476 * Frame numbers are always displayed in decimal.
4480 switch(hfinfo->display) {
4485 switch(hfinfo->type) {
4487 format = "%s: %u (0x%02x)";
4490 format = "%s: %u (0x%04x)";
4493 format = "%s: %u (0x%06x)";
4496 format = "%s: %u (0x%08x)";
4499 DISSECTOR_ASSERT_NOT_REACHED();
4503 case BASE_OCT: /* I'm lazy */
4507 switch(hfinfo->type) {
4509 format = "%s: 0x%02x";
4512 format = "%s: 0x%04x";
4515 format = "%s: 0x%06x";
4518 format = "%s: 0x%08x";
4521 DISSECTOR_ASSERT_NOT_REACHED();
4526 switch(hfinfo->type) {
4528 format = "%s: 0x%02x (%u)";
4531 format = "%s: 0x%04x (%u)";
4534 format = "%s: 0x%06x (%u)";
4537 format = "%s: 0x%08x (%u)";
4540 DISSECTOR_ASSERT_NOT_REACHED();
4545 DISSECTOR_ASSERT_NOT_REACHED();
4553 hfinfo_uint_value_format(header_field_info *hfinfo)
4555 const char *format = NULL;
4557 /* Pick the proper format string */
4558 if (hfinfo->type == FT_FRAMENUM) {
4560 * Frame numbers are always displayed in decimal.
4564 switch(hfinfo->display) {
4569 switch(hfinfo->type) {
4571 format = "%u (0x%02x)";
4574 format = "%u (0x%04x)";
4577 format = "%u (0x%06x)";
4580 format = "%u (0x%08x)";
4583 DISSECTOR_ASSERT_NOT_REACHED();
4591 switch(hfinfo->type) {
4605 DISSECTOR_ASSERT_NOT_REACHED();
4610 switch(hfinfo->type) {
4612 format = "0x%02x (%u)";
4615 format = "0x%04x (%u)";
4618 format = "0x%06x (%u)";
4621 format = "0x%08x (%u)";
4624 DISSECTOR_ASSERT_NOT_REACHED();
4629 DISSECTOR_ASSERT_NOT_REACHED();
4637 hfinfo_int_vals_format(header_field_info *hfinfo)
4639 const char *format = NULL;
4641 /* bit operation to reset the potential BASE_RANGE_STRING (or others in
4643 switch(hfinfo->display & BASE_STRUCTURE_RESET) {
4649 format = "%s: %s (%d)";
4651 case BASE_OCT: /* I'm lazy */
4652 format = "%s: %s (%o)";
4656 switch(hfinfo->type) {
4658 format = "%s: %s (0x%02x)";
4661 format = "%s: %s (0x%04x)";
4664 format = "%s: %s (0x%06x)";
4667 format = "%s: %s (0x%08x)";
4670 DISSECTOR_ASSERT_NOT_REACHED();
4675 DISSECTOR_ASSERT_NOT_REACHED();
4682 hfinfo_uint64_format(header_field_info *hfinfo)
4684 const char *format = NULL;
4686 /* Pick the proper format string */
4687 switch(hfinfo->display) {
4689 format = "%s: %" G_GINT64_MODIFIER "u";
4692 format = "%s: %" G_GINT64_MODIFIER "u (%" G_GINT64_MODIFIER "x)";
4694 case BASE_OCT: /* I'm lazy */
4695 format = "%s: %" G_GINT64_MODIFIER "o";
4698 format = "%s: 0x%016" G_GINT64_MODIFIER "x";
4701 format = "%s: 0x%016" G_GINT64_MODIFIER "x (%" G_GINT64_MODIFIER "u)";
4704 DISSECTOR_ASSERT_NOT_REACHED();
4711 hfinfo_int_format(header_field_info *hfinfo)
4713 const char *format = NULL;
4715 /* Pick the proper format string */
4716 switch(hfinfo->display) {
4721 switch(hfinfo->type) {
4723 format = "%s: %d (0x%02x)";
4726 format = "%s: %d (0x%04x)";
4729 format = "%s: %d (0x%06x)";
4732 format = "%s: %d (0x%08x)";
4735 DISSECTOR_ASSERT_NOT_REACHED();
4739 case BASE_OCT: /* I'm lazy */
4743 switch(hfinfo->type) {
4745 format = "%s: 0x%02x";
4748 format = "%s: 0x%04x";
4751 format = "%s: 0x%06x";
4754 format = "%s: 0x%08x";
4757 DISSECTOR_ASSERT_NOT_REACHED();
4762 switch(hfinfo->type) {
4764 format = "%s: 0x%02x (%d)";
4767 format = "%s: 0x%04x (%d)";
4770 format = "%s: 0x%06x (%d)";
4773 format = "%s: 0x%08x (%d)";
4776 DISSECTOR_ASSERT_NOT_REACHED();
4781 DISSECTOR_ASSERT_NOT_REACHED();
4788 hfinfo_int_value_format(header_field_info *hfinfo)
4790 const char *format = NULL;
4792 /* Pick the proper format string */
4793 switch(hfinfo->display) {
4798 switch(hfinfo->type) {
4800 format = "%d (0x%02x)";
4803 format = "%d (0x%04x)";
4806 format = "%d (0x%06x)";
4809 format = "%d (0x%08x)";
4812 DISSECTOR_ASSERT_NOT_REACHED();
4820 switch(hfinfo->type) {
4834 DISSECTOR_ASSERT_NOT_REACHED();
4839 switch(hfinfo->type) {
4841 format = "0x%02x (%d)";
4844 format = "0x%04x (%d)";
4847 format = "0x%06x (%d)";
4850 format = "0x%08x (%d)";
4853 DISSECTOR_ASSERT_NOT_REACHED();
4858 DISSECTOR_ASSERT_NOT_REACHED();
4865 hfinfo_int64_format(header_field_info *hfinfo)
4867 const char *format = NULL;
4869 /* Pick the proper format string */
4870 switch(hfinfo->display) {
4872 format = "%s: %" G_GINT64_MODIFIER "d";
4875 format = "%s: %" G_GINT64_MODIFIER "d (%" G_GINT64_MODIFIER "x)";
4877 case BASE_OCT: /* I'm lazy */
4878 format = "%s: %" G_GINT64_MODIFIER "o";
4881 format = "%s: 0x%016" G_GINT64_MODIFIER "x";
4884 format = "%s: 0x%016" G_GINT64_MODIFIER "x (%" G_GINT64_MODIFIER "d)";
4887 DISSECTOR_ASSERT_NOT_REACHED();
4896 proto_registrar_n(void)
4898 return gpa_hfinfo.len;
4902 proto_registrar_get_name(int n)
4904 header_field_info *hfinfo;
4906 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
4907 return hfinfo->name;
4911 proto_registrar_get_abbrev(int n)
4913 header_field_info *hfinfo;
4915 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
4916 return hfinfo->abbrev;
4920 proto_registrar_get_ftype(int n)
4922 header_field_info *hfinfo;
4924 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
4925 return hfinfo->type;
4929 proto_registrar_get_parent(int n)
4931 header_field_info *hfinfo;
4933 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
4934 return hfinfo->parent;
4938 proto_registrar_is_protocol(int n)
4940 header_field_info *hfinfo;
4942 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
4943 return (hfinfo->parent == -1 ? TRUE : FALSE);
4946 /* Returns length of field in packet (not necessarily the length
4947 * in our internal representation, as in the case of IPv4).
4948 * 0 means undeterminable at time of registration
4949 * -1 means the field is not registered. */
4951 proto_registrar_get_length(int n)
4953 header_field_info *hfinfo;
4955 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
4956 return ftype_length(hfinfo->type);
4961 /* Looks for a protocol or a field in a proto_tree. Returns TRUE if
4962 * it exists anywhere, or FALSE if it exists nowhere. */
4964 proto_check_for_protocol_or_field(proto_tree* tree, int id)
4966 GPtrArray *ptrs = proto_get_finfo_ptr_array(tree, id);
4971 else if (g_ptr_array_len(ptrs) > 0) {
4979 /* Return GPtrArray* of field_info pointers for all hfindex that appear in tree.
4980 * This only works if the hfindex was "primed" before the dissection
4981 * took place, as we just pass back the already-created GPtrArray*.
4982 * The caller should *not* free the GPtrArray*; proto_tree_free_node()
4985 proto_get_finfo_ptr_array(proto_tree *tree, int id)
4987 if (PTREE_DATA(tree)->interesting_hfids != NULL)
4988 return g_hash_table_lookup(PTREE_DATA(tree)->interesting_hfids,
4989 GINT_TO_POINTER(id));
4995 proto_tracking_interesting_fields(proto_tree *tree)
4997 return (PTREE_DATA(tree)->interesting_hfids != NULL);
5000 /* Helper struct for proto_find_info() and proto_all_finfos() */
5006 /* Helper function for proto_find_info() */
5008 find_finfo(proto_node *node, gpointer data)
5010 field_info *fi = PNODE_FINFO(node);
5011 if (fi && fi->hfinfo) {
5012 if (fi->hfinfo->id == ((ffdata_t*)data)->id) {
5013 g_ptr_array_add(((ffdata_t*)data)->array, fi);
5017 /* Don't stop traversing. */
5021 /* Return GPtrArray* of field_info pointers for all hfindex that appear in a tree.
5022 * This works on any proto_tree, primed or unprimed, but actually searches
5023 * the tree, so it is slower than using proto_get_finfo_ptr_array on a primed tree.
5024 * The caller does need to free the returned GPtrArray with
5025 * g_ptr_array_free(<array>, FALSE).
5028 proto_find_finfo(proto_tree *tree, int id)
5032 ffdata.array = g_ptr_array_new();
5035 proto_tree_traverse_pre_order(tree, find_finfo, &ffdata);
5037 return ffdata.array;
5040 /* Helper function for proto_all_finfos() */
5042 every_finfo(proto_node *node, gpointer data)
5044 field_info *fi = PNODE_FINFO(node);
5045 if (fi && fi->hfinfo) {
5046 g_ptr_array_add(((ffdata_t*)data)->array, fi);
5049 /* Don't stop traversing. */
5053 /* Return GPtrArray* of field_info pointers containing all hfindexes that appear in a tree. */
5055 proto_all_finfos(proto_tree *tree)
5059 ffdata.array = g_ptr_array_new();
5062 proto_tree_traverse_pre_order(tree, every_finfo, &ffdata);
5064 return ffdata.array;
5075 check_for_offset(proto_node *node, gpointer data)
5077 field_info *fi = PNODE_FINFO(node);
5078 offset_search_t *offsearch = data;
5080 /* !fi == the top most container node which holds nothing */
5081 if (fi && !PROTO_ITEM_IS_HIDDEN(node) && fi->ds_tvb && offsearch->tvb == fi->ds_tvb) {
5082 if (offsearch->offset >= (guint) fi->start &&
5083 offsearch->offset < (guint) (fi->start + fi->length)) {
5085 offsearch->finfo = fi;
5086 return FALSE; /* keep traversing */
5089 return FALSE; /* keep traversing */
5092 /* Search a proto_tree backwards (from leaves to root) looking for the field
5093 * whose start/length occupies 'offset' */
5094 /* XXX - I couldn't find an easy way to search backwards, so I search
5095 * forwards, w/o stopping. Therefore, the last finfo I find will the be
5096 * the one I want to return to the user. This algorithm is inefficient
5097 * and could be re-done, but I'd have to handle all the children and
5098 * siblings of each node myself. When I have more time I'll do that.
5101 proto_find_field_from_offset(proto_tree *tree, guint offset, tvbuff_t *tvb)
5103 offset_search_t offsearch;
5105 offsearch.offset = offset;
5106 offsearch.finfo = NULL;
5107 offsearch.tvb = tvb;
5109 proto_tree_traverse_pre_order(tree, check_for_offset, &offsearch);
5111 return offsearch.finfo;
5114 /* Dumps the protocols in the registration database to stdout. An independent
5115 * program can take this output and format it into nice tables or HTML or
5118 * There is one record per line. The fields are tab-delimited.
5120 * Field 1 = protocol name
5121 * Field 2 = protocol short name
5122 * Field 3 = protocol filter name
5125 proto_registrar_dump_protocols(void)
5127 protocol_t *protocol;
5129 void *cookie = NULL;
5131 for (i = proto_get_first_protocol(&cookie); i != -1;
5132 i = proto_get_next_protocol(&cookie)) {
5133 protocol = find_protocol_by_id(i);
5134 printf("%s\t%s\t%s\n", protocol->name, protocol->short_name,
5135 protocol->filter_name);
5139 /* Dumps the value_strings, range_strings or true/false strings for fields
5140 * that have them. There is one record per line. Fields are tab-delimited.
5141 * There are three types of records: Value String, Range String
5142 * and True/False String. The first field, 'V', 'R' or 'T', indicates
5143 * the type of record.
5148 * Field 2 = field abbreviation to which this value string corresponds
5149 * Field 3 = Integer value
5155 * Field 2 = field abbreviation to which this range string corresponds
5156 * Field 3 = Integer value: lower bound
5157 * Field 4 = Integer value: upper bound
5160 * True/False Strings
5161 * ------------------
5163 * Field 2 = field abbreviation to which this true/false string corresponds
5164 * Field 3 = True String
5165 * Field 4 = False String
5168 proto_registrar_dump_values(void)
5170 header_field_info *hfinfo, *parent_hfinfo;
5172 const value_string *vals;
5173 const range_string *range;
5174 const true_false_string *tfs;
5176 len = gpa_hfinfo.len;
5177 for (i = 0; i < len ; i++) {
5178 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
5180 if (hfinfo->id == hf_text_only) {
5184 /* ignore protocols */
5185 if (proto_registrar_is_protocol(i)) {
5188 /* process header fields */
5191 * If this field isn't at the head of the list of
5192 * fields with this name, skip this field - all
5193 * fields with the same name are really just versions
5194 * of the same field stored in different bits, and
5195 * should have the same type/radix/value list, and
5196 * just differ in their bit masks. (If a field isn't
5197 * a bitfield, but can be, say, 1 or 2 bytes long,
5198 * it can just be made FT_UINT16, meaning the
5199 * *maximum* length is 2 bytes, and be used
5202 if (hfinfo->same_name_prev != NULL)
5205 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
5211 if ((hfinfo->display & BASE_STRUCTURE_RESET) != BASE_CUSTOM &&
5212 (hfinfo->type == FT_UINT8 ||
5213 hfinfo->type == FT_UINT16 ||
5214 hfinfo->type == FT_UINT24 ||
5215 hfinfo->type == FT_UINT32 ||
5216 hfinfo->type == FT_UINT64 ||
5217 hfinfo->type == FT_INT8 ||
5218 hfinfo->type == FT_INT16 ||
5219 hfinfo->type == FT_INT24 ||
5220 hfinfo->type == FT_INT32 ||
5221 hfinfo->type == FT_INT64)) {
5223 if ((hfinfo->display & BASE_RANGE_STRING) == 0) {
5224 vals = hfinfo->strings;
5226 range = hfinfo->strings;
5229 else if (hfinfo->type == FT_BOOLEAN) {
5230 tfs = hfinfo->strings;
5233 /* Print value strings? */
5236 while (vals[vi].strptr) {
5237 /* Print in the proper base */
5238 if (hfinfo->display == BASE_HEX) {
5239 printf("V\t%s\t0x%x\t%s\n",
5245 printf("V\t%s\t%u\t%s\n",
5254 /* print range strings? */
5257 while (range[vi].strptr) {
5258 /* Print in the proper base */
5259 if ((hfinfo->display & BASE_STRUCTURE_RESET) == BASE_HEX) {
5260 printf("R\t%s\t0x%x\t0x%x\t%s\n",
5262 range[vi].value_min,
5263 range[vi].value_max,
5267 printf("R\t%s\t%u\t%u\t%s\n",
5269 range[vi].value_min,
5270 range[vi].value_max,
5277 /* Print true/false strings? */
5279 printf("T\t%s\t%s\t%s\n", hfinfo->abbrev,
5280 tfs->true_string, tfs->false_string);
5286 /* Dumps the contents of the registration database to stdout. An independent
5287 * program can take this output and format it into nice tables or HTML or
5290 * There is one record per line. Each record is either a protocol or a header
5291 * field, differentiated by the first field. The fields are tab-delimited.
5296 * Field 2 = descriptive protocol name
5297 * Field 3 = protocol abbreviation
5303 * Field 2 = descriptive field name
5304 * Field 3 = field abbreviation
5305 * Field 4 = type ( textual representation of the the ftenum type )
5306 * Field 5 = parent protocol abbreviation
5307 * Field 6 = blurb describing field
5311 * Field 2 = descriptive field name
5312 * Field 3 = field abbreviation
5313 * Field 4 = type ( textual representation of the the ftenum type )
5314 * Field 5 = parent protocol abbreviation
5315 * Field 6 = blurb describing field
5316 * Field 7 = base for display (for integer types); "parent bitfield width" for FT_BOOLEAN
5317 * Field 8 = blurb describing field (yes, apparently we repeated this accidentally)
5321 * Field 2 = descriptive field name
5322 * Field 3 = field abbreviation
5323 * Field 4 = type ( textual representation of the the ftenum type )
5324 * Field 5 = parent protocol abbreviation
5325 * Field 6 = blurb describing field
5326 * Field 7 = base for display (for integer types); "parent bitfield width" for FT_BOOLEAN
5327 * Field 8 = bitmask: format: hex: 0x....
5331 proto_registrar_dump_fields(int format)
5333 header_field_info *hfinfo, *parent_hfinfo;
5335 const char *enum_name;
5336 const char *base_name;
5340 len = gpa_hfinfo.len;
5341 for (i = 0; i < len ; i++) {
5342 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
5345 * Skip the pseudo-field for "proto_tree_add_text()" since
5346 * we don't want it in the list of filterable fields.
5348 if (hfinfo->id == hf_text_only)
5351 /* format for protocols */
5352 if (proto_registrar_is_protocol(i)) {
5353 printf("P\t%s\t%s\n", hfinfo->name, hfinfo->abbrev);
5355 /* format for header fields */
5358 * If this field isn't at the head of the list of
5359 * fields with this name, skip this field - all
5360 * fields with the same name are really just versions
5361 * of the same field stored in different bits, and
5362 * should have the same type/radix/value list, and
5363 * just differ in their bit masks. (If a field isn't
5364 * a bitfield, but can be, say, 1 or 2 bytes long,
5365 * it can just be made FT_UINT16, meaning the
5366 * *maximum* length is 2 bytes, and be used
5369 if (hfinfo->same_name_prev != NULL)
5372 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
5374 enum_name = ftype_name(hfinfo->type);
5378 if (hfinfo->type == FT_UINT8 ||
5379 hfinfo->type == FT_UINT16 ||
5380 hfinfo->type == FT_UINT24 ||
5381 hfinfo->type == FT_UINT32 ||
5382 hfinfo->type == FT_UINT64 ||
5383 hfinfo->type == FT_INT8 ||
5384 hfinfo->type == FT_INT16 ||
5385 hfinfo->type == FT_INT24 ||
5386 hfinfo->type == FT_INT32 ||
5387 hfinfo->type == FT_INT64) {
5390 switch(hfinfo->display & BASE_STRUCTURE_RESET) {
5392 base_name = "BASE_NONE";
5395 base_name = "BASE_DEC";
5398 base_name = "BASE_HEX";
5401 base_name = "BASE_OCT";
5404 base_name = "BASE_DEC_HEX";
5407 base_name = "BASE_HEX_DEC";
5410 base_name = "BASE_CUSTOM";
5416 } else if (hfinfo->type == FT_BOOLEAN) {
5417 /* For FT_BOOLEAN: 'display' can be "parent bitfield width" */
5418 g_snprintf(width, sizeof(width), "%d", hfinfo->display);
5423 blurb = hfinfo->blurb;
5427 printf("F\t%s\t%s\t%s\t%s\t%s\n",
5428 hfinfo->name, hfinfo->abbrev, enum_name,
5429 parent_hfinfo->abbrev, blurb);
5431 else if (format == 2) {
5432 printf("F\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n",
5433 hfinfo->name, hfinfo->abbrev, enum_name,
5434 parent_hfinfo->abbrev, blurb,
5437 else if (format == 3) {
5438 printf("F\t%s\t%s\t%s\t%s\t%s\t%s\t0x%x\n",
5439 hfinfo->name, hfinfo->abbrev, enum_name,
5440 parent_hfinfo->abbrev, blurb,
5441 base_name, hfinfo->bitmask);
5444 g_assert_not_reached();
5451 hfinfo_numeric_format(header_field_info *hfinfo)
5453 const char *format = NULL;
5455 /* Pick the proper format string */
5456 if (hfinfo->type == FT_FRAMENUM) {
5458 * Frame numbers are always displayed in decimal.
5460 format = "%s == %u";
5462 /* Pick the proper format string, ignoring BASE_RANGE_STRING flag */
5463 switch(hfinfo->display & ~BASE_RANGE_STRING) {
5466 case BASE_OCT: /* I'm lazy */
5468 switch(hfinfo->type) {
5473 format = "%s == %u";
5476 format = "%s == %" G_GINT64_MODIFIER "u";
5482 format = "%s == %d";
5485 format = "%s == %" G_GINT64_MODIFIER "d";
5488 DISSECTOR_ASSERT_NOT_REACHED();
5494 switch(hfinfo->type) {
5496 format = "%s == 0x%02x";
5499 format = "%s == 0x%04x";
5502 format = "%s == 0x%06x";
5505 format = "%s == 0x%08x";
5508 format = "%s == 0x%016" G_GINT64_MODIFIER "x";
5511 DISSECTOR_ASSERT_NOT_REACHED();
5516 DISSECTOR_ASSERT_NOT_REACHED();
5523 /* This function indicates whether it's possible to construct a
5524 * "match selected" display filter string for the specified field,
5525 * returns an indication of whether it's possible, and, if it's
5526 * possible and "filter" is non-null, constructs the filter and
5527 * sets "*filter" to point to it.
5528 * You do not need to [g_]free() this string since it will be automatically
5529 * freed once the next packet is dissected.
5532 construct_match_selected_string(field_info *finfo, epan_dissect_t *edt,
5535 header_field_info *hfinfo;
5541 gint start, length, length_remaining;
5543 gchar is_signed_num = FALSE;
5545 hfinfo = finfo->hfinfo;
5546 DISSECTOR_ASSERT(hfinfo);
5547 abbrev_len = (int) strlen(hfinfo->abbrev);
5549 if (hfinfo->strings && (hfinfo->display & BASE_STRUCTURE_RESET) == BASE_NONE) {
5550 const gchar *str = NULL;
5552 switch(hfinfo->type) {
5558 if (hfinfo->display & BASE_RANGE_STRING) {
5559 str = match_strrval(fvalue_get_sinteger(&finfo->value), hfinfo->strings);
5561 str = match_strval(fvalue_get_sinteger(&finfo->value), hfinfo->strings);
5569 if (hfinfo->display & BASE_RANGE_STRING) {
5570 str = match_strrval(fvalue_get_uinteger(&finfo->value), hfinfo->strings);
5572 str = match_strval(fvalue_get_uinteger(&finfo->value), hfinfo->strings);
5580 if (str != NULL && filter != NULL) {
5581 *filter = ep_strdup_printf("%s == \"%s\"", hfinfo->abbrev, str);
5587 * XXX - we can't use the "val_to_string_repr" and "string_repr_len"
5588 * functions for FT_UINT and FT_INT types, as we choose the base in
5589 * the string expression based on the display base of the field.
5591 * Note that the base does matter, as this is also used for
5592 * the protocolinfo tap.
5594 * It might be nice to use them in "proto_item_fill_label()"
5595 * as well, although, there, you'd have to deal with the base
5596 * *and* with resolved values for addresses.
5598 * Perhaps we need two different val_to_string routines, one
5599 * to generate items for display filters and one to generate
5600 * strings for display, and pass to both of them the
5601 * "display" and "strings" values in the header_field_info
5602 * structure for the field, so they can get the base and,
5603 * if the field is Boolean or an enumerated integer type,
5604 * the tables used to generate human-readable values.
5606 switch(hfinfo->type) {
5612 is_signed_num = TRUE;
5617 if (filter != NULL) {
5618 format = hfinfo_numeric_format(hfinfo);
5620 *filter = ep_strdup_printf(format,
5622 fvalue_get_sinteger(&finfo->value));
5624 *filter = ep_strdup_printf(format,
5626 fvalue_get_uinteger(&finfo->value));
5632 DISSECTOR_ASSERT(!is_signed_num);
5633 if (filter != NULL) {
5634 format = hfinfo_numeric_format(hfinfo);
5635 *filter = ep_strdup_printf(format,
5637 fvalue_get_uinteger(&finfo->value));
5643 if (filter != NULL) {
5644 format = hfinfo_numeric_format(hfinfo);
5645 *filter = ep_strdup_printf(format,
5647 fvalue_get_integer64(&finfo->value));
5653 *filter = ep_strdup(finfo->hfinfo->abbrev);
5658 * If the length is 0, just match the name of the
5661 * (Also check for negative values, just in case,
5662 * as we'll cast it to an unsigned value later.)
5664 length = finfo->length;
5667 *filter = ep_strdup(finfo->hfinfo->abbrev);
5674 * This doesn't have a value, so we'd match
5675 * on the raw bytes at this address.
5677 * Should we be allowed to access to the raw bytes?
5678 * If "edt" is NULL, the answer is "no".
5684 * Is this field part of the raw frame tvbuff?
5685 * If not, we can't use "frame[N:M]" to match
5688 * XXX - should this be frame-relative, or
5689 * protocol-relative?
5691 * XXX - does this fallback for non-registered
5692 * fields even make sense?
5694 if (finfo->ds_tvb != edt->tvb)
5695 return FALSE; /* you lose */
5698 * Don't go past the end of that tvbuff.
5700 length_remaining = tvb_length_remaining(finfo->ds_tvb, finfo->start);
5701 if (length > length_remaining)
5702 length = length_remaining;
5706 if (filter != NULL) {
5707 start = finfo->start;
5708 buf_len = 32 + length * 3;
5709 *filter = ep_alloc0(buf_len);
5712 ptr += g_snprintf(ptr, (gulong) (buf_len-(ptr-*filter)),
5713 "frame[%d:%d] == ", finfo->start, length);
5714 for (i=0;i<length; i++) {
5715 c = tvb_get_guint8(finfo->ds_tvb, start);
5718 ptr += g_snprintf(ptr, (gulong) (buf_len-(ptr-*filter)), "%02x", c);
5721 ptr += g_snprintf(ptr, (gulong) (buf_len-(ptr-*filter)), ":%02x", c);
5728 /* FT_PCRE never appears as a type for a registered field. It is
5729 * only used internally. */
5730 DISSECTOR_ASSERT_NOT_REACHED();
5733 /* By default, use the fvalue's "to_string_repr" method. */
5735 /* Figure out the string length needed.
5736 * The ft_repr length.
5737 * 4 bytes for " == ".
5738 * 1 byte for trailing NUL.
5740 if (filter != NULL) {
5741 dfilter_len = fvalue_string_repr_len(&finfo->value,
5743 dfilter_len += abbrev_len + 4 + 1;
5744 *filter = ep_alloc0(dfilter_len);
5746 /* Create the string */
5747 g_snprintf(*filter, dfilter_len, "%s == ",
5749 fvalue_to_string_repr(&finfo->value,
5751 &(*filter)[abbrev_len + 4]);
5760 * Returns TRUE if we can do a "match selected" on the field, FALSE
5764 proto_can_match_selected(field_info *finfo, epan_dissect_t *edt)
5766 return construct_match_selected_string(finfo, edt, NULL);
5769 /* This function attempts to construct a "match selected" display filter
5770 * string for the specified field; if it can do so, it returns a pointer
5771 * to the string, otherwise it returns NULL.
5773 * The string is allocated with packet lifetime scope.
5774 * You do not need to [g_]free() this string since it will be automatically
5775 * freed once the next packet is dissected.
5778 proto_construct_match_selected_string(field_info *finfo, epan_dissect_t *edt)
5782 if (!construct_match_selected_string(finfo, edt, &filter))
5788 /* This function is common code for both proto_tree_add_bitmask() and
5789 * proto_tree_add_bitmask_text() functions.
5792 proto_item_add_bitmask_tree(proto_item *item, tvbuff_t *tvb, int offset, int len, gint ett,
5793 const int **fields, gboolean little_endian, int flags, gboolean first)
5795 guint32 value = 0, tmpval;
5796 proto_tree *tree = NULL;
5797 header_field_info *hf;
5802 value = tvb_get_guint8(tvb, offset);
5805 value = little_endian ? tvb_get_letohs(tvb, offset) :
5806 tvb_get_ntohs(tvb, offset);
5809 value = little_endian ? tvb_get_letoh24(tvb, offset) :
5810 tvb_get_ntoh24(tvb, offset);
5813 value = little_endian ? tvb_get_letohl(tvb, offset) :
5814 tvb_get_ntohl(tvb, offset);
5817 g_assert_not_reached();
5820 tree = proto_item_add_subtree(item, ett);
5822 proto_tree_add_item(tree, **fields, tvb, offset, len, little_endian);
5823 if (flags & BMT_NO_APPEND) {
5827 hf = proto_registrar_get_nth(**fields);
5828 DISSECTOR_ASSERT(hf->bitmask != 0);
5829 tmpval = (value & hf->bitmask) >> hf->bitshift;
5840 DISSECTOR_ASSERT(len == ftype_length(hf->type));
5842 if (hf->display == BASE_CUSTOM) {
5843 gchar lbl[ITEM_LABEL_LENGTH];
5844 custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hf->strings;
5846 DISSECTOR_ASSERT(fmtfunc);
5847 fmtfunc(lbl, tmpval);
5848 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
5852 else if (hf->strings) {
5853 if (hf->display & BASE_RANGE_STRING) {
5854 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
5855 hf->name, rval_to_str(tmpval, hf->strings, "Unknown"));
5857 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
5858 hf->name, val_to_str(tmpval, cVALS(hf->strings), "Unknown"));
5862 else if (!(flags & BMT_NO_INT)) {
5864 proto_item_append_text(item, ", ");
5867 fmt = IS_FT_INT(hf->type) ? hfinfo_int_format(hf) : hfinfo_uint_format(hf);
5868 if (IS_BASE_DUAL(hf->display)) {
5869 proto_item_append_text(item, fmt, hf->name, tmpval, tmpval);
5871 proto_item_append_text(item, fmt, hf->name, tmpval);
5878 DISSECTOR_ASSERT(len * 8 == hf->display);
5880 if (hf->strings && !(flags & BMT_NO_TFS)) {
5881 /* If we have true/false strings, emit full - otherwise messages
5883 const struct true_false_string *tfs =
5884 (const struct true_false_string *)hf->strings;
5887 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
5888 hf->name, tfs->true_string);
5890 } else if (!(flags & BMT_NO_FALSE)) {
5891 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
5892 hf->name, tfs->false_string);
5895 } else if (hf->bitmask & value) {
5896 /* If the flag is set, show the name */
5897 proto_item_append_text(item, "%s%s", first ? "" : ", ", hf->name);
5902 g_assert_not_reached();
5911 /* This function will dissect a sequence of bytes that describe a
5913 * hf_hdr is a 8/16/24/32 bit integer that describes the bitmask to be dissected.
5914 * This field will form an expansion under which the individual fields of the
5915 * bitmask is dissected and displayed.
5916 * This field must be of the type FT_[U]INT{8|16|24|32}.
5918 * fields is an array of pointers to int that lists all the fields of the
5919 * bitmask. These fields can be either of the type FT_BOOLEAN for flags
5920 * or another integer of the same type/size as hf_hdr with a mask specified.
5921 * This array is terminated by a NULL entry.
5923 * FT_BOOLEAN bits that are set to 1 will have the name added to the expansion.
5924 * FT_integer fields that have a value_string attached will have the
5925 * matched string displayed on the expansion line.
5928 proto_tree_add_bitmask(proto_tree *parent_tree, tvbuff_t *tvb, guint offset, int hf_hdr,
5929 gint ett, const int **fields, gboolean little_endian)
5931 proto_item *item = NULL;
5932 header_field_info *hf;
5935 hf = proto_registrar_get_nth(hf_hdr);
5936 DISSECTOR_ASSERT(IS_FT_INT(hf->type) || IS_FT_UINT(hf->type));
5937 len = ftype_length(hf->type);
5940 item = proto_tree_add_item(parent_tree, hf_hdr, tvb, offset, len, little_endian);
5941 proto_item_add_bitmask_tree(item, tvb, offset, len, ett, fields, little_endian,
5942 BMT_NO_INT|BMT_NO_TFS, FALSE);
5948 /* The same as proto_tree_add_bitmask(), but using an arbitrary text as a top-level item */
5950 proto_tree_add_bitmask_text(proto_tree *parent_tree, tvbuff_t *tvb, guint offset, guint len,
5951 const char *name, const char *fallback,
5952 gint ett, const int **fields, gboolean little_endian, int flags)
5954 proto_item *item = NULL;
5957 item = proto_tree_add_text(parent_tree, tvb, offset, len, "%s", name ? name : "");
5958 if (proto_item_add_bitmask_tree(item, tvb, offset, len, ett, fields, little_endian,
5959 flags, TRUE) && fallback) {
5960 /* Still at first item - append 'fallback' text if any */
5961 proto_item_append_text(item, "%s", fallback);
5969 proto_tree_add_bits_item(proto_tree *tree, int hf_index, tvbuff_t *tvb, gint bit_offset, gint no_of_bits, gboolean little_endian)
5971 return proto_tree_add_bits_ret_val(tree, hf_index, tvb, bit_offset, no_of_bits, NULL, little_endian);
5975 * This function will dissect a sequence of bits that does not need to be byte aligned; the bits
5976 * set vill be shown in the tree as ..10 10.. and the integer value returned if return_value is set.
5977 * Offset should be given in bits from the start of the tvb.
5981 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)
5983 const char *format = NULL;
5987 guint8 remaining_bits;
5988 guint64 mask = 0,tmp;
5990 header_field_info *hf_field;
5995 hf_field = proto_registrar_get_nth(hf_index);
5997 if(hf_field -> bitmask != 0) {
5998 REPORT_DISSECTOR_BUG(ep_strdup_printf("Incompatible use of proto_tree_add_bits_ret_val with field '%s' (%s) with bitmask != 0",
5999 hf_field->abbrev, hf_field->name));
6002 DISSECTOR_ASSERT(bit_offset >= 0);
6003 DISSECTOR_ASSERT(no_of_bits > 0);
6005 /* Byte align offset */
6006 offset = bit_offset>>3;
6009 * Calculate the number of octets used to hold the bits
6011 tot_no_bits = ((bit_offset&0x7)+no_of_bits);
6012 length = tot_no_bits>>3;
6013 remaining_bits = tot_no_bits % 8;
6014 if ((remaining_bits)!=0)
6017 if (no_of_bits < 9){
6018 value = tvb_get_bits8(tvb, bit_offset, no_of_bits);
6019 }else if(no_of_bits < 17){
6020 value = tvb_get_bits16(tvb, bit_offset, no_of_bits, little_endian);
6021 }else if(no_of_bits < 33){
6022 value = tvb_get_bits32(tvb, bit_offset, no_of_bits, little_endian);
6023 }else if(no_of_bits < 65){
6024 value = tvb_get_bits64(tvb, bit_offset, no_of_bits, little_endian);
6026 DISSECTOR_ASSERT_NOT_REACHED();
6031 *return_value=value;
6035 mask = mask << (no_of_bits-1);
6037 /* prepare the string */
6040 for(bit=0;bit<((int)(bit_offset&0x07));bit++){
6041 if(bit&&(!(bit%4))){
6047 /* read the bits for the int */
6048 for(i=0;i<no_of_bits;i++){
6049 if(bit&&(!(bit%4))){
6052 if(bit&&(!(bit%8))){
6066 if(bit&&(!(bit%4))){
6073 strcat(str,hf_field->name);
6075 switch(hf_field->type){
6078 if (hf_field->strings) {
6079 const true_false_string *tfstring =
6080 (const true_false_string *) hf_field->strings;
6081 return proto_tree_add_boolean_format(tree, hf_index, tvb, offset, length, (guint32)value,
6084 (guint32)value ? tfstring->true_string : tfstring->false_string);
6086 return proto_tree_add_boolean_format(tree, hf_index, tvb, offset, length, (guint32)value,
6097 /* 1 - 32 bits field */
6098 if (hf_field->strings) {
6099 return proto_tree_add_uint_format(tree, hf_index, tvb, offset, length, (guint32)value,
6101 str, (hf_field->display & BASE_RANGE_STRING) ?
6102 rval_to_str((guint32)value, hf_field->strings, "Unknown ") :
6103 val_to_str((guint32)value, cVALS(hf_field->strings), "Unknown "),
6107 /* Pick the proper format string */
6108 format = hfinfo_uint_format(hf_field);
6109 if (IS_BASE_DUAL(hf_field->display)) {
6110 return proto_tree_add_uint_format(tree, hf_index, tvb, offset, length, (guint32)value,
6111 format, str, (guint32)value, (guint32)value);
6113 return proto_tree_add_uint_format(tree, hf_index, tvb, offset, length, (guint32)value,
6114 format, str, (guint32)value);
6119 /* Pick the proper format string */
6120 format = hfinfo_uint64_format(hf_field);
6121 if (IS_BASE_DUAL(hf_field->display)) {
6122 return proto_tree_add_uint64_format(tree, hf_index, tvb, offset, length, value,
6123 format, str, value, value);
6125 return proto_tree_add_uint64_format(tree, hf_index, tvb, offset, length, value,
6126 format, str, value);
6131 DISSECTOR_ASSERT_NOT_REACHED();
6138 proto_check_field_name(const gchar *field_name)
6140 return wrs_check_charset(fld_abbrev_chars, field_name);