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 #ifdef NEED_G_ASCII_STRCASECMP_H
51 #include "g_ascii_strcasecmp.h"
54 #define SUBTREE_ONCE_ALLOCATION_NUMBER 8
55 #define SUBTREE_MAX_LEVELS 256
58 typedef struct __subtree_lvl {
65 subtree_lvl *pushed_tree;
66 guint8 pushed_tree_index;
67 guint8 pushed_tree_max;
73 /* Candidates for assembler */
75 wrs_count_bitshift(guint32 bitmask)
79 while ((bitmask & (1 << bitshift)) == 0)
86 #define cVALS(x) (const value_string*)(x)
89 #define TRY_TO_FAKE_THIS_ITEM(tree, hfindex) \
90 /* If this item is not referenced we dont have to do much work \
91 at all but we should still return a node so that \
92 field items below this node ( think proto_item_add_subtree() )\
93 will still have somewhere to attach to \
94 or else filtering will not work (they would be ignored since tree\
96 DONT try to fake a node where PITEM_FINFO(pi) is NULL \
97 since dissectors that want to do proto_item_set_len() or \
98 other operations that dereference this would crash. \
99 We dont fake FT_PROTOCOL either since these are cheap and \
100 some stuff (proto hier stat) assumes they always exist. \
102 if(!(PTREE_DATA(tree)->visible)){ \
103 if(PITEM_FINFO(tree)){ \
104 register header_field_info *hfinfo; \
105 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo); \
106 if((hfinfo->ref_count == 0) \
107 && (hfinfo->type!=FT_PROTOCOL)){ \
108 /* just return tree back to the caller */\
114 #define TRY_TO_FAKE_THIS_ITEM(tree, hfindex) ;
118 proto_tree_free_node(proto_node *node, gpointer data);
120 static void fill_label_boolean(field_info *fi, gchar *label_str);
121 static void fill_label_uint(field_info *fi, gchar *label_str);
122 static void fill_label_uint64(field_info *fi, gchar *label_str);
123 static void fill_label_enumerated_uint(field_info *fi, gchar *label_str);
124 static void fill_label_enumerated_bitfield(field_info *fi, gchar *label_str);
125 static void fill_label_numeric_bitfield(field_info *fi, gchar *label_str);
126 static void fill_label_int(field_info *fi, gchar *label_str);
127 static void fill_label_int64(field_info *fi, gchar *label_str);
128 static void fill_label_enumerated_int(field_info *fi, gchar *label_str);
130 int hfinfo_bitwidth(header_field_info *hfinfo);
131 static const char* hfinfo_uint_vals_format(header_field_info *hfinfo);
132 static const char* hfinfo_uint_format(header_field_info *hfinfo);
133 static const char* hfinfo_uint_value_format(header_field_info *hfinfo);
134 static const char* hfinfo_uint64_format(header_field_info *hfinfo);
135 static const char* hfinfo_int_vals_format(header_field_info *hfinfo);
136 static const char* hfinfo_int_format(header_field_info *hfinfo);
137 static const char* hfinfo_int_value_format(header_field_info *hfinfo);
138 static const char* hfinfo_int64_format(header_field_info *hfinfo);
141 proto_tree_add_node(proto_tree *tree, field_info *fi);
143 static header_field_info *
144 get_hfi_and_length(int hfindex, tvbuff_t *tvb, gint start, gint *length,
148 new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
149 gint start, gint item_length);
152 alloc_field_info(proto_tree *tree, int hfindex, tvbuff_t *tvb,
153 gint start, gint *length);
156 proto_tree_add_pi(proto_tree *tree, int hfindex, tvbuff_t *tvb,
157 gint start, gint *length, field_info **pfi);
160 proto_tree_set_representation_value(proto_item *pi, const char *format, va_list ap);
162 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap);
165 proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb);
167 proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length);
169 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length);
171 proto_tree_set_time(field_info *fi, nstime_t *value_ptr);
173 proto_tree_set_string(field_info *fi, const char* value);
175 proto_tree_set_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
177 proto_tree_set_ebcdic_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
179 proto_tree_set_ether(field_info *fi, const guint8* value);
181 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start);
183 proto_tree_set_ipxnet(field_info *fi, guint32 value);
185 proto_tree_set_ipv4(field_info *fi, guint32 value);
187 proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr);
189 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start);
191 proto_tree_set_guid(field_info *fi, const e_guid_t *value_ptr);
193 proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gboolean little_endian);
195 proto_tree_set_oid(field_info *fi, const guint8* value_ptr, gint length);
197 proto_tree_set_oid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
199 proto_tree_set_boolean(field_info *fi, guint32 value);
201 proto_tree_set_float(field_info *fi, float value);
203 proto_tree_set_double(field_info *fi, double value);
205 proto_tree_set_uint(field_info *fi, guint32 value);
207 proto_tree_set_int(field_info *fi, gint32 value);
209 proto_tree_set_uint64(field_info *fi, guint64 value);
211 proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start, guint length, gboolean little_endian);
213 static int proto_register_field_init(header_field_info *hfinfo, int parent);
215 /* special-case header field used within proto.c */
216 int hf_text_only = -1;
218 /* Structure for information about a protocol */
220 const char *name; /* long description */
221 const char *short_name; /* short description */
222 const char *filter_name; /* name of this protocol in filters */
223 int proto_id; /* field ID for this protocol */
224 GList *fields; /* fields for this protocol */
225 GList *last_field; /* pointer to end of list of fields */
226 gboolean is_enabled; /* TRUE if protocol is enabled */
227 gboolean can_toggle; /* TRUE if is_enabled can be changed */
230 /* List of all protocols */
231 static GList *protocols = NULL;
233 #define INITIAL_NUM_PROTOCOL_HFINFO 200
236 /* Contains information about protocols and header fields. Used when
237 * dissectors register their data */
238 static GMemChunk *gmc_hfinfo = NULL;
240 /* Contains information about a field when a dissector calls
241 * proto_tree_add_item. */
242 SLAB_ITEM_TYPE_DEFINE(field_info)
243 static SLAB_FREE_LIST_DEFINE(field_info)
244 static field_info *field_info_tmp=NULL;
245 #define FIELD_INFO_NEW(fi) \
246 SLAB_ALLOC(fi, field_info)
247 #define FIELD_INFO_FREE(fi) \
248 SLAB_FREE(fi, field_info)
252 /* Contains the space for proto_nodes. */
253 SLAB_ITEM_TYPE_DEFINE(proto_node)
254 static SLAB_FREE_LIST_DEFINE(proto_node)
255 #define PROTO_NODE_NEW(node) \
256 SLAB_ALLOC(node, proto_node) \
257 node->first_child = NULL; \
258 node->last_child = NULL; \
261 #define PROTO_NODE_FREE(node) \
262 SLAB_FREE(node, proto_node)
266 /* String space for protocol and field items for the GUI */
267 SLAB_ITEM_TYPE_DEFINE(item_label_t)
268 static SLAB_FREE_LIST_DEFINE(item_label_t)
269 #define ITEM_LABEL_NEW(il) \
270 SLAB_ALLOC(il, item_label_t)
271 #define ITEM_LABEL_FREE(il) \
272 SLAB_FREE(il, item_label_t)
275 #define PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo) \
276 DISSECTOR_ASSERT((guint)hfindex < gpa_hfinfo.len); \
277 hfinfo=gpa_hfinfo.hfi[hfindex];
280 /* List which stores protocols and fields that have been registered */
281 typedef struct _gpa_hfinfo_t {
283 guint32 allocated_len;
284 header_field_info **hfi;
286 gpa_hfinfo_t gpa_hfinfo;
288 /* Balanced tree of abbreviations and IDs */
289 static GTree *gpa_name_tree = NULL;
290 static header_field_info *same_name_hfinfo;
292 static void save_same_name_hfinfo(gpointer data)
294 same_name_hfinfo = (header_field_info*)data;
297 /* Points to the first element of an array of Booleans, indexed by
298 a subtree item type; that array element is TRUE if subtrees of
299 an item of that type are to be expanded. */
300 gboolean *tree_is_expanded;
302 /* Number of elements in that array. */
305 /* Name hashtables for fast detection of duplicate names */
306 static GHashTable* proto_names = NULL;
307 static GHashTable* proto_short_names = NULL;
308 static GHashTable* proto_filter_names = NULL;
311 proto_compare_name(gconstpointer p1_arg, gconstpointer p2_arg)
313 const protocol_t *p1 = p1_arg;
314 const protocol_t *p2 = p2_arg;
316 return g_ascii_strcasecmp(p1->short_name, p2->short_name);
320 /* initialize data structures and register protocols and fields */
322 proto_init(void (register_all_protocols)(register_cb cb, gpointer client_data),
323 void (register_all_protocol_handoffs)(register_cb cb, gpointer client_data),
325 gpointer client_data)
327 static hf_register_info hf[] = {
329 { "Text item", "", FT_NONE, BASE_NONE, NULL, 0x0,
334 proto_names = g_hash_table_new(g_int_hash, g_int_equal);
335 proto_short_names = g_hash_table_new(wrs_str_hash, g_str_equal);
336 proto_filter_names = g_hash_table_new(wrs_str_hash, g_str_equal);
340 gmc_hfinfo = g_mem_chunk_new("gmc_hfinfo",
341 sizeof(header_field_info),
342 INITIAL_NUM_PROTOCOL_HFINFO * sizeof(header_field_info),
346 gpa_hfinfo.allocated_len=0;
348 gpa_name_tree = g_tree_new_full(wrs_strcmp_with_data, NULL, NULL, save_same_name_hfinfo);
350 /* Initialize the ftype subsystem */
353 /* Register one special-case FT_TEXT_ONLY field for use when
354 converting wireshark to new-style proto_tree. These fields
355 are merely strings on the GUI tree; they are not filterable */
356 proto_register_field_array(-1, hf, array_length(hf));
358 /* Have each built-in dissector register its protocols, fields,
359 dissector tables, and dissectors to be called through a
360 handle, and do whatever one-time initialization it needs to
362 register_all_protocols(cb, client_data);
365 /* Now scan for plugins and load all the ones we find, calling
366 their register routines to do the stuff described above. */
368 (*cb)(RA_PLUGIN_REGISTER, NULL, client_data);
370 register_all_plugin_registrations();
373 /* Now call the "handoff registration" routines of all built-in
374 dissectors; those routines register the dissector in other
375 dissectors' handoff tables, and fetch any dissector handles
377 register_all_protocol_handoffs(cb, client_data);
380 /* Now do the same with plugins. */
382 (*cb)(RA_PLUGIN_HANDOFF, NULL, client_data);
383 register_all_plugin_handoffs();
386 /* sort the protocols by protocol name */
387 protocols = g_list_sort(protocols, proto_compare_name);
389 /* We've assigned all the subtree type values; allocate the array
390 for them, and zero it out. */
391 tree_is_expanded = g_malloc(num_tree_types*sizeof (gboolean));
392 memset(tree_is_expanded, 0, num_tree_types*sizeof (gboolean));
398 /* Free the abbrev/ID GTree */
400 g_tree_destroy(gpa_name_tree);
401 gpa_name_tree = NULL;
405 g_mem_chunk_destroy(gmc_hfinfo);
407 if(gpa_hfinfo.allocated_len){
409 gpa_hfinfo.allocated_len=0;
410 g_free(gpa_hfinfo.hfi);
413 if (tree_is_expanded != NULL)
414 g_free(tree_is_expanded);
419 proto_tree_traverse_pre_order(proto_tree *tree, proto_tree_traverse_func func,
422 proto_node *pnode = tree;
426 if (func(pnode, data))
429 child = pnode->first_child;
430 while (child != NULL) {
432 * The routine we call might modify the child, e.g. by
433 * freeing it, so we get the child's successor before
434 * calling that routine.
437 child = current->next;
438 if (proto_tree_traverse_pre_order((proto_tree *)current, func,
447 proto_tree_traverse_in_order(proto_tree *tree, proto_tree_traverse_func func,
450 proto_node *pnode = tree;
454 child = pnode->first_child;
457 * The routine we call might modify the child, e.g. by
458 * freeing it, so we get the child's successor before
459 * calling that routine.
462 child = current->next;
464 if (proto_tree_traverse_in_order((proto_tree *)current, func,
468 if (func(pnode, data))
471 while (child != NULL) {
473 * The routine we call might modify the child, e.g. by
474 * freeing it, so we get the child's successor before
475 * calling that routine.
478 child = current->next;
479 if (proto_tree_traverse_in_order((proto_tree *)current,
484 if (func(pnode, data))
492 proto_tree_children_foreach(proto_tree *tree, proto_tree_foreach_func func,
495 proto_node *node = tree;
498 node = node->first_child;
499 while (node != NULL) {
501 node = current->next;
502 func((proto_tree *)current, data);
506 /* frees the resources that the dissection a proto_tree uses */
508 proto_tree_free(proto_tree *tree)
510 proto_tree_traverse_in_order(tree, proto_tree_free_node, NULL);
514 free_GPtrArray_value(gpointer key, gpointer value, gpointer user_data _U_)
516 GPtrArray *ptrs = value;
517 gint hfid = (gint)(long)key;
518 header_field_info *hfinfo;
521 PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
522 if(hfinfo->ref_count){
523 /* when a field is referenced by a filter this also
524 affects the refcount for the parent protocol so we need
525 to adjust the refcount for the parent as well
527 if( (hfinfo->parent != -1) && (hfinfo->ref_count) ){
528 header_field_info *parent_hfinfo;
529 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
530 parent_hfinfo->ref_count -= hfinfo->ref_count;
532 hfinfo->ref_count = 0;
535 g_ptr_array_free(ptrs, TRUE);
539 free_node_tree_data(tree_data_t *tree_data)
541 /* Free all the GPtrArray's in the interesting_hfids hash. */
542 g_hash_table_foreach(tree_data->interesting_hfids,
543 free_GPtrArray_value, NULL);
545 /* And then destroy the hash. */
546 g_hash_table_destroy(tree_data->interesting_hfids);
548 /* And finally the tree_data_t itself. */
552 #define FREE_NODE_FIELD_INFO(finfo) \
554 ITEM_LABEL_FREE(finfo->rep); \
556 FVALUE_CLEANUP(&finfo->value); \
557 FIELD_INFO_FREE(finfo);
560 proto_tree_free_node(proto_node *node, gpointer data _U_)
562 field_info *finfo = PITEM_FINFO(node);
565 /* This is the root node. Destroy the per-tree data.
566 * There is no field_info to destroy. */
567 free_node_tree_data(PTREE_DATA(node));
570 /* This is a child node. Don't free the per-tree data, but
571 * do free the field_info data. */
572 FREE_NODE_FIELD_INFO(finfo);
575 /* Free the proto_node. */
576 PROTO_NODE_FREE(node);
578 return FALSE; /* FALSE = do not end traversal of protocol tree */
581 /* Is the parsing being done for a visible proto_tree or an invisible one?
582 * By setting this correctly, the proto_tree creation is sped up by not
583 * having to call g_vsnprintf and copy strings around.
586 proto_tree_set_visible(proto_tree *tree, gboolean visible)
588 PTREE_DATA(tree)->visible = visible;
591 /* Assume dissector set only its protocol fields.
592 This function is called by dissectors and allowes to speed up filtering
593 in wireshark, if this function returns FALSE it is safe to reset tree to NULL
594 and thus skip calling most of the expensive proto_tree_add_...()
596 If the tree is visible we implicitely assume the field is referenced.
599 proto_field_is_referenced(proto_tree *tree, int proto_id)
601 register header_field_info *hfinfo;
607 if (PTREE_DATA(tree)->visible)
610 PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
611 if (hfinfo->ref_count != 0)
618 /* Finds a record in the hf_info_records array by id. */
620 proto_registrar_get_nth(guint hfindex)
622 register header_field_info *hfinfo;
624 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
629 /* Prefix initialization
630 * this allows for a dissector to register a display filter name prefix
631 * so that it can delay the initialization of the hf array as long as
635 /* compute a hash for the part before the dot of a display filter */
636 static guint prefix_hash (gconstpointer key) {
637 /* end the string at the dot and compute its hash */
638 gchar* copy = ep_strdup(key);
648 return g_str_hash(copy);
651 /* are both strings equal up to the end or the dot? */
652 static gboolean prefix_equal (gconstpointer ap,gconstpointer bp) {
660 if ((ac == '.' || ac == '\0') && (bc == '.' || bc == '\0')) return TRUE;
662 if ( (ac == '.' || ac == '\0') && ! (bc == '.' || bc == '\0') ) return FALSE;
663 if ( (bc == '.' || bc == '\0') && ! (ac == '.' || ac == '\0') ) return FALSE;
665 if (ac != bc) return FALSE;
672 /* indexed by prefix, contains initializers */
673 static GHashTable* prefixes = NULL;
676 /* Register a new prefix for "delayed" initialization of field arrays */
678 proto_register_prefix(const char *prefix, prefix_initializer_t pi ) {
680 prefixes = g_hash_table_new(prefix_hash,prefix_equal);
683 g_hash_table_insert(prefixes,(gpointer)prefix,pi);
686 /* helper to call all prefix initializers */
687 static gboolean initialize_prefix(gpointer k, gpointer v, gpointer u _U_) {
688 ((prefix_initializer_t)v)(k);
692 /** Initialize every remaining uninitialized prefix. */
693 void proto_initialize_all_prefixes(void) {
694 g_hash_table_foreach_remove(prefixes, initialize_prefix, NULL);
697 /* Finds a record in the hf_info_records array by name.
698 * If it fails to find it in the already registered fields,
699 * it tries to find and call an initializer in the prefixes
700 * table and if so it looks again.
703 proto_registrar_get_byname(const char *field_name)
705 header_field_info* hfinfo;
706 prefix_initializer_t pi;
708 DISSECTOR_ASSERT(field_name != NULL);
710 hfinfo = g_tree_lookup(gpa_name_tree, field_name);
712 if (hfinfo) return hfinfo;
714 if (!prefixes) return NULL;
716 if(( pi = g_hash_table_lookup(prefixes,field_name) )) {
718 g_hash_table_remove(prefixes,field_name);
723 return g_tree_lookup(gpa_name_tree, field_name);
727 void ptvcursor_new_subtree_levels(ptvcursor_t * ptvc)
729 subtree_lvl * pushed_tree;
731 DISSECTOR_ASSERT(ptvc->pushed_tree_max <= SUBTREE_MAX_LEVELS-SUBTREE_ONCE_ALLOCATION_NUMBER);
732 ptvc->pushed_tree_max += SUBTREE_ONCE_ALLOCATION_NUMBER;
734 pushed_tree = ep_alloc(sizeof(subtree_lvl) * ptvc->pushed_tree_max);
735 DISSECTOR_ASSERT(pushed_tree != NULL);
736 if (ptvc->pushed_tree)
737 memcpy(pushed_tree, ptvc->pushed_tree, ptvc->pushed_tree_max - SUBTREE_ONCE_ALLOCATION_NUMBER);
738 ptvc->pushed_tree = pushed_tree;
741 void ptvcursor_free_subtree_levels(ptvcursor_t * ptvc)
743 ptvc->pushed_tree = NULL;
744 ptvc->pushed_tree_max = 0;
745 DISSECTOR_ASSERT(ptvc->pushed_tree_index ==0);
746 ptvc->pushed_tree_index = 0;
749 /* Allocates an initializes a ptvcursor_t with 3 variables:
750 * proto_tree, tvbuff, and offset. */
752 ptvcursor_new(proto_tree *tree, tvbuff_t *tvb, gint offset)
756 ptvc = ep_alloc(sizeof(ptvcursor_t));
759 ptvc->offset = offset;
760 ptvc->pushed_tree= NULL;
761 ptvc->pushed_tree_max= 0;
762 ptvc->pushed_tree_index= 0;
767 /* Frees memory for ptvcursor_t, but nothing deeper than that. */
769 ptvcursor_free(ptvcursor_t *ptvc)
771 ptvcursor_free_subtree_levels(ptvc);
775 /* Returns tvbuff. */
777 ptvcursor_tvbuff(ptvcursor_t* ptvc)
782 /* Returns current offset. */
784 ptvcursor_current_offset(ptvcursor_t* ptvc)
790 ptvcursor_tree(ptvcursor_t* ptvc)
799 ptvcursor_set_tree(ptvcursor_t* ptvc, proto_tree *tree)
804 /* creates a subtree, sets it as the working tree and pushes the old working tree */
806 ptvcursor_push_subtree(ptvcursor_t *ptvc, proto_item *it, gint ett_subtree)
808 subtree_lvl * subtree;
809 if (ptvc->pushed_tree_index >= ptvc->pushed_tree_max)
810 ptvcursor_new_subtree_levels(ptvc);
812 subtree = ptvc->pushed_tree+ptvc->pushed_tree_index;
813 subtree->tree = ptvc->tree;
815 ptvc->pushed_tree_index++;
816 return ptvcursor_set_subtree(ptvc, it, ett_subtree);
821 ptvcursor_pop_subtree(ptvcursor_t *ptvc)
823 subtree_lvl * subtree;
824 if (ptvc->pushed_tree_index <= 0)
827 ptvc->pushed_tree_index--;
828 subtree = ptvc->pushed_tree+ptvc->pushed_tree_index;
829 if (subtree->it != NULL)
830 proto_item_set_len(subtree->it, ptvcursor_current_offset(ptvc) - subtree->cursor_offset);
831 ptvc->tree = subtree->tree;
834 /* saves the current tvb offset and the item in the current subtree level */
835 void ptvcursor_subtree_set_item(ptvcursor_t * ptvc, proto_item * it)
837 subtree_lvl * subtree;
839 DISSECTOR_ASSERT(ptvc->pushed_tree_index > 0);
841 subtree = ptvc->pushed_tree+ptvc->pushed_tree_index-1;
843 subtree->cursor_offset = ptvcursor_current_offset(ptvc);
846 /* Creates a subtree and adds it to the cursor as the working tree but does not
847 * save the old working tree */
849 ptvcursor_set_subtree(ptvcursor_t *ptvc, proto_item *it, gint ett_subtree)
851 ptvc->tree = proto_item_add_subtree(it, ett_subtree);
855 proto_tree* ptvcursor_add_subtree_item(ptvcursor_t * ptvc, proto_item * it, gint ett_subtree, gint length)
857 ptvcursor_push_subtree(ptvc, it, ett_subtree);
858 if (length == SUBTREE_UNDEFINED_LENGTH)
859 ptvcursor_subtree_set_item(ptvc, it);
860 return ptvcursor_tree(ptvc);
863 /* Add an item to the tree and create a subtree
864 * If the length is unknown, length may be defined as SUBTREE_UNDEFINED_LENGTH.
865 * In this case, when the subtree will be closed, the parent item length will
866 * be equal to the advancement of the cursor since the creation of the subtree.
868 proto_tree* ptvcursor_add_with_subtree(ptvcursor_t * ptvc, int hfindex, gint length,
869 gboolean little_endian, gint ett_subtree)
872 it = ptvcursor_add_no_advance(ptvc, hfindex, length, little_endian);
873 return ptvcursor_add_subtree_item(ptvc, it, ett_subtree, length);
877 proto_tree_add_text_node(proto_tree *tree, tvbuff_t *tvb, gint start, gint length);
879 /* Add a text node to the tree and create a subtree
880 * If the length is unknown, length may be defined as SUBTREE_UNDEFINED_LENGTH.
881 * In this case, when the subtree will be closed, the item length will be equal
882 * to the advancement of the cursor since the creation of the subtree.
884 proto_tree * ptvcursor_add_text_with_subtree(ptvcursor_t * ptvc, gint length,
885 gint ett_subtree, const char *format, ...)
890 it = proto_tree_add_text_node(ptvcursor_tree(ptvc), ptvcursor_tvbuff(ptvc),
891 ptvcursor_current_offset(ptvc), length);
893 va_start(ap, format);
894 proto_tree_set_representation(it, format, ap);
897 return ptvcursor_add_subtree_item(ptvc, it, ett_subtree, length);
900 /* Add a text-only node, leaving it to our caller to fill the text in */
902 proto_tree_add_text_node(proto_tree *tree, tvbuff_t *tvb, gint start, gint length)
906 pi = proto_tree_add_pi(tree, hf_text_only, tvb, start, &length, NULL);
913 /* Add a text-only node to the proto_tree */
915 proto_tree_add_text(proto_tree *tree, tvbuff_t *tvb, gint start, gint length,
916 const char *format, ...)
921 pi = proto_tree_add_text_node(tree, tvb, start, length);
925 va_start(ap, format);
926 proto_tree_set_representation(pi, format, ap);
932 /* Add a text-only node to the proto_tree (va_list version) */
934 proto_tree_add_text_valist(proto_tree *tree, tvbuff_t *tvb, gint start,
935 gint length, const char *format, va_list ap)
939 pi = proto_tree_add_text_node(tree, tvb, start, length);
943 proto_tree_set_representation(pi, format, ap);
948 /* Add a text-only node for debugging purposes. The caller doesn't need
949 * to worry about tvbuff, start, or length. Debug message gets sent to
952 proto_tree_add_debug_text(proto_tree *tree, const char *format, ...)
957 pi = proto_tree_add_text_node(tree, NULL, 0, 0);
959 va_start(ap, format);
961 proto_tree_set_representation(pi, format, ap);
971 get_uint_value(tvbuff_t *tvb, gint offset, gint length, gboolean little_endian)
978 value = tvb_get_guint8(tvb, offset);
982 value = little_endian ? tvb_get_letohs(tvb, offset)
983 : tvb_get_ntohs(tvb, offset);
987 value = little_endian ? tvb_get_letoh24(tvb, offset)
988 : tvb_get_ntoh24(tvb, offset);
992 value = little_endian ? tvb_get_letohl(tvb, offset)
993 : tvb_get_ntohl(tvb, offset);
997 DISSECTOR_ASSERT_NOT_REACHED();
1005 get_int_value(tvbuff_t *tvb, gint offset, gint length, gboolean little_endian)
1012 value = (gint8)tvb_get_guint8(tvb, offset);
1016 value = (gint16) (little_endian ? tvb_get_letohs(tvb, offset)
1017 : tvb_get_ntohs(tvb, offset));
1021 value = little_endian ? tvb_get_letoh24(tvb, offset)
1022 : tvb_get_ntoh24(tvb, offset);
1023 if (value & 0x00800000) {
1024 /* Sign bit is set; sign-extend it. */
1025 value |= 0xFF000000;
1030 value = little_endian ? tvb_get_letohl(tvb, offset)
1031 : tvb_get_ntohl(tvb, offset);
1035 DISSECTOR_ASSERT_NOT_REACHED();
1042 /* Add an item to a proto_tree, using the text label registered to that item;
1043 the item is extracted from the tvbuff handed to it. */
1045 proto_tree_new_item(field_info *new_fi, proto_tree *tree, int hfindex,
1046 tvbuff_t *tvb, gint start, gint length, gboolean little_endian)
1056 /* there is a possibility here that we might raise an exception
1057 * and thus would lose track of the field_info.
1058 * store it in a temp so that if we come here again we can reclaim
1059 * the field_info without leaking memory.
1061 /* XXX this only keeps track of one field_info struct,
1062 if we ever go multithreaded for calls to this function
1063 we have to change this code to use per thread variable.
1066 /* oops, last one we got must have been lost due
1068 * good thing we saved it, now we can reverse the
1069 * memory leak and reclaim it.
1071 SLAB_FREE(field_info_tmp, field_info);
1073 /* we might throw an exception, keep track of this one
1074 * across the "dangerous" section below.
1076 field_info_tmp=new_fi;
1078 switch(new_fi->hfinfo->type) {
1080 /* no value to set for FT_NONE */
1084 proto_tree_set_protocol_tvb(new_fi, tvb);
1088 proto_tree_set_bytes_tvb(new_fi, tvb, start, length);
1092 n = get_uint_value(tvb, start, length, little_endian);
1093 proto_tree_set_bytes_tvb(new_fi, tvb, start + length, n);
1095 /* Instead of calling proto_item_set_len(), since we don't yet
1096 * have a proto_item, we set the field_info's length ourselves. */
1097 new_fi->length = n + length;
1101 proto_tree_set_boolean(new_fi,
1102 get_uint_value(tvb, start, length, little_endian));
1105 /* XXX - make these just FT_UINT? */
1110 proto_tree_set_uint(new_fi,
1111 get_uint_value(tvb, start, length, little_endian));
1116 DISSECTOR_ASSERT( length <= 8 && length >= 1);
1117 proto_tree_set_uint64_tvb(new_fi, tvb, start, length, little_endian);
1120 /* XXX - make these just FT_INT? */
1125 proto_tree_set_int(new_fi,
1126 get_int_value(tvb, start, length, little_endian));
1130 DISSECTOR_ASSERT(length == 4);
1131 value = tvb_get_ipv4(tvb, start);
1132 proto_tree_set_ipv4(new_fi, little_endian ? GUINT32_SWAP_LE_BE(value) : value);
1136 DISSECTOR_ASSERT(length == 4);
1137 proto_tree_set_ipxnet(new_fi,
1138 get_uint_value(tvb, start, 4, FALSE));
1142 DISSECTOR_ASSERT(length == 16);
1143 proto_tree_set_ipv6_tvb(new_fi, tvb, start);
1147 DISSECTOR_ASSERT(length == 6);
1148 proto_tree_set_ether_tvb(new_fi, tvb, start);
1152 DISSECTOR_ASSERT(length == 16);
1153 proto_tree_set_guid_tvb(new_fi, tvb, start, little_endian);
1157 proto_tree_set_oid_tvb(new_fi, tvb, start, length);
1161 DISSECTOR_ASSERT(length == 4);
1163 floatval = tvb_get_letohieee_float(tvb, start);
1165 floatval = tvb_get_ntohieee_float(tvb, start);
1166 proto_tree_set_float(new_fi, floatval);
1170 DISSECTOR_ASSERT(length == 8);
1172 doubleval = tvb_get_letohieee_double(tvb, start);
1174 doubleval = tvb_get_ntohieee_double(tvb, start);
1175 proto_tree_set_double(new_fi, doubleval);
1179 proto_tree_set_string_tvb(new_fi, tvb, start, length);
1183 DISSECTOR_ASSERT(length >= -1);
1184 /* Instead of calling proto_item_set_len(),
1185 * since we don't yet have a proto_item, we
1186 * set the field_info's length ourselves.
1188 * XXX - our caller can't use that length to
1189 * advance an offset unless they arrange that
1190 * there always be a protocol tree into which
1191 * we're putting this item.
1194 /* This can throw an exception */
1195 length = tvb_strsize(tvb, start);
1197 string = ep_alloc(length);
1199 tvb_memcpy(tvb, string, start, length);
1200 } else if (length == 0) {
1203 /* In this case, length signifies
1204 * the length of the string.
1206 * This could either be a null-padded
1207 * string, which doesn't necessarily
1208 * have a '\0' at the end, or a
1209 * null-terminated string, with a
1210 * trailing '\0'. (Yes, there are
1211 * cases where you have a string
1212 * that's both counted and null-
1215 * In the first case, we must
1216 * allocate a buffer of length
1217 * "length+1", to make room for
1220 * In the second case, we don't
1221 * assume that there is a trailing
1222 * '\0' there, as the packet might
1223 * be malformed. (XXX - should we
1224 * throw an exception if there's no
1225 * trailing '\0'?) Therefore, we
1226 * allocate a buffer of length
1227 * "length+1", and put in a trailing
1228 * '\0', just to be safe.
1230 * (XXX - this would change if
1231 * we made string values counted
1232 * rather than null-terminated.)
1234 string = tvb_get_ephemeral_string(tvb,
1238 new_fi->length = length;
1239 proto_tree_set_string(new_fi, string);
1243 proto_tree_set_ebcdic_string_tvb(new_fi, tvb, start, length);
1246 case FT_UINT_STRING:
1247 n = get_uint_value(tvb, start, length, little_endian);
1248 proto_tree_set_string_tvb(new_fi, tvb, start + length, n);
1250 /* Instead of calling proto_item_set_len(), since we
1251 * don't yet have a proto_item, we set the
1252 * field_info's length ourselves.
1254 * XXX - our caller can't use that length to
1255 * advance an offset unless they arrange that
1256 * there always be a protocol tree into which
1257 * we're putting this item.
1259 new_fi->length = n + length;
1263 g_error("new_fi->hfinfo->type %d (%s) not handled\n",
1264 new_fi->hfinfo->type,
1265 ftype_name(new_fi->hfinfo->type));
1266 DISSECTOR_ASSERT_NOT_REACHED();
1270 /* Don't add new node to proto_tree until now so that any exceptions
1271 * raised by a tvbuff access method doesn't leave junk in the proto_tree. */
1272 pi = proto_tree_add_node(tree, new_fi);
1274 /* we did not raise an exception so we dont have to remember this
1275 * field_info struct any more.
1277 field_info_tmp=NULL;
1279 /* If the proto_tree wants to keep a record of this finfo
1280 * for quick lookup, then record it. */
1281 if (new_fi->hfinfo->ref_count) {
1283 hash = PTREE_DATA(tree)->interesting_hfids;
1284 ptrs = g_hash_table_lookup(hash, GINT_TO_POINTER(hfindex));
1286 g_ptr_array_add(ptrs, new_fi);
1293 /* Gets data from tvbuff, adds it to proto_tree, increments offset,
1294 and returns proto_item* */
1296 ptvcursor_add(ptvcursor_t *ptvc, int hfindex, gint length,
1297 gboolean little_endian)
1300 header_field_info *hfinfo;
1305 offset = ptvc->offset;
1306 hfinfo = get_hfi_and_length(hfindex, ptvc->tvb, offset, &length,
1308 ptvc->offset += length;
1309 if (hfinfo->type == FT_UINT_BYTES || hfinfo->type == FT_UINT_STRING) {
1311 * The length of the rest of the item is in the first N
1312 * bytes of the item.
1314 n = get_uint_value(ptvc->tvb, offset, length, little_endian);
1317 if (ptvc->tree == NULL)
1320 TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfindex);
1322 new_fi = new_field_info(ptvc->tree, hfinfo, ptvc->tvb, offset,
1327 return proto_tree_new_item(new_fi, ptvc->tree, hfindex, ptvc->tvb,
1328 offset, length, little_endian);
1331 /* Add an item to a proto_tree, using the text label registered to that item;
1332 the item is extracted from the tvbuff handed to it. */
1334 proto_tree_add_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1335 gint start, gint length, gboolean little_endian)
1342 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1344 new_fi = alloc_field_info(tree, hfindex, tvb, start, &length);
1349 return proto_tree_new_item(new_fi, tree, hfindex, tvb, start,
1350 length, little_endian);
1354 proto_tree_add_item_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1355 gint start, gint length, gboolean little_endian)
1359 pi = proto_tree_add_item(tree, hfindex, tvb, start, length, little_endian);
1363 PROTO_ITEM_SET_HIDDEN(pi);
1369 /* Add a FT_NONE to a proto_tree */
1371 proto_tree_add_none_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1372 gint length, const char *format, ...)
1376 header_field_info *hfinfo;
1381 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1382 DISSECTOR_ASSERT(hfinfo->type == FT_NONE);
1384 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, NULL);
1386 va_start(ap, format);
1387 proto_tree_set_representation(pi, format, ap);
1390 /* no value to set for FT_NONE */
1394 /* Gets data from tvbuff, adds it to proto_tree, *DOES NOT* increment
1395 * offset, and returns proto_item* */
1397 ptvcursor_add_no_advance(ptvcursor_t* ptvc, int hf, gint length,
1398 gboolean endianness)
1402 item = proto_tree_add_item(ptvc->tree, hf, ptvc->tvb, ptvc->offset,
1403 length, endianness);
1408 /* Advance the ptvcursor's offset within its tvbuff without
1409 * adding anything to the proto_tree. */
1411 ptvcursor_advance(ptvcursor_t* ptvc, gint length)
1413 ptvc->offset += length;
1418 proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb)
1420 fvalue_set(&fi->value, tvb, TRUE);
1423 /* Add a FT_PROTOCOL to a proto_tree */
1425 proto_tree_add_protocol_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1426 gint length, const char *format, ...)
1430 header_field_info *hfinfo;
1436 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1437 DISSECTOR_ASSERT(hfinfo->type == FT_PROTOCOL);
1439 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1441 va_start(ap, format);
1442 proto_tree_set_representation(pi, format, ap);
1446 proto_tree_set_protocol_tvb(new_fi, tvb);
1449 proto_tree_set_protocol_tvb(new_fi, NULL);
1455 /* Add a FT_BYTES to a proto_tree */
1457 proto_tree_add_bytes(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1458 gint length, const guint8 *start_ptr)
1462 header_field_info *hfinfo;
1467 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1469 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1470 DISSECTOR_ASSERT(hfinfo->type == FT_BYTES);
1472 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1473 proto_tree_set_bytes(new_fi, start_ptr, length);
1479 proto_tree_add_bytes_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1480 gint length, const guint8 *start_ptr)
1484 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length, start_ptr);
1488 PROTO_ITEM_SET_HIDDEN(pi);
1494 proto_tree_add_bytes_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1495 gint start, gint length, const guint8 *start_ptr,
1496 const char *format, ...)
1501 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length, start_ptr);
1505 va_start(ap, format);
1506 proto_tree_set_representation_value(pi, format, ap);
1513 proto_tree_add_bytes_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1514 gint length, const guint8 *start_ptr, const char *format, ...)
1519 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length, start_ptr);
1523 va_start(ap, format);
1524 proto_tree_set_representation(pi, format, ap);
1531 proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length)
1535 bytes = g_byte_array_new();
1537 g_byte_array_append(bytes, start_ptr, length);
1539 col_custom_set_fstr(fi->hfinfo, "%s", bytes_to_str(bytes->data,
1541 fvalue_set(&fi->value, bytes, TRUE);
1546 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length)
1548 proto_tree_set_bytes(fi, tvb_get_ptr(tvb, offset, length), length);
1551 /* Add a FT_*TIME to a proto_tree */
1553 proto_tree_add_time(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1554 nstime_t *value_ptr)
1558 header_field_info *hfinfo;
1563 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1565 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1566 DISSECTOR_ASSERT(hfinfo->type == FT_ABSOLUTE_TIME ||
1567 hfinfo->type == FT_RELATIVE_TIME);
1569 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1570 proto_tree_set_time(new_fi, value_ptr);
1576 proto_tree_add_time_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1577 nstime_t *value_ptr)
1581 pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
1585 PROTO_ITEM_SET_HIDDEN(pi);
1591 proto_tree_add_time_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1592 gint start, gint length, nstime_t *value_ptr,
1593 const char *format, ...)
1598 pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
1602 va_start(ap, format);
1603 proto_tree_set_representation_value(pi, format, ap);
1610 proto_tree_add_time_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1611 nstime_t *value_ptr, const char *format, ...)
1616 pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
1620 va_start(ap, format);
1621 proto_tree_set_representation(pi, format, ap);
1627 /* Set the FT_*TIME value */
1629 proto_tree_set_time(field_info *fi, nstime_t *value_ptr)
1631 header_field_info *hfinfo;
1633 DISSECTOR_ASSERT(value_ptr != NULL);
1634 hfinfo = fi->hfinfo;
1636 if (hfinfo->type == FT_ABSOLUTE_TIME) {
1637 col_custom_set_fstr(fi->hfinfo, "%s", abs_time_to_str(value_ptr));
1638 } else if (hfinfo->type == FT_RELATIVE_TIME) {
1639 col_custom_set_fstr(fi->hfinfo, "%s", rel_time_to_secs_str(value_ptr));
1641 fvalue_set(&fi->value, value_ptr, FALSE);
1644 /* Add a FT_IPXNET to a proto_tree */
1646 proto_tree_add_ipxnet(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1651 header_field_info *hfinfo;
1656 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1658 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1659 DISSECTOR_ASSERT(hfinfo->type == FT_IPXNET);
1661 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1662 proto_tree_set_ipxnet(new_fi, value);
1668 proto_tree_add_ipxnet_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1673 pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
1677 PROTO_ITEM_SET_HIDDEN(pi);
1683 proto_tree_add_ipxnet_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1684 gint start, gint length, guint32 value, const char *format, ...)
1689 pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
1693 va_start(ap, format);
1694 proto_tree_set_representation_value(pi, format, ap);
1701 proto_tree_add_ipxnet_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1702 guint32 value, const char *format, ...)
1707 pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
1711 va_start(ap, format);
1712 proto_tree_set_representation(pi, format, ap);
1718 /* Set the FT_IPXNET value */
1720 proto_tree_set_ipxnet(field_info *fi, guint32 value)
1722 fvalue_set_uinteger(&fi->value, value);
1725 /* Add a FT_IPv4 to a proto_tree */
1727 proto_tree_add_ipv4(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1732 header_field_info *hfinfo;
1737 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1739 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1740 DISSECTOR_ASSERT(hfinfo->type == FT_IPv4);
1742 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1743 proto_tree_set_ipv4(new_fi, value);
1749 proto_tree_add_ipv4_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1754 pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
1758 PROTO_ITEM_SET_HIDDEN(pi);
1764 proto_tree_add_ipv4_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1765 gint start, gint length, guint32 value, const char *format, ...)
1770 pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
1774 va_start(ap, format);
1775 proto_tree_set_representation_value(pi, format, ap);
1782 proto_tree_add_ipv4_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1783 guint32 value, const char *format, ...)
1788 pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
1792 va_start(ap, format);
1793 proto_tree_set_representation(pi, format, ap);
1799 /* Set the FT_IPv4 value */
1801 proto_tree_set_ipv4(field_info *fi, guint32 value)
1803 col_custom_set_fstr(fi->hfinfo, "%s",
1804 ip_to_str((guint8 *)&value));
1805 fvalue_set_uinteger(&fi->value, value);
1808 /* Add a FT_IPv6 to a proto_tree */
1810 proto_tree_add_ipv6(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1811 const guint8* value_ptr)
1815 header_field_info *hfinfo;
1820 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1822 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1823 DISSECTOR_ASSERT(hfinfo->type == FT_IPv6);
1825 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1826 proto_tree_set_ipv6(new_fi, value_ptr);
1832 proto_tree_add_ipv6_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1833 const guint8* value_ptr)
1837 pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
1841 PROTO_ITEM_SET_HIDDEN(pi);
1847 proto_tree_add_ipv6_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1848 gint start, gint length, const guint8* value_ptr,
1849 const char *format, ...)
1854 pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
1858 va_start(ap, format);
1859 proto_tree_set_representation_value(pi, format, ap);
1866 proto_tree_add_ipv6_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1867 const guint8* value_ptr, const char *format, ...)
1872 pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
1876 va_start(ap, format);
1877 proto_tree_set_representation(pi, format, ap);
1883 /* Set the FT_IPv6 value */
1885 proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr)
1887 DISSECTOR_ASSERT(value_ptr != NULL);
1888 fvalue_set(&fi->value, (gpointer) value_ptr, FALSE);
1892 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start)
1894 proto_tree_set_ipv6(fi, tvb_get_ptr(tvb, start, 16));
1897 /* Add a FT_GUID to a proto_tree */
1899 proto_tree_add_guid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1900 const e_guid_t *value_ptr)
1904 header_field_info *hfinfo;
1909 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1911 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1912 DISSECTOR_ASSERT(hfinfo->type == FT_GUID);
1914 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1915 proto_tree_set_guid(new_fi, value_ptr);
1921 proto_tree_add_guid_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1922 const e_guid_t *value_ptr)
1926 pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
1930 PROTO_ITEM_SET_HIDDEN(pi);
1936 proto_tree_add_guid_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1937 gint start, gint length, const e_guid_t *value_ptr,
1938 const char *format, ...)
1943 pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
1947 va_start(ap, format);
1948 proto_tree_set_representation_value(pi, format, ap);
1955 proto_tree_add_guid_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1956 const e_guid_t *value_ptr, const char *format, ...)
1961 pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
1965 va_start(ap, format);
1966 proto_tree_set_representation(pi, format, ap);
1972 /* Set the FT_GUID value */
1974 proto_tree_set_guid(field_info *fi, const e_guid_t *value_ptr)
1976 DISSECTOR_ASSERT(value_ptr != NULL);
1977 col_custom_set_fstr(fi->hfinfo, "%s",
1978 guid_to_str(value_ptr));
1979 fvalue_set(&fi->value, (gpointer) value_ptr, FALSE);
1983 proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gboolean little_endian)
1987 tvb_get_guid(tvb, start, &guid, little_endian);
1988 proto_tree_set_guid(fi, &guid);
1991 /* Add a FT_OID to a proto_tree */
1993 proto_tree_add_oid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1994 const guint8* value_ptr)
1998 header_field_info *hfinfo;
2003 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
2005 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2006 DISSECTOR_ASSERT(hfinfo->type == FT_OID);
2008 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2009 proto_tree_set_oid(new_fi, value_ptr, length);
2015 proto_tree_add_oid_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2016 const guint8* value_ptr)
2020 pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
2024 PROTO_ITEM_SET_HIDDEN(pi);
2030 proto_tree_add_oid_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2031 gint start, gint length, const guint8* value_ptr,
2032 const char *format, ...)
2037 pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
2041 va_start(ap, format);
2042 proto_tree_set_representation_value(pi, format, ap);
2049 proto_tree_add_oid_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2050 const guint8* value_ptr, const char *format, ...)
2055 pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
2059 va_start(ap, format);
2060 proto_tree_set_representation(pi, format, ap);
2066 /* Set the FT_OID value */
2068 proto_tree_set_oid(field_info *fi, const guint8* value_ptr, gint length)
2072 DISSECTOR_ASSERT(value_ptr != NULL);
2074 bytes = g_byte_array_new();
2076 g_byte_array_append(bytes, value_ptr, length);
2078 col_custom_set_fstr(fi->hfinfo, "%s",
2079 oid_resolved_from_encoded(value_ptr, length));
2080 fvalue_set(&fi->value, bytes, TRUE);
2084 proto_tree_set_oid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
2086 proto_tree_set_oid(fi, tvb_get_ptr(tvb, start, length), length);
2090 proto_tree_set_uint64(field_info *fi, guint64 value)
2092 col_custom_set_fstr(fi->hfinfo, "%" G_GINT64_MODIFIER "u",
2094 fvalue_set_integer64(&fi->value, value);
2098 proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start, guint length, gboolean little_endian)
2101 guint8* b = ep_tvb_memdup(tvb,start,length);
2106 default: DISSECTOR_ASSERT_NOT_REACHED();
2107 case 8: value <<= 8; value += *--b;
2108 case 7: value <<= 8; value += *--b;
2109 case 6: value <<= 8; value += *--b;
2110 case 5: value <<= 8; value += *--b;
2111 case 4: value <<= 8; value += *--b;
2112 case 3: value <<= 8; value += *--b;
2113 case 2: value <<= 8; value += *--b;
2114 case 1: value <<= 8; value += *--b;
2119 default: DISSECTOR_ASSERT_NOT_REACHED();
2120 case 8: value <<= 8; value += *b++;
2121 case 7: value <<= 8; value += *b++;
2122 case 6: value <<= 8; value += *b++;
2123 case 5: value <<= 8; value += *b++;
2124 case 4: value <<= 8; value += *b++;
2125 case 3: value <<= 8; value += *b++;
2126 case 2: value <<= 8; value += *b++;
2127 case 1: value <<= 8; value += *b++;
2132 proto_tree_set_uint64(fi, value);
2135 /* Add a FT_STRING or FT_STRINGZ to a proto_tree. Creates own copy of string,
2136 * and frees it when the proto_tree is destroyed. */
2138 proto_tree_add_string(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2139 gint length, const char* value)
2143 header_field_info *hfinfo;
2148 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
2150 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2151 DISSECTOR_ASSERT(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ);
2153 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2154 DISSECTOR_ASSERT(length >= 0);
2155 proto_tree_set_string(new_fi, value);
2161 proto_tree_add_string_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2162 gint length, const char* value)
2166 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
2170 PROTO_ITEM_SET_HIDDEN(pi);
2176 proto_tree_add_string_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2177 gint start, gint length, const char* value, const char *format,
2183 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
2187 va_start(ap, format);
2188 proto_tree_set_representation_value(pi, format, ap);
2195 proto_tree_add_string_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2196 gint length, const char* value, const char *format, ...)
2201 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
2205 va_start(ap, format);
2206 proto_tree_set_representation(pi, format, ap);
2212 /* Appends string data to a FT_STRING or FT_STRINGZ, allowing progressive
2213 * field info update instead of only updating the representation as does
2214 * proto_item_append_text()
2216 /* NOTE: this function will break with the TRY_TO_FAKE_THIS_ITEM()
2217 * speed optimization.
2218 * Currently only WSP use this function so it is not that bad but try to
2219 * avoid using this one if possible.
2220 * IF you must use this function you MUST also disable the
2221 * TRY_TO_FAKE_THIS_ITEM() optimization for your dissector/function
2222 * using proto_item_append_string().
2223 * Do that by faking that the tree is visible by calling
2224 * proto_tree_set_visible(tree, TRUE) (see packet-wsp.c)
2225 * BEFORE you create the item you are later going to use
2226 * proto_item_append_string() on.
2229 proto_item_append_string(proto_item *pi, const char *str)
2232 header_field_info *hfinfo;
2233 gchar *old_str, *new_str;
2240 fi = PITEM_FINFO(pi);
2241 hfinfo = fi->hfinfo;
2242 if (hfinfo->type == FT_PROTOCOL) {
2243 /* TRY_TO_FAKE_THIS_ITEM() speed optimization: silently skip */
2246 DISSECTOR_ASSERT(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ);
2247 old_str = fvalue_get(&fi->value);
2248 new_str = ep_strdup_printf("%s%s", old_str, str);
2249 fvalue_set(&fi->value, new_str, FALSE);
2252 /* Set the FT_STRING value */
2254 proto_tree_set_string(field_info *fi, const char* value)
2257 col_custom_set_fstr(fi->hfinfo, "%s",
2258 format_text(value, strlen(value)));
2259 fvalue_set(&fi->value, (gpointer) value, FALSE);
2261 col_custom_set_fstr(fi->hfinfo, "[ Null ]");
2262 fvalue_set(&fi->value, (gpointer) "[ Null ]", FALSE);
2267 proto_tree_set_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
2272 length = tvb_ensure_length_remaining(tvb, start);
2275 string = tvb_get_ephemeral_string(tvb, start, length);
2276 proto_tree_set_string(fi, string);
2280 proto_tree_set_ebcdic_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
2285 length = tvb_ensure_length_remaining(tvb, start);
2288 string = tvb_get_ephemeral_string(tvb, start, length);
2289 EBCDIC_to_ASCII(string, length);
2290 proto_tree_set_string(fi, string);
2293 /* Add a FT_ETHER to a proto_tree */
2295 proto_tree_add_ether(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2296 const guint8* value)
2300 header_field_info *hfinfo;
2305 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
2307 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2308 DISSECTOR_ASSERT(hfinfo->type == FT_ETHER);
2310 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2311 proto_tree_set_ether(new_fi, value);
2317 proto_tree_add_ether_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2318 const guint8* value)
2322 pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
2326 PROTO_ITEM_SET_HIDDEN(pi);
2332 proto_tree_add_ether_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2333 gint start, gint length, const guint8* value,
2334 const char *format, ...)
2339 pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
2343 va_start(ap, format);
2344 proto_tree_set_representation_value(pi, format, ap);
2351 proto_tree_add_ether_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2352 const guint8* value, const char *format, ...)
2357 pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
2361 va_start(ap, format);
2362 proto_tree_set_representation(pi, format, ap);
2368 /* Set the FT_ETHER value */
2370 proto_tree_set_ether(field_info *fi, const guint8* value)
2372 col_custom_set_fstr(fi->hfinfo, "%s", bytes_to_str_punct(value, 6, ':'));
2373 fvalue_set(&fi->value, (gpointer) value, FALSE);
2377 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start)
2379 proto_tree_set_ether(fi, tvb_get_ptr(tvb, start, 6));
2382 /* Add a FT_BOOLEAN to a proto_tree */
2384 proto_tree_add_boolean(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2389 header_field_info *hfinfo;
2394 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
2396 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2397 DISSECTOR_ASSERT(hfinfo->type == FT_BOOLEAN);
2399 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2400 proto_tree_set_boolean(new_fi, value);
2406 proto_tree_add_boolean_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2411 pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
2415 PROTO_ITEM_SET_HIDDEN(pi);
2421 proto_tree_add_boolean_format_value(proto_tree *tree, int hfindex,
2422 tvbuff_t *tvb, gint start, gint length, guint32 value,
2423 const char *format, ...)
2428 pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
2432 va_start(ap, format);
2433 proto_tree_set_representation_value(pi, format, ap);
2440 proto_tree_add_boolean_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2441 guint32 value, const char *format, ...)
2446 pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
2450 va_start(ap, format);
2451 proto_tree_set_representation(pi, format, ap);
2457 /* Set the FT_BOOLEAN value */
2459 proto_tree_set_boolean(field_info *fi, guint32 value)
2461 proto_tree_set_uint(fi, value);
2464 /* Add a FT_FLOAT to a proto_tree */
2466 proto_tree_add_float(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2471 header_field_info *hfinfo;
2476 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
2478 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2479 DISSECTOR_ASSERT(hfinfo->type == FT_FLOAT);
2481 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2482 proto_tree_set_float(new_fi, value);
2488 proto_tree_add_float_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2493 pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
2497 PROTO_ITEM_SET_HIDDEN(pi);
2503 proto_tree_add_float_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2504 gint start, gint length, float value, const char *format, ...)
2509 pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
2513 va_start(ap, format);
2514 proto_tree_set_representation_value(pi, format, ap);
2521 proto_tree_add_float_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2522 float value, const char *format, ...)
2527 pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
2531 va_start(ap, format);
2532 proto_tree_set_representation(pi, format, ap);
2538 /* Set the FT_FLOAT value */
2540 proto_tree_set_float(field_info *fi, float value)
2542 col_custom_set_fstr(fi->hfinfo, "%." STRINGIFY(FLT_DIG) "f",
2544 fvalue_set_floating(&fi->value, value);
2547 /* Add a FT_DOUBLE to a proto_tree */
2549 proto_tree_add_double(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2554 header_field_info *hfinfo;
2559 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
2561 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2562 DISSECTOR_ASSERT(hfinfo->type == FT_DOUBLE);
2564 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2565 proto_tree_set_double(new_fi, value);
2571 proto_tree_add_double_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2576 pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
2580 PROTO_ITEM_SET_HIDDEN(pi);
2586 proto_tree_add_double_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2587 gint start, gint length, double value, const char *format, ...)
2592 pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
2596 va_start(ap, format);
2597 proto_tree_set_representation_value(pi, format, ap);
2604 proto_tree_add_double_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2605 double value, const char *format, ...)
2610 pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
2614 va_start(ap, format);
2615 proto_tree_set_representation(pi, format, ap);
2621 /* Set the FT_DOUBLE value */
2623 proto_tree_set_double(field_info *fi, double value)
2625 col_custom_set_fstr(fi->hfinfo, "%." STRINGIFY(DBL_DIG) "g",
2627 fvalue_set_floating(&fi->value, value);
2630 /* Add FT_UINT{8,16,24,32} to a proto_tree */
2632 proto_tree_add_uint(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2635 proto_item *pi = NULL;
2637 header_field_info *hfinfo;
2642 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
2644 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2645 switch(hfinfo->type) {
2651 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length,
2653 proto_tree_set_uint(new_fi, value);
2657 DISSECTOR_ASSERT_NOT_REACHED();
2664 proto_tree_add_uint_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2669 pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
2673 PROTO_ITEM_SET_HIDDEN(pi);
2679 proto_tree_add_uint_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2680 gint start, gint length, guint32 value, const char *format, ...)
2685 pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
2689 va_start(ap, format);
2690 proto_tree_set_representation_value(pi, format, ap);
2697 proto_tree_add_uint_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2698 guint32 value, const char *format, ...)
2703 pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
2707 va_start(ap, format);
2708 proto_tree_set_representation(pi, format, ap);
2714 /* Set the FT_UINT{8,16,24,32} value */
2716 proto_tree_set_uint(field_info *fi, guint32 value)
2718 header_field_info *hfinfo;
2721 hfinfo = fi->hfinfo;
2724 if (hfinfo->bitmask) {
2725 /* Mask out irrelevant portions */
2726 integer &= hfinfo->bitmask;
2729 if (hfinfo->bitshift > 0) {
2730 integer >>= hfinfo->bitshift;
2734 if (hfinfo->type == FT_BOOLEAN) {
2735 const true_false_string *tfstring = &tfs_true_false;
2736 if (hfinfo->strings) {
2737 tfstring = (const struct true_false_string*) hfinfo->strings;
2739 col_custom_set_fstr(fi->hfinfo, "%s", value ? tfstring->true_string : tfstring->false_string);
2740 } else if (hfinfo->strings) {
2741 col_custom_set_fstr(fi->hfinfo, "%s", val_to_str(integer, cVALS(hfinfo->strings), "%d"));
2742 } else if (IS_BASE_DUAL(hfinfo->display)) {
2743 col_custom_set_fstr(fi->hfinfo, hfinfo_uint_value_format(hfinfo), integer, integer);
2745 col_custom_set_fstr(fi->hfinfo, hfinfo_uint_value_format(hfinfo), integer);
2747 fvalue_set_uinteger(&fi->value, integer);
2750 /* Add FT_UINT64 to a proto_tree */
2752 proto_tree_add_uint64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2755 proto_item *pi = NULL;
2757 header_field_info *hfinfo;
2762 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
2764 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2765 DISSECTOR_ASSERT(hfinfo->type == FT_UINT64);
2767 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2768 proto_tree_set_uint64(new_fi, value);
2774 proto_tree_add_uint64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2775 gint start, gint length, guint64 value, const char *format, ...)
2780 pi = proto_tree_add_uint64(tree, hfindex, tvb, start, length, value);
2784 va_start(ap, format);
2785 proto_tree_set_representation_value(pi, format, ap);
2792 proto_tree_add_uint64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2793 guint64 value, const char *format, ...)
2798 pi = proto_tree_add_uint64(tree, hfindex, tvb, start, length, value);
2802 va_start(ap, format);
2803 proto_tree_set_representation(pi, format, ap);
2809 /* Add FT_INT{8,16,24,32} to a proto_tree */
2811 proto_tree_add_int(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2814 proto_item *pi = NULL;
2816 header_field_info *hfinfo;
2821 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
2823 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2824 switch(hfinfo->type) {
2829 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length,
2831 proto_tree_set_int(new_fi, value);
2835 DISSECTOR_ASSERT_NOT_REACHED();
2842 proto_tree_add_int_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2847 pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
2851 PROTO_ITEM_SET_HIDDEN(pi);
2857 proto_tree_add_int_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2858 gint start, gint length, gint32 value, const char *format, ...)
2860 proto_item *pi = NULL;
2863 pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
2867 va_start(ap, format);
2868 proto_tree_set_representation_value(pi, format, ap);
2875 proto_tree_add_int_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2876 gint32 value, const char *format, ...)
2878 proto_item *pi = NULL;
2881 pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
2885 va_start(ap, format);
2886 proto_tree_set_representation(pi, format, ap);
2892 /* Set the FT_INT{8,16,24,32} value */
2894 proto_tree_set_int(field_info *fi, gint32 value)
2896 header_field_info *hfinfo;
2899 hfinfo = fi->hfinfo;
2900 integer = (guint32) value;
2902 if (hfinfo->bitmask) {
2903 /* Mask out irrelevant portions */
2904 integer &= hfinfo->bitmask;
2907 if (hfinfo->bitshift > 0) {
2908 integer >>= hfinfo->bitshift;
2912 if (hfinfo->strings) {
2913 col_custom_set_fstr(fi->hfinfo, "%s", val_to_str(integer, cVALS(hfinfo->strings), "%d"));
2914 } else if (IS_BASE_DUAL(hfinfo->display)) {
2915 col_custom_set_fstr(fi->hfinfo, hfinfo_int_value_format(hfinfo), integer, integer);
2917 col_custom_set_fstr(fi->hfinfo, hfinfo_int_value_format(hfinfo), integer);
2919 fvalue_set_sinteger(&fi->value, integer);
2922 /* Add FT_INT64 to a proto_tree */
2924 proto_tree_add_int64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2927 proto_item *pi = NULL;
2929 header_field_info *hfinfo;
2934 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
2936 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2937 DISSECTOR_ASSERT(hfinfo->type == FT_INT64);
2939 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2940 proto_tree_set_uint64(new_fi, (guint64)value);
2946 proto_tree_add_int64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2947 gint start, gint length, gint64 value, const char *format, ...)
2952 pi = proto_tree_add_int64(tree, hfindex, tvb, start, length, value);
2956 va_start(ap, format);
2957 proto_tree_set_representation_value(pi, format, ap);
2964 proto_tree_add_int64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2965 gint64 value, const char *format, ...)
2970 pi = proto_tree_add_int64(tree, hfindex, tvb, start, length, value);
2974 va_start(ap, format);
2975 proto_tree_set_representation(pi, format, ap);
2981 /* Throw an exception if we exceed this many tree items. */
2982 /* XXX - This should probably be a preference */
2983 #define MAX_TREE_ITEMS (1 * 1000 * 1000)
2984 /* Add a field_info struct to the proto_tree, encapsulating it in a proto_node */
2986 proto_tree_add_node(proto_tree *tree, field_info *fi)
2988 proto_node *pnode, *tnode, *sibling;
2992 * Make sure "tree" is ready to have subtrees under it, by
2993 * checking whether it's been given an ett_ value.
2995 * "tnode->finfo" may be null; that's the case for the root
2996 * node of the protocol tree. That node is not displayed,
2997 * so it doesn't need an ett_ value to remember whether it
3002 if (tfi != NULL && (tfi->tree_type < 0 || tfi->tree_type >= num_tree_types)) {
3003 REPORT_DISSECTOR_BUG(ep_strdup_printf("\"%s\" - \"%s\" tfi->tree_type: %u invalid (%s:%u)",
3004 fi->hfinfo->name, fi->hfinfo->abbrev, tfi->tree_type, __FILE__, __LINE__));
3005 /* XXX - is it safe to continue here? */
3008 DISSECTOR_ASSERT(tfi == NULL ||
3009 (tfi->tree_type >= 0 && tfi->tree_type < num_tree_types));
3011 PTREE_DATA(tree)->count++;
3012 if (PTREE_DATA(tree)->count > MAX_TREE_ITEMS) {
3013 /* Let the exception handler add items to the tree */
3014 PTREE_DATA(tree)->count = 0;
3015 THROW_MESSAGE(DissectorError,
3016 ep_strdup_printf("More than %d items in the tree -- possible infinite loop", MAX_TREE_ITEMS));
3019 PROTO_NODE_NEW(pnode);
3020 pnode->parent = tnode;
3022 pnode->tree_data = PTREE_DATA(tree);
3024 if (tnode->last_child != NULL) {
3025 sibling = tnode->last_child;
3026 DISSECTOR_ASSERT(sibling->next == NULL);
3027 sibling->next = pnode;
3029 tnode->first_child = pnode;
3030 tnode->last_child = pnode;
3032 return (proto_item*)pnode;
3036 /* Generic way to allocate field_info and add to proto_tree.
3037 * Sets *pfi to address of newly-allocated field_info struct, if pfi is
3040 proto_tree_add_pi(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3041 gint *length, field_info **pfi)
3051 fi = alloc_field_info(tree, hfindex, tvb, start, length);
3052 pi = proto_tree_add_node(tree, fi);
3054 /* If the proto_tree wants to keep a record of this finfo
3055 * for quick lookup, then record it. */
3056 if (fi->hfinfo->ref_count) {
3058 hash = PTREE_DATA(tree)->interesting_hfids;
3059 ptrs = g_hash_table_lookup(hash, GINT_TO_POINTER(hfindex));
3061 g_ptr_array_add(ptrs, fi);
3065 /* Does the caller want to know the fi pointer? */
3074 static header_field_info *
3075 get_hfi_and_length(int hfindex, tvbuff_t *tvb, gint start, gint *length,
3078 header_field_info *hfinfo;
3079 gint length_remaining;
3082 * We only allow a null tvbuff if the item has a zero length,
3083 * i.e. if there's no data backing it.
3085 DISSECTOR_ASSERT(tvb != NULL || *length == 0);
3087 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
3090 * XXX - in some protocols, there are 32-bit unsigned length
3091 * fields, so lengths in protocol tree and tvbuff routines
3092 * should really be unsigned. We should have, for those
3093 * field types for which "to the end of the tvbuff" makes sense,
3094 * additional routines that take no length argument and
3095 * add fields that run to the end of the tvbuff.
3097 if (*length == -1) {
3099 * For FT_NONE, FT_PROTOCOL, FT_BYTES, and FT_STRING fields,
3100 * a length of -1 means "set the length to what remains in
3103 * The assumption is either that
3105 * 1) the length of the item can only be determined
3106 * by dissection (typically true of items with
3107 * subitems, which are probably FT_NONE or
3112 * 2) if the tvbuff is "short" (either due to a short
3113 * snapshot length or due to lack of reassembly of
3114 * fragments/segments/whatever), we want to display
3115 * what's available in the field (probably FT_BYTES
3116 * or FT_STRING) and then throw an exception later
3120 * 3) the field is defined to be "what's left in the
3123 * so we set the length to what remains in the tvbuff so
3124 * that, if we throw an exception while dissecting, it
3125 * has what is probably the right value.
3127 * For FT_STRINGZ, it means "the string is null-terminated,
3128 * not null-padded; set the length to the actual length
3129 * of the string", and if the tvbuff if short, we just
3130 * throw an exception.
3132 * It's not valid for any other type of field.
3134 switch (hfinfo->type) {
3138 * We allow this to be zero-length - for
3139 * example, an ONC RPC NULL procedure has
3140 * neither arguments nor reply, so the
3141 * payload for that protocol is empty.
3143 * However, if the length is negative, the
3144 * start offset is *past* the byte past the
3145 * end of the tvbuff, so we throw an
3148 *length = tvb_length_remaining(tvb, start);
3151 * Use "tvb_ensure_bytes_exist()"
3152 * to force the appropriate exception
3155 tvb_ensure_bytes_exist(tvb, start, 0);
3157 DISSECTOR_ASSERT(*length >= 0);
3163 *length = tvb_ensure_length_remaining(tvb, start);
3164 DISSECTOR_ASSERT(*length >= 0);
3169 * Leave the length as -1, so our caller knows
3175 DISSECTOR_ASSERT_NOT_REACHED();
3177 *item_length = *length;
3179 *item_length = *length;
3180 if (hfinfo->type == FT_PROTOCOL || hfinfo->type == FT_NONE) {
3182 * These types are for interior nodes of the
3183 * tree, and don't have data associated with
3184 * them; if the length is negative (XXX - see
3185 * above) or goes past the end of the tvbuff,
3186 * cut it short at the end of the tvbuff.
3187 * That way, if this field is selected in
3188 * Wireshark, we don't highlight stuff past
3189 * the end of the data.
3191 /* XXX - what to do, if we don't have a tvb? */
3193 length_remaining = tvb_length_remaining(tvb, start);
3194 if (*item_length < 0 ||
3195 (*item_length > 0 &&
3196 (length_remaining < *item_length)))
3197 *item_length = length_remaining;
3200 if (*item_length < 0) {
3201 THROW(ReportedBoundsError);
3209 new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
3210 gint start, gint item_length)
3216 fi->hfinfo = hfinfo;
3218 fi->start+=(tvb)?TVB_RAW_OFFSET(tvb):0;
3219 fi->length = item_length;
3222 if (!PTREE_DATA(tree)->visible)
3223 FI_SET_FLAG(fi, FI_HIDDEN);
3224 fvalue_init(&fi->value, fi->hfinfo->type);
3227 /* add the data source tvbuff */
3228 fi->ds_tvb=tvb?TVB_GET_DS_TVB(tvb):NULL;
3230 fi->appendix_start = 0;
3231 fi->appendix_length = 0;
3237 alloc_field_info(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3240 header_field_info *hfinfo;
3243 hfinfo = get_hfi_and_length(hfindex, tvb, start, length, &item_length);
3244 return new_field_info(tree, hfinfo, tvb, start, item_length);
3247 /* If the protocol tree is to be visible, set the representation of a
3248 proto_tree entry with the name of the field for the item and with
3249 the value formatted with the supplied printf-style format and
3252 proto_tree_set_representation_value(proto_item *pi, const char *format, va_list ap)
3254 int ret; /*tmp return value */
3256 field_info *fi = PITEM_FINFO(pi);
3258 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
3259 ITEM_LABEL_NEW(fi->rep);
3262 /* put in the hf name */
3263 ret = g_snprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
3264 "%s: ", fi->hfinfo->name);
3265 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH)) {
3266 /* That's all we can put in the representation. */
3267 fi->rep->representation[ITEM_LABEL_LENGTH - 1] = '\0';
3272 /* Put in the value of the string */
3273 ret = g_vsnprintf(fi->rep->representation + replen,
3274 ITEM_LABEL_LENGTH - replen, format, ap);
3275 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH - replen)) {
3276 /* Uh oh, we don't have enough room. Tell the user
3277 * that the field is truncated.
3281 fi->rep->representation[ITEM_LABEL_LENGTH - 1] = '\0';
3283 /* Argh, we cannot reuse 'ap' here. So make a copy
3284 * of what we formatted for (re)use below.
3286 oldrep = g_strdup(fi->rep->representation);
3288 ret = g_snprintf(fi->rep->representation,
3292 fi->rep->representation[ITEM_LABEL_LENGTH - 1] = '\0';
3298 /* If the protocol tree is to be visible, set the representation of a
3299 proto_tree entry with the representation formatted with the supplied
3300 printf-style format and argument list. */
3302 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap)
3304 int ret; /*tmp return value */
3305 field_info *fi = PITEM_FINFO(pi);
3307 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
3308 ITEM_LABEL_NEW(fi->rep);
3309 ret = g_vsnprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
3311 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH)) {
3312 /* Uh oh, we don't have enough room. Tell the user
3313 * that the field is truncated.
3317 fi->rep->representation[ITEM_LABEL_LENGTH - 1] = '\0';
3319 /* Argh, we cannot reuse 'ap' here. So make a copy
3320 * of what we formatted for (re)use below.
3322 oldrep = g_strdup(fi->rep->representation);
3324 g_snprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
3325 "[truncated] %s", oldrep);
3326 fi->rep->representation[ITEM_LABEL_LENGTH - 1] = '\0';
3332 /* Set text of proto_item after having already been created. */
3334 proto_item_set_text(proto_item *pi, const char *format, ...)
3336 field_info *fi = NULL;
3343 fi = PITEM_FINFO(pi);
3346 ITEM_LABEL_FREE(fi->rep);
3349 va_start(ap, format);
3350 proto_tree_set_representation(pi, format, ap);
3354 /* Append to text of proto_item after having already been created. */
3356 proto_item_append_text(proto_item *pi, const char *format, ...)
3358 field_info *fi = NULL;
3361 int ret; /*tmp return value */
3367 fi = PITEM_FINFO(pi);
3372 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
3373 va_start(ap, format);
3376 * If we don't already have a representation,
3377 * generate the default representation.
3379 if (fi->rep == NULL) {
3380 ITEM_LABEL_NEW(fi->rep);
3381 proto_item_fill_label(fi, fi->rep->representation);
3384 curlen = strlen(fi->rep->representation);
3385 if (ITEM_LABEL_LENGTH > curlen) {
3386 ret = g_vsnprintf(fi->rep->representation + curlen,
3387 ITEM_LABEL_LENGTH - curlen, format, ap);
3388 if ((ret == -1) || (ret >= (int)(ITEM_LABEL_LENGTH - curlen)))
3389 fi->rep->representation[ITEM_LABEL_LENGTH - 1] = '\0';
3396 proto_item_set_len(proto_item *pi, gint length)
3402 fi = PITEM_FINFO(pi);
3403 DISSECTOR_ASSERT(length >= 0);
3404 fi->length = length;
3406 if (fi->value.ftype->ftype == FT_BYTES)
3407 fi->value.value.bytes->len = length;
3411 * Sets the length of the item based on its start and on the specified
3412 * offset, which is the offset past the end of the item; as the start
3413 * in the item is relative to the beginning of the data source tvbuff,
3414 * we need to pass in a tvbuff - the end offset is relative to the beginning
3418 proto_item_set_end(proto_item *pi, tvbuff_t *tvb, gint end)
3424 fi = PITEM_FINFO(pi);
3425 end += TVB_RAW_OFFSET(tvb);
3426 DISSECTOR_ASSERT(end >= fi->start);
3427 fi->length = end - fi->start;
3431 proto_item_get_len(proto_item *pi)
3433 field_info *fi = PITEM_FINFO(pi);
3438 /** clear flags according to the mask and set new flag values */
3439 #define FI_REPLACE_FLAGS(fi, mask, flags_in) { \
3440 (fi->flags = (fi)->flags & ~(mask)); \
3441 (fi->flags = (fi)->flags | (flags_in)); \
3445 proto_item_set_expert_flags(proto_item *pi, int group, guint severity)
3447 if(pi == NULL || pi->finfo == NULL)
3450 /* only change things if severity is worse or at least equal than before */
3451 if(severity >= FI_GET_FLAG(pi->finfo, PI_SEVERITY_MASK)) {
3452 FI_REPLACE_FLAGS(pi->finfo, PI_GROUP_MASK, group);
3453 FI_REPLACE_FLAGS(pi->finfo, PI_SEVERITY_MASK, severity);
3464 proto_tree_create_root(void)
3468 /* Initialize the proto_node */
3469 PROTO_NODE_NEW(pnode);
3470 pnode->parent = NULL;
3471 pnode->finfo = NULL;
3472 pnode->tree_data = g_new(tree_data_t, 1);
3474 /* Initialize the tree_data_t */
3475 pnode->tree_data->interesting_hfids =
3476 g_hash_table_new(g_direct_hash, g_direct_equal);
3478 /* Set the default to FALSE so it's easier to
3479 * find errors; if we expect to see the protocol tree
3480 * but for some reason the default 'visible' is not
3481 * changed, then we'll find out very quickly. */
3482 pnode->tree_data->visible = FALSE;
3484 /* Keep track of the number of children */
3485 pnode->tree_data->count = 0;
3487 return (proto_tree*) pnode;
3491 /* "prime" a proto_tree with a single hfid that a dfilter
3492 * is interested in. */
3494 proto_tree_prime_hfid(proto_tree *tree, gint hfid)
3496 header_field_info *hfinfo;
3498 g_hash_table_insert(PTREE_DATA(tree)->interesting_hfids,
3499 GINT_TO_POINTER(hfid), g_ptr_array_new());
3501 PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
3502 /* this field is referenced by a filter so increase the refcount.
3503 also increase the refcount for the parent, i.e the protocol.
3505 hfinfo->ref_count++;
3506 /* only increase the refcount if there is a parent.
3507 if this is a protocol and not a field then parent will be -1
3508 and there is no parent to add any refcounting for.
3510 if (hfinfo->parent != -1) {
3511 header_field_info *parent_hfinfo;
3512 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
3513 parent_hfinfo->ref_count++;
3518 proto_item_add_subtree(proto_item *pi, gint idx) {
3524 fi = PITEM_FINFO(pi);
3525 DISSECTOR_ASSERT(idx >= 0 && idx < num_tree_types);
3526 fi->tree_type = idx;
3528 return (proto_tree*) pi;
3532 proto_item_get_subtree(proto_item *pi) {
3537 fi = PITEM_FINFO(pi);
3538 if ( (!fi) || (fi->tree_type == -1) )
3540 return (proto_tree*) pi;
3544 proto_item_get_parent(proto_item *ti) {
3551 proto_item_get_parent_nth(proto_item *ti, int gen) {
3564 proto_tree_get_parent(proto_tree *tree) {
3567 return (proto_item*) tree;
3571 proto_tree_get_root(proto_tree *tree) {
3574 while (tree->parent) {
3575 tree = tree->parent;
3581 proto_tree_move_item(proto_tree *tree, proto_item *fixed_item, proto_item *item_to_move)
3583 proto_item *curr_item;
3586 /*** cut item_to_move out ***/
3588 /* is item_to_move the first? */
3589 if(tree->first_child == item_to_move) {
3590 /* simply change first child to next */
3591 tree->first_child = item_to_move->next;
3593 /* find previous and change it's next */
3594 for(curr_item = tree->first_child; curr_item != NULL; curr_item = curr_item->next) {
3595 if(curr_item->next == item_to_move) {
3600 DISSECTOR_ASSERT(curr_item);
3602 curr_item->next = item_to_move->next;
3604 /* fix last_child if required */
3605 if(tree->last_child == item_to_move) {
3606 tree->last_child = curr_item;
3610 /*** insert to_move after fixed ***/
3611 item_to_move->next = fixed_item->next;
3612 fixed_item->next = item_to_move;
3613 if(tree->last_child == fixed_item) {
3614 tree->last_child = item_to_move;
3619 proto_tree_set_appendix(proto_tree *tree, tvbuff_t *tvb, gint start, gint length)
3627 start += TVB_RAW_OFFSET(tvb);
3628 DISSECTOR_ASSERT(start >= 0);
3629 DISSECTOR_ASSERT(length >= 0);
3631 fi->appendix_start = start;
3632 fi->appendix_length = length;
3636 proto_register_protocol(const char *name, const char *short_name, const char *filter_name)
3638 protocol_t *protocol;
3639 header_field_info *hfinfo;
3641 char *existing_name;
3645 gboolean found_invalid;
3648 * Make sure there's not already a protocol with any of those
3649 * names. Crash if there is, as that's an error in the code
3650 * or an inappropriate plugin.
3651 * This situation has to be fixed to not register more than one
3652 * protocol with the same name.
3654 * This is done by reducing the number of strcmp (and alike) calls as much as possible,
3655 * as this significally slows down startup time.
3657 * Drawback: As a hash value is used to reduce insert time,
3658 * this might lead to a hash collision.
3659 * However, as we have around 500+ protocols and we're using a 32 bit int this is very,
3663 key = g_malloc (sizeof(gint));
3664 *key = wrs_str_hash(name);
3665 existing_name = g_hash_table_lookup(proto_names, key);
3666 if (existing_name != NULL) {
3667 /* g_error will terminate the program */
3668 g_error("Duplicate protocol name \"%s\"!"
3669 " This might be caused by an inappropriate plugin or a development error.", name);
3671 g_hash_table_insert(proto_names, key, (gpointer)name);
3673 existing_name = g_hash_table_lookup(proto_short_names, (gpointer)short_name);
3674 if (existing_name != NULL) {
3675 g_error("Duplicate protocol short_name \"%s\"!"
3676 " This might be caused by an inappropriate plugin or a development error.", short_name);
3678 g_hash_table_insert(proto_short_names, (gpointer)short_name, (gpointer)short_name);
3680 found_invalid = FALSE;
3681 for (i = 0; i < strlen(filter_name); i++) {
3683 if (!(islower(c) || isdigit(c) || c == '-' || c == '_' || c == '.')) {
3684 found_invalid = TRUE;
3687 if (found_invalid) {
3688 g_error("Protocol filter name \"%s\" has one or more invalid characters."
3689 " Allowed are lower characters, digits, '-', '_' and '.'."
3690 " This might be caused by an inappropriate plugin or a development error.", filter_name);
3692 existing_name = g_hash_table_lookup(proto_filter_names, (gpointer)filter_name);
3693 if (existing_name != NULL) {
3694 g_error("Duplicate protocol filter_name \"%s\"!"
3695 " This might be caused by an inappropriate plugin or a development error.", filter_name);
3697 g_hash_table_insert(proto_filter_names, (gpointer)filter_name, (gpointer)filter_name);
3699 /* Add this protocol to the list of known protocols; the list
3700 is sorted by protocol short name. */
3701 protocol = g_malloc(sizeof (protocol_t));
3702 protocol->name = name;
3703 protocol->short_name = short_name;
3704 protocol->filter_name = filter_name;
3705 protocol->fields = NULL;
3706 protocol->is_enabled = TRUE; /* protocol is enabled by default */
3707 protocol->can_toggle = TRUE;
3708 /* list will be sorted later by name, when all protocols completed registering */
3709 protocols = g_list_prepend(protocols, protocol);
3711 /* Here we do allocate a new header_field_info struct */
3712 hfinfo = g_mem_chunk_alloc(gmc_hfinfo);
3713 hfinfo->name = name;
3714 hfinfo->abbrev = filter_name;
3715 hfinfo->type = FT_PROTOCOL;
3716 hfinfo->strings = protocol;
3717 hfinfo->bitmask = 0;
3718 hfinfo->bitshift = 0;
3719 hfinfo->ref_count = 0;
3720 hfinfo->blurb = NULL;
3721 hfinfo->parent = -1; /* this field differentiates protos and fields */
3723 proto_id = proto_register_field_init(hfinfo, hfinfo->parent);
3724 protocol->proto_id = proto_id;
3729 * Routines to use to iterate over the protocols.
3730 * The argument passed to the iterator routines is an opaque cookie to
3731 * their callers; it's the GList pointer for the current element in
3733 * The ID of the protocol is returned, or -1 if there is no protocol.
3736 proto_get_first_protocol(void **cookie)
3738 protocol_t *protocol;
3740 if (protocols == NULL)
3742 *cookie = protocols;
3743 protocol = protocols->data;
3744 return protocol->proto_id;
3748 proto_get_next_protocol(void **cookie)
3750 GList *list_item = *cookie;
3751 protocol_t *protocol;
3753 list_item = g_list_next(list_item);
3754 if (list_item == NULL)
3756 *cookie = list_item;
3757 protocol = list_item->data;
3758 return protocol->proto_id;
3762 proto_get_first_protocol_field(int proto_id, void **cookie)
3764 protocol_t *protocol = find_protocol_by_id(proto_id);
3765 hf_register_info *ptr;
3767 if ((protocol == NULL) || (protocol->fields == NULL))
3770 *cookie = protocol->fields;
3771 ptr = protocol->fields->data;
3772 return &ptr->hfinfo;
3776 proto_get_next_protocol_field(void **cookie)
3778 GList *list_item = *cookie;
3779 hf_register_info *ptr;
3781 list_item = g_list_next(list_item);
3782 if (list_item == NULL)
3785 *cookie = list_item;
3786 ptr = list_item->data;
3787 return &ptr->hfinfo;
3791 find_protocol_by_id(int proto_id)
3793 header_field_info *hfinfo;
3798 PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
3799 DISSECTOR_ASSERT(hfinfo->type==FT_PROTOCOL);
3800 return (protocol_t *)hfinfo->strings;
3803 static gint compare_filter_name(gconstpointer proto_arg,
3804 gconstpointer filter_name)
3806 const protocol_t *protocol = proto_arg;
3807 const gchar* f_name = filter_name;
3809 return (strcmp(protocol->filter_name, f_name));
3813 proto_get_id(protocol_t *protocol)
3815 return protocol->proto_id;
3818 int proto_get_id_by_filter_name(const gchar* filter_name)
3821 protocol_t *protocol;
3823 list_entry = g_list_find_custom(protocols, filter_name,
3824 compare_filter_name);
3826 if (list_entry == NULL)
3828 protocol = list_entry->data;
3829 return protocol->proto_id;
3833 proto_get_protocol_name(int proto_id)
3835 protocol_t *protocol;
3837 protocol = find_protocol_by_id(proto_id);
3838 return protocol->name;
3842 proto_get_protocol_short_name(protocol_t *protocol)
3844 if (protocol == NULL)
3846 return protocol->short_name;
3850 proto_get_protocol_filter_name(int proto_id)
3852 protocol_t *protocol;
3854 protocol = find_protocol_by_id(proto_id);
3855 if (protocol == NULL)
3857 return protocol->filter_name;
3861 proto_is_protocol_enabled(protocol_t *protocol)
3863 return protocol->is_enabled;
3867 proto_can_toggle_protocol(int proto_id)
3869 protocol_t *protocol;
3871 protocol = find_protocol_by_id(proto_id);
3872 return protocol->can_toggle;
3876 proto_set_decoding(int proto_id, gboolean enabled)
3878 protocol_t *protocol;
3880 protocol = find_protocol_by_id(proto_id);
3881 DISSECTOR_ASSERT(protocol->can_toggle);
3882 protocol->is_enabled = enabled;
3886 proto_enable_all(void)
3888 protocol_t *protocol;
3889 GList *list_item = protocols;
3891 if (protocols == NULL)
3895 protocol = list_item->data;
3896 if (protocol->can_toggle)
3897 protocol->is_enabled = TRUE;
3898 list_item = g_list_next(list_item);
3903 proto_set_cant_toggle(int proto_id)
3905 protocol_t *protocol;
3907 protocol = find_protocol_by_id(proto_id);
3908 protocol->can_toggle = FALSE;
3911 /* for use with static arrays only, since we don't allocate our own copies
3912 of the header_field_info struct contained within the hf_register_info struct */
3914 proto_register_field_array(int parent, hf_register_info *hf, int num_records)
3917 hf_register_info *ptr = hf;
3920 proto = find_protocol_by_id(parent);
3921 for (i = 0; i < num_records; i++, ptr++) {
3923 * Make sure we haven't registered this yet.
3924 * Most fields have variables associated with them
3925 * that are initialized to -1; some have array elements,
3926 * or possibly uninitialized variables, so we also allow
3927 * 0 (which is unlikely to be the field ID we get back
3928 * from "proto_register_field_init()").
3930 if (*ptr->p_id != -1 && *ptr->p_id != 0) {
3932 "Duplicate field detected in call to proto_register_field_array: %s is already registered\n",
3933 ptr->hfinfo.abbrev);
3937 if (proto != NULL) {
3938 if (proto->fields == NULL) {
3939 proto->fields = g_list_append(NULL, ptr);
3940 proto->last_field = proto->fields;
3943 g_list_append(proto->last_field, ptr)->next;
3946 field_id = proto_register_field_init(&ptr->hfinfo, parent);
3947 *ptr->p_id = field_id;
3951 /* chars allowed in field abbrev */
3953 const guchar fld_abbrev_chars[256] = {
3954 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00-0x0F */
3955 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10-0x1F */
3956 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, /* 0x20-0x2F '-', '.' */
3957 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 0x30-0x3F '0'-'9' */
3958 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x40-0x4F 'A'-'O' */
3959 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 0x50-0x5F 'P'-'Z', '_' */
3960 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x60-0x6F 'a'-'o' */
3961 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 0x70-0x7F 'p'-'z' */
3962 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80-0x8F */
3963 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90-0x9F */
3964 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xA0-0xAF */
3965 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xB0-0xBF */
3966 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xC0-0xCF */
3967 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xD0-0xDF */
3968 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xE0-0xEF */
3969 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xF0-0xFF */
3972 /* temporary function containing assert part for easier profiling */
3973 static void tmp_fld_check_assert(header_field_info *hfinfo) {
3974 /* The field must have a name (with length > 0) */
3975 DISSECTOR_ASSERT(hfinfo->name && hfinfo->name[0]);
3977 /* fields with an empty string for an abbreviation aren't filterable */
3978 DISSECTOR_ASSERT(hfinfo->abbrev);
3980 /* These types of fields are allowed to have value_strings, true_false_strings or a protocol_t struct*/
3981 DISSECTOR_ASSERT((hfinfo->strings == NULL) || (
3982 (hfinfo->type == FT_UINT8) ||
3983 (hfinfo->type == FT_UINT16) ||
3984 (hfinfo->type == FT_UINT24) ||
3985 (hfinfo->type == FT_UINT32) ||
3986 (hfinfo->type == FT_INT8) ||
3987 (hfinfo->type == FT_INT16) ||
3988 (hfinfo->type == FT_INT24) ||
3989 (hfinfo->type == FT_INT32) ||
3990 (hfinfo->type == FT_BOOLEAN) ||
3991 (hfinfo->type == FT_PROTOCOL) ||
3992 (hfinfo->type == FT_FRAMENUM) ));
3994 switch (hfinfo->type) {
4001 /* Hexadecimal and octal are, in printf() and everywhere else,
4002 * unsigned so don't allow dissectors to register a signed
4003 * field to be displayed unsigned. (Else how would we
4004 * display values negative values?)
4006 * If you want to take out this check, be sure to fix
4007 * hfinfo_numeric_format() so that it does not assert out
4008 * when trying to construct a hexadecimal representation of
4011 DISSECTOR_ASSERT(hfinfo->display != BASE_HEX &&
4012 hfinfo->display != BASE_HEX_DEC &&
4013 hfinfo->display != BASE_DEC_HEX &&
4014 hfinfo->display != BASE_OCT);
4021 /* Require integral types (other than frame number, which is
4022 always displayed in decimal) to have a number base */
4023 DISSECTOR_ASSERT(hfinfo->display != BASE_NONE);
4027 /* Don't allow bitfields or value strings for frame numbers */
4028 DISSECTOR_ASSERT(hfinfo->bitmask == 0);
4029 DISSECTOR_ASSERT(hfinfo->strings == NULL);
4038 proto_register_field_init(header_field_info *hfinfo, int parent)
4041 tmp_fld_check_assert(hfinfo);
4043 /* if this is a bitfield, compute bitshift */
4044 if (hfinfo->bitmask) {
4045 hfinfo->bitshift = wrs_count_bitshift(hfinfo->bitmask);
4048 hfinfo->parent = parent;
4049 hfinfo->same_name_next = NULL;
4050 hfinfo->same_name_prev = NULL;
4052 /* if we always add and never delete, then id == len - 1 is correct */
4053 if(gpa_hfinfo.len>=gpa_hfinfo.allocated_len){
4054 if(!gpa_hfinfo.hfi){
4055 gpa_hfinfo.allocated_len=1000;
4056 gpa_hfinfo.hfi=g_malloc(sizeof(header_field_info *)*1000);
4058 gpa_hfinfo.allocated_len+=1000;
4059 gpa_hfinfo.hfi=g_realloc(gpa_hfinfo.hfi, sizeof(header_field_info *)*gpa_hfinfo.allocated_len);
4062 gpa_hfinfo.hfi[gpa_hfinfo.len]=hfinfo;
4064 hfinfo->id = gpa_hfinfo.len - 1;
4066 /* if we have real names, enter this field in the name tree */
4067 if ((hfinfo->name[0] != 0) && (hfinfo->abbrev[0] != 0 )) {
4069 header_field_info *same_name_next_hfinfo;
4072 /* Check that the filter name (abbreviation) is legal;
4073 * it must contain only alphanumerics, '-', "_", and ".". */
4074 c = wrs_check_charset(fld_abbrev_chars, hfinfo->abbrev);
4076 fprintf(stderr, "OOPS: '%c' in '%s'\n", c, hfinfo->abbrev);
4077 DISSECTOR_ASSERT(!c);
4080 /* We allow multiple hfinfo's to be registered under the same
4081 * abbreviation. This was done for X.25, as, depending
4082 * on whether it's modulo-8 or modulo-128 operation,
4083 * some bitfield fields may be in different bits of
4084 * a byte, and we want to be able to refer to that field
4085 * with one name regardless of whether the packets
4086 * are modulo-8 or modulo-128 packets. */
4088 same_name_hfinfo = NULL;
4090 g_tree_insert(gpa_name_tree, (gpointer) (hfinfo->abbrev), hfinfo);
4091 /* GLIB 2.x - if it is already present
4092 * the previous hfinfo with the same name is saved
4093 * to same_name_hfinfo by value destroy callback */
4094 if (same_name_hfinfo) {
4095 /* There's already a field with this name.
4096 * Put it after that field in the list of
4097 * fields with this name, then allow the code
4098 * after this if{} block to replace the old
4099 * hfinfo with the new hfinfo in the GTree. Thus,
4100 * we end up with a linked-list of same-named hfinfo's,
4101 * with the root of the list being the hfinfo in the GTree */
4102 same_name_next_hfinfo =
4103 same_name_hfinfo->same_name_next;
4105 hfinfo->same_name_next = same_name_next_hfinfo;
4106 if (same_name_next_hfinfo)
4107 same_name_next_hfinfo->same_name_prev = hfinfo;
4109 same_name_hfinfo->same_name_next = hfinfo;
4110 hfinfo->same_name_prev = same_name_hfinfo;
4118 proto_register_subtree_array(gint *const *indices, int num_indices)
4121 gint *const *ptr = indices;
4124 * If we've already allocated the array of tree types, expand
4125 * it; this lets plugins such as mate add tree types after
4126 * the initial startup. (If we haven't already allocated it,
4127 * we don't allocate it; on the first pass, we just assign
4128 * ett values and keep track of how many we've assigned, and
4129 * when we're finished registering all dissectors we allocate
4130 * the array, so that we do only one allocation rather than
4131 * wasting CPU time and memory by growing the array for each
4132 * dissector that registers ett values.)
4134 if (tree_is_expanded != NULL) {
4136 g_realloc(tree_is_expanded,
4137 (num_tree_types+num_indices)*sizeof (gboolean));
4138 memset(tree_is_expanded + num_tree_types, 0,
4139 num_indices*sizeof (gboolean));
4143 * Assign "num_indices" subtree numbers starting at "num_tree_types",
4144 * returning the indices through the pointers in the array whose
4145 * first element is pointed to by "indices", and update
4146 * "num_tree_types" appropriately.
4148 for (i = 0; i < num_indices; i++, ptr++, num_tree_types++)
4149 **ptr = num_tree_types;
4153 proto_item_fill_label(field_info *fi, gchar *label_str)
4155 header_field_info *hfinfo = fi->hfinfo;
4161 guint32 n_addr; /* network-order IPv4 address */
4163 int ret; /*tmp return value */
4165 switch(hfinfo->type) {
4168 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4169 "%s", hfinfo->name);
4170 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4171 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4175 fill_label_boolean(fi, label_str);
4180 bytes = fvalue_get(&fi->value);
4182 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4183 "%s: %s", hfinfo->name,
4184 bytes_to_str(bytes, fvalue_length(&fi->value)));
4185 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH)) {
4186 /* Uh oh, we don't have enough room. Tell the
4187 * user that the field is truncated.
4189 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4190 "%s [truncated]: %s",
4192 bytes_to_str(bytes, fvalue_length(&fi->value)));
4193 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4197 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4198 "%s: <MISSING>", hfinfo->name);
4199 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4200 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4204 /* Four types of integers to take care of:
4205 * Bitfield, with val_string
4206 * Bitfield, w/o val_string
4207 * Non-bitfield, with val_string
4208 * Non-bitfield, w/o val_string
4215 if (hfinfo->bitmask) {
4216 if (hfinfo->strings) {
4217 fill_label_enumerated_bitfield(fi, label_str);
4220 fill_label_numeric_bitfield(fi, label_str);
4224 if (hfinfo->strings) {
4225 fill_label_enumerated_uint(fi, label_str);
4228 fill_label_uint(fi, label_str);
4234 fill_label_uint64(fi, label_str);
4241 DISSECTOR_ASSERT(!hfinfo->bitmask);
4242 if (hfinfo->strings) {
4243 fill_label_enumerated_int(fi, label_str);
4246 fill_label_int(fi, label_str);
4251 fill_label_int64(fi, label_str);
4255 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4256 "%s: %." STRINGIFY(FLT_DIG) "f",
4257 hfinfo->name, fvalue_get_floating(&fi->value));
4258 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4259 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4263 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4264 "%s: %." STRINGIFY(DBL_DIG) "g",
4265 hfinfo->name, fvalue_get_floating(&fi->value));
4266 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4267 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4270 case FT_ABSOLUTE_TIME:
4271 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4272 "%s: %s", hfinfo->name,
4273 abs_time_to_str(fvalue_get(&fi->value)));
4274 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4275 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4278 case FT_RELATIVE_TIME:
4279 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4280 "%s: %s seconds", hfinfo->name,
4281 rel_time_to_secs_str(fvalue_get(&fi->value)));
4282 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4283 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4287 integer = fvalue_get_uinteger(&fi->value);
4288 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4289 "%s: %s (0x%08X)", hfinfo->name,
4290 get_ipxnet_name(integer), integer);
4291 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4292 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4296 bytes = fvalue_get(&fi->value);
4297 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4298 "%s: %s (%s)", hfinfo->name,
4299 get_ether_name(bytes),
4300 ether_to_str(bytes));
4301 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4302 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4306 ipv4 = fvalue_get(&fi->value);
4307 n_addr = ipv4_get_net_order_addr(ipv4);
4308 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4309 "%s: %s (%s)", hfinfo->name,
4310 get_hostname(n_addr),
4311 ip_to_str((guint8*)&n_addr));
4312 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4313 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4317 bytes = fvalue_get(&fi->value);
4318 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4319 "%s: %s (%s)", hfinfo->name,
4320 get_hostname6((struct e_in6_addr *)bytes),
4321 ip6_to_str((struct e_in6_addr*)bytes));
4322 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4323 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4327 guid = fvalue_get(&fi->value);
4328 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4329 "%s: %s", hfinfo->name,
4331 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4332 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4336 bytes = fvalue_get(&fi->value);
4337 name = oid_resolved_from_encoded(bytes, fvalue_length(&fi->value));
4339 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4340 "%s: %s (%s)", hfinfo->name,
4341 oid_encoded2string(bytes, fvalue_length(&fi->value)), name);
4343 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4344 "%s: %s", hfinfo->name,
4345 oid_encoded2string(bytes, fvalue_length(&fi->value)));
4347 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4348 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4354 case FT_UINT_STRING:
4355 bytes = fvalue_get(&fi->value);
4356 if(strlen(bytes) > ITEM_LABEL_LENGTH) {
4357 /* Uh oh, we don't have enough room. Tell the
4358 * user that the field is truncated.
4360 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4361 "%s [truncated]: %s",
4363 format_text(bytes, strlen(bytes)));
4365 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4366 "%s: %s", hfinfo->name,
4367 format_text(bytes, strlen(bytes)));
4369 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4370 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4374 g_error("hfinfo->type %d (%s) not handled\n",
4376 ftype_name(hfinfo->type));
4377 DISSECTOR_ASSERT_NOT_REACHED();
4383 fill_label_boolean(field_info *fi, gchar *label_str)
4385 char *p = label_str;
4386 int bitfield_byte_length = 0, bitwidth;
4387 guint32 unshifted_value;
4389 int ret; /*tmp return value */
4391 header_field_info *hfinfo = fi->hfinfo;
4392 const true_false_string *tfstring = &tfs_true_false;
4394 if (hfinfo->strings) {
4395 tfstring = (const struct true_false_string*) hfinfo->strings;
4398 value = fvalue_get_uinteger(&fi->value);
4399 if (hfinfo->bitmask) {
4400 /* Figure out the bit width */
4401 bitwidth = hfinfo_bitwidth(hfinfo);
4404 unshifted_value = value;
4405 if (hfinfo->bitshift > 0) {
4406 unshifted_value <<= hfinfo->bitshift;
4409 /* Create the bitfield first */
4410 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
4411 bitfield_byte_length = p - label_str;
4414 /* Fill in the textual info */
4415 ret = g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
4416 "%s: %s", hfinfo->name,
4417 value ? tfstring->true_string : tfstring->false_string);
4418 if ((ret == -1) || (ret >= (ITEM_LABEL_LENGTH - bitfield_byte_length)))
4419 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4423 /* Fills data for bitfield ints with val_strings */
4425 fill_label_enumerated_bitfield(field_info *fi, gchar *label_str)
4427 const char *format = NULL;
4429 int bitfield_byte_length, bitwidth;
4430 guint32 unshifted_value;
4432 int ret; /*tmp return value */
4434 header_field_info *hfinfo = fi->hfinfo;
4436 /* Figure out the bit width */
4437 bitwidth = hfinfo_bitwidth(hfinfo);
4439 /* Pick the proper format string */
4440 format = hfinfo_uint_vals_format(hfinfo);
4443 unshifted_value = fvalue_get_uinteger(&fi->value);
4444 value = unshifted_value;
4445 if (hfinfo->bitshift > 0) {
4446 unshifted_value <<= hfinfo->bitshift;
4449 /* Create the bitfield first */
4450 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
4451 bitfield_byte_length = p - label_str;
4453 /* Fill in the textual info using stored (shifted) value */
4454 ret = g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
4455 format, hfinfo->name,
4456 val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
4457 if ((ret == -1) || (ret >= (ITEM_LABEL_LENGTH - bitfield_byte_length)))
4458 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4462 fill_label_numeric_bitfield(field_info *fi, gchar *label_str)
4464 const char *format = NULL;
4466 int bitfield_byte_length, bitwidth;
4467 guint32 unshifted_value;
4469 int ret; /*tmp return value */
4471 header_field_info *hfinfo = fi->hfinfo;
4473 /* Figure out the bit width */
4474 bitwidth = hfinfo_bitwidth(hfinfo);
4476 /* Pick the proper format string */
4477 format = hfinfo_uint_format(hfinfo);
4480 unshifted_value = fvalue_get_uinteger(&fi->value);
4481 value = unshifted_value;
4482 if (hfinfo->bitshift > 0) {
4483 unshifted_value <<= hfinfo->bitshift;
4486 /* Create the bitfield using */
4487 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
4488 bitfield_byte_length = p - label_str;
4490 /* Fill in the textual info using stored (shifted) value */
4491 if (IS_BASE_DUAL(hfinfo->display)) {
4492 ret = g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
4493 format, hfinfo->name, value, value);
4495 ret = g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
4496 format, hfinfo->name, value);
4498 if ((ret == -1) || (ret >= (ITEM_LABEL_LENGTH - bitfield_byte_length)))
4499 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4504 fill_label_enumerated_uint(field_info *fi, gchar *label_str)
4506 const char *format = NULL;
4507 header_field_info *hfinfo = fi->hfinfo;
4509 int ret; /*tmp return value */
4511 /* Pick the proper format string */
4512 format = hfinfo_uint_vals_format(hfinfo);
4514 value = fvalue_get_uinteger(&fi->value);
4516 /* Fill in the textual info */
4517 if (hfinfo->display & BASE_RANGE_STRING) {
4518 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4519 format, hfinfo->name,
4520 rval_to_str(value, hfinfo->strings, "Unknown"), value);
4522 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4523 format, hfinfo->name,
4524 val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
4526 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4527 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4531 fill_label_uint(field_info *fi, gchar *label_str)
4533 const char *format = NULL;
4534 header_field_info *hfinfo = fi->hfinfo;
4536 int ret; /*tmp return value */
4538 /* Pick the proper format string */
4539 format = hfinfo_uint_format(hfinfo);
4540 value = fvalue_get_uinteger(&fi->value);
4542 /* Fill in the textual info */
4543 if (IS_BASE_DUAL(hfinfo->display)) {
4544 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4545 format, hfinfo->name, value, value);
4547 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4548 format, hfinfo->name, value);
4550 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4551 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4555 fill_label_uint64(field_info *fi, gchar *label_str)
4557 const char *format = NULL;
4558 header_field_info *hfinfo = fi->hfinfo;
4560 int ret; /*tmp return value */
4562 /* Pick the proper format string */
4563 format = hfinfo_uint64_format(hfinfo);
4564 value = fvalue_get_integer64(&fi->value);
4566 /* Fill in the textual info */
4567 if (IS_BASE_DUAL(hfinfo->display)) {
4568 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4569 format, hfinfo->name, value, value);
4571 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4572 format, hfinfo->name, value);
4574 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4575 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4579 fill_label_enumerated_int(field_info *fi, gchar *label_str)
4581 const char *format = NULL;
4582 header_field_info *hfinfo = fi->hfinfo;
4584 int ret; /*tmp return value */
4586 /* Pick the proper format string */
4587 format = hfinfo_int_vals_format(hfinfo);
4588 value = fvalue_get_sinteger(&fi->value);
4590 /* Fill in the textual info */
4591 if (hfinfo->display & BASE_RANGE_STRING) {
4592 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4593 format, hfinfo->name,
4594 rval_to_str(value, hfinfo->strings, "Unknown"), value);
4596 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4597 format, hfinfo->name,
4598 val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
4600 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4601 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4605 fill_label_int(field_info *fi, gchar *label_str)
4607 const char *format = NULL;
4608 header_field_info *hfinfo = fi->hfinfo;
4610 int ret; /*tmp return value */
4612 /* Pick the proper format string */
4613 format = hfinfo_int_format(hfinfo);
4614 value = fvalue_get_sinteger(&fi->value);
4616 /* Fill in the textual info */
4617 if (IS_BASE_DUAL(hfinfo->display)) {
4618 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4619 format, hfinfo->name, value, value);
4621 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4622 format, hfinfo->name, value);
4624 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4625 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4629 fill_label_int64(field_info *fi, gchar *label_str)
4631 const char *format = NULL;
4632 header_field_info *hfinfo = fi->hfinfo;
4634 int ret; /*tmp return value */
4636 /* Pick the proper format string */
4637 format = hfinfo_int64_format(hfinfo);
4638 value = fvalue_get_integer64(&fi->value);
4640 /* Fill in the textual info */
4641 if (IS_BASE_DUAL(hfinfo->display)) {
4642 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4643 format, hfinfo->name, value, value);
4645 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4646 format, hfinfo->name, value);
4648 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4649 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4653 hfinfo_bitwidth(header_field_info *hfinfo)
4657 if (!hfinfo->bitmask) {
4661 switch(hfinfo->type) {
4679 bitwidth = hfinfo->display; /* hacky? :) */
4682 DISSECTOR_ASSERT_NOT_REACHED();
4689 hfinfo_uint_vals_format(header_field_info *hfinfo)
4691 const char *format = NULL;
4693 /* bit operation to reset the potential BASE_RANGE_STRING (or others in
4695 switch(hfinfo->display & BASE_STRUCTURE_RESET) {
4698 format = "%s: %s (%u)";
4700 case BASE_OCT: /* I'm lazy */
4701 format = "%s: %s (%o)";
4705 switch(hfinfo->type) {
4707 format = "%s: %s (0x%02x)";
4710 format = "%s: %s (0x%04x)";
4713 format = "%s: %s (0x%06x)";
4716 format = "%s: %s (0x%08x)";
4719 DISSECTOR_ASSERT_NOT_REACHED();
4724 DISSECTOR_ASSERT_NOT_REACHED();
4731 hfinfo_uint_format(header_field_info *hfinfo)
4733 const char *format = NULL;
4735 /* Pick the proper format string */
4736 if (hfinfo->type == FT_FRAMENUM) {
4738 * Frame numbers are always displayed in decimal.
4742 switch(hfinfo->display) {
4747 switch(hfinfo->type) {
4749 format = "%s: %u (0x%02x)";
4752 format = "%s: %u (0x%04x)";
4755 format = "%s: %u (0x%06x)";
4758 format = "%s: %u (0x%08x)";
4761 DISSECTOR_ASSERT_NOT_REACHED();
4765 case BASE_OCT: /* I'm lazy */
4769 switch(hfinfo->type) {
4771 format = "%s: 0x%02x";
4774 format = "%s: 0x%04x";
4777 format = "%s: 0x%06x";
4780 format = "%s: 0x%08x";
4783 DISSECTOR_ASSERT_NOT_REACHED();
4788 switch(hfinfo->type) {
4790 format = "%s: 0x%02x (%u)";
4793 format = "%s: 0x%04x (%u)";
4796 format = "%s: 0x%06x (%u)";
4799 format = "%s: 0x%08x (%u)";
4802 DISSECTOR_ASSERT_NOT_REACHED();
4807 DISSECTOR_ASSERT_NOT_REACHED();
4815 hfinfo_uint_value_format(header_field_info *hfinfo)
4817 const char *format = NULL;
4819 /* Pick the proper format string */
4820 if (hfinfo->type == FT_FRAMENUM) {
4822 * Frame numbers are always displayed in decimal.
4826 switch(hfinfo->display) {
4831 switch(hfinfo->type) {
4833 format = "%u (0x%02x)";
4836 format = "%u (0x%04x)";
4839 format = "%u (0x%06x)";
4842 format = "%u (0x%08x)";
4845 DISSECTOR_ASSERT_NOT_REACHED();
4853 switch(hfinfo->type) {
4867 DISSECTOR_ASSERT_NOT_REACHED();
4872 switch(hfinfo->type) {
4874 format = "0x%02x (%u)";
4877 format = "0x%04x (%u)";
4880 format = "0x%06x (%u)";
4883 format = "0x%08x (%u)";
4886 DISSECTOR_ASSERT_NOT_REACHED();
4891 DISSECTOR_ASSERT_NOT_REACHED();
4899 hfinfo_int_vals_format(header_field_info *hfinfo)
4901 const char *format = NULL;
4903 /* bit operation to reset the potential BASE_RANGE_STRING (or others in
4905 switch(hfinfo->display & BASE_STRUCTURE_RESET) {
4908 format = "%s: %s (%d)";
4910 case BASE_OCT: /* I'm lazy */
4911 format = "%s: %s (%o)";
4915 switch(hfinfo->type) {
4917 format = "%s: %s (0x%02x)";
4920 format = "%s: %s (0x%04x)";
4923 format = "%s: %s (0x%06x)";
4926 format = "%s: %s (0x%08x)";
4929 DISSECTOR_ASSERT_NOT_REACHED();
4934 DISSECTOR_ASSERT_NOT_REACHED();
4941 hfinfo_uint64_format(header_field_info *hfinfo)
4943 const char *format = NULL;
4945 /* Pick the proper format string */
4946 switch(hfinfo->display) {
4948 format = "%s: %" G_GINT64_MODIFIER "u";
4951 format = "%s: %" G_GINT64_MODIFIER "u (%" G_GINT64_MODIFIER "x)";
4953 case BASE_OCT: /* I'm lazy */
4954 format = "%s: %" G_GINT64_MODIFIER "o";
4957 format = "%s: 0x%016" G_GINT64_MODIFIER "x";
4960 format = "%s: 0x%016" G_GINT64_MODIFIER "x (%" G_GINT64_MODIFIER "u)";
4963 DISSECTOR_ASSERT_NOT_REACHED();
4970 hfinfo_int_format(header_field_info *hfinfo)
4972 const char *format = NULL;
4974 /* Pick the proper format string */
4975 switch(hfinfo->display) {
4980 switch(hfinfo->type) {
4982 format = "%s: %d (0x%02x)";
4985 format = "%s: %d (0x%04x)";
4988 format = "%s: %d (0x%06x)";
4991 format = "%s: %d (0x%08x)";
4994 DISSECTOR_ASSERT_NOT_REACHED();
4998 case BASE_OCT: /* I'm lazy */
5002 switch(hfinfo->type) {
5004 format = "%s: 0x%02x";
5007 format = "%s: 0x%04x";
5010 format = "%s: 0x%06x";
5013 format = "%s: 0x%08x";
5016 DISSECTOR_ASSERT_NOT_REACHED();
5021 switch(hfinfo->type) {
5023 format = "%s: 0x%02x (%d)";
5026 format = "%s: 0x%04x (%d)";
5029 format = "%s: 0x%06x (%d)";
5032 format = "%s: 0x%08x (%d)";
5035 DISSECTOR_ASSERT_NOT_REACHED();
5040 DISSECTOR_ASSERT_NOT_REACHED();
5047 hfinfo_int_value_format(header_field_info *hfinfo)
5049 const char *format = NULL;
5051 /* Pick the proper format string */
5052 switch(hfinfo->display) {
5057 switch(hfinfo->type) {
5059 format = "%d (0x%02x)";
5062 format = "%d (0x%04x)";
5065 format = "%d (0x%06x)";
5068 format = "%d (0x%08x)";
5071 DISSECTOR_ASSERT_NOT_REACHED();
5079 switch(hfinfo->type) {
5093 DISSECTOR_ASSERT_NOT_REACHED();
5098 switch(hfinfo->type) {
5100 format = "0x%02x (%d)";
5103 format = "0x%04x (%d)";
5106 format = "0x%06x (%d)";
5109 format = "0x%08x (%d)";
5112 DISSECTOR_ASSERT_NOT_REACHED();
5117 DISSECTOR_ASSERT_NOT_REACHED();
5124 hfinfo_int64_format(header_field_info *hfinfo)
5126 const char *format = NULL;
5128 /* Pick the proper format string */
5129 switch(hfinfo->display) {
5131 format = "%s: %" G_GINT64_MODIFIER "d";
5134 format = "%s: %" G_GINT64_MODIFIER "d (%" G_GINT64_MODIFIER "x)";
5136 case BASE_OCT: /* I'm lazy */
5137 format = "%s: %" G_GINT64_MODIFIER "o";
5140 format = "%s: 0x%016" G_GINT64_MODIFIER "x";
5143 format = "%s: 0x%016" G_GINT64_MODIFIER "x (%" G_GINT64_MODIFIER "d)";
5146 DISSECTOR_ASSERT_NOT_REACHED();
5155 proto_registrar_n(void)
5157 return gpa_hfinfo.len;
5161 proto_registrar_get_name(int n)
5163 header_field_info *hfinfo;
5165 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
5166 return hfinfo->name;
5170 proto_registrar_get_abbrev(int n)
5172 header_field_info *hfinfo;
5174 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
5175 return hfinfo->abbrev;
5179 proto_registrar_get_ftype(int n)
5181 header_field_info *hfinfo;
5183 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
5184 return hfinfo->type;
5188 proto_registrar_get_parent(int n)
5190 header_field_info *hfinfo;
5192 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
5193 return hfinfo->parent;
5197 proto_registrar_is_protocol(int n)
5199 header_field_info *hfinfo;
5201 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
5202 return (hfinfo->parent == -1 ? TRUE : FALSE);
5205 /* Returns length of field in packet (not necessarily the length
5206 * in our internal representation, as in the case of IPv4).
5207 * 0 means undeterminable at time of registration
5208 * -1 means the field is not registered. */
5210 proto_registrar_get_length(int n)
5212 header_field_info *hfinfo;
5214 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
5215 return ftype_length(hfinfo->type);
5220 /* Looks for a protocol or a field in a proto_tree. Returns TRUE if
5221 * it exists anywhere, or FALSE if it exists nowhere. */
5223 proto_check_for_protocol_or_field(proto_tree* tree, int id)
5225 GPtrArray *ptrs = proto_get_finfo_ptr_array(tree, id);
5230 else if (g_ptr_array_len(ptrs) > 0) {
5238 /* Return GPtrArray* of field_info pointers for all hfindex that appear in tree.
5239 * This only works if the hfindex was "primed" before the dissection
5240 * took place, as we just pass back the already-created GPtrArray*.
5241 * The caller should *not* free the GPtrArray*; proto_tree_free_node()
5244 proto_get_finfo_ptr_array(proto_tree *tree, int id)
5246 return g_hash_table_lookup(PTREE_DATA(tree)->interesting_hfids,
5247 GINT_TO_POINTER(id));
5251 /* Helper struct for proto_find_info() and proto_all_finfos() */
5257 /* Helper function for proto_find_info() */
5259 find_finfo(proto_node *node, gpointer data)
5261 field_info *fi = PITEM_FINFO(node);
5262 if (fi && fi->hfinfo) {
5263 if (fi->hfinfo->id == ((ffdata_t*)data)->id) {
5264 g_ptr_array_add(((ffdata_t*)data)->array, fi);
5268 /* Don't stop traversing. */
5272 /* Return GPtrArray* of field_info pointers for all hfindex that appear in a tree.
5273 * This works on any proto_tree, primed or unprimed, but actually searches
5274 * the tree, so it is slower than using proto_get_finfo_ptr_array on a primed tree.
5275 * The caller does need to free the returned GPtrArray with
5276 * g_ptr_array_free(<array>, FALSE).
5279 proto_find_finfo(proto_tree *tree, int id)
5283 ffdata.array = g_ptr_array_new();
5286 proto_tree_traverse_pre_order(tree, find_finfo, &ffdata);
5288 return ffdata.array;
5291 /* Helper function for proto_all_finfos() */
5293 every_finfo(proto_node *node, gpointer data)
5295 field_info *fi = PITEM_FINFO(node);
5296 if (fi && fi->hfinfo) {
5297 g_ptr_array_add(((ffdata_t*)data)->array, fi);
5300 /* Don't stop traversing. */
5304 /* Return GPtrArray* of field_info pointers containing all hfindexes that appear in a tree. */
5306 proto_all_finfos(proto_tree *tree)
5310 ffdata.array = g_ptr_array_new();
5313 proto_tree_traverse_pre_order(tree, every_finfo, &ffdata);
5315 return ffdata.array;
5326 check_for_offset(proto_node *node, gpointer data)
5328 field_info *fi = PITEM_FINFO(node);
5329 offset_search_t *offsearch = data;
5331 /* !fi == the top most container node which holds nothing */
5332 if (fi && !PROTO_ITEM_IS_HIDDEN(node) && fi->ds_tvb && offsearch->tvb == fi->ds_tvb) {
5333 if (offsearch->offset >= (guint) fi->start &&
5334 offsearch->offset < (guint) (fi->start + fi->length)) {
5336 offsearch->finfo = fi;
5337 return FALSE; /* keep traversing */
5340 return FALSE; /* keep traversing */
5343 /* Search a proto_tree backwards (from leaves to root) looking for the field
5344 * whose start/length occupies 'offset' */
5345 /* XXX - I couldn't find an easy way to search backwards, so I search
5346 * forwards, w/o stopping. Therefore, the last finfo I find will the be
5347 * the one I want to return to the user. This algorithm is inefficient
5348 * and could be re-done, but I'd have to handle all the children and
5349 * siblings of each node myself. When I have more time I'll do that.
5352 proto_find_field_from_offset(proto_tree *tree, guint offset, tvbuff_t *tvb)
5354 offset_search_t offsearch;
5356 offsearch.offset = offset;
5357 offsearch.finfo = NULL;
5358 offsearch.tvb = tvb;
5360 proto_tree_traverse_pre_order(tree, check_for_offset, &offsearch);
5362 return offsearch.finfo;
5365 /* Dumps the protocols in the registration database to stdout. An independent
5366 * program can take this output and format it into nice tables or HTML or
5369 * There is one record per line. The fields are tab-delimited.
5371 * Field 1 = protocol name
5372 * Field 2 = protocol short name
5373 * Field 3 = protocol filter name
5376 proto_registrar_dump_protocols(void)
5378 protocol_t *protocol;
5380 void *cookie = NULL;
5382 for (i = proto_get_first_protocol(&cookie); i != -1;
5383 i = proto_get_next_protocol(&cookie)) {
5384 protocol = find_protocol_by_id(i);
5385 printf("%s\t%s\t%s\n", protocol->name, protocol->short_name,
5386 protocol->filter_name);
5390 /* Dumps the value_string and true/false strings for fields that have
5391 * them. There is one record per line. Fields are tab-delimited.
5392 * There are two types of records, Value String records and True/False
5393 * String records. The first field, 'V' or 'T', indicates the type
5399 * Field 2 = field abbreviation to which this value string corresponds
5400 * Field 3 = Integer value
5403 * True/False Strings
5404 * ------------------
5406 * Field 2 = field abbreviation to which this true/false string corresponds
5407 * Field 3 = True String
5408 * Field 4 = False String
5411 proto_registrar_dump_values(void)
5413 header_field_info *hfinfo, *parent_hfinfo;
5415 const value_string *vals;
5416 const true_false_string *tfs;
5418 len = gpa_hfinfo.len;
5419 for (i = 0; i < len ; i++) {
5420 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
5422 if (hfinfo->id == hf_text_only) {
5426 /* ignore protocols */
5427 if (proto_registrar_is_protocol(i)) {
5430 /* process header fields */
5433 * If this field isn't at the head of the list of
5434 * fields with this name, skip this field - all
5435 * fields with the same name are really just versions
5436 * of the same field stored in different bits, and
5437 * should have the same type/radix/value list, and
5438 * just differ in their bit masks. (If a field isn't
5439 * a bitfield, but can be, say, 1 or 2 bytes long,
5440 * it can just be made FT_UINT16, meaning the
5441 * *maximum* length is 2 bytes, and be used
5444 if (hfinfo->same_name_prev != NULL)
5447 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
5452 if (hfinfo->type == FT_UINT8 ||
5453 hfinfo->type == FT_UINT16 ||
5454 hfinfo->type == FT_UINT24 ||
5455 hfinfo->type == FT_UINT32 ||
5456 hfinfo->type == FT_UINT64 ||
5457 hfinfo->type == FT_INT8 ||
5458 hfinfo->type == FT_INT16 ||
5459 hfinfo->type == FT_INT24 ||
5460 hfinfo->type == FT_INT32 ||
5461 hfinfo->type == FT_INT64) {
5463 vals = hfinfo->strings;
5465 else if (hfinfo->type == FT_BOOLEAN) {
5466 tfs = hfinfo->strings;
5469 /* Print value strings? */
5472 while (vals[vi].strptr) {
5473 /* Print in the proper base */
5474 if (hfinfo->display == BASE_HEX) {
5475 printf("V\t%s\t0x%x\t%s\n",
5481 printf("V\t%s\t%u\t%s\n",
5490 /* Print true/false strings? */
5492 printf("T\t%s\t%s\t%s\n", hfinfo->abbrev,
5493 tfs->true_string, tfs->false_string);
5499 /* Dumps the contents of the registration database to stdout. An indepedent
5500 * program can take this output and format it into nice tables or HTML or
5503 * There is one record per line. Each record is either a protocol or a header
5504 * field, differentiated by the first field. The fields are tab-delimited.
5509 * Field 2 = descriptive protocol name
5510 * Field 3 = protocol abbreviation
5516 * Field 2 = descriptive field name
5517 * Field 3 = field abbreviation
5518 * Field 4 = type ( textual representation of the the ftenum type )
5519 * Field 5 = parent protocol abbreviation
5520 * Field 6 = blurb describing field
5524 * Field 2 = descriptive field name
5525 * Field 3 = field abbreviation
5526 * Field 4 = type ( textual representation of the the ftenum type )
5527 * Field 5 = parent protocol abbreviation
5528 * Field 6 = blurb describing field
5529 * Field 7 = base for display (for integer types)
5530 * Field 8 = blurb describing field (yes, apparently we repeated this accidentally)
5534 * Field 2 = descriptive field name
5535 * Field 3 = field abbreviation
5536 * Field 4 = type ( textual representation of the the ftenum type )
5537 * Field 5 = parent protocol abbreviation
5538 * Field 6 = blurb describing field
5539 * Field 7 = base for display (for integer types)
5543 proto_registrar_dump_fields(int format)
5545 header_field_info *hfinfo, *parent_hfinfo;
5547 const char *enum_name;
5548 const char *base_name;
5551 len = gpa_hfinfo.len;
5552 for (i = 0; i < len ; i++) {
5553 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
5556 * Skip the pseudo-field for "proto_tree_add_text()" since
5557 * we don't want it in the list of filterable fields.
5559 if (hfinfo->id == hf_text_only)
5562 /* format for protocols */
5563 if (proto_registrar_is_protocol(i)) {
5564 printf("P\t%s\t%s\n", hfinfo->name, hfinfo->abbrev);
5566 /* format for header fields */
5569 * If this field isn't at the head of the list of
5570 * fields with this name, skip this field - all
5571 * fields with the same name are really just versions
5572 * of the same field stored in different bits, and
5573 * should have the same type/radix/value list, and
5574 * just differ in their bit masks. (If a field isn't
5575 * a bitfield, but can be, say, 1 or 2 bytes long,
5576 * it can just be made FT_UINT16, meaning the
5577 * *maximum* length is 2 bytes, and be used
5580 if (hfinfo->same_name_prev != NULL)
5583 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
5585 enum_name = ftype_name(hfinfo->type);
5589 if (hfinfo->type == FT_UINT8 ||
5590 hfinfo->type == FT_UINT16 ||
5591 hfinfo->type == FT_UINT24 ||
5592 hfinfo->type == FT_UINT32 ||
5593 hfinfo->type == FT_UINT64 ||
5594 hfinfo->type == FT_INT8 ||
5595 hfinfo->type == FT_INT16 ||
5596 hfinfo->type == FT_INT24 ||
5597 hfinfo->type == FT_INT32 ||
5598 hfinfo->type == FT_INT64) {
5601 switch(hfinfo->display) {
5603 base_name = "BASE_NONE";
5606 base_name = "BASE_DEC";
5609 base_name = "BASE_HEX";
5612 base_name = "BASE_OCT";
5615 base_name = "BASE_DEC_HEX";
5618 base_name = "BASE_HEX_DEC";
5624 blurb = hfinfo->blurb;
5628 printf("F\t%s\t%s\t%s\t%s\t%s\n",
5629 hfinfo->name, hfinfo->abbrev, enum_name,
5630 parent_hfinfo->abbrev, blurb);
5632 else if (format == 2) {
5633 printf("F\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n",
5634 hfinfo->name, hfinfo->abbrev, enum_name,
5635 parent_hfinfo->abbrev, blurb,
5638 else if (format == 3) {
5639 printf("F\t%s\t%s\t%s\t%s\t%s\t%s\t%u\n",
5640 hfinfo->name, hfinfo->abbrev, enum_name,
5641 parent_hfinfo->abbrev, blurb,
5642 base_name, hfinfo->bitmask);
5645 g_assert_not_reached();
5652 hfinfo_numeric_format(header_field_info *hfinfo)
5654 const char *format = NULL;
5656 /* Pick the proper format string */
5657 if (hfinfo->type == FT_FRAMENUM) {
5659 * Frame numbers are always displayed in decimal.
5661 format = "%s == %u";
5663 /* Pick the proper format string, ignoring BASE_RANGE_STRING flag */
5664 switch(hfinfo->display & ~BASE_RANGE_STRING) {
5667 case BASE_OCT: /* I'm lazy */
5668 switch(hfinfo->type) {
5673 format = "%s == %u";
5676 format = "%s == %" G_GINT64_MODIFIER "u";
5682 format = "%s == %d";
5685 format = "%s == %" G_GINT64_MODIFIER "d";
5688 DISSECTOR_ASSERT_NOT_REACHED();
5694 switch(hfinfo->type) {
5696 format = "%s == 0x%02x";
5699 format = "%s == 0x%04x";
5702 format = "%s == 0x%06x";
5705 format = "%s == 0x%08x";
5708 format = "%s == 0x%016" G_GINT64_MODIFIER "x";
5711 DISSECTOR_ASSERT_NOT_REACHED();
5716 DISSECTOR_ASSERT_NOT_REACHED();
5723 /* This function indicates whether it's possible to construct a
5724 * "match selected" display filter string for the specified field,
5725 * returns an indication of whether it's possible, and, if it's
5726 * possible and "filter" is non-null, constructs the filter and
5727 * sets "*filter" to point to it.
5728 * You do not need to [g_]free() this string since it will be automatically
5729 * freed once the next packet is dissected.
5732 construct_match_selected_string(field_info *finfo, epan_dissect_t *edt,
5735 header_field_info *hfinfo;
5741 gint start, length, length_remaining;
5743 gchar is_signed_num = FALSE;
5745 hfinfo = finfo->hfinfo;
5746 DISSECTOR_ASSERT(hfinfo);
5747 abbrev_len = strlen(hfinfo->abbrev);
5750 * XXX - we can't use the "val_to_string_repr" and "string_repr_len"
5751 * functions for FT_UINT and FT_INT types, as we choose the base in
5752 * the string expression based on the display base of the field.
5754 * Note that the base does matter, as this is also used for
5755 * the protocolinfo tap.
5757 * It might be nice to use them in "proto_item_fill_label()"
5758 * as well, although, there, you'd have to deal with the base
5759 * *and* with resolved values for addresses.
5761 * Perhaps we need two different val_to_string routines, one
5762 * to generate items for display filters and one to generate
5763 * strings for display, and pass to both of them the
5764 * "display" and "strings" values in the header_field_info
5765 * structure for the field, so they can get the base and,
5766 * if the field is Boolean or an enumerated integer type,
5767 * the tables used to generate human-readable values.
5769 switch(hfinfo->type) {
5775 is_signed_num = TRUE;
5782 * 4 bytes for " == ".
5785 * a sign + up to 10 digits of 32-bit integer,
5788 * "0x" + 8 digits of 32-bit integer, in hex;
5790 * 11 digits of 32-bit integer, in octal.
5791 * (No, we don't do octal, but this way,
5792 * we know that if we do, this will still
5795 * 1 byte for the trailing '\0'.
5797 if (filter != NULL) {
5798 dfilter_len = abbrev_len + 4 + 11 + 1;
5799 *filter = ep_alloc0(dfilter_len);
5800 format = hfinfo_numeric_format(hfinfo);
5802 g_snprintf(*filter, dfilter_len, format,
5804 fvalue_get_sinteger(&finfo->value));
5806 g_snprintf(*filter, dfilter_len, format,
5808 fvalue_get_uinteger(&finfo->value));
5816 * 4 bytes for " == ".
5819 * a sign + up to 20 digits of 32-bit integer,
5822 * "0x" + 16 digits of 32-bit integer, in hex;
5824 * 22 digits of 32-bit integer, in octal.
5825 * (No, we don't do octal, but this way,
5826 * we know that if we do, this will still
5829 * 1 byte for the trailing '\0'.
5831 if (filter != NULL) {
5832 dfilter_len = abbrev_len + 4 + 22 + 1;
5833 *filter = ep_alloc0(dfilter_len);
5834 format = hfinfo_numeric_format(hfinfo);
5835 g_snprintf(*filter, dfilter_len, format,
5837 fvalue_get_integer64(&finfo->value));
5843 *filter = ep_strdup(finfo->hfinfo->abbrev);
5849 * If the length is 0, just match the name of the
5852 * (Also check for negative values, just in case,
5853 * as we'll cast it to an unsigned value later.)
5855 length = finfo->length;
5858 *filter = ep_strdup(finfo->hfinfo->abbrev);
5865 * This doesn't have a value, so we'd match
5866 * on the raw bytes at this address.
5868 * Should we be allowed to access to the raw bytes?
5869 * If "edt" is NULL, the answer is "no".
5875 * Is this field part of the raw frame tvbuff?
5876 * If not, we can't use "frame[N:M]" to match
5879 * XXX - should this be frame-relative, or
5880 * protocol-relative?
5882 * XXX - does this fallback for non-registered
5883 * fields even make sense?
5885 if (finfo->ds_tvb != edt->tvb)
5886 return FALSE; /* you lose */
5889 * Don't go past the end of that tvbuff.
5891 length_remaining = tvb_length_remaining(finfo->ds_tvb, finfo->start);
5892 if (length > length_remaining)
5893 length = length_remaining;
5897 if (filter != NULL) {
5898 start = finfo->start;
5899 buf_len = 32 + length * 3;
5900 *filter = ep_alloc0(buf_len);
5903 ptr += g_snprintf(ptr, buf_len-(ptr-*filter),
5904 "frame[%d:%d] == ", finfo->start, length);
5905 for (i=0;i<length; i++) {
5906 c = tvb_get_guint8(finfo->ds_tvb, start);
5909 ptr += g_snprintf(ptr, buf_len-(ptr-*filter), "%02x", c);
5912 ptr += g_snprintf(ptr, buf_len-(ptr-*filter), ":%02x", c);
5918 /* By default, use the fvalue's "to_string_repr" method. */
5920 /* Figure out the string length needed.
5921 * The ft_repr length.
5922 * 4 bytes for " == ".
5923 * 1 byte for trailing NUL.
5925 if (filter != NULL) {
5926 dfilter_len = fvalue_string_repr_len(&finfo->value,
5928 dfilter_len += abbrev_len + 4 + 1;
5929 *filter = ep_alloc0(dfilter_len);
5931 /* Create the string */
5932 g_snprintf(*filter, dfilter_len, "%s == ",
5934 fvalue_to_string_repr(&finfo->value,
5936 &(*filter)[abbrev_len + 4]);
5945 * Returns TRUE if we can do a "match selected" on the field, FALSE
5949 proto_can_match_selected(field_info *finfo, epan_dissect_t *edt)
5951 return construct_match_selected_string(finfo, edt, NULL);
5954 /* This function attempts to construct a "match selected" display filter
5955 * string for the specified field; if it can do so, it returns a pointer
5956 * to the string, otherwise it returns NULL.
5958 * The string is allocated with packet lifetime scope.
5959 * You do not need to [g_]free() this string since it will be automatically
5960 * freed once the next packet is dissected.
5963 proto_construct_match_selected_string(field_info *finfo, epan_dissect_t *edt)
5967 if (!construct_match_selected_string(finfo, edt, &filter))
5973 /* This function will dissect a sequence of bytes that describe a
5975 * hf_hdr is a 8/16/24/32 bit integer that describes the bitmask to be dissected.
5976 * This field will form an expansion under which the individual fields of the
5977 * bitmask is dissected and displayed.
5978 * This field must be of the type FT_[U]INT{8|16|24|32}.
5980 * fields is an array of pointers to int that lists all the fields of the
5981 * bitmask. These fields can be either of the type FT_BOOLEAN for flags
5982 * or another integer of the same type/size as hf_hdr with a mask specified.
5983 * This array is terminated by a NULL entry.
5985 * FT_BOOLEAN bits that are set to 1 will have the name added to the expansion.
5986 * FT_integer fields that have a value_string attached will have the
5987 * matched string displayed on the expansion line.
5990 proto_tree_add_bitmask(proto_tree *parent_tree, tvbuff_t *tvb, int offset, int hf_hdr, gint ett, const int **fields, gboolean little_endian)
5992 proto_tree *tree=NULL;
5993 proto_item *item=NULL;
5994 header_field_info *hf_info;
5998 hf_info=proto_registrar_get_nth(hf_hdr);
5999 switch(hf_info->type){
6003 value=tvb_get_guint8(tvb, offset);
6009 value=tvb_get_letohs(tvb, offset);
6011 value=tvb_get_ntohs(tvb, offset);
6018 value=tvb_get_letoh24(tvb, offset);
6020 value=tvb_get_ntoh24(tvb, offset);
6027 value=tvb_get_letohl(tvb, offset);
6029 value=tvb_get_ntohl(tvb, offset);
6033 g_assert_not_reached();
6037 item=proto_tree_add_item(parent_tree, hf_hdr, tvb, offset, len, little_endian);
6038 tree=proto_item_add_subtree(item, ett);
6042 header_field_info *hf_field;
6043 guint32 tmpval, tmpmask;
6045 hf_field=proto_registrar_get_nth(**fields);
6046 switch(hf_field->type){
6055 proto_tree_add_item(tree, **fields, tvb, offset, len, little_endian);
6057 /* Mask and shift out the value */
6058 tmpmask=hf_field->bitmask;
6062 while(!(tmpmask&0x00000001)){
6067 /* Show the value_string content (if there is one) */
6068 if(hf_field->strings){
6069 proto_item_append_text(item, ", %s", val_to_str(tmpval, hf_field->strings, "Unknown"));
6074 proto_tree_add_item(tree, **fields, tvb, offset, len, little_endian);
6075 /* if the flag is set, show the name */
6076 if(hf_field->bitmask&value){
6077 proto_item_append_text(item, ", %s", hf_field->name);
6081 g_assert_not_reached();
6091 proto_tree_add_bits_item(proto_tree *tree, int hf_index, tvbuff_t *tvb, gint bit_offset, gint no_of_bits, gboolean little_endian)
6093 return proto_tree_add_bits_ret_val(tree, hf_index, tvb, bit_offset, no_of_bits, NULL, little_endian);
6097 * This function will dissect a sequence of bits that does not need to be byte aligned the bits
6098 * set vill be shown in the tree as ..10 10.. and the integer value returned if return_value is set.
6099 * Offset should be given in bits from the start of the tvb.
6103 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)
6108 guint8 remaining_bits;
6109 guint64 mask = 0,tmp;
6111 header_field_info *hf_field;
6116 hf_field = proto_registrar_get_nth(hf_index);
6118 /* Byte align offset */
6119 offset = bit_offset>>3;
6123 * Calculate the number of octets used to hold the bits
6125 tot_no_bits = ((bit_offset&0x7)+no_of_bits);
6126 length = tot_no_bits>>3;
6127 remaining_bits = tot_no_bits % 8;
6128 if ((remaining_bits)!=0)
6131 if (no_of_bits < 9){
6132 value = tvb_get_bits8(tvb, bit_offset, no_of_bits);
6133 }else if(no_of_bits < 17){
6134 value = tvb_get_bits16(tvb, bit_offset, no_of_bits, little_endian);
6135 }else if(no_of_bits < 33){
6136 value = tvb_get_bits32(tvb, bit_offset, no_of_bits, little_endian);
6137 }else if(no_of_bits < 65){
6138 value = tvb_get_bits64(tvb, bit_offset, no_of_bits, little_endian);
6139 }else if(no_of_bits>64){
6140 DISSECTOR_ASSERT_NOT_REACHED();
6146 mask = mask << (no_of_bits-1);
6148 /* prepare the string */
6151 for(bit=0;bit<((int)(bit_offset&0x07));bit++){
6152 if(bit&&(!(bit%4))){
6157 /* read the bits for the int */
6158 for(i=0;i<no_of_bits;i++){
6159 if(bit&&(!(bit%4))){
6162 if(bit&&(!(bit%8))){
6175 if(bit&&(!(bit%4))){
6182 *return_value=value;
6188 strcat(str,hf_field->name);
6190 switch(hf_field->type){
6193 if (hf_field->strings) {
6194 const true_false_string *tfstring = &tfs_true_false;
6195 tfstring = (const struct true_false_string*) hf_field->strings;
6197 return proto_tree_add_boolean_format(tree, hf_index, tvb, offset, length, (guint32)value,
6200 (guint32)value ? tfstring->true_string : tfstring->false_string);
6202 return proto_tree_add_boolean_format(tree, hf_index, tvb, offset, length, (guint32)value,
6212 /* 1 - 32 bits field */
6213 if (hf_field->strings) {
6214 return proto_tree_add_uint_format(tree, hf_index, tvb, offset, length, (guint32)value,
6217 val_to_str((guint32)value, cVALS(hf_field->strings), "Unknown "),
6221 switch(hf_field->display){
6223 return proto_tree_add_uint_format(tree, hf_index, tvb, offset, length, (guint32)value,
6229 return proto_tree_add_uint_format(tree, hf_index, tvb, offset, length, (guint32)value,
6235 DISSECTOR_ASSERT_NOT_REACHED();
6241 switch(hf_field->display){
6243 return proto_tree_add_uint64_format(tree, hf_index, tvb, offset, length, value,
6244 "%s: %" G_GINT64_MODIFIER "u",
6248 return proto_tree_add_uint64_format(tree, hf_index, tvb, offset, length, value,
6249 "%s: 0x%" G_GINT64_MODIFIER "x",
6253 DISSECTOR_ASSERT_NOT_REACHED();
6259 DISSECTOR_ASSERT_NOT_REACHED();