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 \
102 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo); \
103 if(!(PTREE_DATA(tree)->visible)){ \
104 if(PTREE_FINFO(tree)){ \
105 if((hfinfo->ref_count == HF_REF_TYPE_NONE) \
106 && (hfinfo->type!=FT_PROTOCOL || \
107 PTREE_DATA(tree)->fake_protocols)){ \
108 /* just return tree back to the caller */\
115 proto_tree_free_node(proto_node *node, gpointer data);
117 static void fill_label_boolean(field_info *fi, gchar *label_str);
118 static void fill_label_uint(field_info *fi, gchar *label_str);
119 static void fill_label_uint64(field_info *fi, gchar *label_str);
120 static void fill_label_bitfield(field_info *fi, gchar *label_str);
121 static void fill_label_int(field_info *fi, gchar *label_str);
122 static void fill_label_int64(field_info *fi, gchar *label_str);
124 int hfinfo_bitwidth(header_field_info *hfinfo);
125 static const char* hfinfo_uint_vals_format(header_field_info *hfinfo);
126 static const char* hfinfo_uint_format(header_field_info *hfinfo);
127 static const char* hfinfo_uint_value_format(header_field_info *hfinfo);
128 static const char* hfinfo_uint64_format(header_field_info *hfinfo);
129 static const char* hfinfo_int_vals_format(header_field_info *hfinfo);
130 static const char* hfinfo_int_format(header_field_info *hfinfo);
131 static const char* hfinfo_int_value_format(header_field_info *hfinfo);
132 static const char* hfinfo_int64_format(header_field_info *hfinfo);
135 proto_tree_add_node(proto_tree *tree, field_info *fi);
137 static header_field_info *
138 get_hfi_and_length(int hfindex, tvbuff_t *tvb, gint start, gint *length,
142 new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
143 gint start, gint item_length);
146 alloc_field_info(proto_tree *tree, int hfindex, tvbuff_t *tvb,
147 gint start, gint *length);
150 proto_tree_add_pi(proto_tree *tree, int hfindex, tvbuff_t *tvb,
151 gint start, gint *length, field_info **pfi);
154 proto_tree_set_representation_value(proto_item *pi, const char *format, va_list ap);
156 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap);
159 proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb);
161 proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length);
163 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length);
165 proto_tree_set_time(field_info *fi, nstime_t *value_ptr);
167 proto_tree_set_string(field_info *fi, const char* value);
169 proto_tree_set_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
171 proto_tree_set_ebcdic_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
173 proto_tree_set_ether(field_info *fi, const guint8* value);
175 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start);
177 proto_tree_set_ipxnet(field_info *fi, guint32 value);
179 proto_tree_set_ipv4(field_info *fi, guint32 value);
181 proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr);
183 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start);
185 proto_tree_set_guid(field_info *fi, const e_guid_t *value_ptr);
187 proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gboolean little_endian);
189 proto_tree_set_oid(field_info *fi, const guint8* value_ptr, gint length);
191 proto_tree_set_oid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
193 proto_tree_set_boolean(field_info *fi, guint32 value);
195 proto_tree_set_float(field_info *fi, float value);
197 proto_tree_set_double(field_info *fi, double value);
199 proto_tree_set_uint(field_info *fi, guint32 value);
201 proto_tree_set_int(field_info *fi, gint32 value);
203 proto_tree_set_uint64(field_info *fi, guint64 value);
205 proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start, guint length, gboolean little_endian);
207 proto_item_add_bitmask_tree(proto_item *item, tvbuff_t *tvb, int offset, int len, gint ett,
208 const gint **fields, gboolean little_endian, int flags, gboolean first);
210 static int proto_register_field_init(header_field_info *hfinfo, int parent);
212 /* special-case header field used within proto.c */
213 int hf_text_only = -1;
215 /* Structure for information about a protocol */
217 const char *name; /* long description */
218 const char *short_name; /* short description */
219 const char *filter_name; /* name of this protocol in filters */
220 int proto_id; /* field ID for this protocol */
221 GList *fields; /* fields for this protocol */
222 GList *last_field; /* pointer to end of list of fields */
223 gboolean is_enabled; /* TRUE if protocol is enabled */
224 gboolean can_toggle; /* TRUE if is_enabled can be changed */
225 gboolean is_private; /* TRUE is protocol is private */
228 /* List of all protocols */
229 static GList *protocols = NULL;
231 #define INITIAL_NUM_PROTOCOL_HFINFO 200
234 /* Contains information about protocols and header fields. Used when
235 * dissectors register their data */
236 static GMemChunk *gmc_hfinfo = NULL;
238 /* Contains information about a field when a dissector calls
239 * proto_tree_add_item. */
240 SLAB_ITEM_TYPE_DEFINE(field_info)
241 static SLAB_FREE_LIST_DEFINE(field_info)
242 static field_info *field_info_tmp=NULL;
243 #define FIELD_INFO_NEW(fi) \
244 SLAB_ALLOC(fi, field_info)
245 #define FIELD_INFO_FREE(fi) \
246 SLAB_FREE(fi, field_info)
250 /* Contains the space for proto_nodes. */
251 SLAB_ITEM_TYPE_DEFINE(proto_node)
252 static SLAB_FREE_LIST_DEFINE(proto_node)
253 #define PROTO_NODE_NEW(node) \
254 SLAB_ALLOC(node, proto_node) \
255 node->first_child = NULL; \
256 node->last_child = NULL; \
259 #define PROTO_NODE_FREE(node) \
260 SLAB_FREE(node, proto_node)
264 /* String space for protocol and field items for the GUI */
265 SLAB_ITEM_TYPE_DEFINE(item_label_t)
266 static SLAB_FREE_LIST_DEFINE(item_label_t)
267 #define ITEM_LABEL_NEW(il) \
268 SLAB_ALLOC(il, item_label_t)
269 #define ITEM_LABEL_FREE(il) \
270 SLAB_FREE(il, item_label_t)
273 #define PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo) \
274 DISSECTOR_ASSERT((guint)hfindex < gpa_hfinfo.len); \
275 hfinfo=gpa_hfinfo.hfi[hfindex];
278 /* List which stores protocols and fields that have been registered */
279 typedef struct _gpa_hfinfo_t {
281 guint32 allocated_len;
282 header_field_info **hfi;
284 gpa_hfinfo_t gpa_hfinfo;
286 /* Balanced tree of abbreviations and IDs */
287 static GTree *gpa_name_tree = NULL;
288 static header_field_info *same_name_hfinfo;
290 static void save_same_name_hfinfo(gpointer data)
292 same_name_hfinfo = (header_field_info*)data;
295 /* Points to the first element of an array of Booleans, indexed by
296 a subtree item type; that array element is TRUE if subtrees of
297 an item of that type are to be expanded. */
298 gboolean *tree_is_expanded;
300 /* Number of elements in that array. */
303 /* Name hashtables for fast detection of duplicate names */
304 static GHashTable* proto_names = NULL;
305 static GHashTable* proto_short_names = NULL;
306 static GHashTable* proto_filter_names = NULL;
309 proto_compare_name(gconstpointer p1_arg, gconstpointer p2_arg)
311 const protocol_t *p1 = p1_arg;
312 const protocol_t *p2 = p2_arg;
314 return g_ascii_strcasecmp(p1->short_name, p2->short_name);
318 /* initialize data structures and register protocols and fields */
320 proto_init(void (register_all_protocols_func)(register_cb cb, gpointer client_data),
321 void (register_all_handoffs_func)(register_cb cb, gpointer client_data),
323 gpointer client_data)
325 static hf_register_info hf[] = {
327 { "Text item", "text", FT_NONE, BASE_NONE, NULL, 0x0,
332 proto_names = g_hash_table_new(g_int_hash, g_int_equal);
333 proto_short_names = g_hash_table_new(wrs_str_hash, g_str_equal);
334 proto_filter_names = g_hash_table_new(wrs_str_hash, g_str_equal);
338 gmc_hfinfo = g_mem_chunk_new("gmc_hfinfo",
339 sizeof(header_field_info),
340 INITIAL_NUM_PROTOCOL_HFINFO * sizeof(header_field_info),
344 gpa_hfinfo.allocated_len=0;
346 gpa_name_tree = g_tree_new_full(wrs_strcmp_with_data, NULL, NULL, save_same_name_hfinfo);
348 /* Initialize the ftype subsystem */
351 /* Register one special-case FT_TEXT_ONLY field for use when
352 converting wireshark to new-style proto_tree. These fields
353 are merely strings on the GUI tree; they are not filterable */
354 proto_register_field_array(-1, hf, array_length(hf));
356 /* Have each built-in dissector register its protocols, fields,
357 dissector tables, and dissectors to be called through a
358 handle, and do whatever one-time initialization it needs to
360 register_all_protocols_func(cb, client_data);
362 /* Now scan for python protocols */
363 register_all_py_protocols_func(cb, client_data);
367 /* Now scan for plugins and load all the ones we find, calling
368 their register routines to do the stuff described above. */
370 (*cb)(RA_PLUGIN_REGISTER, NULL, client_data);
372 register_all_plugin_registrations();
375 /* Now call the "handoff registration" routines of all built-in
376 dissectors; those routines register the dissector in other
377 dissectors' handoff tables, and fetch any dissector handles
379 register_all_handoffs_func(cb, client_data);
382 /* Now do the same with python dissectors */
383 register_all_py_handoffs_func(cb, client_data);
387 /* Now do the same with plugins. */
389 (*cb)(RA_PLUGIN_HANDOFF, NULL, client_data);
390 register_all_plugin_handoffs();
393 /* sort the protocols by protocol name */
394 protocols = g_list_sort(protocols, proto_compare_name);
396 /* We've assigned all the subtree type values; allocate the array
397 for them, and zero it out. */
398 tree_is_expanded = g_malloc(num_tree_types*sizeof (gboolean));
399 memset(tree_is_expanded, 0, num_tree_types*sizeof (gboolean));
405 /* Free the abbrev/ID GTree */
407 g_tree_destroy(gpa_name_tree);
408 gpa_name_tree = NULL;
412 g_mem_chunk_destroy(gmc_hfinfo);
414 if(gpa_hfinfo.allocated_len){
416 gpa_hfinfo.allocated_len=0;
417 g_free(gpa_hfinfo.hfi);
420 g_free(tree_is_expanded);
425 proto_tree_traverse_pre_order(proto_tree *tree, proto_tree_traverse_func func,
428 proto_node *pnode = tree;
432 if (func(pnode, data))
435 child = pnode->first_child;
436 while (child != NULL) {
438 * The routine we call might modify the child, e.g. by
439 * freeing it, so we get the child's successor before
440 * calling that routine.
443 child = current->next;
444 if (proto_tree_traverse_pre_order((proto_tree *)current, func,
453 proto_tree_traverse_post_order(proto_tree *tree, proto_tree_traverse_func func,
456 proto_node *pnode = tree;
460 child = pnode->first_child;
461 while (child != NULL) {
463 * The routine we call might modify the child, e.g. by
464 * freeing it, so we get the child's successor before
465 * calling that routine.
468 child = current->next;
469 if (proto_tree_traverse_post_order((proto_tree *)current, func,
473 if (func(pnode, data))
480 proto_tree_children_foreach(proto_tree *tree, proto_tree_foreach_func func,
483 proto_node *node = tree;
486 node = node->first_child;
487 while (node != NULL) {
489 node = current->next;
490 func((proto_tree *)current, data);
494 /* frees the resources that the dissection a proto_tree uses */
496 proto_tree_free(proto_tree *tree)
498 proto_tree_traverse_post_order(tree, proto_tree_free_node, NULL);
502 free_GPtrArray_value(gpointer key, gpointer value, gpointer user_data _U_)
504 GPtrArray *ptrs = value;
505 gint hfid = (gint)(long)key;
506 header_field_info *hfinfo;
508 PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
509 if(hfinfo->ref_count != HF_REF_TYPE_NONE) {
510 /* when a field is referenced by a filter this also
511 affects the refcount for the parent protocol so we need
512 to adjust the refcount for the parent as well
514 if( hfinfo->parent != -1 ) {
515 header_field_info *parent_hfinfo;
516 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
517 parent_hfinfo->ref_count = HF_REF_TYPE_NONE;
519 hfinfo->ref_count = HF_REF_TYPE_NONE;
522 g_ptr_array_free(ptrs, TRUE);
526 free_node_tree_data(tree_data_t *tree_data)
528 if (tree_data->interesting_hfids) {
529 /* Free all the GPtrArray's in the interesting_hfids hash. */
530 g_hash_table_foreach(tree_data->interesting_hfids,
531 free_GPtrArray_value, NULL);
533 /* And then destroy the hash. */
534 g_hash_table_destroy(tree_data->interesting_hfids);
537 /* And finally the tree_data_t itself. */
541 #define FREE_NODE_FIELD_INFO(finfo) \
543 ITEM_LABEL_FREE(finfo->rep); \
545 FVALUE_CLEANUP(&finfo->value); \
546 FIELD_INFO_FREE(finfo);
549 proto_tree_free_node(proto_node *node, gpointer data _U_)
551 field_info *finfo = PNODE_FINFO(node);
553 proto_node *parent = node->parent;
557 /* This is the root node. Destroy the per-tree data.
558 * There is no field_info to destroy. */
559 if (PTREE_DATA(node)) free_node_tree_data(PTREE_DATA(node));
562 /* This is a child node. Don't free the per-tree data, but
563 * do free the field_info data. */
564 FREE_NODE_FIELD_INFO(finfo);
568 /* NOTE: This code is required when this function is used to free individual
569 * nodes only. Current use is for the destruction of complete trees, so the
570 * inconsistancies have no ill effect.
572 /* Remove node from parent */
574 proto_item *prev_item = NULL;
575 if (parent->first_child == node) {
576 parent->first_child = node->next;
578 /* find previous and change its next */
579 for (prev_item = parent->first_child; prev_item; prev_item = prev_item->next) {
580 if (prev_item->next == node) {
584 DISSECTOR_ASSERT(prev_item);
585 prev_item->next = node->next;
587 /* fix last_child if required */
588 if (parent->last_child == node) {
589 parent->last_child = prev_item;
592 DISSECTOR_ASSERT(node->first_child == NULL && node->last_child == NULL);
594 /* Free the proto_node. */
595 PROTO_NODE_FREE(node);
597 return FALSE; /* FALSE = do not end traversal of protocol tree */
600 /* Is the parsing being done for a visible proto_tree or an invisible one?
601 * By setting this correctly, the proto_tree creation is sped up by not
602 * having to call g_vsnprintf and copy strings around.
605 proto_tree_set_visible(proto_tree *tree, gboolean visible)
607 PTREE_DATA(tree)->visible = visible;
611 proto_tree_set_fake_protocols(proto_tree *tree, gboolean fake_protocols)
613 PTREE_DATA(tree)->fake_protocols = fake_protocols;
616 /* Assume dissector set only its protocol fields.
617 This function is called by dissectors and allowes to speed up filtering
618 in wireshark, if this function returns FALSE it is safe to reset tree to NULL
619 and thus skip calling most of the expensive proto_tree_add_...()
621 If the tree is visible we implicitely assume the field is referenced.
624 proto_field_is_referenced(proto_tree *tree, int proto_id)
626 register header_field_info *hfinfo;
632 if (PTREE_DATA(tree)->visible)
635 PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
636 if (hfinfo->ref_count != HF_REF_TYPE_NONE)
639 if (hfinfo->type == FT_PROTOCOL && !PTREE_DATA(tree)->fake_protocols)
646 /* Finds a record in the hf_info_records array by id. */
648 proto_registrar_get_nth(guint hfindex)
650 register header_field_info *hfinfo;
652 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
657 /* Prefix initialization
658 * this allows for a dissector to register a display filter name prefix
659 * so that it can delay the initialization of the hf array as long as
663 /* compute a hash for the part before the dot of a display filter */
665 prefix_hash (gconstpointer key) {
666 /* end the string at the dot and compute its hash */
667 gchar* copy = ep_strdup(key);
677 return g_str_hash(copy);
680 /* are both strings equal up to the end or the dot? */
682 prefix_equal (gconstpointer ap,gconstpointer bp) {
690 if ((ac == '.' || ac == '\0') && (bc == '.' || bc == '\0')) return TRUE;
692 if ( (ac == '.' || ac == '\0') && ! (bc == '.' || bc == '\0') ) return FALSE;
693 if ( (bc == '.' || bc == '\0') && ! (ac == '.' || ac == '\0') ) return FALSE;
695 if (ac != bc) return FALSE;
702 /* indexed by prefix, contains initializers */
703 static GHashTable* prefixes = NULL;
706 /* Register a new prefix for "delayed" initialization of field arrays */
708 proto_register_prefix(const char *prefix, prefix_initializer_t pi ) {
710 prefixes = g_hash_table_new(prefix_hash,prefix_equal);
713 g_hash_table_insert(prefixes,(gpointer)prefix,pi);
716 /* helper to call all prefix initializers */
718 initialize_prefix(gpointer k, gpointer v, gpointer u _U_) {
719 ((prefix_initializer_t)v)(k);
723 /** Initialize every remaining uninitialized prefix. */
725 proto_initialize_all_prefixes(void) {
726 g_hash_table_foreach_remove(prefixes, initialize_prefix, NULL);
729 /* Finds a record in the hf_info_records array by name.
730 * If it fails to find it in the already registered fields,
731 * it tries to find and call an initializer in the prefixes
732 * table and if so it looks again.
735 proto_registrar_get_byname(const char *field_name)
737 header_field_info* hfinfo;
738 prefix_initializer_t pi;
743 hfinfo = g_tree_lookup(gpa_name_tree, field_name);
745 if (hfinfo) return hfinfo;
747 if (!prefixes) return NULL;
749 if(( pi = g_hash_table_lookup(prefixes,field_name) )) {
751 g_hash_table_remove(prefixes,field_name);
756 return g_tree_lookup(gpa_name_tree, field_name);
761 ptvcursor_new_subtree_levels(ptvcursor_t * ptvc)
763 subtree_lvl * pushed_tree;
765 DISSECTOR_ASSERT(ptvc->pushed_tree_max <= SUBTREE_MAX_LEVELS-SUBTREE_ONCE_ALLOCATION_NUMBER);
766 ptvc->pushed_tree_max += SUBTREE_ONCE_ALLOCATION_NUMBER;
768 pushed_tree = ep_alloc(sizeof(subtree_lvl) * ptvc->pushed_tree_max);
769 DISSECTOR_ASSERT(pushed_tree != NULL);
770 if (ptvc->pushed_tree)
771 memcpy(pushed_tree, ptvc->pushed_tree, ptvc->pushed_tree_max - SUBTREE_ONCE_ALLOCATION_NUMBER);
772 ptvc->pushed_tree = pushed_tree;
776 ptvcursor_free_subtree_levels(ptvcursor_t * ptvc)
778 ptvc->pushed_tree = NULL;
779 ptvc->pushed_tree_max = 0;
780 DISSECTOR_ASSERT(ptvc->pushed_tree_index ==0);
781 ptvc->pushed_tree_index = 0;
784 /* Allocates an initializes a ptvcursor_t with 3 variables:
785 * proto_tree, tvbuff, and offset. */
787 ptvcursor_new(proto_tree *tree, tvbuff_t *tvb, gint offset)
791 ptvc = ep_alloc(sizeof(ptvcursor_t));
794 ptvc->offset = offset;
795 ptvc->pushed_tree= NULL;
796 ptvc->pushed_tree_max= 0;
797 ptvc->pushed_tree_index= 0;
802 /* Frees memory for ptvcursor_t, but nothing deeper than that. */
804 ptvcursor_free(ptvcursor_t *ptvc)
806 ptvcursor_free_subtree_levels(ptvc);
810 /* Returns tvbuff. */
812 ptvcursor_tvbuff(ptvcursor_t* ptvc)
817 /* Returns current offset. */
819 ptvcursor_current_offset(ptvcursor_t* ptvc)
825 ptvcursor_tree(ptvcursor_t* ptvc)
834 ptvcursor_set_tree(ptvcursor_t* ptvc, proto_tree *tree)
839 /* creates a subtree, sets it as the working tree and pushes the old working tree */
841 ptvcursor_push_subtree(ptvcursor_t *ptvc, proto_item *it, gint ett_subtree)
843 subtree_lvl * subtree;
844 if (ptvc->pushed_tree_index >= ptvc->pushed_tree_max)
845 ptvcursor_new_subtree_levels(ptvc);
847 subtree = ptvc->pushed_tree+ptvc->pushed_tree_index;
848 subtree->tree = ptvc->tree;
850 ptvc->pushed_tree_index++;
851 return ptvcursor_set_subtree(ptvc, it, ett_subtree);
856 ptvcursor_pop_subtree(ptvcursor_t *ptvc)
858 subtree_lvl * subtree;
859 if (ptvc->pushed_tree_index <= 0)
862 ptvc->pushed_tree_index--;
863 subtree = ptvc->pushed_tree+ptvc->pushed_tree_index;
864 if (subtree->it != NULL)
865 proto_item_set_len(subtree->it, ptvcursor_current_offset(ptvc) - subtree->cursor_offset);
867 ptvc->tree = subtree->tree;
870 /* saves the current tvb offset and the item in the current subtree level */
872 ptvcursor_subtree_set_item(ptvcursor_t * ptvc, proto_item * it)
874 subtree_lvl * subtree;
876 DISSECTOR_ASSERT(ptvc->pushed_tree_index > 0);
878 subtree = ptvc->pushed_tree+ptvc->pushed_tree_index-1;
880 subtree->cursor_offset = ptvcursor_current_offset(ptvc);
883 /* Creates a subtree and adds it to the cursor as the working tree but does not
884 * save the old working tree */
886 ptvcursor_set_subtree(ptvcursor_t *ptvc, proto_item *it, gint ett_subtree)
888 ptvc->tree = proto_item_add_subtree(it, ett_subtree);
893 ptvcursor_add_subtree_item(ptvcursor_t * ptvc, proto_item * it, gint ett_subtree, gint length)
895 ptvcursor_push_subtree(ptvc, it, ett_subtree);
896 if (length == SUBTREE_UNDEFINED_LENGTH)
897 ptvcursor_subtree_set_item(ptvc, it);
898 return ptvcursor_tree(ptvc);
901 /* Add an item to the tree and create a subtree
902 * If the length is unknown, length may be defined as SUBTREE_UNDEFINED_LENGTH.
903 * In this case, when the subtree will be closed, the parent item length will
904 * be equal to the advancement of the cursor since the creation of the subtree.
907 ptvcursor_add_with_subtree(ptvcursor_t * ptvc, int hfindex, gint length,
908 gboolean little_endian, gint ett_subtree)
912 it = ptvcursor_add_no_advance(ptvc, hfindex, length, little_endian);
913 return ptvcursor_add_subtree_item(ptvc, it, ett_subtree, length);
917 proto_tree_add_text_node(proto_tree *tree, tvbuff_t *tvb, gint start, gint length);
919 /* Add a text node to the tree and create a subtree
920 * If the length is unknown, length may be defined as SUBTREE_UNDEFINED_LENGTH.
921 * In this case, when the subtree will be closed, the item length will be equal
922 * to the advancement of the cursor since the creation of the subtree.
925 ptvcursor_add_text_with_subtree(ptvcursor_t * ptvc, gint length,
926 gint ett_subtree, const char *format, ...)
931 it = proto_tree_add_text_node(ptvcursor_tree(ptvc), ptvcursor_tvbuff(ptvc),
932 ptvcursor_current_offset(ptvc), length);
937 va_start(ap, format);
938 proto_tree_set_representation(it, format, ap);
941 return ptvcursor_add_subtree_item(ptvc, it, ett_subtree, length);
944 /* Add a text-only node, leaving it to our caller to fill the text in */
946 proto_tree_add_text_node(proto_tree *tree, tvbuff_t *tvb, gint start, gint length)
949 header_field_info *hfinfo;
954 TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
956 pi = proto_tree_add_pi(tree, hf_text_only, tvb, start, &length, NULL);
963 /* Add a text-only node to the proto_tree */
965 proto_tree_add_text(proto_tree *tree, tvbuff_t *tvb, gint start, gint length,
966 const char *format, ...)
971 pi = proto_tree_add_text_node(tree, tvb, start, length);
975 va_start(ap, format);
976 proto_tree_set_representation(pi, format, ap);
982 /* Add a text-only node to the proto_tree (va_list version) */
984 proto_tree_add_text_valist(proto_tree *tree, tvbuff_t *tvb, gint start,
985 gint length, const char *format, va_list ap)
989 pi = proto_tree_add_text_node(tree, tvb, start, length);
993 proto_tree_set_representation(pi, format, ap);
998 /* Add a text-only node for debugging purposes. The caller doesn't need
999 * to worry about tvbuff, start, or length. Debug message gets sent to
1002 proto_tree_add_debug_text(proto_tree *tree, const char *format, ...)
1007 pi = proto_tree_add_text_node(tree, NULL, 0, 0);
1009 va_start(ap, format);
1011 proto_tree_set_representation(pi, format, ap);
1012 vprintf(format, ap);
1021 get_uint_value(tvbuff_t *tvb, gint offset, gint length, gboolean little_endian)
1028 value = tvb_get_guint8(tvb, offset);
1032 value = little_endian ? tvb_get_letohs(tvb, offset)
1033 : tvb_get_ntohs(tvb, offset);
1037 value = little_endian ? tvb_get_letoh24(tvb, offset)
1038 : tvb_get_ntoh24(tvb, offset);
1042 value = little_endian ? tvb_get_letohl(tvb, offset)
1043 : tvb_get_ntohl(tvb, offset);
1047 DISSECTOR_ASSERT_NOT_REACHED();
1055 get_int_value(tvbuff_t *tvb, gint offset, gint length, gboolean little_endian)
1062 value = (gint8)tvb_get_guint8(tvb, offset);
1066 value = (gint16) (little_endian ? tvb_get_letohs(tvb, offset)
1067 : tvb_get_ntohs(tvb, offset));
1071 value = little_endian ? tvb_get_letoh24(tvb, offset)
1072 : tvb_get_ntoh24(tvb, offset);
1073 if (value & 0x00800000) {
1074 /* Sign bit is set; sign-extend it. */
1075 value |= 0xFF000000;
1080 value = little_endian ? tvb_get_letohl(tvb, offset)
1081 : tvb_get_ntohl(tvb, offset);
1085 DISSECTOR_ASSERT_NOT_REACHED();
1092 static GPtrArray *proto_lookup_or_create_interesting_hfids(proto_tree *tree,
1093 header_field_info *hfinfo)
1095 GPtrArray *ptrs = NULL;
1097 DISSECTOR_ASSERT(tree);
1098 DISSECTOR_ASSERT(hfinfo);
1100 if (hfinfo->ref_count == HF_REF_TYPE_DIRECT) {
1101 if (PTREE_DATA(tree)->interesting_hfids == NULL) {
1102 /* Initialize the hash because we now know that it is needed */
1103 PTREE_DATA(tree)->interesting_hfids =
1104 g_hash_table_new(g_direct_hash, NULL /* g_direct_equal */);
1107 ptrs = g_hash_table_lookup(PTREE_DATA(tree)->interesting_hfids,
1108 GINT_TO_POINTER(hfinfo->id));
1110 /* First element triggers the creation of pointer array */
1111 ptrs = g_ptr_array_new();
1112 g_hash_table_insert(PTREE_DATA(tree)->interesting_hfids,
1113 GINT_TO_POINTER(hfinfo->id), ptrs);
1120 /* Add an item to a proto_tree, using the text label registered to that item;
1121 the item is extracted from the tvbuff handed to it. */
1123 proto_tree_new_item(field_info *new_fi, proto_tree *tree,
1124 tvbuff_t *tvb, gint start, gint length, gboolean little_endian)
1133 /* there is a possibility here that we might raise an exception
1134 * and thus would lose track of the field_info.
1135 * store it in a temp so that if we come here again we can reclaim
1136 * the field_info without leaking memory.
1138 /* XXX this only keeps track of one field_info struct,
1139 if we ever go multithreaded for calls to this function
1140 we have to change this code to use per thread variable.
1143 /* oops, last one we got must have been lost due
1145 * good thing we saved it, now we can reverse the
1146 * memory leak and reclaim it.
1148 SLAB_FREE(field_info_tmp, field_info);
1150 /* we might throw an exception, keep track of this one
1151 * across the "dangerous" section below.
1153 field_info_tmp=new_fi;
1155 switch(new_fi->hfinfo->type) {
1157 /* no value to set for FT_NONE */
1161 proto_tree_set_protocol_tvb(new_fi, tvb);
1165 proto_tree_set_bytes_tvb(new_fi, tvb, start, length);
1169 n = get_uint_value(tvb, start, length, little_endian);
1170 proto_tree_set_bytes_tvb(new_fi, tvb, start + length, n);
1172 /* Instead of calling proto_item_set_len(), since we don't yet
1173 * have a proto_item, we set the field_info's length ourselves. */
1174 new_fi->length = n + length;
1178 proto_tree_set_boolean(new_fi,
1179 get_uint_value(tvb, start, length, little_endian));
1182 /* XXX - make these just FT_UINT? */
1187 proto_tree_set_uint(new_fi,
1188 get_uint_value(tvb, start, length, little_endian));
1193 DISSECTOR_ASSERT( length <= 8 && length >= 1);
1194 proto_tree_set_uint64_tvb(new_fi, tvb, start, length, little_endian);
1197 /* XXX - make these just FT_INT? */
1202 proto_tree_set_int(new_fi,
1203 get_int_value(tvb, start, length, little_endian));
1207 DISSECTOR_ASSERT(length == 4);
1208 value = tvb_get_ipv4(tvb, start);
1209 proto_tree_set_ipv4(new_fi, little_endian ? GUINT32_SWAP_LE_BE(value) : value);
1213 DISSECTOR_ASSERT(length == 4);
1214 proto_tree_set_ipxnet(new_fi,
1215 get_uint_value(tvb, start, 4, FALSE));
1219 DISSECTOR_ASSERT(length == 16);
1220 proto_tree_set_ipv6_tvb(new_fi, tvb, start);
1224 DISSECTOR_ASSERT(length == 6);
1225 proto_tree_set_ether_tvb(new_fi, tvb, start);
1229 DISSECTOR_ASSERT(length == 16);
1230 proto_tree_set_guid_tvb(new_fi, tvb, start, little_endian);
1234 proto_tree_set_oid_tvb(new_fi, tvb, start, length);
1238 DISSECTOR_ASSERT(length == 4);
1240 floatval = tvb_get_letohieee_float(tvb, start);
1242 floatval = tvb_get_ntohieee_float(tvb, start);
1243 proto_tree_set_float(new_fi, floatval);
1247 DISSECTOR_ASSERT(length == 8);
1249 doubleval = tvb_get_letohieee_double(tvb, start);
1251 doubleval = tvb_get_ntohieee_double(tvb, start);
1252 proto_tree_set_double(new_fi, doubleval);
1256 proto_tree_set_string_tvb(new_fi, tvb, start, length);
1260 DISSECTOR_ASSERT(length >= -1);
1261 /* Instead of calling proto_item_set_len(),
1262 * since we don't yet have a proto_item, we
1263 * set the field_info's length ourselves.
1265 * XXX - our caller can't use that length to
1266 * advance an offset unless they arrange that
1267 * there always be a protocol tree into which
1268 * we're putting this item.
1271 /* This can throw an exception */
1272 length = tvb_strsize(tvb, start);
1274 string = ep_alloc(length);
1276 tvb_memcpy(tvb, string, start, length);
1277 } else if (length == 0) {
1280 /* In this case, length signifies
1281 * the length of the string.
1283 * This could either be a null-padded
1284 * string, which doesn't necessarily
1285 * have a '\0' at the end, or a
1286 * null-terminated string, with a
1287 * trailing '\0'. (Yes, there are
1288 * cases where you have a string
1289 * that's both counted and null-
1292 * In the first case, we must
1293 * allocate a buffer of length
1294 * "length+1", to make room for
1297 * In the second case, we don't
1298 * assume that there is a trailing
1299 * '\0' there, as the packet might
1300 * be malformed. (XXX - should we
1301 * throw an exception if there's no
1302 * trailing '\0'?) Therefore, we
1303 * allocate a buffer of length
1304 * "length+1", and put in a trailing
1305 * '\0', just to be safe.
1307 * (XXX - this would change if
1308 * we made string values counted
1309 * rather than null-terminated.)
1311 string = tvb_get_ephemeral_string(tvb,
1315 new_fi->length = length;
1316 proto_tree_set_string(new_fi, string);
1320 proto_tree_set_ebcdic_string_tvb(new_fi, tvb, start, length);
1323 case FT_UINT_STRING:
1324 n = get_uint_value(tvb, start, length, little_endian);
1325 proto_tree_set_string_tvb(new_fi, tvb, start + length, n);
1327 /* Instead of calling proto_item_set_len(), since we
1328 * don't yet have a proto_item, we set the
1329 * field_info's length ourselves.
1331 * XXX - our caller can't use that length to
1332 * advance an offset unless they arrange that
1333 * there always be a protocol tree into which
1334 * we're putting this item.
1336 new_fi->length = n + length;
1340 g_error("new_fi->hfinfo->type %d (%s) not handled\n",
1341 new_fi->hfinfo->type,
1342 ftype_name(new_fi->hfinfo->type));
1343 DISSECTOR_ASSERT_NOT_REACHED();
1347 /* Don't add new node to proto_tree until now so that any exceptions
1348 * raised by a tvbuff access method doesn't leave junk in the proto_tree. */
1349 pi = proto_tree_add_node(tree, new_fi);
1351 /* we did not raise an exception so we dont have to remember this
1352 * field_info struct any more.
1354 field_info_tmp=NULL;
1356 /* If the proto_tree wants to keep a record of this finfo
1357 * for quick lookup, then record it. */
1358 ptrs = proto_lookup_or_create_interesting_hfids(tree, new_fi->hfinfo);
1360 g_ptr_array_add(ptrs, new_fi);
1365 /* Gets data from tvbuff, adds it to proto_tree, increments offset,
1366 and returns proto_item* */
1368 ptvcursor_add(ptvcursor_t *ptvc, int hfindex, gint length,
1369 gboolean little_endian)
1372 header_field_info *hfinfo;
1377 offset = ptvc->offset;
1378 hfinfo = get_hfi_and_length(hfindex, ptvc->tvb, offset, &length,
1380 ptvc->offset += length;
1381 if (hfinfo->type == FT_UINT_BYTES || hfinfo->type == FT_UINT_STRING) {
1383 * The length of the rest of the item is in the first N
1384 * bytes of the item.
1386 n = get_uint_value(ptvc->tvb, offset, length, little_endian);
1389 if (ptvc->tree == NULL)
1392 TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfindex, hfinfo);
1394 new_fi = new_field_info(ptvc->tree, hfinfo, ptvc->tvb, offset,
1399 return proto_tree_new_item(new_fi, ptvc->tree, ptvc->tvb,
1400 offset, length, little_endian);
1403 /* Add an item to a proto_tree, using the text label registered to that item;
1404 the item is extracted from the tvbuff handed to it. */
1406 proto_tree_add_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1407 gint start, gint length, gboolean little_endian)
1410 header_field_info *hfinfo;
1415 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1417 new_fi = alloc_field_info(tree, hfindex, tvb, start, &length);
1422 return proto_tree_new_item(new_fi, tree, tvb, start,
1423 length, little_endian);
1426 /* Add a FT_NONE to a proto_tree */
1428 proto_tree_add_none_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1429 gint length, const char *format, ...)
1433 header_field_info *hfinfo;
1438 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1440 DISSECTOR_ASSERT(hfinfo->type == FT_NONE);
1442 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, NULL);
1444 va_start(ap, format);
1445 proto_tree_set_representation(pi, format, ap);
1448 /* no value to set for FT_NONE */
1452 /* Gets data from tvbuff, adds it to proto_tree, *DOES NOT* increment
1453 * offset, and returns proto_item* */
1455 ptvcursor_add_no_advance(ptvcursor_t* ptvc, int hf, gint length,
1456 gboolean endianness)
1460 item = proto_tree_add_item(ptvc->tree, hf, ptvc->tvb, ptvc->offset,
1461 length, endianness);
1466 /* Advance the ptvcursor's offset within its tvbuff without
1467 * adding anything to the proto_tree. */
1469 ptvcursor_advance(ptvcursor_t* ptvc, gint length)
1471 ptvc->offset += length;
1476 proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb)
1478 fvalue_set(&fi->value, tvb, TRUE);
1481 /* Add a FT_PROTOCOL to a proto_tree */
1483 proto_tree_add_protocol_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1484 gint length, const char *format, ...)
1489 header_field_info *hfinfo;
1494 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1496 DISSECTOR_ASSERT(hfinfo->type == FT_PROTOCOL);
1498 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1500 va_start(ap, format);
1501 proto_tree_set_representation(pi, format, ap);
1505 proto_tree_set_protocol_tvb(new_fi, tvb);
1508 proto_tree_set_protocol_tvb(new_fi, NULL);
1514 /* Add a FT_BYTES to a proto_tree */
1516 proto_tree_add_bytes(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1517 gint length, const guint8 *start_ptr)
1521 header_field_info *hfinfo;
1526 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1528 DISSECTOR_ASSERT(hfinfo->type == FT_BYTES);
1530 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1531 proto_tree_set_bytes(new_fi, start_ptr, length);
1537 proto_tree_add_bytes_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1538 gint start, gint length, const guint8 *start_ptr,
1539 const char *format, ...)
1544 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length, start_ptr);
1548 va_start(ap, format);
1549 proto_tree_set_representation_value(pi, format, ap);
1556 proto_tree_add_bytes_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1557 gint length, const guint8 *start_ptr, const char *format, ...)
1562 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length, start_ptr);
1566 va_start(ap, format);
1567 proto_tree_set_representation(pi, format, ap);
1574 proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length)
1578 bytes = g_byte_array_new();
1580 g_byte_array_append(bytes, start_ptr, length);
1582 col_custom_set_fstr(fi->hfinfo, "%s", bytes_to_str(bytes->data,
1584 fvalue_set(&fi->value, bytes, TRUE);
1589 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length)
1591 proto_tree_set_bytes(fi, tvb_get_ptr(tvb, offset, length), length);
1594 /* Add a FT_*TIME to a proto_tree */
1596 proto_tree_add_time(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1597 nstime_t *value_ptr)
1601 header_field_info *hfinfo;
1606 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1608 DISSECTOR_ASSERT(hfinfo->type == FT_ABSOLUTE_TIME ||
1609 hfinfo->type == FT_RELATIVE_TIME);
1611 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1612 proto_tree_set_time(new_fi, value_ptr);
1618 proto_tree_add_time_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1619 gint start, gint length, nstime_t *value_ptr,
1620 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_value(pi, format, ap);
1637 proto_tree_add_time_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1638 nstime_t *value_ptr, const char *format, ...)
1643 pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
1647 va_start(ap, format);
1648 proto_tree_set_representation(pi, format, ap);
1654 /* Set the FT_*TIME value */
1656 proto_tree_set_time(field_info *fi, nstime_t *value_ptr)
1658 header_field_info *hfinfo;
1660 DISSECTOR_ASSERT(value_ptr != NULL);
1661 hfinfo = fi->hfinfo;
1663 if (hfinfo->type == FT_ABSOLUTE_TIME) {
1664 col_custom_set_fstr(fi->hfinfo, "%s", abs_time_to_str(value_ptr));
1665 } else if (hfinfo->type == FT_RELATIVE_TIME) {
1666 col_custom_set_fstr(fi->hfinfo, "%s", rel_time_to_secs_str(value_ptr));
1668 fvalue_set(&fi->value, value_ptr, FALSE);
1671 /* Add a FT_IPXNET to a proto_tree */
1673 proto_tree_add_ipxnet(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1678 header_field_info *hfinfo;
1683 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1685 DISSECTOR_ASSERT(hfinfo->type == FT_IPXNET);
1687 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1688 proto_tree_set_ipxnet(new_fi, value);
1694 proto_tree_add_ipxnet_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1695 gint start, gint length, guint32 value, const char *format, ...)
1700 pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
1704 va_start(ap, format);
1705 proto_tree_set_representation_value(pi, format, ap);
1712 proto_tree_add_ipxnet_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1713 guint32 value, const char *format, ...)
1718 pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
1722 va_start(ap, format);
1723 proto_tree_set_representation(pi, format, ap);
1729 /* Set the FT_IPXNET value */
1731 proto_tree_set_ipxnet(field_info *fi, guint32 value)
1733 fvalue_set_uinteger(&fi->value, value);
1736 /* Add a FT_IPv4 to a proto_tree */
1738 proto_tree_add_ipv4(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1743 header_field_info *hfinfo;
1748 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1750 DISSECTOR_ASSERT(hfinfo->type == FT_IPv4);
1752 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1753 proto_tree_set_ipv4(new_fi, value);
1759 proto_tree_add_ipv4_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1760 gint start, gint length, guint32 value, const char *format, ...)
1765 pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
1769 va_start(ap, format);
1770 proto_tree_set_representation_value(pi, format, ap);
1777 proto_tree_add_ipv4_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1778 guint32 value, const char *format, ...)
1783 pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
1787 va_start(ap, format);
1788 proto_tree_set_representation(pi, format, ap);
1794 /* Set the FT_IPv4 value */
1796 proto_tree_set_ipv4(field_info *fi, guint32 value)
1798 col_custom_set_fstr(fi->hfinfo, "%s",
1799 ip_to_str((guint8 *)&value));
1800 fvalue_set_uinteger(&fi->value, value);
1803 /* Add a FT_IPv6 to a proto_tree */
1805 proto_tree_add_ipv6(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1806 const guint8* value_ptr)
1810 header_field_info *hfinfo;
1815 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1817 DISSECTOR_ASSERT(hfinfo->type == FT_IPv6);
1819 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1820 proto_tree_set_ipv6(new_fi, value_ptr);
1826 proto_tree_add_ipv6_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1827 gint start, gint length, const guint8* value_ptr,
1828 const char *format, ...)
1833 pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
1837 va_start(ap, format);
1838 proto_tree_set_representation_value(pi, format, ap);
1845 proto_tree_add_ipv6_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1846 const guint8* value_ptr, const char *format, ...)
1851 pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
1855 va_start(ap, format);
1856 proto_tree_set_representation(pi, format, ap);
1862 /* Set the FT_IPv6 value */
1864 proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr)
1866 DISSECTOR_ASSERT(value_ptr != NULL);
1867 fvalue_set(&fi->value, (gpointer) value_ptr, FALSE);
1871 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start)
1873 proto_tree_set_ipv6(fi, tvb_get_ptr(tvb, start, 16));
1876 /* Add a FT_GUID to a proto_tree */
1878 proto_tree_add_guid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1879 const e_guid_t *value_ptr)
1883 header_field_info *hfinfo;
1888 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1890 DISSECTOR_ASSERT(hfinfo->type == FT_GUID);
1892 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1893 proto_tree_set_guid(new_fi, value_ptr);
1899 proto_tree_add_guid_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1900 gint start, gint length, const e_guid_t *value_ptr,
1901 const char *format, ...)
1906 pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
1910 va_start(ap, format);
1911 proto_tree_set_representation_value(pi, format, ap);
1918 proto_tree_add_guid_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1919 const e_guid_t *value_ptr, const char *format, ...)
1924 pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
1928 va_start(ap, format);
1929 proto_tree_set_representation(pi, format, ap);
1935 /* Set the FT_GUID value */
1937 proto_tree_set_guid(field_info *fi, const e_guid_t *value_ptr)
1939 DISSECTOR_ASSERT(value_ptr != NULL);
1940 col_custom_set_fstr(fi->hfinfo, "%s",
1941 guid_to_str(value_ptr));
1942 fvalue_set(&fi->value, (gpointer) value_ptr, FALSE);
1946 proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gboolean little_endian)
1950 tvb_get_guid(tvb, start, &guid, little_endian);
1951 proto_tree_set_guid(fi, &guid);
1954 /* Add a FT_OID to a proto_tree */
1956 proto_tree_add_oid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1957 const guint8* value_ptr)
1961 header_field_info *hfinfo;
1966 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1968 DISSECTOR_ASSERT(hfinfo->type == FT_OID);
1970 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1971 proto_tree_set_oid(new_fi, value_ptr, length);
1977 proto_tree_add_oid_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1978 gint start, gint length, const guint8* value_ptr,
1979 const char *format, ...)
1984 pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
1988 va_start(ap, format);
1989 proto_tree_set_representation_value(pi, format, ap);
1996 proto_tree_add_oid_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1997 const guint8* value_ptr, const char *format, ...)
2002 pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
2006 va_start(ap, format);
2007 proto_tree_set_representation(pi, format, ap);
2013 /* Set the FT_OID value */
2015 proto_tree_set_oid(field_info *fi, const guint8* value_ptr, gint length)
2019 DISSECTOR_ASSERT(value_ptr != NULL);
2021 bytes = g_byte_array_new();
2023 g_byte_array_append(bytes, value_ptr, length);
2025 col_custom_set_fstr(fi->hfinfo, "%s",
2026 oid_resolved_from_encoded(value_ptr, length));
2027 fvalue_set(&fi->value, bytes, TRUE);
2031 proto_tree_set_oid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
2033 proto_tree_set_oid(fi, tvb_get_ptr(tvb, start, length), length);
2037 proto_tree_set_uint64(field_info *fi, guint64 value)
2039 col_custom_set_fstr(fi->hfinfo, "%" G_GINT64_MODIFIER "u",
2041 fvalue_set_integer64(&fi->value, value);
2045 proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start, guint length, gboolean little_endian)
2048 guint8* b = ep_tvb_memdup(tvb,start,length);
2053 default: DISSECTOR_ASSERT_NOT_REACHED();
2054 case 8: value <<= 8; value += *--b;
2055 case 7: value <<= 8; value += *--b;
2056 case 6: value <<= 8; value += *--b;
2057 case 5: value <<= 8; value += *--b;
2058 case 4: value <<= 8; value += *--b;
2059 case 3: value <<= 8; value += *--b;
2060 case 2: value <<= 8; value += *--b;
2061 case 1: value <<= 8; value += *--b;
2066 default: DISSECTOR_ASSERT_NOT_REACHED();
2067 case 8: value <<= 8; value += *b++;
2068 case 7: value <<= 8; value += *b++;
2069 case 6: value <<= 8; value += *b++;
2070 case 5: value <<= 8; value += *b++;
2071 case 4: value <<= 8; value += *b++;
2072 case 3: value <<= 8; value += *b++;
2073 case 2: value <<= 8; value += *b++;
2074 case 1: value <<= 8; value += *b++;
2079 proto_tree_set_uint64(fi, value);
2082 /* Add a FT_STRING or FT_STRINGZ to a proto_tree. Creates own copy of string,
2083 * and frees it when the proto_tree is destroyed. */
2085 proto_tree_add_string(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2086 gint length, const char* value)
2090 header_field_info *hfinfo;
2095 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2097 DISSECTOR_ASSERT(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ);
2099 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2100 DISSECTOR_ASSERT(length >= 0);
2101 proto_tree_set_string(new_fi, value);
2107 proto_tree_add_string_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2108 gint start, gint length, const char* value, const char *format,
2114 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
2118 va_start(ap, format);
2119 proto_tree_set_representation_value(pi, format, ap);
2126 proto_tree_add_string_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2127 gint length, const char* value, const char *format, ...)
2132 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
2136 va_start(ap, format);
2137 proto_tree_set_representation(pi, format, ap);
2143 /* Appends string data to a FT_STRING or FT_STRINGZ, allowing progressive
2144 * field info update instead of only updating the representation as does
2145 * proto_item_append_text()
2147 /* NOTE: this function will break with the TRY_TO_FAKE_THIS_ITEM()
2148 * speed optimization.
2149 * Currently only WSP use this function so it is not that bad but try to
2150 * avoid using this one if possible.
2151 * IF you must use this function you MUST also disable the
2152 * TRY_TO_FAKE_THIS_ITEM() optimization for your dissector/function
2153 * using proto_item_append_string().
2154 * Do that by faking that the tree is visible by calling
2155 * proto_tree_set_visible(tree, TRUE) (see packet-wsp.c)
2156 * BEFORE you create the item you are later going to use
2157 * proto_item_append_string() on.
2160 proto_item_append_string(proto_item *pi, const char *str)
2163 header_field_info *hfinfo;
2164 gchar *old_str, *new_str;
2171 fi = PITEM_FINFO(pi);
2172 hfinfo = fi->hfinfo;
2173 if (hfinfo->type == FT_PROTOCOL) {
2174 /* TRY_TO_FAKE_THIS_ITEM() speed optimization: silently skip */
2177 DISSECTOR_ASSERT(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ);
2178 old_str = fvalue_get(&fi->value);
2179 new_str = ep_strdup_printf("%s%s", old_str, str);
2180 fvalue_set(&fi->value, new_str, FALSE);
2183 /* Set the FT_STRING value */
2185 proto_tree_set_string(field_info *fi, const char* value)
2188 col_custom_set_fstr(fi->hfinfo, "%s",
2189 format_text(value, strlen(value)));
2190 fvalue_set(&fi->value, (gpointer) value, FALSE);
2192 col_custom_set_fstr(fi->hfinfo, "[ Null ]");
2193 fvalue_set(&fi->value, (gpointer) "[ Null ]", FALSE);
2198 proto_tree_set_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
2203 length = tvb_ensure_length_remaining(tvb, start);
2206 string = tvb_get_ephemeral_string(tvb, start, length);
2207 proto_tree_set_string(fi, string);
2211 proto_tree_set_ebcdic_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
2216 length = tvb_ensure_length_remaining(tvb, start);
2219 string = tvb_get_ephemeral_string(tvb, start, length);
2220 EBCDIC_to_ASCII(string, length);
2221 proto_tree_set_string(fi, string);
2224 /* Add a FT_ETHER to a proto_tree */
2226 proto_tree_add_ether(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2227 const guint8* value)
2231 header_field_info *hfinfo;
2236 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2238 DISSECTOR_ASSERT(hfinfo->type == FT_ETHER);
2240 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2241 proto_tree_set_ether(new_fi, value);
2247 proto_tree_add_ether_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2248 gint start, gint length, const guint8* value,
2249 const char *format, ...)
2254 pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
2258 va_start(ap, format);
2259 proto_tree_set_representation_value(pi, format, ap);
2266 proto_tree_add_ether_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2267 const guint8* value, const char *format, ...)
2272 pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
2276 va_start(ap, format);
2277 proto_tree_set_representation(pi, format, ap);
2283 /* Set the FT_ETHER value */
2285 proto_tree_set_ether(field_info *fi, const guint8* value)
2287 col_custom_set_fstr(fi->hfinfo, "%s", bytes_to_str_punct(value, 6, ':'));
2288 fvalue_set(&fi->value, (gpointer) value, FALSE);
2292 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start)
2294 proto_tree_set_ether(fi, tvb_get_ptr(tvb, start, 6));
2297 /* Add a FT_BOOLEAN to a proto_tree */
2299 proto_tree_add_boolean(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2304 header_field_info *hfinfo;
2309 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2311 DISSECTOR_ASSERT(hfinfo->type == FT_BOOLEAN);
2313 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2314 proto_tree_set_boolean(new_fi, value);
2320 proto_tree_add_boolean_format_value(proto_tree *tree, int hfindex,
2321 tvbuff_t *tvb, gint start, gint length, guint32 value,
2322 const char *format, ...)
2327 pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
2331 va_start(ap, format);
2332 proto_tree_set_representation_value(pi, format, ap);
2339 proto_tree_add_boolean_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2340 guint32 value, const char *format, ...)
2345 pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
2349 va_start(ap, format);
2350 proto_tree_set_representation(pi, format, ap);
2356 /* Set the FT_BOOLEAN value */
2358 proto_tree_set_boolean(field_info *fi, guint32 value)
2360 proto_tree_set_uint(fi, value);
2363 /* Add a FT_FLOAT to a proto_tree */
2365 proto_tree_add_float(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2370 header_field_info *hfinfo;
2375 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2377 DISSECTOR_ASSERT(hfinfo->type == FT_FLOAT);
2379 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2380 proto_tree_set_float(new_fi, value);
2386 proto_tree_add_float_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2387 gint start, gint length, float value, const char *format, ...)
2392 pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
2396 va_start(ap, format);
2397 proto_tree_set_representation_value(pi, format, ap);
2404 proto_tree_add_float_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2405 float value, const char *format, ...)
2410 pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
2414 va_start(ap, format);
2415 proto_tree_set_representation(pi, format, ap);
2421 /* Set the FT_FLOAT value */
2423 proto_tree_set_float(field_info *fi, float value)
2425 col_custom_set_fstr(fi->hfinfo, "%." STRINGIFY(FLT_DIG) "f",
2427 fvalue_set_floating(&fi->value, value);
2430 /* Add a FT_DOUBLE to a proto_tree */
2432 proto_tree_add_double(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2437 header_field_info *hfinfo;
2442 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2444 DISSECTOR_ASSERT(hfinfo->type == FT_DOUBLE);
2446 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2447 proto_tree_set_double(new_fi, value);
2453 proto_tree_add_double_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2454 gint start, gint length, double value, const char *format, ...)
2459 pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
2463 va_start(ap, format);
2464 proto_tree_set_representation_value(pi, format, ap);
2471 proto_tree_add_double_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2472 double value, const char *format, ...)
2477 pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
2481 va_start(ap, format);
2482 proto_tree_set_representation(pi, format, ap);
2488 /* Set the FT_DOUBLE value */
2490 proto_tree_set_double(field_info *fi, double value)
2492 col_custom_set_fstr(fi->hfinfo, "%." STRINGIFY(DBL_DIG) "g",
2494 fvalue_set_floating(&fi->value, value);
2497 /* Add FT_UINT{8,16,24,32} to a proto_tree */
2499 proto_tree_add_uint(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2502 proto_item *pi = NULL;
2504 header_field_info *hfinfo;
2509 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2511 switch(hfinfo->type) {
2517 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length,
2519 proto_tree_set_uint(new_fi, value);
2523 DISSECTOR_ASSERT_NOT_REACHED();
2530 proto_tree_add_uint_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2531 gint start, gint length, guint32 value, const char *format, ...)
2536 pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
2540 va_start(ap, format);
2541 proto_tree_set_representation_value(pi, format, ap);
2548 proto_tree_add_uint_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2549 guint32 value, const char *format, ...)
2554 pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
2558 va_start(ap, format);
2559 proto_tree_set_representation(pi, format, ap);
2565 /* Set the FT_UINT{8,16,24,32} value */
2567 proto_tree_set_uint(field_info *fi, guint32 value)
2569 header_field_info *hfinfo;
2572 hfinfo = fi->hfinfo;
2575 if (hfinfo->bitmask) {
2576 /* Mask out irrelevant portions */
2577 integer &= hfinfo->bitmask;
2580 if (hfinfo->bitshift > 0) {
2581 integer >>= hfinfo->bitshift;
2585 if (hfinfo->type == FT_BOOLEAN) {
2586 const true_false_string *tfstring = (const true_false_string *)&tfs_true_false;
2587 if (hfinfo->strings) {
2588 tfstring = (const struct true_false_string*) hfinfo->strings;
2590 col_custom_set_fstr(fi->hfinfo, "%s", integer ? tfstring->true_string : tfstring->false_string);
2591 } else if (hfinfo->strings) {
2592 if (hfinfo->display & BASE_RANGE_STRING) {
2593 col_custom_set_fstr(fi->hfinfo, "%s", rval_to_str(integer, hfinfo->strings, "%u"));
2595 col_custom_set_fstr(fi->hfinfo, "%s", val_to_str(integer, cVALS(hfinfo->strings), "%u"));
2597 } else if (IS_BASE_DUAL(hfinfo->display)) {
2598 col_custom_set_fstr(fi->hfinfo, hfinfo_uint_value_format(hfinfo), integer, integer);
2600 col_custom_set_fstr(fi->hfinfo, hfinfo_uint_value_format(hfinfo), integer);
2602 fvalue_set_uinteger(&fi->value, integer);
2605 /* Add FT_UINT64 to a proto_tree */
2607 proto_tree_add_uint64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2610 proto_item *pi = NULL;
2612 header_field_info *hfinfo;
2617 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2619 DISSECTOR_ASSERT(hfinfo->type == FT_UINT64);
2621 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2622 proto_tree_set_uint64(new_fi, value);
2628 proto_tree_add_uint64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2629 gint start, gint length, guint64 value, const char *format, ...)
2634 pi = proto_tree_add_uint64(tree, hfindex, tvb, start, length, value);
2638 va_start(ap, format);
2639 proto_tree_set_representation_value(pi, format, ap);
2646 proto_tree_add_uint64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2647 guint64 value, const char *format, ...)
2652 pi = proto_tree_add_uint64(tree, hfindex, tvb, start, length, value);
2656 va_start(ap, format);
2657 proto_tree_set_representation(pi, format, ap);
2663 /* Add FT_INT{8,16,24,32} to a proto_tree */
2665 proto_tree_add_int(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2668 proto_item *pi = NULL;
2670 header_field_info *hfinfo;
2675 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2677 switch(hfinfo->type) {
2682 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length,
2684 proto_tree_set_int(new_fi, value);
2688 DISSECTOR_ASSERT_NOT_REACHED();
2695 proto_tree_add_int_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2696 gint start, gint length, gint32 value, const char *format, ...)
2698 proto_item *pi = NULL;
2701 pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
2705 va_start(ap, format);
2706 proto_tree_set_representation_value(pi, format, ap);
2713 proto_tree_add_int_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2714 gint32 value, const char *format, ...)
2716 proto_item *pi = NULL;
2719 pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
2723 va_start(ap, format);
2724 proto_tree_set_representation(pi, format, ap);
2730 /* Set the FT_INT{8,16,24,32} value */
2732 proto_tree_set_int(field_info *fi, gint32 value)
2734 header_field_info *hfinfo;
2737 hfinfo = fi->hfinfo;
2738 integer = (guint32) value;
2740 if (hfinfo->bitmask) {
2741 /* Mask out irrelevant portions */
2742 integer &= hfinfo->bitmask;
2745 if (hfinfo->bitshift > 0) {
2746 integer >>= hfinfo->bitshift;
2750 if (hfinfo->strings) {
2751 if (hfinfo->display & BASE_RANGE_STRING) {
2752 col_custom_set_fstr(fi->hfinfo, "%s", rval_to_str(integer, hfinfo->strings, "%d"));
2754 col_custom_set_fstr(fi->hfinfo, "%s", val_to_str(integer, cVALS(hfinfo->strings), "%d"));
2756 } else if (IS_BASE_DUAL(hfinfo->display)) {
2757 col_custom_set_fstr(fi->hfinfo, hfinfo_int_value_format(hfinfo), integer, integer);
2759 col_custom_set_fstr(fi->hfinfo, hfinfo_int_value_format(hfinfo), integer);
2761 fvalue_set_sinteger(&fi->value, integer);
2764 /* Add FT_INT64 to a proto_tree */
2766 proto_tree_add_int64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2769 proto_item *pi = NULL;
2771 header_field_info *hfinfo;
2776 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2778 DISSECTOR_ASSERT(hfinfo->type == FT_INT64);
2780 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2781 proto_tree_set_uint64(new_fi, (guint64)value);
2787 proto_tree_add_int64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2788 gint start, gint length, gint64 value, const char *format, ...)
2793 pi = proto_tree_add_int64(tree, hfindex, tvb, start, length, value);
2797 va_start(ap, format);
2798 proto_tree_set_representation_value(pi, format, ap);
2805 proto_tree_add_int64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2806 gint64 value, const char *format, ...)
2811 pi = proto_tree_add_int64(tree, hfindex, tvb, start, length, value);
2815 va_start(ap, format);
2816 proto_tree_set_representation(pi, format, ap);
2822 /* Throw an exception if we exceed this many tree items. */
2823 /* XXX - This should probably be a preference */
2824 #define MAX_TREE_ITEMS (1 * 1000 * 1000)
2825 /* Add a field_info struct to the proto_tree, encapsulating it in a proto_node */
2827 proto_tree_add_node(proto_tree *tree, field_info *fi)
2829 proto_node *pnode, *tnode, *sibling;
2833 * Make sure "tree" is ready to have subtrees under it, by
2834 * checking whether it's been given an ett_ value.
2836 * "PNODE_FINFO(tnode)" may be null; that's the case for the root
2837 * node of the protocol tree. That node is not displayed,
2838 * so it doesn't need an ett_ value to remember whether it
2842 tfi = PNODE_FINFO(tnode);
2843 if (tfi != NULL && (tfi->tree_type < 0 || tfi->tree_type >= num_tree_types)) {
2844 REPORT_DISSECTOR_BUG(ep_strdup_printf("\"%s\" - \"%s\" tfi->tree_type: %u invalid (%s:%u)",
2845 fi->hfinfo->name, fi->hfinfo->abbrev, tfi->tree_type, __FILE__, __LINE__));
2846 /* XXX - is it safe to continue here? */
2849 DISSECTOR_ASSERT(tfi == NULL ||
2850 (tfi->tree_type >= 0 && tfi->tree_type < num_tree_types));
2852 PTREE_DATA(tree)->count++;
2853 if (PTREE_DATA(tree)->count > MAX_TREE_ITEMS) {
2854 /* Let the exception handler add items to the tree */
2855 PTREE_DATA(tree)->count = 0;
2856 THROW_MESSAGE(DissectorError,
2857 ep_strdup_printf("More than %d items in the tree -- possible infinite loop", MAX_TREE_ITEMS));
2860 PROTO_NODE_NEW(pnode);
2861 pnode->parent = tnode;
2862 PNODE_FINFO(pnode) = fi;
2863 pnode->tree_data = PTREE_DATA(tree);
2865 if (tnode->last_child != NULL) {
2866 sibling = tnode->last_child;
2867 DISSECTOR_ASSERT(sibling->next == NULL);
2868 sibling->next = pnode;
2870 tnode->first_child = pnode;
2871 tnode->last_child = pnode;
2873 return (proto_item*)pnode;
2877 /* Generic way to allocate field_info and add to proto_tree.
2878 * Sets *pfi to address of newly-allocated field_info struct, if pfi is
2881 proto_tree_add_pi(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2882 gint *length, field_info **pfi)
2891 fi = alloc_field_info(tree, hfindex, tvb, start, length);
2892 pi = proto_tree_add_node(tree, fi);
2894 /* If the proto_tree wants to keep a record of this finfo
2895 * for quick lookup, then record it. */
2896 ptrs = proto_lookup_or_create_interesting_hfids(tree, fi->hfinfo);
2898 g_ptr_array_add(ptrs, fi);
2900 /* Does the caller want to know the fi pointer? */
2909 static header_field_info *
2910 get_hfi_and_length(int hfindex, tvbuff_t *tvb, gint start, gint *length,
2913 header_field_info *hfinfo;
2914 gint length_remaining;
2917 * We only allow a null tvbuff if the item has a zero length,
2918 * i.e. if there's no data backing it.
2920 DISSECTOR_ASSERT(tvb != NULL || *length == 0);
2922 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2925 * XXX - in some protocols, there are 32-bit unsigned length
2926 * fields, so lengths in protocol tree and tvbuff routines
2927 * should really be unsigned. We should have, for those
2928 * field types for which "to the end of the tvbuff" makes sense,
2929 * additional routines that take no length argument and
2930 * add fields that run to the end of the tvbuff.
2932 if (*length == -1) {
2934 * For FT_NONE, FT_PROTOCOL, FT_BYTES, and FT_STRING fields,
2935 * a length of -1 means "set the length to what remains in
2938 * The assumption is either that
2940 * 1) the length of the item can only be determined
2941 * by dissection (typically true of items with
2942 * subitems, which are probably FT_NONE or
2947 * 2) if the tvbuff is "short" (either due to a short
2948 * snapshot length or due to lack of reassembly of
2949 * fragments/segments/whatever), we want to display
2950 * what's available in the field (probably FT_BYTES
2951 * or FT_STRING) and then throw an exception later
2955 * 3) the field is defined to be "what's left in the
2958 * so we set the length to what remains in the tvbuff so
2959 * that, if we throw an exception while dissecting, it
2960 * has what is probably the right value.
2962 * For FT_STRINGZ, it means "the string is null-terminated,
2963 * not null-padded; set the length to the actual length
2964 * of the string", and if the tvbuff if short, we just
2965 * throw an exception.
2967 * It's not valid for any other type of field.
2969 switch (hfinfo->type) {
2973 * We allow this to be zero-length - for
2974 * example, an ONC RPC NULL procedure has
2975 * neither arguments nor reply, so the
2976 * payload for that protocol is empty.
2978 * However, if the length is negative, the
2979 * start offset is *past* the byte past the
2980 * end of the tvbuff, so we throw an
2983 *length = tvb_length_remaining(tvb, start);
2986 * Use "tvb_ensure_bytes_exist()"
2987 * to force the appropriate exception
2990 tvb_ensure_bytes_exist(tvb, start, 0);
2992 DISSECTOR_ASSERT(*length >= 0);
2998 *length = tvb_ensure_length_remaining(tvb, start);
2999 DISSECTOR_ASSERT(*length >= 0);
3004 * Leave the length as -1, so our caller knows
3010 DISSECTOR_ASSERT_NOT_REACHED();
3012 *item_length = *length;
3014 *item_length = *length;
3015 if (hfinfo->type == FT_PROTOCOL || hfinfo->type == FT_NONE) {
3017 * These types are for interior nodes of the
3018 * tree, and don't have data associated with
3019 * them; if the length is negative (XXX - see
3020 * above) or goes past the end of the tvbuff,
3021 * cut it short at the end of the tvbuff.
3022 * That way, if this field is selected in
3023 * Wireshark, we don't highlight stuff past
3024 * the end of the data.
3026 /* XXX - what to do, if we don't have a tvb? */
3028 length_remaining = tvb_length_remaining(tvb, start);
3029 if (*item_length < 0 ||
3030 (*item_length > 0 &&
3031 (length_remaining < *item_length)))
3032 *item_length = length_remaining;
3035 if (*item_length < 0) {
3036 THROW(ReportedBoundsError);
3044 new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
3045 gint start, gint item_length)
3051 fi->hfinfo = hfinfo;
3053 fi->start+=(tvb)?TVB_RAW_OFFSET(tvb):0;
3054 fi->length = item_length;
3057 if (!PTREE_DATA(tree)->visible)
3058 FI_SET_FLAG(fi, FI_HIDDEN);
3059 fvalue_init(&fi->value, fi->hfinfo->type);
3062 /* add the data source tvbuff */
3063 fi->ds_tvb=tvb?TVB_GET_DS_TVB(tvb):NULL;
3065 fi->appendix_start = 0;
3066 fi->appendix_length = 0;
3072 alloc_field_info(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3075 header_field_info *hfinfo;
3078 hfinfo = get_hfi_and_length(hfindex, tvb, start, length, &item_length);
3079 return new_field_info(tree, hfinfo, tvb, start, item_length);
3082 /* If the protocol tree is to be visible, set the representation of a
3083 proto_tree entry with the name of the field for the item and with
3084 the value formatted with the supplied printf-style format and
3087 proto_tree_set_representation_value(proto_item *pi, const char *format, va_list ap)
3089 int ret; /*tmp return value */
3090 field_info *fi = PITEM_FINFO(pi);
3091 header_field_info *hf = fi->hfinfo;
3093 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
3094 ITEM_LABEL_NEW(fi->rep);
3095 if (hf->bitmask && (hf->type == FT_BOOLEAN || IS_FT_UINT(hf->type))) {
3099 val = fvalue_get_uinteger(&fi->value);
3100 if (hf->bitshift > 0) {
3101 val <<= hf->bitshift;
3103 decode_bitfield_value(tmpbuf, val, hf->bitmask, hfinfo_bitwidth(hf));
3104 /* put in the hf name */
3105 ret = g_snprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
3106 "%s%s: ", tmpbuf, fi->hfinfo->name);
3108 /* put in the hf name */
3109 ret = g_snprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
3110 "%s: ", fi->hfinfo->name);
3113 /* If possible, Put in the value of the string */
3114 if (ret < ITEM_LABEL_LENGTH) {
3115 ret += g_vsnprintf(fi->rep->representation + ret,
3116 ITEM_LABEL_LENGTH - ret, format, ap);
3118 if (ret >= ITEM_LABEL_LENGTH) {
3119 /* Uh oh, we don't have enough room. Tell the user
3120 * that the field is truncated.
3124 /* Argh, we cannot reuse 'ap' here. So make a copy
3125 * of what we formatted for (re)use below.
3127 oldrep = g_strdup(fi->rep->representation);
3129 g_snprintf(fi->rep->representation,
3138 /* If the protocol tree is to be visible, set the representation of a
3139 proto_tree entry with the representation formatted with the supplied
3140 printf-style format and argument list. */
3142 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap)
3144 int ret; /*tmp return value */
3145 field_info *fi = PITEM_FINFO(pi);
3147 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
3148 ITEM_LABEL_NEW(fi->rep);
3149 ret = g_vsnprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
3151 if (ret >= ITEM_LABEL_LENGTH) {
3152 /* Uh oh, we don't have enough room. Tell the user
3153 * that the field is truncated.
3157 /* Argh, we cannot reuse 'ap' here. So make a copy
3158 * of what we formatted for (re)use below.
3160 oldrep = g_strdup(fi->rep->representation);
3162 g_snprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
3163 "[truncated] %s", oldrep);
3169 /* Set text of proto_item after having already been created. */
3171 proto_item_set_text(proto_item *pi, const char *format, ...)
3173 field_info *fi = NULL;
3180 fi = PITEM_FINFO(pi);
3183 ITEM_LABEL_FREE(fi->rep);
3186 va_start(ap, format);
3187 proto_tree_set_representation(pi, format, ap);
3191 /* Append to text of proto_item after having already been created. */
3193 proto_item_append_text(proto_item *pi, const char *format, ...)
3195 field_info *fi = NULL;
3203 fi = PITEM_FINFO(pi);
3208 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
3209 va_start(ap, format);
3212 * If we don't already have a representation,
3213 * generate the default representation.
3215 if (fi->rep == NULL) {
3216 ITEM_LABEL_NEW(fi->rep);
3217 proto_item_fill_label(fi, fi->rep->representation);
3220 curlen = strlen(fi->rep->representation);
3221 if (ITEM_LABEL_LENGTH > curlen) {
3222 g_vsnprintf(fi->rep->representation + curlen,
3223 ITEM_LABEL_LENGTH - (gulong) curlen, format, ap);
3230 proto_item_set_len(proto_item *pi, gint length)
3236 fi = PITEM_FINFO(pi);
3237 DISSECTOR_ASSERT(length >= 0);
3238 fi->length = length;
3240 if (fi->value.ftype->ftype == FT_BYTES)
3241 fi->value.value.bytes->len = length;
3245 * Sets the length of the item based on its start and on the specified
3246 * offset, which is the offset past the end of the item; as the start
3247 * in the item is relative to the beginning of the data source tvbuff,
3248 * we need to pass in a tvbuff - the end offset is relative to the beginning
3252 proto_item_set_end(proto_item *pi, tvbuff_t *tvb, gint end)
3258 fi = PITEM_FINFO(pi);
3259 end += TVB_RAW_OFFSET(tvb);
3260 DISSECTOR_ASSERT(end >= fi->start);
3261 fi->length = end - fi->start;
3265 proto_item_get_len(proto_item *pi)
3267 field_info *fi = PITEM_FINFO(pi);
3272 /** clear flags according to the mask and set new flag values */
3273 #define FI_REPLACE_FLAGS(fi, mask, flags_in) { \
3274 (fi->flags = (fi)->flags & ~(mask)); \
3275 (fi->flags = (fi)->flags | (flags_in)); \
3279 proto_item_set_expert_flags(proto_item *pi, int group, guint severity)
3281 if(pi == NULL || PITEM_FINFO(pi) == NULL)
3284 /* only change things if severity is worse or at least equal than before */
3285 if(severity >= FI_GET_FLAG(PITEM_FINFO(pi), PI_SEVERITY_MASK)) {
3286 FI_REPLACE_FLAGS(PITEM_FINFO(pi), PI_GROUP_MASK, group);
3287 FI_REPLACE_FLAGS(PITEM_FINFO(pi), PI_SEVERITY_MASK, severity);
3298 proto_tree_create_root(void)
3302 /* Initialize the proto_node */
3303 PROTO_NODE_NEW(pnode);
3304 pnode->parent = NULL;
3305 PNODE_FINFO(pnode) = NULL;
3306 pnode->tree_data = g_new(tree_data_t, 1);
3308 /* Don't initialize the tree_data_t. Wait until we know we need it */
3309 pnode->tree_data->interesting_hfids = NULL;
3311 /* Set the default to FALSE so it's easier to
3312 * find errors; if we expect to see the protocol tree
3313 * but for some reason the default 'visible' is not
3314 * changed, then we'll find out very quickly. */
3315 pnode->tree_data->visible = FALSE;
3317 /* Make sure that we fake protocols (if possible) */
3318 pnode->tree_data->fake_protocols = TRUE;
3320 /* Keep track of the number of children */
3321 pnode->tree_data->count = 0;
3323 return (proto_tree*) pnode;
3327 /* "prime" a proto_tree with a single hfid that a dfilter
3328 * is interested in. */
3330 proto_tree_prime_hfid(proto_tree *tree _U_, gint hfid)
3332 header_field_info *hfinfo;
3334 PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
3335 /* this field is referenced by a filter so increase the refcount.
3336 also increase the refcount for the parent, i.e the protocol.
3338 hfinfo->ref_count = HF_REF_TYPE_DIRECT;
3339 /* only increase the refcount if there is a parent.
3340 if this is a protocol and not a field then parent will be -1
3341 and there is no parent to add any refcounting for.
3343 if (hfinfo->parent != -1) {
3344 header_field_info *parent_hfinfo;
3345 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
3347 /* Mark parent as indirectly referenced unless it is already directly
3348 * referenced, i.e. the user has specified the parent in a filter.
3350 if (parent_hfinfo->ref_count != HF_REF_TYPE_DIRECT)
3351 parent_hfinfo->ref_count = HF_REF_TYPE_INDIRECT;
3356 proto_item_add_subtree(proto_item *pi, gint idx) {
3362 fi = PITEM_FINFO(pi);
3363 DISSECTOR_ASSERT(idx >= 0 && idx < num_tree_types);
3364 fi->tree_type = idx;
3366 return (proto_tree*) pi;
3370 proto_item_get_subtree(proto_item *pi) {
3375 fi = PITEM_FINFO(pi);
3376 if ( (!fi) || (fi->tree_type == -1) )
3378 return (proto_tree*) pi;
3382 proto_item_get_parent(proto_item *ti) {
3389 proto_item_get_parent_nth(proto_item *ti, int gen) {
3402 proto_tree_get_parent(proto_tree *tree) {
3405 return (proto_item*) tree;
3409 proto_tree_get_root(proto_tree *tree) {
3412 while (tree->parent) {
3413 tree = tree->parent;
3419 proto_tree_move_item(proto_tree *tree, proto_item *fixed_item, proto_item *item_to_move)
3421 DISSECTOR_ASSERT(item_to_move->parent == tree);
3422 DISSECTOR_ASSERT(fixed_item->parent == tree);
3424 /*** cut item_to_move out ***/
3426 /* is item_to_move the first? */
3427 if(tree->first_child == item_to_move) {
3428 /* simply change first child to next */
3429 tree->first_child = item_to_move->next;
3431 DISSECTOR_ASSERT(tree->last_child != item_to_move);
3433 proto_item *curr_item;
3434 /* find previous and change it's next */
3435 for(curr_item = tree->first_child; curr_item != NULL; curr_item = curr_item->next) {
3436 if(curr_item->next == item_to_move) {
3441 DISSECTOR_ASSERT(curr_item);
3443 curr_item->next = item_to_move->next;
3445 /* fix last_child if required */
3446 if(tree->last_child == item_to_move) {
3447 tree->last_child = curr_item;
3451 /*** insert to_move after fixed ***/
3452 item_to_move->next = fixed_item->next;
3453 fixed_item->next = item_to_move;
3454 if(tree->last_child == fixed_item) {
3455 tree->last_child = item_to_move;
3460 proto_tree_set_appendix(proto_tree *tree, tvbuff_t *tvb, gint start, gint length)
3467 fi = PTREE_FINFO(tree);
3468 start += TVB_RAW_OFFSET(tvb);
3469 DISSECTOR_ASSERT(start >= 0);
3470 DISSECTOR_ASSERT(length >= 0);
3472 fi->appendix_start = start;
3473 fi->appendix_length = length;
3477 proto_register_protocol(const char *name, const char *short_name, const char *filter_name)
3479 protocol_t *protocol;
3480 header_field_info *hfinfo;
3482 char *existing_name;
3486 gboolean found_invalid;
3489 * Make sure there's not already a protocol with any of those
3490 * names. Crash if there is, as that's an error in the code
3491 * or an inappropriate plugin.
3492 * This situation has to be fixed to not register more than one
3493 * protocol with the same name.
3495 * This is done by reducing the number of strcmp (and alike) calls as much as possible,
3496 * as this significally slows down startup time.
3498 * Drawback: As a hash value is used to reduce insert time,
3499 * this might lead to a hash collision.
3500 * However, as we have around 500+ protocols and we're using a 32 bit int this is very,
3504 key = g_malloc (sizeof(gint));
3505 *key = wrs_str_hash(name);
3506 existing_name = g_hash_table_lookup(proto_names, key);
3507 if (existing_name != NULL) {
3508 /* g_error will terminate the program */
3509 g_error("Duplicate protocol name \"%s\"!"
3510 " This might be caused by an inappropriate plugin or a development error.", name);
3512 g_hash_table_insert(proto_names, key, (gpointer)name);
3514 existing_name = g_hash_table_lookup(proto_short_names, (gpointer)short_name);
3515 if (existing_name != NULL) {
3516 g_error("Duplicate protocol short_name \"%s\"!"
3517 " This might be caused by an inappropriate plugin or a development error.", short_name);
3519 g_hash_table_insert(proto_short_names, (gpointer)short_name, (gpointer)short_name);
3521 found_invalid = FALSE;
3522 for (i = 0; i < strlen(filter_name); i++) {
3524 if (!(islower(c) || isdigit(c) || c == '-' || c == '_' || c == '.')) {
3525 found_invalid = TRUE;
3528 if (found_invalid) {
3529 g_error("Protocol filter name \"%s\" has one or more invalid characters."
3530 " Allowed are lower characters, digits, '-', '_' and '.'."
3531 " This might be caused by an inappropriate plugin or a development error.", filter_name);
3533 existing_name = g_hash_table_lookup(proto_filter_names, (gpointer)filter_name);
3534 if (existing_name != NULL) {
3535 g_error("Duplicate protocol filter_name \"%s\"!"
3536 " This might be caused by an inappropriate plugin or a development error.", filter_name);
3538 g_hash_table_insert(proto_filter_names, (gpointer)filter_name, (gpointer)filter_name);
3540 /* Add this protocol to the list of known protocols; the list
3541 is sorted by protocol short name. */
3542 protocol = g_malloc(sizeof (protocol_t));
3543 protocol->name = name;
3544 protocol->short_name = short_name;
3545 protocol->filter_name = filter_name;
3546 protocol->fields = NULL;
3547 protocol->is_enabled = TRUE; /* protocol is enabled by default */
3548 protocol->can_toggle = TRUE;
3549 protocol->is_private = FALSE;
3550 /* list will be sorted later by name, when all protocols completed registering */
3551 protocols = g_list_prepend(protocols, protocol);
3553 /* Here we do allocate a new header_field_info struct */
3554 hfinfo = g_mem_chunk_alloc(gmc_hfinfo);
3555 hfinfo->name = name;
3556 hfinfo->abbrev = filter_name;
3557 hfinfo->type = FT_PROTOCOL;
3558 hfinfo->display = BASE_NONE;
3559 hfinfo->strings = protocol;
3560 hfinfo->bitmask = 0;
3561 hfinfo->bitshift = 0;
3562 hfinfo->ref_count = HF_REF_TYPE_NONE;
3563 hfinfo->blurb = NULL;
3564 hfinfo->parent = -1; /* this field differentiates protos and fields */
3566 proto_id = proto_register_field_init(hfinfo, hfinfo->parent);
3567 protocol->proto_id = proto_id;
3572 proto_mark_private(int proto_id)
3574 protocol_t *protocol = find_protocol_by_id(proto_id);
3576 protocol->is_private = TRUE;
3580 proto_is_private(int proto_id)
3582 protocol_t *protocol = find_protocol_by_id(proto_id);
3584 return protocol->is_private;
3590 * Routines to use to iterate over the protocols.
3591 * The argument passed to the iterator routines is an opaque cookie to
3592 * their callers; it's the GList pointer for the current element in
3594 * The ID of the protocol is returned, or -1 if there is no protocol.
3597 proto_get_first_protocol(void **cookie)
3599 protocol_t *protocol;
3601 if (protocols == NULL)
3603 *cookie = protocols;
3604 protocol = protocols->data;
3605 return protocol->proto_id;
3609 proto_get_next_protocol(void **cookie)
3611 GList *list_item = *cookie;
3612 protocol_t *protocol;
3614 list_item = g_list_next(list_item);
3615 if (list_item == NULL)
3617 *cookie = list_item;
3618 protocol = list_item->data;
3619 return protocol->proto_id;
3623 proto_get_first_protocol_field(int proto_id, void **cookie)
3625 protocol_t *protocol = find_protocol_by_id(proto_id);
3626 hf_register_info *ptr;
3628 if ((protocol == NULL) || (protocol->fields == NULL))
3631 *cookie = protocol->fields;
3632 ptr = protocol->fields->data;
3633 return &ptr->hfinfo;
3637 proto_get_next_protocol_field(void **cookie)
3639 GList *list_item = *cookie;
3640 hf_register_info *ptr;
3642 list_item = g_list_next(list_item);
3643 if (list_item == NULL)
3646 *cookie = list_item;
3647 ptr = list_item->data;
3648 return &ptr->hfinfo;
3652 find_protocol_by_id(int proto_id)
3654 header_field_info *hfinfo;
3659 PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
3660 DISSECTOR_ASSERT(hfinfo->type==FT_PROTOCOL);
3661 return (protocol_t *)hfinfo->strings;
3664 static gint compare_filter_name(gconstpointer proto_arg,
3665 gconstpointer filter_name)
3667 const protocol_t *protocol = proto_arg;
3668 const gchar* f_name = filter_name;
3670 return (strcmp(protocol->filter_name, f_name));
3674 proto_get_id(protocol_t *protocol)
3676 return protocol->proto_id;
3679 int proto_get_id_by_filter_name(const gchar* filter_name)
3682 protocol_t *protocol;
3684 list_entry = g_list_find_custom(protocols, filter_name,
3685 compare_filter_name);
3687 if (list_entry == NULL)
3689 protocol = list_entry->data;
3690 return protocol->proto_id;
3694 proto_get_protocol_name(int proto_id)
3696 protocol_t *protocol;
3698 protocol = find_protocol_by_id(proto_id);
3699 return protocol->name;
3703 proto_get_protocol_short_name(protocol_t *protocol)
3705 if (protocol == NULL)
3707 return protocol->short_name;
3711 proto_get_protocol_long_name(protocol_t *protocol)
3713 if (protocol == NULL)
3715 return protocol->name;
3719 proto_get_protocol_filter_name(int proto_id)
3721 protocol_t *protocol;
3723 protocol = find_protocol_by_id(proto_id);
3724 if (protocol == NULL)
3726 return protocol->filter_name;
3730 proto_is_protocol_enabled(protocol_t *protocol)
3732 return protocol->is_enabled;
3736 proto_can_toggle_protocol(int proto_id)
3738 protocol_t *protocol;
3740 protocol = find_protocol_by_id(proto_id);
3741 return protocol->can_toggle;
3745 proto_set_decoding(int proto_id, gboolean enabled)
3747 protocol_t *protocol;
3749 protocol = find_protocol_by_id(proto_id);
3750 DISSECTOR_ASSERT(protocol->can_toggle);
3751 protocol->is_enabled = enabled;
3755 proto_enable_all(void)
3757 protocol_t *protocol;
3758 GList *list_item = protocols;
3760 if (protocols == NULL)
3764 protocol = list_item->data;
3765 if (protocol->can_toggle)
3766 protocol->is_enabled = TRUE;
3767 list_item = g_list_next(list_item);
3772 proto_set_cant_toggle(int proto_id)
3774 protocol_t *protocol;
3776 protocol = find_protocol_by_id(proto_id);
3777 protocol->can_toggle = FALSE;
3780 /* for use with static arrays only, since we don't allocate our own copies
3781 of the header_field_info struct contained within the hf_register_info struct */
3783 proto_register_field_array(int parent, hf_register_info *hf, int num_records)
3786 hf_register_info *ptr = hf;
3789 proto = find_protocol_by_id(parent);
3790 for (i = 0; i < num_records; i++, ptr++) {
3792 * Make sure we haven't registered this yet.
3793 * Most fields have variables associated with them
3794 * that are initialized to -1; some have array elements,
3795 * or possibly uninitialized variables, so we also allow
3796 * 0 (which is unlikely to be the field ID we get back
3797 * from "proto_register_field_init()").
3799 if (*ptr->p_id != -1 && *ptr->p_id != 0) {
3801 "Duplicate field detected in call to proto_register_field_array: %s is already registered\n",
3802 ptr->hfinfo.abbrev);
3806 if (proto != NULL) {
3807 if (proto->fields == NULL) {
3808 proto->fields = g_list_append(NULL, ptr);
3809 proto->last_field = proto->fields;
3812 g_list_append(proto->last_field, ptr)->next;
3815 field_id = proto_register_field_init(&ptr->hfinfo, parent);
3816 *ptr->p_id = field_id;
3820 /* chars allowed in field abbrev */
3822 const guchar fld_abbrev_chars[256] = {
3823 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00-0x0F */
3824 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10-0x1F */
3825 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, /* 0x20-0x2F '-', '.' */
3826 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 0x30-0x3F '0'-'9' */
3827 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x40-0x4F 'A'-'O' */
3828 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 0x50-0x5F 'P'-'Z', '_' */
3829 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x60-0x6F 'a'-'o' */
3830 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 0x70-0x7F 'p'-'z' */
3831 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80-0x8F */
3832 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90-0x9F */
3833 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xA0-0xAF */
3834 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xB0-0xBF */
3835 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xC0-0xCF */
3836 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xD0-0xDF */
3837 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xE0-0xEF */
3838 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xF0-0xFF */
3841 /* temporary function containing assert part for easier profiling */
3842 static void tmp_fld_check_assert(header_field_info *hfinfo) {
3843 /* The field must have a name (with length > 0) */
3844 DISSECTOR_ASSERT(hfinfo->name && hfinfo->name[0]);
3846 /* fields with an empty string for an abbreviation aren't filterable */
3847 DISSECTOR_ASSERT(hfinfo->abbrev);
3849 /* These types of fields are allowed to have value_strings, true_false_strings or a protocol_t struct*/
3850 DISSECTOR_ASSERT((hfinfo->strings == NULL) || (
3851 (hfinfo->type == FT_UINT8) ||
3852 (hfinfo->type == FT_UINT16) ||
3853 (hfinfo->type == FT_UINT24) ||
3854 (hfinfo->type == FT_UINT32) ||
3855 (hfinfo->type == FT_INT8) ||
3856 (hfinfo->type == FT_INT16) ||
3857 (hfinfo->type == FT_INT24) ||
3858 (hfinfo->type == FT_INT32) ||
3859 (hfinfo->type == FT_BOOLEAN) ||
3860 (hfinfo->type == FT_PROTOCOL) ||
3861 (hfinfo->type == FT_FRAMENUM) ));
3863 switch (hfinfo->type) {
3870 /* Hexadecimal and octal are, in printf() and everywhere else,
3871 * unsigned so don't allow dissectors to register a signed
3872 * field to be displayed unsigned. (Else how would we
3873 * display values negative values?)
3875 * If you want to take out this check, be sure to fix
3876 * hfinfo_numeric_format() so that it does not assert out
3877 * when trying to construct a hexadecimal representation of
3880 DISSECTOR_ASSERT(hfinfo->display != BASE_HEX &&
3881 hfinfo->display != BASE_HEX_DEC &&
3882 hfinfo->display != BASE_DEC_HEX &&
3883 hfinfo->display != BASE_OCT);
3889 if (hfinfo->strings == NULL) {
3890 /* Require integral types (other than frame number, which is
3891 always displayed in decimal) to have a number base */
3892 DISSECTOR_ASSERT(hfinfo->display != BASE_NONE);
3897 DISSECTOR_ASSERT(hfinfo->display != BASE_NONE);
3904 /* Don't allow bitfields or value strings for frame numbers and strings */
3905 DISSECTOR_ASSERT(hfinfo->bitmask == 0);
3906 DISSECTOR_ASSERT(hfinfo->strings == NULL);
3915 proto_register_field_init(header_field_info *hfinfo, int parent)
3918 tmp_fld_check_assert(hfinfo);
3920 /* if this is a bitfield, compute bitshift */
3921 if (hfinfo->bitmask) {
3922 hfinfo->bitshift = wrs_count_bitshift(hfinfo->bitmask);
3925 hfinfo->parent = parent;
3926 hfinfo->same_name_next = NULL;
3927 hfinfo->same_name_prev = NULL;
3929 /* if we always add and never delete, then id == len - 1 is correct */
3930 if(gpa_hfinfo.len>=gpa_hfinfo.allocated_len){
3931 if(!gpa_hfinfo.hfi){
3932 gpa_hfinfo.allocated_len=1000;
3933 gpa_hfinfo.hfi=g_malloc(sizeof(header_field_info *)*1000);
3935 gpa_hfinfo.allocated_len+=1000;
3936 gpa_hfinfo.hfi=g_realloc(gpa_hfinfo.hfi, sizeof(header_field_info *)*gpa_hfinfo.allocated_len);
3939 gpa_hfinfo.hfi[gpa_hfinfo.len]=hfinfo;
3941 hfinfo->id = gpa_hfinfo.len - 1;
3943 /* if we have real names, enter this field in the name tree */
3944 if ((hfinfo->name[0] != 0) && (hfinfo->abbrev[0] != 0 )) {
3946 header_field_info *same_name_next_hfinfo;
3949 /* Check that the filter name (abbreviation) is legal;
3950 * it must contain only alphanumerics, '-', "_", and ".". */
3951 c = wrs_check_charset(fld_abbrev_chars, hfinfo->abbrev);
3953 fprintf(stderr, "OOPS: '%c' in '%s'\n", c, hfinfo->abbrev);
3954 DISSECTOR_ASSERT(!c);
3957 /* We allow multiple hfinfo's to be registered under the same
3958 * abbreviation. This was done for X.25, as, depending
3959 * on whether it's modulo-8 or modulo-128 operation,
3960 * some bitfield fields may be in different bits of
3961 * a byte, and we want to be able to refer to that field
3962 * with one name regardless of whether the packets
3963 * are modulo-8 or modulo-128 packets. */
3965 same_name_hfinfo = NULL;
3967 g_tree_insert(gpa_name_tree, (gpointer) (hfinfo->abbrev), hfinfo);
3968 /* GLIB 2.x - if it is already present
3969 * the previous hfinfo with the same name is saved
3970 * to same_name_hfinfo by value destroy callback */
3971 if (same_name_hfinfo) {
3972 /* There's already a field with this name.
3973 * Put it after that field in the list of
3974 * fields with this name, then allow the code
3975 * after this if{} block to replace the old
3976 * hfinfo with the new hfinfo in the GTree. Thus,
3977 * we end up with a linked-list of same-named hfinfo's,
3978 * with the root of the list being the hfinfo in the GTree */
3979 same_name_next_hfinfo =
3980 same_name_hfinfo->same_name_next;
3982 hfinfo->same_name_next = same_name_next_hfinfo;
3983 if (same_name_next_hfinfo)
3984 same_name_next_hfinfo->same_name_prev = hfinfo;
3986 same_name_hfinfo->same_name_next = hfinfo;
3987 hfinfo->same_name_prev = same_name_hfinfo;
3995 proto_register_subtree_array(gint *const *indices, int num_indices)
3998 gint *const *ptr = indices;
4001 * If we've already allocated the array of tree types, expand
4002 * it; this lets plugins such as mate add tree types after
4003 * the initial startup. (If we haven't already allocated it,
4004 * we don't allocate it; on the first pass, we just assign
4005 * ett values and keep track of how many we've assigned, and
4006 * when we're finished registering all dissectors we allocate
4007 * the array, so that we do only one allocation rather than
4008 * wasting CPU time and memory by growing the array for each
4009 * dissector that registers ett values.)
4011 if (tree_is_expanded != NULL) {
4013 g_realloc(tree_is_expanded,
4014 (num_tree_types+num_indices)*sizeof (gboolean));
4015 memset(tree_is_expanded + num_tree_types, 0,
4016 num_indices*sizeof (gboolean));
4020 * Assign "num_indices" subtree numbers starting at "num_tree_types",
4021 * returning the indices through the pointers in the array whose
4022 * first element is pointed to by "indices", and update
4023 * "num_tree_types" appropriately.
4025 for (i = 0; i < num_indices; i++, ptr++, num_tree_types++) {
4027 /* g_error will terminate the program */
4028 g_error("register_subtree_array: subtree item type (ett_...) not -1 !"
4029 " This is a development error:"
4030 " Either the subtree item type has already been assigned or"
4031 " was not initialized to -1.");
4033 **ptr = num_tree_types;
4038 proto_item_fill_label(field_info *fi, gchar *label_str)
4040 header_field_info *hfinfo = fi->hfinfo;
4046 guint32 n_addr; /* network-order IPv4 address */
4048 int ret; /*tmp return value */
4050 switch(hfinfo->type) {
4053 g_strlcpy(label_str, hfinfo->name, ITEM_LABEL_LENGTH);
4057 fill_label_boolean(fi, label_str);
4062 bytes = fvalue_get(&fi->value);
4064 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4065 "%s: %s", hfinfo->name,
4066 bytes_to_str(bytes, fvalue_length(&fi->value)));
4067 if (ret >= ITEM_LABEL_LENGTH) {
4068 /* Uh oh, we don't have enough room. Tell the
4069 * user that the field is truncated.
4071 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4072 "%s [truncated]: %s",
4074 bytes_to_str(bytes, fvalue_length(&fi->value)));
4078 g_snprintf(label_str, ITEM_LABEL_LENGTH, "%s: <MISSING>", hfinfo->name);
4082 /* Four types of integers to take care of:
4083 * Bitfield, with val_string
4084 * Bitfield, w/o val_string
4085 * Non-bitfield, with val_string
4086 * Non-bitfield, w/o val_string
4092 if (hfinfo->bitmask) {
4093 fill_label_bitfield(fi, label_str);
4095 fill_label_uint(fi, label_str);
4100 fill_label_uint(fi, label_str);
4104 fill_label_uint64(fi, label_str);
4111 DISSECTOR_ASSERT(!hfinfo->bitmask);
4112 fill_label_int(fi, label_str);
4116 fill_label_int64(fi, label_str);
4120 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4121 "%s: %." STRINGIFY(FLT_DIG) "f",
4122 hfinfo->name, fvalue_get_floating(&fi->value));
4126 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4127 "%s: %." STRINGIFY(DBL_DIG) "g",
4128 hfinfo->name, fvalue_get_floating(&fi->value));
4131 case FT_ABSOLUTE_TIME:
4132 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4133 "%s: %s", hfinfo->name,
4134 abs_time_to_str(fvalue_get(&fi->value)));
4137 case FT_RELATIVE_TIME:
4138 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4139 "%s: %s seconds", hfinfo->name,
4140 rel_time_to_secs_str(fvalue_get(&fi->value)));
4144 integer = fvalue_get_uinteger(&fi->value);
4145 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4146 "%s: %s (0x%08X)", hfinfo->name,
4147 get_ipxnet_name(integer), integer);
4151 bytes = fvalue_get(&fi->value);
4152 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4153 "%s: %s (%s)", hfinfo->name,
4154 get_ether_name(bytes),
4155 ether_to_str(bytes));
4159 ipv4 = fvalue_get(&fi->value);
4160 n_addr = ipv4_get_net_order_addr(ipv4);
4161 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4162 "%s: %s (%s)", hfinfo->name,
4163 get_hostname(n_addr),
4164 ip_to_str((guint8*)&n_addr));
4168 bytes = fvalue_get(&fi->value);
4169 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4170 "%s: %s (%s)", hfinfo->name,
4171 get_hostname6((struct e_in6_addr *)bytes),
4172 ip6_to_str((struct e_in6_addr*)bytes));
4176 guid = fvalue_get(&fi->value);
4177 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4178 "%s: %s", hfinfo->name,
4183 bytes = fvalue_get(&fi->value);
4184 name = oid_resolved_from_encoded(bytes, fvalue_length(&fi->value));
4186 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4187 "%s: %s (%s)", hfinfo->name,
4188 oid_encoded2string(bytes, fvalue_length(&fi->value)), name);
4190 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4191 "%s: %s", hfinfo->name,
4192 oid_encoded2string(bytes, fvalue_length(&fi->value)));
4199 case FT_UINT_STRING:
4200 bytes = fvalue_get(&fi->value);
4201 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4202 "%s: %s", hfinfo->name,
4203 format_text(bytes, strlen(bytes)));
4204 if (ret >= ITEM_LABEL_LENGTH) {
4205 /* Uh oh, we don't have enough room. Tell the
4206 * user that the field is truncated.
4208 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4209 "%s [truncated]: %s",
4211 format_text(bytes, strlen(bytes)));
4216 g_error("hfinfo->type %d (%s) not handled\n",
4218 ftype_name(hfinfo->type));
4219 DISSECTOR_ASSERT_NOT_REACHED();
4225 fill_label_boolean(field_info *fi, gchar *label_str)
4227 char *p = label_str;
4228 int bitfield_byte_length = 0, bitwidth;
4229 guint32 unshifted_value;
4232 header_field_info *hfinfo = fi->hfinfo;
4233 const true_false_string *tfstring = (const true_false_string *)&tfs_true_false;
4235 if (hfinfo->strings) {
4236 tfstring = (const struct true_false_string*) hfinfo->strings;
4239 value = fvalue_get_uinteger(&fi->value);
4240 if (hfinfo->bitmask) {
4241 /* Figure out the bit width */
4242 bitwidth = hfinfo_bitwidth(hfinfo);
4245 unshifted_value = value;
4246 if (hfinfo->bitshift > 0) {
4247 unshifted_value <<= hfinfo->bitshift;
4250 /* Create the bitfield first */
4251 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
4252 bitfield_byte_length = (int) (p - label_str);
4255 /* Fill in the textual info */
4256 g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
4257 "%s: %s", hfinfo->name,
4258 value ? tfstring->true_string : tfstring->false_string);
4261 /* Fills data for bitfield ints with val_strings */
4263 fill_label_bitfield(field_info *fi, gchar *label_str)
4265 const char *format = NULL;
4267 int bitfield_byte_length, bitwidth;
4268 guint32 unshifted_value;
4271 header_field_info *hfinfo = fi->hfinfo;
4273 /* Figure out the bit width */
4274 bitwidth = hfinfo_bitwidth(hfinfo);
4277 unshifted_value = fvalue_get_uinteger(&fi->value);
4278 value = unshifted_value;
4279 if (hfinfo->bitshift > 0) {
4280 unshifted_value <<= hfinfo->bitshift;
4283 /* Create the bitfield first */
4284 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
4285 bitfield_byte_length = (int) (p - label_str);
4287 /* Fill in the textual info using stored (shifted) value */
4288 if (hfinfo->display == BASE_CUSTOM) {
4289 gchar tmp[ITEM_LABEL_LENGTH];
4290 custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hfinfo->strings;
4292 DISSECTOR_ASSERT(fmtfunc);
4293 fmtfunc(tmp, value);
4294 g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
4295 "%s: %s", hfinfo->name, tmp);
4297 else if (hfinfo->strings) {
4298 format = hfinfo_uint_vals_format(hfinfo);
4299 if (hfinfo->display & BASE_RANGE_STRING) {
4300 g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
4301 format, hfinfo->name,
4302 rval_to_str(value, hfinfo->strings, "Unknown"), value);
4304 g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
4305 format, hfinfo->name,
4306 val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
4310 format = hfinfo_uint_format(hfinfo);
4311 if (IS_BASE_DUAL(hfinfo->display)) {
4312 g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
4313 format, hfinfo->name, value, value);
4315 g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
4316 format, hfinfo->name, value);
4322 fill_label_uint(field_info *fi, gchar *label_str)
4324 const char *format = NULL;
4325 header_field_info *hfinfo = fi->hfinfo;
4328 value = fvalue_get_uinteger(&fi->value);
4330 /* Fill in the textual info */
4331 if (hfinfo->display == BASE_CUSTOM) {
4332 gchar tmp[ITEM_LABEL_LENGTH];
4333 custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hfinfo->strings;
4335 DISSECTOR_ASSERT(fmtfunc);
4336 fmtfunc(tmp, value);
4337 g_snprintf(label_str, ITEM_LABEL_LENGTH, "%s: %s", hfinfo->name, tmp);
4339 else if (hfinfo->strings) {
4340 format = hfinfo_uint_vals_format(hfinfo);
4341 if (hfinfo->display & BASE_RANGE_STRING) {
4342 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4343 format, hfinfo->name,
4344 rval_to_str(value, hfinfo->strings, "Unknown"), value);
4346 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4347 format, hfinfo->name,
4348 val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
4352 format = hfinfo_uint_format(hfinfo);
4353 if (IS_BASE_DUAL(hfinfo->display)) {
4354 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4355 format, hfinfo->name, value, value);
4357 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4358 format, hfinfo->name, value);
4364 fill_label_uint64(field_info *fi, gchar *label_str)
4366 const char *format = NULL;
4367 header_field_info *hfinfo = fi->hfinfo;
4370 /* Pick the proper format string */
4371 format = hfinfo_uint64_format(hfinfo);
4372 value = fvalue_get_integer64(&fi->value);
4374 /* Fill in the textual info */
4375 if (IS_BASE_DUAL(hfinfo->display)) {
4376 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4377 format, hfinfo->name, value, value);
4379 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4380 format, hfinfo->name, value);
4385 fill_label_int(field_info *fi, gchar *label_str)
4387 const char *format = NULL;
4388 header_field_info *hfinfo = fi->hfinfo;
4391 value = fvalue_get_sinteger(&fi->value);
4393 /* Fill in the textual info */
4394 if (hfinfo->display == BASE_CUSTOM) {
4395 gchar tmp[ITEM_LABEL_LENGTH];
4396 custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hfinfo->strings;
4398 DISSECTOR_ASSERT(fmtfunc);
4399 fmtfunc(tmp, value);
4400 g_snprintf(label_str, ITEM_LABEL_LENGTH, "%s: %s", hfinfo->name, tmp);
4402 else if (hfinfo->strings) {
4403 format = hfinfo_int_vals_format(hfinfo);
4404 if (hfinfo->display & BASE_RANGE_STRING) {
4405 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4406 format, hfinfo->name,
4407 rval_to_str(value, hfinfo->strings, "Unknown"), value);
4409 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4410 format, hfinfo->name,
4411 val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
4415 format = hfinfo_int_format(hfinfo);
4416 if (IS_BASE_DUAL(hfinfo->display)) {
4417 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4418 format, hfinfo->name, value, value);
4420 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4421 format, hfinfo->name, value);
4427 fill_label_int64(field_info *fi, gchar *label_str)
4429 const char *format = NULL;
4430 header_field_info *hfinfo = fi->hfinfo;
4433 /* Pick the proper format string */
4434 format = hfinfo_int64_format(hfinfo);
4435 value = fvalue_get_integer64(&fi->value);
4437 /* Fill in the textual info */
4438 if (IS_BASE_DUAL(hfinfo->display)) {
4439 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4440 format, hfinfo->name, value, value);
4442 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4443 format, hfinfo->name, value);
4448 hfinfo_bitwidth(header_field_info *hfinfo)
4452 if (!hfinfo->bitmask) {
4456 switch(hfinfo->type) {
4474 bitwidth = hfinfo->display; /* hacky? :) */
4477 DISSECTOR_ASSERT_NOT_REACHED();
4484 hfinfo_uint_vals_format(header_field_info *hfinfo)
4486 const char *format = NULL;
4488 /* bit operation to reset the potential BASE_RANGE_STRING (or others in
4490 switch(hfinfo->display & BASE_STRUCTURE_RESET) {
4496 format = "%s: %s (%u)";
4498 case BASE_OCT: /* I'm lazy */
4499 format = "%s: %s (%o)";
4503 switch(hfinfo->type) {
4505 format = "%s: %s (0x%02x)";
4508 format = "%s: %s (0x%04x)";
4511 format = "%s: %s (0x%06x)";
4514 format = "%s: %s (0x%08x)";
4517 DISSECTOR_ASSERT_NOT_REACHED();
4522 DISSECTOR_ASSERT_NOT_REACHED();
4529 hfinfo_uint_format(header_field_info *hfinfo)
4531 const char *format = NULL;
4533 /* Pick the proper format string */
4534 if (hfinfo->type == FT_FRAMENUM) {
4536 * Frame numbers are always displayed in decimal.
4540 switch(hfinfo->display) {
4545 switch(hfinfo->type) {
4547 format = "%s: %u (0x%02x)";
4550 format = "%s: %u (0x%04x)";
4553 format = "%s: %u (0x%06x)";
4556 format = "%s: %u (0x%08x)";
4559 DISSECTOR_ASSERT_NOT_REACHED();
4563 case BASE_OCT: /* I'm lazy */
4567 switch(hfinfo->type) {
4569 format = "%s: 0x%02x";
4572 format = "%s: 0x%04x";
4575 format = "%s: 0x%06x";
4578 format = "%s: 0x%08x";
4581 DISSECTOR_ASSERT_NOT_REACHED();
4586 switch(hfinfo->type) {
4588 format = "%s: 0x%02x (%u)";
4591 format = "%s: 0x%04x (%u)";
4594 format = "%s: 0x%06x (%u)";
4597 format = "%s: 0x%08x (%u)";
4600 DISSECTOR_ASSERT_NOT_REACHED();
4605 DISSECTOR_ASSERT_NOT_REACHED();
4613 hfinfo_uint_value_format(header_field_info *hfinfo)
4615 const char *format = NULL;
4617 /* Pick the proper format string */
4618 if (hfinfo->type == FT_FRAMENUM) {
4620 * Frame numbers are always displayed in decimal.
4624 switch(hfinfo->display) {
4629 switch(hfinfo->type) {
4631 format = "%u (0x%02x)";
4634 format = "%u (0x%04x)";
4637 format = "%u (0x%06x)";
4640 format = "%u (0x%08x)";
4643 DISSECTOR_ASSERT_NOT_REACHED();
4651 switch(hfinfo->type) {
4665 DISSECTOR_ASSERT_NOT_REACHED();
4670 switch(hfinfo->type) {
4672 format = "0x%02x (%u)";
4675 format = "0x%04x (%u)";
4678 format = "0x%06x (%u)";
4681 format = "0x%08x (%u)";
4684 DISSECTOR_ASSERT_NOT_REACHED();
4689 DISSECTOR_ASSERT_NOT_REACHED();
4697 hfinfo_int_vals_format(header_field_info *hfinfo)
4699 const char *format = NULL;
4701 /* bit operation to reset the potential BASE_RANGE_STRING (or others in
4703 switch(hfinfo->display & BASE_STRUCTURE_RESET) {
4709 format = "%s: %s (%d)";
4711 case BASE_OCT: /* I'm lazy */
4712 format = "%s: %s (%o)";
4716 switch(hfinfo->type) {
4718 format = "%s: %s (0x%02x)";
4721 format = "%s: %s (0x%04x)";
4724 format = "%s: %s (0x%06x)";
4727 format = "%s: %s (0x%08x)";
4730 DISSECTOR_ASSERT_NOT_REACHED();
4735 DISSECTOR_ASSERT_NOT_REACHED();
4742 hfinfo_uint64_format(header_field_info *hfinfo)
4744 const char *format = NULL;
4746 /* Pick the proper format string */
4747 switch(hfinfo->display) {
4749 format = "%s: %" G_GINT64_MODIFIER "u";
4752 format = "%s: %" G_GINT64_MODIFIER "u (%" G_GINT64_MODIFIER "x)";
4754 case BASE_OCT: /* I'm lazy */
4755 format = "%s: %" G_GINT64_MODIFIER "o";
4758 format = "%s: 0x%016" G_GINT64_MODIFIER "x";
4761 format = "%s: 0x%016" G_GINT64_MODIFIER "x (%" G_GINT64_MODIFIER "u)";
4764 DISSECTOR_ASSERT_NOT_REACHED();
4771 hfinfo_int_format(header_field_info *hfinfo)
4773 const char *format = NULL;
4775 /* Pick the proper format string */
4776 switch(hfinfo->display) {
4781 switch(hfinfo->type) {
4783 format = "%s: %d (0x%02x)";
4786 format = "%s: %d (0x%04x)";
4789 format = "%s: %d (0x%06x)";
4792 format = "%s: %d (0x%08x)";
4795 DISSECTOR_ASSERT_NOT_REACHED();
4799 case BASE_OCT: /* I'm lazy */
4803 switch(hfinfo->type) {
4805 format = "%s: 0x%02x";
4808 format = "%s: 0x%04x";
4811 format = "%s: 0x%06x";
4814 format = "%s: 0x%08x";
4817 DISSECTOR_ASSERT_NOT_REACHED();
4822 switch(hfinfo->type) {
4824 format = "%s: 0x%02x (%d)";
4827 format = "%s: 0x%04x (%d)";
4830 format = "%s: 0x%06x (%d)";
4833 format = "%s: 0x%08x (%d)";
4836 DISSECTOR_ASSERT_NOT_REACHED();
4841 DISSECTOR_ASSERT_NOT_REACHED();
4848 hfinfo_int_value_format(header_field_info *hfinfo)
4850 const char *format = NULL;
4852 /* Pick the proper format string */
4853 switch(hfinfo->display) {
4858 switch(hfinfo->type) {
4860 format = "%d (0x%02x)";
4863 format = "%d (0x%04x)";
4866 format = "%d (0x%06x)";
4869 format = "%d (0x%08x)";
4872 DISSECTOR_ASSERT_NOT_REACHED();
4880 switch(hfinfo->type) {
4894 DISSECTOR_ASSERT_NOT_REACHED();
4899 switch(hfinfo->type) {
4901 format = "0x%02x (%d)";
4904 format = "0x%04x (%d)";
4907 format = "0x%06x (%d)";
4910 format = "0x%08x (%d)";
4913 DISSECTOR_ASSERT_NOT_REACHED();
4918 DISSECTOR_ASSERT_NOT_REACHED();
4925 hfinfo_int64_format(header_field_info *hfinfo)
4927 const char *format = NULL;
4929 /* Pick the proper format string */
4930 switch(hfinfo->display) {
4932 format = "%s: %" G_GINT64_MODIFIER "d";
4935 format = "%s: %" G_GINT64_MODIFIER "d (%" G_GINT64_MODIFIER "x)";
4937 case BASE_OCT: /* I'm lazy */
4938 format = "%s: %" G_GINT64_MODIFIER "o";
4941 format = "%s: 0x%016" G_GINT64_MODIFIER "x";
4944 format = "%s: 0x%016" G_GINT64_MODIFIER "x (%" G_GINT64_MODIFIER "d)";
4947 DISSECTOR_ASSERT_NOT_REACHED();
4956 proto_registrar_n(void)
4958 return gpa_hfinfo.len;
4962 proto_registrar_get_name(int n)
4964 header_field_info *hfinfo;
4966 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
4967 return hfinfo->name;
4971 proto_registrar_get_abbrev(int n)
4973 header_field_info *hfinfo;
4975 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
4976 return hfinfo->abbrev;
4980 proto_registrar_get_ftype(int n)
4982 header_field_info *hfinfo;
4984 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
4985 return hfinfo->type;
4989 proto_registrar_get_parent(int n)
4991 header_field_info *hfinfo;
4993 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
4994 return hfinfo->parent;
4998 proto_registrar_is_protocol(int n)
5000 header_field_info *hfinfo;
5002 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
5003 return (hfinfo->parent == -1 ? TRUE : FALSE);
5006 /* Returns length of field in packet (not necessarily the length
5007 * in our internal representation, as in the case of IPv4).
5008 * 0 means undeterminable at time of registration
5009 * -1 means the field is not registered. */
5011 proto_registrar_get_length(int n)
5013 header_field_info *hfinfo;
5015 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
5016 return ftype_length(hfinfo->type);
5021 /* Looks for a protocol or a field in a proto_tree. Returns TRUE if
5022 * it exists anywhere, or FALSE if it exists nowhere. */
5024 proto_check_for_protocol_or_field(proto_tree* tree, int id)
5026 GPtrArray *ptrs = proto_get_finfo_ptr_array(tree, id);
5031 else if (g_ptr_array_len(ptrs) > 0) {
5039 /* Return GPtrArray* of field_info pointers for all hfindex that appear in tree.
5040 * This only works if the hfindex was "primed" before the dissection
5041 * took place, as we just pass back the already-created GPtrArray*.
5042 * The caller should *not* free the GPtrArray*; proto_tree_free_node()
5045 proto_get_finfo_ptr_array(proto_tree *tree, int id)
5047 if (PTREE_DATA(tree)->interesting_hfids != NULL)
5048 return g_hash_table_lookup(PTREE_DATA(tree)->interesting_hfids,
5049 GINT_TO_POINTER(id));
5055 proto_tracking_interesting_fields(proto_tree *tree)
5057 return (PTREE_DATA(tree)->interesting_hfids != NULL);
5060 /* Helper struct for proto_find_info() and proto_all_finfos() */
5066 /* Helper function for proto_find_info() */
5068 find_finfo(proto_node *node, gpointer data)
5070 field_info *fi = PNODE_FINFO(node);
5071 if (fi && fi->hfinfo) {
5072 if (fi->hfinfo->id == ((ffdata_t*)data)->id) {
5073 g_ptr_array_add(((ffdata_t*)data)->array, fi);
5077 /* Don't stop traversing. */
5081 /* Return GPtrArray* of field_info pointers for all hfindex that appear in a tree.
5082 * This works on any proto_tree, primed or unprimed, but actually searches
5083 * the tree, so it is slower than using proto_get_finfo_ptr_array on a primed tree.
5084 * The caller does need to free the returned GPtrArray with
5085 * g_ptr_array_free(<array>, FALSE).
5088 proto_find_finfo(proto_tree *tree, int id)
5092 ffdata.array = g_ptr_array_new();
5095 proto_tree_traverse_pre_order(tree, find_finfo, &ffdata);
5097 return ffdata.array;
5100 /* Helper function for proto_all_finfos() */
5102 every_finfo(proto_node *node, gpointer data)
5104 field_info *fi = PNODE_FINFO(node);
5105 if (fi && fi->hfinfo) {
5106 g_ptr_array_add(((ffdata_t*)data)->array, fi);
5109 /* Don't stop traversing. */
5113 /* Return GPtrArray* of field_info pointers containing all hfindexes that appear in a tree. */
5115 proto_all_finfos(proto_tree *tree)
5119 ffdata.array = g_ptr_array_new();
5122 proto_tree_traverse_pre_order(tree, every_finfo, &ffdata);
5124 return ffdata.array;
5135 check_for_offset(proto_node *node, gpointer data)
5137 field_info *fi = PNODE_FINFO(node);
5138 offset_search_t *offsearch = data;
5140 /* !fi == the top most container node which holds nothing */
5141 if (fi && !PROTO_ITEM_IS_HIDDEN(node) && fi->ds_tvb && offsearch->tvb == fi->ds_tvb) {
5142 if (offsearch->offset >= (guint) fi->start &&
5143 offsearch->offset < (guint) (fi->start + fi->length)) {
5145 offsearch->finfo = fi;
5146 return FALSE; /* keep traversing */
5149 return FALSE; /* keep traversing */
5152 /* Search a proto_tree backwards (from leaves to root) looking for the field
5153 * whose start/length occupies 'offset' */
5154 /* XXX - I couldn't find an easy way to search backwards, so I search
5155 * forwards, w/o stopping. Therefore, the last finfo I find will the be
5156 * the one I want to return to the user. This algorithm is inefficient
5157 * and could be re-done, but I'd have to handle all the children and
5158 * siblings of each node myself. When I have more time I'll do that.
5161 proto_find_field_from_offset(proto_tree *tree, guint offset, tvbuff_t *tvb)
5163 offset_search_t offsearch;
5165 offsearch.offset = offset;
5166 offsearch.finfo = NULL;
5167 offsearch.tvb = tvb;
5169 proto_tree_traverse_pre_order(tree, check_for_offset, &offsearch);
5171 return offsearch.finfo;
5174 /* Dumps the protocols in the registration database to stdout. An independent
5175 * program can take this output and format it into nice tables or HTML or
5178 * There is one record per line. The fields are tab-delimited.
5180 * Field 1 = protocol name
5181 * Field 2 = protocol short name
5182 * Field 3 = protocol filter name
5185 proto_registrar_dump_protocols(void)
5187 protocol_t *protocol;
5189 void *cookie = NULL;
5191 for (i = proto_get_first_protocol(&cookie); i != -1;
5192 i = proto_get_next_protocol(&cookie)) {
5193 protocol = find_protocol_by_id(i);
5194 printf("%s\t%s\t%s\n", protocol->name, protocol->short_name,
5195 protocol->filter_name);
5199 /* Dumps the value_strings, range_strings or true/false strings for fields
5200 * that have them. There is one record per line. Fields are tab-delimited.
5201 * There are three types of records: Value String, Range String
5202 * and True/False String. The first field, 'V', 'R' or 'T', indicates
5203 * the type of record.
5208 * Field 2 = field abbreviation to which this value string corresponds
5209 * Field 3 = Integer value
5215 * Field 2 = field abbreviation to which this range string corresponds
5216 * Field 3 = Integer value: lower bound
5217 * Field 4 = Integer value: upper bound
5220 * True/False Strings
5221 * ------------------
5223 * Field 2 = field abbreviation to which this true/false string corresponds
5224 * Field 3 = True String
5225 * Field 4 = False String
5228 proto_registrar_dump_values(void)
5230 header_field_info *hfinfo, *parent_hfinfo;
5232 const value_string *vals;
5233 const range_string *range;
5234 const true_false_string *tfs;
5236 len = gpa_hfinfo.len;
5237 for (i = 0; i < len ; i++) {
5238 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
5240 if (hfinfo->id == hf_text_only) {
5244 /* ignore protocols */
5245 if (proto_registrar_is_protocol(i)) {
5248 /* process header fields */
5251 * If this field isn't at the head of the list of
5252 * fields with this name, skip this field - all
5253 * fields with the same name are really just versions
5254 * of the same field stored in different bits, and
5255 * should have the same type/radix/value list, and
5256 * just differ in their bit masks. (If a field isn't
5257 * a bitfield, but can be, say, 1 or 2 bytes long,
5258 * it can just be made FT_UINT16, meaning the
5259 * *maximum* length is 2 bytes, and be used
5262 if (hfinfo->same_name_prev != NULL)
5265 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
5271 if ((hfinfo->display & BASE_STRUCTURE_RESET) != BASE_CUSTOM &&
5272 (hfinfo->type == FT_UINT8 ||
5273 hfinfo->type == FT_UINT16 ||
5274 hfinfo->type == FT_UINT24 ||
5275 hfinfo->type == FT_UINT32 ||
5276 hfinfo->type == FT_UINT64 ||
5277 hfinfo->type == FT_INT8 ||
5278 hfinfo->type == FT_INT16 ||
5279 hfinfo->type == FT_INT24 ||
5280 hfinfo->type == FT_INT32 ||
5281 hfinfo->type == FT_INT64)) {
5283 if ((hfinfo->display & BASE_RANGE_STRING) == 0) {
5284 vals = hfinfo->strings;
5286 range = hfinfo->strings;
5289 else if (hfinfo->type == FT_BOOLEAN) {
5290 tfs = hfinfo->strings;
5293 /* Print value strings? */
5296 while (vals[vi].strptr) {
5297 /* Print in the proper base */
5298 if (hfinfo->display == BASE_HEX) {
5299 printf("V\t%s\t0x%x\t%s\n",
5305 printf("V\t%s\t%u\t%s\n",
5314 /* print range strings? */
5317 while (range[vi].strptr) {
5318 /* Print in the proper base */
5319 if ((hfinfo->display & BASE_STRUCTURE_RESET) == BASE_HEX) {
5320 printf("R\t%s\t0x%x\t0x%x\t%s\n",
5322 range[vi].value_min,
5323 range[vi].value_max,
5327 printf("R\t%s\t%u\t%u\t%s\n",
5329 range[vi].value_min,
5330 range[vi].value_max,
5337 /* Print true/false strings? */
5339 printf("T\t%s\t%s\t%s\n", hfinfo->abbrev,
5340 tfs->true_string, tfs->false_string);
5346 /* Dumps the contents of the registration database to stdout. An independent
5347 * program can take this output and format it into nice tables or HTML or
5350 * There is one record per line. Each record is either a protocol or a header
5351 * field, differentiated by the first field. The fields are tab-delimited.
5356 * Field 2 = descriptive protocol name
5357 * Field 3 = protocol abbreviation
5363 * Field 2 = descriptive field name
5364 * Field 3 = field abbreviation
5365 * Field 4 = type ( textual representation of the the ftenum type )
5366 * Field 5 = parent protocol abbreviation
5367 * Field 6 = blurb describing field
5371 * Field 2 = descriptive field name
5372 * Field 3 = field abbreviation
5373 * Field 4 = type ( textual representation of the the ftenum type )
5374 * Field 5 = parent protocol abbreviation
5375 * Field 6 = blurb describing field
5376 * Field 7 = base for display (for integer types); "parent bitfield width" for FT_BOOLEAN
5377 * Field 8 = blurb describing field (yes, apparently we repeated this accidentally)
5381 * Field 2 = descriptive field name
5382 * Field 3 = field abbreviation
5383 * Field 4 = type ( textual representation of the the ftenum type )
5384 * Field 5 = parent protocol abbreviation
5385 * Field 6 = blurb describing field
5386 * Field 7 = base for display (for integer types); "parent bitfield width" for FT_BOOLEAN
5387 * Field 8 = bitmask: format: hex: 0x....
5391 proto_registrar_dump_fields(int format)
5393 header_field_info *hfinfo, *parent_hfinfo;
5395 const char *enum_name;
5396 const char *base_name;
5400 len = gpa_hfinfo.len;
5401 for (i = 0; i < len ; i++) {
5402 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
5405 * Skip the pseudo-field for "proto_tree_add_text()" since
5406 * we don't want it in the list of filterable fields.
5408 if (hfinfo->id == hf_text_only)
5411 /* format for protocols */
5412 if (proto_registrar_is_protocol(i)) {
5413 printf("P\t%s\t%s\n", hfinfo->name, hfinfo->abbrev);
5415 /* format for header fields */
5418 * If this field isn't at the head of the list of
5419 * fields with this name, skip this field - all
5420 * fields with the same name are really just versions
5421 * of the same field stored in different bits, and
5422 * should have the same type/radix/value list, and
5423 * just differ in their bit masks. (If a field isn't
5424 * a bitfield, but can be, say, 1 or 2 bytes long,
5425 * it can just be made FT_UINT16, meaning the
5426 * *maximum* length is 2 bytes, and be used
5429 if (hfinfo->same_name_prev != NULL)
5432 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
5434 enum_name = ftype_name(hfinfo->type);
5438 if (hfinfo->type == FT_UINT8 ||
5439 hfinfo->type == FT_UINT16 ||
5440 hfinfo->type == FT_UINT24 ||
5441 hfinfo->type == FT_UINT32 ||
5442 hfinfo->type == FT_UINT64 ||
5443 hfinfo->type == FT_INT8 ||
5444 hfinfo->type == FT_INT16 ||
5445 hfinfo->type == FT_INT24 ||
5446 hfinfo->type == FT_INT32 ||
5447 hfinfo->type == FT_INT64) {
5450 switch(hfinfo->display & BASE_STRUCTURE_RESET) {
5452 base_name = "BASE_NONE";
5455 base_name = "BASE_DEC";
5458 base_name = "BASE_HEX";
5461 base_name = "BASE_OCT";
5464 base_name = "BASE_DEC_HEX";
5467 base_name = "BASE_HEX_DEC";
5470 base_name = "BASE_CUSTOM";
5476 } else if (hfinfo->type == FT_BOOLEAN) {
5477 /* For FT_BOOLEAN: 'display' can be "parent bitfield width" */
5478 g_snprintf(width, sizeof(width), "%d", hfinfo->display);
5483 blurb = hfinfo->blurb;
5487 printf("F\t%s\t%s\t%s\t%s\t%s\n",
5488 hfinfo->name, hfinfo->abbrev, enum_name,
5489 parent_hfinfo->abbrev, blurb);
5491 else if (format == 2) {
5492 printf("F\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n",
5493 hfinfo->name, hfinfo->abbrev, enum_name,
5494 parent_hfinfo->abbrev, blurb,
5497 else if (format == 3) {
5498 printf("F\t%s\t%s\t%s\t%s\t%s\t%s\t0x%x\n",
5499 hfinfo->name, hfinfo->abbrev, enum_name,
5500 parent_hfinfo->abbrev, blurb,
5501 base_name, hfinfo->bitmask);
5504 g_assert_not_reached();
5511 hfinfo_numeric_format(header_field_info *hfinfo)
5513 const char *format = NULL;
5515 /* Pick the proper format string */
5516 if (hfinfo->type == FT_FRAMENUM) {
5518 * Frame numbers are always displayed in decimal.
5520 format = "%s == %u";
5522 /* Pick the proper format string, ignoring BASE_RANGE_STRING flag */
5523 switch(hfinfo->display & ~BASE_RANGE_STRING) {
5526 case BASE_OCT: /* I'm lazy */
5528 switch(hfinfo->type) {
5533 format = "%s == %u";
5536 format = "%s == %" G_GINT64_MODIFIER "u";
5542 format = "%s == %d";
5545 format = "%s == %" G_GINT64_MODIFIER "d";
5548 DISSECTOR_ASSERT_NOT_REACHED();
5554 switch(hfinfo->type) {
5556 format = "%s == 0x%02x";
5559 format = "%s == 0x%04x";
5562 format = "%s == 0x%06x";
5565 format = "%s == 0x%08x";
5568 format = "%s == 0x%016" G_GINT64_MODIFIER "x";
5571 DISSECTOR_ASSERT_NOT_REACHED();
5576 DISSECTOR_ASSERT_NOT_REACHED();
5583 /* This function indicates whether it's possible to construct a
5584 * "match selected" display filter string for the specified field,
5585 * returns an indication of whether it's possible, and, if it's
5586 * possible and "filter" is non-null, constructs the filter and
5587 * sets "*filter" to point to it.
5588 * You do not need to [g_]free() this string since it will be automatically
5589 * freed once the next packet is dissected.
5592 construct_match_selected_string(field_info *finfo, epan_dissect_t *edt,
5595 header_field_info *hfinfo;
5601 gint start, length, length_remaining;
5603 gchar is_signed_num = FALSE;
5605 hfinfo = finfo->hfinfo;
5606 DISSECTOR_ASSERT(hfinfo);
5607 abbrev_len = (int) strlen(hfinfo->abbrev);
5609 if (hfinfo->strings && (hfinfo->display & BASE_STRUCTURE_RESET) == BASE_NONE) {
5610 const gchar *str = NULL;
5612 switch(hfinfo->type) {
5618 if (hfinfo->display & BASE_RANGE_STRING) {
5619 str = match_strrval(fvalue_get_sinteger(&finfo->value), hfinfo->strings);
5621 str = match_strval(fvalue_get_sinteger(&finfo->value), hfinfo->strings);
5629 if (hfinfo->display & BASE_RANGE_STRING) {
5630 str = match_strrval(fvalue_get_uinteger(&finfo->value), hfinfo->strings);
5632 str = match_strval(fvalue_get_uinteger(&finfo->value), hfinfo->strings);
5640 if (str != NULL && filter != NULL) {
5641 *filter = ep_strdup_printf("%s == \"%s\"", hfinfo->abbrev, str);
5647 * XXX - we can't use the "val_to_string_repr" and "string_repr_len"
5648 * functions for FT_UINT and FT_INT types, as we choose the base in
5649 * the string expression based on the display base of the field.
5651 * Note that the base does matter, as this is also used for
5652 * the protocolinfo tap.
5654 * It might be nice to use them in "proto_item_fill_label()"
5655 * as well, although, there, you'd have to deal with the base
5656 * *and* with resolved values for addresses.
5658 * Perhaps we need two different val_to_string routines, one
5659 * to generate items for display filters and one to generate
5660 * strings for display, and pass to both of them the
5661 * "display" and "strings" values in the header_field_info
5662 * structure for the field, so they can get the base and,
5663 * if the field is Boolean or an enumerated integer type,
5664 * the tables used to generate human-readable values.
5666 switch(hfinfo->type) {
5672 is_signed_num = TRUE;
5677 if (filter != NULL) {
5678 format = hfinfo_numeric_format(hfinfo);
5680 *filter = ep_strdup_printf(format,
5682 fvalue_get_sinteger(&finfo->value));
5684 *filter = ep_strdup_printf(format,
5686 fvalue_get_uinteger(&finfo->value));
5692 DISSECTOR_ASSERT(!is_signed_num);
5693 if (filter != NULL) {
5694 format = hfinfo_numeric_format(hfinfo);
5695 *filter = ep_strdup_printf(format,
5697 fvalue_get_uinteger(&finfo->value));
5703 if (filter != NULL) {
5704 format = hfinfo_numeric_format(hfinfo);
5705 *filter = ep_strdup_printf(format,
5707 fvalue_get_integer64(&finfo->value));
5713 *filter = ep_strdup(finfo->hfinfo->abbrev);
5718 * If the length is 0, just match the name of the
5721 * (Also check for negative values, just in case,
5722 * as we'll cast it to an unsigned value later.)
5724 length = finfo->length;
5727 *filter = ep_strdup(finfo->hfinfo->abbrev);
5734 * This doesn't have a value, so we'd match
5735 * on the raw bytes at this address.
5737 * Should we be allowed to access to the raw bytes?
5738 * If "edt" is NULL, the answer is "no".
5744 * Is this field part of the raw frame tvbuff?
5745 * If not, we can't use "frame[N:M]" to match
5748 * XXX - should this be frame-relative, or
5749 * protocol-relative?
5751 * XXX - does this fallback for non-registered
5752 * fields even make sense?
5754 if (finfo->ds_tvb != edt->tvb)
5755 return FALSE; /* you lose */
5758 * Don't go past the end of that tvbuff.
5760 length_remaining = tvb_length_remaining(finfo->ds_tvb, finfo->start);
5761 if (length > length_remaining)
5762 length = length_remaining;
5766 if (filter != NULL) {
5767 start = finfo->start;
5768 buf_len = 32 + length * 3;
5769 *filter = ep_alloc0(buf_len);
5772 ptr += g_snprintf(ptr, (gulong) (buf_len-(ptr-*filter)),
5773 "frame[%d:%d] == ", finfo->start, length);
5774 for (i=0;i<length; i++) {
5775 c = tvb_get_guint8(finfo->ds_tvb, start);
5778 ptr += g_snprintf(ptr, (gulong) (buf_len-(ptr-*filter)), "%02x", c);
5781 ptr += g_snprintf(ptr, (gulong) (buf_len-(ptr-*filter)), ":%02x", c);
5788 /* FT_PCRE never appears as a type for a registered field. It is
5789 * only used internally. */
5790 DISSECTOR_ASSERT_NOT_REACHED();
5793 /* By default, use the fvalue's "to_string_repr" method. */
5795 /* Figure out the string length needed.
5796 * The ft_repr length.
5797 * 4 bytes for " == ".
5798 * 1 byte for trailing NUL.
5800 if (filter != NULL) {
5801 dfilter_len = fvalue_string_repr_len(&finfo->value,
5803 dfilter_len += abbrev_len + 4 + 1;
5804 *filter = ep_alloc0(dfilter_len);
5806 /* Create the string */
5807 g_snprintf(*filter, dfilter_len, "%s == ",
5809 fvalue_to_string_repr(&finfo->value,
5811 &(*filter)[abbrev_len + 4]);
5820 * Returns TRUE if we can do a "match selected" on the field, FALSE
5824 proto_can_match_selected(field_info *finfo, epan_dissect_t *edt)
5826 return construct_match_selected_string(finfo, edt, NULL);
5829 /* This function attempts to construct a "match selected" display filter
5830 * string for the specified field; if it can do so, it returns a pointer
5831 * to the string, otherwise it returns NULL.
5833 * The string is allocated with packet lifetime scope.
5834 * You do not need to [g_]free() this string since it will be automatically
5835 * freed once the next packet is dissected.
5838 proto_construct_match_selected_string(field_info *finfo, epan_dissect_t *edt)
5842 if (!construct_match_selected_string(finfo, edt, &filter))
5848 /* This function is common code for both proto_tree_add_bitmask() and
5849 * proto_tree_add_bitmask_text() functions.
5852 proto_item_add_bitmask_tree(proto_item *item, tvbuff_t *tvb, int offset, int len, gint ett,
5853 const int **fields, gboolean little_endian, int flags, gboolean first)
5855 guint32 value = 0, tmpval;
5856 proto_tree *tree = NULL;
5857 header_field_info *hf;
5862 value = tvb_get_guint8(tvb, offset);
5865 value = little_endian ? tvb_get_letohs(tvb, offset) :
5866 tvb_get_ntohs(tvb, offset);
5869 value = little_endian ? tvb_get_letoh24(tvb, offset) :
5870 tvb_get_ntoh24(tvb, offset);
5873 value = little_endian ? tvb_get_letohl(tvb, offset) :
5874 tvb_get_ntohl(tvb, offset);
5877 g_assert_not_reached();
5880 tree = proto_item_add_subtree(item, ett);
5882 proto_tree_add_item(tree, **fields, tvb, offset, len, little_endian);
5883 if (flags & BMT_NO_APPEND) {
5887 hf = proto_registrar_get_nth(**fields);
5888 DISSECTOR_ASSERT(hf->bitmask != 0);
5889 tmpval = (value & hf->bitmask) >> hf->bitshift;
5900 DISSECTOR_ASSERT(len == ftype_length(hf->type));
5902 if (hf->display == BASE_CUSTOM) {
5903 gchar lbl[ITEM_LABEL_LENGTH];
5904 custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hf->strings;
5906 DISSECTOR_ASSERT(fmtfunc);
5907 fmtfunc(lbl, tmpval);
5908 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
5912 else if (hf->strings) {
5913 if (hf->display & BASE_RANGE_STRING) {
5914 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
5915 hf->name, rval_to_str(tmpval, hf->strings, "Unknown"));
5917 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
5918 hf->name, val_to_str(tmpval, cVALS(hf->strings), "Unknown"));
5922 else if (!(flags & BMT_NO_INT)) {
5924 proto_item_append_text(item, ", ");
5927 fmt = IS_FT_INT(hf->type) ? hfinfo_int_format(hf) : hfinfo_uint_format(hf);
5928 if (IS_BASE_DUAL(hf->display)) {
5929 proto_item_append_text(item, fmt, hf->name, tmpval, tmpval);
5931 proto_item_append_text(item, fmt, hf->name, tmpval);
5938 DISSECTOR_ASSERT(len * 8 == hf->display);
5940 if (hf->strings && !(flags & BMT_NO_TFS)) {
5941 /* If we have true/false strings, emit full - otherwise messages
5943 const struct true_false_string *tfs =
5944 (const struct true_false_string *)hf->strings;
5947 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
5948 hf->name, tfs->true_string);
5950 } else if (!(flags & BMT_NO_FALSE)) {
5951 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
5952 hf->name, tfs->false_string);
5955 } else if (hf->bitmask & value) {
5956 /* If the flag is set, show the name */
5957 proto_item_append_text(item, "%s%s", first ? "" : ", ", hf->name);
5962 g_assert_not_reached();
5971 /* This function will dissect a sequence of bytes that describe a
5973 * hf_hdr is a 8/16/24/32 bit integer that describes the bitmask to be dissected.
5974 * This field will form an expansion under which the individual fields of the
5975 * bitmask is dissected and displayed.
5976 * This field must be of the type FT_[U]INT{8|16|24|32}.
5978 * fields is an array of pointers to int that lists all the fields of the
5979 * bitmask. These fields can be either of the type FT_BOOLEAN for flags
5980 * or another integer of the same type/size as hf_hdr with a mask specified.
5981 * This array is terminated by a NULL entry.
5983 * FT_BOOLEAN bits that are set to 1 will have the name added to the expansion.
5984 * FT_integer fields that have a value_string attached will have the
5985 * matched string displayed on the expansion line.
5988 proto_tree_add_bitmask(proto_tree *parent_tree, tvbuff_t *tvb, guint offset, int hf_hdr,
5989 gint ett, const int **fields, gboolean little_endian)
5991 proto_item *item = NULL;
5992 header_field_info *hf;
5995 hf = proto_registrar_get_nth(hf_hdr);
5996 DISSECTOR_ASSERT(IS_FT_INT(hf->type) || IS_FT_UINT(hf->type));
5997 len = ftype_length(hf->type);
6000 item = proto_tree_add_item(parent_tree, hf_hdr, tvb, offset, len, little_endian);
6001 proto_item_add_bitmask_tree(item, tvb, offset, len, ett, fields, little_endian,
6002 BMT_NO_INT|BMT_NO_TFS, FALSE);
6008 /* The same as proto_tree_add_bitmask(), but using an arbitrary text as a top-level item */
6010 proto_tree_add_bitmask_text(proto_tree *parent_tree, tvbuff_t *tvb, guint offset, guint len,
6011 const char *name, const char *fallback,
6012 gint ett, const int **fields, gboolean little_endian, int flags)
6014 proto_item *item = NULL;
6017 item = proto_tree_add_text(parent_tree, tvb, offset, len, "%s", name ? name : "");
6018 if (proto_item_add_bitmask_tree(item, tvb, offset, len, ett, fields, little_endian,
6019 flags, TRUE) && fallback) {
6020 /* Still at first item - append 'fallback' text if any */
6021 proto_item_append_text(item, "%s", fallback);
6029 proto_tree_add_bits_item(proto_tree *tree, int hf_index, tvbuff_t *tvb, gint bit_offset, gint no_of_bits, gboolean little_endian)
6031 return proto_tree_add_bits_ret_val(tree, hf_index, tvb, bit_offset, no_of_bits, NULL, little_endian);
6035 * This function will dissect a sequence of bits that does not need to be byte aligned; the bits
6036 * set vill be shown in the tree as ..10 10.. and the integer value returned if return_value is set.
6037 * Offset should be given in bits from the start of the tvb.
6041 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)
6043 const char *format = NULL;
6047 guint8 remaining_bits;
6048 guint64 mask = 0,tmp;
6050 header_field_info *hf_field;
6055 hf_field = proto_registrar_get_nth(hf_index);
6057 if(hf_field -> bitmask != 0) {
6058 REPORT_DISSECTOR_BUG(ep_strdup_printf("Incompatible use of proto_tree_add_bits_ret_val with field '%s' (%s) with bitmask != 0",
6059 hf_field->abbrev, hf_field->name));
6062 DISSECTOR_ASSERT(bit_offset >= 0);
6063 DISSECTOR_ASSERT(no_of_bits > 0);
6065 /* Byte align offset */
6066 offset = bit_offset>>3;
6069 * Calculate the number of octets used to hold the bits
6071 tot_no_bits = ((bit_offset&0x7)+no_of_bits);
6072 length = tot_no_bits>>3;
6073 remaining_bits = tot_no_bits % 8;
6074 if ((remaining_bits)!=0)
6077 if (no_of_bits < 9){
6078 value = tvb_get_bits8(tvb, bit_offset, no_of_bits);
6079 }else if(no_of_bits < 17){
6080 value = tvb_get_bits16(tvb, bit_offset, no_of_bits, little_endian);
6081 }else if(no_of_bits < 33){
6082 value = tvb_get_bits32(tvb, bit_offset, no_of_bits, little_endian);
6083 }else if(no_of_bits < 65){
6084 value = tvb_get_bits64(tvb, bit_offset, no_of_bits, little_endian);
6086 DISSECTOR_ASSERT_NOT_REACHED();
6091 *return_value=value;
6095 mask = mask << (no_of_bits-1);
6097 /* prepare the string */
6100 for(bit=0;bit<((int)(bit_offset&0x07));bit++){
6101 if(bit&&(!(bit%4))){
6107 /* read the bits for the int */
6108 for(i=0;i<no_of_bits;i++){
6109 if(bit&&(!(bit%4))){
6112 if(bit&&(!(bit%8))){
6126 if(bit&&(!(bit%4))){
6133 strcat(str,hf_field->name);
6135 switch(hf_field->type){
6138 if (hf_field->strings) {
6139 const true_false_string *tfstring =
6140 (const true_false_string *) hf_field->strings;
6141 return proto_tree_add_boolean_format(tree, hf_index, tvb, offset, length, (guint32)value,
6144 (guint32)value ? tfstring->true_string : tfstring->false_string);
6146 return proto_tree_add_boolean_format(tree, hf_index, tvb, offset, length, (guint32)value,
6157 /* 1 - 32 bits field */
6158 if (hf_field->strings) {
6159 return proto_tree_add_uint_format(tree, hf_index, tvb, offset, length, (guint32)value,
6161 str, (hf_field->display & BASE_RANGE_STRING) ?
6162 rval_to_str((guint32)value, hf_field->strings, "Unknown ") :
6163 val_to_str((guint32)value, cVALS(hf_field->strings), "Unknown "),
6167 /* Pick the proper format string */
6168 format = hfinfo_uint_format(hf_field);
6169 if (IS_BASE_DUAL(hf_field->display)) {
6170 return proto_tree_add_uint_format(tree, hf_index, tvb, offset, length, (guint32)value,
6171 format, str, (guint32)value, (guint32)value);
6173 return proto_tree_add_uint_format(tree, hf_index, tvb, offset, length, (guint32)value,
6174 format, str, (guint32)value);
6179 /* Pick the proper format string */
6180 format = hfinfo_uint64_format(hf_field);
6181 if (IS_BASE_DUAL(hf_field->display)) {
6182 return proto_tree_add_uint64_format(tree, hf_index, tvb, offset, length, value,
6183 format, str, value, value);
6185 return proto_tree_add_uint64_format(tree, hf_index, tvb, offset, length, value,
6186 format, str, value);
6191 DISSECTOR_ASSERT_NOT_REACHED();
6198 proto_check_field_name(const gchar *field_name)
6200 return wrs_check_charset(fld_abbrev_chars, field_name);