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.
34 #include "ptvcursor.h"
36 #include "addr_resolv.h"
40 #include "epan_dissect.h"
45 #include "asm_utils.h"
46 #include "column-utils.h"
50 #include "wspython/wspy_register.h"
52 #define SUBTREE_ONCE_ALLOCATION_NUMBER 8
53 #define SUBTREE_MAX_LEVELS 256
54 /* Throw an exception if we exceed this many tree items. */
55 /* XXX - This should probably be a preference */
56 #define MAX_TREE_ITEMS (1 * 1000 * 1000)
59 typedef struct __subtree_lvl {
66 subtree_lvl *pushed_tree;
67 guint8 pushed_tree_index;
68 guint8 pushed_tree_max;
74 /* Candidates for assembler */
76 wrs_count_bitshift(const guint32 bitmask)
80 while ((bitmask & (1 << bitshift)) == 0)
85 #define cVALS(x) (const value_string*)(x)
87 /** See inlined comments.
88 @param tree the tree to append this item to
89 @param hfindex field index
90 @param hfinfo header_field
91 @return the header field matching 'hfinfo' */
92 #define TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo) \
93 /* If this item is not referenced we dont have to do much work \
94 at all but we should still return a node so that field items \
95 below this node (think proto_item_add_subtree()) will still \
96 have somewhere to attach to or else filtering will not work \
97 (they would be ignored since tree would be NULL). \
98 DONT try to fake a node where PTREE_FINFO(tree) is NULL \
99 since dissectors that want to do proto_item_set_len() or \
100 other operations that dereference this would crash. \
101 We fake FT_PROTOCOL unless some clients have requested us \
106 PTREE_DATA(tree)->count++; \
107 if (PTREE_DATA(tree)->count > MAX_TREE_ITEMS) { \
108 if (getenv("WIRESHARK_ABORT_ON_DISSECTOR_BUG") != NULL) \
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 */
130 #define TRY_TO_FAKE_THIS_REPR(tree, pi) \
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 */ \
140 proto_tree_free_node(proto_node *node, gpointer data);
142 static void fill_label_boolean(field_info *fi, gchar *label_str);
143 static void fill_label_uint(field_info *fi, gchar *label_str);
144 static void fill_label_uint64(field_info *fi, gchar *label_str);
145 static void fill_label_bitfield(field_info *fi, gchar *label_str);
146 static void fill_label_int(field_info *fi, gchar *label_str);
147 static void fill_label_int64(field_info *fi, gchar *label_str);
149 static const char* hfinfo_uint_vals_format(const header_field_info *hfinfo);
150 static const char* hfinfo_uint_format(const header_field_info *hfinfo);
151 static const char* hfinfo_uint_value_format(const header_field_info *hfinfo);
152 static const char* hfinfo_uint64_format(const header_field_info *hfinfo);
153 static const char* hfinfo_int_vals_format(const header_field_info *hfinfo);
154 static const char* hfinfo_int_format(const header_field_info *hfinfo);
155 static const char* hfinfo_int_value_format(const header_field_info *hfinfo);
156 static const char* hfinfo_int64_format(const header_field_info *hfinfo);
157 static const char* hfinfo_numeric_value_format(const header_field_info *hfinfo);
160 proto_tree_add_node(proto_tree *tree, field_info *fi);
162 static header_field_info *
163 get_hfi_and_length(int hfindex, tvbuff_t *tvb, const gint start, gint *length,
167 new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
168 const gint start, const gint item_length);
171 alloc_field_info(proto_tree *tree, int hfindex, tvbuff_t *tvb,
172 const gint start, gint *length);
175 proto_tree_add_pi(proto_tree *tree, int hfindex, tvbuff_t *tvb,
176 gint start, gint *length, field_info **pfi);
179 proto_tree_set_representation_value(proto_item *pi, const char *format, va_list ap);
181 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap);
184 proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb);
186 proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length);
188 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length);
190 proto_tree_set_time(field_info *fi, nstime_t *value_ptr);
192 proto_tree_set_string(field_info *fi, const char* value);
194 proto_tree_set_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length, gint encoding);
196 proto_tree_set_ax25(field_info *fi, const guint8* value);
198 proto_tree_set_ax25_tvb(field_info *fi, tvbuff_t *tvb, gint start);
200 proto_tree_set_ether(field_info *fi, const guint8* value);
202 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start);
204 proto_tree_set_ipxnet(field_info *fi, guint32 value);
206 proto_tree_set_ipv4(field_info *fi, guint32 value);
208 proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr);
210 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
212 proto_tree_set_guid(field_info *fi, const e_guid_t *value_ptr);
214 proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, gint start, const guint encoding);
216 proto_tree_set_oid(field_info *fi, const guint8* value_ptr, gint length);
218 proto_tree_set_oid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
220 proto_tree_set_boolean(field_info *fi, guint32 value);
222 proto_tree_set_float(field_info *fi, float value);
224 proto_tree_set_double(field_info *fi, double value);
226 proto_tree_set_uint(field_info *fi, guint32 value);
228 proto_tree_set_int(field_info *fi, gint32 value);
230 proto_tree_set_uint64(field_info *fi, guint64 value);
232 proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start, guint length, const guint encoding);
234 proto_tree_set_eui64(field_info *fi, const guint64 value);
236 proto_tree_set_eui64_tvb(field_info *fi, tvbuff_t *tvb, gint start, const guint encoding);
238 proto_item_add_bitmask_tree(proto_item *item, tvbuff_t *tvb, const int offset,
239 const int len, const gint ett, const gint **fields,
240 const guint encoding, const int flags,
243 static int proto_register_field_init(header_field_info *hfinfo, const int parent);
245 /* special-case header field used within proto.c */
246 int hf_text_only = -1;
248 /* Structure for information about a protocol */
250 const char *name; /* long description */
251 const char *short_name; /* short description */
252 const char *filter_name; /* name of this protocol in filters */
253 int proto_id; /* field ID for this protocol */
254 GList *fields; /* fields for this protocol */
255 GList *last_field; /* pointer to end of list of fields */
256 gboolean is_enabled; /* TRUE if protocol is enabled */
257 gboolean can_toggle; /* TRUE if is_enabled can be changed */
258 gboolean is_private; /* TRUE is protocol is private */
261 /* List of all protocols */
262 static GList *protocols = NULL;
264 #define INITIAL_NUM_PROTOCOL_HFINFO 1500
266 /* Contains information about a field when a dissector calls
267 * proto_tree_add_item. */
268 static struct ws_memory_slab field_info_slab =
269 WS_MEMORY_SLAB_INIT(field_info, 128);
271 #define FIELD_INFO_NEW(fi) \
272 fi = sl_alloc(&field_info_slab)
273 #define FIELD_INFO_FREE(fi) \
274 sl_free(&field_info_slab, fi)
276 /* Contains the space for proto_nodes. */
277 static struct ws_memory_slab proto_node_slab =
278 WS_MEMORY_SLAB_INIT(proto_node, 128);
280 #define PROTO_NODE_NEW(node) \
281 node = sl_alloc(&proto_node_slab); \
282 node->first_child = NULL; \
283 node->last_child = NULL; \
286 #define PROTO_NODE_FREE(node) \
287 sl_free(&proto_node_slab, node)
289 /* String space for protocol and field items for the GUI */
290 static struct ws_memory_slab item_label_slab =
291 WS_MEMORY_SLAB_INIT(item_label_t, 128);
293 #define ITEM_LABEL_NEW(il) \
294 il = sl_alloc(&item_label_slab);
295 #define ITEM_LABEL_FREE(il) \
296 sl_free(&item_label_slab, il);
298 #define PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo) \
299 DISSECTOR_ASSERT((guint)hfindex < gpa_hfinfo.len); \
300 hfinfo = gpa_hfinfo.hfi[hfindex];
302 /* List which stores protocols and fields that have been registered */
303 typedef struct _gpa_hfinfo_t {
305 guint32 allocated_len;
306 header_field_info **hfi;
308 gpa_hfinfo_t gpa_hfinfo;
310 /* Balanced tree of abbreviations and IDs */
311 static GTree *gpa_name_tree = NULL;
312 static header_field_info *same_name_hfinfo;
314 static void save_same_name_hfinfo(gpointer data)
316 same_name_hfinfo = (header_field_info*)data;
319 /* Points to the first element of an array of Booleans, indexed by
320 a subtree item type; that array element is TRUE if subtrees of
321 an item of that type are to be expanded. */
322 gboolean *tree_is_expanded;
324 /* Number of elements in that array. */
327 /* Name hashtables for fast detection of duplicate names */
328 static GHashTable* proto_names = NULL;
329 static GHashTable* proto_short_names = NULL;
330 static GHashTable* proto_filter_names = NULL;
333 proto_compare_name(gconstpointer p1_arg, gconstpointer p2_arg)
335 const protocol_t *p1 = p1_arg;
336 const protocol_t *p2 = p2_arg;
338 return g_ascii_strcasecmp(p1->short_name, p2->short_name);
342 /* initialize data structures and register protocols and fields */
344 proto_init(void (register_all_protocols_func)(register_cb cb, gpointer client_data),
345 void (register_all_handoffs_func)(register_cb cb, gpointer client_data),
347 gpointer client_data)
349 static hf_register_info hf[] = {
351 { "Text item", "text", FT_NONE, BASE_NONE, NULL, 0x0,
357 proto_names = g_hash_table_new_full(g_int_hash, g_int_equal, g_free, NULL);
358 proto_short_names = g_hash_table_new(wrs_str_hash, g_str_equal);
359 proto_filter_names = g_hash_table_new(wrs_str_hash, g_str_equal);
362 gpa_hfinfo.allocated_len = 0;
363 gpa_hfinfo.hfi = NULL;
364 gpa_name_tree = g_tree_new_full(wrs_strcmp_with_data, NULL, NULL, save_same_name_hfinfo);
366 /* Initialize the ftype subsystem */
369 /* Register one special-case FT_TEXT_ONLY field for use when
370 converting wireshark to new-style proto_tree. These fields
371 are merely strings on the GUI tree; they are not filterable */
372 proto_register_field_array(-1, hf, array_length(hf));
374 /* Have each built-in dissector register its protocols, fields,
375 dissector tables, and dissectors to be called through a
376 handle, and do whatever one-time initialization it needs to
378 register_all_protocols_func(cb, client_data);
380 /* Now scan for python protocols */
382 (*cb)(RA_PYTHON_REGISTER, NULL, client_data);
383 register_all_py_protocols_func();
387 /* Now scan for plugins and load all the ones we find, calling
388 their register routines to do the stuff described above. */
390 (*cb)(RA_PLUGIN_REGISTER, NULL, client_data);
392 register_all_plugin_registrations();
395 /* Now call the "handoff registration" routines of all built-in
396 dissectors; those routines register the dissector in other
397 dissectors' handoff tables, and fetch any dissector handles
399 register_all_handoffs_func(cb, client_data);
402 /* Now do the same with python dissectors */
404 (*cb)(RA_PYTHON_HANDOFF, NULL, client_data);
405 register_all_py_handoffs_func();
409 /* Now do the same with plugins. */
411 (*cb)(RA_PLUGIN_HANDOFF, NULL, client_data);
412 register_all_plugin_handoffs();
415 /* sort the protocols by protocol name */
416 protocols = g_list_sort(protocols, proto_compare_name);
418 /* We've assigned all the subtree type values; allocate the array
419 for them, and zero it out. */
420 tree_is_expanded = g_new0(gboolean, num_tree_types);
426 /* Free the abbrev/ID GTree */
428 g_tree_destroy(gpa_name_tree);
429 gpa_name_tree = NULL;
433 protocol_t *protocol = protocols->data;
434 header_field_info *hfinfo;
435 PROTO_REGISTRAR_GET_NTH(protocol->proto_id, hfinfo);
436 DISSECTOR_ASSERT(protocol->proto_id == hfinfo->id);
438 g_slice_free(header_field_info, hfinfo);
439 g_list_free(protocol->fields);
440 protocols = g_list_remove(protocols, protocol);
445 g_hash_table_destroy(proto_names);
449 if (proto_short_names) {
450 g_hash_table_destroy(proto_short_names);
451 proto_short_names = NULL;
454 if (proto_filter_names) {
455 g_hash_table_destroy(proto_filter_names);
456 proto_filter_names = NULL;
459 if (gpa_hfinfo.allocated_len) {
461 gpa_hfinfo.allocated_len = 0;
462 g_free(gpa_hfinfo.hfi);
463 gpa_hfinfo.hfi = NULL;
465 g_free(tree_is_expanded);
466 tree_is_expanded = NULL;
470 proto_tree_traverse_pre_order(proto_tree *tree, proto_tree_traverse_func func,
473 proto_node *pnode = tree;
477 if (func(pnode, data))
480 child = pnode->first_child;
481 while (child != NULL) {
483 * The routine we call might modify the child, e.g. by
484 * freeing it, so we get the child's successor before
485 * calling that routine.
488 child = current->next;
489 if (proto_tree_traverse_pre_order((proto_tree *)current, func, data))
497 proto_tree_traverse_post_order(proto_tree *tree, proto_tree_traverse_func func,
500 proto_node *pnode = tree;
504 child = pnode->first_child;
505 while (child != NULL) {
507 * The routine we call might modify the child, e.g. by
508 * freeing it, so we get the child's successor before
509 * calling that routine.
512 child = current->next;
513 if (proto_tree_traverse_post_order((proto_tree *)current, func, data))
516 if (func(pnode, data))
523 proto_tree_children_foreach(proto_tree *tree, proto_tree_foreach_func func,
526 proto_node *node = tree;
529 node = node->first_child;
530 while (node != NULL) {
532 node = current->next;
533 func((proto_tree *)current, data);
537 /* frees the resources that the dissection a proto_tree uses */
539 proto_tree_free(proto_tree *tree)
541 proto_tree_traverse_post_order(tree, proto_tree_free_node, NULL);
545 free_GPtrArray_value(gpointer key, gpointer value, gpointer user_data _U_)
547 GPtrArray *ptrs = value;
548 gint hfid = (gint)(long)key;
549 header_field_info *hfinfo;
551 PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
552 if (hfinfo->ref_type != HF_REF_TYPE_NONE) {
553 /* when a field is referenced by a filter this also
554 affects the refcount for the parent protocol so we need
555 to adjust the refcount for the parent as well
557 if (hfinfo->parent != -1) {
558 header_field_info *parent_hfinfo;
559 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
560 parent_hfinfo->ref_type = HF_REF_TYPE_NONE;
562 hfinfo->ref_type = HF_REF_TYPE_NONE;
565 g_ptr_array_free(ptrs, TRUE);
569 free_node_tree_data(tree_data_t *tree_data)
571 if (tree_data->interesting_hfids) {
572 /* Free all the GPtrArray's in the interesting_hfids hash. */
573 g_hash_table_foreach(tree_data->interesting_hfids,
574 free_GPtrArray_value, NULL);
576 /* And then destroy the hash. */
577 g_hash_table_destroy(tree_data->interesting_hfids);
579 if (tree_data->fi_tmp)
580 FIELD_INFO_FREE(tree_data->fi_tmp);
582 /* And finally the tree_data_t itself. */
586 #define FREE_NODE_FIELD_INFO(finfo) \
588 ITEM_LABEL_FREE(finfo->rep); \
590 FVALUE_CLEANUP(&finfo->value); \
591 FIELD_INFO_FREE(finfo);
594 proto_tree_free_node(proto_node *node, gpointer data _U_)
596 field_info *finfo = PNODE_FINFO(node);
598 proto_node *parent = node->parent;
602 /* This is the root node. Destroy the per-tree data.
603 * There is no field_info to destroy. */
604 if (PTREE_DATA(node))
605 free_node_tree_data(PTREE_DATA(node));
608 /* This is a child node. Don't free the per-tree data, but
609 * do free the field_info data. */
610 FREE_NODE_FIELD_INFO(finfo);
614 /* NOTE: This code is required when this function is used to free individual
615 * nodes only. Current use is for the destruction of complete trees, so the
616 * inconsistancies have no ill effect.
618 /* Remove node from parent */
620 proto_item *prev_item = NULL;
621 if (parent->first_child == node) {
622 parent->first_child = node->next;
624 /* find previous and change its next */
625 for (prev_item = parent->first_child; prev_item; prev_item = prev_item->next) {
626 if (prev_item->next == node) {
630 DISSECTOR_ASSERT(prev_item);
631 prev_item->next = node->next;
633 /* fix last_child if required */
634 if (parent->last_child == node) {
635 parent->last_child = prev_item;
638 DISSECTOR_ASSERT(node->first_child == NULL && node->last_child == NULL);
640 /* Free the proto_node. */
641 PROTO_NODE_FREE(node);
643 return FALSE; /* FALSE = do not end traversal of protocol tree */
646 /* Is the parsing being done for a visible proto_tree or an invisible one?
647 * By setting this correctly, the proto_tree creation is sped up by not
648 * having to call g_vsnprintf and copy strings around.
651 proto_tree_set_visible(proto_tree *tree, gboolean visible)
653 gboolean old_visible = PTREE_DATA(tree)->visible;
655 PTREE_DATA(tree)->visible = visible;
661 proto_tree_set_fake_protocols(proto_tree *tree, gboolean fake_protocols)
663 PTREE_DATA(tree)->fake_protocols = fake_protocols;
666 /* Assume dissector set only its protocol fields.
667 This function is called by dissectors and allows the speeding up of filtering
668 in wireshark; if this function returns FALSE it is safe to reset tree to NULL
669 and thus skip calling most of the expensive proto_tree_add_...()
671 If the tree is visible we implicitly assume the field is referenced.
674 proto_field_is_referenced(proto_tree *tree, int proto_id)
676 register header_field_info *hfinfo;
682 if (PTREE_DATA(tree)->visible)
685 PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
686 if (hfinfo->ref_type != HF_REF_TYPE_NONE)
689 if (hfinfo->type == FT_PROTOCOL && !PTREE_DATA(tree)->fake_protocols)
696 /* Finds a record in the hf_info_records array by id. */
698 proto_registrar_get_nth(guint hfindex)
700 register header_field_info *hfinfo;
702 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
707 /* Prefix initialization
708 * this allows for a dissector to register a display filter name prefix
709 * so that it can delay the initialization of the hf array as long as
713 /* compute a hash for the part before the dot of a display filter */
715 prefix_hash (gconstpointer key) {
716 /* end the string at the dot and compute its hash */
717 gchar* copy = ep_strdup(key);
727 return g_str_hash(copy);
730 /* are both strings equal up to the end or the dot? */
732 prefix_equal (gconstpointer ap, gconstpointer bp) {
740 if ( (ac == '.' || ac == '\0') && (bc == '.' || bc == '\0') ) return TRUE;
742 if ( (ac == '.' || ac == '\0') && ! (bc == '.' || bc == '\0') ) return FALSE;
743 if ( (bc == '.' || bc == '\0') && ! (ac == '.' || ac == '\0') ) return FALSE;
745 if (ac != bc) return FALSE;
752 /* indexed by prefix, contains initializers */
753 static GHashTable* prefixes = NULL;
756 /* Register a new prefix for "delayed" initialization of field arrays */
758 proto_register_prefix(const char *prefix, prefix_initializer_t pi ) {
760 prefixes = g_hash_table_new(prefix_hash, prefix_equal);
763 g_hash_table_insert(prefixes, (gpointer)prefix, pi);
766 /* helper to call all prefix initializers */
768 initialize_prefix(gpointer k, gpointer v, gpointer u _U_) {
769 ((prefix_initializer_t)v)(k);
773 /** Initialize every remaining uninitialized prefix. */
775 proto_initialize_all_prefixes(void) {
776 g_hash_table_foreach_remove(prefixes, initialize_prefix, NULL);
779 /* Finds a record in the hf_info_records array by name.
780 * If it fails to find it in the already registered fields,
781 * it tries to find and call an initializer in the prefixes
782 * table and if so it looks again.
785 proto_registrar_get_byname(const char *field_name)
787 header_field_info *hfinfo;
788 prefix_initializer_t pi;
793 hfinfo = g_tree_lookup(gpa_name_tree, field_name);
801 if ((pi = g_hash_table_lookup(prefixes, field_name) ) != NULL) {
803 g_hash_table_remove(prefixes, field_name);
808 return g_tree_lookup(gpa_name_tree, field_name);
813 ptvcursor_new_subtree_levels(ptvcursor_t *ptvc)
815 subtree_lvl *pushed_tree;
817 DISSECTOR_ASSERT(ptvc->pushed_tree_max <= SUBTREE_MAX_LEVELS-SUBTREE_ONCE_ALLOCATION_NUMBER);
818 ptvc->pushed_tree_max += SUBTREE_ONCE_ALLOCATION_NUMBER;
820 pushed_tree = ep_alloc(sizeof(subtree_lvl) * ptvc->pushed_tree_max);
821 DISSECTOR_ASSERT(pushed_tree != NULL);
822 if (ptvc->pushed_tree)
823 memcpy(pushed_tree, ptvc->pushed_tree, ptvc->pushed_tree_max - SUBTREE_ONCE_ALLOCATION_NUMBER);
824 ptvc->pushed_tree = pushed_tree;
828 ptvcursor_free_subtree_levels(ptvcursor_t *ptvc)
830 ptvc->pushed_tree = NULL;
831 ptvc->pushed_tree_max = 0;
832 DISSECTOR_ASSERT(ptvc->pushed_tree_index == 0);
833 ptvc->pushed_tree_index = 0;
836 /* Allocates an initializes a ptvcursor_t with 3 variables:
837 * proto_tree, tvbuff, and offset. */
839 ptvcursor_new(proto_tree *tree, tvbuff_t *tvb, gint offset)
843 ptvc = ep_alloc(sizeof(ptvcursor_t));
846 ptvc->offset = offset;
847 ptvc->pushed_tree = NULL;
848 ptvc->pushed_tree_max = 0;
849 ptvc->pushed_tree_index = 0;
854 /* Frees memory for ptvcursor_t, but nothing deeper than that. */
856 ptvcursor_free(ptvcursor_t *ptvc)
858 ptvcursor_free_subtree_levels(ptvc);
862 /* Returns tvbuff. */
864 ptvcursor_tvbuff(ptvcursor_t *ptvc)
869 /* Returns current offset. */
871 ptvcursor_current_offset(ptvcursor_t *ptvc)
877 ptvcursor_tree(ptvcursor_t *ptvc)
886 ptvcursor_set_tree(ptvcursor_t *ptvc, proto_tree *tree)
891 /* creates a subtree, sets it as the working tree and pushes the old working tree */
893 ptvcursor_push_subtree(ptvcursor_t *ptvc, proto_item *it, gint ett_subtree)
895 subtree_lvl *subtree;
896 if (ptvc->pushed_tree_index >= ptvc->pushed_tree_max)
897 ptvcursor_new_subtree_levels(ptvc);
899 subtree = ptvc->pushed_tree + ptvc->pushed_tree_index;
900 subtree->tree = ptvc->tree;
902 ptvc->pushed_tree_index++;
903 return ptvcursor_set_subtree(ptvc, it, ett_subtree);
908 ptvcursor_pop_subtree(ptvcursor_t *ptvc)
910 subtree_lvl *subtree;
912 if (ptvc->pushed_tree_index <= 0)
915 ptvc->pushed_tree_index--;
916 subtree = ptvc->pushed_tree + ptvc->pushed_tree_index;
917 if (subtree->it != NULL)
918 proto_item_set_len(subtree->it, ptvcursor_current_offset(ptvc) - subtree->cursor_offset);
920 ptvc->tree = subtree->tree;
923 /* saves the current tvb offset and the item in the current subtree level */
925 ptvcursor_subtree_set_item(ptvcursor_t *ptvc, proto_item *it)
927 subtree_lvl *subtree;
929 DISSECTOR_ASSERT(ptvc->pushed_tree_index > 0);
931 subtree = ptvc->pushed_tree + ptvc->pushed_tree_index - 1;
933 subtree->cursor_offset = ptvcursor_current_offset(ptvc);
936 /* Creates a subtree and adds it to the cursor as the working tree but does not
937 * save the old working tree */
939 ptvcursor_set_subtree(ptvcursor_t *ptvc, proto_item *it, gint ett_subtree)
941 ptvc->tree = proto_item_add_subtree(it, ett_subtree);
946 ptvcursor_add_subtree_item(ptvcursor_t *ptvc, proto_item *it, gint ett_subtree, gint length)
948 ptvcursor_push_subtree(ptvc, it, ett_subtree);
949 if (length == SUBTREE_UNDEFINED_LENGTH)
950 ptvcursor_subtree_set_item(ptvc, it);
951 return ptvcursor_tree(ptvc);
954 /* Add an item to the tree and create a subtree
955 * If the length is unknown, length may be defined as SUBTREE_UNDEFINED_LENGTH.
956 * In this case, when the subtree will be closed, the parent item length will
957 * be equal to the advancement of the cursor since the creation of the subtree.
960 ptvcursor_add_with_subtree(ptvcursor_t *ptvc, int hfindex, gint length,
961 const guint encoding, gint ett_subtree)
965 it = ptvcursor_add_no_advance(ptvc, hfindex, length, encoding);
966 return ptvcursor_add_subtree_item(ptvc, it, ett_subtree, length);
970 proto_tree_add_text_node(proto_tree *tree, tvbuff_t *tvb, gint start, gint length);
972 /* Add a text node to the tree and create a subtree
973 * If the length is unknown, length may be defined as SUBTREE_UNDEFINED_LENGTH.
974 * In this case, when the subtree will be closed, the item length will be equal
975 * to the advancement of the cursor since the creation of the subtree.
978 ptvcursor_add_text_with_subtree(ptvcursor_t *ptvc, gint length,
979 gint ett_subtree, const char *format, ...)
983 header_field_info *hfinfo;
986 tree = ptvcursor_tree(ptvc);
988 TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
990 pi = proto_tree_add_text_node(tree, ptvcursor_tvbuff(ptvc),
991 ptvcursor_current_offset(ptvc), length);
993 TRY_TO_FAKE_THIS_REPR(tree, pi);
995 va_start(ap, format);
996 proto_tree_set_representation(pi, format, ap);
999 return ptvcursor_add_subtree_item(ptvc, pi, ett_subtree, length);
1002 /* Add a text-only node, leaving it to our caller to fill the text in */
1004 proto_tree_add_text_node(proto_tree *tree, tvbuff_t *tvb, gint start, gint length)
1008 pi = proto_tree_add_pi(tree, hf_text_only, tvb, start, &length, NULL);
1013 /* Add a text-only node to the proto_tree */
1015 proto_tree_add_text(proto_tree *tree, tvbuff_t *tvb, gint start, gint length,
1016 const char *format, ...)
1020 header_field_info *hfinfo;
1022 TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
1024 pi = proto_tree_add_text_node(tree, tvb, start, length);
1026 TRY_TO_FAKE_THIS_REPR(tree, pi);
1028 va_start(ap, format);
1029 proto_tree_set_representation(pi, format, ap);
1035 /* Add a text-only node to the proto_tree (va_list version) */
1037 proto_tree_add_text_valist(proto_tree *tree, tvbuff_t *tvb, gint start,
1038 gint length, const char *format, va_list ap)
1041 header_field_info *hfinfo;
1043 TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
1045 pi = proto_tree_add_text_node(tree, tvb, start, length);
1047 TRY_TO_FAKE_THIS_REPR(tree, pi);
1049 proto_tree_set_representation(pi, format, ap);
1054 /* Add a text-only node for debugging purposes. The caller doesn't need
1055 * to worry about tvbuff, start, or length. Debug message gets sent to
1058 proto_tree_add_debug_text(proto_tree *tree, const char *format, ...)
1063 pi = proto_tree_add_text_node(tree, NULL, 0, 0);
1066 va_start(ap, format);
1067 proto_tree_set_representation(pi, format, ap);
1070 va_start(ap, format);
1071 vprintf(format, ap);
1078 /* We could probably get away with changing is_error to a minimum length value. */
1080 report_type_length_mismatch(proto_tree *tree, const gchar *descr, int length, gboolean is_error) {
1081 tree_data_t *tree_data = PTREE_DATA(tree);
1082 field_info *fi_save = tree_data->fi_tmp;
1084 /* Keep the current item from getting freed by proto_tree_new_item. */
1085 tree_data->fi_tmp = NULL;
1087 expert_add_info_format(NULL, tree, PI_MALFORMED, is_error ? PI_ERROR : PI_WARN, "Trying to fetch %s with length %d", descr, length);
1089 tree_data->fi_tmp = fi_save;
1092 THROW(ReportedBoundsError);
1097 * NOTE: to support code written when proto_tree_add_item() took a
1098 * gboolean as its last argument, with FALSE meaning "big-endian"
1099 * and TRUE meaning "little-endian", we treat any non-zero value of
1100 * "encoding" as meaning "little-endian".
1103 get_uint_value(proto_tree *tree, tvbuff_t *tvb, gint offset, gint length, const guint encoding)
1106 gboolean length_error;
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);
1131 length_error = TRUE;
1134 length_error = FALSE;
1135 value = encoding ? tvb_get_letohl(tvb, offset)
1136 : tvb_get_ntohl(tvb, offset);
1138 report_type_length_mismatch(tree, "an unsigned integer", length, length_error);
1145 * NOTE: to support code written when proto_tree_add_item() took a
1146 * gboolean as its last argument, with FALSE meaning "big-endian"
1147 * and TRUE meaning "little-endian", we treat any non-zero value of
1148 * "encoding" as meaning "little-endian".
1151 get_int_value(proto_tree *tree, tvbuff_t *tvb, gint offset, gint length, const guint encoding)
1154 gboolean length_error;
1159 value = (gint8)tvb_get_guint8(tvb, offset);
1163 value = (gint16) (encoding ? tvb_get_letohs(tvb, offset)
1164 : tvb_get_ntohs(tvb, offset));
1168 value = encoding ? tvb_get_letoh24(tvb, offset)
1169 : tvb_get_ntoh24(tvb, offset);
1170 if (value & 0x00800000) {
1171 /* Sign bit is set; sign-extend it. */
1172 value |= 0xFF000000;
1177 value = encoding ? tvb_get_letohl(tvb, offset)
1178 : tvb_get_ntohl(tvb, offset);
1183 length_error = TRUE;
1186 length_error = FALSE;
1187 value = encoding ? tvb_get_letohl(tvb, offset)
1188 : tvb_get_ntohl(tvb, offset);
1190 report_type_length_mismatch(tree, "a signed integer", length, length_error);
1197 proto_lookup_or_create_interesting_hfids(proto_tree *tree,
1198 header_field_info *hfinfo)
1200 GPtrArray *ptrs = NULL;
1202 DISSECTOR_ASSERT(tree);
1203 DISSECTOR_ASSERT(hfinfo);
1205 if (hfinfo->ref_type == HF_REF_TYPE_DIRECT) {
1206 if (PTREE_DATA(tree)->interesting_hfids == NULL) {
1207 /* Initialize the hash because we now know that it is needed */
1208 PTREE_DATA(tree)->interesting_hfids =
1209 g_hash_table_new(g_direct_hash, NULL /* g_direct_equal */);
1212 ptrs = g_hash_table_lookup(PTREE_DATA(tree)->interesting_hfids,
1213 GINT_TO_POINTER(hfinfo->id));
1215 /* First element triggers the creation of pointer array */
1216 ptrs = g_ptr_array_new();
1217 g_hash_table_insert(PTREE_DATA(tree)->interesting_hfids,
1218 GINT_TO_POINTER(hfinfo->id), ptrs);
1225 /* Add an item to a proto_tree, using the text label registered to that item;
1226 the item is extracted from the tvbuff handed to it. */
1228 proto_tree_new_item(field_info *new_fi, proto_tree *tree,
1229 tvbuff_t *tvb, gint start, gint length,
1230 const guint encoding_arg)
1232 tree_data_t *tree_data = PTREE_DATA(tree);
1233 guint encoding = encoding_arg;
1239 nstime_t time_stamp;
1241 gboolean length_error;
1243 /* there is a possibility here that we might raise an exception
1244 * and thus would lose track of the field_info.
1245 * store it in a temp so that if we come here again we can reclaim
1246 * the field_info without leaking memory.
1248 if (tree_data->fi_tmp) {
1249 /* oops, last one we got must have been lost due
1251 * good thing we saved it, now we can reverse the
1252 * memory leak and reclaim it.
1254 FIELD_INFO_FREE(tree_data->fi_tmp);
1256 /* we might throw an exception, keep track of this one
1257 * across the "dangerous" section below.
1259 tree_data->fi_tmp = new_fi;
1261 switch (new_fi->hfinfo->type) {
1263 /* no value to set for FT_NONE */
1267 proto_tree_set_protocol_tvb(new_fi, tvb);
1271 proto_tree_set_bytes_tvb(new_fi, tvb, start, length);
1276 * Map all non-zero values to little-endian for
1277 * backwards compatibility.
1280 encoding = ENC_LITTLE_ENDIAN;
1281 n = get_uint_value(tree, tvb, start, length, encoding);
1282 proto_tree_set_bytes_tvb(new_fi, tvb, start + length, n);
1284 /* Instead of calling proto_item_set_len(), since we don't yet
1285 * have a proto_item, we set the field_info's length ourselves. */
1286 new_fi->length = n + length;
1291 * Map all non-zero values to little-endian for
1292 * backwards compatibility.
1295 encoding = ENC_LITTLE_ENDIAN;
1296 proto_tree_set_boolean(new_fi,
1297 get_uint_value(tree, tvb, start, length, encoding));
1300 /* XXX - make these just FT_UINT? */
1306 * Map all non-zero values to little-endian for
1307 * backwards compatibility.
1310 encoding = ENC_LITTLE_ENDIAN;
1311 proto_tree_set_uint(new_fi,
1312 get_uint_value(tree, tvb, start, length, encoding));
1318 * Map all non-zero values to little-endian for
1319 * backwards compatibility.
1322 encoding = ENC_LITTLE_ENDIAN;
1323 if (length < 1 || length > 8) {
1324 length_error = length < 1 ? TRUE : FALSE;
1325 report_type_length_mismatch(tree, "a 64-bit integer", length, length_error);
1327 proto_tree_set_uint64_tvb(new_fi, tvb, start, length, encoding);
1330 /* XXX - make these just FT_INT? */
1336 * Map all non-zero values to little-endian for
1337 * backwards compatibility.
1340 encoding = ENC_LITTLE_ENDIAN;
1341 proto_tree_set_int(new_fi,
1342 get_int_value(tree, tvb, start, length, encoding));
1347 * Map all non-zero values to little-endian for
1348 * backwards compatibility.
1351 encoding = ENC_LITTLE_ENDIAN;
1352 if (length != FT_IPv4_LEN) {
1353 length_error = length < FT_IPv4_LEN ? TRUE : FALSE;
1354 report_type_length_mismatch(tree, "an IPv4 address", length, length_error);
1356 value = tvb_get_ipv4(tvb, start);
1358 * NOTE: to support code written when
1359 * proto_tree_add_item() took a gboolean as its
1360 * last argument, with FALSE meaning "big-endian"
1361 * and TRUE meaning "little-endian", we treat any
1362 * non-zero value of "encoding" as meaning
1365 proto_tree_set_ipv4(new_fi, encoding ? GUINT32_SWAP_LE_BE(value) : value);
1369 if (length != FT_IPXNET_LEN) {
1370 length_error = length < FT_IPXNET_LEN ? TRUE : FALSE;
1371 report_type_length_mismatch(tree, "an IPXNET address", length, length_error);
1373 proto_tree_set_ipxnet(new_fi,
1374 get_uint_value(tree, tvb, start, FT_IPXNET_LEN, FALSE));
1378 if (length != FT_IPv6_LEN) {
1379 length_error = length < FT_IPv6_LEN ? TRUE : FALSE;
1380 report_type_length_mismatch(tree, "an IPv6 address", length, length_error);
1382 proto_tree_set_ipv6_tvb(new_fi, tvb, start, length);
1387 length_error = length < 7 ? TRUE : FALSE;
1388 expert_add_info_format(NULL, tree, PI_MALFORMED, PI_ERROR, "Trying to fetch an AX.25 address with length %d", length);
1389 THROW(ReportedBoundsError);
1391 proto_tree_set_ax25_tvb(new_fi, tvb, start);
1395 if (length != FT_ETHER_LEN) {
1396 length_error = length < FT_ETHER_LEN ? TRUE : FALSE;
1397 report_type_length_mismatch(tree, "an Ethernet", length, length_error);
1399 proto_tree_set_ether_tvb(new_fi, tvb, start);
1404 * Map all non-zero values to little-endian for
1405 * backwards compatibility.
1408 encoding = ENC_LITTLE_ENDIAN;
1409 if (length != FT_EUI64_LEN) {
1410 length_error = length < FT_EUI64_LEN ? TRUE : FALSE;
1411 report_type_length_mismatch(tree, "an EUI-64 address", length, length_error);
1413 proto_tree_set_eui64_tvb(new_fi, tvb, start, encoding);
1417 * Map all non-zero values to little-endian for
1418 * backwards compatibility.
1421 encoding = ENC_LITTLE_ENDIAN;
1422 if (length != FT_GUID_LEN) {
1423 length_error = length < FT_GUID_LEN ? TRUE : FALSE;
1424 report_type_length_mismatch(tree, "a GUID", length, length_error);
1426 proto_tree_set_guid_tvb(new_fi, tvb, start, encoding);
1430 proto_tree_set_oid_tvb(new_fi, tvb, start, length);
1435 * NOTE: to support code written when
1436 * proto_tree_add_item() took a gboolean as its
1437 * last argument, with FALSE meaning "big-endian"
1438 * and TRUE meaning "little-endian", we treat any
1439 * non-zero value of "encoding" as meaning
1442 * At some point in the future, we might
1443 * support non-IEEE-binary floating-point
1444 * formats in the encoding as well
1445 * (IEEE decimal, System/3x0, VAX).
1448 encoding = ENC_LITTLE_ENDIAN;
1450 length_error = length < 4 ? TRUE : FALSE;
1451 report_type_length_mismatch(tree, "a single-precision floating point number", length, length_error);
1454 floatval = tvb_get_letohieee_float(tvb, start);
1456 floatval = tvb_get_ntohieee_float(tvb, start);
1457 proto_tree_set_float(new_fi, floatval);
1462 * NOTE: to support code written when
1463 * proto_tree_add_item() took a gboolean as its
1464 * last argument, with FALSE meaning "big-endian"
1465 * and TRUE meaning "little-endian", we treat any
1466 * non-zero value of "encoding" as meaning
1469 * At some point in the future, we might
1470 * support non-IEEE-binary floating-point
1471 * formats in the encoding as well
1472 * (IEEE decimal, System/3x0, VAX).
1474 if (encoding == TRUE)
1475 encoding = ENC_LITTLE_ENDIAN;
1477 length_error = length < 8 ? TRUE : FALSE;
1478 report_type_length_mismatch(tree, "a double-precision floating point number", length, length_error);
1481 doubleval = tvb_get_letohieee_double(tvb, start);
1483 doubleval = tvb_get_ntohieee_double(tvb, start);
1484 proto_tree_set_double(new_fi, doubleval);
1488 proto_tree_set_string_tvb(new_fi, tvb, start, length,
1494 report_type_length_mismatch(tree, "a string", length, TRUE);
1496 /* Instead of calling proto_item_set_len(),
1497 * since we don't yet have a proto_item, we
1498 * set the field_info's length ourselves.
1500 * XXX - our caller can't use that length to
1501 * advance an offset unless they arrange that
1502 * there always be a protocol tree into which
1503 * we're putting this item.
1506 /* This can throw an exception */
1507 string = tvb_get_stringz_enc(tvb, start, &length, encoding);
1508 } else if (length == 0) {
1511 /* In this case, length signifies
1512 * the length of the string.
1514 * This could either be a null-padded
1515 * string, which doesn't necessarily
1516 * have a '\0' at the end, or a
1517 * null-terminated string, with a
1518 * trailing '\0'. (Yes, there are
1519 * cases where you have a string
1520 * that's both counted and null-
1523 * In the first case, we must
1524 * allocate a buffer of length
1525 * "length+1", to make room for
1528 * In the second case, we don't
1529 * assume that there is a trailing
1530 * '\0' there, as the packet might
1531 * be malformed. (XXX - should we
1532 * throw an exception if there's no
1533 * trailing '\0'?) Therefore, we
1534 * allocate a buffer of length
1535 * "length+1", and put in a trailing
1536 * '\0', just to be safe.
1538 * (XXX - this would change if
1539 * we made string values counted
1540 * rather than null-terminated.)
1542 string = tvb_get_ephemeral_string_enc(tvb, start, length, encoding);
1544 new_fi->length = length;
1545 proto_tree_set_string(new_fi, string);
1548 case FT_UINT_STRING:
1550 * NOTE: to support code written when
1551 * proto_tree_add_item() took a gboolean as its
1552 * last argument, with FALSE meaning "big-endian"
1553 * and TRUE meaning "little-endian", if the
1554 * encoding value is TRUE, treat that as
1555 * ASCII with a little-endian length.
1557 * This won't work for code that passes
1558 * arbitrary non-zero values; that code
1559 * will need to be fixed.
1561 if (encoding == TRUE)
1562 encoding = ENC_ASCII|ENC_LITTLE_ENDIAN;
1563 n = get_uint_value(tree, tvb, start, length, encoding & ~ENC_CHARENCODING_MASK);
1564 proto_tree_set_string_tvb(new_fi, tvb, start + length, n,
1567 /* Instead of calling proto_item_set_len(), since we
1568 * don't yet have a proto_item, we set the
1569 * field_info's length ourselves.
1571 * XXX - our caller can't use that length to
1572 * advance an offset unless they arrange that
1573 * there always be a protocol tree into which
1574 * we're putting this item.
1576 new_fi->length = n + length;
1579 case FT_ABSOLUTE_TIME:
1581 * Absolute times can be in any of a number of
1582 * formats, and they can be big-endian or
1585 * Historically FT_TIMEs were only timespecs;
1586 * the only question was whether they were stored
1587 * in big- or little-endian format.
1589 * For backwards compatibility, we interpret an
1590 * encoding of 1 as meaning "little-endian timespec",
1591 * so that passing TRUE is interpreted as that.
1593 if (encoding == TRUE)
1594 encoding = ENC_TIME_TIMESPEC|ENC_LITTLE_ENDIAN;
1596 if (length != 8 && length != 4) {
1597 length_error = length < 4 ? TRUE : FALSE;
1598 report_type_length_mismatch(tree, "an absolute time value", length, length_error);
1603 case ENC_TIME_TIMESPEC|ENC_BIG_ENDIAN:
1605 * 4-byte UNIX epoch, possibly followed by
1606 * 4-byte fractional time in nanoseconds,
1609 time_stamp.secs = tvb_get_ntohl(tvb, start);
1611 time_stamp.nsecs = tvb_get_ntohl(tvb, start+4);
1613 time_stamp.nsecs = 0;
1616 case ENC_TIME_TIMESPEC|ENC_LITTLE_ENDIAN:
1618 * 4-byte UNIX epoch, possibly followed by
1619 * 4-byte fractional time in nanoseconds,
1620 * both little-endian.
1622 time_stamp.secs = tvb_get_letohl(tvb, start);
1624 time_stamp.nsecs = tvb_get_letohl(tvb, start+4);
1626 time_stamp.nsecs = 0;
1629 case ENC_TIME_NTP|ENC_BIG_ENDIAN:
1631 * NTP time stamp, big-endian.
1634 /* XXX - where should this go? */
1635 #define NTP_BASETIME 2208988800ul
1636 time_stamp.secs = tvb_get_ntohl(tvb, start);
1637 if (time_stamp.secs)
1638 time_stamp.secs -= NTP_BASETIME;
1642 * We're using nanoseconds here (and we will
1643 * display nanoseconds), but NTP's timestamps
1644 * have a precision in microseconds or greater.
1645 * Round to 1 microsecond.
1647 time_stamp.nsecs = (int)(1000000*(tvb_get_ntohl(tvb, start+4)/4294967296.0));
1648 time_stamp.nsecs *= 1000;
1650 time_stamp.nsecs = 0;
1654 case ENC_TIME_NTP|ENC_LITTLE_ENDIAN:
1656 * NTP time stamp, big-endian.
1658 time_stamp.secs = tvb_get_letohl(tvb, start);
1659 if (time_stamp.secs)
1660 time_stamp.secs -= NTP_BASETIME;
1664 * We're using nanoseconds here (and we will
1665 * display nanoseconds), but NTP's timestamps
1666 * have a precision in microseconds or greater.
1667 * Round to 1 microsecond.
1669 time_stamp.nsecs = (int)(1000000*(tvb_get_letohl(tvb, start+4)/4294967296.0));
1670 time_stamp.nsecs *= 1000;
1672 time_stamp.nsecs = 0;
1677 DISSECTOR_ASSERT_NOT_REACHED();
1678 time_stamp.secs = 0;
1679 time_stamp.nsecs = 0;
1682 proto_tree_set_time(new_fi, &time_stamp);
1685 case FT_RELATIVE_TIME:
1687 * Relative times can be in any of a number of
1688 * formats, and they can be big-endian or
1691 * Historically FT_TIMEs were only timespecs;
1692 * the only question was whether they were stored
1693 * in big- or little-endian format.
1695 * For backwards compatibility, we interpret an
1696 * encoding of 1 as meaning "little-endian timespec",
1697 * so that passing TRUE is interpreted as that.
1699 if (encoding == TRUE)
1700 encoding = ENC_TIME_TIMESPEC|ENC_LITTLE_ENDIAN;
1703 if (length != 8 && length != 4) {
1704 length_error = length < 4 ? TRUE : FALSE;
1705 report_type_length_mismatch(tree, "a relative time value", length, length_error);
1708 case ENC_TIME_TIMESPEC|ENC_BIG_ENDIAN:
1710 * 4-byte UNIX epoch, possibly followed by
1711 * 4-byte fractional time in nanoseconds,
1714 time_stamp.secs = tvb_get_ntohl(tvb, start);
1716 time_stamp.nsecs = tvb_get_ntohl(tvb, start+4);
1718 time_stamp.nsecs = 0;
1721 case ENC_TIME_TIMESPEC|ENC_LITTLE_ENDIAN:
1723 * 4-byte UNIX epoch, possibly followed by
1724 * 4-byte fractional time in nanoseconds,
1725 * both little-endian.
1727 time_stamp.secs = tvb_get_letohl(tvb, start);
1729 time_stamp.nsecs = tvb_get_letohl(tvb, start+4);
1731 time_stamp.nsecs = 0;
1734 proto_tree_set_time(new_fi, &time_stamp);
1738 g_error("new_fi->hfinfo->type %d (%s) not handled\n",
1739 new_fi->hfinfo->type,
1740 ftype_name(new_fi->hfinfo->type));
1741 DISSECTOR_ASSERT_NOT_REACHED();
1744 FI_SET_FLAG(new_fi, (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN);
1746 /* Don't add new node to proto_tree until now so that any exceptions
1747 * raised by a tvbuff access method doesn't leave junk in the proto_tree. */
1748 /* XXX. wouldn't be better to add this item to tree, with some special flag (FI_EXCEPTION?)
1749 * to know which item caused exception? */
1750 pi = proto_tree_add_node(tree, new_fi);
1752 /* we did not raise an exception so we dont have to remember this
1753 * field_info struct any more.
1755 tree_data->fi_tmp = NULL;
1757 /* If the proto_tree wants to keep a record of this finfo
1758 * for quick lookup, then record it. */
1759 ptrs = proto_lookup_or_create_interesting_hfids(tree, new_fi->hfinfo);
1761 g_ptr_array_add(ptrs, new_fi);
1766 /* Gets data from tvbuff, adds it to proto_tree, increments offset,
1767 and returns proto_item* */
1769 ptvcursor_add(ptvcursor_t *ptvc, int hfindex, gint length,
1770 const guint encoding)
1773 header_field_info *hfinfo;
1778 /* We can't fake it just yet. We have to advance the cursor
1779 TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfindex, hfinfo); */
1781 offset = ptvc->offset;
1782 hfinfo = get_hfi_and_length(hfindex, ptvc->tvb, offset, &length,
1784 ptvc->offset += length;
1785 if (hfinfo->type == FT_UINT_BYTES || hfinfo->type == FT_UINT_STRING) {
1787 * The length of the rest of the item is in the first N
1788 * bytes of the item.
1790 n = get_uint_value(ptvc->tree, ptvc->tvb, offset, length, encoding);
1794 /* Coast clear. Try and fake it */
1795 TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfindex, hfinfo);
1797 new_fi = new_field_info(ptvc->tree, hfinfo, ptvc->tvb, offset, item_length);
1799 return proto_tree_new_item(new_fi, ptvc->tree, ptvc->tvb,
1800 offset, length, encoding);
1803 /* Add an item to a proto_tree, using the text label registered to that item;
1804 the item is extracted from the tvbuff handed to it. */
1806 proto_tree_add_item(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
1807 const gint start, gint length, const guint encoding)
1810 header_field_info *hfinfo;
1812 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1814 new_fi = alloc_field_info(tree, hfindex, tvb, start, &length);
1819 return proto_tree_new_item(new_fi, tree, tvb, start,
1823 /* Add a FT_NONE to a proto_tree */
1825 proto_tree_add_none_format(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
1826 const gint start, gint length, const char *format,
1831 header_field_info *hfinfo;
1833 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1835 DISSECTOR_ASSERT(hfinfo->type == FT_NONE);
1837 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, NULL);
1839 TRY_TO_FAKE_THIS_REPR(tree, pi);
1841 va_start(ap, format);
1842 proto_tree_set_representation(pi, format, ap);
1845 /* no value to set for FT_NONE */
1849 /* Gets data from tvbuff, adds it to proto_tree, *DOES NOT* increment
1850 * offset, and returns proto_item* */
1852 ptvcursor_add_no_advance(ptvcursor_t* ptvc, int hf, gint length,
1853 const guint encoding)
1857 item = proto_tree_add_item(ptvc->tree, hf, ptvc->tvb, ptvc->offset,
1863 /* Advance the ptvcursor's offset within its tvbuff without
1864 * adding anything to the proto_tree. */
1866 ptvcursor_advance(ptvcursor_t* ptvc, gint length)
1868 ptvc->offset += length;
1873 proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb)
1875 fvalue_set(&fi->value, tvb, TRUE);
1878 /* Add a FT_PROTOCOL to a proto_tree */
1880 proto_tree_add_protocol_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1881 gint start, gint length, const char *format, ...)
1886 header_field_info *hfinfo;
1888 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1890 DISSECTOR_ASSERT(hfinfo->type == FT_PROTOCOL);
1892 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1894 proto_tree_set_protocol_tvb(new_fi, (start == 0 ? tvb : tvb_new_subset(tvb, start, length, length)));
1896 TRY_TO_FAKE_THIS_REPR(tree, pi);
1898 va_start(ap, format);
1899 proto_tree_set_representation(pi, format, ap);
1906 /* Add a FT_BYTES to a proto_tree */
1908 proto_tree_add_bytes(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1909 gint length, const guint8 *start_ptr)
1913 header_field_info *hfinfo;
1915 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1917 DISSECTOR_ASSERT(hfinfo->type == FT_BYTES);
1919 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1920 proto_tree_set_bytes(new_fi, start_ptr, length);
1926 proto_tree_add_bytes_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1927 gint start, gint length,
1928 const guint8 *start_ptr,
1929 const char *format, ...)
1933 header_field_info *hfinfo;
1935 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1938 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length,
1941 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length,
1942 tvb_get_ptr(tvb, start, length));
1944 TRY_TO_FAKE_THIS_REPR(tree, pi);
1946 va_start(ap, format);
1947 proto_tree_set_representation_value(pi, format, ap);
1954 proto_tree_add_bytes_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1955 gint start, gint length, const guint8 *start_ptr,
1956 const char *format, ...)
1960 header_field_info *hfinfo;
1962 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1965 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length,
1968 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length,
1969 tvb_get_ptr(tvb, start, length));
1971 TRY_TO_FAKE_THIS_REPR(tree, pi);
1973 va_start(ap, format);
1974 proto_tree_set_representation(pi, format, ap);
1981 proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length)
1985 bytes = g_byte_array_new();
1987 g_byte_array_append(bytes, start_ptr, length);
1989 fvalue_set(&fi->value, bytes, TRUE);
1994 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length)
1996 proto_tree_set_bytes(fi, tvb_get_ptr(tvb, offset, length), length);
1999 /* Add a FT_*TIME to a proto_tree */
2001 proto_tree_add_time(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2002 gint length, nstime_t *value_ptr)
2006 header_field_info *hfinfo;
2008 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2010 DISSECTOR_ASSERT(hfinfo->type == FT_ABSOLUTE_TIME ||
2011 hfinfo->type == FT_RELATIVE_TIME);
2013 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2014 proto_tree_set_time(new_fi, value_ptr);
2020 proto_tree_add_time_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2021 gint start, gint length, nstime_t *value_ptr,
2022 const char *format, ...)
2026 header_field_info *hfinfo;
2028 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2030 pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
2032 TRY_TO_FAKE_THIS_REPR(tree, pi);
2034 va_start(ap, format);
2035 proto_tree_set_representation_value(pi, format, ap);
2042 proto_tree_add_time_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2043 gint start, gint length, nstime_t *value_ptr,
2044 const char *format, ...)
2048 header_field_info *hfinfo;
2050 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2052 pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
2054 TRY_TO_FAKE_THIS_REPR(tree, pi);
2056 va_start(ap, format);
2057 proto_tree_set_representation(pi, format, ap);
2063 /* Set the FT_*TIME value */
2065 proto_tree_set_time(field_info *fi, nstime_t *value_ptr)
2067 DISSECTOR_ASSERT(value_ptr != NULL);
2069 fvalue_set(&fi->value, value_ptr, FALSE);
2072 /* Add a FT_IPXNET to a proto_tree */
2074 proto_tree_add_ipxnet(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2075 gint length, guint32 value)
2079 header_field_info *hfinfo;
2081 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2083 DISSECTOR_ASSERT(hfinfo->type == FT_IPXNET);
2085 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2086 proto_tree_set_ipxnet(new_fi, value);
2092 proto_tree_add_ipxnet_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2093 gint start, gint length, guint32 value,
2094 const char *format, ...)
2098 header_field_info *hfinfo;
2100 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2102 pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
2104 TRY_TO_FAKE_THIS_REPR(tree, pi);
2106 va_start(ap, format);
2107 proto_tree_set_representation_value(pi, format, ap);
2114 proto_tree_add_ipxnet_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2115 gint start, gint length, guint32 value,
2116 const char *format, ...)
2120 header_field_info *hfinfo;
2122 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2124 pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
2126 TRY_TO_FAKE_THIS_REPR(tree, pi);
2128 va_start(ap, format);
2129 proto_tree_set_representation(pi, format, ap);
2135 /* Set the FT_IPXNET value */
2137 proto_tree_set_ipxnet(field_info *fi, guint32 value)
2139 fvalue_set_uinteger(&fi->value, value);
2142 /* Add a FT_IPv4 to a proto_tree */
2144 proto_tree_add_ipv4(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2145 gint length, guint32 value)
2149 header_field_info *hfinfo;
2151 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2153 DISSECTOR_ASSERT(hfinfo->type == FT_IPv4);
2155 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2156 proto_tree_set_ipv4(new_fi, value);
2162 proto_tree_add_ipv4_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2163 gint start, gint length, guint32 value,
2164 const char *format, ...)
2168 header_field_info *hfinfo;
2170 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2172 pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
2174 TRY_TO_FAKE_THIS_REPR(tree, pi);
2176 va_start(ap, format);
2177 proto_tree_set_representation_value(pi, format, ap);
2184 proto_tree_add_ipv4_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2185 gint start, gint length, guint32 value,
2186 const char *format, ...)
2190 header_field_info *hfinfo;
2192 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2194 pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
2196 TRY_TO_FAKE_THIS_REPR(tree, pi);
2198 va_start(ap, format);
2199 proto_tree_set_representation(pi, format, ap);
2205 /* Set the FT_IPv4 value */
2207 proto_tree_set_ipv4(field_info *fi, guint32 value)
2209 fvalue_set_uinteger(&fi->value, value);
2212 /* Add a FT_IPv6 to a proto_tree */
2214 proto_tree_add_ipv6(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2215 gint length, const guint8* value_ptr)
2219 header_field_info *hfinfo;
2221 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2223 DISSECTOR_ASSERT(hfinfo->type == FT_IPv6);
2225 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2226 proto_tree_set_ipv6(new_fi, value_ptr);
2232 proto_tree_add_ipv6_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2233 gint start, gint length,
2234 const guint8* value_ptr,
2235 const char *format, ...)
2239 header_field_info *hfinfo;
2241 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2243 pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
2245 TRY_TO_FAKE_THIS_REPR(tree, pi);
2247 va_start(ap, format);
2248 proto_tree_set_representation_value(pi, format, ap);
2255 proto_tree_add_ipv6_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2256 gint start, gint length, const guint8* value_ptr,
2257 const char *format, ...)
2261 header_field_info *hfinfo;
2263 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2265 pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
2267 TRY_TO_FAKE_THIS_REPR(tree, pi);
2269 va_start(ap, format);
2270 proto_tree_set_representation(pi, format, ap);
2276 /* Set the FT_IPv6 value */
2278 proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr)
2280 DISSECTOR_ASSERT(value_ptr != NULL);
2281 fvalue_set(&fi->value, (gpointer) value_ptr, FALSE);
2285 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
2287 proto_tree_set_ipv6(fi, tvb_get_ptr(tvb, start, length));
2290 /* Add a FT_GUID to a proto_tree */
2292 proto_tree_add_guid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2293 gint length, const e_guid_t *value_ptr)
2297 header_field_info *hfinfo;
2299 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2301 DISSECTOR_ASSERT(hfinfo->type == FT_GUID);
2303 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2304 proto_tree_set_guid(new_fi, value_ptr);
2310 proto_tree_add_guid_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2311 gint start, gint length,
2312 const e_guid_t *value_ptr,
2313 const char *format, ...)
2317 header_field_info *hfinfo;
2319 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2321 pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
2323 TRY_TO_FAKE_THIS_REPR(tree, pi);
2325 va_start(ap, format);
2326 proto_tree_set_representation_value(pi, format, ap);
2333 proto_tree_add_guid_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2334 gint start, gint length, const e_guid_t *value_ptr,
2335 const char *format, ...)
2339 header_field_info *hfinfo;
2341 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2343 pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
2345 TRY_TO_FAKE_THIS_REPR(tree, pi);
2347 va_start(ap, format);
2348 proto_tree_set_representation(pi, format, ap);
2354 /* Set the FT_GUID value */
2356 proto_tree_set_guid(field_info *fi, const e_guid_t *value_ptr)
2358 DISSECTOR_ASSERT(value_ptr != NULL);
2359 fvalue_set(&fi->value, (gpointer) value_ptr, FALSE);
2363 proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, gint start,
2364 const guint encoding)
2368 tvb_get_guid(tvb, start, &guid, encoding);
2369 proto_tree_set_guid(fi, &guid);
2372 /* Add a FT_OID to a proto_tree */
2374 proto_tree_add_oid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2375 gint length, const guint8* value_ptr)
2379 header_field_info *hfinfo;
2381 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2383 DISSECTOR_ASSERT(hfinfo->type == FT_OID);
2385 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2386 proto_tree_set_oid(new_fi, value_ptr, length);
2392 proto_tree_add_oid_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2393 gint start, gint length,
2394 const guint8* value_ptr,
2395 const char *format, ...)
2399 header_field_info *hfinfo;
2401 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2403 pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
2405 TRY_TO_FAKE_THIS_REPR(tree, pi);
2407 va_start(ap, format);
2408 proto_tree_set_representation_value(pi, format, ap);
2415 proto_tree_add_oid_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2416 gint start, gint length, const guint8* value_ptr,
2417 const char *format, ...)
2421 header_field_info *hfinfo;
2423 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2425 pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
2427 TRY_TO_FAKE_THIS_REPR(tree, pi);
2429 va_start(ap, format);
2430 proto_tree_set_representation(pi, format, ap);
2436 /* Set the FT_OID value */
2438 proto_tree_set_oid(field_info *fi, const guint8* value_ptr, gint length)
2442 DISSECTOR_ASSERT(value_ptr != NULL);
2444 bytes = g_byte_array_new();
2446 g_byte_array_append(bytes, value_ptr, length);
2448 fvalue_set(&fi->value, bytes, TRUE);
2452 proto_tree_set_oid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
2454 proto_tree_set_oid(fi, tvb_get_ptr(tvb, start, length), length);
2458 proto_tree_set_uint64(field_info *fi, guint64 value)
2460 fvalue_set_integer64(&fi->value, value);
2464 * NOTE: to support code written when proto_tree_add_item() took a
2465 * gboolean as its last argument, with FALSE meaning "big-endian"
2466 * and TRUE meaning "little-endian", we treat any non-zero value of
2467 * "encoding" as meaning "little-endian".
2470 proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start,
2471 guint length, const guint encoding)
2474 guint8* b = ep_tvb_memdup(tvb, start, length);
2479 default: DISSECTOR_ASSERT_NOT_REACHED();
2480 case 8: value <<= 8; value += *--b;
2481 case 7: value <<= 8; value += *--b;
2482 case 6: value <<= 8; value += *--b;
2483 case 5: value <<= 8; value += *--b;
2484 case 4: value <<= 8; value += *--b;
2485 case 3: value <<= 8; value += *--b;
2486 case 2: value <<= 8; value += *--b;
2487 case 1: value <<= 8; value += *--b;
2492 default: DISSECTOR_ASSERT_NOT_REACHED();
2493 case 8: value <<= 8; value += *b++;
2494 case 7: value <<= 8; value += *b++;
2495 case 6: value <<= 8; value += *b++;
2496 case 5: value <<= 8; value += *b++;
2497 case 4: value <<= 8; value += *b++;
2498 case 3: value <<= 8; value += *b++;
2499 case 2: value <<= 8; value += *b++;
2500 case 1: value <<= 8; value += *b++;
2505 proto_tree_set_uint64(fi, value);
2508 /* Add a FT_STRING or FT_STRINGZ to a proto_tree. Creates own copy of string,
2509 * and frees it when the proto_tree is destroyed. */
2511 proto_tree_add_string(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2512 gint length, const char* value)
2516 header_field_info *hfinfo;
2518 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2520 DISSECTOR_ASSERT(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ);
2522 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2523 DISSECTOR_ASSERT(length >= 0);
2524 proto_tree_set_string(new_fi, value);
2530 proto_tree_add_unicode_string(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2531 gint length, const char* value)
2533 DISSECTOR_ASSERT(g_utf8_validate(value, -1, NULL));
2534 return proto_tree_add_string_format_value(tree, hfindex, tvb, start, length, value, "%s", value);
2538 proto_tree_add_string_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2539 gint start, gint length, const char* value,
2545 header_field_info *hfinfo;
2547 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2549 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
2551 TRY_TO_FAKE_THIS_REPR(tree, pi);
2553 va_start(ap, format);
2554 proto_tree_set_representation_value(pi, format, ap);
2561 proto_tree_add_string_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2562 gint start, gint length, const char* value,
2563 const char *format, ...)
2567 header_field_info *hfinfo;
2569 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2571 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
2573 TRY_TO_FAKE_THIS_REPR(tree, pi);
2575 va_start(ap, format);
2576 proto_tree_set_representation(pi, format, ap);
2582 /* Appends string data to a FT_STRING or FT_STRINGZ, allowing progressive
2583 * field info update instead of only updating the representation as does
2584 * proto_item_append_text()
2586 /* NOTE: this function will break with the TRY_TO_FAKE_THIS_ITEM()
2587 * speed optimization.
2588 * Currently only WSP use this function so it is not that bad but try to
2589 * avoid using this one if possible.
2590 * IF you must use this function you MUST also disable the
2591 * TRY_TO_FAKE_THIS_ITEM() optimization for your dissector/function
2592 * using proto_item_append_string().
2593 * Do that by faking that the tree is visible by calling
2594 * proto_tree_set_visible(tree, TRUE) (see packet-wsp.c)
2595 * BEFORE you create the item you are later going to use
2596 * proto_item_append_string() on.
2599 proto_item_append_string(proto_item *pi, const char *str)
2602 header_field_info *hfinfo;
2603 gchar *old_str, *new_str;
2610 fi = PITEM_FINFO(pi);
2611 DISSECTOR_ASSERT_HINT(fi, "proto_tree_set_visible(tree, TRUE) should have been called previously");
2613 hfinfo = fi->hfinfo;
2614 if (hfinfo->type == FT_PROTOCOL) {
2615 /* TRY_TO_FAKE_THIS_ITEM() speed optimization: silently skip */
2618 DISSECTOR_ASSERT(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ);
2619 old_str = fvalue_get(&fi->value);
2620 new_str = ep_strdup_printf("%s%s", old_str, str);
2621 fvalue_set(&fi->value, new_str, FALSE);
2624 /* Set the FT_STRING value */
2626 proto_tree_set_string(field_info *fi, const char* value)
2629 fvalue_set(&fi->value, (gpointer) value, FALSE);
2631 fvalue_set(&fi->value, (gpointer) "[ Null ]", FALSE);
2636 proto_tree_set_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length, gint encoding)
2641 length = tvb_ensure_length_remaining(tvb, start);
2644 string = tvb_get_ephemeral_string_enc(tvb, start, length, encoding);
2645 proto_tree_set_string(fi, string);
2649 /* Add a FT_AX25 to a proto_tree */
2651 proto_tree_add_ax25(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2652 const guint8* value)
2656 header_field_info *hfinfo;
2661 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2663 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2664 DISSECTOR_ASSERT(hfinfo->type == FT_AX25);
2666 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2667 proto_tree_set_ax25(new_fi, value);
2672 /* Set the FT_AX25 value */
2674 proto_tree_set_ax25(field_info *fi, const guint8* value)
2676 fvalue_set(&fi->value, (gpointer) value, FALSE);
2680 proto_tree_set_ax25_tvb(field_info *fi, tvbuff_t *tvb, gint start)
2682 proto_tree_set_ax25(fi, tvb_get_ptr(tvb, start, 7));
2686 /* Add a FT_ETHER to a proto_tree */
2688 proto_tree_add_ether(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2689 gint length, const guint8* value)
2693 header_field_info *hfinfo;
2695 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2697 DISSECTOR_ASSERT(hfinfo->type == FT_ETHER);
2699 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2700 proto_tree_set_ether(new_fi, value);
2706 proto_tree_add_ether_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2707 gint start, gint length, const guint8* value,
2708 const char *format, ...)
2712 header_field_info *hfinfo;
2714 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2716 pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
2718 TRY_TO_FAKE_THIS_REPR(tree, pi);
2720 va_start(ap, format);
2721 proto_tree_set_representation_value(pi, format, ap);
2728 proto_tree_add_ether_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2729 gint start, gint length, const guint8* value,
2730 const char *format, ...)
2734 header_field_info *hfinfo;
2736 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2738 pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
2740 TRY_TO_FAKE_THIS_REPR(tree, pi);
2742 va_start(ap, format);
2743 proto_tree_set_representation(pi, format, ap);
2749 /* Set the FT_ETHER value */
2751 proto_tree_set_ether(field_info *fi, const guint8* value)
2753 fvalue_set(&fi->value, (gpointer) value, FALSE);
2757 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start)
2759 proto_tree_set_ether(fi, tvb_get_ptr(tvb, start, FT_ETHER_LEN));
2762 /* Add a FT_BOOLEAN to a proto_tree */
2764 proto_tree_add_boolean(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2765 gint length, guint32 value)
2769 header_field_info *hfinfo;
2771 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2773 DISSECTOR_ASSERT(hfinfo->type == FT_BOOLEAN);
2775 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2776 proto_tree_set_boolean(new_fi, value);
2782 proto_tree_add_boolean_format_value(proto_tree *tree, int hfindex,
2783 tvbuff_t *tvb, gint start, gint length,
2784 guint32 value, const char *format, ...)
2788 header_field_info *hfinfo;
2790 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2792 pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
2794 TRY_TO_FAKE_THIS_REPR(tree, pi);
2796 va_start(ap, format);
2797 proto_tree_set_representation_value(pi, format, ap);
2804 proto_tree_add_boolean_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2805 gint start, gint length, guint32 value,
2806 const char *format, ...)
2810 header_field_info *hfinfo;
2812 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2814 pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
2816 TRY_TO_FAKE_THIS_REPR(tree, pi);
2818 va_start(ap, format);
2819 proto_tree_set_representation(pi, format, ap);
2825 /* Set the FT_BOOLEAN value */
2827 proto_tree_set_boolean(field_info *fi, guint32 value)
2829 proto_tree_set_uint(fi, value);
2832 /* Add a FT_FLOAT to a proto_tree */
2834 proto_tree_add_float(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2835 gint length, float value)
2839 header_field_info *hfinfo;
2841 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2843 DISSECTOR_ASSERT(hfinfo->type == FT_FLOAT);
2845 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2846 proto_tree_set_float(new_fi, value);
2852 proto_tree_add_float_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2853 gint start, gint length, float value,
2854 const char *format, ...)
2858 header_field_info *hfinfo;
2860 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2862 pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
2864 TRY_TO_FAKE_THIS_REPR(tree, pi);
2866 va_start(ap, format);
2867 proto_tree_set_representation_value(pi, format, ap);
2874 proto_tree_add_float_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2875 gint start, gint length, float value,
2876 const char *format, ...)
2880 header_field_info *hfinfo;
2882 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2884 pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
2886 TRY_TO_FAKE_THIS_REPR(tree, pi);
2888 va_start(ap, format);
2889 proto_tree_set_representation(pi, format, ap);
2895 /* Set the FT_FLOAT value */
2897 proto_tree_set_float(field_info *fi, float value)
2899 fvalue_set_floating(&fi->value, value);
2902 /* Add a FT_DOUBLE to a proto_tree */
2904 proto_tree_add_double(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2905 gint length, double value)
2909 header_field_info *hfinfo;
2911 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2913 DISSECTOR_ASSERT(hfinfo->type == FT_DOUBLE);
2915 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2916 proto_tree_set_double(new_fi, value);
2922 proto_tree_add_double_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2923 gint start, gint length, double value,
2924 const char *format, ...)
2928 header_field_info *hfinfo;
2930 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2932 pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
2934 TRY_TO_FAKE_THIS_REPR(tree, pi);
2936 va_start(ap, format);
2937 proto_tree_set_representation_value(pi, format, ap);
2944 proto_tree_add_double_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2945 gint start, gint length, double value,
2946 const char *format, ...)
2950 header_field_info *hfinfo;
2952 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2954 pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
2956 TRY_TO_FAKE_THIS_REPR(tree, pi);
2958 va_start(ap, format);
2959 proto_tree_set_representation(pi, format, ap);
2965 /* Set the FT_DOUBLE value */
2967 proto_tree_set_double(field_info *fi, double value)
2969 fvalue_set_floating(&fi->value, value);
2972 /* Add FT_UINT{8,16,24,32} to a proto_tree */
2974 proto_tree_add_uint(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2975 gint length, guint32 value)
2977 proto_item *pi = NULL;
2979 header_field_info *hfinfo;
2981 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2983 switch (hfinfo->type) {
2989 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length,
2991 proto_tree_set_uint(new_fi, value);
2995 DISSECTOR_ASSERT_NOT_REACHED();
3002 proto_tree_add_uint_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3003 gint start, gint length, guint32 value,
3004 const char *format, ...)
3008 header_field_info *hfinfo;
3010 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3012 pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
3014 TRY_TO_FAKE_THIS_REPR(tree, pi);
3016 va_start(ap, format);
3017 proto_tree_set_representation_value(pi, format, ap);
3024 proto_tree_add_uint_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3025 gint start, gint length, guint32 value,
3026 const char *format, ...)
3030 header_field_info *hfinfo;
3032 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3034 pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
3036 TRY_TO_FAKE_THIS_REPR(tree, pi);
3038 va_start(ap, format);
3039 proto_tree_set_representation(pi, format, ap);
3045 /* Set the FT_UINT{8,16,24,32} value */
3047 proto_tree_set_uint(field_info *fi, guint32 value)
3049 header_field_info *hfinfo;
3052 hfinfo = fi->hfinfo;
3055 if (hfinfo->bitmask) {
3056 /* Mask out irrelevant portions */
3057 integer &= hfinfo->bitmask;
3060 if (hfinfo->bitshift > 0) {
3061 integer >>= hfinfo->bitshift;
3065 fvalue_set_uinteger(&fi->value, integer);
3068 /* Add FT_UINT64 to a proto_tree */
3070 proto_tree_add_uint64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3071 gint length, guint64 value)
3073 proto_item *pi = NULL;
3075 header_field_info *hfinfo;
3077 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3079 DISSECTOR_ASSERT(hfinfo->type == FT_UINT64);
3081 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
3082 proto_tree_set_uint64(new_fi, value);
3088 proto_tree_add_uint64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3089 gint start, gint length, guint64 value,
3090 const char *format, ...)
3094 header_field_info *hfinfo;
3096 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3098 pi = proto_tree_add_uint64(tree, hfindex, tvb, start, length, value);
3100 TRY_TO_FAKE_THIS_REPR(tree, pi);
3102 va_start(ap, format);
3103 proto_tree_set_representation_value(pi, format, ap);
3110 proto_tree_add_uint64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3111 gint start, gint length, guint64 value,
3112 const char *format, ...)
3116 header_field_info *hfinfo;
3118 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3120 pi = proto_tree_add_uint64(tree, hfindex, tvb, start, length, value);
3122 TRY_TO_FAKE_THIS_REPR(tree, pi);
3124 va_start(ap, format);
3125 proto_tree_set_representation(pi, format, ap);
3131 /* Add FT_INT{8,16,24,32} to a proto_tree */
3133 proto_tree_add_int(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3134 gint length, gint32 value)
3136 proto_item *pi = NULL;
3138 header_field_info *hfinfo;
3140 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3142 switch (hfinfo->type) {
3147 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length,
3149 proto_tree_set_int(new_fi, value);
3153 DISSECTOR_ASSERT_NOT_REACHED();
3160 proto_tree_add_int_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3161 gint start, gint length, gint32 value,
3162 const char *format, ...)
3164 proto_item *pi = NULL;
3166 header_field_info *hfinfo;
3168 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3170 pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
3172 TRY_TO_FAKE_THIS_REPR(tree, pi);
3174 va_start(ap, format);
3175 proto_tree_set_representation_value(pi, format, ap);
3182 proto_tree_add_int_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3183 gint start, gint length, gint32 value,
3184 const char *format, ...)
3186 proto_item *pi = NULL;
3188 header_field_info *hfinfo;
3190 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3192 pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
3194 TRY_TO_FAKE_THIS_REPR(tree, pi);
3196 va_start(ap, format);
3197 proto_tree_set_representation(pi, format, ap);
3203 /* Set the FT_INT{8,16,24,32} value */
3205 proto_tree_set_int(field_info *fi, gint32 value)
3207 header_field_info *hfinfo;
3210 hfinfo = fi->hfinfo;
3211 integer = (guint32) value;
3213 if (hfinfo->bitmask) {
3214 /* Mask out irrelevant portions */
3215 integer &= hfinfo->bitmask;
3218 if (hfinfo->bitshift > 0) {
3219 integer >>= hfinfo->bitshift;
3223 fvalue_set_sinteger(&fi->value, integer);
3226 /* Add FT_INT64 to a proto_tree */
3228 proto_tree_add_int64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3229 gint length, gint64 value)
3231 proto_item *pi = NULL;
3233 header_field_info *hfinfo;
3235 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3237 DISSECTOR_ASSERT(hfinfo->type == FT_INT64);
3239 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
3240 proto_tree_set_uint64(new_fi, (guint64)value);
3246 proto_tree_add_int64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3247 gint start, gint length, gint64 value,
3248 const char *format, ...)
3252 header_field_info *hfinfo;
3254 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3256 pi = proto_tree_add_int64(tree, hfindex, tvb, start, length, value);
3258 TRY_TO_FAKE_THIS_REPR(tree, pi);
3260 va_start(ap, format);
3261 proto_tree_set_representation_value(pi, format, ap);
3268 proto_tree_add_int64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3269 gint start, gint length, gint64 value,
3270 const char *format, ...)
3274 header_field_info *hfinfo;
3276 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3278 pi = proto_tree_add_int64(tree, hfindex, tvb, start, length, value);
3280 TRY_TO_FAKE_THIS_REPR(tree, pi);
3282 va_start(ap, format);
3283 proto_tree_set_representation(pi, format, ap);
3288 /* Add a FT_EUI64 to a proto_tree */
3290 proto_tree_add_eui64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3291 gint length, const guint64 value)
3295 header_field_info *hfinfo;
3297 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3299 DISSECTOR_ASSERT(hfinfo->type == FT_EUI64);
3301 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
3302 proto_tree_set_eui64(new_fi, value);
3308 proto_tree_add_eui64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3309 gint start, gint length, const guint64 value,
3310 const char *format, ...)
3314 header_field_info *hfinfo;
3316 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3318 pi = proto_tree_add_eui64(tree, hfindex, tvb, start, length, value);
3320 TRY_TO_FAKE_THIS_REPR(tree, pi);
3322 va_start(ap, format);
3323 proto_tree_set_representation_value(pi, format, ap);
3330 proto_tree_add_eui64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3331 gint start, gint length, const guint64 value,
3332 const char *format, ...)
3336 header_field_info *hfinfo;
3338 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3340 pi = proto_tree_add_eui64(tree, hfindex, tvb, start, length, value);
3342 TRY_TO_FAKE_THIS_REPR(tree, pi);
3344 va_start(ap, format);
3345 proto_tree_set_representation(pi, format, ap);
3351 /* Set the FT_EUI64 value */
3353 proto_tree_set_eui64(field_info *fi, const guint64 value)
3355 fvalue_set_integer64(&fi->value, value);
3358 proto_tree_set_eui64_tvb(field_info *fi, tvbuff_t *tvb, gint start, const guint encoding)
3362 proto_tree_set_eui64(fi, tvb_get_letoh64(tvb, start));
3364 proto_tree_set_eui64(fi, tvb_get_ntoh64(tvb, start));
3368 /* Add a field_info struct to the proto_tree, encapsulating it in a proto_node */
3370 proto_tree_add_node(proto_tree *tree, field_info *fi)
3372 proto_node *pnode, *tnode, *sibling;
3376 * Make sure "tree" is ready to have subtrees under it, by
3377 * checking whether it's been given an ett_ value.
3379 * "PNODE_FINFO(tnode)" may be null; that's the case for the root
3380 * node of the protocol tree. That node is not displayed,
3381 * so it doesn't need an ett_ value to remember whether it
3385 tfi = PNODE_FINFO(tnode);
3386 if (tfi != NULL && (tfi->tree_type < 0 || tfi->tree_type >= num_tree_types)) {
3387 REPORT_DISSECTOR_BUG(ep_strdup_printf("\"%s\" - \"%s\" tfi->tree_type: %u invalid (%s:%u)",
3388 fi->hfinfo->name, fi->hfinfo->abbrev, tfi->tree_type, __FILE__, __LINE__));
3389 /* XXX - is it safe to continue here? */
3392 DISSECTOR_ASSERT(tfi == NULL ||
3393 (tfi->tree_type >= 0 && tfi->tree_type < num_tree_types));
3395 PROTO_NODE_NEW(pnode);
3396 pnode->parent = tnode;
3397 PNODE_FINFO(pnode) = fi;
3398 pnode->tree_data = PTREE_DATA(tree);
3400 if (tnode->last_child != NULL) {
3401 sibling = tnode->last_child;
3402 DISSECTOR_ASSERT(sibling->next == NULL);
3403 sibling->next = pnode;
3405 tnode->first_child = pnode;
3406 tnode->last_child = pnode;
3408 return (proto_item *)pnode;
3412 /* Generic way to allocate field_info and add to proto_tree.
3413 * Sets *pfi to address of newly-allocated field_info struct, if pfi is
3416 proto_tree_add_pi(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3417 gint *length, field_info **pfi)
3426 fi = alloc_field_info(tree, hfindex, tvb, start, length);
3427 pi = proto_tree_add_node(tree, fi);
3429 /* If the proto_tree wants to keep a record of this finfo
3430 * for quick lookup, then record it. */
3431 ptrs = proto_lookup_or_create_interesting_hfids(tree, fi->hfinfo);
3433 g_ptr_array_add(ptrs, fi);
3435 /* Does the caller want to know the fi pointer? */
3444 static header_field_info *
3445 get_hfi_and_length(int hfindex, tvbuff_t *tvb, const gint start, gint *length,
3448 header_field_info *hfinfo;
3449 gint length_remaining;
3452 * We only allow a null tvbuff if the item has a zero length,
3453 * i.e. if there's no data backing it.
3455 DISSECTOR_ASSERT(tvb != NULL || *length == 0);
3457 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
3460 * XXX - in some protocols, there are 32-bit unsigned length
3461 * fields, so lengths in protocol tree and tvbuff routines
3462 * should really be unsigned. We should have, for those
3463 * field types for which "to the end of the tvbuff" makes sense,
3464 * additional routines that take no length argument and
3465 * add fields that run to the end of the tvbuff.
3467 if (*length == -1) {
3469 * For FT_NONE, FT_PROTOCOL, FT_BYTES, and FT_STRING fields,
3470 * a length of -1 means "set the length to what remains in
3473 * The assumption is either that
3475 * 1) the length of the item can only be determined
3476 * by dissection (typically true of items with
3477 * subitems, which are probably FT_NONE or
3482 * 2) if the tvbuff is "short" (either due to a short
3483 * snapshot length or due to lack of reassembly of
3484 * fragments/segments/whatever), we want to display
3485 * what's available in the field (probably FT_BYTES
3486 * or FT_STRING) and then throw an exception later
3490 * 3) the field is defined to be "what's left in the
3493 * so we set the length to what remains in the tvbuff so
3494 * that, if we throw an exception while dissecting, it
3495 * has what is probably the right value.
3497 * For FT_STRINGZ, it means "the string is null-terminated,
3498 * not null-padded; set the length to the actual length
3499 * of the string", and if the tvbuff if short, we just
3500 * throw an exception.
3502 * It's not valid for any other type of field.
3504 switch (hfinfo->type) {
3508 * We allow this to be zero-length - for
3509 * example, an ONC RPC NULL procedure has
3510 * neither arguments nor reply, so the
3511 * payload for that protocol is empty.
3513 * However, if the length is negative, the
3514 * start offset is *past* the byte past the
3515 * end of the tvbuff, so we throw an
3518 *length = tvb_length_remaining(tvb, start);
3521 * Use "tvb_ensure_bytes_exist()"
3522 * to force the appropriate exception
3525 tvb_ensure_bytes_exist(tvb, start, 0);
3527 DISSECTOR_ASSERT(*length >= 0);
3533 *length = tvb_ensure_length_remaining(tvb, start);
3534 DISSECTOR_ASSERT(*length >= 0);
3539 * Leave the length as -1, so our caller knows
3545 DISSECTOR_ASSERT_NOT_REACHED();
3547 *item_length = *length;
3549 *item_length = *length;
3550 if (hfinfo->type == FT_PROTOCOL || hfinfo->type == FT_NONE) {
3552 * These types are for interior nodes of the
3553 * tree, and don't have data associated with
3554 * them; if the length is negative (XXX - see
3555 * above) or goes past the end of the tvbuff,
3556 * cut it short at the end of the tvbuff.
3557 * That way, if this field is selected in
3558 * Wireshark, we don't highlight stuff past
3559 * the end of the data.
3561 /* XXX - what to do, if we don't have a tvb? */
3563 length_remaining = tvb_length_remaining(tvb, start);
3564 if (*item_length < 0 ||
3565 (*item_length > 0 &&
3566 (length_remaining < *item_length)))
3567 *item_length = length_remaining;
3570 if (*item_length < 0) {
3571 THROW(ReportedBoundsError);
3579 new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
3580 const gint start, const gint item_length)
3586 fi->hfinfo = hfinfo;
3588 fi->start += (tvb)?tvb_raw_offset(tvb):0;
3589 fi->length = item_length;
3592 if (!PTREE_DATA(tree)->visible)
3593 FI_SET_FLAG(fi, FI_HIDDEN);
3594 fvalue_init(&fi->value, fi->hfinfo->type);
3597 /* add the data source tvbuff */
3598 fi->ds_tvb = tvb ? tvb_get_ds_tvb(tvb) : NULL;
3600 fi->appendix_start = 0;
3601 fi->appendix_length = 0;
3607 alloc_field_info(proto_tree *tree, int hfindex, tvbuff_t *tvb, const gint start,
3610 header_field_info *hfinfo;
3613 hfinfo = get_hfi_and_length(hfindex, tvb, start, length, &item_length);
3614 return new_field_info(tree, hfinfo, tvb, start, item_length);
3617 /* If the protocol tree is to be visible, set the representation of a
3618 proto_tree entry with the name of the field for the item and with
3619 the value formatted with the supplied printf-style format and
3622 proto_tree_set_representation_value(proto_item *pi, const char *format, va_list ap)
3624 int ret; /*tmp return value */
3625 field_info *fi = PITEM_FINFO(pi);
3626 header_field_info *hf;
3628 DISSECTOR_ASSERT(fi);
3632 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
3633 ITEM_LABEL_NEW(fi->rep);
3634 if (hf->bitmask && (hf->type == FT_BOOLEAN || IS_FT_UINT(hf->type))) {
3638 val = fvalue_get_uinteger(&fi->value);
3639 if (hf->bitshift > 0) {
3640 val <<= hf->bitshift;
3642 decode_bitfield_value(tmpbuf, val, hf->bitmask, hfinfo_bitwidth(hf));
3643 /* put in the hf name */
3644 ret = g_snprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
3645 "%s%s: ", tmpbuf, fi->hfinfo->name);
3647 /* put in the hf name */
3648 ret = g_snprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
3649 "%s: ", fi->hfinfo->name);
3652 /* If possible, Put in the value of the string */
3653 if (ret < ITEM_LABEL_LENGTH) {
3654 ret += g_vsnprintf(fi->rep->representation + ret,
3655 ITEM_LABEL_LENGTH - ret, format, ap);
3657 if (ret >= ITEM_LABEL_LENGTH) {
3658 /* Uh oh, we don't have enough room. Tell the user
3659 * that the field is truncated.
3663 /* Argh, we cannot reuse 'ap' here. So make a copy
3664 * of what we formatted for (re)use below.
3666 oldrep = g_strdup(fi->rep->representation);
3668 g_snprintf(fi->rep->representation,
3677 /* If the protocol tree is to be visible, set the representation of a
3678 proto_tree entry with the representation formatted with the supplied
3679 printf-style format and argument list. */
3681 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap)
3683 int ret; /*tmp return value */
3684 field_info *fi = PITEM_FINFO(pi);
3686 DISSECTOR_ASSERT(fi);
3688 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
3689 ITEM_LABEL_NEW(fi->rep);
3690 ret = g_vsnprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
3692 if (ret >= ITEM_LABEL_LENGTH) {
3693 /* Uh oh, we don't have enough room. Tell the user
3694 * that the field is truncated.
3698 /* Argh, we cannot reuse 'ap' here. So make a copy
3699 * of what we formatted for (re)use below.
3701 oldrep = g_strdup(fi->rep->representation);
3703 g_snprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
3704 "[truncated] %s", oldrep);
3711 protoo_strlcpy(gchar *dest, const gchar *src, gsize dest_size)
3713 gsize res = g_strlcpy(dest, src, dest_size);
3715 if (res > dest_size)
3720 /* -------------------------- */
3722 proto_custom_set(proto_tree* tree, const int field_id, gint occurrence,
3723 gchar *result, gchar *expr, const int size)
3729 struct e_in6_addr *ipv6;
3731 guint32 n_addr; /* network-order IPv4 address */
3733 const true_false_string *tfstring;
3735 int len, prev_len = 0, last, i, offset_r = 0, offset_e = 0;
3737 field_info *finfo = NULL;
3738 header_field_info* hfinfo;
3739 const gchar *abbrev = NULL;
3741 g_assert(field_id >= 0);
3743 hfinfo = proto_registrar_get_nth((guint)field_id);
3745 /* do we need to rewind ? */
3749 if (occurrence < 0) {
3750 /* Search other direction */
3751 while (hfinfo->same_name_prev) {
3752 hfinfo = hfinfo->same_name_prev;
3757 finfos = proto_get_finfo_ptr_array(tree, hfinfo->id);
3759 if (!finfos || !(len = g_ptr_array_len(finfos))) {
3760 if (occurrence < 0) {
3761 hfinfo = hfinfo->same_name_next;
3763 hfinfo = hfinfo->same_name_prev;
3768 /* Are there enough occurrences of the field? */
3769 if (((occurrence - prev_len) > len) || ((occurrence + prev_len) < -len)) {
3770 if (occurrence < 0) {
3771 hfinfo = hfinfo->same_name_next;
3773 hfinfo = hfinfo->same_name_prev;
3779 /* Calculate single index or set outer bounderies */
3780 if (occurrence < 0) {
3781 i = occurrence + len + prev_len;
3783 } else if (occurrence > 0) {
3784 i = occurrence - 1 - prev_len;
3791 prev_len += len; /* Count handled occurrences */
3794 finfo = g_ptr_array_index(finfos, i);
3796 if (offset_r && (offset_r < (size - 2)))
3797 result[offset_r++] = ',';
3799 if (offset_e && (offset_e < (size - 2)))
3800 expr[offset_e++] = ',';
3802 switch (hfinfo->type) {
3804 case FT_NONE: /* Nothing to add */
3805 if (offset_r == 0) {
3807 } else if (result[offset_r-1] == ',') {
3808 result[offset_r-1] = '\0';
3813 /* prevent multiple "yes" entries by setting result directly */
3814 g_strlcpy(result, "Yes", size);
3819 bytes = fvalue_get(&finfo->value);
3820 offset_r += protoo_strlcpy(result+offset_r,
3822 fvalue_length(&finfo->value)),
3826 case FT_ABSOLUTE_TIME:
3827 offset_r += protoo_strlcpy(result+offset_r,
3828 abs_time_to_str(fvalue_get(&finfo->value),
3829 hfinfo->display, TRUE),
3833 case FT_RELATIVE_TIME:
3834 offset_r += protoo_strlcpy(result+offset_r,
3835 rel_time_to_secs_str(fvalue_get(&finfo->value)),
3840 u_integer = fvalue_get_uinteger(&finfo->value);
3841 tfstring = (const true_false_string *)&tfs_true_false;
3842 if (hfinfo->strings) {
3843 tfstring = (const struct true_false_string*) hfinfo->strings;
3845 offset_r += protoo_strlcpy(result+offset_r,
3847 tfstring->true_string :
3848 tfstring->false_string, size-offset_r);
3850 g_snprintf(expr+offset_e, size-offset_e, "%u",
3851 fvalue_get_uinteger(&finfo->value) ? 1 : 0);
3852 offset_e = (int)strlen(expr);
3860 u_integer = fvalue_get_uinteger(&finfo->value);
3861 if ((hfinfo->display & BASE_DISPLAY_E_MASK) == BASE_CUSTOM) {
3862 gchar tmp[ITEM_LABEL_LENGTH];
3863 custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hfinfo->strings;
3865 DISSECTOR_ASSERT(fmtfunc);
3866 fmtfunc(tmp, u_integer);
3867 g_snprintf(result+offset_r, size-offset_r, "%s", tmp);
3868 } else if (hfinfo->strings) {
3869 if (hfinfo->display & BASE_RANGE_STRING) {
3870 g_strlcpy(result+offset_r,
3871 rval_to_str(u_integer, hfinfo->strings, "%u"),
3873 } else if (hfinfo->display & BASE_EXT_STRING) {
3874 g_strlcpy(result+offset_r,
3875 val_to_str_ext(u_integer,
3876 (value_string_ext *)(hfinfo->strings),
3877 "%u"), size-offset_r);
3879 g_strlcpy(result+offset_r,
3880 val_to_str(u_integer, cVALS(hfinfo->strings), "%u"),
3883 } else if (IS_BASE_DUAL(hfinfo->display)) {
3884 g_snprintf(result+offset_r, size-offset_r,
3885 hfinfo_uint_value_format(hfinfo), u_integer, u_integer);
3887 g_snprintf(result+offset_r, size-offset_r,
3888 hfinfo_uint_value_format(hfinfo), u_integer);
3891 if (hfinfo->strings && (hfinfo->display & BASE_DISPLAY_E_MASK) == BASE_NONE) {
3892 g_snprintf(expr+offset_e, size-offset_e,
3893 "\"%s\"", result+offset_r);
3895 g_snprintf(expr+offset_e, size-offset_e,
3896 hfinfo_numeric_value_format(hfinfo),
3897 fvalue_get_uinteger(&finfo->value));
3900 offset_r = (int)strlen(result);
3901 offset_e = (int)strlen(expr);
3905 /* XXX: Should handle BASE_CUSTOM ? */
3906 g_snprintf(result+offset_r, size-offset_r,
3907 "%" G_GINT64_MODIFIER "d",
3908 fvalue_get_integer64(&finfo->value));
3909 offset_r = (int)strlen(result);
3912 g_snprintf(result+offset_r, size-offset_r,
3913 /* XXX: Should handle BASE_CUSTOM ? */
3914 "%" G_GINT64_MODIFIER "u",
3915 fvalue_get_integer64(&finfo->value));
3916 offset_r = (int)strlen(result);
3919 offset_r += protoo_strlcpy(result+offset_r,
3920 eui64_to_str(fvalue_get_integer64(&finfo->value)),
3923 /* XXX - make these just FT_INT? */
3928 integer = fvalue_get_sinteger(&finfo->value);
3929 if ((hfinfo->display & BASE_DISPLAY_E_MASK) == BASE_CUSTOM) {
3930 gchar tmp[ITEM_LABEL_LENGTH];
3931 custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hfinfo->strings;
3933 DISSECTOR_ASSERT(fmtfunc);
3934 fmtfunc(tmp, integer);
3935 g_snprintf(result+offset_r, size-offset_r, "%s", tmp);
3936 } else if (hfinfo->strings) {
3937 if (hfinfo->display & BASE_RANGE_STRING) {
3938 g_strlcpy(result+offset_r,
3939 rval_to_str(integer, hfinfo->strings, "%d"),
3941 } else if (hfinfo->display & BASE_EXT_STRING) {
3942 g_strlcpy(result+offset_r,
3943 val_to_str_ext(integer,
3944 (value_string_ext *)(hfinfo->strings),
3948 g_strlcpy(result+offset_r,
3949 val_to_str(integer, cVALS(hfinfo->strings), "%d"),
3952 } else if (IS_BASE_DUAL(hfinfo->display)) {
3953 g_snprintf(result+offset_r, size-offset_r,
3954 hfinfo_int_value_format(hfinfo), integer, integer);
3956 g_snprintf(result+offset_r, size-offset_r,
3957 hfinfo_int_value_format(hfinfo), integer);
3960 if (hfinfo->strings && (hfinfo->display & BASE_DISPLAY_E_MASK) == BASE_NONE) {
3961 g_snprintf(expr+offset_e, size-offset_e, "\"%s\"", result+offset_r);
3963 g_snprintf(expr+offset_e, size-offset_e,
3964 hfinfo_numeric_value_format(hfinfo),
3965 fvalue_get_sinteger(&finfo->value));
3968 offset_r = (int)strlen(result);
3969 offset_e = (int)strlen(expr);
3973 ipv4 = fvalue_get(&finfo->value);
3974 n_addr = ipv4_get_net_order_addr(ipv4);
3975 offset_r += protoo_strlcpy(result+offset_r,
3976 ip_to_str((guint8 *)&n_addr),
3981 ipv6 = fvalue_get(&finfo->value);
3982 SET_ADDRESS (&addr, AT_IPv6, sizeof(struct e_in6_addr), ipv6);
3983 address_to_str_buf(&addr, result+offset_r, size-offset_r);
3984 offset_r = (int)strlen(result);
3988 offset_r += protoo_strlcpy(result+offset_r,
3989 bytes_to_str_punct(fvalue_get(&finfo->value),
3995 offset_r += protoo_strlcpy(result+offset_r,
3996 guid_to_str((e_guid_t *)fvalue_get(&finfo->value)),
4001 bytes = fvalue_get(&finfo->value);
4002 offset_r += protoo_strlcpy(result+offset_r,
4003 oid_resolved_from_encoded(bytes,
4004 fvalue_length(&finfo->value)),
4006 offset_e += protoo_strlcpy(expr+offset_e,
4007 oid_encoded2string(bytes, fvalue_length(&finfo->value)),
4012 g_snprintf(result+offset_r, size-offset_r,
4013 "%." STRINGIFY(FLT_DIG) "g", fvalue_get_floating(&finfo->value));
4014 offset_r = (int)strlen(result);
4018 g_snprintf(result+offset_r, size-offset_r,
4019 "%." STRINGIFY(DBL_DIG) "g", fvalue_get_floating(&finfo->value));
4020 offset_r = (int)strlen(result);
4025 case FT_UINT_STRING:
4026 bytes = fvalue_get(&finfo->value);
4027 offset_r += protoo_strlcpy(result+offset_r,
4028 format_text(bytes, strlen(bytes)),
4032 case FT_IPXNET: /*XXX really No column custom ?*/
4035 g_error("hfinfo->type %d (%s) not handled\n",
4037 ftype_name(hfinfo->type));
4038 DISSECTOR_ASSERT_NOT_REACHED();
4044 switch (hfinfo->type) {
4057 /* for these types, "expr" is filled in the loop above */
4061 /* for all others, just copy "result" to "expr" */
4062 g_strlcpy(expr, result, size);
4067 /* Store abbrev for return value */
4068 abbrev = hfinfo->abbrev;
4071 if (occurrence == 0) {
4072 /* Fetch next hfinfo with same name (abbrev) */
4073 hfinfo = hfinfo->same_name_prev;
4079 return abbrev ? abbrev : "";
4083 /* Set text of proto_item after having already been created. */
4085 proto_item_set_text(proto_item *pi, const char *format, ...)
4087 field_info *fi = NULL;
4094 fi = PITEM_FINFO(pi);
4099 ITEM_LABEL_FREE(fi->rep);
4102 va_start(ap, format);
4103 proto_tree_set_representation(pi, format, ap);
4107 /* Append to text of proto_item after having already been created. */
4109 proto_item_append_text(proto_item *pi, const char *format, ...)
4111 field_info *fi = NULL;
4119 fi = PITEM_FINFO(pi);
4124 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
4126 * If we don't already have a representation,
4127 * generate the default representation.
4129 if (fi->rep == NULL) {
4130 ITEM_LABEL_NEW(fi->rep);
4131 proto_item_fill_label(fi, fi->rep->representation);
4134 curlen = strlen(fi->rep->representation);
4135 if (ITEM_LABEL_LENGTH > curlen) {
4136 va_start(ap, format);
4137 g_vsnprintf(fi->rep->representation + curlen,
4138 ITEM_LABEL_LENGTH - (gulong) curlen, format, ap);
4144 /* Prepend to text of proto_item after having already been created. */
4146 proto_item_prepend_text(proto_item *pi, const char *format, ...)
4148 field_info *fi = NULL;
4149 char representation[ITEM_LABEL_LENGTH];
4156 fi = PITEM_FINFO(pi);
4161 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
4163 * If we don't already have a representation,
4164 * generate the default representation.
4166 if (fi->rep == NULL) {
4167 ITEM_LABEL_NEW(fi->rep);
4168 proto_item_fill_label(fi, fi->rep->representation);
4171 g_strlcpy(representation, fi->rep->representation, ITEM_LABEL_LENGTH);
4172 va_start(ap, format);
4173 g_vsnprintf(fi->rep->representation,
4174 ITEM_LABEL_LENGTH, format, ap);
4176 g_strlcat(fi->rep->representation, representation, ITEM_LABEL_LENGTH);
4181 proto_item_set_len(proto_item *pi, const gint length)
4188 fi = PITEM_FINFO(pi);
4192 DISSECTOR_ASSERT(length >= 0);
4193 fi->length = length;
4196 * You cannot just make the "len" field of a GByteArray
4197 * larger, if there's no data to back that length;
4198 * you can only make it smaller.
4200 if (fi->value.ftype->ftype == FT_BYTES && length <= (gint)fi->value.value.bytes->len)
4201 fi->value.value.bytes->len = length;
4205 * Sets the length of the item based on its start and on the specified
4206 * offset, which is the offset past the end of the item; as the start
4207 * in the item is relative to the beginning of the data source tvbuff,
4208 * we need to pass in a tvbuff - the end offset is relative to the beginning
4212 proto_item_set_end(proto_item *pi, tvbuff_t *tvb, gint end)
4219 fi = PITEM_FINFO(pi);
4223 end += tvb_raw_offset(tvb);
4224 DISSECTOR_ASSERT(end >= fi->start);
4225 fi->length = end - fi->start;
4229 proto_item_get_len(const proto_item *pi)
4231 field_info *fi = PITEM_FINFO(pi);
4232 return fi ? fi->length : -1;
4236 /** clear flags according to the mask and set new flag values */
4237 #define FI_REPLACE_FLAGS(fi, mask, flags_in) { \
4238 (fi->flags = (fi)->flags & ~(mask)); \
4239 (fi->flags = (fi)->flags | (flags_in)); \
4243 proto_item_set_expert_flags(proto_item *pi, const int group, const guint severity)
4245 if (pi == NULL || PITEM_FINFO(pi) == NULL)
4248 /* only change things if severity is worse or at least equal than before */
4249 if (severity >= FI_GET_FLAG(PITEM_FINFO(pi), PI_SEVERITY_MASK)) {
4250 FI_REPLACE_FLAGS(PITEM_FINFO(pi), PI_GROUP_MASK, group);
4251 FI_REPLACE_FLAGS(PITEM_FINFO(pi), PI_SEVERITY_MASK, severity);
4260 proto_tree_create_root(packet_info *pinfo)
4264 /* Initialize the proto_node */
4265 PROTO_NODE_NEW(pnode);
4266 pnode->parent = NULL;
4267 PNODE_FINFO(pnode) = NULL;
4268 pnode->tree_data = g_new(tree_data_t, 1);
4270 /* Make sure we can access pinfo everywhere */
4271 pnode->tree_data->pinfo = pinfo;
4273 /* Don't initialize the tree_data_t. Wait until we know we need it */
4274 pnode->tree_data->interesting_hfids = NULL;
4276 /* Set the default to FALSE so it's easier to
4277 * find errors; if we expect to see the protocol tree
4278 * but for some reason the default 'visible' is not
4279 * changed, then we'll find out very quickly. */
4280 pnode->tree_data->visible = FALSE;
4282 /* Make sure that we fake protocols (if possible) */
4283 pnode->tree_data->fake_protocols = TRUE;
4285 /* Keep track of the number of children */
4286 pnode->tree_data->count = 0;
4288 pnode->tree_data->fi_tmp = NULL;
4290 return (proto_tree *)pnode;
4294 /* "prime" a proto_tree with a single hfid that a dfilter
4295 * is interested in. */
4297 proto_tree_prime_hfid(proto_tree *tree _U_, const gint hfid)
4299 header_field_info *hfinfo;
4301 PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
4302 /* this field is referenced by a filter so increase the refcount.
4303 also increase the refcount for the parent, i.e the protocol.
4305 hfinfo->ref_type = HF_REF_TYPE_DIRECT;
4306 /* only increase the refcount if there is a parent.
4307 if this is a protocol and not a field then parent will be -1
4308 and there is no parent to add any refcounting for.
4310 if (hfinfo->parent != -1) {
4311 header_field_info *parent_hfinfo;
4312 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
4314 /* Mark parent as indirectly referenced unless it is already directly
4315 * referenced, i.e. the user has specified the parent in a filter.
4317 if (parent_hfinfo->ref_type != HF_REF_TYPE_DIRECT)
4318 parent_hfinfo->ref_type = HF_REF_TYPE_INDIRECT;
4323 proto_item_add_subtree(proto_item *pi, const gint idx) {
4329 DISSECTOR_ASSERT(idx >= 0 && idx < num_tree_types);
4331 fi = PITEM_FINFO(pi);
4333 return (proto_tree *)pi;
4335 fi->tree_type = idx;
4337 return (proto_tree *)pi;
4341 proto_item_get_subtree(const proto_item *pi) {
4346 fi = PITEM_FINFO(pi);
4347 if ( (!fi) || (fi->tree_type == -1) )
4349 return (proto_tree *)pi;
4353 proto_item_get_parent(const proto_item *ti) {
4360 proto_item_get_parent_nth(proto_item *ti, int gen) {
4373 proto_tree_get_parent(const proto_tree *tree) {
4376 return (proto_item *)tree;
4380 proto_tree_get_root(proto_tree *tree) {
4383 while (tree->parent) {
4384 tree = tree->parent;
4390 proto_tree_move_item(proto_tree *tree, proto_item *fixed_item,
4391 proto_item *item_to_move)
4394 /* Revert part of: http://anonsvn.wireshark.org/viewvc?view=rev&revision=32443
4395 * See https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=5500
4397 /* This function doesn't generate any values. It only reorganizes the prococol tree
4398 * so we can bail out immediately if it isn't visible. */
4399 if (!tree || !PTREE_DATA(tree)->visible)
4402 DISSECTOR_ASSERT(item_to_move->parent == tree);
4403 DISSECTOR_ASSERT(fixed_item->parent == tree);
4405 /*** cut item_to_move out ***/
4407 /* is item_to_move the first? */
4408 if (tree->first_child == item_to_move) {
4409 /* simply change first child to next */
4410 tree->first_child = item_to_move->next;
4412 DISSECTOR_ASSERT(tree->last_child != item_to_move);
4414 proto_item *curr_item;
4415 /* find previous and change it's next */
4416 for(curr_item = tree->first_child; curr_item != NULL; curr_item = curr_item->next) {
4417 if (curr_item->next == item_to_move) {
4422 DISSECTOR_ASSERT(curr_item);
4424 curr_item->next = item_to_move->next;
4426 /* fix last_child if required */
4427 if (tree->last_child == item_to_move) {
4428 tree->last_child = curr_item;
4432 /*** insert to_move after fixed ***/
4433 item_to_move->next = fixed_item->next;
4434 fixed_item->next = item_to_move;
4435 if (tree->last_child == fixed_item) {
4436 tree->last_child = item_to_move;
4441 proto_tree_set_appendix(proto_tree *tree, tvbuff_t *tvb, gint start,
4449 fi = PTREE_FINFO(tree);
4453 start += tvb_raw_offset(tvb);
4454 DISSECTOR_ASSERT(start >= 0);
4455 DISSECTOR_ASSERT(length >= 0);
4457 fi->appendix_start = start;
4458 fi->appendix_length = length;
4462 proto_register_protocol(const char *name, const char *short_name,
4463 const char *filter_name)
4465 protocol_t *protocol;
4466 header_field_info *hfinfo;
4468 char *existing_name;
4472 gboolean found_invalid;
4475 * Make sure there's not already a protocol with any of those
4476 * names. Crash if there is, as that's an error in the code
4477 * or an inappropriate plugin.
4478 * This situation has to be fixed to not register more than one
4479 * protocol with the same name.
4481 * This is done by reducing the number of strcmp (and alike) calls
4482 * as much as possible, as this significally slows down startup time.
4484 * Drawback: As a hash value is used to reduce insert time,
4485 * this might lead to a hash collision.
4486 * However, although we have somewhat over 1000 protocols, we're using
4487 * a 32 bit int so this is very, very unlikely.
4490 key = g_malloc (sizeof(gint));
4491 *key = wrs_str_hash(name);
4493 existing_name = g_hash_table_lookup(proto_names, key);
4494 if (existing_name != NULL) {
4495 /* g_error will terminate the program */
4496 g_error("Duplicate protocol name \"%s\"!"
4497 " This might be caused by an inappropriate plugin or a development error.", name);
4499 g_hash_table_insert(proto_names, key, (gpointer)name);
4501 existing_name = g_hash_table_lookup(proto_short_names, (gpointer)short_name);
4502 if (existing_name != NULL) {
4503 g_error("Duplicate protocol short_name \"%s\"!"
4504 " This might be caused by an inappropriate plugin or a development error.", short_name);
4506 g_hash_table_insert(proto_short_names, (gpointer)short_name, (gpointer)short_name);
4508 found_invalid = FALSE;
4509 for (i = 0; filter_name[i]; i++) {
4511 if (!(islower(c) || isdigit(c) || c == '-' || c == '_' || c == '.')) {
4512 found_invalid = TRUE;
4515 if (found_invalid) {
4516 g_error("Protocol filter name \"%s\" has one or more invalid characters."
4517 " Allowed are lower characters, digits, '-', '_' and '.'."
4518 " This might be caused by an inappropriate plugin or a development error.", filter_name);
4520 existing_name = g_hash_table_lookup(proto_filter_names, (gpointer)filter_name);
4521 if (existing_name != NULL) {
4522 g_error("Duplicate protocol filter_name \"%s\"!"
4523 " This might be caused by an inappropriate plugin or a development error.", filter_name);
4525 g_hash_table_insert(proto_filter_names, (gpointer)filter_name, (gpointer)filter_name);
4527 /* Add this protocol to the list of known protocols; the list
4528 is sorted by protocol short name. */
4529 protocol = g_new(protocol_t, 1);
4530 protocol->name = name;
4531 protocol->short_name = short_name;
4532 protocol->filter_name = filter_name;
4533 protocol->fields = NULL;
4534 protocol->is_enabled = TRUE; /* protocol is enabled by default */
4535 protocol->can_toggle = TRUE;
4536 protocol->is_private = FALSE;
4537 /* list will be sorted later by name, when all protocols completed registering */
4538 protocols = g_list_prepend(protocols, protocol);
4540 /* Here we allocate a new header_field_info struct */
4541 hfinfo = g_slice_new(header_field_info);
4542 hfinfo->name = name;
4543 hfinfo->abbrev = filter_name;
4544 hfinfo->type = FT_PROTOCOL;
4545 hfinfo->display = BASE_NONE;
4546 hfinfo->strings = protocol;
4547 hfinfo->bitmask = 0;
4548 hfinfo->bitshift = 0;
4549 hfinfo->ref_type = HF_REF_TYPE_NONE;
4550 hfinfo->blurb = NULL;
4551 hfinfo->parent = -1; /* this field differentiates protos and fields */
4553 proto_id = proto_register_field_init(hfinfo, hfinfo->parent);
4554 protocol->proto_id = proto_id;
4559 proto_mark_private(const int proto_id)
4561 protocol_t *protocol = find_protocol_by_id(proto_id);
4563 protocol->is_private = TRUE;
4567 proto_is_private(const int proto_id)
4569 protocol_t *protocol = find_protocol_by_id(proto_id);
4571 return protocol->is_private;
4577 * Routines to use to iterate over the protocols.
4578 * The argument passed to the iterator routines is an opaque cookie to
4579 * their callers; it's the GList pointer for the current element in
4581 * The ID of the protocol is returned, or -1 if there is no protocol.
4584 proto_get_first_protocol(void **cookie)
4586 protocol_t *protocol;
4588 if (protocols == NULL)
4590 *cookie = protocols;
4591 protocol = protocols->data;
4592 return protocol->proto_id;
4596 proto_get_data_protocol(void *cookie)
4598 GList *list_item = cookie;
4600 protocol_t *protocol = list_item->data;
4601 return protocol->proto_id;
4605 proto_get_next_protocol(void **cookie)
4607 GList *list_item = *cookie;
4608 protocol_t *protocol;
4610 list_item = g_list_next(list_item);
4611 if (list_item == NULL)
4613 *cookie = list_item;
4614 protocol = list_item->data;
4615 return protocol->proto_id;
4619 proto_get_first_protocol_field(const int proto_id, void **cookie)
4621 protocol_t *protocol = find_protocol_by_id(proto_id);
4622 hf_register_info *ptr;
4624 if ((protocol == NULL) || (protocol->fields == NULL))
4627 *cookie = protocol->fields;
4628 ptr = protocol->fields->data;
4629 return &ptr->hfinfo;
4633 proto_get_next_protocol_field(void **cookie)
4635 GList *list_item = *cookie;
4636 hf_register_info *ptr;
4638 list_item = g_list_next(list_item);
4639 if (list_item == NULL)
4642 *cookie = list_item;
4643 ptr = list_item->data;
4644 return &ptr->hfinfo;
4648 find_protocol_by_id(const int proto_id)
4650 header_field_info *hfinfo;
4655 PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
4656 DISSECTOR_ASSERT(hfinfo->type == FT_PROTOCOL);
4657 return (protocol_t *)hfinfo->strings;
4660 static gint compare_filter_name(gconstpointer proto_arg,
4661 gconstpointer filter_name)
4663 const protocol_t *protocol = proto_arg;
4664 const gchar *f_name = filter_name;
4666 return (strcmp(protocol->filter_name, f_name));
4670 proto_get_id(const protocol_t *protocol)
4672 return protocol->proto_id;
4675 int proto_get_id_by_filter_name(const gchar* filter_name)
4678 protocol_t *protocol;
4680 list_entry = g_list_find_custom(protocols, filter_name,
4681 compare_filter_name);
4683 if (list_entry == NULL)
4685 protocol = list_entry->data;
4686 return protocol->proto_id;
4690 proto_get_protocol_name(const int proto_id)
4692 protocol_t *protocol;
4694 protocol = find_protocol_by_id(proto_id);
4696 if (protocol == NULL)
4698 return protocol->name;
4702 proto_get_protocol_short_name(const protocol_t *protocol)
4704 if (protocol == NULL)
4706 return protocol->short_name;
4710 proto_get_protocol_long_name(const protocol_t *protocol)
4712 if (protocol == NULL)
4714 return protocol->name;
4718 proto_get_protocol_filter_name(const int proto_id)
4720 protocol_t *protocol;
4722 protocol = find_protocol_by_id(proto_id);
4723 if (protocol == NULL)
4725 return protocol->filter_name;
4729 proto_is_protocol_enabled(const protocol_t *protocol)
4731 return protocol->is_enabled;
4735 proto_can_toggle_protocol(const int proto_id)
4737 protocol_t *protocol;
4739 protocol = find_protocol_by_id(proto_id);
4740 return protocol->can_toggle;
4744 proto_set_decoding(const int proto_id, const gboolean enabled)
4746 protocol_t *protocol;
4748 protocol = find_protocol_by_id(proto_id);
4749 DISSECTOR_ASSERT(protocol->can_toggle);
4750 protocol->is_enabled = enabled;
4754 proto_enable_all(void)
4756 protocol_t *protocol;
4757 GList *list_item = protocols;
4759 if (protocols == NULL)
4763 protocol = list_item->data;
4764 if (protocol->can_toggle)
4765 protocol->is_enabled = TRUE;
4766 list_item = g_list_next(list_item);
4771 proto_set_cant_toggle(const int proto_id)
4773 protocol_t *protocol;
4775 protocol = find_protocol_by_id(proto_id);
4776 protocol->can_toggle = FALSE;
4779 /* for use with static arrays only, since we don't allocate our own copies
4780 of the header_field_info struct contained within the hf_register_info struct */
4782 proto_register_field_array(const int parent, hf_register_info *hf, const int num_records)
4785 hf_register_info *ptr = hf;
4788 proto = find_protocol_by_id(parent);
4789 for (i = 0; i < num_records; i++, ptr++) {
4791 * Make sure we haven't registered this yet.
4792 * Most fields have variables associated with them
4793 * that are initialized to -1; some have array elements,
4794 * or possibly uninitialized variables, so we also allow
4795 * 0 (which is unlikely to be the field ID we get back
4796 * from "proto_register_field_init()").
4798 if (*ptr->p_id != -1 && *ptr->p_id != 0) {
4800 "Duplicate field detected in call to proto_register_field_array: %s is already registered\n",
4801 ptr->hfinfo.abbrev);
4805 if (proto != NULL) {
4806 if (proto->fields == NULL) {
4807 proto->fields = g_list_append(NULL, ptr);
4808 proto->last_field = proto->fields;
4811 g_list_append(proto->last_field, ptr)->next;
4814 field_id = proto_register_field_init(&ptr->hfinfo, parent);
4815 *ptr->p_id = field_id;
4819 /* unregister already registered fields */
4821 proto_unregister_field (const int parent, gint hf_id)
4823 hf_register_info *hf;
4827 if (hf_id == -1 || hf_id == 0)
4830 proto = find_protocol_by_id (parent);
4831 if (!proto || !proto->fields) {
4835 for (field = g_list_first (proto->fields); field; field = g_list_next (field)) {
4837 if (*hf->p_id == hf_id) {
4838 /* Found the hf_id in this protocol */
4839 g_tree_steal (gpa_name_tree, hf->hfinfo.abbrev);
4840 proto->fields = g_list_remove_link (proto->fields, field);
4841 proto->last_field = g_list_last (proto->fields);
4847 /* chars allowed in field abbrev */
4849 const guchar fld_abbrev_chars[256] = {
4850 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00-0x0F */
4851 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10-0x1F */
4852 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, /* 0x20-0x2F '-', '.' */
4853 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 0x30-0x3F '0'-'9' */
4854 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x40-0x4F 'A'-'O' */
4855 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 0x50-0x5F 'P'-'Z', '_' */
4856 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x60-0x6F 'a'-'o' */
4857 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 0x70-0x7F 'p'-'z' */
4858 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80-0x8F */
4859 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90-0x9F */
4860 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xA0-0xAF */
4861 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xB0-0xBF */
4862 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xC0-0xCF */
4863 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xD0-0xDF */
4864 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xE0-0xEF */
4865 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xF0-0xFF */
4868 static const value_string hf_types[] = {
4869 { FT_NONE, "FT_NONE" },
4870 { FT_PROTOCOL, "FT_PROTOCOL" },
4871 { FT_BOOLEAN, "FT_BOOLEAN" },
4872 { FT_UINT8, "FT_UINT8" },
4873 { FT_UINT16, "FT_UINT16" },
4874 { FT_UINT24, "FT_UINT24" },
4875 { FT_UINT32, "FT_UINT32" },
4876 { FT_UINT64, "FT_UINT64" },
4877 { FT_INT8, "FT_INT8" },
4878 { FT_INT16, "FT_INT16" },
4879 { FT_INT24, "FT_INT24" },
4880 { FT_INT32, "FT_INT32" },
4881 { FT_INT64, "FT_INT64" },
4882 { FT_EUI64, "FT_EUI64" },
4883 { FT_FLOAT, "FT_FLOAT" },
4884 { FT_DOUBLE, "FT_DOUBLE" },
4885 { FT_ABSOLUTE_TIME, "FT_ABSOLUTE_TIME" },
4886 { FT_RELATIVE_TIME, "FT_RELATIVE_TIME" },
4887 { FT_STRING, "FT_STRING" },
4888 { FT_STRINGZ, "FT_STRINGZ" },
4889 { FT_UINT_STRING, "FT_UINT_STRING" },
4890 { FT_ETHER, "FT_ETHER" },
4891 { FT_BYTES, "FT_BYTES" },
4892 { FT_UINT_BYTES, "FT_UINT_BYTES" },
4893 { FT_IPv4, "FT_IPv4" },
4894 { FT_IPv6, "FT_IPv6" },
4895 { FT_IPXNET, "FT_IPXNET" },
4896 { FT_FRAMENUM, "FT_FRAMENUM" },
4897 { FT_PCRE, "FT_PCR" },
4898 { FT_GUID, "FT_GUID" },
4899 { FT_OID, "FT_OID" },
4902 static const value_string hf_display[] = {
4903 { BASE_NONE, "BASE_NONE" },
4904 { BASE_DEC, "BASE_DEC" },
4905 { BASE_HEX, "BASE_HEX" },
4906 { BASE_OCT, "BASE_OCT" },
4907 { BASE_DEC_HEX, "BASE_DEC_HEX" },
4908 { BASE_HEX_DEC, "BASE_HEX_DEC" },
4909 { BASE_CUSTOM, "BASE_CUSTOM" },
4910 { BASE_NONE|BASE_RANGE_STRING, "BASE_NONE|BASE_RANGE_STRING" },
4911 { BASE_DEC|BASE_RANGE_STRING, "BASE_DEC|BASE_RANGE_STRING" },
4912 { BASE_HEX|BASE_RANGE_STRING, "BASE_HEX|BASE_RANGE_STRING" },
4913 { BASE_OCT|BASE_RANGE_STRING, "BASE_OCT|BASE_RANGE_STRING" },
4914 { BASE_DEC_HEX|BASE_RANGE_STRING, "BASE_DEC_HEX|BASE_RANGE_STRING" },
4915 { BASE_HEX_DEC|BASE_RANGE_STRING, "BASE_HEX_DEC|BASE_RANGE_STRING" },
4916 { BASE_CUSTOM|BASE_RANGE_STRING, "BASE_CUSTOM|BASE_RANGE_STRING" },
4917 { ABSOLUTE_TIME_LOCAL, "ABSOLUTE_TIME_LOCAL" },
4918 { ABSOLUTE_TIME_UTC, "ABSOLUTE_TIME_UTC" },
4919 { ABSOLUTE_TIME_DOY_UTC, "ABSOLUTE_TIME_DOY_UTC" },
4922 /* temporary function containing assert part for easier profiling */
4924 tmp_fld_check_assert(header_field_info *hfinfo)
4927 /* The field must have a name (with length > 0) */
4928 if (!hfinfo->name || !hfinfo->name[0]) {
4930 /* Try to identify the field */
4931 g_error("Field (abbrev='%s') does not have a name\n",
4935 g_error("Field does not have a name (nor an abbreviation)\n");
4938 /* fields with an empty string for an abbreviation aren't filterable */
4939 if (!hfinfo->abbrev || !hfinfo->abbrev[0])
4940 g_error("Field '%s' does not have an abbreviation\n", hfinfo->name);
4942 /* These types of fields are allowed to have value_strings,
4943 * true_false_strings or a protocol_t struct
4945 if (hfinfo->strings != NULL && !(
4946 (hfinfo->type == FT_UINT8) ||
4947 (hfinfo->type == FT_UINT16) ||
4948 (hfinfo->type == FT_UINT24) ||
4949 (hfinfo->type == FT_UINT32) ||
4950 (hfinfo->type == FT_INT8) ||
4951 (hfinfo->type == FT_INT16) ||
4952 (hfinfo->type == FT_INT24) ||
4953 (hfinfo->type == FT_INT32) ||
4954 (hfinfo->type == FT_BOOLEAN) ||
4955 (hfinfo->type == FT_PROTOCOL) ||
4956 (hfinfo->type == FT_FRAMENUM) ))
4957 g_error("Field '%s' (%s) has a 'strings' value but is of type %s"
4958 " (which is not allowed to have strings)\n",
4959 hfinfo->name, hfinfo->abbrev,
4960 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"));
4962 /* TODO: This check may slow down startup, and output quite a few warnings.
4963 It would be good to be able to enable this (and possibly other checks?)
4964 in non-release builds. */
4966 /* Check for duplicate value_string values.
4967 There are lots that have the same value *and* string, so for now only
4968 report those that have same value but different string. */
4969 if ((hfinfo->strings != NULL) &&
4970 !(hfinfo->display & BASE_RANGE_STRING) &&
4971 !((hfinfo->display & BASE_DISPLAY_E_MASK) == BASE_CUSTOM) &&
4973 (hfinfo->type == FT_UINT8) ||
4974 (hfinfo->type == FT_UINT16) ||
4975 (hfinfo->type == FT_UINT24) ||
4976 (hfinfo->type == FT_UINT32) ||
4977 (hfinfo->type == FT_INT8) ||
4978 (hfinfo->type == FT_INT16) ||
4979 (hfinfo->type == FT_INT24) ||
4980 (hfinfo->type == FT_INT32) ||
4981 (hfinfo->type == FT_FRAMENUM) )) {
4984 const value_string *start_values;
4985 const value_string *current;
4987 if (hfinfo->display & BASE_EXT_STRING)
4988 start_values = VALUE_STRING_EXT_VS_P(((const value_string_ext*)hfinfo->strings));
4990 start_values = (const value_string*)hfinfo->strings;
4991 current = start_values;
4993 for (n=0; current; n++, current++) {
4994 /* Drop out if we reached the end. */
4995 if ((current->value == 0) && (current->strptr == NULL)) {
4999 /* Check value against all previous */
5000 for (m=0; m < n; m++) {
5001 /* There are lots of duplicates with the same string,
5002 so only report if different... */
5003 if ((start_values[m].value == current->value) &&
5004 (strcmp(start_values[m].strptr, current->strptr) != 0)) {
5005 g_warning("Field '%s' (%s) has a conflicting entry in its"
5006 " value_string: %u is at indices %u (%s) and %u (%s))\n",
5007 hfinfo->name, hfinfo->abbrev,
5008 current->value, m, start_values[m].strptr, n, current->strptr);
5016 switch (hfinfo->type) {
5023 /* Hexadecimal and octal are, in printf() and everywhere
5024 * else, unsigned so don't allow dissectors to register a
5025 * signed field to be displayed unsigned. (Else how would
5026 * we display negative values?)
5028 * If you want to take out this check, be sure to fix
5029 * hfinfo_numeric_format() so that it does not assert out
5030 * when trying to construct a hexadecimal representation of
5033 if (hfinfo->display == BASE_HEX ||
5034 hfinfo->display == BASE_OCT)
5035 g_error("Field '%s' (%s) is signed (%s) but is being displayed unsigned (%s)\n",
5036 hfinfo->name, hfinfo->abbrev,
5037 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"),
5038 val_to_str(hfinfo->display, hf_display, "(Bit count: %d)"));
5045 /* Require integral types (other than frame number,
5046 * which is always displayed in decimal) to have a
5048 * If there is a strings value then this base is not
5049 * normally used except when constructing a display
5050 * filter for a value not found in the strings lookup.
5052 switch (hfinfo->display & BASE_DISPLAY_E_MASK) {
5058 case BASE_CUSTOM: /* hfinfo_numeric_value_format() treats this as decimal */
5061 g_error("Field '%s' (%s) is an integral value (%s)"
5062 " but is being displayed as %s\n",
5063 hfinfo->name, hfinfo->abbrev,
5064 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"),
5065 val_to_str(hfinfo->display, hf_display, "(Unknown: 0x%x)"));
5071 if (hfinfo->display != BASE_NONE)
5072 g_error("Field '%s' (%s) is an %s but is being displayed as %s instead of BASE_NONE\n",
5073 hfinfo->name, hfinfo->abbrev,
5074 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"),
5075 val_to_str(hfinfo->display, hf_display, "(Bit count: %d)"));
5076 if (hfinfo->bitmask != 0)
5077 g_error("Field '%s' (%s) is an %s but has a bitmask\n",
5078 hfinfo->name, hfinfo->abbrev,
5079 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"));
5085 case FT_ABSOLUTE_TIME:
5086 if (!(hfinfo->display == ABSOLUTE_TIME_LOCAL ||
5087 hfinfo->display == ABSOLUTE_TIME_UTC ||
5088 hfinfo->display == ABSOLUTE_TIME_DOY_UTC))
5089 g_error("Field '%s' (%s) is a %s but is being displayed as %s instead of as a time\n",
5090 hfinfo->name, hfinfo->abbrev,
5091 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"),
5092 val_to_str(hfinfo->display, hf_display, "(Bit count: %d)"));
5093 if (hfinfo->bitmask != 0)
5094 g_error("Field '%s' (%s) is an %s but has a bitmask\n",
5095 hfinfo->name, hfinfo->abbrev,
5096 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"));
5100 if (hfinfo->display != BASE_NONE)
5101 g_error("Field '%s' (%s) is an %s but is being displayed as %s instead of BASE_NONE\n",
5102 hfinfo->name, hfinfo->abbrev,
5103 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"),
5104 val_to_str(hfinfo->display, hf_display, "(Bit count: %d)"));
5105 if (hfinfo->bitmask != 0)
5106 g_error("Field '%s' (%s) is an %s but has a bitmask\n",
5107 hfinfo->name, hfinfo->abbrev,
5108 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"));
5109 if (hfinfo->strings != NULL)
5110 g_error("Field '%s' (%s) is an %s but has a strings value\n",
5111 hfinfo->name, hfinfo->abbrev,
5112 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"));
5117 #define PROTO_PRE_ALLOC_HF_FIELDS_MEM 120000
5119 proto_register_field_init(header_field_info *hfinfo, const int parent)
5122 tmp_fld_check_assert(hfinfo);
5124 /* if this is a bitfield, compute bitshift */
5125 if (hfinfo->bitmask) {
5126 hfinfo->bitshift = wrs_count_bitshift(hfinfo->bitmask);
5129 hfinfo->parent = parent;
5130 hfinfo->same_name_next = NULL;
5131 hfinfo->same_name_prev = NULL;
5133 /* if we always add and never delete, then id == len - 1 is correct */
5134 if (gpa_hfinfo.len >= gpa_hfinfo.allocated_len) {
5135 if (!gpa_hfinfo.hfi) {
5136 gpa_hfinfo.allocated_len = PROTO_PRE_ALLOC_HF_FIELDS_MEM;
5137 gpa_hfinfo.hfi = g_malloc(sizeof(header_field_info *)*PROTO_PRE_ALLOC_HF_FIELDS_MEM);
5139 gpa_hfinfo.allocated_len += 1000;
5140 gpa_hfinfo.hfi = g_realloc(gpa_hfinfo.hfi,
5141 sizeof(header_field_info *)*gpa_hfinfo.allocated_len);
5142 /*g_warning("gpa_hfinfo.allocated_len %u", gpa_hfinfo.allocated_len);*/
5145 gpa_hfinfo.hfi[gpa_hfinfo.len] = hfinfo;
5147 hfinfo->id = gpa_hfinfo.len - 1;
5149 /* if we have real names, enter this field in the name tree */
5150 if ((hfinfo->name[0] != 0) && (hfinfo->abbrev[0] != 0 )) {
5152 header_field_info *same_name_next_hfinfo;
5155 /* Check that the filter name (abbreviation) is legal;
5156 * it must contain only alphanumerics, '-', "_", and ".". */
5157 c = wrs_check_charset(fld_abbrev_chars, hfinfo->abbrev);
5159 fprintf(stderr, "Invalid character '%c' in filter name '%s'\n", c, hfinfo->abbrev);
5160 DISSECTOR_ASSERT(!c);
5163 /* We allow multiple hfinfo's to be registered under the same
5164 * abbreviation. This was done for X.25, as, depending
5165 * on whether it's modulo-8 or modulo-128 operation,
5166 * some bitfield fields may be in different bits of
5167 * a byte, and we want to be able to refer to that field
5168 * with one name regardless of whether the packets
5169 * are modulo-8 or modulo-128 packets. */
5171 same_name_hfinfo = NULL;
5173 g_tree_insert(gpa_name_tree, (gpointer) (hfinfo->abbrev), hfinfo);
5174 /* GLIB 2.x - if it is already present
5175 * the previous hfinfo with the same name is saved
5176 * to same_name_hfinfo by value destroy callback */
5177 if (same_name_hfinfo) {
5178 /* There's already a field with this name.
5179 * Put it after that field in the list of
5180 * fields with this name, then allow the code
5181 * after this if{} block to replace the old
5182 * hfinfo with the new hfinfo in the GTree. Thus,
5183 * we end up with a linked-list of same-named hfinfo's,
5184 * with the root of the list being the hfinfo in the GTree */
5185 same_name_next_hfinfo =
5186 same_name_hfinfo->same_name_next;
5188 hfinfo->same_name_next = same_name_next_hfinfo;
5189 if (same_name_next_hfinfo)
5190 same_name_next_hfinfo->same_name_prev = hfinfo;
5192 same_name_hfinfo->same_name_next = hfinfo;
5193 hfinfo->same_name_prev = same_name_hfinfo;
5201 proto_register_subtree_array(gint *const *indices, const int num_indices)
5204 gint *const *ptr = indices;
5207 * If we've already allocated the array of tree types, expand
5208 * it; this lets plugins such as mate add tree types after
5209 * the initial startup. (If we haven't already allocated it,
5210 * we don't allocate it; on the first pass, we just assign
5211 * ett values and keep track of how many we've assigned, and
5212 * when we're finished registering all dissectors we allocate
5213 * the array, so that we do only one allocation rather than
5214 * wasting CPU time and memory by growing the array for each
5215 * dissector that registers ett values.)
5217 if (tree_is_expanded != NULL) {
5219 g_realloc(tree_is_expanded,
5220 (num_tree_types + num_indices)*sizeof (gboolean));
5221 memset(tree_is_expanded + num_tree_types, 0,
5222 num_indices*sizeof (gboolean));
5226 * Assign "num_indices" subtree numbers starting at "num_tree_types",
5227 * returning the indices through the pointers in the array whose
5228 * first element is pointed to by "indices", and update
5229 * "num_tree_types" appropriately.
5231 for (i = 0; i < num_indices; i++, ptr++, num_tree_types++) {
5233 /* g_error will terminate the program */
5234 g_error("register_subtree_array: subtree item type (ett_...) not -1 !"
5235 " This is a development error:"
5236 " Either the subtree item type has already been assigned or"
5237 " was not initialized to -1.");
5239 **ptr = num_tree_types;
5244 label_fill_descr(char *label_str, const header_field_info *hfinfo, const char *text, const char *descr)
5248 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH, "%s: %s (%s)", hfinfo->name, text, descr);
5249 if (ret >= ITEM_LABEL_LENGTH) {
5250 /* Uh oh, we don't have enough room. Tell the user that the field is truncated. */
5251 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH, "%s [truncated]: %s (%s)", hfinfo->name, text, descr);
5258 label_fill(char *label_str, const header_field_info *hfinfo, const char *text)
5262 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH, "%s: %s", hfinfo->name, text);
5263 if (ret >= ITEM_LABEL_LENGTH) {
5264 /* Uh oh, we don't have enough room. Tell the user that the field is truncated. */
5265 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH, "%s [truncated]: %s", hfinfo->name, text);
5272 proto_item_fill_label(field_info *fi, gchar *label_str)
5274 header_field_info *hfinfo;
5280 guint32 n_addr; /* network-order IPv4 address */
5286 /* XXX: Check validity of hfinfo->type */
5290 hfinfo = fi->hfinfo;
5292 switch (hfinfo->type) {
5295 g_strlcpy(label_str, hfinfo->name, ITEM_LABEL_LENGTH);
5299 fill_label_boolean(fi, label_str);
5304 bytes = fvalue_get(&fi->value);
5305 label_fill(label_str, hfinfo,
5306 (bytes) ? bytes_to_str(bytes, fvalue_length(&fi->value)) : "<MISSING>");
5309 /* Four types of integers to take care of:
5310 * Bitfield, with val_string
5311 * Bitfield, w/o val_string
5312 * Non-bitfield, with val_string
5313 * Non-bitfield, w/o val_string
5319 if (hfinfo->bitmask) {
5320 fill_label_bitfield(fi, label_str);
5322 fill_label_uint(fi, label_str);
5327 fill_label_uint(fi, label_str);
5331 fill_label_uint64(fi, label_str);
5338 DISSECTOR_ASSERT(!hfinfo->bitmask);
5339 fill_label_int(fi, label_str);
5343 fill_label_int64(fi, label_str);
5347 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5348 "%s: %." STRINGIFY(FLT_DIG) "g",
5349 hfinfo->name, fvalue_get_floating(&fi->value));
5353 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5354 "%s: %." STRINGIFY(DBL_DIG) "g",
5355 hfinfo->name, fvalue_get_floating(&fi->value));
5358 case FT_ABSOLUTE_TIME:
5359 label_fill(label_str, hfinfo,
5360 abs_time_to_str(fvalue_get(&fi->value), hfinfo->display, TRUE));
5363 case FT_RELATIVE_TIME:
5364 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5365 "%s: %s seconds", hfinfo->name,
5366 rel_time_to_secs_str(fvalue_get(&fi->value)));
5370 integer = fvalue_get_uinteger(&fi->value);
5371 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5372 "%s: %s (0x%08X)", hfinfo->name,
5373 get_ipxnet_name(integer), integer);
5377 bytes = fvalue_get(&fi->value);
5378 label_fill_descr(label_str, hfinfo,
5379 get_ax25_name(bytes),
5380 ax25_to_str(bytes));
5384 bytes = fvalue_get(&fi->value);
5385 label_fill_descr(label_str, hfinfo,
5386 get_ether_name(bytes),
5387 ether_to_str(bytes));
5391 ipv4 = fvalue_get(&fi->value);
5392 n_addr = ipv4_get_net_order_addr(ipv4);
5393 label_fill_descr(label_str, hfinfo,
5394 get_hostname(n_addr),
5395 ip_to_str((guint8*)&n_addr));
5399 bytes = fvalue_get(&fi->value);
5400 label_fill_descr(label_str, hfinfo,
5401 get_hostname6((struct e_in6_addr *)bytes),
5402 ip6_to_str((struct e_in6_addr*)bytes));
5406 guid = fvalue_get(&fi->value);
5407 label_fill(label_str, hfinfo, guid_to_str(guid));
5411 bytes = fvalue_get(&fi->value);
5412 name = oid_resolved_from_encoded(bytes, fvalue_length(&fi->value));
5414 label_fill_descr(label_str, hfinfo,
5415 oid_encoded2string(bytes, fvalue_length(&fi->value)), name);
5417 label_fill(label_str, hfinfo,
5418 oid_encoded2string(bytes, fvalue_length(&fi->value)));
5422 integer64 = fvalue_get_integer64(&fi->value);
5423 label_fill_descr(label_str, hfinfo,
5424 get_eui64_name(integer64),
5425 eui64_to_str(integer64));
5429 case FT_UINT_STRING:
5430 bytes = fvalue_get(&fi->value);
5431 label_fill(label_str, hfinfo, format_text(bytes, strlen(bytes)));
5435 g_error("hfinfo->type %d (%s) not handled\n",
5436 hfinfo->type, ftype_name(hfinfo->type));
5437 DISSECTOR_ASSERT_NOT_REACHED();
5443 fill_label_boolean(field_info *fi, gchar *label_str)
5445 char *p = label_str;
5446 int bitfield_byte_length = 0, bitwidth;
5447 guint32 unshifted_value;
5450 header_field_info *hfinfo = fi->hfinfo;
5451 const true_false_string *tfstring = (const true_false_string *)&tfs_true_false;
5453 if (hfinfo->strings) {
5454 tfstring = (const struct true_false_string*) hfinfo->strings;
5457 value = fvalue_get_uinteger(&fi->value);
5458 if (hfinfo->bitmask) {
5459 /* Figure out the bit width */
5460 bitwidth = hfinfo_bitwidth(hfinfo);
5463 unshifted_value = value;
5464 if (hfinfo->bitshift > 0) {
5465 unshifted_value <<= hfinfo->bitshift;
5468 /* Create the bitfield first */
5469 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
5470 bitfield_byte_length = (int) (p - label_str);
5473 /* Fill in the textual info */
5474 g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
5475 "%s: %s", hfinfo->name,
5476 value ? tfstring->true_string : tfstring->false_string);
5479 /* Fills data for bitfield ints with val_strings */
5481 fill_label_bitfield(field_info *fi, gchar *label_str)
5483 const char *format = NULL;
5485 int bitfield_byte_length, bitwidth;
5486 guint32 unshifted_value;
5489 header_field_info *hfinfo = fi->hfinfo;
5491 /* Figure out the bit width */
5492 bitwidth = hfinfo_bitwidth(hfinfo);
5495 unshifted_value = fvalue_get_uinteger(&fi->value);
5496 value = unshifted_value;
5497 if (hfinfo->bitshift > 0) {
5498 unshifted_value <<= hfinfo->bitshift;
5501 /* Create the bitfield first */
5502 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
5503 bitfield_byte_length = (int) (p - label_str);
5505 /* Fill in the textual info using stored (shifted) value */
5506 if (hfinfo->display == BASE_CUSTOM) {
5507 gchar tmp[ITEM_LABEL_LENGTH];
5508 custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hfinfo->strings;
5510 DISSECTOR_ASSERT(fmtfunc);
5511 fmtfunc(tmp, value);
5512 g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
5513 "%s: %s", hfinfo->name, tmp);
5515 else if (hfinfo->strings) {
5516 format = hfinfo_uint_vals_format(hfinfo);
5517 if (hfinfo->display & BASE_RANGE_STRING) {
5518 g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
5519 format, hfinfo->name,
5520 rval_to_str(value, hfinfo->strings, "Unknown"), value);
5521 } else if (hfinfo->display & BASE_EXT_STRING) {
5522 g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
5523 format, hfinfo->name,
5524 val_to_str_ext_const(value, (value_string_ext *) hfinfo->strings, "Unknown"), value);
5526 g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
5527 format, hfinfo->name,
5528 val_to_str_const(value, cVALS(hfinfo->strings), "Unknown"), value);
5532 format = hfinfo_uint_format(hfinfo);
5533 if (IS_BASE_DUAL(hfinfo->display)) {
5534 g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
5535 format, hfinfo->name, value, value);
5537 g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
5538 format, hfinfo->name, value);
5544 fill_label_uint(field_info *fi, gchar *label_str)
5546 const char *format = NULL;
5547 header_field_info *hfinfo = fi->hfinfo;
5550 value = fvalue_get_uinteger(&fi->value);
5552 /* Fill in the textual info */
5553 if (hfinfo->display == BASE_CUSTOM) {
5554 gchar tmp[ITEM_LABEL_LENGTH];
5555 custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hfinfo->strings;
5557 DISSECTOR_ASSERT(fmtfunc);
5558 fmtfunc(tmp, value);
5559 label_fill(label_str, hfinfo, tmp);
5561 else if (hfinfo->strings) {
5562 format = hfinfo_uint_vals_format(hfinfo);
5563 if (hfinfo->display & BASE_RANGE_STRING) {
5564 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5565 format, hfinfo->name,
5566 rval_to_str(value, hfinfo->strings, "Unknown"), value);
5567 } else if (hfinfo->display & BASE_EXT_STRING) {
5568 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5569 format, hfinfo->name,
5570 val_to_str_ext_const(value, (value_string_ext *) hfinfo->strings, "Unknown"), value);
5572 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5573 format, hfinfo->name,
5574 val_to_str_const(value, cVALS(hfinfo->strings), "Unknown"), value);
5578 format = hfinfo_uint_format(hfinfo);
5579 if (IS_BASE_DUAL(hfinfo->display)) {
5580 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5581 format, hfinfo->name, value, value);
5583 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5584 format, hfinfo->name, value);
5590 fill_label_uint64(field_info *fi, gchar *label_str)
5592 const char *format = NULL;
5593 header_field_info *hfinfo = fi->hfinfo;
5596 /* Pick the proper format string */
5597 format = hfinfo_uint64_format(hfinfo);
5598 value = fvalue_get_integer64(&fi->value);
5600 /* Fill in the textual info */
5601 if (IS_BASE_DUAL(hfinfo->display)) {
5602 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5603 format, hfinfo->name, value, value);
5605 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5606 format, hfinfo->name, value);
5611 fill_label_int(field_info *fi, gchar *label_str)
5613 const char *format = NULL;
5614 header_field_info *hfinfo = fi->hfinfo;
5617 value = fvalue_get_sinteger(&fi->value);
5619 /* Fill in the textual info */
5620 if (hfinfo->display == BASE_CUSTOM) {
5621 gchar tmp[ITEM_LABEL_LENGTH];
5622 custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hfinfo->strings;
5624 DISSECTOR_ASSERT(fmtfunc);
5625 fmtfunc(tmp, value);
5626 label_fill(label_str, hfinfo, tmp);
5628 else if (hfinfo->strings) {
5629 format = hfinfo_int_vals_format(hfinfo);
5630 if (hfinfo->display & BASE_RANGE_STRING) {
5631 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5632 format, hfinfo->name,
5633 rval_to_str(value, hfinfo->strings, "Unknown"), value);
5634 } else if (hfinfo->display & BASE_EXT_STRING) {
5635 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5636 format, hfinfo->name,
5637 val_to_str_ext_const(value, (value_string_ext *) hfinfo->strings, "Unknown"), value);
5639 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5640 format, hfinfo->name,
5641 val_to_str_const(value, cVALS(hfinfo->strings), "Unknown"), value);
5645 format = hfinfo_int_format(hfinfo);
5646 if (IS_BASE_DUAL(hfinfo->display)) {
5647 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5648 format, hfinfo->name, value, value);
5650 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5651 format, hfinfo->name, value);
5657 fill_label_int64(field_info *fi, gchar *label_str)
5659 const char *format = NULL;
5660 header_field_info *hfinfo = fi->hfinfo;
5663 /* Pick the proper format string */
5664 format = hfinfo_int64_format(hfinfo);
5665 value = fvalue_get_integer64(&fi->value);
5667 /* Fill in the textual info */
5668 if (IS_BASE_DUAL(hfinfo->display)) {
5669 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5670 format, hfinfo->name, value, value);
5672 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5673 format, hfinfo->name, value);
5678 hfinfo_bitwidth(const header_field_info *hfinfo)
5682 if (!hfinfo->bitmask) {
5686 switch (hfinfo->type) {
5704 bitwidth = hfinfo->display; /* hacky? :) */
5707 DISSECTOR_ASSERT_NOT_REACHED();
5714 hfinfo_uint_vals_format(const header_field_info *hfinfo)
5716 const char *format = NULL;
5718 /* Get the underlying BASE_ value */
5719 switch (hfinfo->display & BASE_DISPLAY_E_MASK) {
5725 format = "%s: %s (%u)";
5727 case BASE_OCT: /* I'm lazy */
5728 format = "%s: %s (%#o)";
5732 switch (hfinfo->type) {
5734 format = "%s: %s (0x%02x)";
5737 format = "%s: %s (0x%04x)";
5740 format = "%s: %s (0x%06x)";
5743 format = "%s: %s (0x%08x)";
5746 DISSECTOR_ASSERT_NOT_REACHED();
5751 DISSECTOR_ASSERT_NOT_REACHED();
5758 hfinfo_uint_format(const header_field_info *hfinfo)
5760 const char *format = NULL;
5762 /* Pick the proper format string */
5763 if (hfinfo->type == FT_FRAMENUM) {
5765 * Frame numbers are always displayed in decimal.
5769 switch (hfinfo->display) {
5774 switch (hfinfo->type) {
5776 format = "%s: %u (0x%02x)";
5779 format = "%s: %u (0x%04x)";
5782 format = "%s: %u (0x%06x)";
5785 format = "%s: %u (0x%08x)";
5788 DISSECTOR_ASSERT_NOT_REACHED();
5792 case BASE_OCT: /* I'm lazy */
5796 switch (hfinfo->type) {
5798 format = "%s: 0x%02x";
5801 format = "%s: 0x%04x";
5804 format = "%s: 0x%06x";
5807 format = "%s: 0x%08x";
5810 DISSECTOR_ASSERT_NOT_REACHED();
5815 switch (hfinfo->type) {
5817 format = "%s: 0x%02x (%u)";
5820 format = "%s: 0x%04x (%u)";
5823 format = "%s: 0x%06x (%u)";
5826 format = "%s: 0x%08x (%u)";
5829 DISSECTOR_ASSERT_NOT_REACHED();
5834 DISSECTOR_ASSERT_NOT_REACHED();
5842 hfinfo_uint_value_format(const header_field_info *hfinfo)
5844 const char *format = NULL;
5846 /* Pick the proper format string */
5847 if (hfinfo->type == FT_FRAMENUM) {
5849 * Frame numbers are always displayed in decimal.
5853 switch (hfinfo->display) {
5858 switch (hfinfo->type) {
5860 format = "%u (0x%02x)";
5863 format = "%u (0x%04x)";
5866 format = "%u (0x%06x)";
5869 format = "%u (0x%08x)";
5872 DISSECTOR_ASSERT_NOT_REACHED();
5880 switch (hfinfo->type) {
5894 DISSECTOR_ASSERT_NOT_REACHED();
5899 switch (hfinfo->type) {
5901 format = "0x%02x (%u)";
5904 format = "0x%04x (%u)";
5907 format = "0x%06x (%u)";
5910 format = "0x%08x (%u)";
5913 DISSECTOR_ASSERT_NOT_REACHED();
5918 DISSECTOR_ASSERT_NOT_REACHED();
5926 hfinfo_int_vals_format(const header_field_info *hfinfo)
5928 const char *format = NULL;
5930 /* Get the underlying BASE_ value */
5931 switch (hfinfo->display & BASE_DISPLAY_E_MASK) {
5937 format = "%s: %s (%d)";
5939 case BASE_OCT: /* I'm lazy */
5940 format = "%s: %s (%#o)";
5944 switch (hfinfo->type) {
5946 format = "%s: %s (0x%02x)";
5949 format = "%s: %s (0x%04x)";
5952 format = "%s: %s (0x%06x)";
5955 format = "%s: %s (0x%08x)";
5958 DISSECTOR_ASSERT_NOT_REACHED();
5963 DISSECTOR_ASSERT_NOT_REACHED();
5970 hfinfo_uint64_format(const header_field_info *hfinfo)
5972 const char *format = NULL;
5974 /* Pick the proper format string */
5975 switch (hfinfo->display) {
5977 format = "%s: %" G_GINT64_MODIFIER "u";
5980 format = "%s: %" G_GINT64_MODIFIER "u (0x%016" G_GINT64_MODIFIER "x)";
5982 case BASE_OCT: /* I'm lazy */
5983 format = "%s: %#" G_GINT64_MODIFIER "o";
5986 format = "%s: 0x%016" G_GINT64_MODIFIER "x";
5989 format = "%s: 0x%016" G_GINT64_MODIFIER "x (%" G_GINT64_MODIFIER "u)";
5992 DISSECTOR_ASSERT_NOT_REACHED();
5999 hfinfo_int_format(const header_field_info *hfinfo)
6001 const char *format = NULL;
6003 /* Pick the proper format string */
6004 switch (hfinfo->display) {
6009 switch (hfinfo->type) {
6011 format = "%s: %d (0x%02x)";
6014 format = "%s: %d (0x%04x)";
6017 format = "%s: %d (0x%06x)";
6020 format = "%s: %d (0x%08x)";
6023 DISSECTOR_ASSERT_NOT_REACHED();
6027 case BASE_OCT: /* I'm lazy */
6031 switch (hfinfo->type) {
6033 format = "%s: 0x%02x";
6036 format = "%s: 0x%04x";
6039 format = "%s: 0x%06x";
6042 format = "%s: 0x%08x";
6045 DISSECTOR_ASSERT_NOT_REACHED();
6050 switch (hfinfo->type) {
6052 format = "%s: 0x%02x (%d)";
6055 format = "%s: 0x%04x (%d)";
6058 format = "%s: 0x%06x (%d)";
6061 format = "%s: 0x%08x (%d)";
6064 DISSECTOR_ASSERT_NOT_REACHED();
6069 DISSECTOR_ASSERT_NOT_REACHED();
6076 hfinfo_int_value_format(const header_field_info *hfinfo)
6078 const char *format = NULL;
6080 /* Pick the proper format string */
6081 switch (hfinfo->display) {
6086 switch (hfinfo->type) {
6088 format = "%d (0x%02x)";
6091 format = "%d (0x%04x)";
6094 format = "%d (0x%06x)";
6097 format = "%d (0x%08x)";
6100 DISSECTOR_ASSERT_NOT_REACHED();
6108 switch (hfinfo->type) {
6122 DISSECTOR_ASSERT_NOT_REACHED();
6127 switch (hfinfo->type) {
6129 format = "0x%02x (%d)";
6132 format = "0x%04x (%d)";
6135 format = "0x%06x (%d)";
6138 format = "0x%08x (%d)";
6141 DISSECTOR_ASSERT_NOT_REACHED();
6146 DISSECTOR_ASSERT_NOT_REACHED();
6153 hfinfo_int64_format(const header_field_info *hfinfo)
6155 const char *format = NULL;
6157 /* Pick the proper format string */
6158 switch (hfinfo->display) {
6160 format = "%s: %" G_GINT64_MODIFIER "d";
6163 format = "%s: %" G_GINT64_MODIFIER "d (0x%016" G_GINT64_MODIFIER "x)";
6165 case BASE_OCT: /* I'm lazy */
6166 format = "%s: %#" G_GINT64_MODIFIER "o";
6169 format = "%s: 0x%016" G_GINT64_MODIFIER "x";
6172 format = "%s: 0x%016" G_GINT64_MODIFIER "x (%" G_GINT64_MODIFIER "d)";
6175 DISSECTOR_ASSERT_NOT_REACHED();
6182 proto_registrar_n(void)
6184 return gpa_hfinfo.len;
6188 proto_registrar_get_name(const int n)
6190 header_field_info *hfinfo;
6192 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
6193 return hfinfo->name;
6197 proto_registrar_get_abbrev(const int n)
6199 header_field_info *hfinfo;
6201 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
6202 return hfinfo->abbrev;
6206 proto_registrar_get_ftype(const int n)
6208 header_field_info *hfinfo;
6210 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
6211 return hfinfo->type;
6215 proto_registrar_get_parent(const int n)
6217 header_field_info *hfinfo;
6219 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
6220 return hfinfo->parent;
6224 proto_registrar_is_protocol(const int n)
6226 header_field_info *hfinfo;
6228 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
6229 return (hfinfo->parent == -1 ? TRUE : FALSE);
6232 /* Returns length of field in packet (not necessarily the length
6233 * in our internal representation, as in the case of IPv4).
6234 * 0 means undeterminable at time of registration
6235 * -1 means the field is not registered. */
6237 proto_registrar_get_length(const int n)
6239 header_field_info *hfinfo;
6241 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
6242 return ftype_length(hfinfo->type);
6245 /* Looks for a protocol or a field in a proto_tree. Returns TRUE if
6246 * it exists anywhere, or FALSE if it exists nowhere. */
6248 proto_check_for_protocol_or_field(const proto_tree* tree, const int id)
6250 GPtrArray *ptrs = proto_get_finfo_ptr_array(tree, id);
6255 else if (g_ptr_array_len(ptrs) > 0) {
6263 /* Return GPtrArray* of field_info pointers for all hfindex that appear in tree.
6264 * This only works if the hfindex was "primed" before the dissection
6265 * took place, as we just pass back the already-created GPtrArray*.
6266 * The caller should *not* free the GPtrArray*; proto_tree_free_node()
6269 proto_get_finfo_ptr_array(const proto_tree *tree, const int id)
6274 if (PTREE_DATA(tree)->interesting_hfids != NULL)
6275 return g_hash_table_lookup(PTREE_DATA(tree)->interesting_hfids,
6276 GINT_TO_POINTER(id));
6282 proto_tracking_interesting_fields(const proto_tree *tree)
6287 return (PTREE_DATA(tree)->interesting_hfids != NULL);
6290 /* Helper struct for proto_find_info() and proto_all_finfos() */
6296 /* Helper function for proto_find_info() */
6298 find_finfo(proto_node *node, gpointer data)
6300 field_info *fi = PNODE_FINFO(node);
6301 if (fi && fi->hfinfo) {
6302 if (fi->hfinfo->id == ((ffdata_t*)data)->id) {
6303 g_ptr_array_add(((ffdata_t*)data)->array, fi);
6307 /* Don't stop traversing. */
6311 /* Return GPtrArray* of field_info pointers for all hfindex that appear in a tree.
6312 * This works on any proto_tree, primed or unprimed, but actually searches
6313 * the tree, so it is slower than using proto_get_finfo_ptr_array on a primed tree.
6314 * The caller does need to free the returned GPtrArray with
6315 * g_ptr_array_free(<array>, TRUE).
6318 proto_find_finfo(proto_tree *tree, const int id)
6322 ffdata.array = g_ptr_array_new();
6325 proto_tree_traverse_pre_order(tree, find_finfo, &ffdata);
6327 return ffdata.array;
6330 /* Helper function for proto_all_finfos() */
6332 every_finfo(proto_node *node, gpointer data)
6334 field_info *fi = PNODE_FINFO(node);
6335 if (fi && fi->hfinfo) {
6336 g_ptr_array_add(((ffdata_t*)data)->array, fi);
6339 /* Don't stop traversing. */
6343 /* Return GPtrArray* of field_info pointers containing all hfindexes that appear in a tree. */
6345 proto_all_finfos(proto_tree *tree)
6349 ffdata.array = g_ptr_array_new();
6352 proto_tree_traverse_pre_order(tree, every_finfo, &ffdata);
6354 return ffdata.array;
6365 check_for_offset(proto_node *node, const gpointer data)
6367 field_info *fi = PNODE_FINFO(node);
6368 offset_search_t *offsearch = data;
6370 /* !fi == the top most container node which holds nothing */
6371 if (fi && !PROTO_ITEM_IS_HIDDEN(node) && fi->ds_tvb && offsearch->tvb == fi->ds_tvb) {
6372 if (offsearch->offset >= (guint) fi->start &&
6373 offsearch->offset < (guint) (fi->start + fi->length)) {
6375 offsearch->finfo = fi;
6376 return FALSE; /* keep traversing */
6379 return FALSE; /* keep traversing */
6382 /* Search a proto_tree backwards (from leaves to root) looking for the field
6383 * whose start/length occupies 'offset' */
6384 /* XXX - I couldn't find an easy way to search backwards, so I search
6385 * forwards, w/o stopping. Therefore, the last finfo I find will the be
6386 * the one I want to return to the user. This algorithm is inefficient
6387 * and could be re-done, but I'd have to handle all the children and
6388 * siblings of each node myself. When I have more time I'll do that.
6391 proto_find_field_from_offset(proto_tree *tree, guint offset, tvbuff_t *tvb)
6393 offset_search_t offsearch;
6395 offsearch.offset = offset;
6396 offsearch.finfo = NULL;
6397 offsearch.tvb = tvb;
6399 proto_tree_traverse_pre_order(tree, check_for_offset, &offsearch);
6401 return offsearch.finfo;
6404 /* Dumps the protocols in the registration database to stdout. An independent
6405 * program can take this output and format it into nice tables or HTML or
6408 * There is one record per line. The fields are tab-delimited.
6410 * Field 1 = protocol name
6411 * Field 2 = protocol short name
6412 * Field 3 = protocol filter name
6415 proto_registrar_dump_protocols(void)
6417 protocol_t *protocol;
6419 void *cookie = NULL;
6422 i = proto_get_first_protocol(&cookie);
6424 protocol = find_protocol_by_id(i);
6425 printf("%s\t%s\t%s\n", protocol->name, protocol->short_name,
6426 protocol->filter_name);
6427 i = proto_get_next_protocol(&cookie);
6431 /* Dumps the value_strings, extended value string headers, range_strings
6432 * or true/false strings for fields that have them.
6433 * There is one record per line. Fields are tab-delimited.
6434 * There are four types of records: Value String, Extended Value String Header,
6435 * Range String and True/False String. The first field, 'V', 'E', 'R' or 'T', indicates
6436 * the type of record.
6438 * Note that a record will be generated only if the value_string,... is referenced
6439 * in a registered hfinfo entry.
6445 * Field 2 = Field abbreviation to which this value string corresponds
6446 * Field 3 = Integer value
6449 * Extended Value String Headers
6450 * -----------------------------
6452 * Field 2 = Field abbreviation to which this extended value string header corresponds
6453 * Field 3 = Extended Value String "Name"
6454 * Field 4 = Number of entries in the associated value_string array
6455 * Field 5 = Access Type: "Linear Search", "Binary Search", "Direct (indexed) Access"
6460 * Field 2 = Field abbreviation to which this range string corresponds
6461 * Field 3 = Integer value: lower bound
6462 * Field 4 = Integer value: upper bound
6465 * True/False Strings
6466 * ------------------
6468 * Field 2 = Field abbreviation to which this true/false string corresponds
6469 * Field 3 = True String
6470 * Field 4 = False String
6473 proto_registrar_dump_values(void)
6475 header_field_info *hfinfo;
6477 const value_string *vals;
6478 const range_string *range;
6479 const true_false_string *tfs;
6481 len = gpa_hfinfo.len;
6482 for (i = 0; i < len ; i++) {
6483 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
6485 if (hfinfo->id == hf_text_only) {
6489 /* ignore protocols */
6490 if (proto_registrar_is_protocol(i)) {
6493 /* process header fields */
6496 * If this field isn't at the head of the list of
6497 * fields with this name, skip this field - all
6498 * fields with the same name are really just versions
6499 * of the same field stored in different bits, and
6500 * should have the same type/radix/value list, and
6501 * just differ in their bit masks. (If a field isn't
6502 * a bitfield, but can be, say, 1 or 2 bytes long,
6503 * it can just be made FT_UINT16, meaning the
6504 * *maximum* length is 2 bytes, and be used
6507 if (hfinfo->same_name_prev != NULL)
6514 if (hfinfo->strings != NULL) {
6515 if ((hfinfo->display & BASE_DISPLAY_E_MASK) != BASE_CUSTOM &&
6516 (hfinfo->type == FT_UINT8 ||
6517 hfinfo->type == FT_UINT16 ||
6518 hfinfo->type == FT_UINT24 ||
6519 hfinfo->type == FT_UINT32 ||
6520 hfinfo->type == FT_UINT64 ||
6521 hfinfo->type == FT_INT8 ||
6522 hfinfo->type == FT_INT16 ||
6523 hfinfo->type == FT_INT24 ||
6524 hfinfo->type == FT_INT32 ||
6525 hfinfo->type == FT_INT64)) {
6527 if (hfinfo->display & BASE_EXT_STRING) {
6528 vals = VALUE_STRING_EXT_VS_P((value_string_ext *)hfinfo->strings);
6529 } else if ((hfinfo->display & BASE_RANGE_STRING) == 0) {
6530 vals = hfinfo->strings;
6532 range = hfinfo->strings;
6535 else if (hfinfo->type == FT_BOOLEAN) {
6536 tfs = hfinfo->strings;
6540 /* Print value strings? */
6542 if (hfinfo->display & BASE_EXT_STRING) {
6543 value_string_ext *vse_p = (value_string_ext *)hfinfo->strings;
6544 if (!value_string_ext_validate(vse_p)) {
6545 g_warning("Invalid value_string_ext ptr for: %s", hfinfo->abbrev);
6548 match_strval_ext(0, vse_p); /* "prime" the extended value_string */
6549 printf("E\t%s\t%d\t%s\t%s\n",
6551 VALUE_STRING_EXT_VS_NUM_ENTRIES(vse_p),
6552 VALUE_STRING_EXT_VS_NAME(vse_p),
6553 value_string_ext_match_type_str(vse_p));
6556 while (vals[vi].strptr) {
6557 /* Print in the proper base */
6558 if (hfinfo->display == BASE_HEX) {
6559 printf("V\t%s\t0x%x\t%s\n",
6565 printf("V\t%s\t%u\t%s\n",
6574 /* print range strings? */
6577 while (range[vi].strptr) {
6578 /* Print in the proper base */
6579 if ((hfinfo->display & BASE_DISPLAY_E_MASK) == BASE_HEX) {
6580 printf("R\t%s\t0x%x\t0x%x\t%s\n",
6582 range[vi].value_min,
6583 range[vi].value_max,
6587 printf("R\t%s\t%u\t%u\t%s\n",
6589 range[vi].value_min,
6590 range[vi].value_max,
6597 /* Print true/false strings? */
6599 printf("T\t%s\t%s\t%s\n", hfinfo->abbrev,
6600 tfs->true_string, tfs->false_string);
6606 /* Dumps the contents of the registration database to stdout. An independent
6607 * program can take this output and format it into nice tables or HTML or
6610 * There is one record per line. Each record is either a protocol or a header
6611 * field, differentiated by the first field. The fields are tab-delimited.
6616 * Field 2 = descriptive protocol name
6617 * Field 3 = protocol abbreviation
6623 * Field 2 = descriptive field name
6624 * Field 3 = field abbreviation
6625 * Field 4 = type ( textual representation of the the ftenum type )
6626 * Field 5 = parent protocol abbreviation
6627 * Field 6 = blurb describing field
6631 * Field 2 = descriptive field name
6632 * Field 3 = field abbreviation
6633 * Field 4 = type ( textual representation of the the ftenum type )
6634 * Field 5 = parent protocol abbreviation
6635 * Field 6 = blurb describing field
6636 * Field 7 = base for display (for integer types); "parent bitfield width" for FT_BOOLEAN
6637 * Field 8 = blurb describing field (yes, apparently we repeated this accidentally)
6641 * Field 2 = descriptive field name
6642 * Field 3 = field abbreviation
6643 * Field 4 = type ( textual representation of the the ftenum type )
6644 * Field 5 = parent protocol abbreviation
6645 * Field 6 = blurb describing field
6646 * Field 7 = base for display (for integer types); "parent bitfield width" for FT_BOOLEAN
6647 * Field 8 = bitmask: format: hex: 0x....
6650 proto_registrar_dump_fields(const int format)
6652 header_field_info *hfinfo, *parent_hfinfo;
6654 const char *enum_name;
6655 const char *base_name;
6659 len = gpa_hfinfo.len;
6660 for (i = 0; i < len ; i++) {
6661 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
6664 * Skip the pseudo-field for "proto_tree_add_text()" since
6665 * we don't want it in the list of filterable fields.
6667 if (hfinfo->id == hf_text_only)
6670 /* format for protocols */
6671 if (proto_registrar_is_protocol(i)) {
6672 printf("P\t%s\t%s\n", hfinfo->name, hfinfo->abbrev);
6674 /* format for header fields */
6677 * If this field isn't at the head of the list of
6678 * fields with this name, skip this field - all
6679 * fields with the same name are really just versions
6680 * of the same field stored in different bits, and
6681 * should have the same type/radix/value list, and
6682 * just differ in their bit masks. (If a field isn't
6683 * a bitfield, but can be, say, 1 or 2 bytes long,
6684 * it can just be made FT_UINT16, meaning the
6685 * *maximum* length is 2 bytes, and be used
6688 if (hfinfo->same_name_prev != NULL)
6691 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
6693 enum_name = ftype_name(hfinfo->type);
6697 if (hfinfo->type == FT_UINT8 ||
6698 hfinfo->type == FT_UINT16 ||
6699 hfinfo->type == FT_UINT24 ||
6700 hfinfo->type == FT_UINT32 ||
6701 hfinfo->type == FT_UINT64 ||
6702 hfinfo->type == FT_INT8 ||
6703 hfinfo->type == FT_INT16 ||
6704 hfinfo->type == FT_INT24 ||
6705 hfinfo->type == FT_INT32 ||
6706 hfinfo->type == FT_INT64) {
6709 switch (hfinfo->display & BASE_DISPLAY_E_MASK) {
6711 base_name = "BASE_NONE";
6714 base_name = "BASE_DEC";
6717 base_name = "BASE_HEX";
6720 base_name = "BASE_OCT";
6723 base_name = "BASE_DEC_HEX";
6726 base_name = "BASE_HEX_DEC";
6729 base_name = "BASE_CUSTOM";
6735 } else if (hfinfo->type == FT_BOOLEAN) {
6736 /* For FT_BOOLEAN: 'display' can be "parent bitfield width" */
6737 g_snprintf(width, sizeof(width), "%d", hfinfo->display);
6742 blurb = hfinfo->blurb;
6745 else if (strlen(blurb) == 0)
6748 printf("F\t%s\t%s\t%s\t%s\t%s\n",
6749 hfinfo->name, hfinfo->abbrev, enum_name,
6750 parent_hfinfo->abbrev, blurb);
6752 else if (format == 2) {
6753 printf("F\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n",
6754 hfinfo->name, hfinfo->abbrev, enum_name,
6755 parent_hfinfo->abbrev, blurb,
6758 else if (format == 3) {
6759 printf("F\t%s\t%s\t%s\t%s\t%s\t%s\t0x%x\n",
6760 hfinfo->name, hfinfo->abbrev, enum_name,
6761 parent_hfinfo->abbrev, blurb,
6762 base_name, hfinfo->bitmask);
6765 g_assert_not_reached();
6771 /* Dumps field types and descriptive names to stdout. An independent
6772 * program can take this output and format it into nice tables or HTML or
6775 * There is one record per line. The fields are tab-delimited.
6777 * Field 1 = field type name, e.g. FT_UINT8
6778 * Field 2 = descriptive name, e.g. "Unsigned, 1 byte"
6781 proto_registrar_dump_ftypes(void)
6785 for (fte = 0; fte < FT_NUM_TYPES; fte++) {
6786 printf("%s\t%s\n", ftype_name(fte), ftype_pretty_name(fte));
6791 hfinfo_numeric_format(const header_field_info *hfinfo)
6793 const char *format = NULL;
6795 /* Pick the proper format string */
6796 if (hfinfo->type == FT_FRAMENUM) {
6798 * Frame numbers are always displayed in decimal.
6800 format = "%s == %u";
6802 /* Get the underlying BASE_ value */
6803 switch (hfinfo->display & BASE_DISPLAY_E_MASK) {
6806 case BASE_OCT: /* I'm lazy */
6808 switch (hfinfo->type) {
6813 format = "%s == %u";
6816 format = "%s == %" G_GINT64_MODIFIER "u";
6822 format = "%s == %d";
6825 format = "%s == %" G_GINT64_MODIFIER "d";
6828 DISSECTOR_ASSERT_NOT_REACHED();
6834 switch (hfinfo->type) {
6837 format = "%s == 0x%02x";
6841 format = "%s == 0x%04x";
6845 format = "%s == 0x%06x";
6849 format = "%s == 0x%08x";
6853 format = "%s == 0x%016" G_GINT64_MODIFIER "x";
6856 DISSECTOR_ASSERT_NOT_REACHED();
6861 DISSECTOR_ASSERT_NOT_REACHED();
6869 hfinfo_numeric_value_format(const header_field_info *hfinfo)
6871 const char *format = NULL;
6873 /* Pick the proper format string */
6874 if (hfinfo->type == FT_FRAMENUM) {
6876 * Frame numbers are always displayed in decimal.
6880 /* Get the underlying BASE_ value */
6881 switch (hfinfo->display & BASE_DISPLAY_E_MASK) {
6885 case BASE_OCT: /* I'm lazy */
6887 switch (hfinfo->type) {
6895 format = "%" G_GINT64_MODIFIER "u";
6904 format = "%" G_GINT64_MODIFIER "d";
6907 DISSECTOR_ASSERT_NOT_REACHED();
6913 switch (hfinfo->type) {
6932 format = "0x%016" G_GINT64_MODIFIER "x";
6935 DISSECTOR_ASSERT_NOT_REACHED();
6940 DISSECTOR_ASSERT_NOT_REACHED();
6947 /* This function indicates whether it's possible to construct a
6948 * "match selected" display filter string for the specified field,
6949 * returns an indication of whether it's possible, and, if it's
6950 * possible and "filter" is non-null, constructs the filter and
6951 * sets "*filter" to point to it.
6952 * You do not need to [g_]free() this string since it will be automatically
6953 * freed once the next packet is dissected.
6956 construct_match_selected_string(field_info *finfo, epan_dissect_t *edt,
6959 header_field_info *hfinfo;
6965 gint start, length, length_remaining;
6967 gchar is_signed_num = FALSE;
6969 hfinfo = finfo->hfinfo;
6970 DISSECTOR_ASSERT(hfinfo);
6971 abbrev_len = (int) strlen(hfinfo->abbrev);
6973 if (hfinfo->strings && (hfinfo->display & BASE_DISPLAY_E_MASK) == BASE_NONE) {
6974 const gchar *str = NULL;
6976 switch (hfinfo->type) {
6982 if (hfinfo->display & BASE_RANGE_STRING) {
6983 str = match_strrval(fvalue_get_sinteger(&finfo->value), hfinfo->strings);
6984 } else if (hfinfo->display & BASE_EXT_STRING) {
6985 str = match_strval_ext(fvalue_get_sinteger(&finfo->value), hfinfo->strings);
6987 str = match_strval(fvalue_get_sinteger(&finfo->value), hfinfo->strings);
6995 if (hfinfo->display & BASE_RANGE_STRING) {
6996 str = match_strrval(fvalue_get_uinteger(&finfo->value), hfinfo->strings);
6997 } else if (hfinfo->display & BASE_EXT_STRING) {
6998 str = match_strval_ext(fvalue_get_uinteger(&finfo->value), hfinfo->strings);
7000 str = match_strval(fvalue_get_uinteger(&finfo->value), hfinfo->strings);
7008 if (str != NULL && filter != NULL) {
7009 *filter = ep_strdup_printf("%s == \"%s\"", hfinfo->abbrev, str);
7015 * XXX - we can't use the "val_to_string_repr" and "string_repr_len"
7016 * functions for FT_UINT and FT_INT types, as we choose the base in
7017 * the string expression based on the display base of the field.
7019 * Note that the base does matter, as this is also used for
7020 * the protocolinfo tap.
7022 * It might be nice to use them in "proto_item_fill_label()"
7023 * as well, although, there, you'd have to deal with the base
7024 * *and* with resolved values for addresses.
7026 * Perhaps we need two different val_to_string routines, one
7027 * to generate items for display filters and one to generate
7028 * strings for display, and pass to both of them the
7029 * "display" and "strings" values in the header_field_info
7030 * structure for the field, so they can get the base and,
7031 * if the field is Boolean or an enumerated integer type,
7032 * the tables used to generate human-readable values.
7034 switch (hfinfo->type) {
7040 is_signed_num = TRUE;
7046 if (filter != NULL) {
7047 format = hfinfo_numeric_format(hfinfo);
7048 if (is_signed_num) {
7049 *filter = ep_strdup_printf(format,
7051 fvalue_get_sinteger(&finfo->value));
7053 *filter = ep_strdup_printf(format,
7055 fvalue_get_uinteger(&finfo->value));
7061 DISSECTOR_ASSERT(!is_signed_num);
7062 if (filter != NULL) {
7063 format = hfinfo_numeric_format(hfinfo);
7064 *filter = ep_strdup_printf(format,
7066 fvalue_get_uinteger(&finfo->value));
7072 if (filter != NULL) {
7073 format = hfinfo_numeric_format(hfinfo);
7074 *filter = ep_strdup_printf(format,
7076 fvalue_get_integer64(&finfo->value));
7082 *filter = ep_strdup(finfo->hfinfo->abbrev);
7087 * If the length is 0, just match the name of the
7090 * (Also check for negative values, just in case,
7091 * as we'll cast it to an unsigned value later.)
7093 length = finfo->length;
7096 *filter = ep_strdup(finfo->hfinfo->abbrev);
7103 * This doesn't have a value, so we'd match
7104 * on the raw bytes at this address.
7106 * Should we be allowed to access to the raw bytes?
7107 * If "edt" is NULL, the answer is "no".
7113 * Is this field part of the raw frame tvbuff?
7114 * If not, we can't use "frame[N:M]" to match
7117 * XXX - should this be frame-relative, or
7118 * protocol-relative?
7120 * XXX - does this fallback for non-registered
7121 * fields even make sense?
7123 if (finfo->ds_tvb != edt->tvb)
7124 return FALSE; /* you lose */
7127 * Don't go past the end of that tvbuff.
7129 length_remaining = tvb_length_remaining(finfo->ds_tvb, finfo->start);
7130 if (length > length_remaining)
7131 length = length_remaining;
7135 if (filter != NULL) {
7136 start = finfo->start;
7137 buf_len = 32 + length * 3;
7138 *filter = ep_alloc0(buf_len);
7141 ptr += g_snprintf(ptr, (gulong) (buf_len-(ptr-*filter)),
7142 "frame[%d:%d] == ", finfo->start, length);
7143 for (i=0; i<length; i++) {
7144 c = tvb_get_guint8(finfo->ds_tvb, start);
7147 ptr += g_snprintf(ptr, (gulong) (buf_len-(ptr-*filter)), "%02x", c);
7150 ptr += g_snprintf(ptr, (gulong) (buf_len-(ptr-*filter)), ":%02x", c);
7157 /* FT_PCRE never appears as a type for a registered field. It is
7158 * only used internally. */
7159 DISSECTOR_ASSERT_NOT_REACHED();
7162 /* By default, use the fvalue's "to_string_repr" method. */
7164 /* Figure out the string length needed.
7165 * The ft_repr length.
7166 * 4 bytes for " == ".
7167 * 1 byte for trailing NUL.
7169 if (filter != NULL) {
7170 dfilter_len = fvalue_string_repr_len(&finfo->value,
7172 dfilter_len += abbrev_len + 4 + 1;
7173 *filter = ep_alloc0(dfilter_len);
7175 /* Create the string */
7176 g_snprintf(*filter, dfilter_len, "%s == ",
7178 fvalue_to_string_repr(&finfo->value,
7180 &(*filter)[abbrev_len + 4]);
7189 * Returns TRUE if we can do a "match selected" on the field, FALSE
7193 proto_can_match_selected(field_info *finfo, epan_dissect_t *edt)
7195 return construct_match_selected_string(finfo, edt, NULL);
7198 /* This function attempts to construct a "match selected" display filter
7199 * string for the specified field; if it can do so, it returns a pointer
7200 * to the string, otherwise it returns NULL.
7202 * The string is allocated with packet lifetime scope.
7203 * You do not need to [g_]free() this string since it will be automatically
7204 * freed once the next packet is dissected.
7207 proto_construct_match_selected_string(field_info *finfo, epan_dissect_t *edt)
7211 if (!construct_match_selected_string(finfo, edt, &filter))
7216 /* This function is common code for both proto_tree_add_bitmask() and
7217 * proto_tree_add_bitmask_text() functions.
7220 /* NOTE: to support code written when proto_tree_add_bitmask() and
7221 * proto_tree_add_bitmask_text took a
7222 * gboolean as its last argument, with FALSE meaning "big-endian"
7223 * and TRUE meaning "little-endian", we treat any non-zero value of
7224 * "encoding" as meaning "little-endian".
7227 proto_item_add_bitmask_tree(proto_item *item, tvbuff_t *tvb, const int offset,
7228 const int len, const gint ett, const int **fields,
7229 const guint encoding, const int flags,
7234 proto_tree *tree = NULL;
7235 header_field_info *hf;
7240 value = tvb_get_guint8(tvb, offset);
7243 value = encoding ? tvb_get_letohs(tvb, offset) :
7244 tvb_get_ntohs(tvb, offset);
7247 value = encoding ? tvb_get_letoh24(tvb, offset) :
7248 tvb_get_ntoh24(tvb, offset);
7251 value = encoding ? tvb_get_letohl(tvb, offset) :
7252 tvb_get_ntohl(tvb, offset);
7255 g_assert_not_reached();
7258 tree = proto_item_add_subtree(item, ett);
7260 proto_tree_add_item(tree, **fields, tvb, offset, len, encoding);
7261 if (flags & BMT_NO_APPEND) {
7265 hf = proto_registrar_get_nth(**fields);
7266 DISSECTOR_ASSERT(hf->bitmask != 0);
7267 tmpval = (value & hf->bitmask) >> hf->bitshift;
7278 DISSECTOR_ASSERT(len == ftype_length(hf->type));
7280 if (hf->display == BASE_CUSTOM) {
7281 gchar lbl[ITEM_LABEL_LENGTH];
7282 custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hf->strings;
7284 DISSECTOR_ASSERT(fmtfunc);
7285 fmtfunc(lbl, tmpval);
7286 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
7290 else if (hf->strings) {
7291 if (hf->display & BASE_RANGE_STRING) {
7292 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
7293 hf->name, rval_to_str(tmpval, hf->strings, "Unknown"));
7294 } else if (hf->display & BASE_EXT_STRING) {
7295 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
7296 hf->name, val_to_str_ext_const(tmpval, (value_string_ext *) (hf->strings), "Unknown"));
7298 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
7299 hf->name, val_to_str_const(tmpval, cVALS(hf->strings), "Unknown"));
7303 else if (!(flags & BMT_NO_INT)) {
7305 proto_item_append_text(item, ", ");
7308 fmt = IS_FT_INT(hf->type) ? hfinfo_int_format(hf) : hfinfo_uint_format(hf);
7309 if (IS_BASE_DUAL(hf->display)) {
7310 proto_item_append_text(item, fmt, hf->name, tmpval, tmpval);
7312 proto_item_append_text(item, fmt, hf->name, tmpval);
7319 DISSECTOR_ASSERT(len * 8 == hf->display);
7321 if (hf->strings && !(flags & BMT_NO_TFS)) {
7322 /* If we have true/false strings, emit full - otherwise messages
7324 const struct true_false_string *tfs =
7325 (const struct true_false_string *)hf->strings;
7328 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
7329 hf->name, tfs->true_string);
7331 } else if (!(flags & BMT_NO_FALSE)) {
7332 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
7333 hf->name, tfs->false_string);
7336 } else if (hf->bitmask & value) {
7337 /* If the flag is set, show the name */
7338 proto_item_append_text(item, "%s%s", first ? "" : ", ", hf->name);
7343 g_assert_not_reached();
7352 /* This function will dissect a sequence of bytes that describe a
7354 * hf_hdr is a 8/16/24/32 bit integer that describes the bitmask to be dissected.
7355 * This field will form an expansion under which the individual fields of the
7356 * bitmask is dissected and displayed.
7357 * This field must be of the type FT_[U]INT{8|16|24|32}.
7359 * fields is an array of pointers to int that lists all the fields of the
7360 * bitmask. These fields can be either of the type FT_BOOLEAN for flags
7361 * or another integer of the same type/size as hf_hdr with a mask specified.
7362 * This array is terminated by a NULL entry.
7364 * FT_BOOLEAN bits that are set to 1 will have the name added to the expansion.
7365 * FT_integer fields that have a value_string attached will have the
7366 * matched string displayed on the expansion line.
7369 proto_tree_add_bitmask(proto_tree *parent_tree, tvbuff_t *tvb,
7370 const guint offset, const int hf_hdr,
7371 const gint ett, const int **fields,
7372 const guint encoding)
7374 proto_item *item = NULL;
7375 header_field_info *hf;
7378 hf = proto_registrar_get_nth(hf_hdr);
7379 DISSECTOR_ASSERT(IS_FT_INT(hf->type) || IS_FT_UINT(hf->type));
7380 len = ftype_length(hf->type);
7383 item = proto_tree_add_item(parent_tree, hf_hdr, tvb, offset, len, encoding);
7384 proto_item_add_bitmask_tree(item, tvb, offset, len, ett, fields, encoding,
7385 BMT_NO_INT|BMT_NO_TFS, FALSE);
7391 /* The same as proto_tree_add_bitmask(), but using an arbitrary text as a top-level item */
7393 proto_tree_add_bitmask_text(proto_tree *parent_tree, tvbuff_t *tvb,
7394 const guint offset, const guint len,
7395 const char *name, const char *fallback,
7396 const gint ett, const int **fields,
7397 const guint encoding, const int flags)
7399 proto_item *item = NULL;
7402 item = proto_tree_add_text(parent_tree, tvb, offset, len, "%s", name ? name : "");
7403 if (proto_item_add_bitmask_tree(item, tvb, offset, len, ett, fields, encoding,
7404 flags, TRUE) && fallback) {
7405 /* Still at first item - append 'fallback' text if any */
7406 proto_item_append_text(item, "%s", fallback);
7414 proto_tree_add_bits_item(proto_tree *tree, const int hf_index, tvbuff_t *tvb,
7415 const guint bit_offset, const gint no_of_bits,
7416 const guint encoding)
7418 header_field_info *hfinfo;
7420 TRY_TO_FAKE_THIS_ITEM(tree, hf_index, hfinfo);
7422 return proto_tree_add_bits_ret_val(tree, hf_index, tvb, bit_offset, no_of_bits, NULL, encoding);
7426 * This function will dissect a sequence of bits that does not need to be byte aligned; the bits
7427 * set will be shown in the tree as ..10 10.. and the integer value returned if return_value is set.
7428 * Offset should be given in bits from the start of the tvb.
7432 _proto_tree_add_bits_ret_val(proto_tree *tree, const int hf_index, tvbuff_t *tvb,
7433 const guint bit_offset, const gint no_of_bits,
7434 guint64 *return_value, const guint encoding)
7440 char lbl_str[ITEM_LABEL_LENGTH];
7444 header_field_info *hf_field;
7446 const true_false_string *tfstring;
7448 /* We can't fake it just yet. We have to fill in the 'return_value' parameter */
7449 PROTO_REGISTRAR_GET_NTH(hf_index, hf_field);
7451 if (hf_field->bitmask != 0) {
7452 REPORT_DISSECTOR_BUG(ep_strdup_printf("Incompatible use of proto_tree_add_bits_ret_val"
7453 " with field '%s' (%s) with bitmask != 0",
7454 hf_field->abbrev, hf_field->name));
7457 DISSECTOR_ASSERT(no_of_bits > 0);
7459 /* Byte align offset */
7460 offset = bit_offset>>3;
7463 * Calculate the number of octets used to hold the bits
7465 tot_no_bits = ((bit_offset&0x7) + no_of_bits);
7466 length = tot_no_bits>>3;
7467 /* If we are using part of the next octet, increase length by 1 */
7468 if (tot_no_bits & 0x07)
7471 if (no_of_bits < 65) {
7472 value = tvb_get_bits64(tvb, bit_offset, no_of_bits, encoding);
7474 DISSECTOR_ASSERT_NOT_REACHED();
7478 /* Sign extend for signed types */
7479 switch (hf_field->type) {
7485 if (value & (G_GINT64_CONSTANT(1) << (no_of_bits-1)))
7486 value |= (G_GINT64_CONSTANT(-1) << no_of_bits);
7494 *return_value = value;
7497 /* Coast clear. Try and fake it */
7498 TRY_TO_FAKE_THIS_ITEM(tree, hf_index, hf_field);
7500 bf_str = decode_bits_in_field(bit_offset, no_of_bits, value);
7502 switch (hf_field->type) {
7505 tfstring = (const true_false_string *) &tfs_true_false;
7506 if (hf_field->strings)
7507 tfstring = (const true_false_string *)hf_field->strings;
7508 return proto_tree_add_boolean_format(tree, hf_index, tvb, offset, length, (guint32)value,
7510 bf_str, hf_field->name,
7511 (guint32)value ? tfstring->true_string : tfstring->false_string);
7518 pi = proto_tree_add_uint(tree, hf_index, tvb, offset, length, (guint32)value);
7519 fill_label_uint(PITEM_FINFO(pi), lbl_str);
7526 pi = proto_tree_add_int(tree, hf_index, tvb, offset, length, (gint32)value);
7527 fill_label_int(PITEM_FINFO(pi), lbl_str);
7531 pi = proto_tree_add_uint64(tree, hf_index, tvb, offset, length, value);
7532 fill_label_uint64(PITEM_FINFO(pi), lbl_str);
7536 pi = proto_tree_add_int64(tree, hf_index, tvb, offset, length, (gint64)value);
7537 fill_label_int64(PITEM_FINFO(pi), lbl_str);
7541 DISSECTOR_ASSERT_NOT_REACHED();
7546 proto_item_set_text(pi, "%s = %s", bf_str, lbl_str);
7551 proto_tree_add_split_bits_item_ret_val(proto_tree *tree, const int hf_index, tvbuff_t *tvb,
7552 const guint bit_offset, const crumb_spec_t *crumb_spec,
7553 guint64 *return_value)
7558 guint mask_initial_bit_offset;
7559 guint mask_greatest_bit_offset;
7563 char lbl_str[ITEM_LABEL_LENGTH];
7565 guint64 composite_bitmask;
7566 guint64 composite_bitmap;
7568 header_field_info *hf_field;
7569 const true_false_string *tfstring;
7571 /* We can't fake it just yet. We have to fill in the 'return_value' parameter */
7572 PROTO_REGISTRAR_GET_NTH(hf_index, hf_field);
7574 if (hf_field->bitmask != 0) {
7575 REPORT_DISSECTOR_BUG(ep_strdup_printf(
7576 "Incompatible use of proto_tree_add_split_bits_item_ret_val"
7577 " with field '%s' (%s) with bitmask != 0",
7578 hf_field->abbrev, hf_field->name));
7581 mask_initial_bit_offset = bit_offset % 8;
7586 mask_greatest_bit_offset = 0;
7587 composite_bitmask = 0;
7588 composite_bitmap = 0;
7590 while (crumb_spec[i].crumb_bit_length != 0) {
7591 guint64 crumb_mask, crumb_value;
7592 guint8 crumb_end_bit_offset;
7594 DISSECTOR_ASSERT(i < 64);
7595 crumb_value = tvb_get_bits64(tvb,
7596 bit_offset + crumb_spec[i].crumb_bit_offset,
7597 crumb_spec[i].crumb_bit_length,
7599 value += crumb_value;
7600 no_of_bits += crumb_spec[i].crumb_bit_length;
7602 /* The bitmask is 64 bit, left-aligned, starting at the first bit of the
7603 octet containing the initial offset.
7604 If the mask is beyond 32 bits, then give up on bit map display.
7605 This could be improved in future, probably showing a table
7606 of 32 or 64 bits per row */
7607 if (mask_greatest_bit_offset < 32) {
7608 crumb_end_bit_offset = mask_initial_bit_offset
7609 + crumb_spec[i].crumb_bit_offset
7610 + crumb_spec[i].crumb_bit_length;
7611 crumb_mask = (G_GUINT64_CONSTANT(1) << crumb_spec[i].crumb_bit_length) - 1;
7613 if (crumb_end_bit_offset > mask_greatest_bit_offset) {
7614 mask_greatest_bit_offset = crumb_end_bit_offset;
7616 composite_bitmask |= (crumb_mask << (64 - crumb_end_bit_offset));
7617 composite_bitmap |= (crumb_value << (64 - crumb_end_bit_offset));
7619 /* Shift left for the next segment */
7620 value <<= crumb_spec[++i].crumb_bit_length;
7623 /* Sign extend for signed types */
7624 switch (hf_field->type) {
7630 if (value & no_of_bits && (G_GINT64_CONSTANT(1) << (no_of_bits-1)))
7631 value |= (G_GINT64_CONSTANT(-1) << no_of_bits);
7638 *return_value = value;
7641 /* Coast clear. Try and fake it */
7642 TRY_TO_FAKE_THIS_ITEM(tree, hf_index, hf_field);
7644 /* initialise the format string */
7645 bf_str = ep_alloc(256);
7648 octet_offset = bit_offset >> 3;
7650 /* Round up mask length to nearest octet */
7651 octet_length = ((mask_greatest_bit_offset + 7) >> 3);
7652 mask_greatest_bit_offset = octet_length << 3;
7654 /* As noted above, we currently only produce a bitmap if the crumbs span less than 4 octets of the tvb.
7655 It would be a useful enhancement to eliminate this restriction. */
7656 if (mask_greatest_bit_offset <= 32) {
7657 other_decode_bitfield_value(bf_str,
7658 (guint32)(composite_bitmap >> (64 - mask_greatest_bit_offset)),
7659 (guint32)(composite_bitmask >> (64 - mask_greatest_bit_offset)),
7660 mask_greatest_bit_offset);
7663 switch (hf_field->type) {
7664 case FT_BOOLEAN: /* it is a bit odd to have a boolean encoded as split-bits, but possible, I suppose? */
7666 tfstring = (const true_false_string *) &tfs_true_false;
7667 if (hf_field->strings)
7668 tfstring = (const true_false_string *) hf_field->strings;
7669 return proto_tree_add_boolean_format(tree, hf_index,
7670 tvb, octet_offset, octet_length, (guint32)value,
7672 bf_str, hf_field->name,
7673 (guint32)value ? tfstring->true_string : tfstring->false_string);
7680 pi = proto_tree_add_uint(tree, hf_index, tvb, octet_offset, octet_length, (guint32)value);
7681 fill_label_uint(PITEM_FINFO(pi), lbl_str);
7688 pi = proto_tree_add_int(tree, hf_index, tvb, octet_offset, octet_length, (gint32)value);
7689 fill_label_int(PITEM_FINFO(pi), lbl_str);
7693 pi = proto_tree_add_uint64(tree, hf_index, tvb, octet_offset, octet_length, value);
7694 fill_label_uint64(PITEM_FINFO(pi), lbl_str);
7698 pi = proto_tree_add_int64(tree, hf_index, tvb, octet_offset, octet_length, (gint64)value);
7699 fill_label_int64(PITEM_FINFO(pi), lbl_str);
7703 DISSECTOR_ASSERT_NOT_REACHED();
7707 proto_item_set_text(pi, "%s = %s", bf_str, lbl_str);
7712 proto_tree_add_split_bits_crumb(proto_tree *tree, const int hf_index, tvbuff_t *tvb, const guint bit_offset,
7713 const crumb_spec_t *crumb_spec, guint16 crumb_index)
7715 header_field_info *hf_info;
7717 PROTO_REGISTRAR_GET_NTH(hf_index, hf_info);
7718 proto_tree_add_text(tree, tvb,
7720 ((bit_offset + crumb_spec[crumb_index].crumb_bit_length - 1) >> 3) - (bit_offset >> 3) + 1,
7721 "%s crumb %d of %s (decoded above)",
7722 decode_bits_in_field(bit_offset, crumb_spec[crumb_index].crumb_bit_length,
7725 crumb_spec[crumb_index].crumb_bit_length,
7732 proto_tree_add_bits_ret_val(proto_tree *tree, const int hf_index, tvbuff_t *tvb,
7733 const guint bit_offset, const gint no_of_bits,
7734 guint64 *return_value, const guint encoding)
7738 if ((item = _proto_tree_add_bits_ret_val(tree, hf_index, tvb,
7739 bit_offset, no_of_bits,
7740 return_value, encoding))) {
7741 FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_OFFSET(bit_offset));
7742 FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_SIZE(no_of_bits));
7748 _proto_tree_add_bits_format_value(proto_tree *tree, const int hf_index,
7749 tvbuff_t *tvb, const guint bit_offset,
7750 const gint no_of_bits, void *value_ptr,
7758 header_field_info *hf_field;
7760 /* We do not have to return a value, try to fake it as soon as possible */
7761 TRY_TO_FAKE_THIS_ITEM(tree, hf_index, hf_field);
7763 if (hf_field->bitmask != 0) {
7764 REPORT_DISSECTOR_BUG(ep_strdup_printf(
7765 "Incompatible use of proto_tree_add_bits_format_value"
7766 " with field '%s' (%s) with bitmask != 0",
7767 hf_field->abbrev, hf_field->name));
7770 DISSECTOR_ASSERT(no_of_bits > 0);
7772 /* Byte align offset */
7773 offset = bit_offset>>3;
7776 * Calculate the number of octets used to hold the bits
7778 tot_no_bits = ((bit_offset&0x7) + no_of_bits);
7779 length = tot_no_bits>>3;
7780 /* If we are using part of the next octet, increase length by 1 */
7781 if (tot_no_bits & 0x07)
7784 if (no_of_bits < 65) {
7785 value = tvb_get_bits64(tvb, bit_offset, no_of_bits, ENC_BIG_ENDIAN);
7787 DISSECTOR_ASSERT_NOT_REACHED();
7791 str = decode_bits_in_field(bit_offset, no_of_bits, value);
7794 strcat(str, hf_field->name);
7797 * This function does not receive an actual value but a dimensionless pointer to that value.
7798 * For this reason, the type of the header field is examined in order to determine
7799 * what kind of value we should read from this address.
7800 * The caller of this function must make sure that for the specific header field type the address of
7801 * a compatible value is provided.
7803 switch (hf_field->type) {
7805 return proto_tree_add_boolean_format(tree, hf_index, tvb, offset, length, *(guint32 *)value_ptr,
7806 "%s: %s", str, value_str);
7813 return proto_tree_add_uint_format(tree, hf_index, tvb, offset, length, *(guint32 *)value_ptr,
7814 "%s: %s", str, value_str);
7818 return proto_tree_add_uint64_format(tree, hf_index, tvb, offset, length, *(guint64 *)value_ptr,
7819 "%s: %s", str, value_str);
7826 return proto_tree_add_int_format(tree, hf_index, tvb, offset, length, *(gint32 *)value_ptr,
7827 "%s: %s", str, value_str);
7831 return proto_tree_add_int64_format(tree, hf_index, tvb, offset, length, *(gint64 *)value_ptr,
7832 "%s: %s", str, value_str);
7836 return proto_tree_add_float_format(tree, hf_index, tvb, offset, length, *(float *)value_ptr,
7837 "%s: %s", str, value_str);
7841 DISSECTOR_ASSERT_NOT_REACHED();
7848 proto_tree_add_bits_format_value(proto_tree *tree, const int hf_index,
7849 tvbuff_t *tvb, const guint bit_offset,
7850 const gint no_of_bits, void *value_ptr,
7855 if ((item = _proto_tree_add_bits_format_value(tree, hf_index,
7856 tvb, bit_offset, no_of_bits,
7857 value_ptr, value_str))) {
7858 FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_OFFSET(bit_offset));
7859 FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_SIZE(no_of_bits));
7864 #define CREATE_VALUE_STRING(dst,format,ap) \
7865 va_start(ap, format); \
7866 dst = ep_strdup_vprintf(format, ap); \
7870 proto_tree_add_uint_bits_format_value(proto_tree *tree, const int hf_index,
7871 tvbuff_t *tvb, const guint bit_offset,
7872 const gint no_of_bits, guint32 value,
7873 const char *format, ...)
7877 header_field_info *hf_field;
7879 TRY_TO_FAKE_THIS_ITEM(tree, hf_index, hf_field);
7881 switch (hf_field->type) {
7889 DISSECTOR_ASSERT_NOT_REACHED();
7894 CREATE_VALUE_STRING(dst, format, ap);
7896 return proto_tree_add_bits_format_value(tree, hf_index, tvb, bit_offset, no_of_bits, &value, dst);
7900 proto_tree_add_float_bits_format_value(proto_tree *tree, const int hf_index,
7901 tvbuff_t *tvb, const guint bit_offset,
7902 const gint no_of_bits, float value,
7903 const char *format, ...)
7907 header_field_info *hf_field;
7909 TRY_TO_FAKE_THIS_ITEM(tree, hf_index, hf_field);
7911 DISSECTOR_ASSERT(hf_field->type == FT_FLOAT);
7913 CREATE_VALUE_STRING(dst, format, ap);
7915 return proto_tree_add_bits_format_value(tree, hf_index, tvb, bit_offset, no_of_bits, &value, dst);
7919 proto_tree_add_int_bits_format_value(proto_tree *tree, const int hf_index,
7920 tvbuff_t *tvb, const guint bit_offset,
7921 const gint no_of_bits, gint32 value,
7922 const char *format, ...)
7926 header_field_info *hf_field;
7928 TRY_TO_FAKE_THIS_ITEM(tree, hf_index, hf_field);
7930 switch (hf_field->type) {
7938 DISSECTOR_ASSERT_NOT_REACHED();
7943 CREATE_VALUE_STRING(dst, format, ap);
7945 return proto_tree_add_bits_format_value(tree, hf_index, tvb, bit_offset, no_of_bits, &value, dst);
7949 proto_tree_add_boolean_bits_format_value(proto_tree *tree, const int hf_index,
7950 tvbuff_t *tvb, const guint bit_offset,
7951 const gint no_of_bits, guint32 value,
7952 const char *format, ...)
7956 header_field_info *hf_field;
7958 TRY_TO_FAKE_THIS_ITEM(tree, hf_index, hf_field);
7960 DISSECTOR_ASSERT(hf_field->type == FT_BOOLEAN);
7962 CREATE_VALUE_STRING(dst, format, ap);
7964 return proto_tree_add_bits_format_value(tree, hf_index, tvb, bit_offset, no_of_bits, &value, dst);
7968 proto_check_field_name(const gchar *field_name)
7970 return wrs_check_charset(fld_abbrev_chars, field_name);