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"
51 #include "wspython/wspy_register.h"
53 #define SUBTREE_ONCE_ALLOCATION_NUMBER 8
54 #define SUBTREE_MAX_LEVELS 256
55 /* Throw an exception if we exceed this many tree items. */
56 /* XXX - This should probably be a preference */
57 #define MAX_TREE_ITEMS (1 * 1000 * 1000)
60 typedef struct __subtree_lvl {
67 subtree_lvl *pushed_tree;
68 guint8 pushed_tree_index;
69 guint8 pushed_tree_max;
75 /* Candidates for assembler */
77 wrs_count_bitshift(const guint32 bitmask)
81 while ((bitmask & (1 << bitshift)) == 0)
86 #define cVALS(x) (const value_string*)(x)
88 /** See inlined comments.
89 @param tree the tree to append this item to
90 @param hfindex field index
91 @param hfinfo header_field
92 @return the header field matching 'hfinfo' */
93 #define TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo) \
94 /* If this item is not referenced we dont have to do much work \
95 at all but we should still return a node so that \
96 field items below this node ( think proto_item_add_subtree() )\
97 will still have somewhere to attach to \
98 or else filtering will not work (they would be ignored since tree\
100 DONT try to fake a node where PTREE_FINFO(tree) is NULL \
101 since dissectors that want to do proto_item_set_len() or \
102 other operations that dereference this would crash. \
103 We fake FT_PROTOCOL unless some clients have requested us \
108 PTREE_DATA(tree)->count++; \
109 if (PTREE_DATA(tree)->count > MAX_TREE_ITEMS) { \
110 /* Let the exception handler add items to the tree */ \
111 PTREE_DATA(tree)->count = 0; \
112 THROW_MESSAGE(DissectorError, \
113 ep_strdup_printf("More than %d items in the tree -- possible infinite loop", MAX_TREE_ITEMS)); \
115 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo); \
116 if(!(PTREE_DATA(tree)->visible)){ \
117 if(PTREE_FINFO(tree)){ \
118 if((hfinfo->ref_type != HF_REF_TYPE_DIRECT) \
119 && (hfinfo->type!=FT_PROTOCOL || \
120 PTREE_DATA(tree)->fake_protocols)){ \
121 /* just return tree back to the caller */\
127 /** See inlined comments.
128 @param tree the tree to append this item to
129 @param pi the created protocol item we're about to return */
131 #define TRY_TO_FAKE_THIS_REPR(tree, pi) \
132 DISSECTOR_ASSERT(tree); \
133 if(!(PTREE_DATA(tree)->visible)) { \
134 /* If the tree (GUI) isn't visible it's pointless for us to generate the protocol \
135 * items string representation */ \
139 #define TRY_TO_FAKE_THIS_REPR(tree, pi)
143 proto_tree_free_node(proto_node *node, gpointer data);
145 static void fill_label_boolean(field_info *fi, gchar *label_str);
146 static void fill_label_uint(field_info *fi, gchar *label_str);
147 static void fill_label_uint64(field_info *fi, gchar *label_str);
148 static void fill_label_bitfield(field_info *fi, gchar *label_str);
149 static void fill_label_int(field_info *fi, gchar *label_str);
150 static void fill_label_int64(field_info *fi, gchar *label_str);
152 static const char* hfinfo_uint_vals_format(const header_field_info *hfinfo);
153 static const char* hfinfo_uint_format(const header_field_info *hfinfo);
154 static const char* hfinfo_uint_value_format(const header_field_info *hfinfo);
155 static const char* hfinfo_uint64_format(const header_field_info *hfinfo);
156 static const char* hfinfo_int_vals_format(const header_field_info *hfinfo);
157 static const char* hfinfo_int_format(const header_field_info *hfinfo);
158 static const char* hfinfo_int_value_format(const header_field_info *hfinfo);
159 static const char* hfinfo_int64_format(const header_field_info *hfinfo);
160 static const char* hfinfo_numeric_value_format(const header_field_info *hfinfo);
163 proto_tree_add_node(proto_tree *tree, field_info *fi);
165 static header_field_info *
166 get_hfi_and_length(int hfindex, tvbuff_t *tvb, const gint start, gint *length,
170 new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
171 const gint start, const gint item_length);
174 alloc_field_info(proto_tree *tree, int hfindex, tvbuff_t *tvb,
175 const gint start, gint *length);
178 proto_tree_add_pi(proto_tree *tree, int hfindex, tvbuff_t *tvb,
179 gint start, gint *length, field_info **pfi);
182 proto_tree_set_representation_value(proto_item *pi, const char *format, va_list ap);
184 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap);
187 proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb);
189 proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length);
191 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length);
193 proto_tree_set_time(field_info *fi, nstime_t *value_ptr);
195 proto_tree_set_string(field_info *fi, const char* value);
197 proto_tree_set_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
199 proto_tree_set_ebcdic_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
201 proto_tree_set_ether(field_info *fi, const guint8* value);
203 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start);
205 proto_tree_set_ipxnet(field_info *fi, guint32 value);
207 proto_tree_set_ipv4(field_info *fi, guint32 value);
209 proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr);
211 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
213 proto_tree_set_guid(field_info *fi, const e_guid_t *value_ptr);
215 proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, gint start, const guint encoding);
217 proto_tree_set_oid(field_info *fi, const guint8* value_ptr, gint length);
219 proto_tree_set_oid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
221 proto_tree_set_boolean(field_info *fi, guint32 value);
223 proto_tree_set_float(field_info *fi, float value);
225 proto_tree_set_double(field_info *fi, double value);
227 proto_tree_set_uint(field_info *fi, guint32 value);
229 proto_tree_set_int(field_info *fi, gint32 value);
231 proto_tree_set_uint64(field_info *fi, guint64 value);
233 proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start, guint length, const guint encoding);
235 proto_item_add_bitmask_tree(proto_item *item, tvbuff_t *tvb, const int offset,
236 const int len, const gint ett, const gint **fields,
237 const gboolean little_endian, const int flags,
240 static int proto_register_field_init(header_field_info *hfinfo, const int parent);
242 /* special-case header field used within proto.c */
243 int hf_text_only = -1;
245 /* Structure for information about a protocol */
247 const char *name; /* long description */
248 const char *short_name; /* short description */
249 const char *filter_name; /* name of this protocol in filters */
250 int proto_id; /* field ID for this protocol */
251 GList *fields; /* fields for this protocol */
252 GList *last_field; /* pointer to end of list of fields */
253 gboolean is_enabled; /* TRUE if protocol is enabled */
254 gboolean can_toggle; /* TRUE if is_enabled can be changed */
255 gboolean is_private; /* TRUE is protocol is private */
258 /* List of all protocols */
259 static GList *protocols = NULL;
261 #define INITIAL_NUM_PROTOCOL_HFINFO 1500
263 /* Contains information about protocols and header fields. Used when
264 * dissectors register their data */
265 #if GLIB_CHECK_VERSION(2,10,0)
267 static GMemChunk *gmc_hfinfo = NULL;
270 /* Contains information about a field when a dissector calls
271 * proto_tree_add_item. */
272 SLAB_ITEM_TYPE_DEFINE(field_info)
273 static SLAB_FREE_LIST_DEFINE(field_info)
274 static field_info *field_info_tmp=NULL;
275 #define FIELD_INFO_NEW(fi) \
276 SLAB_ALLOC(fi, field_info)
277 #define FIELD_INFO_FREE(fi) \
278 SLAB_FREE(fi, field_info)
280 /* Contains the space for proto_nodes. */
281 SLAB_ITEM_TYPE_DEFINE(proto_node)
282 static SLAB_FREE_LIST_DEFINE(proto_node)
283 #define PROTO_NODE_NEW(node) \
284 SLAB_ALLOC(node, proto_node) \
285 node->first_child = NULL; \
286 node->last_child = NULL; \
289 #define PROTO_NODE_FREE(node) \
290 SLAB_FREE(node, proto_node)
292 /* String space for protocol and field items for the GUI */
293 SLAB_ITEM_TYPE_DEFINE(item_label_t)
294 static SLAB_FREE_LIST_DEFINE(item_label_t)
295 #define ITEM_LABEL_NEW(il) \
296 SLAB_ALLOC(il, item_label_t)
297 #define ITEM_LABEL_FREE(il) \
298 SLAB_FREE(il, item_label_t)
300 #define PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo) \
301 DISSECTOR_ASSERT((guint)hfindex < gpa_hfinfo.len); \
302 hfinfo=gpa_hfinfo.hfi[hfindex];
304 /* List which stores protocols and fields that have been registered */
305 typedef struct _gpa_hfinfo_t {
307 guint32 allocated_len;
308 header_field_info **hfi;
310 gpa_hfinfo_t gpa_hfinfo;
312 /* Balanced tree of abbreviations and IDs */
313 static GTree *gpa_name_tree = NULL;
314 static header_field_info *same_name_hfinfo;
316 static void save_same_name_hfinfo(gpointer data)
318 same_name_hfinfo = (header_field_info*)data;
321 /* Points to the first element of an array of Booleans, indexed by
322 a subtree item type; that array element is TRUE if subtrees of
323 an item of that type are to be expanded. */
324 gboolean *tree_is_expanded;
326 /* Number of elements in that array. */
329 /* Name hashtables for fast detection of duplicate names */
330 static GHashTable* proto_names = NULL;
331 static GHashTable* proto_short_names = NULL;
332 static GHashTable* proto_filter_names = NULL;
335 proto_compare_name(gconstpointer p1_arg, gconstpointer p2_arg)
337 const protocol_t *p1 = p1_arg;
338 const protocol_t *p2 = p2_arg;
340 return g_ascii_strcasecmp(p1->short_name, p2->short_name);
344 /* initialize data structures and register protocols and fields */
346 proto_init(void (register_all_protocols_func)(register_cb cb, gpointer client_data),
347 void (register_all_handoffs_func)(register_cb cb, gpointer client_data),
349 gpointer client_data)
351 static hf_register_info hf[] = {
353 { "Text item", "text", FT_NONE, BASE_NONE, NULL, 0x0,
359 proto_names = g_hash_table_new_full(g_int_hash, g_int_equal, g_free, NULL);
360 proto_short_names = g_hash_table_new(wrs_str_hash, g_str_equal);
361 proto_filter_names = g_hash_table_new(wrs_str_hash, g_str_equal);
363 #if GLIB_CHECK_VERSION(2,10,0)
365 gmc_hfinfo = g_mem_chunk_new("gmc_hfinfo",
366 sizeof(header_field_info),
367 INITIAL_NUM_PROTOCOL_HFINFO * sizeof(header_field_info),
372 gpa_hfinfo.allocated_len=0;
374 gpa_name_tree = g_tree_new_full(wrs_strcmp_with_data, NULL, NULL, save_same_name_hfinfo);
376 /* Initialize the ftype subsystem */
379 /* Register one special-case FT_TEXT_ONLY field for use when
380 converting wireshark to new-style proto_tree. These fields
381 are merely strings on the GUI tree; they are not filterable */
382 proto_register_field_array(-1, hf, array_length(hf));
384 /* Have each built-in dissector register its protocols, fields,
385 dissector tables, and dissectors to be called through a
386 handle, and do whatever one-time initialization it needs to
388 register_all_protocols_func(cb, client_data);
390 /* Now scan for python protocols */
391 register_all_py_protocols_func(cb, client_data);
395 /* Now scan for plugins and load all the ones we find, calling
396 their register routines to do the stuff described above. */
398 (*cb)(RA_PLUGIN_REGISTER, NULL, client_data);
400 register_all_plugin_registrations();
403 /* Now call the "handoff registration" routines of all built-in
404 dissectors; those routines register the dissector in other
405 dissectors' handoff tables, and fetch any dissector handles
407 register_all_handoffs_func(cb, client_data);
410 /* Now do the same with python dissectors */
411 register_all_py_handoffs_func(cb, client_data);
415 /* Now do the same with plugins. */
417 (*cb)(RA_PLUGIN_HANDOFF, NULL, client_data);
418 register_all_plugin_handoffs();
421 /* sort the protocols by protocol name */
422 protocols = g_list_sort(protocols, proto_compare_name);
424 /* We've assigned all the subtree type values; allocate the array
425 for them, and zero it out. */
426 tree_is_expanded = g_new0(gboolean, num_tree_types);
432 /* Free the abbrev/ID GTree */
434 g_tree_destroy(gpa_name_tree);
435 gpa_name_tree = NULL;
439 protocol_t *protocol = protocols->data;
440 header_field_info *hfinfo;
441 PROTO_REGISTRAR_GET_NTH(protocol->proto_id, hfinfo);
442 DISSECTOR_ASSERT(protocol->proto_id == hfinfo->id);
444 #if GLIB_CHECK_VERSION(2,10,0)
445 g_slice_free(header_field_info, hfinfo);
447 g_mem_chunk_free(gmc_hfinfo, hfinfo);
450 g_list_free(protocol->fields);
451 protocols = g_list_remove(protocols, protocol);
456 g_hash_table_destroy(proto_names);
460 if (proto_short_names) {
461 g_hash_table_destroy(proto_short_names);
462 proto_short_names = NULL;
465 if (proto_filter_names) {
466 g_hash_table_destroy(proto_filter_names);
467 proto_filter_names = NULL;
470 #if GLIB_CHECK_VERSION(2,10,0)
473 g_mem_chunk_destroy(gmc_hfinfo);
478 if(gpa_hfinfo.allocated_len){
480 gpa_hfinfo.allocated_len=0;
481 g_free(gpa_hfinfo.hfi);
484 g_free(tree_is_expanded);
485 tree_is_expanded = NULL;
489 proto_tree_traverse_pre_order(proto_tree *tree, proto_tree_traverse_func func,
492 proto_node *pnode = tree;
496 if (func(pnode, data))
499 child = pnode->first_child;
500 while (child != NULL) {
502 * The routine we call might modify the child, e.g. by
503 * freeing it, so we get the child's successor before
504 * calling that routine.
507 child = current->next;
508 if (proto_tree_traverse_pre_order((proto_tree *)current, func,
517 proto_tree_traverse_post_order(proto_tree *tree, proto_tree_traverse_func func,
520 proto_node *pnode = tree;
524 child = pnode->first_child;
525 while (child != NULL) {
527 * The routine we call might modify the child, e.g. by
528 * freeing it, so we get the child's successor before
529 * calling that routine.
532 child = current->next;
533 if (proto_tree_traverse_post_order((proto_tree *)current, func,
537 if (func(pnode, data))
544 proto_tree_children_foreach(proto_tree *tree, proto_tree_foreach_func func,
547 proto_node *node = tree;
550 node = node->first_child;
551 while (node != NULL) {
553 node = current->next;
554 func((proto_tree *)current, data);
558 /* frees the resources that the dissection a proto_tree uses */
560 proto_tree_free(proto_tree *tree)
562 proto_tree_traverse_post_order(tree, proto_tree_free_node, NULL);
566 free_GPtrArray_value(gpointer key, gpointer value, gpointer user_data _U_)
568 GPtrArray *ptrs = value;
569 gint hfid = (gint)(long)key;
570 header_field_info *hfinfo;
572 PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
573 if(hfinfo->ref_type != HF_REF_TYPE_NONE) {
574 /* when a field is referenced by a filter this also
575 affects the refcount for the parent protocol so we need
576 to adjust the refcount for the parent as well
578 if( hfinfo->parent != -1 ) {
579 header_field_info *parent_hfinfo;
580 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
581 parent_hfinfo->ref_type = HF_REF_TYPE_NONE;
583 hfinfo->ref_type = HF_REF_TYPE_NONE;
586 g_ptr_array_free(ptrs, TRUE);
590 free_node_tree_data(tree_data_t *tree_data)
592 if (tree_data->interesting_hfids) {
593 /* Free all the GPtrArray's in the interesting_hfids hash. */
594 g_hash_table_foreach(tree_data->interesting_hfids,
595 free_GPtrArray_value, NULL);
597 /* And then destroy the hash. */
598 g_hash_table_destroy(tree_data->interesting_hfids);
601 /* And finally the tree_data_t itself. */
605 #define FREE_NODE_FIELD_INFO(finfo) \
607 ITEM_LABEL_FREE(finfo->rep); \
609 FVALUE_CLEANUP(&finfo->value); \
610 FIELD_INFO_FREE(finfo);
613 proto_tree_free_node(proto_node *node, gpointer data _U_)
615 field_info *finfo = PNODE_FINFO(node);
617 proto_node *parent = node->parent;
621 /* This is the root node. Destroy the per-tree data.
622 * There is no field_info to destroy. */
623 if (PTREE_DATA(node)) free_node_tree_data(PTREE_DATA(node));
626 /* This is a child node. Don't free the per-tree data, but
627 * do free the field_info data. */
628 FREE_NODE_FIELD_INFO(finfo);
632 /* NOTE: This code is required when this function is used to free individual
633 * nodes only. Current use is for the destruction of complete trees, so the
634 * inconsistancies have no ill effect.
636 /* Remove node from parent */
638 proto_item *prev_item = NULL;
639 if (parent->first_child == node) {
640 parent->first_child = node->next;
642 /* find previous and change its next */
643 for (prev_item = parent->first_child; prev_item; prev_item = prev_item->next) {
644 if (prev_item->next == node) {
648 DISSECTOR_ASSERT(prev_item);
649 prev_item->next = node->next;
651 /* fix last_child if required */
652 if (parent->last_child == node) {
653 parent->last_child = prev_item;
656 DISSECTOR_ASSERT(node->first_child == NULL && node->last_child == NULL);
658 /* Free the proto_node. */
659 PROTO_NODE_FREE(node);
661 return FALSE; /* FALSE = do not end traversal of protocol tree */
664 /* Is the parsing being done for a visible proto_tree or an invisible one?
665 * By setting this correctly, the proto_tree creation is sped up by not
666 * having to call g_vsnprintf and copy strings around.
669 proto_tree_set_visible(proto_tree *tree, gboolean visible)
671 gboolean old_visible = PTREE_DATA(tree)->visible;
673 PTREE_DATA(tree)->visible = visible;
679 proto_tree_set_fake_protocols(proto_tree *tree, gboolean fake_protocols)
681 PTREE_DATA(tree)->fake_protocols = fake_protocols;
684 /* Assume dissector set only its protocol fields.
685 This function is called by dissectors and allows the speeding up of filtering
686 in wireshark; if this function returns FALSE it is safe to reset tree to NULL
687 and thus skip calling most of the expensive proto_tree_add_...()
689 If the tree is visible we implicitly assume the field is referenced.
692 proto_field_is_referenced(proto_tree *tree, int proto_id)
694 register header_field_info *hfinfo;
700 if (PTREE_DATA(tree)->visible)
703 PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
704 if (hfinfo->ref_type != HF_REF_TYPE_NONE)
707 if (hfinfo->type == FT_PROTOCOL && !PTREE_DATA(tree)->fake_protocols)
714 /* Finds a record in the hf_info_records array by id. */
716 proto_registrar_get_nth(guint hfindex)
718 register header_field_info *hfinfo;
720 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
725 /* Prefix initialization
726 * this allows for a dissector to register a display filter name prefix
727 * so that it can delay the initialization of the hf array as long as
731 /* compute a hash for the part before the dot of a display filter */
733 prefix_hash (gconstpointer key) {
734 /* end the string at the dot and compute its hash */
735 gchar* copy = ep_strdup(key);
745 return g_str_hash(copy);
748 /* are both strings equal up to the end or the dot? */
750 prefix_equal (gconstpointer ap,gconstpointer bp) {
758 if ((ac == '.' || ac == '\0') && (bc == '.' || bc == '\0')) return TRUE;
760 if ( (ac == '.' || ac == '\0') && ! (bc == '.' || bc == '\0') ) return FALSE;
761 if ( (bc == '.' || bc == '\0') && ! (ac == '.' || ac == '\0') ) return FALSE;
763 if (ac != bc) return FALSE;
770 /* indexed by prefix, contains initializers */
771 static GHashTable* prefixes = NULL;
774 /* Register a new prefix for "delayed" initialization of field arrays */
776 proto_register_prefix(const char *prefix, prefix_initializer_t pi ) {
778 prefixes = g_hash_table_new(prefix_hash,prefix_equal);
781 g_hash_table_insert(prefixes,(gpointer)prefix,pi);
784 /* helper to call all prefix initializers */
786 initialize_prefix(gpointer k, gpointer v, gpointer u _U_) {
787 ((prefix_initializer_t)v)(k);
791 /** Initialize every remaining uninitialized prefix. */
793 proto_initialize_all_prefixes(void) {
794 g_hash_table_foreach_remove(prefixes, initialize_prefix, NULL);
797 /* Finds a record in the hf_info_records array by name.
798 * If it fails to find it in the already registered fields,
799 * it tries to find and call an initializer in the prefixes
800 * table and if so it looks again.
803 proto_registrar_get_byname(const char *field_name)
805 header_field_info* hfinfo;
806 prefix_initializer_t pi;
811 hfinfo = g_tree_lookup(gpa_name_tree, field_name);
813 if (hfinfo) return hfinfo;
815 if (!prefixes) return NULL;
817 if(( pi = g_hash_table_lookup(prefixes,field_name) )) {
819 g_hash_table_remove(prefixes,field_name);
824 return g_tree_lookup(gpa_name_tree, field_name);
829 ptvcursor_new_subtree_levels(ptvcursor_t * ptvc)
831 subtree_lvl * pushed_tree;
833 DISSECTOR_ASSERT(ptvc->pushed_tree_max <= SUBTREE_MAX_LEVELS-SUBTREE_ONCE_ALLOCATION_NUMBER);
834 ptvc->pushed_tree_max += SUBTREE_ONCE_ALLOCATION_NUMBER;
836 pushed_tree = ep_alloc(sizeof(subtree_lvl) * ptvc->pushed_tree_max);
837 DISSECTOR_ASSERT(pushed_tree != NULL);
838 if (ptvc->pushed_tree)
839 memcpy(pushed_tree, ptvc->pushed_tree, ptvc->pushed_tree_max - SUBTREE_ONCE_ALLOCATION_NUMBER);
840 ptvc->pushed_tree = pushed_tree;
844 ptvcursor_free_subtree_levels(ptvcursor_t * ptvc)
846 ptvc->pushed_tree = NULL;
847 ptvc->pushed_tree_max = 0;
848 DISSECTOR_ASSERT(ptvc->pushed_tree_index ==0);
849 ptvc->pushed_tree_index = 0;
852 /* Allocates an initializes a ptvcursor_t with 3 variables:
853 * proto_tree, tvbuff, and offset. */
855 ptvcursor_new(proto_tree *tree, tvbuff_t *tvb, gint offset)
859 ptvc = ep_alloc(sizeof(ptvcursor_t));
862 ptvc->offset = offset;
863 ptvc->pushed_tree= NULL;
864 ptvc->pushed_tree_max= 0;
865 ptvc->pushed_tree_index= 0;
870 /* Frees memory for ptvcursor_t, but nothing deeper than that. */
872 ptvcursor_free(ptvcursor_t *ptvc)
874 ptvcursor_free_subtree_levels(ptvc);
878 /* Returns tvbuff. */
880 ptvcursor_tvbuff(ptvcursor_t* ptvc)
885 /* Returns current offset. */
887 ptvcursor_current_offset(ptvcursor_t* ptvc)
893 ptvcursor_tree(ptvcursor_t* ptvc)
902 ptvcursor_set_tree(ptvcursor_t* ptvc, proto_tree *tree)
907 /* creates a subtree, sets it as the working tree and pushes the old working tree */
909 ptvcursor_push_subtree(ptvcursor_t *ptvc, proto_item *it, gint ett_subtree)
911 subtree_lvl * subtree;
912 if (ptvc->pushed_tree_index >= ptvc->pushed_tree_max)
913 ptvcursor_new_subtree_levels(ptvc);
915 subtree = ptvc->pushed_tree+ptvc->pushed_tree_index;
916 subtree->tree = ptvc->tree;
918 ptvc->pushed_tree_index++;
919 return ptvcursor_set_subtree(ptvc, it, ett_subtree);
924 ptvcursor_pop_subtree(ptvcursor_t *ptvc)
926 subtree_lvl * subtree;
927 if (ptvc->pushed_tree_index <= 0)
930 ptvc->pushed_tree_index--;
931 subtree = ptvc->pushed_tree+ptvc->pushed_tree_index;
932 if (subtree->it != NULL)
933 proto_item_set_len(subtree->it, ptvcursor_current_offset(ptvc) - subtree->cursor_offset);
935 ptvc->tree = subtree->tree;
938 /* saves the current tvb offset and the item in the current subtree level */
940 ptvcursor_subtree_set_item(ptvcursor_t * ptvc, proto_item * it)
942 subtree_lvl * subtree;
944 DISSECTOR_ASSERT(ptvc->pushed_tree_index > 0);
946 subtree = ptvc->pushed_tree+ptvc->pushed_tree_index-1;
948 subtree->cursor_offset = ptvcursor_current_offset(ptvc);
951 /* Creates a subtree and adds it to the cursor as the working tree but does not
952 * save the old working tree */
954 ptvcursor_set_subtree(ptvcursor_t *ptvc, proto_item *it, gint ett_subtree)
956 ptvc->tree = proto_item_add_subtree(it, ett_subtree);
961 ptvcursor_add_subtree_item(ptvcursor_t * ptvc, proto_item * it, gint ett_subtree, gint length)
963 ptvcursor_push_subtree(ptvc, it, ett_subtree);
964 if (length == SUBTREE_UNDEFINED_LENGTH)
965 ptvcursor_subtree_set_item(ptvc, it);
966 return ptvcursor_tree(ptvc);
969 /* Add an item to the tree and create a subtree
970 * If the length is unknown, length may be defined as SUBTREE_UNDEFINED_LENGTH.
971 * In this case, when the subtree will be closed, the parent item length will
972 * be equal to the advancement of the cursor since the creation of the subtree.
975 ptvcursor_add_with_subtree(ptvcursor_t * ptvc, int hfindex, gint length,
976 const guint encoding, gint ett_subtree)
980 it = ptvcursor_add_no_advance(ptvc, hfindex, length, encoding);
981 return ptvcursor_add_subtree_item(ptvc, it, ett_subtree, length);
985 proto_tree_add_text_node(proto_tree *tree, tvbuff_t *tvb, gint start, gint length);
987 /* Add a text node to the tree and create a subtree
988 * If the length is unknown, length may be defined as SUBTREE_UNDEFINED_LENGTH.
989 * In this case, when the subtree will be closed, the item length will be equal
990 * to the advancement of the cursor since the creation of the subtree.
993 ptvcursor_add_text_with_subtree(ptvcursor_t * ptvc, gint length,
994 gint ett_subtree, const char *format, ...)
998 header_field_info *hfinfo;
1000 TRY_TO_FAKE_THIS_ITEM(ptvcursor_tree(ptvc), hf_text_only, hfinfo);
1002 it = proto_tree_add_text_node(ptvcursor_tree(ptvc), ptvcursor_tvbuff(ptvc),
1003 ptvcursor_current_offset(ptvc), length);
1008 va_start(ap, format);
1009 proto_tree_set_representation(it, format, ap);
1012 return ptvcursor_add_subtree_item(ptvc, it, ett_subtree, length);
1015 /* Add a text-only node, leaving it to our caller to fill the text in */
1017 proto_tree_add_text_node(proto_tree *tree, tvbuff_t *tvb, gint start, gint length)
1021 pi = proto_tree_add_pi(tree, hf_text_only, tvb, start, &length, NULL);
1028 /* Add a text-only node to the proto_tree */
1030 proto_tree_add_text(proto_tree *tree, tvbuff_t *tvb, gint start, gint length,
1031 const char *format, ...)
1035 header_field_info *hfinfo;
1037 TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
1039 pi = proto_tree_add_text_node(tree, tvb, start, length);
1043 TRY_TO_FAKE_THIS_REPR(tree, pi);
1045 va_start(ap, format);
1046 proto_tree_set_representation(pi, format, ap);
1052 /* Add a text-only node to the proto_tree (va_list version) */
1054 proto_tree_add_text_valist(proto_tree *tree, tvbuff_t *tvb, gint start,
1055 gint length, const char *format, va_list ap)
1058 header_field_info *hfinfo;
1060 TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
1062 pi = proto_tree_add_text_node(tree, tvb, start, length);
1066 TRY_TO_FAKE_THIS_REPR(tree, pi);
1068 proto_tree_set_representation(pi, format, ap);
1073 /* Add a text-only node for debugging purposes. The caller doesn't need
1074 * to worry about tvbuff, start, or length. Debug message gets sent to
1077 proto_tree_add_debug_text(proto_tree *tree, const char *format, ...)
1082 pi = proto_tree_add_text_node(tree, NULL, 0, 0);
1085 va_start(ap, format);
1086 proto_tree_set_representation(pi, format, ap);
1089 va_start(ap, format);
1090 vprintf(format, ap);
1098 * NOTE: to support code written when proto_tree_add_item() took a
1099 * gboolean as its last argument, with FALSE meaning "big-endian"
1100 * and TRUE meaning "little-endian", we treat any non-zero value of
1101 * "encoding" as meaning "little-endian".
1104 get_uint_value(tvbuff_t *tvb, gint offset, gint length, const guint encoding)
1111 value = tvb_get_guint8(tvb, offset);
1115 value = encoding ? tvb_get_letohs(tvb, offset)
1116 : tvb_get_ntohs(tvb, offset);
1120 value = encoding ? tvb_get_letoh24(tvb, offset)
1121 : tvb_get_ntoh24(tvb, offset);
1125 value = encoding ? tvb_get_letohl(tvb, offset)
1126 : tvb_get_ntohl(tvb, offset);
1130 DISSECTOR_ASSERT_NOT_REACHED();
1138 * NOTE: to support code written when proto_tree_add_item() took a
1139 * gboolean as its last argument, with FALSE meaning "big-endian"
1140 * and TRUE meaning "little-endian", we treat any non-zero value of
1141 * "encoding" as meaning "little-endian".
1144 get_int_value(tvbuff_t *tvb, gint offset, gint length, const guint encoding)
1151 value = (gint8)tvb_get_guint8(tvb, offset);
1155 value = (gint16) (encoding ? tvb_get_letohs(tvb, offset)
1156 : tvb_get_ntohs(tvb, offset));
1160 value = encoding ? tvb_get_letoh24(tvb, offset)
1161 : tvb_get_ntoh24(tvb, offset);
1162 if (value & 0x00800000) {
1163 /* Sign bit is set; sign-extend it. */
1164 value |= 0xFF000000;
1169 value = encoding ? tvb_get_letohl(tvb, offset)
1170 : tvb_get_ntohl(tvb, offset);
1174 DISSECTOR_ASSERT_NOT_REACHED();
1182 proto_lookup_or_create_interesting_hfids(proto_tree *tree,
1183 header_field_info *hfinfo)
1185 GPtrArray *ptrs = NULL;
1187 DISSECTOR_ASSERT(tree);
1188 DISSECTOR_ASSERT(hfinfo);
1190 if (hfinfo->ref_type == HF_REF_TYPE_DIRECT) {
1191 if (PTREE_DATA(tree)->interesting_hfids == NULL) {
1192 /* Initialize the hash because we now know that it is needed */
1193 PTREE_DATA(tree)->interesting_hfids =
1194 g_hash_table_new(g_direct_hash, NULL /* g_direct_equal */);
1197 ptrs = g_hash_table_lookup(PTREE_DATA(tree)->interesting_hfids,
1198 GINT_TO_POINTER(hfinfo->id));
1200 /* First element triggers the creation of pointer array */
1201 ptrs = g_ptr_array_new();
1202 g_hash_table_insert(PTREE_DATA(tree)->interesting_hfids,
1203 GINT_TO_POINTER(hfinfo->id), ptrs);
1210 /* Add an item to a proto_tree, using the text label registered to that item;
1211 the item is extracted from the tvbuff handed to it. */
1213 proto_tree_new_item(field_info *new_fi, proto_tree *tree,
1214 tvbuff_t *tvb, gint start, gint length,
1215 const guint encoding_arg)
1217 guint encoding = encoding_arg;
1223 nstime_t time_stamp;
1226 /* there is a possibility here that we might raise an exception
1227 * and thus would lose track of the field_info.
1228 * store it in a temp so that if we come here again we can reclaim
1229 * the field_info without leaking memory.
1231 /* XXX this only keeps track of one field_info struct,
1232 if we ever go multithreaded for calls to this function
1233 we have to change this code to use per thread variable.
1236 /* oops, last one we got must have been lost due
1238 * good thing we saved it, now we can reverse the
1239 * memory leak and reclaim it.
1241 SLAB_FREE(field_info_tmp, field_info);
1243 /* we might throw an exception, keep track of this one
1244 * across the "dangerous" section below.
1246 field_info_tmp=new_fi;
1248 switch(new_fi->hfinfo->type) {
1250 /* no value to set for FT_NONE */
1254 proto_tree_set_protocol_tvb(new_fi, tvb);
1258 proto_tree_set_bytes_tvb(new_fi, tvb, start, length);
1263 * Map all non-zero values to little-endian for
1264 * backwards compatibility.
1267 encoding = ENC_LITTLE_ENDIAN;
1268 n = get_uint_value(tvb, start, length, encoding);
1269 proto_tree_set_bytes_tvb(new_fi, tvb, start + length, n);
1271 /* Instead of calling proto_item_set_len(), since we don't yet
1272 * have a proto_item, we set the field_info's length ourselves. */
1273 new_fi->length = n + length;
1278 * Map all non-zero values to little-endian for
1279 * backwards compatibility.
1282 encoding = ENC_LITTLE_ENDIAN;
1283 proto_tree_set_boolean(new_fi,
1284 get_uint_value(tvb, start, length, encoding));
1287 /* XXX - make these just FT_UINT? */
1293 * Map all non-zero values to little-endian for
1294 * backwards compatibility.
1297 encoding = ENC_LITTLE_ENDIAN;
1298 proto_tree_set_uint(new_fi,
1299 get_uint_value(tvb, start, length, encoding));
1305 * Map all non-zero values to little-endian for
1306 * backwards compatibility.
1309 encoding = ENC_LITTLE_ENDIAN;
1310 DISSECTOR_ASSERT( length <= 8 && length >= 1);
1311 proto_tree_set_uint64_tvb(new_fi, tvb, start, length, encoding);
1314 /* XXX - make these just FT_INT? */
1320 * Map all non-zero values to little-endian for
1321 * backwards compatibility.
1324 encoding = ENC_LITTLE_ENDIAN;
1325 proto_tree_set_int(new_fi,
1326 get_int_value(tvb, start, length, encoding));
1331 * Map all non-zero values to little-endian for
1332 * backwards compatibility.
1335 encoding = ENC_LITTLE_ENDIAN;
1336 DISSECTOR_ASSERT(length == FT_IPv4_LEN);
1337 value = tvb_get_ipv4(tvb, start);
1339 * NOTE: to support code written when
1340 * proto_tree_add_item() took a gboolean as its
1341 * last argument, with FALSE meaning "big-endian"
1342 * and TRUE meaning "little-endian", we treat any
1343 * non-zero value of "encoding" as meaning
1346 proto_tree_set_ipv4(new_fi, encoding ? GUINT32_SWAP_LE_BE(value) : value);
1350 DISSECTOR_ASSERT(length == FT_IPXNET_LEN);
1351 proto_tree_set_ipxnet(new_fi,
1352 get_uint_value(tvb, start, 4, FALSE));
1356 DISSECTOR_ASSERT(length >=0 && length <= FT_IPv6_LEN);
1357 proto_tree_set_ipv6_tvb(new_fi, tvb, start, length);
1361 DISSECTOR_ASSERT(length == FT_ETHER_LEN);
1362 proto_tree_set_ether_tvb(new_fi, tvb, start);
1367 * Map all non-zero values to little-endian for
1368 * backwards compatibility.
1371 encoding = ENC_LITTLE_ENDIAN;
1372 DISSECTOR_ASSERT(length == FT_GUID_LEN);
1373 proto_tree_set_guid_tvb(new_fi, tvb, start, encoding);
1377 proto_tree_set_oid_tvb(new_fi, tvb, start, length);
1382 * NOTE: to support code written when
1383 * proto_tree_add_item() took a gboolean as its
1384 * last argument, with FALSE meaning "big-endian"
1385 * and TRUE meaning "little-endian", we treat any
1386 * non-zero value of "encoding" as meaning
1389 * At some point in the future, we might
1390 * support non-IEEE-binary floating-point
1391 * formats in the encoding as well
1392 * (IEEE decimal, System/3x0, VAX).
1395 encoding = ENC_LITTLE_ENDIAN;
1396 DISSECTOR_ASSERT(length == 4);
1398 floatval = tvb_get_letohieee_float(tvb, start);
1400 floatval = tvb_get_ntohieee_float(tvb, start);
1401 proto_tree_set_float(new_fi, floatval);
1406 * NOTE: to support code written when
1407 * proto_tree_add_item() took a gboolean as its
1408 * last argument, with FALSE meaning "big-endian"
1409 * and TRUE meaning "little-endian", we treat any
1410 * non-zero value of "encoding" as meaning
1413 * At some point in the future, we might
1414 * support non-IEEE-binary floating-point
1415 * formats in the encoding as well
1416 * (IEEE decimal, System/3x0, VAX).
1418 if (encoding == TRUE)
1419 encoding = ENC_LITTLE_ENDIAN;
1420 DISSECTOR_ASSERT(length == 8);
1422 doubleval = tvb_get_letohieee_double(tvb, start);
1424 doubleval = tvb_get_ntohieee_double(tvb, start);
1425 proto_tree_set_double(new_fi, doubleval);
1429 proto_tree_set_string_tvb(new_fi, tvb, start, length);
1433 DISSECTOR_ASSERT(length >= -1);
1434 /* Instead of calling proto_item_set_len(),
1435 * since we don't yet have a proto_item, we
1436 * set the field_info's length ourselves.
1438 * XXX - our caller can't use that length to
1439 * advance an offset unless they arrange that
1440 * there always be a protocol tree into which
1441 * we're putting this item.
1444 /* This can throw an exception */
1445 length = tvb_strsize(tvb, start);
1447 string = ep_alloc(length);
1449 tvb_memcpy(tvb, string, start, length);
1450 } else if (length == 0) {
1453 /* In this case, length signifies
1454 * the length of the string.
1456 * This could either be a null-padded
1457 * string, which doesn't necessarily
1458 * have a '\0' at the end, or a
1459 * null-terminated string, with a
1460 * trailing '\0'. (Yes, there are
1461 * cases where you have a string
1462 * that's both counted and null-
1465 * In the first case, we must
1466 * allocate a buffer of length
1467 * "length+1", to make room for
1470 * In the second case, we don't
1471 * assume that there is a trailing
1472 * '\0' there, as the packet might
1473 * be malformed. (XXX - should we
1474 * throw an exception if there's no
1475 * trailing '\0'?) Therefore, we
1476 * allocate a buffer of length
1477 * "length+1", and put in a trailing
1478 * '\0', just to be safe.
1480 * (XXX - this would change if
1481 * we made string values counted
1482 * rather than null-terminated.)
1484 string = tvb_get_ephemeral_string(tvb, start, length);
1486 new_fi->length = length;
1487 proto_tree_set_string(new_fi, string);
1491 proto_tree_set_ebcdic_string_tvb(new_fi, tvb, start, length);
1494 case FT_UINT_STRING:
1496 * NOTE: to support code written when
1497 * proto_tree_add_item() took a gboolean as its
1498 * last argument, with FALSE meaning "big-endian"
1499 * and TRUE meaning "little-endian", we treat any
1500 * non-zero value of "encoding" as meaning
1503 * At some point in the future, we might
1504 * support character encodings in the
1505 * encoding value as well.
1508 encoding = ENC_LITTLE_ENDIAN;
1509 n = get_uint_value(tvb, start, length, encoding);
1510 proto_tree_set_string_tvb(new_fi, tvb, start + length, n);
1512 /* Instead of calling proto_item_set_len(), since we
1513 * don't yet have a proto_item, we set the
1514 * field_info's length ourselves.
1516 * XXX - our caller can't use that length to
1517 * advance an offset unless they arrange that
1518 * there always be a protocol tree into which
1519 * we're putting this item.
1521 new_fi->length = n + length;
1524 case FT_ABSOLUTE_TIME:
1526 * Absolute times can be in any of a number of
1527 * formats, and they can be big-endian or
1530 * Historically FT_TIMEs were only timespecs;
1531 * the only question was whether they were stored
1532 * in big- or little-endian format.
1534 * For backwards compatibility, we interpret an
1535 * encoding of 1 as meaning "little-endian timespec",
1536 * so that passing TRUE is interpreted as that.
1538 if (encoding == TRUE)
1539 encoding = ENC_TIME_TIMESPEC|ENC_LITTLE_ENDIAN;
1543 case ENC_TIME_TIMESPEC|ENC_BIG_ENDIAN:
1545 * 4-byte UNIX epoch, possibly followed by
1546 * 4-byte fractional time in nanoseconds,
1549 DISSECTOR_ASSERT(length == 8 || length == 4);
1550 time_stamp.secs = tvb_get_ntohl(tvb, start);
1552 time_stamp.nsecs = tvb_get_ntohl(tvb, start+4);
1554 time_stamp.nsecs = 0;
1557 case ENC_TIME_TIMESPEC|ENC_LITTLE_ENDIAN:
1559 * 4-byte UNIX epoch, possibly followed by
1560 * 4-byte fractional time in nanoseconds,
1561 * both little-endian.
1563 DISSECTOR_ASSERT(length == 8 || length == 4);
1564 time_stamp.secs = tvb_get_letohl(tvb, start);
1566 time_stamp.nsecs = tvb_get_letohl(tvb, start+4);
1568 time_stamp.nsecs = 0;
1571 case ENC_TIME_NTP|ENC_BIG_ENDIAN:
1573 * NTP time stamp, big-endian.
1575 DISSECTOR_ASSERT(length == 8 || length == 4);
1577 /* XXX - where should this go? */
1578 #define NTP_BASETIME 2208988800ul
1579 time_stamp.secs = tvb_get_ntohl(tvb, start);
1580 if (time_stamp.secs)
1581 time_stamp.secs -= NTP_BASETIME;
1585 * We're using nanoseconds here (and we will
1586 * display nanoseconds), but NTP's timestamps
1587 * have a precision in microseconds or greater.
1588 * Round to 1 microsecond.
1590 time_stamp.nsecs = (int)(1000000*(tvb_get_ntohl(tvb, start+4)/4294967296.0));
1591 time_stamp.nsecs *= 1000;
1593 time_stamp.nsecs = 0;
1597 case ENC_TIME_NTP|ENC_LITTLE_ENDIAN:
1599 * NTP time stamp, big-endian.
1601 DISSECTOR_ASSERT(length == 8 || length == 4);
1602 time_stamp.secs = tvb_get_letohl(tvb, start);
1603 if (time_stamp.secs)
1604 time_stamp.secs -= NTP_BASETIME;
1608 * We're using nanoseconds here (and we will
1609 * display nanoseconds), but NTP's timestamps
1610 * have a precision in microseconds or greater.
1611 * Round to 1 microsecond.
1613 time_stamp.nsecs = (int)(1000000*(tvb_get_letohl(tvb, start+4)/4294967296.0));
1614 time_stamp.nsecs *= 1000;
1616 time_stamp.nsecs = 0;
1621 DISSECTOR_ASSERT_NOT_REACHED();
1622 time_stamp.secs = 0;
1623 time_stamp.nsecs = 0;
1626 proto_tree_set_time(new_fi, &time_stamp);
1629 case FT_RELATIVE_TIME:
1631 * Relative times can be in any of a number of
1632 * formats, and they can be big-endian or
1635 * Historically FT_TIMEs were only timespecs;
1636 * the only question was whether they were stored
1637 * in big- or little-endian format.
1639 * For backwards compatibility, we interpret an
1640 * encoding of 1 as meaning "little-endian timespec",
1641 * so that passing TRUE is interpreted as that.
1643 if (encoding == TRUE)
1644 encoding = ENC_TIME_TIMESPEC|ENC_LITTLE_ENDIAN;
1647 case ENC_TIME_TIMESPEC|ENC_BIG_ENDIAN:
1649 * 4-byte UNIX epoch, possibly followed by
1650 * 4-byte fractional time in nanoseconds,
1653 DISSECTOR_ASSERT(length == 8 || length == 4);
1654 time_stamp.secs = tvb_get_ntohl(tvb, start);
1656 time_stamp.nsecs = tvb_get_ntohl(tvb, start+4);
1658 time_stamp.nsecs = 0;
1661 case ENC_TIME_TIMESPEC|ENC_LITTLE_ENDIAN:
1663 * 4-byte UNIX epoch, possibly followed by
1664 * 4-byte fractional time in nanoseconds,
1665 * both little-endian.
1667 DISSECTOR_ASSERT(length == 8 || length == 4);
1668 time_stamp.secs = tvb_get_letohl(tvb, start);
1670 time_stamp.nsecs = tvb_get_letohl(tvb, start+4);
1672 time_stamp.nsecs = 0;
1675 proto_tree_set_time(new_fi, &time_stamp);
1679 g_error("new_fi->hfinfo->type %d (%s) not handled\n",
1680 new_fi->hfinfo->type,
1681 ftype_name(new_fi->hfinfo->type));
1682 DISSECTOR_ASSERT_NOT_REACHED();
1685 FI_SET_FLAG(new_fi, (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN);
1687 /* Don't add new node to proto_tree until now so that any exceptions
1688 * raised by a tvbuff access method doesn't leave junk in the proto_tree. */
1689 pi = proto_tree_add_node(tree, new_fi);
1691 /* we did not raise an exception so we dont have to remember this
1692 * field_info struct any more.
1694 field_info_tmp=NULL;
1696 /* If the proto_tree wants to keep a record of this finfo
1697 * for quick lookup, then record it. */
1698 ptrs = proto_lookup_or_create_interesting_hfids(tree, new_fi->hfinfo);
1700 g_ptr_array_add(ptrs, new_fi);
1705 /* Gets data from tvbuff, adds it to proto_tree, increments offset,
1706 and returns proto_item* */
1708 ptvcursor_add(ptvcursor_t *ptvc, int hfindex, gint length,
1709 const guint encoding)
1712 header_field_info *hfinfo;
1717 /* We can't fake it just yet. We have to advance the cursor
1718 TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfindex, hfinfo); */
1720 offset = ptvc->offset;
1721 hfinfo = get_hfi_and_length(hfindex, ptvc->tvb, offset, &length,
1723 ptvc->offset += length;
1724 if (hfinfo->type == FT_UINT_BYTES || hfinfo->type == FT_UINT_STRING) {
1726 * The length of the rest of the item is in the first N
1727 * bytes of the item.
1729 n = get_uint_value(ptvc->tvb, offset, length, encoding);
1733 /* Coast clear. Try and fake it */
1734 TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfindex, hfinfo);
1736 new_fi = new_field_info(ptvc->tree, hfinfo, ptvc->tvb, offset, item_length);
1740 return proto_tree_new_item(new_fi, ptvc->tree, ptvc->tvb,
1741 offset, length, encoding);
1744 /* Add an item to a proto_tree, using the text label registered to that item;
1745 the item is extracted from the tvbuff handed to it. */
1747 proto_tree_add_item(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
1748 const gint start, gint length, const guint encoding)
1751 header_field_info *hfinfo;
1753 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1755 new_fi = alloc_field_info(tree, hfindex, tvb, start, &length);
1760 return proto_tree_new_item(new_fi, tree, tvb, start,
1764 /* Add a FT_NONE to a proto_tree */
1766 proto_tree_add_none_format(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
1767 const gint start, gint length, const char *format,
1772 header_field_info *hfinfo;
1774 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1776 DISSECTOR_ASSERT(hfinfo->type == FT_NONE);
1778 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, NULL);
1780 TRY_TO_FAKE_THIS_REPR(tree, pi);
1782 va_start(ap, format);
1783 proto_tree_set_representation(pi, format, ap);
1786 /* no value to set for FT_NONE */
1790 /* Gets data from tvbuff, adds it to proto_tree, *DOES NOT* increment
1791 * offset, and returns proto_item* */
1793 ptvcursor_add_no_advance(ptvcursor_t* ptvc, int hf, gint length,
1794 const guint encoding)
1798 item = proto_tree_add_item(ptvc->tree, hf, ptvc->tvb, ptvc->offset,
1804 /* Advance the ptvcursor's offset within its tvbuff without
1805 * adding anything to the proto_tree. */
1807 ptvcursor_advance(ptvcursor_t* ptvc, gint length)
1809 ptvc->offset += length;
1814 proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb)
1816 fvalue_set(&fi->value, tvb, TRUE);
1819 /* Add a FT_PROTOCOL to a proto_tree */
1821 proto_tree_add_protocol_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1822 gint start, gint length, const char *format, ...)
1827 header_field_info *hfinfo;
1829 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1831 DISSECTOR_ASSERT(hfinfo->type == FT_PROTOCOL);
1833 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1835 proto_tree_set_protocol_tvb(new_fi, (start == 0 ? tvb : tvb_new_subset(tvb, start, length, length)));
1837 TRY_TO_FAKE_THIS_REPR(tree, pi);
1839 va_start(ap, format);
1840 proto_tree_set_representation(pi, format, ap);
1847 /* Add a FT_BYTES to a proto_tree */
1849 proto_tree_add_bytes(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1850 gint length, const guint8 *start_ptr)
1854 header_field_info *hfinfo;
1856 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1858 DISSECTOR_ASSERT(hfinfo->type == FT_BYTES);
1860 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1861 proto_tree_set_bytes(new_fi, start_ptr, length);
1867 proto_tree_add_bytes_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1868 gint start, gint length,
1869 const guint8 *start_ptr,
1870 const char *format, ...)
1874 header_field_info *hfinfo;
1876 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1879 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length,
1882 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length,
1883 tvb_get_ptr(tvb, start, length));
1888 TRY_TO_FAKE_THIS_REPR(tree, pi);
1890 va_start(ap, format);
1891 proto_tree_set_representation_value(pi, format, ap);
1898 proto_tree_add_bytes_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1899 gint start, gint length, const guint8 *start_ptr,
1900 const char *format, ...)
1904 header_field_info *hfinfo;
1906 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1909 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length,
1912 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length,
1913 tvb_get_ptr(tvb, start, length));
1918 TRY_TO_FAKE_THIS_REPR(tree, pi);
1920 va_start(ap, format);
1921 proto_tree_set_representation(pi, format, ap);
1928 proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length)
1932 bytes = g_byte_array_new();
1934 g_byte_array_append(bytes, start_ptr, length);
1936 fvalue_set(&fi->value, bytes, TRUE);
1941 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length)
1943 proto_tree_set_bytes(fi, tvb_get_ptr(tvb, offset, length), length);
1946 /* Add a FT_*TIME to a proto_tree */
1948 proto_tree_add_time(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1949 gint length, nstime_t *value_ptr)
1953 header_field_info *hfinfo;
1955 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1957 DISSECTOR_ASSERT(hfinfo->type == FT_ABSOLUTE_TIME ||
1958 hfinfo->type == FT_RELATIVE_TIME);
1960 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1961 proto_tree_set_time(new_fi, value_ptr);
1967 proto_tree_add_time_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1968 gint start, gint length, nstime_t *value_ptr,
1969 const char *format, ...)
1973 header_field_info *hfinfo;
1975 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1977 pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
1981 TRY_TO_FAKE_THIS_REPR(tree, pi);
1983 va_start(ap, format);
1984 proto_tree_set_representation_value(pi, format, ap);
1991 proto_tree_add_time_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1992 gint start, gint length, nstime_t *value_ptr,
1993 const char *format, ...)
1997 header_field_info *hfinfo;
1999 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2001 pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
2005 TRY_TO_FAKE_THIS_REPR(tree, pi);
2007 va_start(ap, format);
2008 proto_tree_set_representation(pi, format, ap);
2014 /* Set the FT_*TIME value */
2016 proto_tree_set_time(field_info *fi, nstime_t *value_ptr)
2018 DISSECTOR_ASSERT(value_ptr != NULL);
2020 fvalue_set(&fi->value, value_ptr, FALSE);
2023 /* Add a FT_IPXNET to a proto_tree */
2025 proto_tree_add_ipxnet(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2026 gint length, guint32 value)
2030 header_field_info *hfinfo;
2032 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2034 DISSECTOR_ASSERT(hfinfo->type == FT_IPXNET);
2036 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2037 proto_tree_set_ipxnet(new_fi, value);
2043 proto_tree_add_ipxnet_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2044 gint start, gint length, guint32 value,
2045 const char *format, ...)
2049 header_field_info *hfinfo;
2051 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2053 pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
2057 TRY_TO_FAKE_THIS_REPR(tree, pi);
2059 va_start(ap, format);
2060 proto_tree_set_representation_value(pi, format, ap);
2067 proto_tree_add_ipxnet_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2068 gint start, gint length, guint32 value,
2069 const char *format, ...)
2073 header_field_info *hfinfo;
2075 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2077 pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
2081 TRY_TO_FAKE_THIS_REPR(tree, pi);
2083 va_start(ap, format);
2084 proto_tree_set_representation(pi, format, ap);
2090 /* Set the FT_IPXNET value */
2092 proto_tree_set_ipxnet(field_info *fi, guint32 value)
2094 fvalue_set_uinteger(&fi->value, value);
2097 /* Add a FT_IPv4 to a proto_tree */
2099 proto_tree_add_ipv4(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2100 gint length, guint32 value)
2104 header_field_info *hfinfo;
2106 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2108 DISSECTOR_ASSERT(hfinfo->type == FT_IPv4);
2110 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2111 proto_tree_set_ipv4(new_fi, value);
2117 proto_tree_add_ipv4_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2118 gint start, gint length, guint32 value,
2119 const char *format, ...)
2123 header_field_info *hfinfo;
2125 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2127 pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
2131 TRY_TO_FAKE_THIS_REPR(tree, pi);
2133 va_start(ap, format);
2134 proto_tree_set_representation_value(pi, format, ap);
2141 proto_tree_add_ipv4_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2142 gint start, gint length, guint32 value,
2143 const char *format, ...)
2147 header_field_info *hfinfo;
2149 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2151 pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
2155 TRY_TO_FAKE_THIS_REPR(tree, pi);
2157 va_start(ap, format);
2158 proto_tree_set_representation(pi, format, ap);
2164 /* Set the FT_IPv4 value */
2166 proto_tree_set_ipv4(field_info *fi, guint32 value)
2168 fvalue_set_uinteger(&fi->value, value);
2171 /* Add a FT_IPv6 to a proto_tree */
2173 proto_tree_add_ipv6(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2174 gint length, const guint8* value_ptr)
2178 header_field_info *hfinfo;
2180 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2182 DISSECTOR_ASSERT(hfinfo->type == FT_IPv6);
2184 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2185 proto_tree_set_ipv6(new_fi, value_ptr);
2191 proto_tree_add_ipv6_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2192 gint start, gint length,
2193 const guint8* value_ptr,
2194 const char *format, ...)
2198 header_field_info *hfinfo;
2200 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2202 pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
2206 TRY_TO_FAKE_THIS_REPR(tree, pi);
2208 va_start(ap, format);
2209 proto_tree_set_representation_value(pi, format, ap);
2216 proto_tree_add_ipv6_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2217 gint start, gint length, const guint8* value_ptr,
2218 const char *format, ...)
2222 header_field_info *hfinfo;
2224 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2226 pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
2230 TRY_TO_FAKE_THIS_REPR(tree, pi);
2232 va_start(ap, format);
2233 proto_tree_set_representation(pi, format, ap);
2239 /* Set the FT_IPv6 value */
2241 proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr)
2243 DISSECTOR_ASSERT(value_ptr != NULL);
2244 fvalue_set(&fi->value, (gpointer) value_ptr, FALSE);
2248 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
2250 proto_tree_set_ipv6(fi, tvb_get_ptr(tvb, start, length));
2253 /* Add a FT_GUID to a proto_tree */
2255 proto_tree_add_guid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2256 gint length, const e_guid_t *value_ptr)
2260 header_field_info *hfinfo;
2262 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2264 DISSECTOR_ASSERT(hfinfo->type == FT_GUID);
2266 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2267 proto_tree_set_guid(new_fi, value_ptr);
2273 proto_tree_add_guid_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2274 gint start, gint length,
2275 const e_guid_t *value_ptr,
2276 const char *format, ...)
2280 header_field_info *hfinfo;
2282 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2284 pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
2288 TRY_TO_FAKE_THIS_REPR(tree, pi);
2290 va_start(ap, format);
2291 proto_tree_set_representation_value(pi, format, ap);
2298 proto_tree_add_guid_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2299 gint start, gint length, const e_guid_t *value_ptr,
2300 const char *format, ...)
2304 header_field_info *hfinfo;
2306 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2308 pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
2312 TRY_TO_FAKE_THIS_REPR(tree, pi);
2314 va_start(ap, format);
2315 proto_tree_set_representation(pi, format, ap);
2321 /* Set the FT_GUID value */
2323 proto_tree_set_guid(field_info *fi, const e_guid_t *value_ptr)
2325 DISSECTOR_ASSERT(value_ptr != NULL);
2326 fvalue_set(&fi->value, (gpointer) value_ptr, FALSE);
2330 proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, gint start,
2331 const guint encoding)
2335 tvb_get_guid(tvb, start, &guid, encoding);
2336 proto_tree_set_guid(fi, &guid);
2339 /* Add a FT_OID to a proto_tree */
2341 proto_tree_add_oid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2342 gint length, const guint8* value_ptr)
2346 header_field_info *hfinfo;
2348 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2350 DISSECTOR_ASSERT(hfinfo->type == FT_OID);
2352 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2353 proto_tree_set_oid(new_fi, value_ptr, length);
2359 proto_tree_add_oid_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2360 gint start, gint length,
2361 const guint8* value_ptr,
2362 const char *format, ...)
2366 header_field_info *hfinfo;
2368 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2370 pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
2374 TRY_TO_FAKE_THIS_REPR(tree, pi);
2376 va_start(ap, format);
2377 proto_tree_set_representation_value(pi, format, ap);
2384 proto_tree_add_oid_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2385 gint start, gint length, const guint8* value_ptr,
2386 const char *format, ...)
2390 header_field_info *hfinfo;
2392 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2394 pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
2398 TRY_TO_FAKE_THIS_REPR(tree, pi);
2400 va_start(ap, format);
2401 proto_tree_set_representation(pi, format, ap);
2407 /* Set the FT_OID value */
2409 proto_tree_set_oid(field_info *fi, const guint8* value_ptr, gint length)
2413 DISSECTOR_ASSERT(value_ptr != NULL);
2415 bytes = g_byte_array_new();
2417 g_byte_array_append(bytes, value_ptr, length);
2419 fvalue_set(&fi->value, bytes, TRUE);
2423 proto_tree_set_oid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
2425 proto_tree_set_oid(fi, tvb_get_ptr(tvb, start, length), length);
2429 proto_tree_set_uint64(field_info *fi, guint64 value)
2431 fvalue_set_integer64(&fi->value, value);
2435 * NOTE: to support code written when proto_tree_add_item() took a
2436 * gboolean as its last argument, with FALSE meaning "big-endian"
2437 * and TRUE meaning "little-endian", we treat any non-zero value of
2438 * "encoding" as meaning "little-endian".
2441 proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start,
2442 guint length, const guint encoding)
2445 guint8* b = ep_tvb_memdup(tvb,start,length);
2450 default: DISSECTOR_ASSERT_NOT_REACHED();
2451 case 8: value <<= 8; value += *--b;
2452 case 7: value <<= 8; value += *--b;
2453 case 6: value <<= 8; value += *--b;
2454 case 5: value <<= 8; value += *--b;
2455 case 4: value <<= 8; value += *--b;
2456 case 3: value <<= 8; value += *--b;
2457 case 2: value <<= 8; value += *--b;
2458 case 1: value <<= 8; value += *--b;
2463 default: DISSECTOR_ASSERT_NOT_REACHED();
2464 case 8: value <<= 8; value += *b++;
2465 case 7: value <<= 8; value += *b++;
2466 case 6: value <<= 8; value += *b++;
2467 case 5: value <<= 8; value += *b++;
2468 case 4: value <<= 8; value += *b++;
2469 case 3: value <<= 8; value += *b++;
2470 case 2: value <<= 8; value += *b++;
2471 case 1: value <<= 8; value += *b++;
2476 proto_tree_set_uint64(fi, value);
2479 /* Add a FT_STRING or FT_STRINGZ to a proto_tree. Creates own copy of string,
2480 * and frees it when the proto_tree is destroyed. */
2482 proto_tree_add_string(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2483 gint length, const char* value)
2487 header_field_info *hfinfo;
2489 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2491 DISSECTOR_ASSERT(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ);
2493 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2494 DISSECTOR_ASSERT(length >= 0);
2495 proto_tree_set_string(new_fi, value);
2501 proto_tree_add_string_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2502 gint start, gint length, const char* value,
2508 header_field_info *hfinfo;
2510 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2512 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
2516 TRY_TO_FAKE_THIS_REPR(tree, pi);
2518 va_start(ap, format);
2519 proto_tree_set_representation_value(pi, format, ap);
2526 proto_tree_add_string_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2527 gint start, gint length, const char* value,
2528 const char *format, ...)
2532 header_field_info *hfinfo;
2534 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2536 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
2540 TRY_TO_FAKE_THIS_REPR(tree, pi);
2542 va_start(ap, format);
2543 proto_tree_set_representation(pi, format, ap);
2549 /* Appends string data to a FT_STRING or FT_STRINGZ, allowing progressive
2550 * field info update instead of only updating the representation as does
2551 * proto_item_append_text()
2553 /* NOTE: this function will break with the TRY_TO_FAKE_THIS_ITEM()
2554 * speed optimization.
2555 * Currently only WSP use this function so it is not that bad but try to
2556 * avoid using this one if possible.
2557 * IF you must use this function you MUST also disable the
2558 * TRY_TO_FAKE_THIS_ITEM() optimization for your dissector/function
2559 * using proto_item_append_string().
2560 * Do that by faking that the tree is visible by calling
2561 * proto_tree_set_visible(tree, TRUE) (see packet-wsp.c)
2562 * BEFORE you create the item you are later going to use
2563 * proto_item_append_string() on.
2566 proto_item_append_string(proto_item *pi, const char *str)
2569 header_field_info *hfinfo;
2570 gchar *old_str, *new_str;
2577 fi = PITEM_FINFO(pi);
2578 DISSECTOR_ASSERT(fi && "proto_tree_set_visible(tree, TRUE) should have been called previously");
2580 hfinfo = fi->hfinfo;
2581 if (hfinfo->type == FT_PROTOCOL) {
2582 /* TRY_TO_FAKE_THIS_ITEM() speed optimization: silently skip */
2585 DISSECTOR_ASSERT(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ);
2586 old_str = fvalue_get(&fi->value);
2587 new_str = ep_strdup_printf("%s%s", old_str, str);
2588 fvalue_set(&fi->value, new_str, FALSE);
2591 /* Set the FT_STRING value */
2593 proto_tree_set_string(field_info *fi, const char* value)
2596 fvalue_set(&fi->value, (gpointer) value, FALSE);
2598 fvalue_set(&fi->value, (gpointer) "[ Null ]", FALSE);
2603 proto_tree_set_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
2608 length = tvb_ensure_length_remaining(tvb, start);
2611 string = tvb_get_ephemeral_string(tvb, start, length);
2612 proto_tree_set_string(fi, string);
2616 proto_tree_set_ebcdic_string_tvb(field_info *fi, tvbuff_t *tvb, gint start,
2622 length = tvb_ensure_length_remaining(tvb, start);
2625 string = tvb_get_ephemeral_string(tvb, start, length);
2626 EBCDIC_to_ASCII(string, length);
2627 proto_tree_set_string(fi, string);
2630 /* Add a FT_ETHER to a proto_tree */
2632 proto_tree_add_ether(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2633 gint length, const guint8* value)
2637 header_field_info *hfinfo;
2639 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2641 DISSECTOR_ASSERT(hfinfo->type == FT_ETHER);
2643 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2644 proto_tree_set_ether(new_fi, value);
2650 proto_tree_add_ether_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2651 gint start, gint length, const guint8* value,
2652 const char *format, ...)
2656 header_field_info *hfinfo;
2658 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2660 pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
2664 TRY_TO_FAKE_THIS_REPR(tree, pi);
2666 va_start(ap, format);
2667 proto_tree_set_representation_value(pi, format, ap);
2674 proto_tree_add_ether_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2675 gint start, gint length, const guint8* value,
2676 const char *format, ...)
2680 header_field_info *hfinfo;
2682 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2684 pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
2688 TRY_TO_FAKE_THIS_REPR(tree, pi);
2690 va_start(ap, format);
2691 proto_tree_set_representation(pi, format, ap);
2697 /* Set the FT_ETHER value */
2699 proto_tree_set_ether(field_info *fi, const guint8* value)
2701 fvalue_set(&fi->value, (gpointer) value, FALSE);
2705 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start)
2707 proto_tree_set_ether(fi, tvb_get_ptr(tvb, start, FT_ETHER_LEN));
2710 /* Add a FT_BOOLEAN to a proto_tree */
2712 proto_tree_add_boolean(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2713 gint length, guint32 value)
2717 header_field_info *hfinfo;
2719 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2721 DISSECTOR_ASSERT(hfinfo->type == FT_BOOLEAN);
2723 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2724 proto_tree_set_boolean(new_fi, value);
2730 proto_tree_add_boolean_format_value(proto_tree *tree, int hfindex,
2731 tvbuff_t *tvb, gint start, gint length,
2732 guint32 value, const char *format, ...)
2736 header_field_info *hfinfo;
2738 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2740 pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
2744 TRY_TO_FAKE_THIS_REPR(tree, pi);
2746 va_start(ap, format);
2747 proto_tree_set_representation_value(pi, format, ap);
2754 proto_tree_add_boolean_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2755 gint start, gint length, guint32 value,
2756 const char *format, ...)
2760 header_field_info *hfinfo;
2762 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2764 pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
2768 TRY_TO_FAKE_THIS_REPR(tree, pi);
2770 va_start(ap, format);
2771 proto_tree_set_representation(pi, format, ap);
2777 /* Set the FT_BOOLEAN value */
2779 proto_tree_set_boolean(field_info *fi, guint32 value)
2781 proto_tree_set_uint(fi, value);
2784 /* Add a FT_FLOAT to a proto_tree */
2786 proto_tree_add_float(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2787 gint length, float value)
2791 header_field_info *hfinfo;
2793 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2795 DISSECTOR_ASSERT(hfinfo->type == FT_FLOAT);
2797 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2798 proto_tree_set_float(new_fi, value);
2804 proto_tree_add_float_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2805 gint start, gint length, float value,
2806 const char *format, ...)
2810 header_field_info *hfinfo;
2812 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2814 pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
2818 TRY_TO_FAKE_THIS_REPR(tree, pi);
2820 va_start(ap, format);
2821 proto_tree_set_representation_value(pi, format, ap);
2828 proto_tree_add_float_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2829 gint start, gint length, float value,
2830 const char *format, ...)
2834 header_field_info *hfinfo;
2836 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2838 pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
2842 TRY_TO_FAKE_THIS_REPR(tree, pi);
2844 va_start(ap, format);
2845 proto_tree_set_representation(pi, format, ap);
2851 /* Set the FT_FLOAT value */
2853 proto_tree_set_float(field_info *fi, float value)
2855 fvalue_set_floating(&fi->value, value);
2858 /* Add a FT_DOUBLE to a proto_tree */
2860 proto_tree_add_double(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2861 gint length, double value)
2865 header_field_info *hfinfo;
2867 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2869 DISSECTOR_ASSERT(hfinfo->type == FT_DOUBLE);
2871 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2872 proto_tree_set_double(new_fi, value);
2878 proto_tree_add_double_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2879 gint start, gint length, double value,
2880 const char *format, ...)
2884 header_field_info *hfinfo;
2886 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2888 pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
2892 TRY_TO_FAKE_THIS_REPR(tree, pi);
2894 va_start(ap, format);
2895 proto_tree_set_representation_value(pi, format, ap);
2902 proto_tree_add_double_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2903 gint start, gint length, double value,
2904 const char *format, ...)
2908 header_field_info *hfinfo;
2910 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2912 pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
2916 TRY_TO_FAKE_THIS_REPR(tree, pi);
2918 va_start(ap, format);
2919 proto_tree_set_representation(pi, format, ap);
2925 /* Set the FT_DOUBLE value */
2927 proto_tree_set_double(field_info *fi, double value)
2929 fvalue_set_floating(&fi->value, value);
2932 /* Add FT_UINT{8,16,24,32} to a proto_tree */
2934 proto_tree_add_uint(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2935 gint length, guint32 value)
2937 proto_item *pi = NULL;
2939 header_field_info *hfinfo;
2941 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2943 switch(hfinfo->type) {
2949 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length,
2951 proto_tree_set_uint(new_fi, value);
2955 DISSECTOR_ASSERT_NOT_REACHED();
2962 proto_tree_add_uint_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2963 gint start, gint length, guint32 value,
2964 const char *format, ...)
2968 header_field_info *hfinfo;
2970 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2972 pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
2976 TRY_TO_FAKE_THIS_REPR(tree, pi);
2978 va_start(ap, format);
2979 proto_tree_set_representation_value(pi, format, ap);
2986 proto_tree_add_uint_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2987 gint start, gint length, guint32 value,
2988 const char *format, ...)
2992 header_field_info *hfinfo;
2994 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2996 pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
3000 TRY_TO_FAKE_THIS_REPR(tree, pi);
3002 va_start(ap, format);
3003 proto_tree_set_representation(pi, format, ap);
3009 /* Set the FT_UINT{8,16,24,32} value */
3011 proto_tree_set_uint(field_info *fi, guint32 value)
3013 header_field_info *hfinfo;
3016 hfinfo = fi->hfinfo;
3019 if (hfinfo->bitmask) {
3020 /* Mask out irrelevant portions */
3021 integer &= hfinfo->bitmask;
3024 if (hfinfo->bitshift > 0) {
3025 integer >>= hfinfo->bitshift;
3029 fvalue_set_uinteger(&fi->value, integer);
3032 /* Add FT_UINT64 to a proto_tree */
3034 proto_tree_add_uint64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3035 gint length, guint64 value)
3037 proto_item *pi = NULL;
3039 header_field_info *hfinfo;
3041 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3043 DISSECTOR_ASSERT(hfinfo->type == FT_UINT64);
3045 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
3046 proto_tree_set_uint64(new_fi, value);
3052 proto_tree_add_uint64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3053 gint start, gint length, guint64 value,
3054 const char *format, ...)
3058 header_field_info *hfinfo;
3060 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3062 pi = proto_tree_add_uint64(tree, hfindex, tvb, start, length, value);
3066 TRY_TO_FAKE_THIS_REPR(tree, pi);
3068 va_start(ap, format);
3069 proto_tree_set_representation_value(pi, format, ap);
3076 proto_tree_add_uint64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3077 gint start, gint length, guint64 value,
3078 const char *format, ...)
3082 header_field_info *hfinfo;
3084 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3086 pi = proto_tree_add_uint64(tree, hfindex, tvb, start, length, value);
3090 TRY_TO_FAKE_THIS_REPR(tree, pi);
3092 va_start(ap, format);
3093 proto_tree_set_representation(pi, format, ap);
3099 /* Add FT_INT{8,16,24,32} to a proto_tree */
3101 proto_tree_add_int(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3102 gint length, gint32 value)
3104 proto_item *pi = NULL;
3106 header_field_info *hfinfo;
3108 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3110 switch(hfinfo->type) {
3115 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length,
3117 proto_tree_set_int(new_fi, value);
3121 DISSECTOR_ASSERT_NOT_REACHED();
3128 proto_tree_add_int_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3129 gint start, gint length, gint32 value,
3130 const char *format, ...)
3132 proto_item *pi = NULL;
3134 header_field_info *hfinfo;
3136 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3138 pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
3142 TRY_TO_FAKE_THIS_REPR(tree, pi);
3144 va_start(ap, format);
3145 proto_tree_set_representation_value(pi, format, ap);
3152 proto_tree_add_int_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3153 gint start, gint length, gint32 value,
3154 const char *format, ...)
3156 proto_item *pi = NULL;
3158 header_field_info *hfinfo;
3160 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3162 pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
3166 TRY_TO_FAKE_THIS_REPR(tree, pi);
3168 va_start(ap, format);
3169 proto_tree_set_representation(pi, format, ap);
3175 /* Set the FT_INT{8,16,24,32} value */
3177 proto_tree_set_int(field_info *fi, gint32 value)
3179 header_field_info *hfinfo;
3182 hfinfo = fi->hfinfo;
3183 integer = (guint32) value;
3185 if (hfinfo->bitmask) {
3186 /* Mask out irrelevant portions */
3187 integer &= hfinfo->bitmask;
3190 if (hfinfo->bitshift > 0) {
3191 integer >>= hfinfo->bitshift;
3195 fvalue_set_sinteger(&fi->value, integer);
3198 /* Add FT_INT64 to a proto_tree */
3200 proto_tree_add_int64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3201 gint length, gint64 value)
3203 proto_item *pi = NULL;
3205 header_field_info *hfinfo;
3207 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3209 DISSECTOR_ASSERT(hfinfo->type == FT_INT64);
3211 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
3212 proto_tree_set_uint64(new_fi, (guint64)value);
3218 proto_tree_add_int64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3219 gint start, gint length, gint64 value,
3220 const char *format, ...)
3224 header_field_info *hfinfo;
3226 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3228 pi = proto_tree_add_int64(tree, hfindex, tvb, start, length, value);
3232 TRY_TO_FAKE_THIS_REPR(tree, pi);
3234 va_start(ap, format);
3235 proto_tree_set_representation_value(pi, format, ap);
3242 proto_tree_add_int64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3243 gint start, gint length, gint64 value,
3244 const char *format, ...)
3248 header_field_info *hfinfo;
3250 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3252 pi = proto_tree_add_int64(tree, hfindex, tvb, start, length, value);
3256 TRY_TO_FAKE_THIS_REPR(tree, pi);
3258 va_start(ap, format);
3259 proto_tree_set_representation(pi, format, ap);
3265 /* Add a field_info struct to the proto_tree, encapsulating it in a proto_node */
3267 proto_tree_add_node(proto_tree *tree, field_info *fi)
3269 proto_node *pnode, *tnode, *sibling;
3273 * Make sure "tree" is ready to have subtrees under it, by
3274 * checking whether it's been given an ett_ value.
3276 * "PNODE_FINFO(tnode)" may be null; that's the case for the root
3277 * node of the protocol tree. That node is not displayed,
3278 * so it doesn't need an ett_ value to remember whether it
3282 tfi = PNODE_FINFO(tnode);
3283 if (tfi != NULL && (tfi->tree_type < 0 || tfi->tree_type >= num_tree_types)) {
3284 REPORT_DISSECTOR_BUG(ep_strdup_printf("\"%s\" - \"%s\" tfi->tree_type: %u invalid (%s:%u)",
3285 fi->hfinfo->name, fi->hfinfo->abbrev, tfi->tree_type, __FILE__, __LINE__));
3286 /* XXX - is it safe to continue here? */
3289 DISSECTOR_ASSERT(tfi == NULL ||
3290 (tfi->tree_type >= 0 && tfi->tree_type < num_tree_types));
3292 PROTO_NODE_NEW(pnode);
3293 pnode->parent = tnode;
3294 PNODE_FINFO(pnode) = fi;
3295 pnode->tree_data = PTREE_DATA(tree);
3297 if (tnode->last_child != NULL) {
3298 sibling = tnode->last_child;
3299 DISSECTOR_ASSERT(sibling->next == NULL);
3300 sibling->next = pnode;
3302 tnode->first_child = pnode;
3303 tnode->last_child = pnode;
3305 return (proto_item*)pnode;
3309 /* Generic way to allocate field_info and add to proto_tree.
3310 * Sets *pfi to address of newly-allocated field_info struct, if pfi is
3313 proto_tree_add_pi(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3314 gint *length, field_info **pfi)
3323 fi = alloc_field_info(tree, hfindex, tvb, start, length);
3324 pi = proto_tree_add_node(tree, fi);
3326 /* If the proto_tree wants to keep a record of this finfo
3327 * for quick lookup, then record it. */
3328 ptrs = proto_lookup_or_create_interesting_hfids(tree, fi->hfinfo);
3330 g_ptr_array_add(ptrs, fi);
3332 /* Does the caller want to know the fi pointer? */
3341 static header_field_info *
3342 get_hfi_and_length(int hfindex, tvbuff_t *tvb, const gint start, gint *length,
3345 header_field_info *hfinfo;
3346 gint length_remaining;
3349 * We only allow a null tvbuff if the item has a zero length,
3350 * i.e. if there's no data backing it.
3352 DISSECTOR_ASSERT(tvb != NULL || *length == 0);
3354 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
3357 * XXX - in some protocols, there are 32-bit unsigned length
3358 * fields, so lengths in protocol tree and tvbuff routines
3359 * should really be unsigned. We should have, for those
3360 * field types for which "to the end of the tvbuff" makes sense,
3361 * additional routines that take no length argument and
3362 * add fields that run to the end of the tvbuff.
3364 if (*length == -1) {
3366 * For FT_NONE, FT_PROTOCOL, FT_BYTES, and FT_STRING fields,
3367 * a length of -1 means "set the length to what remains in
3370 * The assumption is either that
3372 * 1) the length of the item can only be determined
3373 * by dissection (typically true of items with
3374 * subitems, which are probably FT_NONE or
3379 * 2) if the tvbuff is "short" (either due to a short
3380 * snapshot length or due to lack of reassembly of
3381 * fragments/segments/whatever), we want to display
3382 * what's available in the field (probably FT_BYTES
3383 * or FT_STRING) and then throw an exception later
3387 * 3) the field is defined to be "what's left in the
3390 * so we set the length to what remains in the tvbuff so
3391 * that, if we throw an exception while dissecting, it
3392 * has what is probably the right value.
3394 * For FT_STRINGZ, it means "the string is null-terminated,
3395 * not null-padded; set the length to the actual length
3396 * of the string", and if the tvbuff if short, we just
3397 * throw an exception.
3399 * It's not valid for any other type of field.
3401 switch (hfinfo->type) {
3405 * We allow this to be zero-length - for
3406 * example, an ONC RPC NULL procedure has
3407 * neither arguments nor reply, so the
3408 * payload for that protocol is empty.
3410 * However, if the length is negative, the
3411 * start offset is *past* the byte past the
3412 * end of the tvbuff, so we throw an
3415 *length = tvb_length_remaining(tvb, start);
3418 * Use "tvb_ensure_bytes_exist()"
3419 * to force the appropriate exception
3422 tvb_ensure_bytes_exist(tvb, start, 0);
3424 DISSECTOR_ASSERT(*length >= 0);
3430 *length = tvb_ensure_length_remaining(tvb, start);
3431 DISSECTOR_ASSERT(*length >= 0);
3436 * Leave the length as -1, so our caller knows
3442 DISSECTOR_ASSERT_NOT_REACHED();
3444 *item_length = *length;
3446 *item_length = *length;
3447 if (hfinfo->type == FT_PROTOCOL || hfinfo->type == FT_NONE) {
3449 * These types are for interior nodes of the
3450 * tree, and don't have data associated with
3451 * them; if the length is negative (XXX - see
3452 * above) or goes past the end of the tvbuff,
3453 * cut it short at the end of the tvbuff.
3454 * That way, if this field is selected in
3455 * Wireshark, we don't highlight stuff past
3456 * the end of the data.
3458 /* XXX - what to do, if we don't have a tvb? */
3460 length_remaining = tvb_length_remaining(tvb, start);
3461 if (*item_length < 0 ||
3462 (*item_length > 0 &&
3463 (length_remaining < *item_length)))
3464 *item_length = length_remaining;
3467 if (*item_length < 0) {
3468 THROW(ReportedBoundsError);
3476 new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
3477 const gint start, const gint item_length)
3483 fi->hfinfo = hfinfo;
3485 fi->start+=(tvb)?TVB_RAW_OFFSET(tvb):0;
3486 fi->length = item_length;
3489 if (!PTREE_DATA(tree)->visible)
3490 FI_SET_FLAG(fi, FI_HIDDEN);
3491 fvalue_init(&fi->value, fi->hfinfo->type);
3494 /* add the data source tvbuff */
3495 fi->ds_tvb=tvb?TVB_GET_DS_TVB(tvb):NULL;
3497 fi->appendix_start = 0;
3498 fi->appendix_length = 0;
3504 alloc_field_info(proto_tree *tree, int hfindex, tvbuff_t *tvb, const gint start,
3507 header_field_info *hfinfo;
3510 hfinfo = get_hfi_and_length(hfindex, tvb, start, length, &item_length);
3511 return new_field_info(tree, hfinfo, tvb, start, item_length);
3514 /* If the protocol tree is to be visible, set the representation of a
3515 proto_tree entry with the name of the field for the item and with
3516 the value formatted with the supplied printf-style format and
3519 proto_tree_set_representation_value(proto_item *pi, const char *format, va_list ap)
3521 int ret; /*tmp return value */
3522 field_info *fi = PITEM_FINFO(pi);
3523 header_field_info *hf;
3525 DISSECTOR_ASSERT(fi);
3529 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
3530 ITEM_LABEL_NEW(fi->rep);
3531 if (hf->bitmask && (hf->type == FT_BOOLEAN || IS_FT_UINT(hf->type))) {
3535 val = fvalue_get_uinteger(&fi->value);
3536 if (hf->bitshift > 0) {
3537 val <<= hf->bitshift;
3539 decode_bitfield_value(tmpbuf, val, hf->bitmask, hfinfo_bitwidth(hf));
3540 /* put in the hf name */
3541 ret = g_snprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
3542 "%s%s: ", tmpbuf, fi->hfinfo->name);
3544 /* put in the hf name */
3545 ret = g_snprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
3546 "%s: ", fi->hfinfo->name);
3549 /* If possible, Put in the value of the string */
3550 if (ret < ITEM_LABEL_LENGTH) {
3551 ret += g_vsnprintf(fi->rep->representation + ret,
3552 ITEM_LABEL_LENGTH - ret, format, ap);
3554 if (ret >= ITEM_LABEL_LENGTH) {
3555 /* Uh oh, we don't have enough room. Tell the user
3556 * that the field is truncated.
3560 /* Argh, we cannot reuse 'ap' here. So make a copy
3561 * of what we formatted for (re)use below.
3563 oldrep = g_strdup(fi->rep->representation);
3565 g_snprintf(fi->rep->representation,
3574 /* If the protocol tree is to be visible, set the representation of a
3575 proto_tree entry with the representation formatted with the supplied
3576 printf-style format and argument list. */
3578 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap)
3580 int ret; /*tmp return value */
3581 field_info *fi = PITEM_FINFO(pi);
3583 DISSECTOR_ASSERT(fi);
3585 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
3586 ITEM_LABEL_NEW(fi->rep);
3587 ret = g_vsnprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
3589 if (ret >= ITEM_LABEL_LENGTH) {
3590 /* Uh oh, we don't have enough room. Tell the user
3591 * that the field is truncated.
3595 /* Argh, we cannot reuse 'ap' here. So make a copy
3596 * of what we formatted for (re)use below.
3598 oldrep = g_strdup(fi->rep->representation);
3600 g_snprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
3601 "[truncated] %s", oldrep);
3607 /* -------------------------- */
3609 proto_custom_set(proto_tree* tree, const int field_id, gint occurrence,
3610 gchar *result, gchar *expr, const int size)
3616 struct e_in6_addr *ipv6;
3618 guint32 n_addr; /* network-order IPv4 address */
3620 const true_false_string *tfstring;
3621 int len, prev_len=0, last, i, offset_r=0, offset_e=0;
3623 field_info *finfo = NULL;
3624 header_field_info* hfinfo;
3625 const gchar *abbrev = NULL;
3627 g_assert(field_id >= 0);
3629 hfinfo = proto_registrar_get_nth((guint)field_id);
3631 /* do we need to rewind ? */
3635 if (occurrence < 0) {
3636 /* Search other direction */
3637 while (hfinfo->same_name_prev) {
3638 hfinfo = hfinfo->same_name_prev;
3643 finfos = proto_get_finfo_ptr_array(tree, hfinfo->id);
3645 if (!finfos || !(len = g_ptr_array_len(finfos))) {
3646 if (occurrence < 0) {
3647 hfinfo = hfinfo->same_name_next;
3649 hfinfo = hfinfo->same_name_prev;
3654 /* Are there enough occurrences of the field? */
3655 if ((occurrence-prev_len > len) || (occurrence+prev_len < -len)) {
3656 if (occurrence < 0) {
3657 hfinfo = hfinfo->same_name_next;
3659 hfinfo = hfinfo->same_name_prev;
3665 /* Calculate single index or set outer bounderies */
3666 if (occurrence < 0) {
3667 i = occurrence + len + prev_len;
3669 } else if (occurrence > 0) {
3670 i = occurrence - 1 - prev_len;
3677 prev_len += len; /* Count handled occurrences */
3680 finfo = g_ptr_array_index(finfos, i);
3682 if (offset_r && (offset_r < size-2))
3683 result[offset_r++]=',';
3685 if (offset_e && (offset_e < size-2))
3686 expr[offset_e++]=',';
3688 switch(hfinfo->type) {
3690 case FT_NONE: /* Nothing to add */
3691 if (offset_r == 0) {
3693 } else if (result[offset_r-1] == ',') {
3694 result[offset_r-1] = '\0';
3699 /* prevent multiple "yes" entries by setting result directly */
3700 g_strlcpy(result, "Yes", size);
3705 bytes = fvalue_get(&finfo->value);
3706 offset_r += (int)g_strlcpy(result+offset_r, bytes_to_str(bytes, fvalue_length(&finfo->value)), size-offset_r);
3709 case FT_ABSOLUTE_TIME:
3710 offset_r += (int)g_strlcpy(result+offset_r,
3711 abs_time_to_str(fvalue_get(&finfo->value), hfinfo->display, TRUE),
3715 case FT_RELATIVE_TIME:
3716 offset_r += (int)g_strlcpy(result+offset_r, rel_time_to_secs_str(fvalue_get(&finfo->value)), size-offset_r);
3720 u_integer = fvalue_get_uinteger(&finfo->value);
3721 tfstring = (const true_false_string *)&tfs_true_false;
3722 if (hfinfo->strings) {
3723 tfstring = (const struct true_false_string*) hfinfo->strings;
3725 offset_r += (int)g_strlcpy(result+offset_r, u_integer ? tfstring->true_string : tfstring->false_string, size-offset_r);
3727 g_snprintf(expr+offset_e, size-offset_e, "%u", fvalue_get_uinteger(&finfo->value) ? 1 : 0);
3728 offset_e = (int)strlen(expr);
3736 u_integer = fvalue_get_uinteger(&finfo->value);
3737 if (hfinfo->strings) {
3738 if (hfinfo->display & BASE_RANGE_STRING) {
3739 offset_r += (int)g_strlcpy(result+offset_r, rval_to_str(u_integer, hfinfo->strings, "%u"), size-offset_r);
3740 } else if (hfinfo->display & BASE_EXT_STRING) {
3741 offset_r += (int)g_strlcpy(result+offset_r, val_to_str_ext(u_integer, (value_string_ext *) (hfinfo->strings), "%u"), size-offset_r);
3743 offset_r += (int)g_strlcpy(result+offset_r, val_to_str(u_integer, cVALS(hfinfo->strings), "%u"), size-offset_r);
3745 } else if (IS_BASE_DUAL(hfinfo->display)) {
3746 g_snprintf(result+offset_r, size-offset_r, hfinfo_uint_value_format(hfinfo), u_integer, u_integer);
3747 offset_r = (int)strlen(result);
3749 g_snprintf(result+offset_r, size-offset_r, hfinfo_uint_value_format(hfinfo), u_integer);
3750 offset_r = (int)strlen(result);
3753 g_snprintf(expr+offset_e, size-offset_e, hfinfo_numeric_value_format(hfinfo), fvalue_get_uinteger(&finfo->value));
3754 offset_e = (int)strlen(expr);
3759 g_snprintf(result+offset_r, size-offset_r, "%" G_GINT64_MODIFIER "u", fvalue_get_integer64(&finfo->value));
3760 offset_r = (int)strlen(result);
3763 /* XXX - make these just FT_INT? */
3768 integer = fvalue_get_sinteger(&finfo->value);
3769 if (hfinfo->strings) {
3770 if (hfinfo->display & BASE_RANGE_STRING) {
3771 offset_r += (int)g_strlcpy(result+offset_r, rval_to_str(integer, hfinfo->strings, "%d"), size-offset_r);
3772 } else if (hfinfo->display & BASE_EXT_STRING) {
3773 offset_r += (int)g_strlcpy(result+offset_r, val_to_str_ext(integer, (value_string_ext *) (hfinfo->strings), "%d"), size-offset_r);
3775 offset_r += (int)g_strlcpy(result+offset_r, val_to_str(integer, cVALS(hfinfo->strings), "%d"), size-offset_r);
3777 } else if (IS_BASE_DUAL(hfinfo->display)) {
3778 g_snprintf(result+offset_r, size-offset_r, hfinfo_int_value_format(hfinfo), integer, integer);
3779 offset_r = (int)strlen(result);
3781 g_snprintf(result+offset_r, size-offset_r, hfinfo_int_value_format(hfinfo), integer);
3782 offset_r = (int)strlen(result);
3785 g_snprintf(expr+offset_e, size-offset_e, hfinfo_numeric_value_format(hfinfo), fvalue_get_sinteger(&finfo->value));
3786 offset_e = (int)strlen(expr);
3790 ipv4 = fvalue_get(&finfo->value);
3791 n_addr = ipv4_get_net_order_addr(ipv4);
3792 offset_r += (int)g_strlcpy(result+offset_r, ip_to_str((guint8 *)&n_addr), size-offset_r);
3796 ipv6 = fvalue_get(&finfo->value);
3797 SET_ADDRESS (&addr, AT_IPv6, sizeof(struct e_in6_addr), ipv6);
3798 address_to_str_buf(&addr, result+offset_r, size-offset_r);
3799 offset_r = (int)strlen(result);
3803 offset_r += (int)g_strlcpy(result+offset_r, bytes_to_str_punct(fvalue_get(&finfo->value), 6, ':'), size-offset_r);
3807 offset_r += (int)g_strlcpy(result+offset_r, guid_to_str((e_guid_t *)fvalue_get(&finfo->value)), size-offset_r);
3811 bytes = fvalue_get(&finfo->value);
3812 offset_r += (int)g_strlcpy(result+offset_r, oid_resolved_from_encoded(bytes, fvalue_length(&finfo->value)), size-offset_r);
3813 offset_e += (int)g_strlcpy(expr+offset_e, oid_encoded2string(bytes, fvalue_length(&finfo->value)), size-offset_e);
3817 g_snprintf(result+offset_r, size-offset_r, "%." STRINGIFY(FLT_DIG) "f", fvalue_get_floating(&finfo->value));
3818 offset_r = (int)strlen(result);
3822 g_snprintf(result+offset_r, size-offset_r, "%." STRINGIFY(DBL_DIG) "g", fvalue_get_floating(&finfo->value));
3823 offset_r = (int)strlen(result);
3829 case FT_UINT_STRING:
3830 bytes = fvalue_get(&finfo->value);
3831 offset_r += (int)g_strlcpy(result+offset_r, format_text(bytes, strlen(bytes)), size-offset_r);
3834 case FT_IPXNET: /*XXX really No column custom ?*/
3837 g_error("hfinfo->type %d (%s) not handled\n",
3839 ftype_name(hfinfo->type));
3840 DISSECTOR_ASSERT_NOT_REACHED();
3846 switch(hfinfo->type) {
3859 /* for these types, "expr" is filled in the loop above */
3863 /* for all others, just copy "result" to "expr" */
3864 g_strlcpy(expr, result, size);
3869 /* Store abbrev for return value */
3870 abbrev = hfinfo->abbrev;
3873 if (occurrence == 0) {
3874 /* Fetch next hfinfo with same name (abbrev) */
3875 hfinfo = hfinfo->same_name_prev;
3881 return abbrev ? abbrev : "";
3885 /* Set text of proto_item after having already been created. */
3887 proto_item_set_text(proto_item *pi, const char *format, ...)
3889 field_info *fi = NULL;
3896 fi = PITEM_FINFO(pi);
3901 ITEM_LABEL_FREE(fi->rep);
3904 va_start(ap, format);
3905 proto_tree_set_representation(pi, format, ap);
3909 /* Append to text of proto_item after having already been created. */
3911 proto_item_append_text(proto_item *pi, const char *format, ...)
3913 field_info *fi = NULL;
3921 fi = PITEM_FINFO(pi);
3926 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
3928 * If we don't already have a representation,
3929 * generate the default representation.
3931 if (fi->rep == NULL) {
3932 ITEM_LABEL_NEW(fi->rep);
3933 proto_item_fill_label(fi, fi->rep->representation);
3936 curlen = strlen(fi->rep->representation);
3937 if (ITEM_LABEL_LENGTH > curlen) {
3938 va_start(ap, format);
3939 g_vsnprintf(fi->rep->representation + curlen,
3940 ITEM_LABEL_LENGTH - (gulong) curlen, format, ap);
3946 /* Prepend to text of proto_item after having already been created. */
3948 proto_item_prepend_text(proto_item *pi, const char *format, ...)
3950 field_info *fi = NULL;
3951 char representation[ITEM_LABEL_LENGTH];
3958 fi = PITEM_FINFO(pi);
3963 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
3965 * If we don't already have a representation,
3966 * generate the default representation.
3968 if (fi->rep == NULL) {
3969 ITEM_LABEL_NEW(fi->rep);
3970 proto_item_fill_label(fi, fi->rep->representation);
3973 g_strlcpy(representation, fi->rep->representation, ITEM_LABEL_LENGTH);
3974 va_start(ap, format);
3975 g_vsnprintf(fi->rep->representation,
3976 ITEM_LABEL_LENGTH, format, ap);
3978 g_strlcat(fi->rep->representation, representation, ITEM_LABEL_LENGTH);
3983 proto_item_set_len(proto_item *pi, const gint length)
3990 fi = PITEM_FINFO(pi);
3994 DISSECTOR_ASSERT(length >= 0);
3995 fi->length = length;
3997 if (fi->value.ftype->ftype == FT_BYTES)
3998 fi->value.value.bytes->len = length;
4002 * Sets the length of the item based on its start and on the specified
4003 * offset, which is the offset past the end of the item; as the start
4004 * in the item is relative to the beginning of the data source tvbuff,
4005 * we need to pass in a tvbuff - the end offset is relative to the beginning
4009 proto_item_set_end(proto_item *pi, tvbuff_t *tvb, gint end)
4016 fi = PITEM_FINFO(pi);
4020 end += TVB_RAW_OFFSET(tvb);
4021 DISSECTOR_ASSERT(end >= fi->start);
4022 fi->length = end - fi->start;
4026 proto_item_get_len(const proto_item *pi)
4028 field_info *fi = PITEM_FINFO(pi);
4029 return fi ? fi->length : -1;
4033 /** clear flags according to the mask and set new flag values */
4034 #define FI_REPLACE_FLAGS(fi, mask, flags_in) { \
4035 (fi->flags = (fi)->flags & ~(mask)); \
4036 (fi->flags = (fi)->flags | (flags_in)); \
4040 proto_item_set_expert_flags(proto_item *pi, const int group, const guint severity)
4042 if(pi == NULL || PITEM_FINFO(pi) == NULL)
4045 /* only change things if severity is worse or at least equal than before */
4046 if(severity >= FI_GET_FLAG(PITEM_FINFO(pi), PI_SEVERITY_MASK)) {
4047 FI_REPLACE_FLAGS(PITEM_FINFO(pi), PI_GROUP_MASK, group);
4048 FI_REPLACE_FLAGS(PITEM_FINFO(pi), PI_SEVERITY_MASK, severity);
4057 proto_tree_create_root(void)
4061 /* Initialize the proto_node */
4062 PROTO_NODE_NEW(pnode);
4063 pnode->parent = NULL;
4064 PNODE_FINFO(pnode) = NULL;
4065 pnode->tree_data = g_new(tree_data_t, 1);
4067 /* Don't initialize the tree_data_t. Wait until we know we need it */
4068 pnode->tree_data->interesting_hfids = NULL;
4070 /* Set the default to FALSE so it's easier to
4071 * find errors; if we expect to see the protocol tree
4072 * but for some reason the default 'visible' is not
4073 * changed, then we'll find out very quickly. */
4074 pnode->tree_data->visible = FALSE;
4076 /* Make sure that we fake protocols (if possible) */
4077 pnode->tree_data->fake_protocols = TRUE;
4079 /* Keep track of the number of children */
4080 pnode->tree_data->count = 0;
4082 return (proto_tree*) pnode;
4086 /* "prime" a proto_tree with a single hfid that a dfilter
4087 * is interested in. */
4089 proto_tree_prime_hfid(proto_tree *tree _U_, const gint hfid)
4091 header_field_info *hfinfo;
4093 PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
4094 /* this field is referenced by a filter so increase the refcount.
4095 also increase the refcount for the parent, i.e the protocol.
4097 hfinfo->ref_type = HF_REF_TYPE_DIRECT;
4098 /* only increase the refcount if there is a parent.
4099 if this is a protocol and not a field then parent will be -1
4100 and there is no parent to add any refcounting for.
4102 if (hfinfo->parent != -1) {
4103 header_field_info *parent_hfinfo;
4104 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
4106 /* Mark parent as indirectly referenced unless it is already directly
4107 * referenced, i.e. the user has specified the parent in a filter.
4109 if (parent_hfinfo->ref_type != HF_REF_TYPE_DIRECT)
4110 parent_hfinfo->ref_type = HF_REF_TYPE_INDIRECT;
4115 proto_item_add_subtree(proto_item *pi, const gint idx) {
4121 DISSECTOR_ASSERT(idx >= 0 && idx < num_tree_types);
4123 fi = PITEM_FINFO(pi);
4125 return (proto_tree*) pi;
4127 fi->tree_type = idx;
4129 return (proto_tree*) pi;
4133 proto_item_get_subtree(const proto_item *pi) {
4138 fi = PITEM_FINFO(pi);
4139 if ( (!fi) || (fi->tree_type == -1) )
4141 return (proto_tree*) pi;
4145 proto_item_get_parent(const proto_item *ti) {
4152 proto_item_get_parent_nth(proto_item *ti, int gen) {
4165 proto_tree_get_parent(const proto_tree *tree) {
4168 return (proto_item*) tree;
4172 proto_tree_get_root(proto_tree *tree) {
4175 while (tree->parent) {
4176 tree = tree->parent;
4182 proto_tree_move_item(proto_tree *tree, proto_item *fixed_item,
4183 proto_item *item_to_move)
4186 /* Revert part of: http://anonsvn.wireshark.org/viewvc?view=rev&revision=32443
4187 * See https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=5500
4189 /* This function doesn't generate any values. It only reorganizes the prococol tree
4190 * so we can bail out immediately if it isn't visible. */
4191 if (!tree || !PTREE_DATA(tree)->visible)
4194 DISSECTOR_ASSERT(item_to_move->parent == tree);
4195 DISSECTOR_ASSERT(fixed_item->parent == tree);
4197 /*** cut item_to_move out ***/
4199 /* is item_to_move the first? */
4200 if(tree->first_child == item_to_move) {
4201 /* simply change first child to next */
4202 tree->first_child = item_to_move->next;
4204 DISSECTOR_ASSERT(tree->last_child != item_to_move);
4206 proto_item *curr_item;
4207 /* find previous and change it's next */
4208 for(curr_item = tree->first_child; curr_item != NULL; curr_item = curr_item->next) {
4209 if(curr_item->next == item_to_move) {
4214 DISSECTOR_ASSERT(curr_item);
4216 curr_item->next = item_to_move->next;
4218 /* fix last_child if required */
4219 if(tree->last_child == item_to_move) {
4220 tree->last_child = curr_item;
4224 /*** insert to_move after fixed ***/
4225 item_to_move->next = fixed_item->next;
4226 fixed_item->next = item_to_move;
4227 if(tree->last_child == fixed_item) {
4228 tree->last_child = item_to_move;
4233 proto_tree_set_appendix(proto_tree *tree, tvbuff_t *tvb, gint start,
4241 fi = PTREE_FINFO(tree);
4245 start += TVB_RAW_OFFSET(tvb);
4246 DISSECTOR_ASSERT(start >= 0);
4247 DISSECTOR_ASSERT(length >= 0);
4249 fi->appendix_start = start;
4250 fi->appendix_length = length;
4254 proto_register_protocol(const char *name, const char *short_name,
4255 const char *filter_name)
4257 protocol_t *protocol;
4258 header_field_info *hfinfo;
4260 char *existing_name;
4264 gboolean found_invalid;
4267 * Make sure there's not already a protocol with any of those
4268 * names. Crash if there is, as that's an error in the code
4269 * or an inappropriate plugin.
4270 * This situation has to be fixed to not register more than one
4271 * protocol with the same name.
4273 * This is done by reducing the number of strcmp (and alike) calls as much as possible,
4274 * as this significally slows down startup time.
4276 * Drawback: As a hash value is used to reduce insert time,
4277 * this might lead to a hash collision.
4278 * However, as we have around 500+ protocols and we're using a 32 bit int this is very,
4282 key = g_malloc (sizeof(gint));
4283 *key = wrs_str_hash(name);
4284 existing_name = g_hash_table_lookup(proto_names, key);
4285 if (existing_name != NULL) {
4286 /* g_error will terminate the program */
4287 g_error("Duplicate protocol name \"%s\"!"
4288 " This might be caused by an inappropriate plugin or a development error.", name);
4290 g_hash_table_insert(proto_names, key, (gpointer)name);
4292 existing_name = g_hash_table_lookup(proto_short_names, (gpointer)short_name);
4293 if (existing_name != NULL) {
4294 g_error("Duplicate protocol short_name \"%s\"!"
4295 " This might be caused by an inappropriate plugin or a development error.", short_name);
4297 g_hash_table_insert(proto_short_names, (gpointer)short_name, (gpointer)short_name);
4299 found_invalid = FALSE;
4300 for (i = 0; i < strlen(filter_name); i++) {
4302 if (!(islower(c) || isdigit(c) || c == '-' || c == '_' || c == '.')) {
4303 found_invalid = TRUE;
4306 if (found_invalid) {
4307 g_error("Protocol filter name \"%s\" has one or more invalid characters."
4308 " Allowed are lower characters, digits, '-', '_' and '.'."
4309 " This might be caused by an inappropriate plugin or a development error.", filter_name);
4311 existing_name = g_hash_table_lookup(proto_filter_names, (gpointer)filter_name);
4312 if (existing_name != NULL) {
4313 g_error("Duplicate protocol filter_name \"%s\"!"
4314 " This might be caused by an inappropriate plugin or a development error.", filter_name);
4316 g_hash_table_insert(proto_filter_names, (gpointer)filter_name, (gpointer)filter_name);
4318 /* Add this protocol to the list of known protocols; the list
4319 is sorted by protocol short name. */
4320 protocol = g_new(protocol_t, 1);
4321 protocol->name = name;
4322 protocol->short_name = short_name;
4323 protocol->filter_name = filter_name;
4324 protocol->fields = NULL;
4325 protocol->is_enabled = TRUE; /* protocol is enabled by default */
4326 protocol->can_toggle = TRUE;
4327 protocol->is_private = FALSE;
4328 /* list will be sorted later by name, when all protocols completed registering */
4329 protocols = g_list_prepend(protocols, protocol);
4331 /* Here we do allocate a new header_field_info struct */
4332 #if GLIB_CHECK_VERSION(2,10,0)
4333 hfinfo = g_slice_new(header_field_info);
4335 hfinfo = g_mem_chunk_alloc(gmc_hfinfo);
4337 hfinfo->name = name;
4338 hfinfo->abbrev = filter_name;
4339 hfinfo->type = FT_PROTOCOL;
4340 hfinfo->display = BASE_NONE;
4341 hfinfo->strings = protocol;
4342 hfinfo->bitmask = 0;
4343 hfinfo->bitshift = 0;
4344 hfinfo->ref_type = HF_REF_TYPE_NONE;
4345 hfinfo->blurb = NULL;
4346 hfinfo->parent = -1; /* this field differentiates protos and fields */
4348 proto_id = proto_register_field_init(hfinfo, hfinfo->parent);
4349 protocol->proto_id = proto_id;
4354 proto_mark_private(const int proto_id)
4356 protocol_t *protocol = find_protocol_by_id(proto_id);
4358 protocol->is_private = TRUE;
4362 proto_is_private(const int proto_id)
4364 protocol_t *protocol = find_protocol_by_id(proto_id);
4366 return protocol->is_private;
4372 * Routines to use to iterate over the protocols.
4373 * The argument passed to the iterator routines is an opaque cookie to
4374 * their callers; it's the GList pointer for the current element in
4376 * The ID of the protocol is returned, or -1 if there is no protocol.
4379 proto_get_first_protocol(void **cookie)
4381 protocol_t *protocol;
4383 if (protocols == NULL)
4385 *cookie = protocols;
4386 protocol = protocols->data;
4387 return protocol->proto_id;
4391 proto_get_next_protocol(void **cookie)
4393 GList *list_item = *cookie;
4394 protocol_t *protocol;
4396 list_item = g_list_next(list_item);
4397 if (list_item == NULL)
4399 *cookie = list_item;
4400 protocol = list_item->data;
4401 return protocol->proto_id;
4405 proto_get_first_protocol_field(const int proto_id, void **cookie)
4407 protocol_t *protocol = find_protocol_by_id(proto_id);
4408 hf_register_info *ptr;
4410 if ((protocol == NULL) || (protocol->fields == NULL))
4413 *cookie = protocol->fields;
4414 ptr = protocol->fields->data;
4415 return &ptr->hfinfo;
4419 proto_get_next_protocol_field(void **cookie)
4421 GList *list_item = *cookie;
4422 hf_register_info *ptr;
4424 list_item = g_list_next(list_item);
4425 if (list_item == NULL)
4428 *cookie = list_item;
4429 ptr = list_item->data;
4430 return &ptr->hfinfo;
4434 find_protocol_by_id(const int proto_id)
4436 header_field_info *hfinfo;
4441 PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
4442 DISSECTOR_ASSERT(hfinfo->type==FT_PROTOCOL);
4443 return (protocol_t *)hfinfo->strings;
4446 static gint compare_filter_name(gconstpointer proto_arg,
4447 gconstpointer filter_name)
4449 const protocol_t *protocol = proto_arg;
4450 const gchar* f_name = filter_name;
4452 return (strcmp(protocol->filter_name, f_name));
4456 proto_get_id(const protocol_t *protocol)
4458 return protocol->proto_id;
4461 int proto_get_id_by_filter_name(const gchar* filter_name)
4464 protocol_t *protocol;
4466 list_entry = g_list_find_custom(protocols, filter_name,
4467 compare_filter_name);
4469 if (list_entry == NULL)
4471 protocol = list_entry->data;
4472 return protocol->proto_id;
4476 proto_get_protocol_name(const int proto_id)
4478 protocol_t *protocol;
4480 protocol = find_protocol_by_id(proto_id);
4482 if (protocol == NULL)
4484 return protocol->name;
4488 proto_get_protocol_short_name(const protocol_t *protocol)
4490 if (protocol == NULL)
4492 return protocol->short_name;
4496 proto_get_protocol_long_name(const protocol_t *protocol)
4498 if (protocol == NULL)
4500 return protocol->name;
4504 proto_get_protocol_filter_name(const int proto_id)
4506 protocol_t *protocol;
4508 protocol = find_protocol_by_id(proto_id);
4509 if (protocol == NULL)
4511 return protocol->filter_name;
4515 proto_is_protocol_enabled(const protocol_t *protocol)
4517 return protocol->is_enabled;
4521 proto_can_toggle_protocol(const int proto_id)
4523 protocol_t *protocol;
4525 protocol = find_protocol_by_id(proto_id);
4526 return protocol->can_toggle;
4530 proto_set_decoding(const int proto_id, const gboolean enabled)
4532 protocol_t *protocol;
4534 protocol = find_protocol_by_id(proto_id);
4535 DISSECTOR_ASSERT(protocol->can_toggle);
4536 protocol->is_enabled = enabled;
4540 proto_enable_all(void)
4542 protocol_t *protocol;
4543 GList *list_item = protocols;
4545 if (protocols == NULL)
4549 protocol = list_item->data;
4550 if (protocol->can_toggle)
4551 protocol->is_enabled = TRUE;
4552 list_item = g_list_next(list_item);
4557 proto_set_cant_toggle(const int proto_id)
4559 protocol_t *protocol;
4561 protocol = find_protocol_by_id(proto_id);
4562 protocol->can_toggle = FALSE;
4565 /* for use with static arrays only, since we don't allocate our own copies
4566 of the header_field_info struct contained within the hf_register_info struct */
4568 proto_register_field_array(const int parent, hf_register_info *hf, const int num_records)
4571 hf_register_info *ptr = hf;
4574 proto = find_protocol_by_id(parent);
4575 for (i = 0; i < num_records; i++, ptr++) {
4577 * Make sure we haven't registered this yet.
4578 * Most fields have variables associated with them
4579 * that are initialized to -1; some have array elements,
4580 * or possibly uninitialized variables, so we also allow
4581 * 0 (which is unlikely to be the field ID we get back
4582 * from "proto_register_field_init()").
4584 if (*ptr->p_id != -1 && *ptr->p_id != 0) {
4586 "Duplicate field detected in call to proto_register_field_array: %s is already registered\n",
4587 ptr->hfinfo.abbrev);
4591 if (proto != NULL) {
4592 if (proto->fields == NULL) {
4593 proto->fields = g_list_append(NULL, ptr);
4594 proto->last_field = proto->fields;
4597 g_list_append(proto->last_field, ptr)->next;
4600 field_id = proto_register_field_init(&ptr->hfinfo, parent);
4601 *ptr->p_id = field_id;
4605 /* chars allowed in field abbrev */
4607 const guchar fld_abbrev_chars[256] = {
4608 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00-0x0F */
4609 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10-0x1F */
4610 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, /* 0x20-0x2F '-', '.' */
4611 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 0x30-0x3F '0'-'9' */
4612 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x40-0x4F 'A'-'O' */
4613 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 0x50-0x5F 'P'-'Z', '_' */
4614 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x60-0x6F 'a'-'o' */
4615 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 0x70-0x7F 'p'-'z' */
4616 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80-0x8F */
4617 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90-0x9F */
4618 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xA0-0xAF */
4619 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xB0-0xBF */
4620 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xC0-0xCF */
4621 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xD0-0xDF */
4622 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xE0-0xEF */
4623 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xF0-0xFF */
4626 /* temporary function containing assert part for easier profiling */
4627 static void tmp_fld_check_assert(header_field_info *hfinfo) {
4628 static const value_string hf_types[] = {
4629 { FT_NONE, "FT_NONE" },
4630 { FT_PROTOCOL, "FT_PROTOCOL" },
4631 { FT_BOOLEAN, "FT_BOOLEAN" },
4632 { FT_UINT8, "FT_UINT8" },
4633 { FT_UINT16, "FT_UINT16" },
4634 { FT_UINT24, "FT_UINT24" },
4635 { FT_UINT32, "FT_UINT32" },
4636 { FT_UINT64, "FT_UINT64" },
4637 { FT_INT8, "FT_INT8" },
4638 { FT_INT16, "FT_INT16" },
4639 { FT_INT24, "FT_INT24" },
4640 { FT_INT32, "FT_INT32" },
4641 { FT_INT64, "FT_INT64" },
4642 { FT_FLOAT, "FT_FLOAT" },
4643 { FT_DOUBLE, "FT_DOUBLE" },
4644 { FT_ABSOLUTE_TIME, "FT_ABSOLUTE_TIME" },
4645 { FT_RELATIVE_TIME, "FT_RELATIVE_TIME" },
4646 { FT_STRING, "FT_STRING" },
4647 { FT_STRINGZ, "FT_STRINGZ" },
4648 { FT_EBCDIC, "FT_EBCDIC" },
4649 { FT_UINT_STRING, "FT_UINT_STRING" },
4650 { FT_ETHER, "FT_ETHER" },
4651 { FT_BYTES, "FT_BYTES" },
4652 { FT_UINT_BYTES, "FT_UINT_BYTES" },
4653 { FT_IPv4, "FT_IPv4" },
4654 { FT_IPv6, "FT_IPv6" },
4655 { FT_IPXNET, "FT_IPXNET" },
4656 { FT_FRAMENUM, "FT_FRAMENUM" },
4657 { FT_PCRE, "FT_PCR" },
4658 { FT_GUID, "FT_GUID" },
4659 { FT_OID, "FT_OID" },
4662 static const value_string hf_display[] = {
4663 { BASE_NONE, "BASE_NONE" },
4664 { BASE_DEC, "BASE_DEC" },
4665 { BASE_HEX, "BASE_HEX" },
4666 { BASE_OCT, "BASE_OCT" },
4667 { BASE_DEC_HEX, "BASE_DEC_HEX" },
4668 { BASE_HEX_DEC, "BASE_HEX_DEC" },
4669 { BASE_CUSTOM, "BASE_CUSTOM" },
4670 { BASE_NONE|BASE_RANGE_STRING, "BASE_NONE|BASE_RANGE_STRING" },
4671 { BASE_DEC|BASE_RANGE_STRING, "BASE_DEC|BASE_RANGE_STRING" },
4672 { BASE_HEX|BASE_RANGE_STRING, "BASE_HEX|BASE_RANGE_STRING" },
4673 { BASE_OCT|BASE_RANGE_STRING, "BASE_OCT|BASE_RANGE_STRING" },
4674 { BASE_DEC_HEX|BASE_RANGE_STRING, "BASE_DEC_HEX|BASE_RANGE_STRING" },
4675 { BASE_HEX_DEC|BASE_RANGE_STRING, "BASE_HEX_DEC|BASE_RANGE_STRING" },
4676 { BASE_CUSTOM|BASE_RANGE_STRING, "BASE_CUSTOM|BASE_RANGE_STRING" },
4677 { ABSOLUTE_TIME_LOCAL, "ABSOLUTE_TIME_LOCAL" },
4678 { ABSOLUTE_TIME_UTC, "ABSOLUTE_TIME_LOCAL" },
4679 { ABSOLUTE_TIME_DOY_UTC, "ABSOLUTE_TIME_LOCAL" },
4682 /* The field must have a name (with length > 0) */
4683 if (!hfinfo->name || !hfinfo->name[0]) {
4685 /* Try to identify the field */
4686 g_error("Field (abbrev='%s') does not have a name\n",
4690 g_error("Field does not have a name (nor an abbreviation)\n");
4693 /* fields with an empty string for an abbreviation aren't filterable */
4694 /* XXX - so why aren't we checking for an empty string here?? */
4695 if (!hfinfo->abbrev)
4696 g_error("Field '%s' does not have an abbreviation\n", hfinfo->name);
4697 /* Okay, let's at least put out a warning and see if anyone complains */
4698 if (!hfinfo->abbrev[0])
4699 g_warning("Field '%s' does not have an abbreviation", hfinfo->name);
4701 /* These types of fields are allowed to have value_strings,
4702 * true_false_strings or a protocol_t struct
4704 if (hfinfo->strings != NULL && !(
4705 (hfinfo->type == FT_UINT8) ||
4706 (hfinfo->type == FT_UINT16) ||
4707 (hfinfo->type == FT_UINT24) ||
4708 (hfinfo->type == FT_UINT32) ||
4709 (hfinfo->type == FT_INT8) ||
4710 (hfinfo->type == FT_INT16) ||
4711 (hfinfo->type == FT_INT24) ||
4712 (hfinfo->type == FT_INT32) ||
4713 (hfinfo->type == FT_BOOLEAN) ||
4714 (hfinfo->type == FT_PROTOCOL) ||
4715 (hfinfo->type == FT_FRAMENUM) ))
4716 g_error("Field '%s' (%s) has a 'strings' value but is of type %s (which is not allowed to have strings)\n",
4717 hfinfo->name, hfinfo->abbrev,
4718 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"));
4720 switch (hfinfo->type) {
4727 /* Hexadecimal and octal are, in printf() and everywhere
4728 * else, unsigned so don't allow dissectors to register a
4729 * signed field to be displayed unsigned. (Else how would
4730 * we display negative values?)
4732 * If you want to take out this check, be sure to fix
4733 * hfinfo_numeric_format() so that it does not assert out
4734 * when trying to construct a hexadecimal representation of
4737 if (hfinfo->display == BASE_HEX ||
4738 hfinfo->display == BASE_HEX_DEC ||
4739 hfinfo->display == BASE_DEC_HEX ||
4740 hfinfo->display == BASE_OCT)
4741 g_error("Field '%s' (%s) is signed (%s) but is being displayed unsigned (%s)\n",
4742 hfinfo->name, hfinfo->abbrev,
4743 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"),
4744 val_to_str(hfinfo->display, hf_display, "(Bit count: %d)"));
4750 if (hfinfo->strings == NULL) {
4751 /* Require integral types (other than frame number,
4752 * which is always displayed in decimal) to have a
4754 if (hfinfo->display == BASE_NONE)
4755 g_error("Field '%s' (%s) is an integral value (%s) without strings but is being displayed as BASE_NONE\n",
4756 hfinfo->name, hfinfo->abbrev,
4757 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"));
4762 if (hfinfo->display == BASE_NONE)
4763 g_error("Field '%s' (%s) is an integral value (%s) but is being displayed as BASE_NONE\n",
4764 hfinfo->name, hfinfo->abbrev,
4765 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"));
4770 if (hfinfo->display != BASE_NONE)
4771 g_error("Field '%s' (%s) is an %s but is being displayed as %s instead of BASE_NONE\n",
4772 hfinfo->name, hfinfo->abbrev,
4773 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"),
4774 val_to_str(hfinfo->display, hf_display, "(Bit count: %d)"));
4775 if (hfinfo->bitmask != 0)
4776 g_error("Field '%s' (%s) is an %s but has a bitmask\n",
4777 hfinfo->name, hfinfo->abbrev,
4778 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"));
4784 case FT_ABSOLUTE_TIME:
4785 if (!(hfinfo->display == ABSOLUTE_TIME_LOCAL ||
4786 hfinfo->display == ABSOLUTE_TIME_UTC ||
4787 hfinfo->display == ABSOLUTE_TIME_DOY_UTC))
4788 g_error("Field '%s' (%s) is a %s but is being displayed as %s instead of as a time\n",
4789 hfinfo->name, hfinfo->abbrev,
4790 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"),
4791 val_to_str(hfinfo->display, hf_display, "(Bit count: %d)"));
4792 if (hfinfo->bitmask != 0)
4793 g_error("Field '%s' (%s) is an %s but has a bitmask\n",
4794 hfinfo->name, hfinfo->abbrev,
4795 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"));
4799 if (hfinfo->display != BASE_NONE)
4800 g_error("Field '%s' (%s) is an %s but is being displayed as %s instead of BASE_NONE\n",
4801 hfinfo->name, hfinfo->abbrev,
4802 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"),
4803 val_to_str(hfinfo->display, hf_display, "(Bit count: %d)"));
4804 if (hfinfo->bitmask != 0)
4805 g_error("Field '%s' (%s) is an %s but has a bitmask\n",
4806 hfinfo->name, hfinfo->abbrev,
4807 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"));
4808 if (hfinfo->strings != NULL)
4809 g_error("Field '%s' (%s) is an %s but has a strings value\n",
4810 hfinfo->name, hfinfo->abbrev,
4811 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"));
4817 proto_register_field_init(header_field_info *hfinfo, const int parent)
4820 tmp_fld_check_assert(hfinfo);
4822 /* if this is a bitfield, compute bitshift */
4823 if (hfinfo->bitmask) {
4824 hfinfo->bitshift = wrs_count_bitshift(hfinfo->bitmask);
4827 hfinfo->parent = parent;
4828 hfinfo->same_name_next = NULL;
4829 hfinfo->same_name_prev = NULL;
4831 /* if we always add and never delete, then id == len - 1 is correct */
4832 if(gpa_hfinfo.len>=gpa_hfinfo.allocated_len){
4833 if(!gpa_hfinfo.hfi){
4834 gpa_hfinfo.allocated_len=100000;
4835 gpa_hfinfo.hfi=g_malloc(sizeof(header_field_info *)*100000);
4837 gpa_hfinfo.allocated_len+=1000;
4838 gpa_hfinfo.hfi=g_realloc(gpa_hfinfo.hfi, sizeof(header_field_info *)*gpa_hfinfo.allocated_len);
4841 gpa_hfinfo.hfi[gpa_hfinfo.len]=hfinfo;
4843 hfinfo->id = gpa_hfinfo.len - 1;
4845 /* if we have real names, enter this field in the name tree */
4846 if ((hfinfo->name[0] != 0) && (hfinfo->abbrev[0] != 0 )) {
4848 header_field_info *same_name_next_hfinfo;
4851 /* Check that the filter name (abbreviation) is legal;
4852 * it must contain only alphanumerics, '-', "_", and ".". */
4853 c = wrs_check_charset(fld_abbrev_chars, hfinfo->abbrev);
4855 fprintf(stderr, "OOPS: '%c' in '%s'\n", c, hfinfo->abbrev);
4856 DISSECTOR_ASSERT(!c);
4859 /* We allow multiple hfinfo's to be registered under the same
4860 * abbreviation. This was done for X.25, as, depending
4861 * on whether it's modulo-8 or modulo-128 operation,
4862 * some bitfield fields may be in different bits of
4863 * a byte, and we want to be able to refer to that field
4864 * with one name regardless of whether the packets
4865 * are modulo-8 or modulo-128 packets. */
4867 same_name_hfinfo = NULL;
4869 g_tree_insert(gpa_name_tree, (gpointer) (hfinfo->abbrev), hfinfo);
4870 /* GLIB 2.x - if it is already present
4871 * the previous hfinfo with the same name is saved
4872 * to same_name_hfinfo by value destroy callback */
4873 if (same_name_hfinfo) {
4874 /* There's already a field with this name.
4875 * Put it after that field in the list of
4876 * fields with this name, then allow the code
4877 * after this if{} block to replace the old
4878 * hfinfo with the new hfinfo in the GTree. Thus,
4879 * we end up with a linked-list of same-named hfinfo's,
4880 * with the root of the list being the hfinfo in the GTree */
4881 same_name_next_hfinfo =
4882 same_name_hfinfo->same_name_next;
4884 hfinfo->same_name_next = same_name_next_hfinfo;
4885 if (same_name_next_hfinfo)
4886 same_name_next_hfinfo->same_name_prev = hfinfo;
4888 same_name_hfinfo->same_name_next = hfinfo;
4889 hfinfo->same_name_prev = same_name_hfinfo;
4897 proto_register_subtree_array(gint *const *indices, const int num_indices)
4900 gint *const *ptr = indices;
4903 * If we've already allocated the array of tree types, expand
4904 * it; this lets plugins such as mate add tree types after
4905 * the initial startup. (If we haven't already allocated it,
4906 * we don't allocate it; on the first pass, we just assign
4907 * ett values and keep track of how many we've assigned, and
4908 * when we're finished registering all dissectors we allocate
4909 * the array, so that we do only one allocation rather than
4910 * wasting CPU time and memory by growing the array for each
4911 * dissector that registers ett values.)
4913 if (tree_is_expanded != NULL) {
4915 g_realloc(tree_is_expanded,
4916 (num_tree_types+num_indices)*sizeof (gboolean));
4917 memset(tree_is_expanded + num_tree_types, 0,
4918 num_indices*sizeof (gboolean));
4922 * Assign "num_indices" subtree numbers starting at "num_tree_types",
4923 * returning the indices through the pointers in the array whose
4924 * first element is pointed to by "indices", and update
4925 * "num_tree_types" appropriately.
4927 for (i = 0; i < num_indices; i++, ptr++, num_tree_types++) {
4929 /* g_error will terminate the program */
4930 g_error("register_subtree_array: subtree item type (ett_...) not -1 !"
4931 " This is a development error:"
4932 " Either the subtree item type has already been assigned or"
4933 " was not initialized to -1.");
4935 **ptr = num_tree_types;
4940 proto_item_fill_label(field_info *fi, gchar *label_str)
4942 header_field_info *hfinfo;
4948 guint32 n_addr; /* network-order IPv4 address */
4950 int ret; /*tmp return value */
4955 /* XXX: Check validity of hfinfo->type */
4959 hfinfo = fi->hfinfo;
4961 switch(hfinfo->type) {
4964 g_strlcpy(label_str, hfinfo->name, ITEM_LABEL_LENGTH);
4968 fill_label_boolean(fi, label_str);
4973 bytes = fvalue_get(&fi->value);
4975 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4976 "%s: %s", hfinfo->name,
4977 bytes_to_str(bytes, fvalue_length(&fi->value)));
4978 if (ret >= ITEM_LABEL_LENGTH) {
4979 /* Uh oh, we don't have enough room. Tell the
4980 * user that the field is truncated.
4982 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4983 "%s [truncated]: %s",
4985 bytes_to_str(bytes, fvalue_length(&fi->value)));
4989 g_snprintf(label_str, ITEM_LABEL_LENGTH, "%s: <MISSING>", hfinfo->name);
4993 /* Four types of integers to take care of:
4994 * Bitfield, with val_string
4995 * Bitfield, w/o val_string
4996 * Non-bitfield, with val_string
4997 * Non-bitfield, w/o val_string
5003 if (hfinfo->bitmask) {
5004 fill_label_bitfield(fi, label_str);
5006 fill_label_uint(fi, label_str);
5011 fill_label_uint(fi, label_str);
5015 fill_label_uint64(fi, label_str);
5022 DISSECTOR_ASSERT(!hfinfo->bitmask);
5023 fill_label_int(fi, label_str);
5027 fill_label_int64(fi, label_str);
5031 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5032 "%s: %." STRINGIFY(FLT_DIG) "f",
5033 hfinfo->name, fvalue_get_floating(&fi->value));
5037 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5038 "%s: %." STRINGIFY(DBL_DIG) "g",
5039 hfinfo->name, fvalue_get_floating(&fi->value));
5042 case FT_ABSOLUTE_TIME:
5043 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5044 "%s: %s", hfinfo->name,
5045 abs_time_to_str(fvalue_get(&fi->value), hfinfo->display, TRUE));
5048 case FT_RELATIVE_TIME:
5049 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5050 "%s: %s seconds", hfinfo->name,
5051 rel_time_to_secs_str(fvalue_get(&fi->value)));
5055 integer = fvalue_get_uinteger(&fi->value);
5056 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5057 "%s: %s (0x%08X)", hfinfo->name,
5058 get_ipxnet_name(integer), integer);
5062 bytes = fvalue_get(&fi->value);
5063 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5064 "%s: %s (%s)", hfinfo->name,
5065 get_ether_name(bytes),
5066 ether_to_str(bytes));
5070 ipv4 = fvalue_get(&fi->value);
5071 n_addr = ipv4_get_net_order_addr(ipv4);
5072 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5073 "%s: %s (%s)", hfinfo->name,
5074 get_hostname(n_addr),
5075 ip_to_str((guint8*)&n_addr));
5079 bytes = fvalue_get(&fi->value);
5080 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5081 "%s: %s (%s)", hfinfo->name,
5082 get_hostname6((struct e_in6_addr *)bytes),
5083 ip6_to_str((struct e_in6_addr*)bytes));
5087 guid = fvalue_get(&fi->value);
5088 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5089 "%s: %s", hfinfo->name,
5094 bytes = fvalue_get(&fi->value);
5095 name = oid_resolved_from_encoded(bytes, fvalue_length(&fi->value));
5097 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5098 "%s: %s (%s)", hfinfo->name,
5099 oid_encoded2string(bytes, fvalue_length(&fi->value)), name);
5101 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5102 "%s: %s", hfinfo->name,
5103 oid_encoded2string(bytes, fvalue_length(&fi->value)));
5110 case FT_UINT_STRING:
5111 bytes = fvalue_get(&fi->value);
5112 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
5113 "%s: %s", hfinfo->name,
5114 format_text(bytes, strlen(bytes)));
5115 if (ret >= ITEM_LABEL_LENGTH) {
5116 /* Uh oh, we don't have enough room. Tell the
5117 * user that the field is truncated.
5119 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5120 "%s [truncated]: %s", hfinfo->name,
5121 format_text(bytes, strlen(bytes)));
5126 g_error("hfinfo->type %d (%s) not handled\n",
5127 hfinfo->type, ftype_name(hfinfo->type));
5128 DISSECTOR_ASSERT_NOT_REACHED();
5134 fill_label_boolean(field_info *fi, gchar *label_str)
5136 char *p = label_str;
5137 int bitfield_byte_length = 0, bitwidth;
5138 guint32 unshifted_value;
5141 header_field_info *hfinfo = fi->hfinfo;
5142 const true_false_string *tfstring = (const true_false_string *)&tfs_true_false;
5144 if (hfinfo->strings) {
5145 tfstring = (const struct true_false_string*) hfinfo->strings;
5148 value = fvalue_get_uinteger(&fi->value);
5149 if (hfinfo->bitmask) {
5150 /* Figure out the bit width */
5151 bitwidth = hfinfo_bitwidth(hfinfo);
5154 unshifted_value = value;
5155 if (hfinfo->bitshift > 0) {
5156 unshifted_value <<= hfinfo->bitshift;
5159 /* Create the bitfield first */
5160 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
5161 bitfield_byte_length = (int) (p - label_str);
5164 /* Fill in the textual info */
5165 g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
5166 "%s: %s", hfinfo->name,
5167 value ? tfstring->true_string : tfstring->false_string);
5170 /* Fills data for bitfield ints with val_strings */
5172 fill_label_bitfield(field_info *fi, gchar *label_str)
5174 const char *format = NULL;
5176 int bitfield_byte_length, bitwidth;
5177 guint32 unshifted_value;
5180 header_field_info *hfinfo = fi->hfinfo;
5182 /* Figure out the bit width */
5183 bitwidth = hfinfo_bitwidth(hfinfo);
5186 unshifted_value = fvalue_get_uinteger(&fi->value);
5187 value = unshifted_value;
5188 if (hfinfo->bitshift > 0) {
5189 unshifted_value <<= hfinfo->bitshift;
5192 /* Create the bitfield first */
5193 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
5194 bitfield_byte_length = (int) (p - label_str);
5196 /* Fill in the textual info using stored (shifted) value */
5197 if (hfinfo->display == BASE_CUSTOM) {
5198 gchar tmp[ITEM_LABEL_LENGTH];
5199 custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hfinfo->strings;
5201 DISSECTOR_ASSERT(fmtfunc);
5202 fmtfunc(tmp, value);
5203 g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
5204 "%s: %s", hfinfo->name, tmp);
5206 else if (hfinfo->strings) {
5207 format = hfinfo_uint_vals_format(hfinfo);
5208 if (hfinfo->display & BASE_RANGE_STRING) {
5209 g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
5210 format, hfinfo->name,
5211 rval_to_str(value, hfinfo->strings, "Unknown"), value);
5212 } else if (hfinfo->display & BASE_EXT_STRING) {
5213 g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
5214 format, hfinfo->name,
5215 val_to_str_ext_const(value, (value_string_ext *) hfinfo->strings, "Unknown"), value);
5217 g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
5218 format, hfinfo->name,
5219 val_to_str_const(value, cVALS(hfinfo->strings), "Unknown"), value);
5223 format = hfinfo_uint_format(hfinfo);
5224 if (IS_BASE_DUAL(hfinfo->display)) {
5225 g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
5226 format, hfinfo->name, value, value);
5228 g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
5229 format, hfinfo->name, value);
5235 fill_label_uint(field_info *fi, gchar *label_str)
5237 const char *format = NULL;
5238 header_field_info *hfinfo = fi->hfinfo;
5241 value = fvalue_get_uinteger(&fi->value);
5243 /* Fill in the textual info */
5244 if (hfinfo->display == BASE_CUSTOM) {
5245 gchar tmp[ITEM_LABEL_LENGTH];
5246 custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hfinfo->strings;
5248 DISSECTOR_ASSERT(fmtfunc);
5249 fmtfunc(tmp, value);
5250 g_snprintf(label_str, ITEM_LABEL_LENGTH, "%s: %s", hfinfo->name, tmp);
5252 else if (hfinfo->strings) {
5253 format = hfinfo_uint_vals_format(hfinfo);
5254 if (hfinfo->display & BASE_RANGE_STRING) {
5255 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5256 format, hfinfo->name,
5257 rval_to_str(value, hfinfo->strings, "Unknown"), value);
5258 } else if (hfinfo->display & BASE_EXT_STRING) {
5259 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5260 format, hfinfo->name,
5261 val_to_str_ext_const(value, (value_string_ext *) hfinfo->strings, "Unknown"), value);
5263 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5264 format, hfinfo->name,
5265 val_to_str_const(value, cVALS(hfinfo->strings), "Unknown"), value);
5269 format = hfinfo_uint_format(hfinfo);
5270 if (IS_BASE_DUAL(hfinfo->display)) {
5271 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5272 format, hfinfo->name, value, value);
5274 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5275 format, hfinfo->name, value);
5281 fill_label_uint64(field_info *fi, gchar *label_str)
5283 const char *format = NULL;
5284 header_field_info *hfinfo = fi->hfinfo;
5287 /* Pick the proper format string */
5288 format = hfinfo_uint64_format(hfinfo);
5289 value = fvalue_get_integer64(&fi->value);
5291 /* Fill in the textual info */
5292 if (IS_BASE_DUAL(hfinfo->display)) {
5293 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5294 format, hfinfo->name, value, value);
5296 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5297 format, hfinfo->name, value);
5302 fill_label_int(field_info *fi, gchar *label_str)
5304 const char *format = NULL;
5305 header_field_info *hfinfo = fi->hfinfo;
5308 value = fvalue_get_sinteger(&fi->value);
5310 /* Fill in the textual info */
5311 if (hfinfo->display == BASE_CUSTOM) {
5312 gchar tmp[ITEM_LABEL_LENGTH];
5313 custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hfinfo->strings;
5315 DISSECTOR_ASSERT(fmtfunc);
5316 fmtfunc(tmp, value);
5317 g_snprintf(label_str, ITEM_LABEL_LENGTH, "%s: %s", hfinfo->name, tmp);
5319 else if (hfinfo->strings) {
5320 format = hfinfo_int_vals_format(hfinfo);
5321 if (hfinfo->display & BASE_RANGE_STRING) {
5322 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5323 format, hfinfo->name,
5324 rval_to_str(value, hfinfo->strings, "Unknown"), value);
5325 } else if (hfinfo->display & BASE_EXT_STRING) {
5326 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5327 format, hfinfo->name,
5328 val_to_str_ext_const(value, (value_string_ext *) hfinfo->strings, "Unknown"), value);
5330 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5331 format, hfinfo->name,
5332 val_to_str_const(value, cVALS(hfinfo->strings), "Unknown"), value);
5336 format = hfinfo_int_format(hfinfo);
5337 if (IS_BASE_DUAL(hfinfo->display)) {
5338 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5339 format, hfinfo->name, value, value);
5341 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5342 format, hfinfo->name, value);
5348 fill_label_int64(field_info *fi, gchar *label_str)
5350 const char *format = NULL;
5351 header_field_info *hfinfo = fi->hfinfo;
5354 /* Pick the proper format string */
5355 format = hfinfo_int64_format(hfinfo);
5356 value = fvalue_get_integer64(&fi->value);
5358 /* Fill in the textual info */
5359 if (IS_BASE_DUAL(hfinfo->display)) {
5360 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5361 format, hfinfo->name, value, value);
5363 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5364 format, hfinfo->name, value);
5369 hfinfo_bitwidth(const header_field_info *hfinfo)
5373 if (!hfinfo->bitmask) {
5377 switch(hfinfo->type) {
5395 bitwidth = hfinfo->display; /* hacky? :) */
5398 DISSECTOR_ASSERT_NOT_REACHED();
5405 hfinfo_uint_vals_format(const header_field_info *hfinfo)
5407 const char *format = NULL;
5409 /* Get the underlying BASE_ value */
5410 switch(hfinfo->display & BASE_DISPLAY_E_MASK) {
5416 format = "%s: %s (%u)";
5418 case BASE_OCT: /* I'm lazy */
5419 format = "%s: %s (%#o)";
5423 switch(hfinfo->type) {
5425 format = "%s: %s (0x%02x)";
5428 format = "%s: %s (0x%04x)";
5431 format = "%s: %s (0x%06x)";
5434 format = "%s: %s (0x%08x)";
5437 DISSECTOR_ASSERT_NOT_REACHED();
5442 DISSECTOR_ASSERT_NOT_REACHED();
5449 hfinfo_uint_format(const header_field_info *hfinfo)
5451 const char *format = NULL;
5453 /* Pick the proper format string */
5454 if (hfinfo->type == FT_FRAMENUM) {
5456 * Frame numbers are always displayed in decimal.
5460 switch(hfinfo->display) {
5465 switch(hfinfo->type) {
5467 format = "%s: %u (0x%02x)";
5470 format = "%s: %u (0x%04x)";
5473 format = "%s: %u (0x%06x)";
5476 format = "%s: %u (0x%08x)";
5479 DISSECTOR_ASSERT_NOT_REACHED();
5483 case BASE_OCT: /* I'm lazy */
5487 switch(hfinfo->type) {
5489 format = "%s: 0x%02x";
5492 format = "%s: 0x%04x";
5495 format = "%s: 0x%06x";
5498 format = "%s: 0x%08x";
5501 DISSECTOR_ASSERT_NOT_REACHED();
5506 switch(hfinfo->type) {
5508 format = "%s: 0x%02x (%u)";
5511 format = "%s: 0x%04x (%u)";
5514 format = "%s: 0x%06x (%u)";
5517 format = "%s: 0x%08x (%u)";
5520 DISSECTOR_ASSERT_NOT_REACHED();
5525 DISSECTOR_ASSERT_NOT_REACHED();
5533 hfinfo_uint_value_format(const header_field_info *hfinfo)
5535 const char *format = NULL;
5537 /* Pick the proper format string */
5538 if (hfinfo->type == FT_FRAMENUM) {
5540 * Frame numbers are always displayed in decimal.
5544 switch(hfinfo->display) {
5549 switch(hfinfo->type) {
5551 format = "%u (0x%02x)";
5554 format = "%u (0x%04x)";
5557 format = "%u (0x%06x)";
5560 format = "%u (0x%08x)";
5563 DISSECTOR_ASSERT_NOT_REACHED();
5571 switch(hfinfo->type) {
5585 DISSECTOR_ASSERT_NOT_REACHED();
5590 switch(hfinfo->type) {
5592 format = "0x%02x (%u)";
5595 format = "0x%04x (%u)";
5598 format = "0x%06x (%u)";
5601 format = "0x%08x (%u)";
5604 DISSECTOR_ASSERT_NOT_REACHED();
5609 DISSECTOR_ASSERT_NOT_REACHED();
5617 hfinfo_int_vals_format(const header_field_info *hfinfo)
5619 const char *format = NULL;
5621 /* Get the underlying BASE_ value */
5622 switch(hfinfo->display & BASE_DISPLAY_E_MASK) {
5628 format = "%s: %s (%d)";
5630 case BASE_OCT: /* I'm lazy */
5631 format = "%s: %s (%#o)";
5635 switch(hfinfo->type) {
5637 format = "%s: %s (0x%02x)";
5640 format = "%s: %s (0x%04x)";
5643 format = "%s: %s (0x%06x)";
5646 format = "%s: %s (0x%08x)";
5649 DISSECTOR_ASSERT_NOT_REACHED();
5654 DISSECTOR_ASSERT_NOT_REACHED();
5661 hfinfo_uint64_format(const header_field_info *hfinfo)
5663 const char *format = NULL;
5665 /* Pick the proper format string */
5666 switch(hfinfo->display) {
5668 format = "%s: %" G_GINT64_MODIFIER "u";
5671 format = "%s: %" G_GINT64_MODIFIER "u (%" G_GINT64_MODIFIER "x)";
5673 case BASE_OCT: /* I'm lazy */
5674 format = "%s: %#" G_GINT64_MODIFIER "o";
5677 format = "%s: 0x%016" G_GINT64_MODIFIER "x";
5680 format = "%s: 0x%016" G_GINT64_MODIFIER "x (%" G_GINT64_MODIFIER "u)";
5683 DISSECTOR_ASSERT_NOT_REACHED();
5690 hfinfo_int_format(const header_field_info *hfinfo)
5692 const char *format = NULL;
5694 /* Pick the proper format string */
5695 switch(hfinfo->display) {
5700 switch(hfinfo->type) {
5702 format = "%s: %d (0x%02x)";
5705 format = "%s: %d (0x%04x)";
5708 format = "%s: %d (0x%06x)";
5711 format = "%s: %d (0x%08x)";
5714 DISSECTOR_ASSERT_NOT_REACHED();
5718 case BASE_OCT: /* I'm lazy */
5722 switch(hfinfo->type) {
5724 format = "%s: 0x%02x";
5727 format = "%s: 0x%04x";
5730 format = "%s: 0x%06x";
5733 format = "%s: 0x%08x";
5736 DISSECTOR_ASSERT_NOT_REACHED();
5741 switch(hfinfo->type) {
5743 format = "%s: 0x%02x (%d)";
5746 format = "%s: 0x%04x (%d)";
5749 format = "%s: 0x%06x (%d)";
5752 format = "%s: 0x%08x (%d)";
5755 DISSECTOR_ASSERT_NOT_REACHED();
5760 DISSECTOR_ASSERT_NOT_REACHED();
5767 hfinfo_int_value_format(const header_field_info *hfinfo)
5769 const char *format = NULL;
5771 /* Pick the proper format string */
5772 switch(hfinfo->display) {
5777 switch(hfinfo->type) {
5779 format = "%d (0x%02x)";
5782 format = "%d (0x%04x)";
5785 format = "%d (0x%06x)";
5788 format = "%d (0x%08x)";
5791 DISSECTOR_ASSERT_NOT_REACHED();
5799 switch(hfinfo->type) {
5813 DISSECTOR_ASSERT_NOT_REACHED();
5818 switch(hfinfo->type) {
5820 format = "0x%02x (%d)";
5823 format = "0x%04x (%d)";
5826 format = "0x%06x (%d)";
5829 format = "0x%08x (%d)";
5832 DISSECTOR_ASSERT_NOT_REACHED();
5837 DISSECTOR_ASSERT_NOT_REACHED();
5844 hfinfo_int64_format(const header_field_info *hfinfo)
5846 const char *format = NULL;
5848 /* Pick the proper format string */
5849 switch(hfinfo->display) {
5851 format = "%s: %" G_GINT64_MODIFIER "d";
5854 format = "%s: %" G_GINT64_MODIFIER "d (%" G_GINT64_MODIFIER "x)";
5856 case BASE_OCT: /* I'm lazy */
5857 format = "%s: %#" G_GINT64_MODIFIER "o";
5860 format = "%s: 0x%016" G_GINT64_MODIFIER "x";
5863 format = "%s: 0x%016" G_GINT64_MODIFIER "x (%" G_GINT64_MODIFIER "d)";
5866 DISSECTOR_ASSERT_NOT_REACHED();
5873 proto_registrar_n(void)
5875 return gpa_hfinfo.len;
5879 proto_registrar_get_name(const int n)
5881 header_field_info *hfinfo;
5883 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
5884 return hfinfo->name;
5888 proto_registrar_get_abbrev(const int n)
5890 header_field_info *hfinfo;
5892 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
5893 return hfinfo->abbrev;
5897 proto_registrar_get_ftype(const int n)
5899 header_field_info *hfinfo;
5901 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
5902 return hfinfo->type;
5906 proto_registrar_get_parent(const int n)
5908 header_field_info *hfinfo;
5910 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
5911 return hfinfo->parent;
5915 proto_registrar_is_protocol(const int n)
5917 header_field_info *hfinfo;
5919 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
5920 return (hfinfo->parent == -1 ? TRUE : FALSE);
5923 /* Returns length of field in packet (not necessarily the length
5924 * in our internal representation, as in the case of IPv4).
5925 * 0 means undeterminable at time of registration
5926 * -1 means the field is not registered. */
5928 proto_registrar_get_length(const int n)
5930 header_field_info *hfinfo;
5932 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
5933 return ftype_length(hfinfo->type);
5936 /* Looks for a protocol or a field in a proto_tree. Returns TRUE if
5937 * it exists anywhere, or FALSE if it exists nowhere. */
5939 proto_check_for_protocol_or_field(const proto_tree* tree, const int id)
5941 GPtrArray *ptrs = proto_get_finfo_ptr_array(tree, id);
5946 else if (g_ptr_array_len(ptrs) > 0) {
5954 /* Return GPtrArray* of field_info pointers for all hfindex that appear in tree.
5955 * This only works if the hfindex was "primed" before the dissection
5956 * took place, as we just pass back the already-created GPtrArray*.
5957 * The caller should *not* free the GPtrArray*; proto_tree_free_node()
5960 proto_get_finfo_ptr_array(const proto_tree *tree, const int id)
5965 if (PTREE_DATA(tree)->interesting_hfids != NULL)
5966 return g_hash_table_lookup(PTREE_DATA(tree)->interesting_hfids,
5967 GINT_TO_POINTER(id));
5973 proto_tracking_interesting_fields(const proto_tree *tree)
5978 return (PTREE_DATA(tree)->interesting_hfids != NULL);
5981 /* Helper struct for proto_find_info() and proto_all_finfos() */
5987 /* Helper function for proto_find_info() */
5989 find_finfo(proto_node *node, gpointer data)
5991 field_info *fi = PNODE_FINFO(node);
5992 if (fi && fi->hfinfo) {
5993 if (fi->hfinfo->id == ((ffdata_t*)data)->id) {
5994 g_ptr_array_add(((ffdata_t*)data)->array, fi);
5998 /* Don't stop traversing. */
6002 /* Return GPtrArray* of field_info pointers for all hfindex that appear in a tree.
6003 * This works on any proto_tree, primed or unprimed, but actually searches
6004 * the tree, so it is slower than using proto_get_finfo_ptr_array on a primed tree.
6005 * The caller does need to free the returned GPtrArray with
6006 * g_ptr_array_free(<array>, TRUE).
6009 proto_find_finfo(proto_tree *tree, const int id)
6013 ffdata.array = g_ptr_array_new();
6016 proto_tree_traverse_pre_order(tree, find_finfo, &ffdata);
6018 return ffdata.array;
6021 /* Helper function for proto_all_finfos() */
6023 every_finfo(proto_node *node, gpointer data)
6025 field_info *fi = PNODE_FINFO(node);
6026 if (fi && fi->hfinfo) {
6027 g_ptr_array_add(((ffdata_t*)data)->array, fi);
6030 /* Don't stop traversing. */
6034 /* Return GPtrArray* of field_info pointers containing all hfindexes that appear in a tree. */
6036 proto_all_finfos(proto_tree *tree)
6040 ffdata.array = g_ptr_array_new();
6043 proto_tree_traverse_pre_order(tree, every_finfo, &ffdata);
6045 return ffdata.array;
6056 check_for_offset(proto_node *node, const gpointer data)
6058 field_info *fi = PNODE_FINFO(node);
6059 offset_search_t *offsearch = data;
6061 /* !fi == the top most container node which holds nothing */
6062 if (fi && !PROTO_ITEM_IS_HIDDEN(node) && fi->ds_tvb && offsearch->tvb == fi->ds_tvb) {
6063 if (offsearch->offset >= (guint) fi->start &&
6064 offsearch->offset < (guint) (fi->start + fi->length)) {
6066 offsearch->finfo = fi;
6067 return FALSE; /* keep traversing */
6070 return FALSE; /* keep traversing */
6073 /* Search a proto_tree backwards (from leaves to root) looking for the field
6074 * whose start/length occupies 'offset' */
6075 /* XXX - I couldn't find an easy way to search backwards, so I search
6076 * forwards, w/o stopping. Therefore, the last finfo I find will the be
6077 * the one I want to return to the user. This algorithm is inefficient
6078 * and could be re-done, but I'd have to handle all the children and
6079 * siblings of each node myself. When I have more time I'll do that.
6082 proto_find_field_from_offset(proto_tree *tree, guint offset, tvbuff_t *tvb)
6084 offset_search_t offsearch;
6086 offsearch.offset = offset;
6087 offsearch.finfo = NULL;
6088 offsearch.tvb = tvb;
6090 proto_tree_traverse_pre_order(tree, check_for_offset, &offsearch);
6092 return offsearch.finfo;
6095 /* Dumps the protocols in the registration database to stdout. An independent
6096 * program can take this output and format it into nice tables or HTML or
6099 * There is one record per line. The fields are tab-delimited.
6101 * Field 1 = protocol name
6102 * Field 2 = protocol short name
6103 * Field 3 = protocol filter name
6106 proto_registrar_dump_protocols(void)
6108 protocol_t *protocol;
6110 void *cookie = NULL;
6112 for (i = proto_get_first_protocol(&cookie); i != -1;
6113 i = proto_get_next_protocol(&cookie)) {
6114 protocol = find_protocol_by_id(i);
6115 printf("%s\t%s\t%s\n", protocol->name, protocol->short_name,
6116 protocol->filter_name);
6120 /* Dumps the value_strings, extended value string headers, range_strings
6121 * or true/false strings for fields that have them.
6122 * There is one record per line. Fields are tab-delimited.
6123 * There are four types of records: Value String, Extended Value String Header,
6124 * Range String and True/False String. The first field, 'V', 'E', 'R' or 'T', indicates
6125 * the type of record.
6127 * Note that a record will be generated only if the value_string,... is referenced
6128 * in a registered hfinfo entry.
6134 * Field 2 = Field abbreviation to which this value string corresponds
6135 * Field 3 = Integer value
6138 * Extended Value String Headers
6139 * -----------------------------
6141 * Field 2 = Field abbreviation to which this extended value string header corresponds
6142 * Field 3 = Extended Value String "Name"
6143 * Field 4 = Number of entries in the associated value_string array
6144 * Field 5 = Access Type: "Linear Search", "Binary Search", "Direct (indexed) Access"
6149 * Field 2 = Field abbreviation to which this range string corresponds
6150 * Field 3 = Integer value: lower bound
6151 * Field 4 = Integer value: upper bound
6154 * True/False Strings
6155 * ------------------
6157 * Field 2 = Field abbreviation to which this true/false string corresponds
6158 * Field 3 = True String
6159 * Field 4 = False String
6162 proto_registrar_dump_values(void)
6164 header_field_info *hfinfo, *parent_hfinfo;
6166 const value_string *vals;
6167 const range_string *range;
6168 const true_false_string *tfs;
6170 len = gpa_hfinfo.len;
6171 for (i = 0; i < len ; i++) {
6172 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
6174 if (hfinfo->id == hf_text_only) {
6178 /* ignore protocols */
6179 if (proto_registrar_is_protocol(i)) {
6182 /* process header fields */
6185 * If this field isn't at the head of the list of
6186 * fields with this name, skip this field - all
6187 * fields with the same name are really just versions
6188 * of the same field stored in different bits, and
6189 * should have the same type/radix/value list, and
6190 * just differ in their bit masks. (If a field isn't
6191 * a bitfield, but can be, say, 1 or 2 bytes long,
6192 * it can just be made FT_UINT16, meaning the
6193 * *maximum* length is 2 bytes, and be used
6196 if (hfinfo->same_name_prev != NULL)
6199 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
6205 if ((hfinfo->display & BASE_DISPLAY_E_MASK) != BASE_CUSTOM &&
6206 (hfinfo->type == FT_UINT8 ||
6207 hfinfo->type == FT_UINT16 ||
6208 hfinfo->type == FT_UINT24 ||
6209 hfinfo->type == FT_UINT32 ||
6210 hfinfo->type == FT_UINT64 ||
6211 hfinfo->type == FT_INT8 ||
6212 hfinfo->type == FT_INT16 ||
6213 hfinfo->type == FT_INT24 ||
6214 hfinfo->type == FT_INT32 ||
6215 hfinfo->type == FT_INT64)) {
6217 if (hfinfo->display & BASE_EXT_STRING) {
6218 vals = VALUE_STRING_EXT_VS_P((value_string_ext *)hfinfo->strings);
6219 } else if ((hfinfo->display & BASE_RANGE_STRING) == 0) {
6220 vals = hfinfo->strings;
6222 range = hfinfo->strings;
6225 else if (hfinfo->type == FT_BOOLEAN) {
6226 tfs = hfinfo->strings;
6229 /* Print value strings? */
6231 if (hfinfo->display & BASE_EXT_STRING) {
6232 value_string_ext *vse_p = (value_string_ext *)hfinfo->strings;
6233 if (!value_string_ext_validate(vse_p)) {
6234 g_warning("Invalid value_string_ext ptr for: %s", hfinfo->abbrev);
6237 match_strval_ext(0, vse_p); /* "prime" the extended value_string */
6238 printf("E\t%s\t%d\t%s\t%s\n",
6240 VALUE_STRING_EXT_VS_NUM_ENTRIES(vse_p),
6241 VALUE_STRING_EXT_VS_NAME(vse_p),
6242 value_string_ext_match_type_str(vse_p));
6245 while (vals[vi].strptr) {
6246 /* Print in the proper base */
6247 if (hfinfo->display == BASE_HEX) {
6248 printf("V\t%s\t0x%x\t%s\n",
6254 printf("V\t%s\t%u\t%s\n",
6263 /* print range strings? */
6266 while (range[vi].strptr) {
6267 /* Print in the proper base */
6268 if ((hfinfo->display & BASE_DISPLAY_E_MASK) == BASE_HEX) {
6269 printf("R\t%s\t0x%x\t0x%x\t%s\n",
6271 range[vi].value_min,
6272 range[vi].value_max,
6276 printf("R\t%s\t%u\t%u\t%s\n",
6278 range[vi].value_min,
6279 range[vi].value_max,
6286 /* Print true/false strings? */
6288 printf("T\t%s\t%s\t%s\n", hfinfo->abbrev,
6289 tfs->true_string, tfs->false_string);
6295 /* Dumps the contents of the registration database to stdout. An independent
6296 * program can take this output and format it into nice tables or HTML or
6299 * There is one record per line. Each record is either a protocol or a header
6300 * field, differentiated by the first field. The fields are tab-delimited.
6305 * Field 2 = descriptive protocol name
6306 * Field 3 = protocol abbreviation
6312 * Field 2 = descriptive field name
6313 * Field 3 = field abbreviation
6314 * Field 4 = type ( textual representation of the the ftenum type )
6315 * Field 5 = parent protocol abbreviation
6316 * Field 6 = blurb describing field
6320 * Field 2 = descriptive field name
6321 * Field 3 = field abbreviation
6322 * Field 4 = type ( textual representation of the the ftenum type )
6323 * Field 5 = parent protocol abbreviation
6324 * Field 6 = blurb describing field
6325 * Field 7 = base for display (for integer types); "parent bitfield width" for FT_BOOLEAN
6326 * Field 8 = blurb describing field (yes, apparently we repeated this accidentally)
6330 * Field 2 = descriptive field name
6331 * Field 3 = field abbreviation
6332 * Field 4 = type ( textual representation of the the ftenum type )
6333 * Field 5 = parent protocol abbreviation
6334 * Field 6 = blurb describing field
6335 * Field 7 = base for display (for integer types); "parent bitfield width" for FT_BOOLEAN
6336 * Field 8 = bitmask: format: hex: 0x....
6339 proto_registrar_dump_fields(const int format)
6341 header_field_info *hfinfo, *parent_hfinfo;
6343 const char *enum_name;
6344 const char *base_name;
6348 len = gpa_hfinfo.len;
6349 for (i = 0; i < len ; i++) {
6350 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
6353 * Skip the pseudo-field for "proto_tree_add_text()" since
6354 * we don't want it in the list of filterable fields.
6356 if (hfinfo->id == hf_text_only)
6359 /* format for protocols */
6360 if (proto_registrar_is_protocol(i)) {
6361 printf("P\t%s\t%s\n", hfinfo->name, hfinfo->abbrev);
6363 /* format for header fields */
6366 * If this field isn't at the head of the list of
6367 * fields with this name, skip this field - all
6368 * fields with the same name are really just versions
6369 * of the same field stored in different bits, and
6370 * should have the same type/radix/value list, and
6371 * just differ in their bit masks. (If a field isn't
6372 * a bitfield, but can be, say, 1 or 2 bytes long,
6373 * it can just be made FT_UINT16, meaning the
6374 * *maximum* length is 2 bytes, and be used
6377 if (hfinfo->same_name_prev != NULL)
6380 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
6382 enum_name = ftype_name(hfinfo->type);
6386 if (hfinfo->type == FT_UINT8 ||
6387 hfinfo->type == FT_UINT16 ||
6388 hfinfo->type == FT_UINT24 ||
6389 hfinfo->type == FT_UINT32 ||
6390 hfinfo->type == FT_UINT64 ||
6391 hfinfo->type == FT_INT8 ||
6392 hfinfo->type == FT_INT16 ||
6393 hfinfo->type == FT_INT24 ||
6394 hfinfo->type == FT_INT32 ||
6395 hfinfo->type == FT_INT64) {
6398 switch(hfinfo->display & BASE_DISPLAY_E_MASK) {
6400 base_name = "BASE_NONE";
6403 base_name = "BASE_DEC";
6406 base_name = "BASE_HEX";
6409 base_name = "BASE_OCT";
6412 base_name = "BASE_DEC_HEX";
6415 base_name = "BASE_HEX_DEC";
6418 base_name = "BASE_CUSTOM";
6424 } else if (hfinfo->type == FT_BOOLEAN) {
6425 /* For FT_BOOLEAN: 'display' can be "parent bitfield width" */
6426 g_snprintf(width, sizeof(width), "%d", hfinfo->display);
6431 blurb = hfinfo->blurb;
6434 else if (strlen(blurb) == 0)
6437 printf("F\t%s\t%s\t%s\t%s\t%s\n",
6438 hfinfo->name, hfinfo->abbrev, enum_name,
6439 parent_hfinfo->abbrev, blurb);
6441 else if (format == 2) {
6442 printf("F\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n",
6443 hfinfo->name, hfinfo->abbrev, enum_name,
6444 parent_hfinfo->abbrev, blurb,
6447 else if (format == 3) {
6448 printf("F\t%s\t%s\t%s\t%s\t%s\t%s\t0x%x\n",
6449 hfinfo->name, hfinfo->abbrev, enum_name,
6450 parent_hfinfo->abbrev, blurb,
6451 base_name, hfinfo->bitmask);
6454 g_assert_not_reached();
6461 hfinfo_numeric_format(const header_field_info *hfinfo)
6463 const char *format = NULL;
6465 /* Pick the proper format string */
6466 if (hfinfo->type == FT_FRAMENUM) {
6468 * Frame numbers are always displayed in decimal.
6470 format = "%s == %u";
6472 /* Get the underlying BASE_ value */
6473 switch(hfinfo->display & BASE_DISPLAY_E_MASK) {
6476 case BASE_OCT: /* I'm lazy */
6478 switch(hfinfo->type) {
6483 format = "%s == %u";
6486 format = "%s == %" G_GINT64_MODIFIER "u";
6492 format = "%s == %d";
6495 format = "%s == %" G_GINT64_MODIFIER "d";
6498 DISSECTOR_ASSERT_NOT_REACHED();
6504 switch(hfinfo->type) {
6506 format = "%s == 0x%02x";
6509 format = "%s == 0x%04x";
6512 format = "%s == 0x%06x";
6515 format = "%s == 0x%08x";
6518 format = "%s == 0x%016" G_GINT64_MODIFIER "x";
6521 DISSECTOR_ASSERT_NOT_REACHED();
6526 DISSECTOR_ASSERT_NOT_REACHED();
6534 hfinfo_numeric_value_format(const header_field_info *hfinfo)
6536 const char *format = NULL;
6538 /* Pick the proper format string */
6539 if (hfinfo->type == FT_FRAMENUM) {
6541 * Frame numbers are always displayed in decimal.
6545 /* Get the underlying BASE_ value */
6546 switch(hfinfo->display & BASE_DISPLAY_E_MASK) {
6549 case BASE_OCT: /* I'm lazy */
6551 switch(hfinfo->type) {
6559 format = "%" G_GINT64_MODIFIER "u";
6568 format = "%" G_GINT64_MODIFIER "d";
6571 DISSECTOR_ASSERT_NOT_REACHED();
6577 switch(hfinfo->type) {
6591 format = "0x%016" G_GINT64_MODIFIER "x";
6594 DISSECTOR_ASSERT_NOT_REACHED();
6599 DISSECTOR_ASSERT_NOT_REACHED();
6606 /* This function indicates whether it's possible to construct a
6607 * "match selected" display filter string for the specified field,
6608 * returns an indication of whether it's possible, and, if it's
6609 * possible and "filter" is non-null, constructs the filter and
6610 * sets "*filter" to point to it.
6611 * You do not need to [g_]free() this string since it will be automatically
6612 * freed once the next packet is dissected.
6615 construct_match_selected_string(field_info *finfo, epan_dissect_t *edt,
6618 header_field_info *hfinfo;
6624 gint start, length, length_remaining;
6626 gchar is_signed_num = FALSE;
6628 hfinfo = finfo->hfinfo;
6629 DISSECTOR_ASSERT(hfinfo);
6630 abbrev_len = (int) strlen(hfinfo->abbrev);
6632 if (hfinfo->strings && (hfinfo->display & BASE_DISPLAY_E_MASK) == BASE_NONE) {
6633 const gchar *str = NULL;
6635 switch(hfinfo->type) {
6641 if (hfinfo->display & BASE_RANGE_STRING) {
6642 str = match_strrval(fvalue_get_sinteger(&finfo->value), hfinfo->strings);
6643 } else if (hfinfo->display & BASE_EXT_STRING) {
6644 str = match_strval_ext(fvalue_get_sinteger(&finfo->value), hfinfo->strings);
6646 str = match_strval(fvalue_get_sinteger(&finfo->value), hfinfo->strings);
6654 if (hfinfo->display & BASE_RANGE_STRING) {
6655 str = match_strrval(fvalue_get_uinteger(&finfo->value), hfinfo->strings);
6656 } else if (hfinfo->display & BASE_EXT_STRING) {
6657 str = match_strval_ext(fvalue_get_uinteger(&finfo->value), hfinfo->strings);
6659 str = match_strval(fvalue_get_uinteger(&finfo->value), hfinfo->strings);
6667 if (str != NULL && filter != NULL) {
6668 *filter = ep_strdup_printf("%s == \"%s\"", hfinfo->abbrev, str);
6674 * XXX - we can't use the "val_to_string_repr" and "string_repr_len"
6675 * functions for FT_UINT and FT_INT types, as we choose the base in
6676 * the string expression based on the display base of the field.
6678 * Note that the base does matter, as this is also used for
6679 * the protocolinfo tap.
6681 * It might be nice to use them in "proto_item_fill_label()"
6682 * as well, although, there, you'd have to deal with the base
6683 * *and* with resolved values for addresses.
6685 * Perhaps we need two different val_to_string routines, one
6686 * to generate items for display filters and one to generate
6687 * strings for display, and pass to both of them the
6688 * "display" and "strings" values in the header_field_info
6689 * structure for the field, so they can get the base and,
6690 * if the field is Boolean or an enumerated integer type,
6691 * the tables used to generate human-readable values.
6693 switch(hfinfo->type) {
6699 is_signed_num = TRUE;
6705 if (filter != NULL) {
6706 format = hfinfo_numeric_format(hfinfo);
6708 *filter = ep_strdup_printf(format,
6710 fvalue_get_sinteger(&finfo->value));
6712 *filter = ep_strdup_printf(format,
6714 fvalue_get_uinteger(&finfo->value));
6720 DISSECTOR_ASSERT(!is_signed_num);
6721 if (filter != NULL) {
6722 format = hfinfo_numeric_format(hfinfo);
6723 *filter = ep_strdup_printf(format,
6725 fvalue_get_uinteger(&finfo->value));
6731 if (filter != NULL) {
6732 format = hfinfo_numeric_format(hfinfo);
6733 *filter = ep_strdup_printf(format,
6735 fvalue_get_integer64(&finfo->value));
6741 *filter = ep_strdup(finfo->hfinfo->abbrev);
6746 * If the length is 0, just match the name of the
6749 * (Also check for negative values, just in case,
6750 * as we'll cast it to an unsigned value later.)
6752 length = finfo->length;
6755 *filter = ep_strdup(finfo->hfinfo->abbrev);
6762 * This doesn't have a value, so we'd match
6763 * on the raw bytes at this address.
6765 * Should we be allowed to access to the raw bytes?
6766 * If "edt" is NULL, the answer is "no".
6772 * Is this field part of the raw frame tvbuff?
6773 * If not, we can't use "frame[N:M]" to match
6776 * XXX - should this be frame-relative, or
6777 * protocol-relative?
6779 * XXX - does this fallback for non-registered
6780 * fields even make sense?
6782 if (finfo->ds_tvb != edt->tvb)
6783 return FALSE; /* you lose */
6786 * Don't go past the end of that tvbuff.
6788 length_remaining = tvb_length_remaining(finfo->ds_tvb, finfo->start);
6789 if (length > length_remaining)
6790 length = length_remaining;
6794 if (filter != NULL) {
6795 start = finfo->start;
6796 buf_len = 32 + length * 3;
6797 *filter = ep_alloc0(buf_len);
6800 ptr += g_snprintf(ptr, (gulong) (buf_len-(ptr-*filter)),
6801 "frame[%d:%d] == ", finfo->start, length);
6802 for (i=0;i<length; i++) {
6803 c = tvb_get_guint8(finfo->ds_tvb, start);
6806 ptr += g_snprintf(ptr, (gulong) (buf_len-(ptr-*filter)), "%02x", c);
6809 ptr += g_snprintf(ptr, (gulong) (buf_len-(ptr-*filter)), ":%02x", c);
6816 /* FT_PCRE never appears as a type for a registered field. It is
6817 * only used internally. */
6818 DISSECTOR_ASSERT_NOT_REACHED();
6821 /* By default, use the fvalue's "to_string_repr" method. */
6823 /* Figure out the string length needed.
6824 * The ft_repr length.
6825 * 4 bytes for " == ".
6826 * 1 byte for trailing NUL.
6828 if (filter != NULL) {
6829 dfilter_len = fvalue_string_repr_len(&finfo->value,
6831 dfilter_len += abbrev_len + 4 + 1;
6832 *filter = ep_alloc0(dfilter_len);
6834 /* Create the string */
6835 g_snprintf(*filter, dfilter_len, "%s == ",
6837 fvalue_to_string_repr(&finfo->value,
6839 &(*filter)[abbrev_len + 4]);
6848 * Returns TRUE if we can do a "match selected" on the field, FALSE
6852 proto_can_match_selected(field_info *finfo, epan_dissect_t *edt)
6854 return construct_match_selected_string(finfo, edt, NULL);
6857 /* This function attempts to construct a "match selected" display filter
6858 * string for the specified field; if it can do so, it returns a pointer
6859 * to the string, otherwise it returns NULL.
6861 * The string is allocated with packet lifetime scope.
6862 * You do not need to [g_]free() this string since it will be automatically
6863 * freed once the next packet is dissected.
6866 proto_construct_match_selected_string(field_info *finfo, epan_dissect_t *edt)
6870 if (!construct_match_selected_string(finfo, edt, &filter))
6875 /* This function is common code for both proto_tree_add_bitmask() and
6876 * proto_tree_add_bitmask_text() functions.
6879 proto_item_add_bitmask_tree(proto_item *item, tvbuff_t *tvb, const int offset,
6880 const int len, const gint ett, const int **fields,
6881 const gboolean little_endian, const int flags,
6884 guint32 value = 0, tmpval;
6885 proto_tree *tree = NULL;
6886 header_field_info *hf;
6891 value = tvb_get_guint8(tvb, offset);
6894 value = little_endian ? tvb_get_letohs(tvb, offset) :
6895 tvb_get_ntohs(tvb, offset);
6898 value = little_endian ? tvb_get_letoh24(tvb, offset) :
6899 tvb_get_ntoh24(tvb, offset);
6902 value = little_endian ? tvb_get_letohl(tvb, offset) :
6903 tvb_get_ntohl(tvb, offset);
6906 g_assert_not_reached();
6909 tree = proto_item_add_subtree(item, ett);
6911 proto_tree_add_item(tree, **fields, tvb, offset, len, little_endian);
6912 if (flags & BMT_NO_APPEND) {
6916 hf = proto_registrar_get_nth(**fields);
6917 DISSECTOR_ASSERT(hf->bitmask != 0);
6918 tmpval = (value & hf->bitmask) >> hf->bitshift;
6929 DISSECTOR_ASSERT(len == ftype_length(hf->type));
6931 if (hf->display == BASE_CUSTOM) {
6932 gchar lbl[ITEM_LABEL_LENGTH];
6933 custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hf->strings;
6935 DISSECTOR_ASSERT(fmtfunc);
6936 fmtfunc(lbl, tmpval);
6937 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
6941 else if (hf->strings) {
6942 if (hf->display & BASE_RANGE_STRING) {
6943 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
6944 hf->name, rval_to_str(tmpval, hf->strings, "Unknown"));
6945 } else if (hf->display & BASE_EXT_STRING) {
6946 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
6947 hf->name, val_to_str_ext_const(tmpval, (value_string_ext *) (hf->strings), "Unknown"));
6949 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
6950 hf->name, val_to_str_const(tmpval, cVALS(hf->strings), "Unknown"));
6954 else if (!(flags & BMT_NO_INT)) {
6956 proto_item_append_text(item, ", ");
6959 fmt = IS_FT_INT(hf->type) ? hfinfo_int_format(hf) : hfinfo_uint_format(hf);
6960 if (IS_BASE_DUAL(hf->display)) {
6961 proto_item_append_text(item, fmt, hf->name, tmpval, tmpval);
6963 proto_item_append_text(item, fmt, hf->name, tmpval);
6970 DISSECTOR_ASSERT(len * 8 == hf->display);
6972 if (hf->strings && !(flags & BMT_NO_TFS)) {
6973 /* If we have true/false strings, emit full - otherwise messages
6975 const struct true_false_string *tfs =
6976 (const struct true_false_string *)hf->strings;
6979 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
6980 hf->name, tfs->true_string);
6982 } else if (!(flags & BMT_NO_FALSE)) {
6983 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
6984 hf->name, tfs->false_string);
6987 } else if (hf->bitmask & value) {
6988 /* If the flag is set, show the name */
6989 proto_item_append_text(item, "%s%s", first ? "" : ", ", hf->name);
6994 g_assert_not_reached();
7003 /* This function will dissect a sequence of bytes that describe a
7005 * hf_hdr is a 8/16/24/32 bit integer that describes the bitmask to be dissected.
7006 * This field will form an expansion under which the individual fields of the
7007 * bitmask is dissected and displayed.
7008 * This field must be of the type FT_[U]INT{8|16|24|32}.
7010 * fields is an array of pointers to int that lists all the fields of the
7011 * bitmask. These fields can be either of the type FT_BOOLEAN for flags
7012 * or another integer of the same type/size as hf_hdr with a mask specified.
7013 * This array is terminated by a NULL entry.
7015 * FT_BOOLEAN bits that are set to 1 will have the name added to the expansion.
7016 * FT_integer fields that have a value_string attached will have the
7017 * matched string displayed on the expansion line.
7020 proto_tree_add_bitmask(proto_tree *parent_tree, tvbuff_t *tvb,
7021 const guint offset, const int hf_hdr,
7022 const gint ett, const int **fields,
7023 const gboolean little_endian)
7025 proto_item *item = NULL;
7026 header_field_info *hf;
7029 hf = proto_registrar_get_nth(hf_hdr);
7030 DISSECTOR_ASSERT(IS_FT_INT(hf->type) || IS_FT_UINT(hf->type));
7031 len = ftype_length(hf->type);
7034 item = proto_tree_add_item(parent_tree, hf_hdr, tvb, offset, len, little_endian);
7035 proto_item_add_bitmask_tree(item, tvb, offset, len, ett, fields, little_endian,
7036 BMT_NO_INT|BMT_NO_TFS, FALSE);
7042 /* The same as proto_tree_add_bitmask(), but using an arbitrary text as a top-level item */
7044 proto_tree_add_bitmask_text(proto_tree *parent_tree, tvbuff_t *tvb,
7045 const guint offset, const guint len,
7046 const char *name, const char *fallback,
7047 const gint ett, const int **fields,
7048 const gboolean little_endian, const int flags)
7050 proto_item *item = NULL;
7053 item = proto_tree_add_text(parent_tree, tvb, offset, len, "%s", name ? name : "");
7054 if (proto_item_add_bitmask_tree(item, tvb, offset, len, ett, fields, little_endian,
7055 flags, TRUE) && fallback) {
7056 /* Still at first item - append 'fallback' text if any */
7057 proto_item_append_text(item, "%s", fallback);
7065 proto_tree_add_bits_item(proto_tree *tree, const int hf_index, tvbuff_t *tvb,
7066 const gint bit_offset, const gint no_of_bits,
7067 const gboolean little_endian)
7069 header_field_info *hfinfo;
7071 TRY_TO_FAKE_THIS_ITEM(tree, hf_index, hfinfo);
7073 return proto_tree_add_bits_ret_val(tree, hf_index, tvb, bit_offset, no_of_bits, NULL, little_endian);
7077 * This function will dissect a sequence of bits that does not need to be byte aligned; the bits
7078 * set will be shown in the tree as ..10 10.. and the integer value returned if return_value is set.
7079 * Offset should be given in bits from the start of the tvb.
7083 _proto_tree_add_bits_ret_val(proto_tree *tree, const int hf_index, tvbuff_t *tvb,
7084 const gint bit_offset, const gint no_of_bits,
7085 guint64 *return_value, const gboolean little_endian)
7087 const char *format = NULL;
7092 header_field_info *hf_field;
7094 const true_false_string *tfstring;
7096 /* We can't fake it just yet. We have to fill in the 'return_value' parameter */
7097 PROTO_REGISTRAR_GET_NTH(hf_index, hf_field);
7099 if(hf_field -> bitmask != 0) {
7100 REPORT_DISSECTOR_BUG(ep_strdup_printf("Incompatible use of proto_tree_add_bits_ret_val with field '%s' (%s) with bitmask != 0",
7101 hf_field->abbrev, hf_field->name));
7104 DISSECTOR_ASSERT(bit_offset >= 0);
7105 DISSECTOR_ASSERT(no_of_bits > 0);
7107 /* Byte align offset */
7108 offset = bit_offset>>3;
7111 * Calculate the number of octets used to hold the bits
7113 tot_no_bits = ((bit_offset&0x7)+no_of_bits);
7114 length = tot_no_bits>>3;
7115 /* If we are using part of the next octet, increase length by 1 */
7116 if (tot_no_bits & 0x07)
7119 if (no_of_bits < 9){
7120 value = tvb_get_bits8(tvb, bit_offset, no_of_bits);
7121 }else if(no_of_bits < 17){
7122 value = tvb_get_bits16(tvb, bit_offset, no_of_bits, little_endian);
7123 }else if(no_of_bits < 33){
7124 value = tvb_get_bits32(tvb, bit_offset, no_of_bits, little_endian);
7125 }else if(no_of_bits < 65){
7126 value = tvb_get_bits64(tvb, bit_offset, no_of_bits, little_endian);
7128 DISSECTOR_ASSERT_NOT_REACHED();
7133 *return_value=value;
7136 /* Coast clear. Try and fake it */
7137 TRY_TO_FAKE_THIS_ITEM(tree, hf_index, hf_field);
7139 str = decode_bits_in_field(bit_offset, no_of_bits, value);
7142 strcat(str,hf_field->name);
7144 switch(hf_field->type){
7147 tfstring = (const true_false_string *) &tfs_true_false;
7148 if (hf_field->strings)
7149 tfstring = (const true_false_string *) hf_field->strings;
7150 return proto_tree_add_boolean_format(tree, hf_index, tvb, offset, length, (guint32)value,
7153 (guint32)value ? tfstring->true_string : tfstring->false_string);
7160 /* 1 - 32 bits field */
7161 if (hf_field->strings) {
7162 return proto_tree_add_uint_format(tree, hf_index, tvb, offset, length, (guint32)value,
7164 str, (hf_field->display & BASE_RANGE_STRING) ?
7165 rval_to_str((guint32)value, hf_field->strings, "Unknown ") :
7166 (hf_field->display & BASE_EXT_STRING) ?
7167 val_to_str_ext_const((guint32)value, (value_string_ext *) (hf_field->strings), "Unknown ") :
7168 val_to_str_const((guint32)value, cVALS(hf_field->strings), "Unknown "),
7172 /* Pick the proper format string */
7173 format = hfinfo_uint_format(hf_field);
7174 if (IS_BASE_DUAL(hf_field->display)) {
7175 return proto_tree_add_uint_format(tree, hf_index, tvb, offset, length, (guint32)value,
7176 format, str, (guint32)value, (guint32)value);
7178 return proto_tree_add_uint_format(tree, hf_index, tvb, offset, length, (guint32)value,
7179 format, str, (guint32)value);
7184 /* Pick the proper format string */
7185 format = hfinfo_uint64_format(hf_field);
7186 if (IS_BASE_DUAL(hf_field->display)) {
7187 return proto_tree_add_uint64_format(tree, hf_index, tvb, offset, length, value,
7188 format, str, value, value);
7190 return proto_tree_add_uint64_format(tree, hf_index, tvb, offset, length, value,
7191 format, str, value);
7196 DISSECTOR_ASSERT_NOT_REACHED();
7203 proto_tree_add_bits_ret_val(proto_tree *tree, const int hf_index, tvbuff_t *tvb,
7204 const gint bit_offset, const gint no_of_bits,
7205 guint64 *return_value, const gboolean little_endian)
7209 if ((item = _proto_tree_add_bits_ret_val(tree, hf_index, tvb, bit_offset, no_of_bits, return_value, little_endian))) {
7210 FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_OFFSET(bit_offset));
7211 FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_SIZE(no_of_bits));
7217 _proto_tree_add_bits_format_value(proto_tree *tree, const int hf_index,
7218 tvbuff_t *tvb, const gint bit_offset,
7219 const gint no_of_bits, void *value_ptr,
7226 header_field_info *hf_field;
7229 /* We do not have to return a value, try to fake it as soon as possible */
7230 TRY_TO_FAKE_THIS_ITEM(tree, hf_index, hf_field);
7232 if(hf_field -> bitmask != 0) {
7233 REPORT_DISSECTOR_BUG(ep_strdup_printf("Incompatible use of proto_tree_add_bits_ret_val with field '%s' (%s) with bitmask != 0",
7234 hf_field->abbrev, hf_field->name));
7237 DISSECTOR_ASSERT(bit_offset >= 0);
7238 DISSECTOR_ASSERT(no_of_bits > 0);
7240 /* Byte align offset */
7241 offset = bit_offset>>3;
7244 * Calculate the number of octets used to hold the bits
7246 tot_no_bits = ((bit_offset&0x7)+no_of_bits);
7247 length = tot_no_bits>>3;
7248 /* If we are using part of the next octet, increase length by 1 */
7249 if (tot_no_bits & 0x07)
7252 if (no_of_bits < 9){
7253 value = tvb_get_bits8(tvb, bit_offset, no_of_bits);
7254 }else if(no_of_bits < 17){
7255 value = tvb_get_bits16(tvb, bit_offset, no_of_bits, FALSE);
7256 }else if(no_of_bits < 33){
7257 value = tvb_get_bits32(tvb, bit_offset, no_of_bits, FALSE);
7258 }else if(no_of_bits < 65){
7259 value = tvb_get_bits64(tvb, bit_offset, no_of_bits, FALSE);
7261 DISSECTOR_ASSERT_NOT_REACHED();
7265 str = decode_bits_in_field(bit_offset, no_of_bits, value);
7268 strcat(str,hf_field->name);
7271 * This function does not receive an actual value but a dimensionless pointer to that value.
7272 * For this reason, the type of the header field is examined in order to determine
7273 * what kind of value we should read from this address.
7274 * The caller of this function must make sure that for the specific header field type the address of
7275 * a compatible value is provided.
7277 switch(hf_field->type){
7279 return proto_tree_add_boolean_format(tree, hf_index, tvb, offset, length, *(guint32 *)value_ptr,
7280 "%s: %s", str, value_str);
7287 return proto_tree_add_uint_format(tree, hf_index, tvb, offset, length, *(guint32 *)value_ptr,
7288 "%s: %s", str, value_str);
7292 return proto_tree_add_uint64_format(tree, hf_index, tvb, offset, length, *(guint64 *)value_ptr,
7293 "%s: %s", str, value_str);
7300 return proto_tree_add_int_format(tree, hf_index, tvb, offset, length, *(gint32 *)value_ptr,
7301 "%s: %s", str, value_str);
7305 return proto_tree_add_float_format(tree, hf_index, tvb, offset, length, *(float *)value_ptr,
7306 "%s: %s", str, value_str);
7310 DISSECTOR_ASSERT_NOT_REACHED();
7317 proto_tree_add_bits_format_value(proto_tree *tree, const int hf_index,
7318 tvbuff_t *tvb, const gint bit_offset,
7319 const gint no_of_bits, void *value_ptr,
7324 if ((item = _proto_tree_add_bits_format_value(tree, hf_index, tvb, bit_offset, no_of_bits, value_ptr, value_str))) {
7325 FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_OFFSET(bit_offset));
7326 FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_SIZE(no_of_bits));
7331 #define CREATE_VALUE_STRING(dst,format,ap) \
7332 va_start(ap,format); \
7333 dst = ep_strdup_vprintf(format, ap); \
7337 proto_tree_add_uint_bits_format_value(proto_tree *tree, const int hf_index,
7338 tvbuff_t *tvb, const gint bit_offset,
7339 const gint no_of_bits, guint32 value,
7340 const char *format, ...)
7344 header_field_info *hf_field;
7346 TRY_TO_FAKE_THIS_ITEM(tree, hf_index, hf_field);
7348 switch(hf_field->type){
7356 DISSECTOR_ASSERT_NOT_REACHED();
7361 CREATE_VALUE_STRING(dst,format,ap);
7363 return proto_tree_add_bits_format_value(tree, hf_index, tvb, bit_offset, no_of_bits, &value, dst);
7367 proto_tree_add_float_bits_format_value(proto_tree *tree, const int hf_index,
7368 tvbuff_t *tvb, const gint bit_offset,
7369 const gint no_of_bits, float value,
7370 const char *format, ...)
7374 header_field_info *hf_field;
7376 TRY_TO_FAKE_THIS_ITEM(tree, hf_index, hf_field);
7378 DISSECTOR_ASSERT(hf_field->type == FT_FLOAT);
7380 CREATE_VALUE_STRING(dst,format,ap);
7382 return proto_tree_add_bits_format_value(tree, hf_index, tvb, bit_offset, no_of_bits, &value, dst);
7386 proto_tree_add_int_bits_format_value(proto_tree *tree, const int hf_index,
7387 tvbuff_t *tvb, const gint bit_offset,
7388 const gint no_of_bits, gint32 value,
7389 const char *format, ...)
7393 header_field_info *hf_field;
7395 TRY_TO_FAKE_THIS_ITEM(tree, hf_index, hf_field);
7397 switch(hf_field->type){
7405 DISSECTOR_ASSERT_NOT_REACHED();
7410 CREATE_VALUE_STRING(dst,format,ap);
7412 return proto_tree_add_bits_format_value(tree, hf_index, tvb, bit_offset, no_of_bits, &value, dst);
7416 proto_tree_add_boolean_bits_format_value(proto_tree *tree, const int hf_index,
7417 tvbuff_t *tvb, const gint bit_offset,
7418 const gint no_of_bits, guint32 value,
7419 const char *format, ...)
7423 header_field_info *hf_field;
7425 TRY_TO_FAKE_THIS_ITEM(tree, hf_index, hf_field);
7427 DISSECTOR_ASSERT(hf_field->type == FT_BOOLEAN);
7429 CREATE_VALUE_STRING(dst,format,ap);
7431 return proto_tree_add_bits_format_value(tree, hf_index, tvb, bit_offset, no_of_bits, &value, dst);
7435 proto_check_field_name(const gchar *field_name)
7437 return wrs_check_charset(fld_abbrev_chars, field_name);