2 * Routines for protocol tree
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
36 #include "ptvcursor.h"
38 #include "addr_resolv.h"
42 #include "epan_dissect.h"
47 #include "asm_utils.h"
48 #include "column-utils.h"
50 #define SUBTREE_ONCE_ALLOCATION_NUMBER 8
51 #define SUBTREE_MAX_LEVELS 256
54 typedef struct __subtree_lvl {
61 subtree_lvl *pushed_tree;
62 guint8 pushed_tree_index;
63 guint8 pushed_tree_max;
69 /* Candidates for assembler */
71 wrs_count_bitshift(guint32 bitmask)
75 while ((bitmask & (1 << bitshift)) == 0)
82 #define cVALS(x) (const value_string*)(x)
85 #define TRY_TO_FAKE_THIS_ITEM(tree, hfindex) \
86 /* If this item is not referenced we dont have to do much work \
87 at all but we should still return a node so that \
88 field items below this node ( think proto_item_add_subtree() )\
89 will still have somewhere to attach to \
90 or else filtering will not work (they would be ignored since tree\
92 DONT try to fake a node where PITEM_FINFO(pi) is NULL \
93 since dissectors that want to do proto_item_set_len() or \
94 other operations that dereference this would crash. \
95 We dont fake FT_PROTOCOL either since these are cheap and \
96 some stuff (proto hier stat) assumes they always exist. \
98 if(!(PTREE_DATA(tree)->visible)){ \
99 if(PITEM_FINFO(tree)){ \
100 register header_field_info *hfinfo; \
101 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo); \
102 if((hfinfo->ref_count == 0) \
103 && (hfinfo->type!=FT_PROTOCOL)){ \
104 /* just return tree back to the caller */\
110 #define TRY_TO_FAKE_THIS_ITEM(tree, hfindex) ;
114 proto_tree_free_node(proto_node *node, gpointer data);
116 static void fill_label_boolean(field_info *fi, gchar *label_str);
117 static void fill_label_uint(field_info *fi, gchar *label_str);
118 static void fill_label_uint64(field_info *fi, gchar *label_str);
119 static void fill_label_bitfield(field_info *fi, gchar *label_str);
120 static void fill_label_int(field_info *fi, gchar *label_str);
121 static void fill_label_int64(field_info *fi, gchar *label_str);
123 int hfinfo_bitwidth(header_field_info *hfinfo);
124 static const char* hfinfo_uint_vals_format(header_field_info *hfinfo);
125 static const char* hfinfo_uint_format(header_field_info *hfinfo);
126 static const char* hfinfo_uint_value_format(header_field_info *hfinfo);
127 static const char* hfinfo_uint64_format(header_field_info *hfinfo);
128 static const char* hfinfo_int_vals_format(header_field_info *hfinfo);
129 static const char* hfinfo_int_format(header_field_info *hfinfo);
130 static const char* hfinfo_int_value_format(header_field_info *hfinfo);
131 static const char* hfinfo_int64_format(header_field_info *hfinfo);
134 proto_tree_add_node(proto_tree *tree, field_info *fi);
136 static header_field_info *
137 get_hfi_and_length(int hfindex, tvbuff_t *tvb, gint start, gint *length,
141 new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
142 gint start, gint item_length);
145 alloc_field_info(proto_tree *tree, int hfindex, tvbuff_t *tvb,
146 gint start, gint *length);
149 proto_tree_add_pi(proto_tree *tree, int hfindex, tvbuff_t *tvb,
150 gint start, gint *length, field_info **pfi);
153 proto_tree_set_representation_value(proto_item *pi, const char *format, va_list ap);
155 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap);
158 proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb);
160 proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length);
162 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length);
164 proto_tree_set_time(field_info *fi, nstime_t *value_ptr);
166 proto_tree_set_string(field_info *fi, const char* value);
168 proto_tree_set_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
170 proto_tree_set_ebcdic_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
172 proto_tree_set_ether(field_info *fi, const guint8* value);
174 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start);
176 proto_tree_set_ipxnet(field_info *fi, guint32 value);
178 proto_tree_set_ipv4(field_info *fi, guint32 value);
180 proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr);
182 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start);
184 proto_tree_set_guid(field_info *fi, const e_guid_t *value_ptr);
186 proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gboolean little_endian);
188 proto_tree_set_oid(field_info *fi, const guint8* value_ptr, gint length);
190 proto_tree_set_oid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
192 proto_tree_set_boolean(field_info *fi, guint32 value);
194 proto_tree_set_float(field_info *fi, float value);
196 proto_tree_set_double(field_info *fi, double value);
198 proto_tree_set_uint(field_info *fi, guint32 value);
200 proto_tree_set_int(field_info *fi, gint32 value);
202 proto_tree_set_uint64(field_info *fi, guint64 value);
204 proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start, guint length, gboolean little_endian);
206 static int proto_register_field_init(header_field_info *hfinfo, int parent);
208 /* special-case header field used within proto.c */
209 int hf_text_only = -1;
211 /* Structure for information about a protocol */
213 const char *name; /* long description */
214 const char *short_name; /* short description */
215 const char *filter_name; /* name of this protocol in filters */
216 int proto_id; /* field ID for this protocol */
217 GList *fields; /* fields for this protocol */
218 GList *last_field; /* pointer to end of list of fields */
219 gboolean is_enabled; /* TRUE if protocol is enabled */
220 gboolean can_toggle; /* TRUE if is_enabled can be changed */
223 /* List of all protocols */
224 static GList *protocols = NULL;
226 #define INITIAL_NUM_PROTOCOL_HFINFO 200
229 /* Contains information about protocols and header fields. Used when
230 * dissectors register their data */
231 static GMemChunk *gmc_hfinfo = NULL;
233 /* Contains information about a field when a dissector calls
234 * proto_tree_add_item. */
235 SLAB_ITEM_TYPE_DEFINE(field_info)
236 static SLAB_FREE_LIST_DEFINE(field_info)
237 static field_info *field_info_tmp=NULL;
238 #define FIELD_INFO_NEW(fi) \
239 SLAB_ALLOC(fi, field_info)
240 #define FIELD_INFO_FREE(fi) \
241 SLAB_FREE(fi, field_info)
245 /* Contains the space for proto_nodes. */
246 SLAB_ITEM_TYPE_DEFINE(proto_node)
247 static SLAB_FREE_LIST_DEFINE(proto_node)
248 #define PROTO_NODE_NEW(node) \
249 SLAB_ALLOC(node, proto_node) \
250 node->first_child = NULL; \
251 node->last_child = NULL; \
254 #define PROTO_NODE_FREE(node) \
255 SLAB_FREE(node, proto_node)
259 /* String space for protocol and field items for the GUI */
260 SLAB_ITEM_TYPE_DEFINE(item_label_t)
261 static SLAB_FREE_LIST_DEFINE(item_label_t)
262 #define ITEM_LABEL_NEW(il) \
263 SLAB_ALLOC(il, item_label_t)
264 #define ITEM_LABEL_FREE(il) \
265 SLAB_FREE(il, item_label_t)
268 #define PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo) \
269 DISSECTOR_ASSERT((guint)hfindex < gpa_hfinfo.len); \
270 hfinfo=gpa_hfinfo.hfi[hfindex];
273 /* List which stores protocols and fields that have been registered */
274 typedef struct _gpa_hfinfo_t {
276 guint32 allocated_len;
277 header_field_info **hfi;
279 gpa_hfinfo_t gpa_hfinfo;
281 /* Balanced tree of abbreviations and IDs */
282 static GTree *gpa_name_tree = NULL;
283 static header_field_info *same_name_hfinfo;
285 static void save_same_name_hfinfo(gpointer data)
287 same_name_hfinfo = (header_field_info*)data;
290 /* Points to the first element of an array of Booleans, indexed by
291 a subtree item type; that array element is TRUE if subtrees of
292 an item of that type are to be expanded. */
293 gboolean *tree_is_expanded;
295 /* Number of elements in that array. */
298 /* Name hashtables for fast detection of duplicate names */
299 static GHashTable* proto_names = NULL;
300 static GHashTable* proto_short_names = NULL;
301 static GHashTable* proto_filter_names = NULL;
304 proto_compare_name(gconstpointer p1_arg, gconstpointer p2_arg)
306 const protocol_t *p1 = p1_arg;
307 const protocol_t *p2 = p2_arg;
309 return g_ascii_strcasecmp(p1->short_name, p2->short_name);
313 /* initialize data structures and register protocols and fields */
315 proto_init(void (register_all_protocols_func)(register_cb cb, gpointer client_data),
316 void (register_all_handoffs_func)(register_cb cb, gpointer client_data),
318 gpointer client_data)
320 static hf_register_info hf[] = {
322 { "Text item", "", FT_NONE, BASE_NONE, NULL, 0x0,
327 proto_names = g_hash_table_new(g_int_hash, g_int_equal);
328 proto_short_names = g_hash_table_new(wrs_str_hash, g_str_equal);
329 proto_filter_names = g_hash_table_new(wrs_str_hash, g_str_equal);
333 gmc_hfinfo = g_mem_chunk_new("gmc_hfinfo",
334 sizeof(header_field_info),
335 INITIAL_NUM_PROTOCOL_HFINFO * sizeof(header_field_info),
339 gpa_hfinfo.allocated_len=0;
341 gpa_name_tree = g_tree_new_full(wrs_strcmp_with_data, NULL, NULL, save_same_name_hfinfo);
343 /* Initialize the ftype subsystem */
346 /* Register one special-case FT_TEXT_ONLY field for use when
347 converting wireshark to new-style proto_tree. These fields
348 are merely strings on the GUI tree; they are not filterable */
349 proto_register_field_array(-1, hf, array_length(hf));
351 /* Have each built-in dissector register its protocols, fields,
352 dissector tables, and dissectors to be called through a
353 handle, and do whatever one-time initialization it needs to
355 register_all_protocols_func(cb, client_data);
358 /* Now scan for plugins and load all the ones we find, calling
359 their register routines to do the stuff described above. */
361 (*cb)(RA_PLUGIN_REGISTER, NULL, client_data);
363 register_all_plugin_registrations();
366 /* Now call the "handoff registration" routines of all built-in
367 dissectors; those routines register the dissector in other
368 dissectors' handoff tables, and fetch any dissector handles
370 register_all_handoffs_func(cb, client_data);
373 /* Now do the same with plugins. */
375 (*cb)(RA_PLUGIN_HANDOFF, NULL, client_data);
376 register_all_plugin_handoffs();
379 /* sort the protocols by protocol name */
380 protocols = g_list_sort(protocols, proto_compare_name);
382 /* We've assigned all the subtree type values; allocate the array
383 for them, and zero it out. */
384 tree_is_expanded = g_malloc(num_tree_types*sizeof (gboolean));
385 memset(tree_is_expanded, 0, num_tree_types*sizeof (gboolean));
391 /* Free the abbrev/ID GTree */
393 g_tree_destroy(gpa_name_tree);
394 gpa_name_tree = NULL;
398 g_mem_chunk_destroy(gmc_hfinfo);
400 if(gpa_hfinfo.allocated_len){
402 gpa_hfinfo.allocated_len=0;
403 g_free(gpa_hfinfo.hfi);
406 if (tree_is_expanded != NULL)
407 g_free(tree_is_expanded);
412 proto_tree_traverse_pre_order(proto_tree *tree, proto_tree_traverse_func func,
415 proto_node *pnode = tree;
419 if (func(pnode, data))
422 child = pnode->first_child;
423 while (child != NULL) {
425 * The routine we call might modify the child, e.g. by
426 * freeing it, so we get the child's successor before
427 * calling that routine.
430 child = current->next;
431 if (proto_tree_traverse_pre_order((proto_tree *)current, func,
440 proto_tree_traverse_in_order(proto_tree *tree, proto_tree_traverse_func func,
443 proto_node *pnode = tree;
447 child = pnode->first_child;
450 * The routine we call might modify the child, e.g. by
451 * freeing it, so we get the child's successor before
452 * calling that routine.
455 child = current->next;
457 if (proto_tree_traverse_in_order((proto_tree *)current, func,
461 if (func(pnode, data))
464 while (child != NULL) {
466 * The routine we call might modify the child, e.g. by
467 * freeing it, so we get the child's successor before
468 * calling that routine.
471 child = current->next;
472 if (proto_tree_traverse_in_order((proto_tree *)current,
477 if (func(pnode, data))
485 proto_tree_children_foreach(proto_tree *tree, proto_tree_foreach_func func,
488 proto_node *node = tree;
491 node = node->first_child;
492 while (node != NULL) {
494 node = current->next;
495 func((proto_tree *)current, data);
499 /* frees the resources that the dissection a proto_tree uses */
501 proto_tree_free(proto_tree *tree)
503 proto_tree_traverse_in_order(tree, proto_tree_free_node, NULL);
507 free_GPtrArray_value(gpointer key, gpointer value, gpointer user_data _U_)
509 GPtrArray *ptrs = value;
510 gint hfid = (gint)(long)key;
511 header_field_info *hfinfo;
514 PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
515 if(hfinfo->ref_count){
516 /* when a field is referenced by a filter this also
517 affects the refcount for the parent protocol so we need
518 to adjust the refcount for the parent as well
520 if( (hfinfo->parent != -1) && (hfinfo->ref_count) ){
521 header_field_info *parent_hfinfo;
522 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
523 parent_hfinfo->ref_count -= hfinfo->ref_count;
525 hfinfo->ref_count = 0;
528 g_ptr_array_free(ptrs, TRUE);
532 free_node_tree_data(tree_data_t *tree_data)
534 /* Free all the GPtrArray's in the interesting_hfids hash. */
535 g_hash_table_foreach(tree_data->interesting_hfids,
536 free_GPtrArray_value, NULL);
538 /* And then destroy the hash. */
539 g_hash_table_destroy(tree_data->interesting_hfids);
541 /* And finally the tree_data_t itself. */
545 #define FREE_NODE_FIELD_INFO(finfo) \
547 ITEM_LABEL_FREE(finfo->rep); \
549 FVALUE_CLEANUP(&finfo->value); \
550 FIELD_INFO_FREE(finfo);
553 proto_tree_free_node(proto_node *node, gpointer data _U_)
555 field_info *finfo = PITEM_FINFO(node);
558 /* This is the root node. Destroy the per-tree data.
559 * There is no field_info to destroy. */
560 free_node_tree_data(PTREE_DATA(node));
563 /* This is a child node. Don't free the per-tree data, but
564 * do free the field_info data. */
565 FREE_NODE_FIELD_INFO(finfo);
568 /* Free the proto_node. */
569 PROTO_NODE_FREE(node);
571 return FALSE; /* FALSE = do not end traversal of protocol tree */
574 /* Is the parsing being done for a visible proto_tree or an invisible one?
575 * By setting this correctly, the proto_tree creation is sped up by not
576 * having to call g_vsnprintf and copy strings around.
579 proto_tree_set_visible(proto_tree *tree, gboolean visible)
581 PTREE_DATA(tree)->visible = visible;
584 /* Assume dissector set only its protocol fields.
585 This function is called by dissectors and allowes to speed up filtering
586 in wireshark, if this function returns FALSE it is safe to reset tree to NULL
587 and thus skip calling most of the expensive proto_tree_add_...()
589 If the tree is visible we implicitely assume the field is referenced.
592 proto_field_is_referenced(proto_tree *tree, int proto_id)
594 register header_field_info *hfinfo;
600 if (PTREE_DATA(tree)->visible)
603 PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
604 if (hfinfo->ref_count != 0)
611 /* Finds a record in the hf_info_records array by id. */
613 proto_registrar_get_nth(guint hfindex)
615 register header_field_info *hfinfo;
617 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
622 /* Prefix initialization
623 * this allows for a dissector to register a display filter name prefix
624 * so that it can delay the initialization of the hf array as long as
628 /* compute a hash for the part before the dot of a display filter */
629 static guint prefix_hash (gconstpointer key) {
630 /* end the string at the dot and compute its hash */
631 gchar* copy = ep_strdup(key);
641 return g_str_hash(copy);
644 /* are both strings equal up to the end or the dot? */
645 static gboolean prefix_equal (gconstpointer ap,gconstpointer bp) {
653 if ((ac == '.' || ac == '\0') && (bc == '.' || bc == '\0')) return TRUE;
655 if ( (ac == '.' || ac == '\0') && ! (bc == '.' || bc == '\0') ) return FALSE;
656 if ( (bc == '.' || bc == '\0') && ! (ac == '.' || ac == '\0') ) return FALSE;
658 if (ac != bc) return FALSE;
665 /* indexed by prefix, contains initializers */
666 static GHashTable* prefixes = NULL;
669 /* Register a new prefix for "delayed" initialization of field arrays */
671 proto_register_prefix(const char *prefix, prefix_initializer_t pi ) {
673 prefixes = g_hash_table_new(prefix_hash,prefix_equal);
676 g_hash_table_insert(prefixes,(gpointer)prefix,pi);
679 /* helper to call all prefix initializers */
680 static gboolean initialize_prefix(gpointer k, gpointer v, gpointer u _U_) {
681 ((prefix_initializer_t)v)(k);
685 /** Initialize every remaining uninitialized prefix. */
686 void proto_initialize_all_prefixes(void) {
687 g_hash_table_foreach_remove(prefixes, initialize_prefix, NULL);
690 /* Finds a record in the hf_info_records array by name.
691 * If it fails to find it in the already registered fields,
692 * it tries to find and call an initializer in the prefixes
693 * table and if so it looks again.
696 proto_registrar_get_byname(const char *field_name)
698 header_field_info* hfinfo;
699 prefix_initializer_t pi;
701 DISSECTOR_ASSERT(field_name != NULL);
703 hfinfo = g_tree_lookup(gpa_name_tree, field_name);
705 if (hfinfo) return hfinfo;
707 if (!prefixes) return NULL;
709 if(( pi = g_hash_table_lookup(prefixes,field_name) )) {
711 g_hash_table_remove(prefixes,field_name);
716 return g_tree_lookup(gpa_name_tree, field_name);
720 void ptvcursor_new_subtree_levels(ptvcursor_t * ptvc)
722 subtree_lvl * pushed_tree;
724 DISSECTOR_ASSERT(ptvc->pushed_tree_max <= SUBTREE_MAX_LEVELS-SUBTREE_ONCE_ALLOCATION_NUMBER);
725 ptvc->pushed_tree_max += SUBTREE_ONCE_ALLOCATION_NUMBER;
727 pushed_tree = ep_alloc(sizeof(subtree_lvl) * ptvc->pushed_tree_max);
728 DISSECTOR_ASSERT(pushed_tree != NULL);
729 if (ptvc->pushed_tree)
730 memcpy(pushed_tree, ptvc->pushed_tree, ptvc->pushed_tree_max - SUBTREE_ONCE_ALLOCATION_NUMBER);
731 ptvc->pushed_tree = pushed_tree;
734 void ptvcursor_free_subtree_levels(ptvcursor_t * ptvc)
736 ptvc->pushed_tree = NULL;
737 ptvc->pushed_tree_max = 0;
738 DISSECTOR_ASSERT(ptvc->pushed_tree_index ==0);
739 ptvc->pushed_tree_index = 0;
742 /* Allocates an initializes a ptvcursor_t with 3 variables:
743 * proto_tree, tvbuff, and offset. */
745 ptvcursor_new(proto_tree *tree, tvbuff_t *tvb, gint offset)
749 ptvc = ep_alloc(sizeof(ptvcursor_t));
752 ptvc->offset = offset;
753 ptvc->pushed_tree= NULL;
754 ptvc->pushed_tree_max= 0;
755 ptvc->pushed_tree_index= 0;
760 /* Frees memory for ptvcursor_t, but nothing deeper than that. */
762 ptvcursor_free(ptvcursor_t *ptvc)
764 ptvcursor_free_subtree_levels(ptvc);
768 /* Returns tvbuff. */
770 ptvcursor_tvbuff(ptvcursor_t* ptvc)
775 /* Returns current offset. */
777 ptvcursor_current_offset(ptvcursor_t* ptvc)
783 ptvcursor_tree(ptvcursor_t* ptvc)
792 ptvcursor_set_tree(ptvcursor_t* ptvc, proto_tree *tree)
797 /* creates a subtree, sets it as the working tree and pushes the old working tree */
799 ptvcursor_push_subtree(ptvcursor_t *ptvc, proto_item *it, gint ett_subtree)
801 subtree_lvl * subtree;
802 if (ptvc->pushed_tree_index >= ptvc->pushed_tree_max)
803 ptvcursor_new_subtree_levels(ptvc);
805 subtree = ptvc->pushed_tree+ptvc->pushed_tree_index;
806 subtree->tree = ptvc->tree;
808 ptvc->pushed_tree_index++;
809 return ptvcursor_set_subtree(ptvc, it, ett_subtree);
814 ptvcursor_pop_subtree(ptvcursor_t *ptvc)
816 subtree_lvl * subtree;
817 if (ptvc->pushed_tree_index <= 0)
820 ptvc->pushed_tree_index--;
821 subtree = ptvc->pushed_tree+ptvc->pushed_tree_index;
822 if (subtree->it != NULL)
823 proto_item_set_len(subtree->it, ptvcursor_current_offset(ptvc) - subtree->cursor_offset);
824 ptvc->tree = subtree->tree;
827 /* saves the current tvb offset and the item in the current subtree level */
829 ptvcursor_subtree_set_item(ptvcursor_t * ptvc, proto_item * it)
831 subtree_lvl * subtree;
833 DISSECTOR_ASSERT(ptvc->pushed_tree_index > 0);
835 subtree = ptvc->pushed_tree+ptvc->pushed_tree_index-1;
837 subtree->cursor_offset = ptvcursor_current_offset(ptvc);
840 /* Creates a subtree and adds it to the cursor as the working tree but does not
841 * save the old working tree */
843 ptvcursor_set_subtree(ptvcursor_t *ptvc, proto_item *it, gint ett_subtree)
845 ptvc->tree = proto_item_add_subtree(it, ett_subtree);
849 proto_tree* ptvcursor_add_subtree_item(ptvcursor_t * ptvc, proto_item * it, gint ett_subtree, gint length)
851 ptvcursor_push_subtree(ptvc, it, ett_subtree);
852 if (length == SUBTREE_UNDEFINED_LENGTH)
853 ptvcursor_subtree_set_item(ptvc, it);
854 return ptvcursor_tree(ptvc);
857 /* Add an item to the tree and create a subtree
858 * If the length is unknown, length may be defined as SUBTREE_UNDEFINED_LENGTH.
859 * In this case, when the subtree will be closed, the parent item length will
860 * be equal to the advancement of the cursor since the creation of the subtree.
862 proto_tree* ptvcursor_add_with_subtree(ptvcursor_t * ptvc, int hfindex, gint length,
863 gboolean little_endian, gint ett_subtree)
866 it = ptvcursor_add_no_advance(ptvc, hfindex, length, little_endian);
867 return ptvcursor_add_subtree_item(ptvc, it, ett_subtree, length);
871 proto_tree_add_text_node(proto_tree *tree, tvbuff_t *tvb, gint start, gint length);
873 /* Add a text node to the tree and create a subtree
874 * If the length is unknown, length may be defined as SUBTREE_UNDEFINED_LENGTH.
875 * In this case, when the subtree will be closed, the item length will be equal
876 * to the advancement of the cursor since the creation of the subtree.
878 proto_tree * ptvcursor_add_text_with_subtree(ptvcursor_t * ptvc, gint length,
879 gint ett_subtree, const char *format, ...)
884 it = proto_tree_add_text_node(ptvcursor_tree(ptvc), ptvcursor_tvbuff(ptvc),
885 ptvcursor_current_offset(ptvc), length);
887 va_start(ap, format);
888 proto_tree_set_representation(it, format, ap);
891 return ptvcursor_add_subtree_item(ptvc, it, ett_subtree, length);
894 /* Add a text-only node, leaving it to our caller to fill the text in */
896 proto_tree_add_text_node(proto_tree *tree, tvbuff_t *tvb, gint start, gint length)
900 pi = proto_tree_add_pi(tree, hf_text_only, tvb, start, &length, NULL);
907 /* Add a text-only node to the proto_tree */
909 proto_tree_add_text(proto_tree *tree, tvbuff_t *tvb, gint start, gint length,
910 const char *format, ...)
915 pi = proto_tree_add_text_node(tree, tvb, start, length);
919 va_start(ap, format);
920 proto_tree_set_representation(pi, format, ap);
926 /* Add a text-only node to the proto_tree (va_list version) */
928 proto_tree_add_text_valist(proto_tree *tree, tvbuff_t *tvb, gint start,
929 gint length, const char *format, va_list ap)
933 pi = proto_tree_add_text_node(tree, tvb, start, length);
937 proto_tree_set_representation(pi, format, ap);
942 /* Add a text-only node for debugging purposes. The caller doesn't need
943 * to worry about tvbuff, start, or length. Debug message gets sent to
946 proto_tree_add_debug_text(proto_tree *tree, const char *format, ...)
951 pi = proto_tree_add_text_node(tree, NULL, 0, 0);
953 va_start(ap, format);
955 proto_tree_set_representation(pi, format, ap);
965 get_uint_value(tvbuff_t *tvb, gint offset, gint length, gboolean little_endian)
972 value = tvb_get_guint8(tvb, offset);
976 value = little_endian ? tvb_get_letohs(tvb, offset)
977 : tvb_get_ntohs(tvb, offset);
981 value = little_endian ? tvb_get_letoh24(tvb, offset)
982 : tvb_get_ntoh24(tvb, offset);
986 value = little_endian ? tvb_get_letohl(tvb, offset)
987 : tvb_get_ntohl(tvb, offset);
991 DISSECTOR_ASSERT_NOT_REACHED();
999 get_int_value(tvbuff_t *tvb, gint offset, gint length, gboolean little_endian)
1006 value = (gint8)tvb_get_guint8(tvb, offset);
1010 value = (gint16) (little_endian ? tvb_get_letohs(tvb, offset)
1011 : tvb_get_ntohs(tvb, offset));
1015 value = little_endian ? tvb_get_letoh24(tvb, offset)
1016 : tvb_get_ntoh24(tvb, offset);
1017 if (value & 0x00800000) {
1018 /* Sign bit is set; sign-extend it. */
1019 value |= 0xFF000000;
1024 value = little_endian ? tvb_get_letohl(tvb, offset)
1025 : tvb_get_ntohl(tvb, offset);
1029 DISSECTOR_ASSERT_NOT_REACHED();
1036 /* Add an item to a proto_tree, using the text label registered to that item;
1037 the item is extracted from the tvbuff handed to it. */
1039 proto_tree_new_item(field_info *new_fi, proto_tree *tree, int hfindex,
1040 tvbuff_t *tvb, gint start, gint length, gboolean little_endian)
1050 /* there is a possibility here that we might raise an exception
1051 * and thus would lose track of the field_info.
1052 * store it in a temp so that if we come here again we can reclaim
1053 * the field_info without leaking memory.
1055 /* XXX this only keeps track of one field_info struct,
1056 if we ever go multithreaded for calls to this function
1057 we have to change this code to use per thread variable.
1060 /* oops, last one we got must have been lost due
1062 * good thing we saved it, now we can reverse the
1063 * memory leak and reclaim it.
1065 SLAB_FREE(field_info_tmp, field_info);
1067 /* we might throw an exception, keep track of this one
1068 * across the "dangerous" section below.
1070 field_info_tmp=new_fi;
1072 switch(new_fi->hfinfo->type) {
1074 /* no value to set for FT_NONE */
1078 proto_tree_set_protocol_tvb(new_fi, tvb);
1082 proto_tree_set_bytes_tvb(new_fi, tvb, start, length);
1086 n = get_uint_value(tvb, start, length, little_endian);
1087 proto_tree_set_bytes_tvb(new_fi, tvb, start + length, n);
1089 /* Instead of calling proto_item_set_len(), since we don't yet
1090 * have a proto_item, we set the field_info's length ourselves. */
1091 new_fi->length = n + length;
1095 proto_tree_set_boolean(new_fi,
1096 get_uint_value(tvb, start, length, little_endian));
1099 /* XXX - make these just FT_UINT? */
1104 proto_tree_set_uint(new_fi,
1105 get_uint_value(tvb, start, length, little_endian));
1110 DISSECTOR_ASSERT( length <= 8 && length >= 1);
1111 proto_tree_set_uint64_tvb(new_fi, tvb, start, length, little_endian);
1114 /* XXX - make these just FT_INT? */
1119 proto_tree_set_int(new_fi,
1120 get_int_value(tvb, start, length, little_endian));
1124 DISSECTOR_ASSERT(length == 4);
1125 value = tvb_get_ipv4(tvb, start);
1126 proto_tree_set_ipv4(new_fi, little_endian ? GUINT32_SWAP_LE_BE(value) : value);
1130 DISSECTOR_ASSERT(length == 4);
1131 proto_tree_set_ipxnet(new_fi,
1132 get_uint_value(tvb, start, 4, FALSE));
1136 DISSECTOR_ASSERT(length == 16);
1137 proto_tree_set_ipv6_tvb(new_fi, tvb, start);
1141 DISSECTOR_ASSERT(length == 6);
1142 proto_tree_set_ether_tvb(new_fi, tvb, start);
1146 DISSECTOR_ASSERT(length == 16);
1147 proto_tree_set_guid_tvb(new_fi, tvb, start, little_endian);
1151 proto_tree_set_oid_tvb(new_fi, tvb, start, length);
1155 DISSECTOR_ASSERT(length == 4);
1157 floatval = tvb_get_letohieee_float(tvb, start);
1159 floatval = tvb_get_ntohieee_float(tvb, start);
1160 proto_tree_set_float(new_fi, floatval);
1164 DISSECTOR_ASSERT(length == 8);
1166 doubleval = tvb_get_letohieee_double(tvb, start);
1168 doubleval = tvb_get_ntohieee_double(tvb, start);
1169 proto_tree_set_double(new_fi, doubleval);
1173 proto_tree_set_string_tvb(new_fi, tvb, start, length);
1177 DISSECTOR_ASSERT(length >= -1);
1178 /* Instead of calling proto_item_set_len(),
1179 * since we don't yet have a proto_item, we
1180 * set the field_info's length ourselves.
1182 * XXX - our caller can't use that length to
1183 * advance an offset unless they arrange that
1184 * there always be a protocol tree into which
1185 * we're putting this item.
1188 /* This can throw an exception */
1189 length = tvb_strsize(tvb, start);
1191 string = ep_alloc(length);
1193 tvb_memcpy(tvb, string, start, length);
1194 } else if (length == 0) {
1197 /* In this case, length signifies
1198 * the length of the string.
1200 * This could either be a null-padded
1201 * string, which doesn't necessarily
1202 * have a '\0' at the end, or a
1203 * null-terminated string, with a
1204 * trailing '\0'. (Yes, there are
1205 * cases where you have a string
1206 * that's both counted and null-
1209 * In the first case, we must
1210 * allocate a buffer of length
1211 * "length+1", to make room for
1214 * In the second case, we don't
1215 * assume that there is a trailing
1216 * '\0' there, as the packet might
1217 * be malformed. (XXX - should we
1218 * throw an exception if there's no
1219 * trailing '\0'?) Therefore, we
1220 * allocate a buffer of length
1221 * "length+1", and put in a trailing
1222 * '\0', just to be safe.
1224 * (XXX - this would change if
1225 * we made string values counted
1226 * rather than null-terminated.)
1228 string = tvb_get_ephemeral_string(tvb,
1232 new_fi->length = length;
1233 proto_tree_set_string(new_fi, string);
1237 proto_tree_set_ebcdic_string_tvb(new_fi, tvb, start, length);
1240 case FT_UINT_STRING:
1241 n = get_uint_value(tvb, start, length, little_endian);
1242 proto_tree_set_string_tvb(new_fi, tvb, start + length, n);
1244 /* Instead of calling proto_item_set_len(), since we
1245 * don't yet have a proto_item, we set the
1246 * field_info's length ourselves.
1248 * XXX - our caller can't use that length to
1249 * advance an offset unless they arrange that
1250 * there always be a protocol tree into which
1251 * we're putting this item.
1253 new_fi->length = n + length;
1257 g_error("new_fi->hfinfo->type %d (%s) not handled\n",
1258 new_fi->hfinfo->type,
1259 ftype_name(new_fi->hfinfo->type));
1260 DISSECTOR_ASSERT_NOT_REACHED();
1264 /* Don't add new node to proto_tree until now so that any exceptions
1265 * raised by a tvbuff access method doesn't leave junk in the proto_tree. */
1266 pi = proto_tree_add_node(tree, new_fi);
1268 /* we did not raise an exception so we dont have to remember this
1269 * field_info struct any more.
1271 field_info_tmp=NULL;
1273 /* If the proto_tree wants to keep a record of this finfo
1274 * for quick lookup, then record it. */
1275 if (new_fi->hfinfo->ref_count) {
1277 hash = PTREE_DATA(tree)->interesting_hfids;
1278 ptrs = g_hash_table_lookup(hash, GINT_TO_POINTER(hfindex));
1280 g_ptr_array_add(ptrs, new_fi);
1287 /* Gets data from tvbuff, adds it to proto_tree, increments offset,
1288 and returns proto_item* */
1290 ptvcursor_add(ptvcursor_t *ptvc, int hfindex, gint length,
1291 gboolean little_endian)
1294 header_field_info *hfinfo;
1299 offset = ptvc->offset;
1300 hfinfo = get_hfi_and_length(hfindex, ptvc->tvb, offset, &length,
1302 ptvc->offset += length;
1303 if (hfinfo->type == FT_UINT_BYTES || hfinfo->type == FT_UINT_STRING) {
1305 * The length of the rest of the item is in the first N
1306 * bytes of the item.
1308 n = get_uint_value(ptvc->tvb, offset, length, little_endian);
1311 if (ptvc->tree == NULL)
1314 TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfindex);
1316 new_fi = new_field_info(ptvc->tree, hfinfo, ptvc->tvb, offset,
1321 return proto_tree_new_item(new_fi, ptvc->tree, hfindex, ptvc->tvb,
1322 offset, length, little_endian);
1325 /* Add an item to a proto_tree, using the text label registered to that item;
1326 the item is extracted from the tvbuff handed to it. */
1328 proto_tree_add_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1329 gint start, gint length, gboolean little_endian)
1336 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1338 new_fi = alloc_field_info(tree, hfindex, tvb, start, &length);
1343 return proto_tree_new_item(new_fi, tree, hfindex, tvb, start,
1344 length, little_endian);
1347 /* Add a FT_NONE to a proto_tree */
1349 proto_tree_add_none_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1350 gint length, const char *format, ...)
1354 header_field_info *hfinfo;
1359 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1360 DISSECTOR_ASSERT(hfinfo->type == FT_NONE);
1362 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, NULL);
1364 va_start(ap, format);
1365 proto_tree_set_representation(pi, format, ap);
1368 /* no value to set for FT_NONE */
1372 /* Gets data from tvbuff, adds it to proto_tree, *DOES NOT* increment
1373 * offset, and returns proto_item* */
1375 ptvcursor_add_no_advance(ptvcursor_t* ptvc, int hf, gint length,
1376 gboolean endianness)
1380 item = proto_tree_add_item(ptvc->tree, hf, ptvc->tvb, ptvc->offset,
1381 length, endianness);
1386 /* Advance the ptvcursor's offset within its tvbuff without
1387 * adding anything to the proto_tree. */
1389 ptvcursor_advance(ptvcursor_t* ptvc, gint length)
1391 ptvc->offset += length;
1396 proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb)
1398 fvalue_set(&fi->value, tvb, TRUE);
1401 /* Add a FT_PROTOCOL to a proto_tree */
1403 proto_tree_add_protocol_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1404 gint length, const char *format, ...)
1408 header_field_info *hfinfo;
1414 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1415 DISSECTOR_ASSERT(hfinfo->type == FT_PROTOCOL);
1417 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1419 va_start(ap, format);
1420 proto_tree_set_representation(pi, format, ap);
1424 proto_tree_set_protocol_tvb(new_fi, tvb);
1427 proto_tree_set_protocol_tvb(new_fi, NULL);
1433 /* Add a FT_BYTES to a proto_tree */
1435 proto_tree_add_bytes(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1436 gint length, const guint8 *start_ptr)
1440 header_field_info *hfinfo;
1445 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1447 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1448 DISSECTOR_ASSERT(hfinfo->type == FT_BYTES);
1450 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1451 proto_tree_set_bytes(new_fi, start_ptr, length);
1457 proto_tree_add_bytes_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1458 gint start, gint length, const guint8 *start_ptr,
1459 const char *format, ...)
1464 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length, start_ptr);
1468 va_start(ap, format);
1469 proto_tree_set_representation_value(pi, format, ap);
1476 proto_tree_add_bytes_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1477 gint length, const guint8 *start_ptr, const char *format, ...)
1482 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length, start_ptr);
1486 va_start(ap, format);
1487 proto_tree_set_representation(pi, format, ap);
1494 proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length)
1498 bytes = g_byte_array_new();
1500 g_byte_array_append(bytes, start_ptr, length);
1502 col_custom_set_fstr(fi->hfinfo, "%s", bytes_to_str(bytes->data,
1504 fvalue_set(&fi->value, bytes, TRUE);
1509 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length)
1511 proto_tree_set_bytes(fi, tvb_get_ptr(tvb, offset, length), length);
1514 /* Add a FT_*TIME to a proto_tree */
1516 proto_tree_add_time(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1517 nstime_t *value_ptr)
1521 header_field_info *hfinfo;
1526 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1528 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1529 DISSECTOR_ASSERT(hfinfo->type == FT_ABSOLUTE_TIME ||
1530 hfinfo->type == FT_RELATIVE_TIME);
1532 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1533 proto_tree_set_time(new_fi, value_ptr);
1539 proto_tree_add_time_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1540 gint start, gint length, nstime_t *value_ptr,
1541 const char *format, ...)
1546 pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
1550 va_start(ap, format);
1551 proto_tree_set_representation_value(pi, format, ap);
1558 proto_tree_add_time_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1559 nstime_t *value_ptr, const char *format, ...)
1564 pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
1568 va_start(ap, format);
1569 proto_tree_set_representation(pi, format, ap);
1575 /* Set the FT_*TIME value */
1577 proto_tree_set_time(field_info *fi, nstime_t *value_ptr)
1579 header_field_info *hfinfo;
1581 DISSECTOR_ASSERT(value_ptr != NULL);
1582 hfinfo = fi->hfinfo;
1584 if (hfinfo->type == FT_ABSOLUTE_TIME) {
1585 col_custom_set_fstr(fi->hfinfo, "%s", abs_time_to_str(value_ptr));
1586 } else if (hfinfo->type == FT_RELATIVE_TIME) {
1587 col_custom_set_fstr(fi->hfinfo, "%s", rel_time_to_secs_str(value_ptr));
1589 fvalue_set(&fi->value, value_ptr, FALSE);
1592 /* Add a FT_IPXNET to a proto_tree */
1594 proto_tree_add_ipxnet(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1599 header_field_info *hfinfo;
1604 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1606 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1607 DISSECTOR_ASSERT(hfinfo->type == FT_IPXNET);
1609 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1610 proto_tree_set_ipxnet(new_fi, value);
1616 proto_tree_add_ipxnet_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1617 gint start, gint length, guint32 value, const char *format, ...)
1622 pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
1626 va_start(ap, format);
1627 proto_tree_set_representation_value(pi, format, ap);
1634 proto_tree_add_ipxnet_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1635 guint32 value, const char *format, ...)
1640 pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
1644 va_start(ap, format);
1645 proto_tree_set_representation(pi, format, ap);
1651 /* Set the FT_IPXNET value */
1653 proto_tree_set_ipxnet(field_info *fi, guint32 value)
1655 fvalue_set_uinteger(&fi->value, value);
1658 /* Add a FT_IPv4 to a proto_tree */
1660 proto_tree_add_ipv4(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1665 header_field_info *hfinfo;
1670 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1672 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1673 DISSECTOR_ASSERT(hfinfo->type == FT_IPv4);
1675 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1676 proto_tree_set_ipv4(new_fi, value);
1682 proto_tree_add_ipv4_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1683 gint start, gint length, guint32 value, const char *format, ...)
1688 pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
1692 va_start(ap, format);
1693 proto_tree_set_representation_value(pi, format, ap);
1700 proto_tree_add_ipv4_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1701 guint32 value, const char *format, ...)
1706 pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
1710 va_start(ap, format);
1711 proto_tree_set_representation(pi, format, ap);
1717 /* Set the FT_IPv4 value */
1719 proto_tree_set_ipv4(field_info *fi, guint32 value)
1721 col_custom_set_fstr(fi->hfinfo, "%s",
1722 ip_to_str((guint8 *)&value));
1723 fvalue_set_uinteger(&fi->value, value);
1726 /* Add a FT_IPv6 to a proto_tree */
1728 proto_tree_add_ipv6(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1729 const guint8* value_ptr)
1733 header_field_info *hfinfo;
1738 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1740 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1741 DISSECTOR_ASSERT(hfinfo->type == FT_IPv6);
1743 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1744 proto_tree_set_ipv6(new_fi, value_ptr);
1750 proto_tree_add_ipv6_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1751 gint start, gint length, const guint8* value_ptr,
1752 const char *format, ...)
1757 pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
1761 va_start(ap, format);
1762 proto_tree_set_representation_value(pi, format, ap);
1769 proto_tree_add_ipv6_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1770 const guint8* value_ptr, const char *format, ...)
1775 pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
1779 va_start(ap, format);
1780 proto_tree_set_representation(pi, format, ap);
1786 /* Set the FT_IPv6 value */
1788 proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr)
1790 DISSECTOR_ASSERT(value_ptr != NULL);
1791 fvalue_set(&fi->value, (gpointer) value_ptr, FALSE);
1795 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start)
1797 proto_tree_set_ipv6(fi, tvb_get_ptr(tvb, start, 16));
1800 /* Add a FT_GUID to a proto_tree */
1802 proto_tree_add_guid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1803 const e_guid_t *value_ptr)
1807 header_field_info *hfinfo;
1812 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1814 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1815 DISSECTOR_ASSERT(hfinfo->type == FT_GUID);
1817 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1818 proto_tree_set_guid(new_fi, value_ptr);
1824 proto_tree_add_guid_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1825 gint start, gint length, const e_guid_t *value_ptr,
1826 const char *format, ...)
1831 pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
1835 va_start(ap, format);
1836 proto_tree_set_representation_value(pi, format, ap);
1843 proto_tree_add_guid_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1844 const e_guid_t *value_ptr, const char *format, ...)
1849 pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
1853 va_start(ap, format);
1854 proto_tree_set_representation(pi, format, ap);
1860 /* Set the FT_GUID value */
1862 proto_tree_set_guid(field_info *fi, const e_guid_t *value_ptr)
1864 DISSECTOR_ASSERT(value_ptr != NULL);
1865 col_custom_set_fstr(fi->hfinfo, "%s",
1866 guid_to_str(value_ptr));
1867 fvalue_set(&fi->value, (gpointer) value_ptr, FALSE);
1871 proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gboolean little_endian)
1875 tvb_get_guid(tvb, start, &guid, little_endian);
1876 proto_tree_set_guid(fi, &guid);
1879 /* Add a FT_OID to a proto_tree */
1881 proto_tree_add_oid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1882 const guint8* value_ptr)
1886 header_field_info *hfinfo;
1891 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1893 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1894 DISSECTOR_ASSERT(hfinfo->type == FT_OID);
1896 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1897 proto_tree_set_oid(new_fi, value_ptr, length);
1903 proto_tree_add_oid_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1904 gint start, gint length, const guint8* value_ptr,
1905 const char *format, ...)
1910 pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
1914 va_start(ap, format);
1915 proto_tree_set_representation_value(pi, format, ap);
1922 proto_tree_add_oid_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1923 const guint8* value_ptr, const char *format, ...)
1928 pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
1932 va_start(ap, format);
1933 proto_tree_set_representation(pi, format, ap);
1939 /* Set the FT_OID value */
1941 proto_tree_set_oid(field_info *fi, const guint8* value_ptr, gint length)
1945 DISSECTOR_ASSERT(value_ptr != NULL);
1947 bytes = g_byte_array_new();
1949 g_byte_array_append(bytes, value_ptr, length);
1951 col_custom_set_fstr(fi->hfinfo, "%s",
1952 oid_resolved_from_encoded(value_ptr, length));
1953 fvalue_set(&fi->value, bytes, TRUE);
1957 proto_tree_set_oid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
1959 proto_tree_set_oid(fi, tvb_get_ptr(tvb, start, length), length);
1963 proto_tree_set_uint64(field_info *fi, guint64 value)
1965 col_custom_set_fstr(fi->hfinfo, "%" G_GINT64_MODIFIER "u",
1967 fvalue_set_integer64(&fi->value, value);
1971 proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start, guint length, gboolean little_endian)
1974 guint8* b = ep_tvb_memdup(tvb,start,length);
1979 default: DISSECTOR_ASSERT_NOT_REACHED();
1980 case 8: value <<= 8; value += *--b;
1981 case 7: value <<= 8; value += *--b;
1982 case 6: value <<= 8; value += *--b;
1983 case 5: value <<= 8; value += *--b;
1984 case 4: value <<= 8; value += *--b;
1985 case 3: value <<= 8; value += *--b;
1986 case 2: value <<= 8; value += *--b;
1987 case 1: value <<= 8; value += *--b;
1992 default: DISSECTOR_ASSERT_NOT_REACHED();
1993 case 8: value <<= 8; value += *b++;
1994 case 7: value <<= 8; value += *b++;
1995 case 6: value <<= 8; value += *b++;
1996 case 5: value <<= 8; value += *b++;
1997 case 4: value <<= 8; value += *b++;
1998 case 3: value <<= 8; value += *b++;
1999 case 2: value <<= 8; value += *b++;
2000 case 1: value <<= 8; value += *b++;
2005 proto_tree_set_uint64(fi, value);
2008 /* Add a FT_STRING or FT_STRINGZ to a proto_tree. Creates own copy of string,
2009 * and frees it when the proto_tree is destroyed. */
2011 proto_tree_add_string(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2012 gint length, const char* value)
2016 header_field_info *hfinfo;
2021 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
2023 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2024 DISSECTOR_ASSERT(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ);
2026 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2027 DISSECTOR_ASSERT(length >= 0);
2028 proto_tree_set_string(new_fi, value);
2034 proto_tree_add_string_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2035 gint start, gint length, const char* value, const char *format,
2041 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
2045 va_start(ap, format);
2046 proto_tree_set_representation_value(pi, format, ap);
2053 proto_tree_add_string_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2054 gint length, const char* value, const char *format, ...)
2059 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
2063 va_start(ap, format);
2064 proto_tree_set_representation(pi, format, ap);
2070 /* Appends string data to a FT_STRING or FT_STRINGZ, allowing progressive
2071 * field info update instead of only updating the representation as does
2072 * proto_item_append_text()
2074 /* NOTE: this function will break with the TRY_TO_FAKE_THIS_ITEM()
2075 * speed optimization.
2076 * Currently only WSP use this function so it is not that bad but try to
2077 * avoid using this one if possible.
2078 * IF you must use this function you MUST also disable the
2079 * TRY_TO_FAKE_THIS_ITEM() optimization for your dissector/function
2080 * using proto_item_append_string().
2081 * Do that by faking that the tree is visible by calling
2082 * proto_tree_set_visible(tree, TRUE) (see packet-wsp.c)
2083 * BEFORE you create the item you are later going to use
2084 * proto_item_append_string() on.
2087 proto_item_append_string(proto_item *pi, const char *str)
2090 header_field_info *hfinfo;
2091 gchar *old_str, *new_str;
2098 fi = PITEM_FINFO(pi);
2099 hfinfo = fi->hfinfo;
2100 if (hfinfo->type == FT_PROTOCOL) {
2101 /* TRY_TO_FAKE_THIS_ITEM() speed optimization: silently skip */
2104 DISSECTOR_ASSERT(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ);
2105 old_str = fvalue_get(&fi->value);
2106 new_str = ep_strdup_printf("%s%s", old_str, str);
2107 fvalue_set(&fi->value, new_str, FALSE);
2110 /* Set the FT_STRING value */
2112 proto_tree_set_string(field_info *fi, const char* value)
2115 col_custom_set_fstr(fi->hfinfo, "%s",
2116 format_text(value, strlen(value)));
2117 fvalue_set(&fi->value, (gpointer) value, FALSE);
2119 col_custom_set_fstr(fi->hfinfo, "[ Null ]");
2120 fvalue_set(&fi->value, (gpointer) "[ Null ]", FALSE);
2125 proto_tree_set_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
2130 length = tvb_ensure_length_remaining(tvb, start);
2133 string = tvb_get_ephemeral_string(tvb, start, length);
2134 proto_tree_set_string(fi, string);
2138 proto_tree_set_ebcdic_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
2143 length = tvb_ensure_length_remaining(tvb, start);
2146 string = tvb_get_ephemeral_string(tvb, start, length);
2147 EBCDIC_to_ASCII(string, length);
2148 proto_tree_set_string(fi, string);
2151 /* Add a FT_ETHER to a proto_tree */
2153 proto_tree_add_ether(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2154 const guint8* value)
2158 header_field_info *hfinfo;
2163 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
2165 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2166 DISSECTOR_ASSERT(hfinfo->type == FT_ETHER);
2168 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2169 proto_tree_set_ether(new_fi, value);
2175 proto_tree_add_ether_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2176 gint start, gint length, const guint8* value,
2177 const char *format, ...)
2182 pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
2186 va_start(ap, format);
2187 proto_tree_set_representation_value(pi, format, ap);
2194 proto_tree_add_ether_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2195 const guint8* value, const char *format, ...)
2200 pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
2204 va_start(ap, format);
2205 proto_tree_set_representation(pi, format, ap);
2211 /* Set the FT_ETHER value */
2213 proto_tree_set_ether(field_info *fi, const guint8* value)
2215 col_custom_set_fstr(fi->hfinfo, "%s", bytes_to_str_punct(value, 6, ':'));
2216 fvalue_set(&fi->value, (gpointer) value, FALSE);
2220 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start)
2222 proto_tree_set_ether(fi, tvb_get_ptr(tvb, start, 6));
2225 /* Add a FT_BOOLEAN to a proto_tree */
2227 proto_tree_add_boolean(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2232 header_field_info *hfinfo;
2237 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
2239 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2240 DISSECTOR_ASSERT(hfinfo->type == FT_BOOLEAN);
2242 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2243 proto_tree_set_boolean(new_fi, value);
2249 proto_tree_add_boolean_format_value(proto_tree *tree, int hfindex,
2250 tvbuff_t *tvb, gint start, gint length, guint32 value,
2251 const char *format, ...)
2256 pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
2260 va_start(ap, format);
2261 proto_tree_set_representation_value(pi, format, ap);
2268 proto_tree_add_boolean_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2269 guint32 value, const char *format, ...)
2274 pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
2278 va_start(ap, format);
2279 proto_tree_set_representation(pi, format, ap);
2285 /* Set the FT_BOOLEAN value */
2287 proto_tree_set_boolean(field_info *fi, guint32 value)
2289 proto_tree_set_uint(fi, value);
2292 /* Add a FT_FLOAT to a proto_tree */
2294 proto_tree_add_float(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2299 header_field_info *hfinfo;
2304 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
2306 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2307 DISSECTOR_ASSERT(hfinfo->type == FT_FLOAT);
2309 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2310 proto_tree_set_float(new_fi, value);
2316 proto_tree_add_float_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2317 gint start, gint length, float value, const char *format, ...)
2322 pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
2326 va_start(ap, format);
2327 proto_tree_set_representation_value(pi, format, ap);
2334 proto_tree_add_float_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2335 float value, const char *format, ...)
2340 pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
2344 va_start(ap, format);
2345 proto_tree_set_representation(pi, format, ap);
2351 /* Set the FT_FLOAT value */
2353 proto_tree_set_float(field_info *fi, float value)
2355 col_custom_set_fstr(fi->hfinfo, "%." STRINGIFY(FLT_DIG) "f",
2357 fvalue_set_floating(&fi->value, value);
2360 /* Add a FT_DOUBLE to a proto_tree */
2362 proto_tree_add_double(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2367 header_field_info *hfinfo;
2372 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
2374 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2375 DISSECTOR_ASSERT(hfinfo->type == FT_DOUBLE);
2377 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2378 proto_tree_set_double(new_fi, value);
2384 proto_tree_add_double_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2385 gint start, gint length, double value, const char *format, ...)
2390 pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
2394 va_start(ap, format);
2395 proto_tree_set_representation_value(pi, format, ap);
2402 proto_tree_add_double_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2403 double value, const char *format, ...)
2408 pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
2412 va_start(ap, format);
2413 proto_tree_set_representation(pi, format, ap);
2419 /* Set the FT_DOUBLE value */
2421 proto_tree_set_double(field_info *fi, double value)
2423 col_custom_set_fstr(fi->hfinfo, "%." STRINGIFY(DBL_DIG) "g",
2425 fvalue_set_floating(&fi->value, value);
2428 /* Add FT_UINT{8,16,24,32} to a proto_tree */
2430 proto_tree_add_uint(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2433 proto_item *pi = NULL;
2435 header_field_info *hfinfo;
2440 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
2442 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2443 switch(hfinfo->type) {
2449 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length,
2451 proto_tree_set_uint(new_fi, value);
2455 DISSECTOR_ASSERT_NOT_REACHED();
2462 proto_tree_add_uint_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2463 gint start, gint length, guint32 value, const char *format, ...)
2468 pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
2472 va_start(ap, format);
2473 proto_tree_set_representation_value(pi, format, ap);
2480 proto_tree_add_uint_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2481 guint32 value, const char *format, ...)
2486 pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
2490 va_start(ap, format);
2491 proto_tree_set_representation(pi, format, ap);
2497 /* Set the FT_UINT{8,16,24,32} value */
2499 proto_tree_set_uint(field_info *fi, guint32 value)
2501 header_field_info *hfinfo;
2504 hfinfo = fi->hfinfo;
2507 if (hfinfo->bitmask) {
2508 /* Mask out irrelevant portions */
2509 integer &= hfinfo->bitmask;
2512 if (hfinfo->bitshift > 0) {
2513 integer >>= hfinfo->bitshift;
2517 if (hfinfo->type == FT_BOOLEAN) {
2518 const true_false_string *tfstring = &tfs_true_false;
2519 if (hfinfo->strings) {
2520 tfstring = (const struct true_false_string*) hfinfo->strings;
2522 col_custom_set_fstr(fi->hfinfo, "%s", integer ? tfstring->true_string : tfstring->false_string);
2523 } else if (hfinfo->strings) {
2524 col_custom_set_fstr(fi->hfinfo, "%s", val_to_str(integer, cVALS(hfinfo->strings), "%d"));
2525 } else if (IS_BASE_DUAL(hfinfo->display)) {
2526 col_custom_set_fstr(fi->hfinfo, hfinfo_uint_value_format(hfinfo), integer, integer);
2528 col_custom_set_fstr(fi->hfinfo, hfinfo_uint_value_format(hfinfo), integer);
2530 fvalue_set_uinteger(&fi->value, integer);
2533 /* Add FT_UINT64 to a proto_tree */
2535 proto_tree_add_uint64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2538 proto_item *pi = NULL;
2540 header_field_info *hfinfo;
2545 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
2547 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2548 DISSECTOR_ASSERT(hfinfo->type == FT_UINT64);
2550 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2551 proto_tree_set_uint64(new_fi, value);
2557 proto_tree_add_uint64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2558 gint start, gint length, guint64 value, const char *format, ...)
2563 pi = proto_tree_add_uint64(tree, hfindex, tvb, start, length, value);
2567 va_start(ap, format);
2568 proto_tree_set_representation_value(pi, format, ap);
2575 proto_tree_add_uint64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2576 guint64 value, const char *format, ...)
2581 pi = proto_tree_add_uint64(tree, hfindex, tvb, start, length, value);
2585 va_start(ap, format);
2586 proto_tree_set_representation(pi, format, ap);
2592 /* Add FT_INT{8,16,24,32} to a proto_tree */
2594 proto_tree_add_int(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2597 proto_item *pi = NULL;
2599 header_field_info *hfinfo;
2604 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
2606 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2607 switch(hfinfo->type) {
2612 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length,
2614 proto_tree_set_int(new_fi, value);
2618 DISSECTOR_ASSERT_NOT_REACHED();
2625 proto_tree_add_int_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2626 gint start, gint length, gint32 value, const char *format, ...)
2628 proto_item *pi = NULL;
2631 pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
2635 va_start(ap, format);
2636 proto_tree_set_representation_value(pi, format, ap);
2643 proto_tree_add_int_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2644 gint32 value, const char *format, ...)
2646 proto_item *pi = NULL;
2649 pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
2653 va_start(ap, format);
2654 proto_tree_set_representation(pi, format, ap);
2660 /* Set the FT_INT{8,16,24,32} value */
2662 proto_tree_set_int(field_info *fi, gint32 value)
2664 header_field_info *hfinfo;
2667 hfinfo = fi->hfinfo;
2668 integer = (guint32) value;
2670 if (hfinfo->bitmask) {
2671 /* Mask out irrelevant portions */
2672 integer &= hfinfo->bitmask;
2675 if (hfinfo->bitshift > 0) {
2676 integer >>= hfinfo->bitshift;
2680 if (hfinfo->strings) {
2681 col_custom_set_fstr(fi->hfinfo, "%s", val_to_str(integer, cVALS(hfinfo->strings), "%d"));
2682 } else if (IS_BASE_DUAL(hfinfo->display)) {
2683 col_custom_set_fstr(fi->hfinfo, hfinfo_int_value_format(hfinfo), integer, integer);
2685 col_custom_set_fstr(fi->hfinfo, hfinfo_int_value_format(hfinfo), integer);
2687 fvalue_set_sinteger(&fi->value, integer);
2690 /* Add FT_INT64 to a proto_tree */
2692 proto_tree_add_int64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2695 proto_item *pi = NULL;
2697 header_field_info *hfinfo;
2702 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
2704 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2705 DISSECTOR_ASSERT(hfinfo->type == FT_INT64);
2707 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2708 proto_tree_set_uint64(new_fi, (guint64)value);
2714 proto_tree_add_int64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2715 gint start, gint length, gint64 value, const char *format, ...)
2720 pi = proto_tree_add_int64(tree, hfindex, tvb, start, length, value);
2724 va_start(ap, format);
2725 proto_tree_set_representation_value(pi, format, ap);
2732 proto_tree_add_int64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2733 gint64 value, const char *format, ...)
2738 pi = proto_tree_add_int64(tree, hfindex, tvb, start, length, value);
2742 va_start(ap, format);
2743 proto_tree_set_representation(pi, format, ap);
2749 /* Throw an exception if we exceed this many tree items. */
2750 /* XXX - This should probably be a preference */
2751 #define MAX_TREE_ITEMS (1 * 1000 * 1000)
2752 /* Add a field_info struct to the proto_tree, encapsulating it in a proto_node */
2754 proto_tree_add_node(proto_tree *tree, field_info *fi)
2756 proto_node *pnode, *tnode, *sibling;
2760 * Make sure "tree" is ready to have subtrees under it, by
2761 * checking whether it's been given an ett_ value.
2763 * "tnode->finfo" may be null; that's the case for the root
2764 * node of the protocol tree. That node is not displayed,
2765 * so it doesn't need an ett_ value to remember whether it
2770 if (tfi != NULL && (tfi->tree_type < 0 || tfi->tree_type >= num_tree_types)) {
2771 REPORT_DISSECTOR_BUG(ep_strdup_printf("\"%s\" - \"%s\" tfi->tree_type: %u invalid (%s:%u)",
2772 fi->hfinfo->name, fi->hfinfo->abbrev, tfi->tree_type, __FILE__, __LINE__));
2773 /* XXX - is it safe to continue here? */
2776 DISSECTOR_ASSERT(tfi == NULL ||
2777 (tfi->tree_type >= 0 && tfi->tree_type < num_tree_types));
2779 PTREE_DATA(tree)->count++;
2780 if (PTREE_DATA(tree)->count > MAX_TREE_ITEMS) {
2781 /* Let the exception handler add items to the tree */
2782 PTREE_DATA(tree)->count = 0;
2783 THROW_MESSAGE(DissectorError,
2784 ep_strdup_printf("More than %d items in the tree -- possible infinite loop", MAX_TREE_ITEMS));
2787 PROTO_NODE_NEW(pnode);
2788 pnode->parent = tnode;
2790 pnode->tree_data = PTREE_DATA(tree);
2792 if (tnode->last_child != NULL) {
2793 sibling = tnode->last_child;
2794 DISSECTOR_ASSERT(sibling->next == NULL);
2795 sibling->next = pnode;
2797 tnode->first_child = pnode;
2798 tnode->last_child = pnode;
2800 return (proto_item*)pnode;
2804 /* Generic way to allocate field_info and add to proto_tree.
2805 * Sets *pfi to address of newly-allocated field_info struct, if pfi is
2808 proto_tree_add_pi(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2809 gint *length, field_info **pfi)
2819 fi = alloc_field_info(tree, hfindex, tvb, start, length);
2820 pi = proto_tree_add_node(tree, fi);
2822 /* If the proto_tree wants to keep a record of this finfo
2823 * for quick lookup, then record it. */
2824 if (fi->hfinfo->ref_count) {
2826 hash = PTREE_DATA(tree)->interesting_hfids;
2827 ptrs = g_hash_table_lookup(hash, GINT_TO_POINTER(hfindex));
2829 g_ptr_array_add(ptrs, fi);
2833 /* Does the caller want to know the fi pointer? */
2842 static header_field_info *
2843 get_hfi_and_length(int hfindex, tvbuff_t *tvb, gint start, gint *length,
2846 header_field_info *hfinfo;
2847 gint length_remaining;
2850 * We only allow a null tvbuff if the item has a zero length,
2851 * i.e. if there's no data backing it.
2853 DISSECTOR_ASSERT(tvb != NULL || *length == 0);
2855 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2858 * XXX - in some protocols, there are 32-bit unsigned length
2859 * fields, so lengths in protocol tree and tvbuff routines
2860 * should really be unsigned. We should have, for those
2861 * field types for which "to the end of the tvbuff" makes sense,
2862 * additional routines that take no length argument and
2863 * add fields that run to the end of the tvbuff.
2865 if (*length == -1) {
2867 * For FT_NONE, FT_PROTOCOL, FT_BYTES, and FT_STRING fields,
2868 * a length of -1 means "set the length to what remains in
2871 * The assumption is either that
2873 * 1) the length of the item can only be determined
2874 * by dissection (typically true of items with
2875 * subitems, which are probably FT_NONE or
2880 * 2) if the tvbuff is "short" (either due to a short
2881 * snapshot length or due to lack of reassembly of
2882 * fragments/segments/whatever), we want to display
2883 * what's available in the field (probably FT_BYTES
2884 * or FT_STRING) and then throw an exception later
2888 * 3) the field is defined to be "what's left in the
2891 * so we set the length to what remains in the tvbuff so
2892 * that, if we throw an exception while dissecting, it
2893 * has what is probably the right value.
2895 * For FT_STRINGZ, it means "the string is null-terminated,
2896 * not null-padded; set the length to the actual length
2897 * of the string", and if the tvbuff if short, we just
2898 * throw an exception.
2900 * It's not valid for any other type of field.
2902 switch (hfinfo->type) {
2906 * We allow this to be zero-length - for
2907 * example, an ONC RPC NULL procedure has
2908 * neither arguments nor reply, so the
2909 * payload for that protocol is empty.
2911 * However, if the length is negative, the
2912 * start offset is *past* the byte past the
2913 * end of the tvbuff, so we throw an
2916 *length = tvb_length_remaining(tvb, start);
2919 * Use "tvb_ensure_bytes_exist()"
2920 * to force the appropriate exception
2923 tvb_ensure_bytes_exist(tvb, start, 0);
2925 DISSECTOR_ASSERT(*length >= 0);
2931 *length = tvb_ensure_length_remaining(tvb, start);
2932 DISSECTOR_ASSERT(*length >= 0);
2937 * Leave the length as -1, so our caller knows
2943 DISSECTOR_ASSERT_NOT_REACHED();
2945 *item_length = *length;
2947 *item_length = *length;
2948 if (hfinfo->type == FT_PROTOCOL || hfinfo->type == FT_NONE) {
2950 * These types are for interior nodes of the
2951 * tree, and don't have data associated with
2952 * them; if the length is negative (XXX - see
2953 * above) or goes past the end of the tvbuff,
2954 * cut it short at the end of the tvbuff.
2955 * That way, if this field is selected in
2956 * Wireshark, we don't highlight stuff past
2957 * the end of the data.
2959 /* XXX - what to do, if we don't have a tvb? */
2961 length_remaining = tvb_length_remaining(tvb, start);
2962 if (*item_length < 0 ||
2963 (*item_length > 0 &&
2964 (length_remaining < *item_length)))
2965 *item_length = length_remaining;
2968 if (*item_length < 0) {
2969 THROW(ReportedBoundsError);
2977 new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
2978 gint start, gint item_length)
2984 fi->hfinfo = hfinfo;
2986 fi->start+=(tvb)?TVB_RAW_OFFSET(tvb):0;
2987 fi->length = item_length;
2990 if (!PTREE_DATA(tree)->visible)
2991 FI_SET_FLAG(fi, FI_HIDDEN);
2992 fvalue_init(&fi->value, fi->hfinfo->type);
2995 /* add the data source tvbuff */
2996 fi->ds_tvb=tvb?TVB_GET_DS_TVB(tvb):NULL;
2998 fi->appendix_start = 0;
2999 fi->appendix_length = 0;
3005 alloc_field_info(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3008 header_field_info *hfinfo;
3011 hfinfo = get_hfi_and_length(hfindex, tvb, start, length, &item_length);
3012 return new_field_info(tree, hfinfo, tvb, start, item_length);
3015 /* If the protocol tree is to be visible, set the representation of a
3016 proto_tree entry with the name of the field for the item and with
3017 the value formatted with the supplied printf-style format and
3020 proto_tree_set_representation_value(proto_item *pi, const char *format, va_list ap)
3022 int ret; /*tmp return value */
3024 field_info *fi = PITEM_FINFO(pi);
3025 header_field_info *hf = fi->hfinfo;
3027 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
3028 ITEM_LABEL_NEW(fi->rep);
3030 if (hf->bitmask && (hf->type == FT_BOOLEAN || IS_FT_UINT(hf->type))) {
3034 val = fvalue_get_uinteger(&fi->value);
3035 if (hf->bitshift > 0) {
3036 val <<= hf->bitshift;
3038 decode_bitfield_value(tmpbuf, val, hf->bitmask, hfinfo_bitwidth(hf));
3039 /* put in the hf name */
3040 ret = g_snprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
3041 "%s%s: ", tmpbuf, fi->hfinfo->name);
3043 /* put in the hf name */
3044 ret = g_snprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
3045 "%s: ", fi->hfinfo->name);
3047 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH)) {
3048 /* That's all we can put in the representation. */
3049 fi->rep->representation[ITEM_LABEL_LENGTH - 1] = '\0';
3054 /* Put in the value of the string */
3055 ret = g_vsnprintf(fi->rep->representation + replen,
3056 ITEM_LABEL_LENGTH - replen, format, ap);
3057 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH - replen)) {
3058 /* Uh oh, we don't have enough room. Tell the user
3059 * that the field is truncated.
3063 fi->rep->representation[ITEM_LABEL_LENGTH - 1] = '\0';
3065 /* Argh, we cannot reuse 'ap' here. So make a copy
3066 * of what we formatted for (re)use below.
3068 oldrep = g_strdup(fi->rep->representation);
3070 ret = g_snprintf(fi->rep->representation,
3074 fi->rep->representation[ITEM_LABEL_LENGTH - 1] = '\0';
3080 /* If the protocol tree is to be visible, set the representation of a
3081 proto_tree entry with the representation formatted with the supplied
3082 printf-style format and argument list. */
3084 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap)
3086 int ret; /*tmp return value */
3087 field_info *fi = PITEM_FINFO(pi);
3089 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
3090 ITEM_LABEL_NEW(fi->rep);
3091 ret = g_vsnprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
3093 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH)) {
3094 /* Uh oh, we don't have enough room. Tell the user
3095 * that the field is truncated.
3099 fi->rep->representation[ITEM_LABEL_LENGTH - 1] = '\0';
3101 /* Argh, we cannot reuse 'ap' here. So make a copy
3102 * of what we formatted for (re)use below.
3104 oldrep = g_strdup(fi->rep->representation);
3106 g_snprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
3107 "[truncated] %s", oldrep);
3108 fi->rep->representation[ITEM_LABEL_LENGTH - 1] = '\0';
3114 /* Set text of proto_item after having already been created. */
3116 proto_item_set_text(proto_item *pi, const char *format, ...)
3118 field_info *fi = NULL;
3125 fi = PITEM_FINFO(pi);
3128 ITEM_LABEL_FREE(fi->rep);
3131 va_start(ap, format);
3132 proto_tree_set_representation(pi, format, ap);
3136 /* Append to text of proto_item after having already been created. */
3138 proto_item_append_text(proto_item *pi, const char *format, ...)
3140 field_info *fi = NULL;
3143 int ret; /*tmp return value */
3149 fi = PITEM_FINFO(pi);
3154 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
3155 va_start(ap, format);
3158 * If we don't already have a representation,
3159 * generate the default representation.
3161 if (fi->rep == NULL) {
3162 ITEM_LABEL_NEW(fi->rep);
3163 proto_item_fill_label(fi, fi->rep->representation);
3166 curlen = strlen(fi->rep->representation);
3167 if (ITEM_LABEL_LENGTH > curlen) {
3168 ret = g_vsnprintf(fi->rep->representation + curlen,
3169 ITEM_LABEL_LENGTH - curlen, format, ap);
3170 if ((ret == -1) || (ret >= (int)(ITEM_LABEL_LENGTH - curlen)))
3171 fi->rep->representation[ITEM_LABEL_LENGTH - 1] = '\0';
3178 proto_item_set_len(proto_item *pi, gint length)
3184 fi = PITEM_FINFO(pi);
3185 DISSECTOR_ASSERT(length >= 0);
3186 fi->length = length;
3188 if (fi->value.ftype->ftype == FT_BYTES)
3189 fi->value.value.bytes->len = length;
3193 * Sets the length of the item based on its start and on the specified
3194 * offset, which is the offset past the end of the item; as the start
3195 * in the item is relative to the beginning of the data source tvbuff,
3196 * we need to pass in a tvbuff - the end offset is relative to the beginning
3200 proto_item_set_end(proto_item *pi, tvbuff_t *tvb, gint end)
3206 fi = PITEM_FINFO(pi);
3207 end += TVB_RAW_OFFSET(tvb);
3208 DISSECTOR_ASSERT(end >= fi->start);
3209 fi->length = end - fi->start;
3213 proto_item_get_len(proto_item *pi)
3215 field_info *fi = PITEM_FINFO(pi);
3220 /** clear flags according to the mask and set new flag values */
3221 #define FI_REPLACE_FLAGS(fi, mask, flags_in) { \
3222 (fi->flags = (fi)->flags & ~(mask)); \
3223 (fi->flags = (fi)->flags | (flags_in)); \
3227 proto_item_set_expert_flags(proto_item *pi, int group, guint severity)
3229 if(pi == NULL || pi->finfo == NULL)
3232 /* only change things if severity is worse or at least equal than before */
3233 if(severity >= FI_GET_FLAG(pi->finfo, PI_SEVERITY_MASK)) {
3234 FI_REPLACE_FLAGS(pi->finfo, PI_GROUP_MASK, group);
3235 FI_REPLACE_FLAGS(pi->finfo, PI_SEVERITY_MASK, severity);
3246 proto_tree_create_root(void)
3250 /* Initialize the proto_node */
3251 PROTO_NODE_NEW(pnode);
3252 pnode->parent = NULL;
3253 pnode->finfo = NULL;
3254 pnode->tree_data = g_new(tree_data_t, 1);
3256 /* Initialize the tree_data_t */
3257 pnode->tree_data->interesting_hfids =
3258 g_hash_table_new(g_direct_hash, g_direct_equal);
3260 /* Set the default to FALSE so it's easier to
3261 * find errors; if we expect to see the protocol tree
3262 * but for some reason the default 'visible' is not
3263 * changed, then we'll find out very quickly. */
3264 pnode->tree_data->visible = FALSE;
3266 /* Keep track of the number of children */
3267 pnode->tree_data->count = 0;
3269 return (proto_tree*) pnode;
3273 /* "prime" a proto_tree with a single hfid that a dfilter
3274 * is interested in. */
3276 proto_tree_prime_hfid(proto_tree *tree, gint hfid)
3278 header_field_info *hfinfo;
3280 g_hash_table_insert(PTREE_DATA(tree)->interesting_hfids,
3281 GINT_TO_POINTER(hfid), g_ptr_array_new());
3283 PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
3284 /* this field is referenced by a filter so increase the refcount.
3285 also increase the refcount for the parent, i.e the protocol.
3287 hfinfo->ref_count++;
3288 /* only increase the refcount if there is a parent.
3289 if this is a protocol and not a field then parent will be -1
3290 and there is no parent to add any refcounting for.
3292 if (hfinfo->parent != -1) {
3293 header_field_info *parent_hfinfo;
3294 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
3295 parent_hfinfo->ref_count++;
3300 proto_item_add_subtree(proto_item *pi, gint idx) {
3306 fi = PITEM_FINFO(pi);
3307 DISSECTOR_ASSERT(idx >= 0 && idx < num_tree_types);
3308 fi->tree_type = idx;
3310 return (proto_tree*) pi;
3314 proto_item_get_subtree(proto_item *pi) {
3319 fi = PITEM_FINFO(pi);
3320 if ( (!fi) || (fi->tree_type == -1) )
3322 return (proto_tree*) pi;
3326 proto_item_get_parent(proto_item *ti) {
3333 proto_item_get_parent_nth(proto_item *ti, int gen) {
3346 proto_tree_get_parent(proto_tree *tree) {
3349 return (proto_item*) tree;
3353 proto_tree_get_root(proto_tree *tree) {
3356 while (tree->parent) {
3357 tree = tree->parent;
3363 proto_tree_move_item(proto_tree *tree, proto_item *fixed_item, proto_item *item_to_move)
3365 proto_item *curr_item;
3368 /*** cut item_to_move out ***/
3370 /* is item_to_move the first? */
3371 if(tree->first_child == item_to_move) {
3372 /* simply change first child to next */
3373 tree->first_child = item_to_move->next;
3375 /* find previous and change it's next */
3376 for(curr_item = tree->first_child; curr_item != NULL; curr_item = curr_item->next) {
3377 if(curr_item->next == item_to_move) {
3382 DISSECTOR_ASSERT(curr_item);
3384 curr_item->next = item_to_move->next;
3386 /* fix last_child if required */
3387 if(tree->last_child == item_to_move) {
3388 tree->last_child = curr_item;
3392 /*** insert to_move after fixed ***/
3393 item_to_move->next = fixed_item->next;
3394 fixed_item->next = item_to_move;
3395 if(tree->last_child == fixed_item) {
3396 tree->last_child = item_to_move;
3401 proto_tree_set_appendix(proto_tree *tree, tvbuff_t *tvb, gint start, gint length)
3409 start += TVB_RAW_OFFSET(tvb);
3410 DISSECTOR_ASSERT(start >= 0);
3411 DISSECTOR_ASSERT(length >= 0);
3413 fi->appendix_start = start;
3414 fi->appendix_length = length;
3418 proto_register_protocol(const char *name, const char *short_name, const char *filter_name)
3420 protocol_t *protocol;
3421 header_field_info *hfinfo;
3423 char *existing_name;
3427 gboolean found_invalid;
3430 * Make sure there's not already a protocol with any of those
3431 * names. Crash if there is, as that's an error in the code
3432 * or an inappropriate plugin.
3433 * This situation has to be fixed to not register more than one
3434 * protocol with the same name.
3436 * This is done by reducing the number of strcmp (and alike) calls as much as possible,
3437 * as this significally slows down startup time.
3439 * Drawback: As a hash value is used to reduce insert time,
3440 * this might lead to a hash collision.
3441 * However, as we have around 500+ protocols and we're using a 32 bit int this is very,
3445 key = g_malloc (sizeof(gint));
3446 *key = wrs_str_hash(name);
3447 existing_name = g_hash_table_lookup(proto_names, key);
3448 if (existing_name != NULL) {
3449 /* g_error will terminate the program */
3450 g_error("Duplicate protocol name \"%s\"!"
3451 " This might be caused by an inappropriate plugin or a development error.", name);
3453 g_hash_table_insert(proto_names, key, (gpointer)name);
3455 existing_name = g_hash_table_lookup(proto_short_names, (gpointer)short_name);
3456 if (existing_name != NULL) {
3457 g_error("Duplicate protocol short_name \"%s\"!"
3458 " This might be caused by an inappropriate plugin or a development error.", short_name);
3460 g_hash_table_insert(proto_short_names, (gpointer)short_name, (gpointer)short_name);
3462 found_invalid = FALSE;
3463 for (i = 0; i < strlen(filter_name); i++) {
3465 if (!(islower(c) || isdigit(c) || c == '-' || c == '_' || c == '.')) {
3466 found_invalid = TRUE;
3469 if (found_invalid) {
3470 g_error("Protocol filter name \"%s\" has one or more invalid characters."
3471 " Allowed are lower characters, digits, '-', '_' and '.'."
3472 " This might be caused by an inappropriate plugin or a development error.", filter_name);
3474 existing_name = g_hash_table_lookup(proto_filter_names, (gpointer)filter_name);
3475 if (existing_name != NULL) {
3476 g_error("Duplicate protocol filter_name \"%s\"!"
3477 " This might be caused by an inappropriate plugin or a development error.", filter_name);
3479 g_hash_table_insert(proto_filter_names, (gpointer)filter_name, (gpointer)filter_name);
3481 /* Add this protocol to the list of known protocols; the list
3482 is sorted by protocol short name. */
3483 protocol = g_malloc(sizeof (protocol_t));
3484 protocol->name = name;
3485 protocol->short_name = short_name;
3486 protocol->filter_name = filter_name;
3487 protocol->fields = NULL;
3488 protocol->is_enabled = TRUE; /* protocol is enabled by default */
3489 protocol->can_toggle = TRUE;
3490 /* list will be sorted later by name, when all protocols completed registering */
3491 protocols = g_list_prepend(protocols, protocol);
3493 /* Here we do allocate a new header_field_info struct */
3494 hfinfo = g_mem_chunk_alloc(gmc_hfinfo);
3495 hfinfo->name = name;
3496 hfinfo->abbrev = filter_name;
3497 hfinfo->type = FT_PROTOCOL;
3498 hfinfo->strings = protocol;
3499 hfinfo->bitmask = 0;
3500 hfinfo->bitshift = 0;
3501 hfinfo->ref_count = 0;
3502 hfinfo->blurb = NULL;
3503 hfinfo->parent = -1; /* this field differentiates protos and fields */
3505 proto_id = proto_register_field_init(hfinfo, hfinfo->parent);
3506 protocol->proto_id = proto_id;
3511 * Routines to use to iterate over the protocols.
3512 * The argument passed to the iterator routines is an opaque cookie to
3513 * their callers; it's the GList pointer for the current element in
3515 * The ID of the protocol is returned, or -1 if there is no protocol.
3518 proto_get_first_protocol(void **cookie)
3520 protocol_t *protocol;
3522 if (protocols == NULL)
3524 *cookie = protocols;
3525 protocol = protocols->data;
3526 return protocol->proto_id;
3530 proto_get_next_protocol(void **cookie)
3532 GList *list_item = *cookie;
3533 protocol_t *protocol;
3535 list_item = g_list_next(list_item);
3536 if (list_item == NULL)
3538 *cookie = list_item;
3539 protocol = list_item->data;
3540 return protocol->proto_id;
3544 proto_get_first_protocol_field(int proto_id, void **cookie)
3546 protocol_t *protocol = find_protocol_by_id(proto_id);
3547 hf_register_info *ptr;
3549 if ((protocol == NULL) || (protocol->fields == NULL))
3552 *cookie = protocol->fields;
3553 ptr = protocol->fields->data;
3554 return &ptr->hfinfo;
3558 proto_get_next_protocol_field(void **cookie)
3560 GList *list_item = *cookie;
3561 hf_register_info *ptr;
3563 list_item = g_list_next(list_item);
3564 if (list_item == NULL)
3567 *cookie = list_item;
3568 ptr = list_item->data;
3569 return &ptr->hfinfo;
3573 find_protocol_by_id(int proto_id)
3575 header_field_info *hfinfo;
3580 PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
3581 DISSECTOR_ASSERT(hfinfo->type==FT_PROTOCOL);
3582 return (protocol_t *)hfinfo->strings;
3585 static gint compare_filter_name(gconstpointer proto_arg,
3586 gconstpointer filter_name)
3588 const protocol_t *protocol = proto_arg;
3589 const gchar* f_name = filter_name;
3591 return (strcmp(protocol->filter_name, f_name));
3595 proto_get_id(protocol_t *protocol)
3597 return protocol->proto_id;
3600 int proto_get_id_by_filter_name(const gchar* filter_name)
3603 protocol_t *protocol;
3605 list_entry = g_list_find_custom(protocols, filter_name,
3606 compare_filter_name);
3608 if (list_entry == NULL)
3610 protocol = list_entry->data;
3611 return protocol->proto_id;
3615 proto_get_protocol_name(int proto_id)
3617 protocol_t *protocol;
3619 protocol = find_protocol_by_id(proto_id);
3620 return protocol->name;
3624 proto_get_protocol_short_name(protocol_t *protocol)
3626 if (protocol == NULL)
3628 return protocol->short_name;
3632 proto_get_protocol_filter_name(int proto_id)
3634 protocol_t *protocol;
3636 protocol = find_protocol_by_id(proto_id);
3637 if (protocol == NULL)
3639 return protocol->filter_name;
3643 proto_is_protocol_enabled(protocol_t *protocol)
3645 return protocol->is_enabled;
3649 proto_can_toggle_protocol(int proto_id)
3651 protocol_t *protocol;
3653 protocol = find_protocol_by_id(proto_id);
3654 return protocol->can_toggle;
3658 proto_set_decoding(int proto_id, gboolean enabled)
3660 protocol_t *protocol;
3662 protocol = find_protocol_by_id(proto_id);
3663 DISSECTOR_ASSERT(protocol->can_toggle);
3664 protocol->is_enabled = enabled;
3668 proto_enable_all(void)
3670 protocol_t *protocol;
3671 GList *list_item = protocols;
3673 if (protocols == NULL)
3677 protocol = list_item->data;
3678 if (protocol->can_toggle)
3679 protocol->is_enabled = TRUE;
3680 list_item = g_list_next(list_item);
3685 proto_set_cant_toggle(int proto_id)
3687 protocol_t *protocol;
3689 protocol = find_protocol_by_id(proto_id);
3690 protocol->can_toggle = FALSE;
3693 /* for use with static arrays only, since we don't allocate our own copies
3694 of the header_field_info struct contained within the hf_register_info struct */
3696 proto_register_field_array(int parent, hf_register_info *hf, int num_records)
3699 hf_register_info *ptr = hf;
3702 proto = find_protocol_by_id(parent);
3703 for (i = 0; i < num_records; i++, ptr++) {
3705 * Make sure we haven't registered this yet.
3706 * Most fields have variables associated with them
3707 * that are initialized to -1; some have array elements,
3708 * or possibly uninitialized variables, so we also allow
3709 * 0 (which is unlikely to be the field ID we get back
3710 * from "proto_register_field_init()").
3712 if (*ptr->p_id != -1 && *ptr->p_id != 0) {
3714 "Duplicate field detected in call to proto_register_field_array: %s is already registered\n",
3715 ptr->hfinfo.abbrev);
3719 if (proto != NULL) {
3720 if (proto->fields == NULL) {
3721 proto->fields = g_list_append(NULL, ptr);
3722 proto->last_field = proto->fields;
3725 g_list_append(proto->last_field, ptr)->next;
3728 field_id = proto_register_field_init(&ptr->hfinfo, parent);
3729 *ptr->p_id = field_id;
3733 /* chars allowed in field abbrev */
3735 const guchar fld_abbrev_chars[256] = {
3736 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00-0x0F */
3737 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10-0x1F */
3738 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, /* 0x20-0x2F '-', '.' */
3739 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 0x30-0x3F '0'-'9' */
3740 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x40-0x4F 'A'-'O' */
3741 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 0x50-0x5F 'P'-'Z', '_' */
3742 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x60-0x6F 'a'-'o' */
3743 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 0x70-0x7F 'p'-'z' */
3744 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80-0x8F */
3745 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90-0x9F */
3746 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xA0-0xAF */
3747 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xB0-0xBF */
3748 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xC0-0xCF */
3749 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xD0-0xDF */
3750 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xE0-0xEF */
3751 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xF0-0xFF */
3754 /* temporary function containing assert part for easier profiling */
3755 static void tmp_fld_check_assert(header_field_info *hfinfo) {
3756 /* The field must have a name (with length > 0) */
3757 DISSECTOR_ASSERT(hfinfo->name && hfinfo->name[0]);
3759 /* fields with an empty string for an abbreviation aren't filterable */
3760 DISSECTOR_ASSERT(hfinfo->abbrev);
3762 /* These types of fields are allowed to have value_strings, true_false_strings or a protocol_t struct*/
3763 DISSECTOR_ASSERT((hfinfo->strings == NULL) || (
3764 (hfinfo->type == FT_UINT8) ||
3765 (hfinfo->type == FT_UINT16) ||
3766 (hfinfo->type == FT_UINT24) ||
3767 (hfinfo->type == FT_UINT32) ||
3768 (hfinfo->type == FT_INT8) ||
3769 (hfinfo->type == FT_INT16) ||
3770 (hfinfo->type == FT_INT24) ||
3771 (hfinfo->type == FT_INT32) ||
3772 (hfinfo->type == FT_BOOLEAN) ||
3773 (hfinfo->type == FT_PROTOCOL) ||
3774 (hfinfo->type == FT_FRAMENUM) ));
3776 switch (hfinfo->type) {
3783 /* Hexadecimal and octal are, in printf() and everywhere else,
3784 * unsigned so don't allow dissectors to register a signed
3785 * field to be displayed unsigned. (Else how would we
3786 * display values negative values?)
3788 * If you want to take out this check, be sure to fix
3789 * hfinfo_numeric_format() so that it does not assert out
3790 * when trying to construct a hexadecimal representation of
3793 DISSECTOR_ASSERT(hfinfo->display != BASE_HEX &&
3794 hfinfo->display != BASE_HEX_DEC &&
3795 hfinfo->display != BASE_DEC_HEX &&
3796 hfinfo->display != BASE_OCT);
3803 /* Require integral types (other than frame number, which is
3804 always displayed in decimal) to have a number base */
3805 DISSECTOR_ASSERT(hfinfo->display != BASE_NONE);
3809 /* Don't allow bitfields or value strings for frame numbers */
3810 DISSECTOR_ASSERT(hfinfo->bitmask == 0);
3811 DISSECTOR_ASSERT(hfinfo->strings == NULL);
3820 proto_register_field_init(header_field_info *hfinfo, int parent)
3823 tmp_fld_check_assert(hfinfo);
3825 /* if this is a bitfield, compute bitshift */
3826 if (hfinfo->bitmask) {
3827 hfinfo->bitshift = wrs_count_bitshift(hfinfo->bitmask);
3830 hfinfo->parent = parent;
3831 hfinfo->same_name_next = NULL;
3832 hfinfo->same_name_prev = NULL;
3834 /* if we always add and never delete, then id == len - 1 is correct */
3835 if(gpa_hfinfo.len>=gpa_hfinfo.allocated_len){
3836 if(!gpa_hfinfo.hfi){
3837 gpa_hfinfo.allocated_len=1000;
3838 gpa_hfinfo.hfi=g_malloc(sizeof(header_field_info *)*1000);
3840 gpa_hfinfo.allocated_len+=1000;
3841 gpa_hfinfo.hfi=g_realloc(gpa_hfinfo.hfi, sizeof(header_field_info *)*gpa_hfinfo.allocated_len);
3844 gpa_hfinfo.hfi[gpa_hfinfo.len]=hfinfo;
3846 hfinfo->id = gpa_hfinfo.len - 1;
3848 /* if we have real names, enter this field in the name tree */
3849 if ((hfinfo->name[0] != 0) && (hfinfo->abbrev[0] != 0 )) {
3851 header_field_info *same_name_next_hfinfo;
3854 /* Check that the filter name (abbreviation) is legal;
3855 * it must contain only alphanumerics, '-', "_", and ".". */
3856 c = wrs_check_charset(fld_abbrev_chars, hfinfo->abbrev);
3858 fprintf(stderr, "OOPS: '%c' in '%s'\n", c, hfinfo->abbrev);
3859 DISSECTOR_ASSERT(!c);
3862 /* We allow multiple hfinfo's to be registered under the same
3863 * abbreviation. This was done for X.25, as, depending
3864 * on whether it's modulo-8 or modulo-128 operation,
3865 * some bitfield fields may be in different bits of
3866 * a byte, and we want to be able to refer to that field
3867 * with one name regardless of whether the packets
3868 * are modulo-8 or modulo-128 packets. */
3870 same_name_hfinfo = NULL;
3872 g_tree_insert(gpa_name_tree, (gpointer) (hfinfo->abbrev), hfinfo);
3873 /* GLIB 2.x - if it is already present
3874 * the previous hfinfo with the same name is saved
3875 * to same_name_hfinfo by value destroy callback */
3876 if (same_name_hfinfo) {
3877 /* There's already a field with this name.
3878 * Put it after that field in the list of
3879 * fields with this name, then allow the code
3880 * after this if{} block to replace the old
3881 * hfinfo with the new hfinfo in the GTree. Thus,
3882 * we end up with a linked-list of same-named hfinfo's,
3883 * with the root of the list being the hfinfo in the GTree */
3884 same_name_next_hfinfo =
3885 same_name_hfinfo->same_name_next;
3887 hfinfo->same_name_next = same_name_next_hfinfo;
3888 if (same_name_next_hfinfo)
3889 same_name_next_hfinfo->same_name_prev = hfinfo;
3891 same_name_hfinfo->same_name_next = hfinfo;
3892 hfinfo->same_name_prev = same_name_hfinfo;
3900 proto_register_subtree_array(gint *const *indices, int num_indices)
3903 gint *const *ptr = indices;
3906 * If we've already allocated the array of tree types, expand
3907 * it; this lets plugins such as mate add tree types after
3908 * the initial startup. (If we haven't already allocated it,
3909 * we don't allocate it; on the first pass, we just assign
3910 * ett values and keep track of how many we've assigned, and
3911 * when we're finished registering all dissectors we allocate
3912 * the array, so that we do only one allocation rather than
3913 * wasting CPU time and memory by growing the array for each
3914 * dissector that registers ett values.)
3916 if (tree_is_expanded != NULL) {
3918 g_realloc(tree_is_expanded,
3919 (num_tree_types+num_indices)*sizeof (gboolean));
3920 memset(tree_is_expanded + num_tree_types, 0,
3921 num_indices*sizeof (gboolean));
3925 * Assign "num_indices" subtree numbers starting at "num_tree_types",
3926 * returning the indices through the pointers in the array whose
3927 * first element is pointed to by "indices", and update
3928 * "num_tree_types" appropriately.
3930 for (i = 0; i < num_indices; i++, ptr++, num_tree_types++)
3931 **ptr = num_tree_types;
3935 proto_item_fill_label(field_info *fi, gchar *label_str)
3937 header_field_info *hfinfo = fi->hfinfo;
3943 guint32 n_addr; /* network-order IPv4 address */
3945 int ret; /*tmp return value */
3947 switch(hfinfo->type) {
3950 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3951 "%s", hfinfo->name);
3952 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3953 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3957 fill_label_boolean(fi, label_str);
3962 bytes = fvalue_get(&fi->value);
3964 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3965 "%s: %s", hfinfo->name,
3966 bytes_to_str(bytes, fvalue_length(&fi->value)));
3967 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH)) {
3968 /* Uh oh, we don't have enough room. Tell the
3969 * user that the field is truncated.
3971 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3972 "%s [truncated]: %s",
3974 bytes_to_str(bytes, fvalue_length(&fi->value)));
3975 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3979 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3980 "%s: <MISSING>", hfinfo->name);
3981 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3982 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3986 /* Four types of integers to take care of:
3987 * Bitfield, with val_string
3988 * Bitfield, w/o val_string
3989 * Non-bitfield, with val_string
3990 * Non-bitfield, w/o val_string
3997 if (hfinfo->bitmask) {
3998 fill_label_bitfield(fi, label_str);
4000 fill_label_uint(fi, label_str);
4005 fill_label_uint64(fi, label_str);
4012 DISSECTOR_ASSERT(!hfinfo->bitmask);
4013 fill_label_int(fi, label_str);
4017 fill_label_int64(fi, label_str);
4021 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4022 "%s: %." STRINGIFY(FLT_DIG) "f",
4023 hfinfo->name, fvalue_get_floating(&fi->value));
4024 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4025 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4029 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4030 "%s: %." STRINGIFY(DBL_DIG) "g",
4031 hfinfo->name, fvalue_get_floating(&fi->value));
4032 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4033 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4036 case FT_ABSOLUTE_TIME:
4037 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4038 "%s: %s", hfinfo->name,
4039 abs_time_to_str(fvalue_get(&fi->value)));
4040 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4041 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4044 case FT_RELATIVE_TIME:
4045 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4046 "%s: %s seconds", hfinfo->name,
4047 rel_time_to_secs_str(fvalue_get(&fi->value)));
4048 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4049 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4053 integer = fvalue_get_uinteger(&fi->value);
4054 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4055 "%s: %s (0x%08X)", hfinfo->name,
4056 get_ipxnet_name(integer), integer);
4057 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4058 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4062 bytes = fvalue_get(&fi->value);
4063 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4064 "%s: %s (%s)", hfinfo->name,
4065 get_ether_name(bytes),
4066 ether_to_str(bytes));
4067 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4068 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4072 ipv4 = fvalue_get(&fi->value);
4073 n_addr = ipv4_get_net_order_addr(ipv4);
4074 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4075 "%s: %s (%s)", hfinfo->name,
4076 get_hostname(n_addr),
4077 ip_to_str((guint8*)&n_addr));
4078 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4079 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4083 bytes = fvalue_get(&fi->value);
4084 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4085 "%s: %s (%s)", hfinfo->name,
4086 get_hostname6((struct e_in6_addr *)bytes),
4087 ip6_to_str((struct e_in6_addr*)bytes));
4088 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4089 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4093 guid = fvalue_get(&fi->value);
4094 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4095 "%s: %s", hfinfo->name,
4097 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4098 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4102 bytes = fvalue_get(&fi->value);
4103 name = oid_resolved_from_encoded(bytes, fvalue_length(&fi->value));
4105 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4106 "%s: %s (%s)", hfinfo->name,
4107 oid_encoded2string(bytes, fvalue_length(&fi->value)), name);
4109 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4110 "%s: %s", hfinfo->name,
4111 oid_encoded2string(bytes, fvalue_length(&fi->value)));
4113 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4114 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4120 case FT_UINT_STRING:
4121 bytes = fvalue_get(&fi->value);
4122 if(strlen(bytes) > ITEM_LABEL_LENGTH) {
4123 /* Uh oh, we don't have enough room. Tell the
4124 * user that the field is truncated.
4126 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4127 "%s [truncated]: %s",
4129 format_text(bytes, strlen(bytes)));
4131 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4132 "%s: %s", hfinfo->name,
4133 format_text(bytes, strlen(bytes)));
4135 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4136 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4140 g_error("hfinfo->type %d (%s) not handled\n",
4142 ftype_name(hfinfo->type));
4143 DISSECTOR_ASSERT_NOT_REACHED();
4149 fill_label_boolean(field_info *fi, gchar *label_str)
4151 char *p = label_str;
4152 int bitfield_byte_length = 0, bitwidth;
4153 guint32 unshifted_value;
4155 int ret; /*tmp return value */
4157 header_field_info *hfinfo = fi->hfinfo;
4158 const true_false_string *tfstring = &tfs_true_false;
4160 if (hfinfo->strings) {
4161 tfstring = (const struct true_false_string*) hfinfo->strings;
4164 value = fvalue_get_uinteger(&fi->value);
4165 if (hfinfo->bitmask) {
4166 /* Figure out the bit width */
4167 bitwidth = hfinfo_bitwidth(hfinfo);
4170 unshifted_value = value;
4171 if (hfinfo->bitshift > 0) {
4172 unshifted_value <<= hfinfo->bitshift;
4175 /* Create the bitfield first */
4176 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
4177 bitfield_byte_length = p - label_str;
4180 /* Fill in the textual info */
4181 ret = g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
4182 "%s: %s", hfinfo->name,
4183 value ? tfstring->true_string : tfstring->false_string);
4184 if ((ret == -1) || (ret >= (ITEM_LABEL_LENGTH - bitfield_byte_length)))
4185 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4189 /* Fills data for bitfield ints with val_strings */
4191 fill_label_bitfield(field_info *fi, gchar *label_str)
4193 const char *format = NULL;
4195 int bitfield_byte_length, bitwidth;
4196 guint32 unshifted_value;
4198 int ret; /*tmp return value */
4200 header_field_info *hfinfo = fi->hfinfo;
4202 /* Figure out the bit width */
4203 bitwidth = hfinfo_bitwidth(hfinfo);
4206 unshifted_value = fvalue_get_uinteger(&fi->value);
4207 value = unshifted_value;
4208 if (hfinfo->bitshift > 0) {
4209 unshifted_value <<= hfinfo->bitshift;
4212 /* Create the bitfield first */
4213 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
4214 bitfield_byte_length = p - label_str;
4216 /* Fill in the textual info using stored (shifted) value */
4217 if (hfinfo->display == BASE_CUSTOM) {
4218 gchar tmp[ITEM_LABEL_LENGTH];
4219 custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hfinfo->strings;
4221 DISSECTOR_ASSERT(fmtfunc);
4222 fmtfunc(tmp, value);
4223 ret = g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
4224 "%s: %s", hfinfo->name, tmp);
4226 else if (hfinfo->strings) {
4227 format = hfinfo_uint_vals_format(hfinfo);
4228 ret = g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
4229 format, hfinfo->name,
4230 val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
4233 format = hfinfo_uint_format(hfinfo);
4234 if (IS_BASE_DUAL(hfinfo->display)) {
4235 ret = g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
4236 format, hfinfo->name, value, value);
4238 ret = g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
4239 format, hfinfo->name, value);
4242 if ((ret == -1) || (ret >= (ITEM_LABEL_LENGTH - bitfield_byte_length)))
4243 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4247 fill_label_uint(field_info *fi, gchar *label_str)
4249 const char *format = NULL;
4250 header_field_info *hfinfo = fi->hfinfo;
4252 int ret; /*tmp return value */
4254 value = fvalue_get_uinteger(&fi->value);
4256 /* Fill in the textual info */
4257 if (hfinfo->display == BASE_CUSTOM) {
4258 gchar tmp[ITEM_LABEL_LENGTH];
4259 custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hfinfo->strings;
4261 DISSECTOR_ASSERT(fmtfunc);
4262 fmtfunc(tmp, value);
4263 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH, "%s: %s", hfinfo->name, tmp);
4265 else if (hfinfo->strings) {
4266 format = hfinfo_uint_vals_format(hfinfo);
4267 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4268 format, hfinfo->name,
4269 val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
4272 format = hfinfo_uint_format(hfinfo);
4273 if (IS_BASE_DUAL(hfinfo->display)) {
4274 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4275 format, hfinfo->name, value, value);
4277 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4278 format, hfinfo->name, value);
4281 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4282 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4286 fill_label_uint64(field_info *fi, gchar *label_str)
4288 const char *format = NULL;
4289 header_field_info *hfinfo = fi->hfinfo;
4291 int ret; /*tmp return value */
4293 /* Pick the proper format string */
4294 format = hfinfo_uint64_format(hfinfo);
4295 value = fvalue_get_integer64(&fi->value);
4297 /* Fill in the textual info */
4298 if (IS_BASE_DUAL(hfinfo->display)) {
4299 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4300 format, hfinfo->name, value, value);
4302 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4303 format, hfinfo->name, value);
4305 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4306 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4310 fill_label_int(field_info *fi, gchar *label_str)
4312 const char *format = NULL;
4313 header_field_info *hfinfo = fi->hfinfo;
4315 int ret; /*tmp return value */
4317 value = fvalue_get_sinteger(&fi->value);
4319 /* Fill in the textual info */
4320 if (hfinfo->display == BASE_CUSTOM) {
4321 gchar tmp[ITEM_LABEL_LENGTH];
4322 custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hfinfo->strings;
4324 DISSECTOR_ASSERT(fmtfunc);
4325 fmtfunc(tmp, value);
4326 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH, "%s: %s", hfinfo->name, tmp);
4328 else if (hfinfo->strings) {
4329 format = hfinfo_int_vals_format(hfinfo);
4330 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4331 format, hfinfo->name,
4332 val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
4335 format = hfinfo_int_format(hfinfo);
4336 if (IS_BASE_DUAL(hfinfo->display)) {
4337 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4338 format, hfinfo->name, value, value);
4340 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4341 format, hfinfo->name, value);
4344 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4345 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4349 fill_label_int64(field_info *fi, gchar *label_str)
4351 const char *format = NULL;
4352 header_field_info *hfinfo = fi->hfinfo;
4354 int ret; /*tmp return value */
4356 /* Pick the proper format string */
4357 format = hfinfo_int64_format(hfinfo);
4358 value = fvalue_get_integer64(&fi->value);
4360 /* Fill in the textual info */
4361 if (IS_BASE_DUAL(hfinfo->display)) {
4362 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4363 format, hfinfo->name, value, value);
4365 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4366 format, hfinfo->name, value);
4368 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4369 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4373 hfinfo_bitwidth(header_field_info *hfinfo)
4377 if (!hfinfo->bitmask) {
4381 switch(hfinfo->type) {
4399 bitwidth = hfinfo->display; /* hacky? :) */
4402 DISSECTOR_ASSERT_NOT_REACHED();
4409 hfinfo_uint_vals_format(header_field_info *hfinfo)
4411 const char *format = NULL;
4413 /* bit operation to reset the potential BASE_RANGE_STRING (or others in
4415 switch(hfinfo->display & BASE_STRUCTURE_RESET) {
4418 format = "%s: %s (%u)";
4420 case BASE_OCT: /* I'm lazy */
4421 format = "%s: %s (%o)";
4425 switch(hfinfo->type) {
4427 format = "%s: %s (0x%02x)";
4430 format = "%s: %s (0x%04x)";
4433 format = "%s: %s (0x%06x)";
4436 format = "%s: %s (0x%08x)";
4439 DISSECTOR_ASSERT_NOT_REACHED();
4444 DISSECTOR_ASSERT_NOT_REACHED();
4451 hfinfo_uint_format(header_field_info *hfinfo)
4453 const char *format = NULL;
4455 /* Pick the proper format string */
4456 if (hfinfo->type == FT_FRAMENUM) {
4458 * Frame numbers are always displayed in decimal.
4462 switch(hfinfo->display) {
4467 switch(hfinfo->type) {
4469 format = "%s: %u (0x%02x)";
4472 format = "%s: %u (0x%04x)";
4475 format = "%s: %u (0x%06x)";
4478 format = "%s: %u (0x%08x)";
4481 DISSECTOR_ASSERT_NOT_REACHED();
4485 case BASE_OCT: /* I'm lazy */
4489 switch(hfinfo->type) {
4491 format = "%s: 0x%02x";
4494 format = "%s: 0x%04x";
4497 format = "%s: 0x%06x";
4500 format = "%s: 0x%08x";
4503 DISSECTOR_ASSERT_NOT_REACHED();
4508 switch(hfinfo->type) {
4510 format = "%s: 0x%02x (%u)";
4513 format = "%s: 0x%04x (%u)";
4516 format = "%s: 0x%06x (%u)";
4519 format = "%s: 0x%08x (%u)";
4522 DISSECTOR_ASSERT_NOT_REACHED();
4527 DISSECTOR_ASSERT_NOT_REACHED();
4535 hfinfo_uint_value_format(header_field_info *hfinfo)
4537 const char *format = NULL;
4539 /* Pick the proper format string */
4540 if (hfinfo->type == FT_FRAMENUM) {
4542 * Frame numbers are always displayed in decimal.
4546 switch(hfinfo->display) {
4551 switch(hfinfo->type) {
4553 format = "%u (0x%02x)";
4556 format = "%u (0x%04x)";
4559 format = "%u (0x%06x)";
4562 format = "%u (0x%08x)";
4565 DISSECTOR_ASSERT_NOT_REACHED();
4573 switch(hfinfo->type) {
4587 DISSECTOR_ASSERT_NOT_REACHED();
4592 switch(hfinfo->type) {
4594 format = "0x%02x (%u)";
4597 format = "0x%04x (%u)";
4600 format = "0x%06x (%u)";
4603 format = "0x%08x (%u)";
4606 DISSECTOR_ASSERT_NOT_REACHED();
4611 DISSECTOR_ASSERT_NOT_REACHED();
4619 hfinfo_int_vals_format(header_field_info *hfinfo)
4621 const char *format = NULL;
4623 /* bit operation to reset the potential BASE_RANGE_STRING (or others in
4625 switch(hfinfo->display & BASE_STRUCTURE_RESET) {
4628 format = "%s: %s (%d)";
4630 case BASE_OCT: /* I'm lazy */
4631 format = "%s: %s (%o)";
4635 switch(hfinfo->type) {
4637 format = "%s: %s (0x%02x)";
4640 format = "%s: %s (0x%04x)";
4643 format = "%s: %s (0x%06x)";
4646 format = "%s: %s (0x%08x)";
4649 DISSECTOR_ASSERT_NOT_REACHED();
4654 DISSECTOR_ASSERT_NOT_REACHED();
4661 hfinfo_uint64_format(header_field_info *hfinfo)
4663 const char *format = NULL;
4665 /* Pick the proper format string */
4666 switch(hfinfo->display) {
4668 format = "%s: %" G_GINT64_MODIFIER "u";
4671 format = "%s: %" G_GINT64_MODIFIER "u (%" G_GINT64_MODIFIER "x)";
4673 case BASE_OCT: /* I'm lazy */
4674 format = "%s: %" G_GINT64_MODIFIER "o";
4677 format = "%s: 0x%016" G_GINT64_MODIFIER "x";
4680 format = "%s: 0x%016" G_GINT64_MODIFIER "x (%" G_GINT64_MODIFIER "u)";
4683 DISSECTOR_ASSERT_NOT_REACHED();
4690 hfinfo_int_format(header_field_info *hfinfo)
4692 const char *format = NULL;
4694 /* Pick the proper format string */
4695 switch(hfinfo->display) {
4700 switch(hfinfo->type) {
4702 format = "%s: %d (0x%02x)";
4705 format = "%s: %d (0x%04x)";
4708 format = "%s: %d (0x%06x)";
4711 format = "%s: %d (0x%08x)";
4714 DISSECTOR_ASSERT_NOT_REACHED();
4718 case BASE_OCT: /* I'm lazy */
4722 switch(hfinfo->type) {
4724 format = "%s: 0x%02x";
4727 format = "%s: 0x%04x";
4730 format = "%s: 0x%06x";
4733 format = "%s: 0x%08x";
4736 DISSECTOR_ASSERT_NOT_REACHED();
4741 switch(hfinfo->type) {
4743 format = "%s: 0x%02x (%d)";
4746 format = "%s: 0x%04x (%d)";
4749 format = "%s: 0x%06x (%d)";
4752 format = "%s: 0x%08x (%d)";
4755 DISSECTOR_ASSERT_NOT_REACHED();
4760 DISSECTOR_ASSERT_NOT_REACHED();
4767 hfinfo_int_value_format(header_field_info *hfinfo)
4769 const char *format = NULL;
4771 /* Pick the proper format string */
4772 switch(hfinfo->display) {
4777 switch(hfinfo->type) {
4779 format = "%d (0x%02x)";
4782 format = "%d (0x%04x)";
4785 format = "%d (0x%06x)";
4788 format = "%d (0x%08x)";
4791 DISSECTOR_ASSERT_NOT_REACHED();
4799 switch(hfinfo->type) {
4813 DISSECTOR_ASSERT_NOT_REACHED();
4818 switch(hfinfo->type) {
4820 format = "0x%02x (%d)";
4823 format = "0x%04x (%d)";
4826 format = "0x%06x (%d)";
4829 format = "0x%08x (%d)";
4832 DISSECTOR_ASSERT_NOT_REACHED();
4837 DISSECTOR_ASSERT_NOT_REACHED();
4844 hfinfo_int64_format(header_field_info *hfinfo)
4846 const char *format = NULL;
4848 /* Pick the proper format string */
4849 switch(hfinfo->display) {
4851 format = "%s: %" G_GINT64_MODIFIER "d";
4854 format = "%s: %" G_GINT64_MODIFIER "d (%" G_GINT64_MODIFIER "x)";
4856 case BASE_OCT: /* I'm lazy */
4857 format = "%s: %" G_GINT64_MODIFIER "o";
4860 format = "%s: 0x%016" G_GINT64_MODIFIER "x";
4863 format = "%s: 0x%016" G_GINT64_MODIFIER "x (%" G_GINT64_MODIFIER "d)";
4866 DISSECTOR_ASSERT_NOT_REACHED();
4875 proto_registrar_n(void)
4877 return gpa_hfinfo.len;
4881 proto_registrar_get_name(int n)
4883 header_field_info *hfinfo;
4885 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
4886 return hfinfo->name;
4890 proto_registrar_get_abbrev(int n)
4892 header_field_info *hfinfo;
4894 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
4895 return hfinfo->abbrev;
4899 proto_registrar_get_ftype(int n)
4901 header_field_info *hfinfo;
4903 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
4904 return hfinfo->type;
4908 proto_registrar_get_parent(int n)
4910 header_field_info *hfinfo;
4912 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
4913 return hfinfo->parent;
4917 proto_registrar_is_protocol(int n)
4919 header_field_info *hfinfo;
4921 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
4922 return (hfinfo->parent == -1 ? TRUE : FALSE);
4925 /* Returns length of field in packet (not necessarily the length
4926 * in our internal representation, as in the case of IPv4).
4927 * 0 means undeterminable at time of registration
4928 * -1 means the field is not registered. */
4930 proto_registrar_get_length(int n)
4932 header_field_info *hfinfo;
4934 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
4935 return ftype_length(hfinfo->type);
4940 /* Looks for a protocol or a field in a proto_tree. Returns TRUE if
4941 * it exists anywhere, or FALSE if it exists nowhere. */
4943 proto_check_for_protocol_or_field(proto_tree* tree, int id)
4945 GPtrArray *ptrs = proto_get_finfo_ptr_array(tree, id);
4950 else if (g_ptr_array_len(ptrs) > 0) {
4958 /* Return GPtrArray* of field_info pointers for all hfindex that appear in tree.
4959 * This only works if the hfindex was "primed" before the dissection
4960 * took place, as we just pass back the already-created GPtrArray*.
4961 * The caller should *not* free the GPtrArray*; proto_tree_free_node()
4964 proto_get_finfo_ptr_array(proto_tree *tree, int id)
4966 return g_hash_table_lookup(PTREE_DATA(tree)->interesting_hfids,
4967 GINT_TO_POINTER(id));
4971 /* Helper struct for proto_find_info() and proto_all_finfos() */
4977 /* Helper function for proto_find_info() */
4979 find_finfo(proto_node *node, gpointer data)
4981 field_info *fi = PITEM_FINFO(node);
4982 if (fi && fi->hfinfo) {
4983 if (fi->hfinfo->id == ((ffdata_t*)data)->id) {
4984 g_ptr_array_add(((ffdata_t*)data)->array, fi);
4988 /* Don't stop traversing. */
4992 /* Return GPtrArray* of field_info pointers for all hfindex that appear in a tree.
4993 * This works on any proto_tree, primed or unprimed, but actually searches
4994 * the tree, so it is slower than using proto_get_finfo_ptr_array on a primed tree.
4995 * The caller does need to free the returned GPtrArray with
4996 * g_ptr_array_free(<array>, FALSE).
4999 proto_find_finfo(proto_tree *tree, int id)
5003 ffdata.array = g_ptr_array_new();
5006 proto_tree_traverse_pre_order(tree, find_finfo, &ffdata);
5008 return ffdata.array;
5011 /* Helper function for proto_all_finfos() */
5013 every_finfo(proto_node *node, gpointer data)
5015 field_info *fi = PITEM_FINFO(node);
5016 if (fi && fi->hfinfo) {
5017 g_ptr_array_add(((ffdata_t*)data)->array, fi);
5020 /* Don't stop traversing. */
5024 /* Return GPtrArray* of field_info pointers containing all hfindexes that appear in a tree. */
5026 proto_all_finfos(proto_tree *tree)
5030 ffdata.array = g_ptr_array_new();
5033 proto_tree_traverse_pre_order(tree, every_finfo, &ffdata);
5035 return ffdata.array;
5046 check_for_offset(proto_node *node, gpointer data)
5048 field_info *fi = PITEM_FINFO(node);
5049 offset_search_t *offsearch = data;
5051 /* !fi == the top most container node which holds nothing */
5052 if (fi && !PROTO_ITEM_IS_HIDDEN(node) && fi->ds_tvb && offsearch->tvb == fi->ds_tvb) {
5053 if (offsearch->offset >= (guint) fi->start &&
5054 offsearch->offset < (guint) (fi->start + fi->length)) {
5056 offsearch->finfo = fi;
5057 return FALSE; /* keep traversing */
5060 return FALSE; /* keep traversing */
5063 /* Search a proto_tree backwards (from leaves to root) looking for the field
5064 * whose start/length occupies 'offset' */
5065 /* XXX - I couldn't find an easy way to search backwards, so I search
5066 * forwards, w/o stopping. Therefore, the last finfo I find will the be
5067 * the one I want to return to the user. This algorithm is inefficient
5068 * and could be re-done, but I'd have to handle all the children and
5069 * siblings of each node myself. When I have more time I'll do that.
5072 proto_find_field_from_offset(proto_tree *tree, guint offset, tvbuff_t *tvb)
5074 offset_search_t offsearch;
5076 offsearch.offset = offset;
5077 offsearch.finfo = NULL;
5078 offsearch.tvb = tvb;
5080 proto_tree_traverse_pre_order(tree, check_for_offset, &offsearch);
5082 return offsearch.finfo;
5085 /* Dumps the protocols in the registration database to stdout. An independent
5086 * program can take this output and format it into nice tables or HTML or
5089 * There is one record per line. The fields are tab-delimited.
5091 * Field 1 = protocol name
5092 * Field 2 = protocol short name
5093 * Field 3 = protocol filter name
5096 proto_registrar_dump_protocols(void)
5098 protocol_t *protocol;
5100 void *cookie = NULL;
5102 for (i = proto_get_first_protocol(&cookie); i != -1;
5103 i = proto_get_next_protocol(&cookie)) {
5104 protocol = find_protocol_by_id(i);
5105 printf("%s\t%s\t%s\n", protocol->name, protocol->short_name,
5106 protocol->filter_name);
5110 /* Dumps the value_string and true/false strings for fields that have
5111 * them. There is one record per line. Fields are tab-delimited.
5112 * There are two types of records, Value String records and True/False
5113 * String records. The first field, 'V' or 'T', indicates the type
5119 * Field 2 = field abbreviation to which this value string corresponds
5120 * Field 3 = Integer value
5123 * True/False Strings
5124 * ------------------
5126 * Field 2 = field abbreviation to which this true/false string corresponds
5127 * Field 3 = True String
5128 * Field 4 = False String
5131 proto_registrar_dump_values(void)
5133 header_field_info *hfinfo, *parent_hfinfo;
5135 const value_string *vals;
5136 const true_false_string *tfs;
5138 len = gpa_hfinfo.len;
5139 for (i = 0; i < len ; i++) {
5140 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
5142 if (hfinfo->id == hf_text_only) {
5146 /* ignore protocols */
5147 if (proto_registrar_is_protocol(i)) {
5150 /* process header fields */
5153 * If this field isn't at the head of the list of
5154 * fields with this name, skip this field - all
5155 * fields with the same name are really just versions
5156 * of the same field stored in different bits, and
5157 * should have the same type/radix/value list, and
5158 * just differ in their bit masks. (If a field isn't
5159 * a bitfield, but can be, say, 1 or 2 bytes long,
5160 * it can just be made FT_UINT16, meaning the
5161 * *maximum* length is 2 bytes, and be used
5164 if (hfinfo->same_name_prev != NULL)
5167 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
5172 if (hfinfo->display != BASE_CUSTOM &&
5173 (hfinfo->type == FT_UINT8 ||
5174 hfinfo->type == FT_UINT16 ||
5175 hfinfo->type == FT_UINT24 ||
5176 hfinfo->type == FT_UINT32 ||
5177 hfinfo->type == FT_UINT64 ||
5178 hfinfo->type == FT_INT8 ||
5179 hfinfo->type == FT_INT16 ||
5180 hfinfo->type == FT_INT24 ||
5181 hfinfo->type == FT_INT32 ||
5182 hfinfo->type == FT_INT64)) {
5184 vals = hfinfo->strings;
5186 else if (hfinfo->type == FT_BOOLEAN) {
5187 tfs = hfinfo->strings;
5190 /* Print value strings? */
5193 while (vals[vi].strptr) {
5194 /* Print in the proper base */
5195 if (hfinfo->display == BASE_HEX) {
5196 printf("V\t%s\t0x%x\t%s\n",
5202 printf("V\t%s\t%u\t%s\n",
5211 /* Print true/false strings? */
5213 printf("T\t%s\t%s\t%s\n", hfinfo->abbrev,
5214 tfs->true_string, tfs->false_string);
5220 /* Dumps the contents of the registration database to stdout. An indepedent
5221 * program can take this output and format it into nice tables or HTML or
5224 * There is one record per line. Each record is either a protocol or a header
5225 * field, differentiated by the first field. The fields are tab-delimited.
5230 * Field 2 = descriptive protocol name
5231 * Field 3 = protocol abbreviation
5237 * Field 2 = descriptive field name
5238 * Field 3 = field abbreviation
5239 * Field 4 = type ( textual representation of the the ftenum type )
5240 * Field 5 = parent protocol abbreviation
5241 * Field 6 = blurb describing field
5245 * Field 2 = descriptive field name
5246 * Field 3 = field abbreviation
5247 * Field 4 = type ( textual representation of the the ftenum type )
5248 * Field 5 = parent protocol abbreviation
5249 * Field 6 = blurb describing field
5250 * Field 7 = base for display (for integer types)
5251 * Field 8 = blurb describing field (yes, apparently we repeated this accidentally)
5255 * Field 2 = descriptive field name
5256 * Field 3 = field abbreviation
5257 * Field 4 = type ( textual representation of the the ftenum type )
5258 * Field 5 = parent protocol abbreviation
5259 * Field 6 = blurb describing field
5260 * Field 7 = base for display (for integer types)
5264 proto_registrar_dump_fields(int format)
5266 header_field_info *hfinfo, *parent_hfinfo;
5268 const char *enum_name;
5269 const char *base_name;
5272 len = gpa_hfinfo.len;
5273 for (i = 0; i < len ; i++) {
5274 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
5277 * Skip the pseudo-field for "proto_tree_add_text()" since
5278 * we don't want it in the list of filterable fields.
5280 if (hfinfo->id == hf_text_only)
5283 /* format for protocols */
5284 if (proto_registrar_is_protocol(i)) {
5285 printf("P\t%s\t%s\n", hfinfo->name, hfinfo->abbrev);
5287 /* format for header fields */
5290 * If this field isn't at the head of the list of
5291 * fields with this name, skip this field - all
5292 * fields with the same name are really just versions
5293 * of the same field stored in different bits, and
5294 * should have the same type/radix/value list, and
5295 * just differ in their bit masks. (If a field isn't
5296 * a bitfield, but can be, say, 1 or 2 bytes long,
5297 * it can just be made FT_UINT16, meaning the
5298 * *maximum* length is 2 bytes, and be used
5301 if (hfinfo->same_name_prev != NULL)
5304 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
5306 enum_name = ftype_name(hfinfo->type);
5310 if (hfinfo->type == FT_UINT8 ||
5311 hfinfo->type == FT_UINT16 ||
5312 hfinfo->type == FT_UINT24 ||
5313 hfinfo->type == FT_UINT32 ||
5314 hfinfo->type == FT_UINT64 ||
5315 hfinfo->type == FT_INT8 ||
5316 hfinfo->type == FT_INT16 ||
5317 hfinfo->type == FT_INT24 ||
5318 hfinfo->type == FT_INT32 ||
5319 hfinfo->type == FT_INT64) {
5322 switch(hfinfo->display) {
5324 base_name = "BASE_NONE";
5327 base_name = "BASE_DEC";
5330 base_name = "BASE_HEX";
5333 base_name = "BASE_OCT";
5336 base_name = "BASE_DEC_HEX";
5339 base_name = "BASE_HEX_DEC";
5342 base_name = "BASE_CUSTOM";
5348 blurb = hfinfo->blurb;
5352 printf("F\t%s\t%s\t%s\t%s\t%s\n",
5353 hfinfo->name, hfinfo->abbrev, enum_name,
5354 parent_hfinfo->abbrev, blurb);
5356 else if (format == 2) {
5357 printf("F\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n",
5358 hfinfo->name, hfinfo->abbrev, enum_name,
5359 parent_hfinfo->abbrev, blurb,
5362 else if (format == 3) {
5363 printf("F\t%s\t%s\t%s\t%s\t%s\t%s\t%u\n",
5364 hfinfo->name, hfinfo->abbrev, enum_name,
5365 parent_hfinfo->abbrev, blurb,
5366 base_name, hfinfo->bitmask);
5369 g_assert_not_reached();
5376 hfinfo_numeric_format(header_field_info *hfinfo)
5378 const char *format = NULL;
5380 /* Pick the proper format string */
5381 if (hfinfo->type == FT_FRAMENUM) {
5383 * Frame numbers are always displayed in decimal.
5385 format = "%s == %u";
5387 /* Pick the proper format string, ignoring BASE_RANGE_STRING flag */
5388 switch(hfinfo->display & ~BASE_RANGE_STRING) {
5391 case BASE_OCT: /* I'm lazy */
5393 switch(hfinfo->type) {
5398 format = "%s == %u";
5401 format = "%s == %" G_GINT64_MODIFIER "u";
5407 format = "%s == %d";
5410 format = "%s == %" G_GINT64_MODIFIER "d";
5413 DISSECTOR_ASSERT_NOT_REACHED();
5419 switch(hfinfo->type) {
5421 format = "%s == 0x%02x";
5424 format = "%s == 0x%04x";
5427 format = "%s == 0x%06x";
5430 format = "%s == 0x%08x";
5433 format = "%s == 0x%016" G_GINT64_MODIFIER "x";
5436 DISSECTOR_ASSERT_NOT_REACHED();
5441 DISSECTOR_ASSERT_NOT_REACHED();
5448 /* This function indicates whether it's possible to construct a
5449 * "match selected" display filter string for the specified field,
5450 * returns an indication of whether it's possible, and, if it's
5451 * possible and "filter" is non-null, constructs the filter and
5452 * sets "*filter" to point to it.
5453 * You do not need to [g_]free() this string since it will be automatically
5454 * freed once the next packet is dissected.
5457 construct_match_selected_string(field_info *finfo, epan_dissect_t *edt,
5460 header_field_info *hfinfo;
5466 gint start, length, length_remaining;
5468 gchar is_signed_num = FALSE;
5470 hfinfo = finfo->hfinfo;
5471 DISSECTOR_ASSERT(hfinfo);
5472 abbrev_len = strlen(hfinfo->abbrev);
5475 * XXX - we can't use the "val_to_string_repr" and "string_repr_len"
5476 * functions for FT_UINT and FT_INT types, as we choose the base in
5477 * the string expression based on the display base of the field.
5479 * Note that the base does matter, as this is also used for
5480 * the protocolinfo tap.
5482 * It might be nice to use them in "proto_item_fill_label()"
5483 * as well, although, there, you'd have to deal with the base
5484 * *and* with resolved values for addresses.
5486 * Perhaps we need two different val_to_string routines, one
5487 * to generate items for display filters and one to generate
5488 * strings for display, and pass to both of them the
5489 * "display" and "strings" values in the header_field_info
5490 * structure for the field, so they can get the base and,
5491 * if the field is Boolean or an enumerated integer type,
5492 * the tables used to generate human-readable values.
5494 switch(hfinfo->type) {
5500 is_signed_num = TRUE;
5507 * 4 bytes for " == ".
5510 * a sign + up to 10 digits of 32-bit integer,
5513 * "0x" + 8 digits of 32-bit integer, in hex;
5515 * 11 digits of 32-bit integer, in octal.
5516 * (No, we don't do octal, but this way,
5517 * we know that if we do, this will still
5520 * 1 byte for the trailing '\0'.
5522 if (filter != NULL) {
5523 dfilter_len = abbrev_len + 4 + 11 + 1;
5524 *filter = ep_alloc0(dfilter_len);
5525 format = hfinfo_numeric_format(hfinfo);
5527 g_snprintf(*filter, dfilter_len, format,
5529 fvalue_get_sinteger(&finfo->value));
5531 g_snprintf(*filter, dfilter_len, format,
5533 fvalue_get_uinteger(&finfo->value));
5541 * 4 bytes for " == ".
5544 * a sign + up to 20 digits of 32-bit integer,
5547 * "0x" + 16 digits of 32-bit integer, in hex;
5549 * 22 digits of 32-bit integer, in octal.
5550 * (No, we don't do octal, but this way,
5551 * we know that if we do, this will still
5554 * 1 byte for the trailing '\0'.
5556 if (filter != NULL) {
5557 dfilter_len = abbrev_len + 4 + 22 + 1;
5558 *filter = ep_alloc0(dfilter_len);
5559 format = hfinfo_numeric_format(hfinfo);
5560 g_snprintf(*filter, dfilter_len, format,
5562 fvalue_get_integer64(&finfo->value));
5568 *filter = ep_strdup(finfo->hfinfo->abbrev);
5574 * If the length is 0, just match the name of the
5577 * (Also check for negative values, just in case,
5578 * as we'll cast it to an unsigned value later.)
5580 length = finfo->length;
5583 *filter = ep_strdup(finfo->hfinfo->abbrev);
5590 * This doesn't have a value, so we'd match
5591 * on the raw bytes at this address.
5593 * Should we be allowed to access to the raw bytes?
5594 * If "edt" is NULL, the answer is "no".
5600 * Is this field part of the raw frame tvbuff?
5601 * If not, we can't use "frame[N:M]" to match
5604 * XXX - should this be frame-relative, or
5605 * protocol-relative?
5607 * XXX - does this fallback for non-registered
5608 * fields even make sense?
5610 if (finfo->ds_tvb != edt->tvb)
5611 return FALSE; /* you lose */
5614 * Don't go past the end of that tvbuff.
5616 length_remaining = tvb_length_remaining(finfo->ds_tvb, finfo->start);
5617 if (length > length_remaining)
5618 length = length_remaining;
5622 if (filter != NULL) {
5623 start = finfo->start;
5624 buf_len = 32 + length * 3;
5625 *filter = ep_alloc0(buf_len);
5628 ptr += g_snprintf(ptr, buf_len-(ptr-*filter),
5629 "frame[%d:%d] == ", finfo->start, length);
5630 for (i=0;i<length; i++) {
5631 c = tvb_get_guint8(finfo->ds_tvb, start);
5634 ptr += g_snprintf(ptr, buf_len-(ptr-*filter), "%02x", c);
5637 ptr += g_snprintf(ptr, buf_len-(ptr-*filter), ":%02x", c);
5643 /* By default, use the fvalue's "to_string_repr" method. */
5645 /* Figure out the string length needed.
5646 * The ft_repr length.
5647 * 4 bytes for " == ".
5648 * 1 byte for trailing NUL.
5650 if (filter != NULL) {
5651 dfilter_len = fvalue_string_repr_len(&finfo->value,
5653 dfilter_len += abbrev_len + 4 + 1;
5654 *filter = ep_alloc0(dfilter_len);
5656 /* Create the string */
5657 g_snprintf(*filter, dfilter_len, "%s == ",
5659 fvalue_to_string_repr(&finfo->value,
5661 &(*filter)[abbrev_len + 4]);
5670 * Returns TRUE if we can do a "match selected" on the field, FALSE
5674 proto_can_match_selected(field_info *finfo, epan_dissect_t *edt)
5676 return construct_match_selected_string(finfo, edt, NULL);
5679 /* This function attempts to construct a "match selected" display filter
5680 * string for the specified field; if it can do so, it returns a pointer
5681 * to the string, otherwise it returns NULL.
5683 * The string is allocated with packet lifetime scope.
5684 * You do not need to [g_]free() this string since it will be automatically
5685 * freed once the next packet is dissected.
5688 proto_construct_match_selected_string(field_info *finfo, epan_dissect_t *edt)
5692 if (!construct_match_selected_string(finfo, edt, &filter))
5698 /* This function will dissect a sequence of bytes that describe a
5700 * hf_hdr is a 8/16/24/32 bit integer that describes the bitmask to be dissected.
5701 * This field will form an expansion under which the individual fields of the
5702 * bitmask is dissected and displayed.
5703 * This field must be of the type FT_[U]INT{8|16|24|32}.
5705 * fields is an array of pointers to int that lists all the fields of the
5706 * bitmask. These fields can be either of the type FT_BOOLEAN for flags
5707 * or another integer of the same type/size as hf_hdr with a mask specified.
5708 * This array is terminated by a NULL entry.
5710 * FT_BOOLEAN bits that are set to 1 will have the name added to the expansion.
5711 * FT_integer fields that have a value_string attached will have the
5712 * matched string displayed on the expansion line.
5715 proto_tree_add_bitmask(proto_tree *parent_tree, tvbuff_t *tvb, int offset, int hf_hdr, gint ett, const int **fields, gboolean little_endian)
5717 proto_tree *tree=NULL;
5718 proto_item *item=NULL;
5719 header_field_info *hf_info;
5723 hf_info=proto_registrar_get_nth(hf_hdr);
5724 switch(hf_info->type){
5728 value=tvb_get_guint8(tvb, offset);
5734 value=tvb_get_letohs(tvb, offset);
5736 value=tvb_get_ntohs(tvb, offset);
5743 value=tvb_get_letoh24(tvb, offset);
5745 value=tvb_get_ntoh24(tvb, offset);
5752 value=tvb_get_letohl(tvb, offset);
5754 value=tvb_get_ntohl(tvb, offset);
5758 g_assert_not_reached();
5762 item=proto_tree_add_item(parent_tree, hf_hdr, tvb, offset, len, little_endian);
5763 tree=proto_item_add_subtree(item, ett);
5767 header_field_info *hf_field;
5768 guint32 tmpval, tmpmask;
5770 hf_field=proto_registrar_get_nth(**fields);
5771 switch(hf_field->type){
5780 proto_tree_add_item(tree, **fields, tvb, offset, len, little_endian);
5782 /* Mask and shift out the value */
5783 tmpmask=hf_field->bitmask;
5787 while(!(tmpmask&0x00000001)){
5792 /* Show the value_string content (if there is one) */
5793 if(hf_field->strings && hf_field->display != BASE_CUSTOM){
5794 proto_item_append_text(item, ", %s", val_to_str(tmpval, hf_field->strings, "Unknown"));
5799 proto_tree_add_item(tree, **fields, tvb, offset, len, little_endian);
5800 /* if the flag is set, show the name */
5801 if(hf_field->bitmask&value){
5802 proto_item_append_text(item, ", %s", hf_field->name);
5806 g_assert_not_reached();
5816 proto_tree_add_bits_item(proto_tree *tree, int hf_index, tvbuff_t *tvb, gint bit_offset, gint no_of_bits, gboolean little_endian)
5818 return proto_tree_add_bits_ret_val(tree, hf_index, tvb, bit_offset, no_of_bits, NULL, little_endian);
5822 * This function will dissect a sequence of bits that does not need to be byte aligned the bits
5823 * set vill be shown in the tree as ..10 10.. and the integer value returned if return_value is set.
5824 * Offset should be given in bits from the start of the tvb.
5828 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)
5833 guint8 remaining_bits;
5834 guint64 mask = 0,tmp;
5836 header_field_info *hf_field;
5841 hf_field = proto_registrar_get_nth(hf_index);
5843 if(hf_field -> bitmask != 0) {
5844 REPORT_DISSECTOR_BUG(ep_strdup_printf("Incompatible use of proto_tree_add_bits_ret_val with field '%s' (%s) with bitmask != 0",
5845 hf_field->abbrev, hf_field->name));
5848 /* Byte align offset */
5849 offset = bit_offset>>3;
5853 * Calculate the number of octets used to hold the bits
5855 tot_no_bits = ((bit_offset&0x7)+no_of_bits);
5856 length = tot_no_bits>>3;
5857 remaining_bits = tot_no_bits % 8;
5858 if ((remaining_bits)!=0)
5861 if (no_of_bits < 9){
5862 value = tvb_get_bits8(tvb, bit_offset, no_of_bits);
5863 }else if(no_of_bits < 17){
5864 value = tvb_get_bits16(tvb, bit_offset, no_of_bits, little_endian);
5865 }else if(no_of_bits < 33){
5866 value = tvb_get_bits32(tvb, bit_offset, no_of_bits, little_endian);
5867 }else if(no_of_bits < 65){
5868 value = tvb_get_bits64(tvb, bit_offset, no_of_bits, little_endian);
5869 }else if(no_of_bits>64){
5870 DISSECTOR_ASSERT_NOT_REACHED();
5876 mask = mask << (no_of_bits-1);
5878 /* prepare the string */
5881 for(bit=0;bit<((int)(bit_offset&0x07));bit++){
5882 if(bit&&(!(bit%4))){
5887 /* read the bits for the int */
5888 for(i=0;i<no_of_bits;i++){
5889 if(bit&&(!(bit%4))){
5892 if(bit&&(!(bit%8))){
5905 if(bit&&(!(bit%4))){
5912 *return_value=value;
5918 strcat(str,hf_field->name);
5920 switch(hf_field->type){
5923 if (hf_field->strings) {
5924 const true_false_string *tfstring = &tfs_true_false;
5925 tfstring = (const struct true_false_string*) hf_field->strings;
5927 return proto_tree_add_boolean_format(tree, hf_index, tvb, offset, length, (guint32)value,
5930 (guint32)value ? tfstring->true_string : tfstring->false_string);
5932 return proto_tree_add_boolean_format(tree, hf_index, tvb, offset, length, (guint32)value,
5942 /* 1 - 32 bits field */
5943 if (hf_field->strings) {
5944 return proto_tree_add_uint_format(tree, hf_index, tvb, offset, length, (guint32)value,
5947 val_to_str((guint32)value, cVALS(hf_field->strings), "Unknown "),
5951 switch(hf_field->display){
5953 return proto_tree_add_uint_format(tree, hf_index, tvb, offset, length, (guint32)value,
5959 return proto_tree_add_uint_format(tree, hf_index, tvb, offset, length, (guint32)value,
5965 DISSECTOR_ASSERT_NOT_REACHED();
5971 switch(hf_field->display){
5973 return proto_tree_add_uint64_format(tree, hf_index, tvb, offset, length, value,
5974 "%s: %" G_GINT64_MODIFIER "u",
5978 return proto_tree_add_uint64_format(tree, hf_index, tvb, offset, length, value,
5979 "%s: 0x%" G_GINT64_MODIFIER "x",
5983 DISSECTOR_ASSERT_NOT_REACHED();
5989 DISSECTOR_ASSERT_NOT_REACHED();