2 * Routines for protocol tree
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
36 #include "ptvcursor.h"
38 #include "addr_resolv.h"
42 #include "epan_dissect.h"
47 #include "asm_utils.h"
48 #include "column-utils.h"
52 #include "wspython/wspy_register.h"
54 #define SUBTREE_ONCE_ALLOCATION_NUMBER 8
55 #define SUBTREE_MAX_LEVELS 256
56 /* Throw an exception if we exceed this many tree items. */
57 /* XXX - This should probably be a preference */
58 #define MAX_TREE_ITEMS (1 * 1000 * 1000)
61 typedef struct __subtree_lvl {
68 subtree_lvl *pushed_tree;
69 guint8 pushed_tree_index;
70 guint8 pushed_tree_max;
76 /* Candidates for assembler */
78 wrs_count_bitshift(const guint32 bitmask)
82 while ((bitmask & (1 << bitshift)) == 0)
87 #define cVALS(x) (const value_string*)(x)
89 /** See inlined comments.
90 @param tree the tree to append this item to
91 @param hfindex field index
92 @param hfinfo header_field
93 @return the header field matching 'hfinfo' */
94 #define TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo) \
95 /* If this item is not referenced we dont have to do much work \
96 at all but we should still return a node so that field items \
97 below this node (think proto_item_add_subtree()) will still \
98 have somewhere to attach to or else filtering will not work \
99 (they would be ignored since tree would be NULL). \
100 DONT try to fake a node where PTREE_FINFO(tree) is NULL \
101 since dissectors that want to do proto_item_set_len() or \
102 other operations that dereference this would crash. \
103 We fake FT_PROTOCOL unless some clients have requested us \
108 PTREE_DATA(tree)->count++; \
109 if (PTREE_DATA(tree)->count > MAX_TREE_ITEMS) { \
110 if (getenv("WIRESHARK_ABORT_ON_DISSECTOR_BUG") != NULL) \
112 /* Let the exception handler add items to the tree */ \
113 PTREE_DATA(tree)->count = 0; \
114 THROW_MESSAGE(DissectorError, \
115 ep_strdup_printf("More than %d items in the tree -- possible infinite loop", MAX_TREE_ITEMS)); \
117 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo); \
118 if (!(PTREE_DATA(tree)->visible)) { \
119 if (PTREE_FINFO(tree)) { \
120 if ((hfinfo->ref_type != HF_REF_TYPE_DIRECT) \
121 && (hfinfo->type != FT_PROTOCOL || \
122 PTREE_DATA(tree)->fake_protocols)) { \
123 /* just return tree back to the caller */\
129 /** See inlined comments.
130 @param tree the tree to append this item to
131 @param pi the created protocol item we're about to return */
132 #define TRY_TO_FAKE_THIS_REPR(tree, pi) \
135 if (!(PTREE_DATA(tree)->visible)) { \
136 /* If the tree (GUI) isn't visible it's pointless for us to generate the protocol \
137 * items string representation */ \
142 proto_tree_free_node(proto_node *node, gpointer data);
144 static void fill_label_boolean(field_info *fi, gchar *label_str);
145 static void fill_label_uint(field_info *fi, gchar *label_str);
146 static void fill_label_uint64(field_info *fi, gchar *label_str);
147 static void fill_label_bitfield(field_info *fi, gchar *label_str);
148 static void fill_label_int(field_info *fi, gchar *label_str);
149 static void fill_label_int64(field_info *fi, gchar *label_str);
151 static const char* hfinfo_uint_vals_format(const header_field_info *hfinfo);
152 static const char* hfinfo_uint_format(const header_field_info *hfinfo);
153 static const char* hfinfo_uint_value_format(const header_field_info *hfinfo);
154 static const char* hfinfo_uint64_format(const header_field_info *hfinfo);
155 static const char* hfinfo_int_vals_format(const header_field_info *hfinfo);
156 static const char* hfinfo_int_format(const header_field_info *hfinfo);
157 static const char* hfinfo_int_value_format(const header_field_info *hfinfo);
158 static const char* hfinfo_int64_format(const header_field_info *hfinfo);
159 static const char* hfinfo_numeric_value_format(const header_field_info *hfinfo);
162 proto_tree_add_node(proto_tree *tree, field_info *fi);
164 static header_field_info *
165 get_hfi_and_length(int hfindex, tvbuff_t *tvb, const gint start, gint *length,
169 new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
170 const gint start, const gint item_length);
173 alloc_field_info(proto_tree *tree, int hfindex, tvbuff_t *tvb,
174 const gint start, gint *length);
177 proto_tree_add_pi(proto_tree *tree, int hfindex, tvbuff_t *tvb,
178 gint start, gint *length, field_info **pfi);
181 proto_tree_set_representation_value(proto_item *pi, const char *format, va_list ap);
183 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap);
186 proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb);
188 proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length);
190 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length);
192 proto_tree_set_time(field_info *fi, nstime_t *value_ptr);
194 proto_tree_set_string(field_info *fi, const char* value);
196 proto_tree_set_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length, gint encoding);
198 proto_tree_set_ax25(field_info *fi, const guint8* value);
200 proto_tree_set_ax25_tvb(field_info *fi, tvbuff_t *tvb, gint start);
202 proto_tree_set_ether(field_info *fi, const guint8* value);
204 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start);
206 proto_tree_set_ipxnet(field_info *fi, guint32 value);
208 proto_tree_set_ipv4(field_info *fi, guint32 value);
210 proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr);
212 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
214 proto_tree_set_guid(field_info *fi, const e_guid_t *value_ptr);
216 proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, gint start, const guint encoding);
218 proto_tree_set_oid(field_info *fi, const guint8* value_ptr, gint length);
220 proto_tree_set_oid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
222 proto_tree_set_boolean(field_info *fi, guint32 value);
224 proto_tree_set_float(field_info *fi, float value);
226 proto_tree_set_double(field_info *fi, double value);
228 proto_tree_set_uint(field_info *fi, guint32 value);
230 proto_tree_set_int(field_info *fi, gint32 value);
232 proto_tree_set_uint64(field_info *fi, guint64 value);
234 proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start, guint length, const guint encoding);
236 proto_tree_set_eui64(field_info *fi, const guint64 value);
238 proto_tree_set_eui64_tvb(field_info *fi, tvbuff_t *tvb, gint start, const guint encoding);
240 proto_item_add_bitmask_tree(proto_item *item, tvbuff_t *tvb, const int offset,
241 const int len, const gint ett, const gint **fields,
242 const guint encoding, const int flags,
245 static int proto_register_field_init(header_field_info *hfinfo, const int parent);
247 /* special-case header field used within proto.c */
248 int hf_text_only = -1;
250 /* Structure for information about a protocol */
252 const char *name; /* long description */
253 const char *short_name; /* short description */
254 const char *filter_name; /* name of this protocol in filters */
255 int proto_id; /* field ID for this protocol */
256 GList *fields; /* fields for this protocol */
257 GList *last_field; /* pointer to end of list of fields */
258 gboolean is_enabled; /* TRUE if protocol is enabled */
259 gboolean can_toggle; /* TRUE if is_enabled can be changed */
260 gboolean is_private; /* TRUE is protocol is private */
263 /* List of all protocols */
264 static GList *protocols = NULL;
266 #define INITIAL_NUM_PROTOCOL_HFINFO 1500
268 /* Contains information about a field when a dissector calls
269 * proto_tree_add_item. */
270 static struct ws_memory_slab field_info_slab =
271 WS_MEMORY_SLAB_INIT(field_info, 128);
273 #define FIELD_INFO_NEW(fi) \
274 fi = sl_alloc(&field_info_slab)
275 #define FIELD_INFO_FREE(fi) \
276 sl_free(&field_info_slab, fi)
278 /* Contains the space for proto_nodes. */
279 static struct ws_memory_slab proto_node_slab =
280 WS_MEMORY_SLAB_INIT(proto_node, 128);
282 #define PROTO_NODE_NEW(node) \
283 node = sl_alloc(&proto_node_slab); \
284 node->first_child = NULL; \
285 node->last_child = NULL; \
288 #define PROTO_NODE_FREE(node) \
289 sl_free(&proto_node_slab, node)
291 /* String space for protocol and field items for the GUI */
292 static struct ws_memory_slab item_label_slab =
293 WS_MEMORY_SLAB_INIT(item_label_t, 128);
295 #define ITEM_LABEL_NEW(il) \
296 il = sl_alloc(&item_label_slab);
297 #define ITEM_LABEL_FREE(il) \
298 sl_free(&item_label_slab, il);
300 #define PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo) \
301 DISSECTOR_ASSERT((guint)hfindex < gpa_hfinfo.len); \
302 hfinfo = gpa_hfinfo.hfi[hfindex];
304 /* List which stores protocols and fields that have been registered */
305 typedef struct _gpa_hfinfo_t {
307 guint32 allocated_len;
308 header_field_info **hfi;
310 gpa_hfinfo_t gpa_hfinfo;
312 /* Balanced tree of abbreviations and IDs */
313 static GTree *gpa_name_tree = NULL;
314 static header_field_info *same_name_hfinfo;
316 static void save_same_name_hfinfo(gpointer data)
318 same_name_hfinfo = (header_field_info*)data;
321 /* Points to the first element of an array of Booleans, indexed by
322 a subtree item type; that array element is TRUE if subtrees of
323 an item of that type are to be expanded. */
324 gboolean *tree_is_expanded;
326 /* Number of elements in that array. */
329 /* Name hashtables for fast detection of duplicate names */
330 static GHashTable* proto_names = NULL;
331 static GHashTable* proto_short_names = NULL;
332 static GHashTable* proto_filter_names = NULL;
335 proto_compare_name(gconstpointer p1_arg, gconstpointer p2_arg)
337 const protocol_t *p1 = p1_arg;
338 const protocol_t *p2 = p2_arg;
340 return g_ascii_strcasecmp(p1->short_name, p2->short_name);
344 /* initialize data structures and register protocols and fields */
346 proto_init(void (register_all_protocols_func)(register_cb cb, gpointer client_data),
347 void (register_all_handoffs_func)(register_cb cb, gpointer client_data),
349 gpointer client_data)
351 static hf_register_info hf[] = {
353 { "Text item", "text", FT_NONE, BASE_NONE, NULL, 0x0,
359 proto_names = g_hash_table_new_full(g_int_hash, g_int_equal, g_free, NULL);
360 proto_short_names = g_hash_table_new(wrs_str_hash, g_str_equal);
361 proto_filter_names = g_hash_table_new(wrs_str_hash, g_str_equal);
364 gpa_hfinfo.allocated_len = 0;
365 gpa_hfinfo.hfi = NULL;
366 gpa_name_tree = g_tree_new_full(wrs_strcmp_with_data, NULL, NULL, save_same_name_hfinfo);
368 /* Initialize the ftype subsystem */
371 /* Register one special-case FT_TEXT_ONLY field for use when
372 converting wireshark to new-style proto_tree. These fields
373 are merely strings on the GUI tree; they are not filterable */
374 proto_register_field_array(-1, hf, array_length(hf));
376 /* Have each built-in dissector register its protocols, fields,
377 dissector tables, and dissectors to be called through a
378 handle, and do whatever one-time initialization it needs to
380 register_all_protocols_func(cb, client_data);
382 /* Now scan for python protocols */
384 (*cb)(RA_PYTHON_REGISTER, NULL, client_data);
385 register_all_py_protocols_func();
389 /* Now scan for plugins and load all the ones we find, calling
390 their register routines to do the stuff described above. */
392 (*cb)(RA_PLUGIN_REGISTER, NULL, client_data);
394 register_all_plugin_registrations();
397 /* Now call the "handoff registration" routines of all built-in
398 dissectors; those routines register the dissector in other
399 dissectors' handoff tables, and fetch any dissector handles
401 register_all_handoffs_func(cb, client_data);
404 /* Now do the same with python dissectors */
406 (*cb)(RA_PYTHON_HANDOFF, NULL, client_data);
407 register_all_py_handoffs_func();
411 /* Now do the same with plugins. */
413 (*cb)(RA_PLUGIN_HANDOFF, NULL, client_data);
414 register_all_plugin_handoffs();
417 /* sort the protocols by protocol name */
418 protocols = g_list_sort(protocols, proto_compare_name);
420 /* We've assigned all the subtree type values; allocate the array
421 for them, and zero it out. */
422 tree_is_expanded = g_new0(gboolean, num_tree_types);
428 /* Free the abbrev/ID GTree */
430 g_tree_destroy(gpa_name_tree);
431 gpa_name_tree = NULL;
435 protocol_t *protocol = protocols->data;
436 header_field_info *hfinfo;
437 PROTO_REGISTRAR_GET_NTH(protocol->proto_id, hfinfo);
438 DISSECTOR_ASSERT(protocol->proto_id == hfinfo->id);
440 g_slice_free(header_field_info, hfinfo);
441 g_list_free(protocol->fields);
442 protocols = g_list_remove(protocols, protocol);
447 g_hash_table_destroy(proto_names);
451 if (proto_short_names) {
452 g_hash_table_destroy(proto_short_names);
453 proto_short_names = NULL;
456 if (proto_filter_names) {
457 g_hash_table_destroy(proto_filter_names);
458 proto_filter_names = NULL;
461 if (gpa_hfinfo.allocated_len) {
463 gpa_hfinfo.allocated_len = 0;
464 g_free(gpa_hfinfo.hfi);
465 gpa_hfinfo.hfi = NULL;
467 g_free(tree_is_expanded);
468 tree_is_expanded = NULL;
472 proto_tree_traverse_pre_order(proto_tree *tree, proto_tree_traverse_func func,
475 proto_node *pnode = tree;
479 if (func(pnode, data))
482 child = pnode->first_child;
483 while (child != NULL) {
485 * The routine we call might modify the child, e.g. by
486 * freeing it, so we get the child's successor before
487 * calling that routine.
490 child = current->next;
491 if (proto_tree_traverse_pre_order((proto_tree *)current, func, data))
499 proto_tree_traverse_post_order(proto_tree *tree, proto_tree_traverse_func func,
502 proto_node *pnode = tree;
506 child = pnode->first_child;
507 while (child != NULL) {
509 * The routine we call might modify the child, e.g. by
510 * freeing it, so we get the child's successor before
511 * calling that routine.
514 child = current->next;
515 if (proto_tree_traverse_post_order((proto_tree *)current, func, data))
518 if (func(pnode, data))
525 proto_tree_children_foreach(proto_tree *tree, proto_tree_foreach_func func,
528 proto_node *node = tree;
531 node = node->first_child;
532 while (node != NULL) {
534 node = current->next;
535 func((proto_tree *)current, data);
539 /* frees the resources that the dissection a proto_tree uses */
541 proto_tree_free(proto_tree *tree)
543 proto_tree_traverse_post_order(tree, proto_tree_free_node, NULL);
547 free_GPtrArray_value(gpointer key, gpointer value, gpointer user_data _U_)
549 GPtrArray *ptrs = value;
550 gint hfid = (gint)(long)key;
551 header_field_info *hfinfo;
553 PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
554 if (hfinfo->ref_type != HF_REF_TYPE_NONE) {
555 /* when a field is referenced by a filter this also
556 affects the refcount for the parent protocol so we need
557 to adjust the refcount for the parent as well
559 if (hfinfo->parent != -1) {
560 header_field_info *parent_hfinfo;
561 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
562 parent_hfinfo->ref_type = HF_REF_TYPE_NONE;
564 hfinfo->ref_type = HF_REF_TYPE_NONE;
567 g_ptr_array_free(ptrs, TRUE);
571 free_node_tree_data(tree_data_t *tree_data)
573 if (tree_data->interesting_hfids) {
574 /* Free all the GPtrArray's in the interesting_hfids hash. */
575 g_hash_table_foreach(tree_data->interesting_hfids,
576 free_GPtrArray_value, NULL);
578 /* And then destroy the hash. */
579 g_hash_table_destroy(tree_data->interesting_hfids);
581 if (tree_data->fi_tmp)
582 FIELD_INFO_FREE(tree_data->fi_tmp);
584 /* And finally the tree_data_t itself. */
588 #define FREE_NODE_FIELD_INFO(finfo) \
590 ITEM_LABEL_FREE(finfo->rep); \
592 FVALUE_CLEANUP(&finfo->value); \
593 FIELD_INFO_FREE(finfo);
596 proto_tree_free_node(proto_node *node, gpointer data _U_)
598 field_info *finfo = PNODE_FINFO(node);
600 proto_node *parent = node->parent;
604 /* This is the root node. Destroy the per-tree data.
605 * There is no field_info to destroy. */
606 if (PTREE_DATA(node))
607 free_node_tree_data(PTREE_DATA(node));
610 /* This is a child node. Don't free the per-tree data, but
611 * do free the field_info data. */
612 FREE_NODE_FIELD_INFO(finfo);
616 /* NOTE: This code is required when this function is used to free individual
617 * nodes only. Current use is for the destruction of complete trees, so the
618 * inconsistancies have no ill effect.
620 /* Remove node from parent */
622 proto_item *prev_item = NULL;
623 if (parent->first_child == node) {
624 parent->first_child = node->next;
626 /* find previous and change its next */
627 for (prev_item = parent->first_child; prev_item; prev_item = prev_item->next) {
628 if (prev_item->next == node) {
632 DISSECTOR_ASSERT(prev_item);
633 prev_item->next = node->next;
635 /* fix last_child if required */
636 if (parent->last_child == node) {
637 parent->last_child = prev_item;
640 DISSECTOR_ASSERT(node->first_child == NULL && node->last_child == NULL);
642 /* Free the proto_node. */
643 PROTO_NODE_FREE(node);
645 return FALSE; /* FALSE = do not end traversal of protocol tree */
648 /* Is the parsing being done for a visible proto_tree or an invisible one?
649 * By setting this correctly, the proto_tree creation is sped up by not
650 * having to call g_vsnprintf and copy strings around.
653 proto_tree_set_visible(proto_tree *tree, gboolean visible)
655 gboolean old_visible = PTREE_DATA(tree)->visible;
657 PTREE_DATA(tree)->visible = visible;
663 proto_tree_set_fake_protocols(proto_tree *tree, gboolean fake_protocols)
665 PTREE_DATA(tree)->fake_protocols = fake_protocols;
668 /* Assume dissector set only its protocol fields.
669 This function is called by dissectors and allows the speeding up of filtering
670 in wireshark; if this function returns FALSE it is safe to reset tree to NULL
671 and thus skip calling most of the expensive proto_tree_add_...()
673 If the tree is visible we implicitly assume the field is referenced.
676 proto_field_is_referenced(proto_tree *tree, int proto_id)
678 register header_field_info *hfinfo;
684 if (PTREE_DATA(tree)->visible)
687 PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
688 if (hfinfo->ref_type != HF_REF_TYPE_NONE)
691 if (hfinfo->type == FT_PROTOCOL && !PTREE_DATA(tree)->fake_protocols)
698 /* Finds a record in the hf_info_records array by id. */
700 proto_registrar_get_nth(guint hfindex)
702 register header_field_info *hfinfo;
704 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
709 /* Prefix initialization
710 * this allows for a dissector to register a display filter name prefix
711 * so that it can delay the initialization of the hf array as long as
715 /* compute a hash for the part before the dot of a display filter */
717 prefix_hash (gconstpointer key) {
718 /* end the string at the dot and compute its hash */
719 gchar* copy = ep_strdup(key);
729 return g_str_hash(copy);
732 /* are both strings equal up to the end or the dot? */
734 prefix_equal (gconstpointer ap, gconstpointer bp) {
742 if ( (ac == '.' || ac == '\0') && (bc == '.' || bc == '\0') ) return TRUE;
744 if ( (ac == '.' || ac == '\0') && ! (bc == '.' || bc == '\0') ) return FALSE;
745 if ( (bc == '.' || bc == '\0') && ! (ac == '.' || ac == '\0') ) return FALSE;
747 if (ac != bc) return FALSE;
754 /* indexed by prefix, contains initializers */
755 static GHashTable* prefixes = NULL;
758 /* Register a new prefix for "delayed" initialization of field arrays */
760 proto_register_prefix(const char *prefix, prefix_initializer_t pi ) {
762 prefixes = g_hash_table_new(prefix_hash, prefix_equal);
765 g_hash_table_insert(prefixes, (gpointer)prefix, pi);
768 /* helper to call all prefix initializers */
770 initialize_prefix(gpointer k, gpointer v, gpointer u _U_) {
771 ((prefix_initializer_t)v)(k);
775 /** Initialize every remaining uninitialized prefix. */
777 proto_initialize_all_prefixes(void) {
778 g_hash_table_foreach_remove(prefixes, initialize_prefix, NULL);
781 /* Finds a record in the hf_info_records array by name.
782 * If it fails to find it in the already registered fields,
783 * it tries to find and call an initializer in the prefixes
784 * table and if so it looks again.
787 proto_registrar_get_byname(const char *field_name)
789 header_field_info *hfinfo;
790 prefix_initializer_t pi;
795 hfinfo = g_tree_lookup(gpa_name_tree, field_name);
803 if ((pi = g_hash_table_lookup(prefixes, field_name) ) != NULL) {
805 g_hash_table_remove(prefixes, field_name);
810 return g_tree_lookup(gpa_name_tree, field_name);
815 ptvcursor_new_subtree_levels(ptvcursor_t *ptvc)
817 subtree_lvl *pushed_tree;
819 DISSECTOR_ASSERT(ptvc->pushed_tree_max <= SUBTREE_MAX_LEVELS-SUBTREE_ONCE_ALLOCATION_NUMBER);
820 ptvc->pushed_tree_max += SUBTREE_ONCE_ALLOCATION_NUMBER;
822 pushed_tree = ep_alloc(sizeof(subtree_lvl) * ptvc->pushed_tree_max);
823 DISSECTOR_ASSERT(pushed_tree != NULL);
824 if (ptvc->pushed_tree)
825 memcpy(pushed_tree, ptvc->pushed_tree, ptvc->pushed_tree_max - SUBTREE_ONCE_ALLOCATION_NUMBER);
826 ptvc->pushed_tree = pushed_tree;
830 ptvcursor_free_subtree_levels(ptvcursor_t *ptvc)
832 ptvc->pushed_tree = NULL;
833 ptvc->pushed_tree_max = 0;
834 DISSECTOR_ASSERT(ptvc->pushed_tree_index == 0);
835 ptvc->pushed_tree_index = 0;
838 /* Allocates an initializes a ptvcursor_t with 3 variables:
839 * proto_tree, tvbuff, and offset. */
841 ptvcursor_new(proto_tree *tree, tvbuff_t *tvb, gint offset)
845 ptvc = ep_alloc(sizeof(ptvcursor_t));
848 ptvc->offset = offset;
849 ptvc->pushed_tree = NULL;
850 ptvc->pushed_tree_max = 0;
851 ptvc->pushed_tree_index = 0;
856 /* Frees memory for ptvcursor_t, but nothing deeper than that. */
858 ptvcursor_free(ptvcursor_t *ptvc)
860 ptvcursor_free_subtree_levels(ptvc);
864 /* Returns tvbuff. */
866 ptvcursor_tvbuff(ptvcursor_t *ptvc)
871 /* Returns current offset. */
873 ptvcursor_current_offset(ptvcursor_t *ptvc)
879 ptvcursor_tree(ptvcursor_t *ptvc)
888 ptvcursor_set_tree(ptvcursor_t *ptvc, proto_tree *tree)
893 /* creates a subtree, sets it as the working tree and pushes the old working tree */
895 ptvcursor_push_subtree(ptvcursor_t *ptvc, proto_item *it, gint ett_subtree)
897 subtree_lvl *subtree;
898 if (ptvc->pushed_tree_index >= ptvc->pushed_tree_max)
899 ptvcursor_new_subtree_levels(ptvc);
901 subtree = ptvc->pushed_tree + ptvc->pushed_tree_index;
902 subtree->tree = ptvc->tree;
904 ptvc->pushed_tree_index++;
905 return ptvcursor_set_subtree(ptvc, it, ett_subtree);
910 ptvcursor_pop_subtree(ptvcursor_t *ptvc)
912 subtree_lvl *subtree;
914 if (ptvc->pushed_tree_index <= 0)
917 ptvc->pushed_tree_index--;
918 subtree = ptvc->pushed_tree + ptvc->pushed_tree_index;
919 if (subtree->it != NULL)
920 proto_item_set_len(subtree->it, ptvcursor_current_offset(ptvc) - subtree->cursor_offset);
922 ptvc->tree = subtree->tree;
925 /* saves the current tvb offset and the item in the current subtree level */
927 ptvcursor_subtree_set_item(ptvcursor_t *ptvc, proto_item *it)
929 subtree_lvl *subtree;
931 DISSECTOR_ASSERT(ptvc->pushed_tree_index > 0);
933 subtree = ptvc->pushed_tree + ptvc->pushed_tree_index - 1;
935 subtree->cursor_offset = ptvcursor_current_offset(ptvc);
938 /* Creates a subtree and adds it to the cursor as the working tree but does not
939 * save the old working tree */
941 ptvcursor_set_subtree(ptvcursor_t *ptvc, proto_item *it, gint ett_subtree)
943 ptvc->tree = proto_item_add_subtree(it, ett_subtree);
948 ptvcursor_add_subtree_item(ptvcursor_t *ptvc, proto_item *it, gint ett_subtree, gint length)
950 ptvcursor_push_subtree(ptvc, it, ett_subtree);
951 if (length == SUBTREE_UNDEFINED_LENGTH)
952 ptvcursor_subtree_set_item(ptvc, it);
953 return ptvcursor_tree(ptvc);
956 /* Add an item to the tree and create a subtree
957 * If the length is unknown, length may be defined as SUBTREE_UNDEFINED_LENGTH.
958 * In this case, when the subtree will be closed, the parent item length will
959 * be equal to the advancement of the cursor since the creation of the subtree.
962 ptvcursor_add_with_subtree(ptvcursor_t *ptvc, int hfindex, gint length,
963 const guint encoding, gint ett_subtree)
967 it = ptvcursor_add_no_advance(ptvc, hfindex, length, encoding);
968 return ptvcursor_add_subtree_item(ptvc, it, ett_subtree, length);
972 proto_tree_add_text_node(proto_tree *tree, tvbuff_t *tvb, gint start, gint length);
974 /* Add a text node to the tree and create a subtree
975 * If the length is unknown, length may be defined as SUBTREE_UNDEFINED_LENGTH.
976 * In this case, when the subtree will be closed, the item length will be equal
977 * to the advancement of the cursor since the creation of the subtree.
980 ptvcursor_add_text_with_subtree(ptvcursor_t *ptvc, gint length,
981 gint ett_subtree, const char *format, ...)
985 header_field_info *hfinfo;
988 tree = ptvcursor_tree(ptvc);
990 TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
992 pi = proto_tree_add_text_node(tree, ptvcursor_tvbuff(ptvc),
993 ptvcursor_current_offset(ptvc), length);
995 TRY_TO_FAKE_THIS_REPR(tree, pi);
997 va_start(ap, format);
998 proto_tree_set_representation(pi, format, ap);
1001 return ptvcursor_add_subtree_item(ptvc, pi, ett_subtree, length);
1004 /* Add a text-only node, leaving it to our caller to fill the text in */
1006 proto_tree_add_text_node(proto_tree *tree, tvbuff_t *tvb, gint start, gint length)
1010 pi = proto_tree_add_pi(tree, hf_text_only, tvb, start, &length, NULL);
1015 /* Add a text-only node to the proto_tree */
1017 proto_tree_add_text(proto_tree *tree, tvbuff_t *tvb, gint start, gint length,
1018 const char *format, ...)
1022 header_field_info *hfinfo;
1024 TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
1026 pi = proto_tree_add_text_node(tree, tvb, start, length);
1028 TRY_TO_FAKE_THIS_REPR(tree, pi);
1030 va_start(ap, format);
1031 proto_tree_set_representation(pi, format, ap);
1037 /* Add a text-only node to the proto_tree (va_list version) */
1039 proto_tree_add_text_valist(proto_tree *tree, tvbuff_t *tvb, gint start,
1040 gint length, const char *format, va_list ap)
1043 header_field_info *hfinfo;
1045 TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
1047 pi = proto_tree_add_text_node(tree, tvb, start, length);
1049 TRY_TO_FAKE_THIS_REPR(tree, pi);
1051 proto_tree_set_representation(pi, format, ap);
1056 /* Add a text-only node for debugging purposes. The caller doesn't need
1057 * to worry about tvbuff, start, or length. Debug message gets sent to
1060 proto_tree_add_debug_text(proto_tree *tree, const char *format, ...)
1065 pi = proto_tree_add_text_node(tree, NULL, 0, 0);
1068 va_start(ap, format);
1069 proto_tree_set_representation(pi, format, ap);
1072 va_start(ap, format);
1073 vprintf(format, ap);
1080 /* We could probably get away with changing is_error to a minimum length value. */
1082 report_type_length_mismatch(proto_tree *tree, const gchar *descr, int length, gboolean is_error) {
1083 tree_data_t *tree_data = PTREE_DATA(tree);
1084 field_info *fi_save = tree_data->fi_tmp;
1086 /* Keep the current item from getting freed by proto_tree_new_item. */
1087 tree_data->fi_tmp = NULL;
1089 expert_add_info_format(NULL, tree, PI_MALFORMED, is_error ? PI_ERROR : PI_WARN, "Trying to fetch %s with length %d", descr, length);
1091 tree_data->fi_tmp = fi_save;
1094 THROW(ReportedBoundsError);
1099 * NOTE: to support code written when proto_tree_add_item() took a
1100 * gboolean as its last argument, with FALSE meaning "big-endian"
1101 * and TRUE meaning "little-endian", we treat any non-zero value of
1102 * "encoding" as meaning "little-endian".
1105 get_uint_value(proto_tree *tree, tvbuff_t *tvb, gint offset, gint length, const guint encoding)
1108 gboolean length_error;
1113 value = tvb_get_guint8(tvb, offset);
1117 value = encoding ? tvb_get_letohs(tvb, offset)
1118 : tvb_get_ntohs(tvb, offset);
1122 value = encoding ? tvb_get_letoh24(tvb, offset)
1123 : tvb_get_ntoh24(tvb, offset);
1127 value = encoding ? tvb_get_letohl(tvb, offset)
1128 : tvb_get_ntohl(tvb, offset);
1133 length_error = TRUE;
1136 length_error = FALSE;
1137 value = encoding ? tvb_get_letohl(tvb, offset)
1138 : tvb_get_ntohl(tvb, offset);
1140 report_type_length_mismatch(tree, "an unsigned integer", length, length_error);
1147 * NOTE: to support code written when proto_tree_add_item() took a
1148 * gboolean as its last argument, with FALSE meaning "big-endian"
1149 * and TRUE meaning "little-endian", we treat any non-zero value of
1150 * "encoding" as meaning "little-endian".
1153 get_int_value(proto_tree *tree, tvbuff_t *tvb, gint offset, gint length, const guint encoding)
1156 gboolean length_error;
1161 value = (gint8)tvb_get_guint8(tvb, offset);
1165 value = (gint16) (encoding ? tvb_get_letohs(tvb, offset)
1166 : tvb_get_ntohs(tvb, offset));
1170 value = encoding ? tvb_get_letoh24(tvb, offset)
1171 : tvb_get_ntoh24(tvb, offset);
1172 if (value & 0x00800000) {
1173 /* Sign bit is set; sign-extend it. */
1174 value |= 0xFF000000;
1179 value = encoding ? tvb_get_letohl(tvb, offset)
1180 : tvb_get_ntohl(tvb, offset);
1185 length_error = TRUE;
1188 length_error = FALSE;
1189 value = encoding ? tvb_get_letohl(tvb, offset)
1190 : tvb_get_ntohl(tvb, offset);
1192 report_type_length_mismatch(tree, "a signed integer", length, length_error);
1199 proto_lookup_or_create_interesting_hfids(proto_tree *tree,
1200 header_field_info *hfinfo)
1202 GPtrArray *ptrs = NULL;
1204 DISSECTOR_ASSERT(tree);
1205 DISSECTOR_ASSERT(hfinfo);
1207 if (hfinfo->ref_type == HF_REF_TYPE_DIRECT) {
1208 if (PTREE_DATA(tree)->interesting_hfids == NULL) {
1209 /* Initialize the hash because we now know that it is needed */
1210 PTREE_DATA(tree)->interesting_hfids =
1211 g_hash_table_new(g_direct_hash, NULL /* g_direct_equal */);
1214 ptrs = g_hash_table_lookup(PTREE_DATA(tree)->interesting_hfids,
1215 GINT_TO_POINTER(hfinfo->id));
1217 /* First element triggers the creation of pointer array */
1218 ptrs = g_ptr_array_new();
1219 g_hash_table_insert(PTREE_DATA(tree)->interesting_hfids,
1220 GINT_TO_POINTER(hfinfo->id), ptrs);
1227 /* Add an item to a proto_tree, using the text label registered to that item;
1228 the item is extracted from the tvbuff handed to it. */
1230 proto_tree_new_item(field_info *new_fi, proto_tree *tree,
1231 tvbuff_t *tvb, gint start, gint length,
1232 const guint encoding_arg)
1234 tree_data_t *tree_data = PTREE_DATA(tree);
1235 guint encoding = encoding_arg;
1241 nstime_t time_stamp;
1243 gboolean length_error;
1245 /* there is a possibility here that we might raise an exception
1246 * and thus would lose track of the field_info.
1247 * store it in a temp so that if we come here again we can reclaim
1248 * the field_info without leaking memory.
1250 if (tree_data->fi_tmp) {
1251 /* oops, last one we got must have been lost due
1253 * good thing we saved it, now we can reverse the
1254 * memory leak and reclaim it.
1256 FIELD_INFO_FREE(tree_data->fi_tmp);
1258 /* we might throw an exception, keep track of this one
1259 * across the "dangerous" section below.
1261 tree_data->fi_tmp = new_fi;
1263 switch (new_fi->hfinfo->type) {
1265 /* no value to set for FT_NONE */
1269 proto_tree_set_protocol_tvb(new_fi, tvb);
1273 proto_tree_set_bytes_tvb(new_fi, tvb, start, length);
1278 * Map all non-zero values to little-endian for
1279 * backwards compatibility.
1282 encoding = ENC_LITTLE_ENDIAN;
1283 n = get_uint_value(tree, tvb, start, length, encoding);
1284 proto_tree_set_bytes_tvb(new_fi, tvb, start + length, n);
1286 /* Instead of calling proto_item_set_len(), since we don't yet
1287 * have a proto_item, we set the field_info's length ourselves. */
1288 new_fi->length = n + length;
1293 * Map all non-zero values to little-endian for
1294 * backwards compatibility.
1297 encoding = ENC_LITTLE_ENDIAN;
1298 proto_tree_set_boolean(new_fi,
1299 get_uint_value(tree, tvb, start, length, encoding));
1302 /* XXX - make these just FT_UINT? */
1308 * Map all non-zero values to little-endian for
1309 * backwards compatibility.
1312 encoding = ENC_LITTLE_ENDIAN;
1313 proto_tree_set_uint(new_fi,
1314 get_uint_value(tree, tvb, start, length, encoding));
1320 * Map all non-zero values to little-endian for
1321 * backwards compatibility.
1324 encoding = ENC_LITTLE_ENDIAN;
1325 if (length < 1 || length > 8) {
1326 length_error = length < 1 ? TRUE : FALSE;
1327 report_type_length_mismatch(tree, "a 64-bit integer", length, length_error);
1329 proto_tree_set_uint64_tvb(new_fi, tvb, start, length, encoding);
1332 /* XXX - make these just FT_INT? */
1338 * Map all non-zero values to little-endian for
1339 * backwards compatibility.
1342 encoding = ENC_LITTLE_ENDIAN;
1343 proto_tree_set_int(new_fi,
1344 get_int_value(tree, tvb, start, length, encoding));
1349 * Map all non-zero values to little-endian for
1350 * backwards compatibility.
1353 encoding = ENC_LITTLE_ENDIAN;
1354 if (length != FT_IPv4_LEN) {
1355 length_error = length < FT_IPv4_LEN ? TRUE : FALSE;
1356 report_type_length_mismatch(tree, "an IPv4 address", length, length_error);
1358 value = tvb_get_ipv4(tvb, start);
1360 * NOTE: to support code written when
1361 * proto_tree_add_item() took a gboolean as its
1362 * last argument, with FALSE meaning "big-endian"
1363 * and TRUE meaning "little-endian", we treat any
1364 * non-zero value of "encoding" as meaning
1367 proto_tree_set_ipv4(new_fi, encoding ? GUINT32_SWAP_LE_BE(value) : value);
1371 if (length != FT_IPXNET_LEN) {
1372 length_error = length < FT_IPXNET_LEN ? TRUE : FALSE;
1373 report_type_length_mismatch(tree, "an IPXNET address", length, length_error);
1375 proto_tree_set_ipxnet(new_fi,
1376 get_uint_value(tree, tvb, start, FT_IPXNET_LEN, FALSE));
1380 if (length != FT_IPv6_LEN) {
1381 length_error = length < FT_IPv6_LEN ? TRUE : FALSE;
1382 report_type_length_mismatch(tree, "an IPv6 address", length, length_error);
1384 proto_tree_set_ipv6_tvb(new_fi, tvb, start, length);
1389 length_error = length < 7 ? TRUE : FALSE;
1390 expert_add_info_format(NULL, tree, PI_MALFORMED, PI_ERROR, "Trying to fetch an AX.25 address with length %d", length);
1391 THROW(ReportedBoundsError);
1393 proto_tree_set_ax25_tvb(new_fi, tvb, start);
1397 if (length != FT_ETHER_LEN) {
1398 length_error = length < FT_ETHER_LEN ? TRUE : FALSE;
1399 report_type_length_mismatch(tree, "an Ethernet", length, length_error);
1401 proto_tree_set_ether_tvb(new_fi, tvb, start);
1406 * Map all non-zero values to little-endian for
1407 * backwards compatibility.
1410 encoding = ENC_LITTLE_ENDIAN;
1411 if (length != FT_EUI64_LEN) {
1412 length_error = length < FT_EUI64_LEN ? TRUE : FALSE;
1413 report_type_length_mismatch(tree, "an EUI-64 address", length, length_error);
1415 proto_tree_set_eui64_tvb(new_fi, tvb, start, encoding);
1419 * Map all non-zero values to little-endian for
1420 * backwards compatibility.
1423 encoding = ENC_LITTLE_ENDIAN;
1424 if (length != FT_GUID_LEN) {
1425 length_error = length < FT_GUID_LEN ? TRUE : FALSE;
1426 report_type_length_mismatch(tree, "a GUID", length, length_error);
1428 proto_tree_set_guid_tvb(new_fi, tvb, start, encoding);
1432 proto_tree_set_oid_tvb(new_fi, tvb, start, length);
1437 * NOTE: to support code written when
1438 * proto_tree_add_item() took a gboolean as its
1439 * last argument, with FALSE meaning "big-endian"
1440 * and TRUE meaning "little-endian", we treat any
1441 * non-zero value of "encoding" as meaning
1444 * At some point in the future, we might
1445 * support non-IEEE-binary floating-point
1446 * formats in the encoding as well
1447 * (IEEE decimal, System/3x0, VAX).
1450 encoding = ENC_LITTLE_ENDIAN;
1452 length_error = length < 4 ? TRUE : FALSE;
1453 report_type_length_mismatch(tree, "a single-precision floating point number", length, length_error);
1456 floatval = tvb_get_letohieee_float(tvb, start);
1458 floatval = tvb_get_ntohieee_float(tvb, start);
1459 proto_tree_set_float(new_fi, floatval);
1464 * NOTE: to support code written when
1465 * proto_tree_add_item() took a gboolean as its
1466 * last argument, with FALSE meaning "big-endian"
1467 * and TRUE meaning "little-endian", we treat any
1468 * non-zero value of "encoding" as meaning
1471 * At some point in the future, we might
1472 * support non-IEEE-binary floating-point
1473 * formats in the encoding as well
1474 * (IEEE decimal, System/3x0, VAX).
1476 if (encoding == TRUE)
1477 encoding = ENC_LITTLE_ENDIAN;
1479 length_error = length < 8 ? TRUE : FALSE;
1480 report_type_length_mismatch(tree, "a double-precision floating point number", length, length_error);
1483 doubleval = tvb_get_letohieee_double(tvb, start);
1485 doubleval = tvb_get_ntohieee_double(tvb, start);
1486 proto_tree_set_double(new_fi, doubleval);
1490 proto_tree_set_string_tvb(new_fi, tvb, start, length,
1496 report_type_length_mismatch(tree, "a string", length, TRUE);
1498 /* Instead of calling proto_item_set_len(),
1499 * since we don't yet have a proto_item, we
1500 * set the field_info's length ourselves.
1502 * XXX - our caller can't use that length to
1503 * advance an offset unless they arrange that
1504 * there always be a protocol tree into which
1505 * we're putting this item.
1508 /* This can throw an exception */
1509 string = tvb_get_stringz_enc(tvb, start, &length, encoding);
1510 } else if (length == 0) {
1513 /* In this case, length signifies
1514 * the length of the string.
1516 * This could either be a null-padded
1517 * string, which doesn't necessarily
1518 * have a '\0' at the end, or a
1519 * null-terminated string, with a
1520 * trailing '\0'. (Yes, there are
1521 * cases where you have a string
1522 * that's both counted and null-
1525 * In the first case, we must
1526 * allocate a buffer of length
1527 * "length+1", to make room for
1530 * In the second case, we don't
1531 * assume that there is a trailing
1532 * '\0' there, as the packet might
1533 * be malformed. (XXX - should we
1534 * throw an exception if there's no
1535 * trailing '\0'?) Therefore, we
1536 * allocate a buffer of length
1537 * "length+1", and put in a trailing
1538 * '\0', just to be safe.
1540 * (XXX - this would change if
1541 * we made string values counted
1542 * rather than null-terminated.)
1544 string = tvb_get_ephemeral_string_enc(tvb, start, length, encoding);
1546 new_fi->length = length;
1547 proto_tree_set_string(new_fi, string);
1550 case FT_UINT_STRING:
1552 * NOTE: to support code written when
1553 * proto_tree_add_item() took a gboolean as its
1554 * last argument, with FALSE meaning "big-endian"
1555 * and TRUE meaning "little-endian", if the
1556 * encoding value is TRUE, treat that as
1557 * ASCII with a little-endian length.
1559 * This won't work for code that passes
1560 * arbitrary non-zero values; that code
1561 * will need to be fixed.
1563 if (encoding == TRUE)
1564 encoding = ENC_ASCII|ENC_LITTLE_ENDIAN;
1565 n = get_uint_value(tree, tvb, start, length, encoding & ~ENC_CHARENCODING_MASK);
1566 proto_tree_set_string_tvb(new_fi, tvb, start + length, n,
1569 /* Instead of calling proto_item_set_len(), since we
1570 * don't yet have a proto_item, we set the
1571 * field_info's length ourselves.
1573 * XXX - our caller can't use that length to
1574 * advance an offset unless they arrange that
1575 * there always be a protocol tree into which
1576 * we're putting this item.
1578 new_fi->length = n + length;
1581 case FT_ABSOLUTE_TIME:
1583 * Absolute times can be in any of a number of
1584 * formats, and they can be big-endian or
1587 * Historically FT_TIMEs were only timespecs;
1588 * the only question was whether they were stored
1589 * in big- or little-endian format.
1591 * For backwards compatibility, we interpret an
1592 * encoding of 1 as meaning "little-endian timespec",
1593 * so that passing TRUE is interpreted as that.
1595 if (encoding == TRUE)
1596 encoding = ENC_TIME_TIMESPEC|ENC_LITTLE_ENDIAN;
1598 if (length != 8 && length != 4) {
1599 length_error = length < 4 ? TRUE : FALSE;
1600 report_type_length_mismatch(tree, "an absolute time value", length, length_error);
1605 case ENC_TIME_TIMESPEC|ENC_BIG_ENDIAN:
1607 * 4-byte UNIX epoch, possibly followed by
1608 * 4-byte fractional time in nanoseconds,
1611 time_stamp.secs = tvb_get_ntohl(tvb, start);
1613 time_stamp.nsecs = tvb_get_ntohl(tvb, start+4);
1615 time_stamp.nsecs = 0;
1618 case ENC_TIME_TIMESPEC|ENC_LITTLE_ENDIAN:
1620 * 4-byte UNIX epoch, possibly followed by
1621 * 4-byte fractional time in nanoseconds,
1622 * both little-endian.
1624 time_stamp.secs = tvb_get_letohl(tvb, start);
1626 time_stamp.nsecs = tvb_get_letohl(tvb, start+4);
1628 time_stamp.nsecs = 0;
1631 case ENC_TIME_NTP|ENC_BIG_ENDIAN:
1633 * NTP time stamp, big-endian.
1636 /* XXX - where should this go? */
1637 #define NTP_BASETIME 2208988800ul
1638 time_stamp.secs = tvb_get_ntohl(tvb, start);
1639 if (time_stamp.secs)
1640 time_stamp.secs -= NTP_BASETIME;
1644 * We're using nanoseconds here (and we will
1645 * display nanoseconds), but NTP's timestamps
1646 * have a precision in microseconds or greater.
1647 * Round to 1 microsecond.
1649 time_stamp.nsecs = (int)(1000000*(tvb_get_ntohl(tvb, start+4)/4294967296.0));
1650 time_stamp.nsecs *= 1000;
1652 time_stamp.nsecs = 0;
1656 case ENC_TIME_NTP|ENC_LITTLE_ENDIAN:
1658 * NTP time stamp, big-endian.
1660 time_stamp.secs = tvb_get_letohl(tvb, start);
1661 if (time_stamp.secs)
1662 time_stamp.secs -= NTP_BASETIME;
1666 * We're using nanoseconds here (and we will
1667 * display nanoseconds), but NTP's timestamps
1668 * have a precision in microseconds or greater.
1669 * Round to 1 microsecond.
1671 time_stamp.nsecs = (int)(1000000*(tvb_get_letohl(tvb, start+4)/4294967296.0));
1672 time_stamp.nsecs *= 1000;
1674 time_stamp.nsecs = 0;
1679 DISSECTOR_ASSERT_NOT_REACHED();
1680 time_stamp.secs = 0;
1681 time_stamp.nsecs = 0;
1684 proto_tree_set_time(new_fi, &time_stamp);
1687 case FT_RELATIVE_TIME:
1689 * Relative times can be in any of a number of
1690 * formats, and they can be big-endian or
1693 * Historically FT_TIMEs were only timespecs;
1694 * the only question was whether they were stored
1695 * in big- or little-endian format.
1697 * For backwards compatibility, we interpret an
1698 * encoding of 1 as meaning "little-endian timespec",
1699 * so that passing TRUE is interpreted as that.
1701 if (encoding == TRUE)
1702 encoding = ENC_TIME_TIMESPEC|ENC_LITTLE_ENDIAN;
1705 if (length != 8 && length != 4) {
1706 length_error = length < 4 ? TRUE : FALSE;
1707 report_type_length_mismatch(tree, "a relative time value", length, length_error);
1710 case ENC_TIME_TIMESPEC|ENC_BIG_ENDIAN:
1712 * 4-byte UNIX epoch, possibly followed by
1713 * 4-byte fractional time in nanoseconds,
1716 time_stamp.secs = tvb_get_ntohl(tvb, start);
1718 time_stamp.nsecs = tvb_get_ntohl(tvb, start+4);
1720 time_stamp.nsecs = 0;
1723 case ENC_TIME_TIMESPEC|ENC_LITTLE_ENDIAN:
1725 * 4-byte UNIX epoch, possibly followed by
1726 * 4-byte fractional time in nanoseconds,
1727 * both little-endian.
1729 time_stamp.secs = tvb_get_letohl(tvb, start);
1731 time_stamp.nsecs = tvb_get_letohl(tvb, start+4);
1733 time_stamp.nsecs = 0;
1736 proto_tree_set_time(new_fi, &time_stamp);
1740 g_error("new_fi->hfinfo->type %d (%s) not handled\n",
1741 new_fi->hfinfo->type,
1742 ftype_name(new_fi->hfinfo->type));
1743 DISSECTOR_ASSERT_NOT_REACHED();
1746 FI_SET_FLAG(new_fi, (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN);
1748 /* Don't add new node to proto_tree until now so that any exceptions
1749 * raised by a tvbuff access method doesn't leave junk in the proto_tree. */
1750 /* XXX. wouldn't be better to add this item to tree, with some special flag (FI_EXCEPTION?)
1751 * to know which item caused exception? */
1752 pi = proto_tree_add_node(tree, new_fi);
1754 /* we did not raise an exception so we dont have to remember this
1755 * field_info struct any more.
1757 tree_data->fi_tmp = NULL;
1759 /* If the proto_tree wants to keep a record of this finfo
1760 * for quick lookup, then record it. */
1761 ptrs = proto_lookup_or_create_interesting_hfids(tree, new_fi->hfinfo);
1763 g_ptr_array_add(ptrs, new_fi);
1768 /* Gets data from tvbuff, adds it to proto_tree, increments offset,
1769 and returns proto_item* */
1771 ptvcursor_add(ptvcursor_t *ptvc, int hfindex, gint length,
1772 const guint encoding)
1775 header_field_info *hfinfo;
1780 /* We can't fake it just yet. We have to advance the cursor
1781 TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfindex, hfinfo); */
1783 offset = ptvc->offset;
1784 hfinfo = get_hfi_and_length(hfindex, ptvc->tvb, offset, &length,
1786 ptvc->offset += length;
1787 if (hfinfo->type == FT_UINT_BYTES || hfinfo->type == FT_UINT_STRING) {
1789 * The length of the rest of the item is in the first N
1790 * bytes of the item.
1792 n = get_uint_value(ptvc->tree, ptvc->tvb, offset, length, encoding);
1796 /* Coast clear. Try and fake it */
1797 TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfindex, hfinfo);
1799 new_fi = new_field_info(ptvc->tree, hfinfo, ptvc->tvb, offset, item_length);
1801 return proto_tree_new_item(new_fi, ptvc->tree, ptvc->tvb,
1802 offset, length, encoding);
1805 /* Add an item to a proto_tree, using the text label registered to that item;
1806 the item is extracted from the tvbuff handed to it. */
1808 proto_tree_add_item(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
1809 const gint start, gint length, const guint encoding)
1812 header_field_info *hfinfo;
1814 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1816 new_fi = alloc_field_info(tree, hfindex, tvb, start, &length);
1821 return proto_tree_new_item(new_fi, tree, tvb, start,
1825 /* Add a FT_NONE to a proto_tree */
1827 proto_tree_add_none_format(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
1828 const gint start, gint length, const char *format,
1833 header_field_info *hfinfo;
1835 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1837 DISSECTOR_ASSERT(hfinfo->type == FT_NONE);
1839 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, NULL);
1841 TRY_TO_FAKE_THIS_REPR(tree, pi);
1843 va_start(ap, format);
1844 proto_tree_set_representation(pi, format, ap);
1847 /* no value to set for FT_NONE */
1851 /* Gets data from tvbuff, adds it to proto_tree, *DOES NOT* increment
1852 * offset, and returns proto_item* */
1854 ptvcursor_add_no_advance(ptvcursor_t* ptvc, int hf, gint length,
1855 const guint encoding)
1859 item = proto_tree_add_item(ptvc->tree, hf, ptvc->tvb, ptvc->offset,
1865 /* Advance the ptvcursor's offset within its tvbuff without
1866 * adding anything to the proto_tree. */
1868 ptvcursor_advance(ptvcursor_t* ptvc, gint length)
1870 ptvc->offset += length;
1875 proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb)
1877 fvalue_set(&fi->value, tvb, TRUE);
1880 /* Add a FT_PROTOCOL to a proto_tree */
1882 proto_tree_add_protocol_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1883 gint start, gint length, const char *format, ...)
1888 header_field_info *hfinfo;
1890 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1892 DISSECTOR_ASSERT(hfinfo->type == FT_PROTOCOL);
1894 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1896 proto_tree_set_protocol_tvb(new_fi, (start == 0 ? tvb : tvb_new_subset(tvb, start, length, length)));
1898 TRY_TO_FAKE_THIS_REPR(tree, pi);
1900 va_start(ap, format);
1901 proto_tree_set_representation(pi, format, ap);
1908 /* Add a FT_BYTES to a proto_tree */
1910 proto_tree_add_bytes(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1911 gint length, const guint8 *start_ptr)
1915 header_field_info *hfinfo;
1917 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1919 DISSECTOR_ASSERT(hfinfo->type == FT_BYTES);
1921 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1922 proto_tree_set_bytes(new_fi, start_ptr, length);
1928 proto_tree_add_bytes_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1929 gint start, gint length,
1930 const guint8 *start_ptr,
1931 const char *format, ...)
1935 header_field_info *hfinfo;
1937 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1940 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length,
1943 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length,
1944 tvb_get_ptr(tvb, start, length));
1946 TRY_TO_FAKE_THIS_REPR(tree, pi);
1948 va_start(ap, format);
1949 proto_tree_set_representation_value(pi, format, ap);
1956 proto_tree_add_bytes_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1957 gint start, gint length, const guint8 *start_ptr,
1958 const char *format, ...)
1962 header_field_info *hfinfo;
1964 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1967 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length,
1970 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length,
1971 tvb_get_ptr(tvb, start, length));
1973 TRY_TO_FAKE_THIS_REPR(tree, pi);
1975 va_start(ap, format);
1976 proto_tree_set_representation(pi, format, ap);
1983 proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length)
1987 bytes = g_byte_array_new();
1989 g_byte_array_append(bytes, start_ptr, length);
1991 fvalue_set(&fi->value, bytes, TRUE);
1996 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length)
1998 proto_tree_set_bytes(fi, tvb_get_ptr(tvb, offset, length), length);
2001 /* Add a FT_*TIME to a proto_tree */
2003 proto_tree_add_time(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2004 gint length, nstime_t *value_ptr)
2008 header_field_info *hfinfo;
2010 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2012 DISSECTOR_ASSERT(hfinfo->type == FT_ABSOLUTE_TIME ||
2013 hfinfo->type == FT_RELATIVE_TIME);
2015 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2016 proto_tree_set_time(new_fi, value_ptr);
2022 proto_tree_add_time_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2023 gint start, gint length, nstime_t *value_ptr,
2024 const char *format, ...)
2028 header_field_info *hfinfo;
2030 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2032 pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
2034 TRY_TO_FAKE_THIS_REPR(tree, pi);
2036 va_start(ap, format);
2037 proto_tree_set_representation_value(pi, format, ap);
2044 proto_tree_add_time_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2045 gint start, gint length, nstime_t *value_ptr,
2046 const char *format, ...)
2050 header_field_info *hfinfo;
2052 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2054 pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
2056 TRY_TO_FAKE_THIS_REPR(tree, pi);
2058 va_start(ap, format);
2059 proto_tree_set_representation(pi, format, ap);
2065 /* Set the FT_*TIME value */
2067 proto_tree_set_time(field_info *fi, nstime_t *value_ptr)
2069 DISSECTOR_ASSERT(value_ptr != NULL);
2071 fvalue_set(&fi->value, value_ptr, FALSE);
2074 /* Add a FT_IPXNET to a proto_tree */
2076 proto_tree_add_ipxnet(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2077 gint length, guint32 value)
2081 header_field_info *hfinfo;
2083 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2085 DISSECTOR_ASSERT(hfinfo->type == FT_IPXNET);
2087 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2088 proto_tree_set_ipxnet(new_fi, value);
2094 proto_tree_add_ipxnet_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2095 gint start, gint length, guint32 value,
2096 const char *format, ...)
2100 header_field_info *hfinfo;
2102 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2104 pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
2106 TRY_TO_FAKE_THIS_REPR(tree, pi);
2108 va_start(ap, format);
2109 proto_tree_set_representation_value(pi, format, ap);
2116 proto_tree_add_ipxnet_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2117 gint start, gint length, guint32 value,
2118 const char *format, ...)
2122 header_field_info *hfinfo;
2124 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2126 pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
2128 TRY_TO_FAKE_THIS_REPR(tree, pi);
2130 va_start(ap, format);
2131 proto_tree_set_representation(pi, format, ap);
2137 /* Set the FT_IPXNET value */
2139 proto_tree_set_ipxnet(field_info *fi, guint32 value)
2141 fvalue_set_uinteger(&fi->value, value);
2144 /* Add a FT_IPv4 to a proto_tree */
2146 proto_tree_add_ipv4(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2147 gint length, guint32 value)
2151 header_field_info *hfinfo;
2153 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2155 DISSECTOR_ASSERT(hfinfo->type == FT_IPv4);
2157 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2158 proto_tree_set_ipv4(new_fi, value);
2164 proto_tree_add_ipv4_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2165 gint start, gint length, guint32 value,
2166 const char *format, ...)
2170 header_field_info *hfinfo;
2172 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2174 pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
2176 TRY_TO_FAKE_THIS_REPR(tree, pi);
2178 va_start(ap, format);
2179 proto_tree_set_representation_value(pi, format, ap);
2186 proto_tree_add_ipv4_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2187 gint start, gint length, guint32 value,
2188 const char *format, ...)
2192 header_field_info *hfinfo;
2194 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2196 pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
2198 TRY_TO_FAKE_THIS_REPR(tree, pi);
2200 va_start(ap, format);
2201 proto_tree_set_representation(pi, format, ap);
2207 /* Set the FT_IPv4 value */
2209 proto_tree_set_ipv4(field_info *fi, guint32 value)
2211 fvalue_set_uinteger(&fi->value, value);
2214 /* Add a FT_IPv6 to a proto_tree */
2216 proto_tree_add_ipv6(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2217 gint length, const guint8* value_ptr)
2221 header_field_info *hfinfo;
2223 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2225 DISSECTOR_ASSERT(hfinfo->type == FT_IPv6);
2227 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2228 proto_tree_set_ipv6(new_fi, value_ptr);
2234 proto_tree_add_ipv6_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2235 gint start, gint length,
2236 const guint8* value_ptr,
2237 const char *format, ...)
2241 header_field_info *hfinfo;
2243 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2245 pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
2247 TRY_TO_FAKE_THIS_REPR(tree, pi);
2249 va_start(ap, format);
2250 proto_tree_set_representation_value(pi, format, ap);
2257 proto_tree_add_ipv6_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2258 gint start, gint length, const guint8* value_ptr,
2259 const char *format, ...)
2263 header_field_info *hfinfo;
2265 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2267 pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
2269 TRY_TO_FAKE_THIS_REPR(tree, pi);
2271 va_start(ap, format);
2272 proto_tree_set_representation(pi, format, ap);
2278 /* Set the FT_IPv6 value */
2280 proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr)
2282 DISSECTOR_ASSERT(value_ptr != NULL);
2283 fvalue_set(&fi->value, (gpointer) value_ptr, FALSE);
2287 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
2289 proto_tree_set_ipv6(fi, tvb_get_ptr(tvb, start, length));
2292 /* Add a FT_GUID to a proto_tree */
2294 proto_tree_add_guid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2295 gint length, const e_guid_t *value_ptr)
2299 header_field_info *hfinfo;
2301 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2303 DISSECTOR_ASSERT(hfinfo->type == FT_GUID);
2305 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2306 proto_tree_set_guid(new_fi, value_ptr);
2312 proto_tree_add_guid_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2313 gint start, gint length,
2314 const e_guid_t *value_ptr,
2315 const char *format, ...)
2319 header_field_info *hfinfo;
2321 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2323 pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
2325 TRY_TO_FAKE_THIS_REPR(tree, pi);
2327 va_start(ap, format);
2328 proto_tree_set_representation_value(pi, format, ap);
2335 proto_tree_add_guid_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2336 gint start, gint length, const e_guid_t *value_ptr,
2337 const char *format, ...)
2341 header_field_info *hfinfo;
2343 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2345 pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
2347 TRY_TO_FAKE_THIS_REPR(tree, pi);
2349 va_start(ap, format);
2350 proto_tree_set_representation(pi, format, ap);
2356 /* Set the FT_GUID value */
2358 proto_tree_set_guid(field_info *fi, const e_guid_t *value_ptr)
2360 DISSECTOR_ASSERT(value_ptr != NULL);
2361 fvalue_set(&fi->value, (gpointer) value_ptr, FALSE);
2365 proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, gint start,
2366 const guint encoding)
2370 tvb_get_guid(tvb, start, &guid, encoding);
2371 proto_tree_set_guid(fi, &guid);
2374 /* Add a FT_OID to a proto_tree */
2376 proto_tree_add_oid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2377 gint length, const guint8* value_ptr)
2381 header_field_info *hfinfo;
2383 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2385 DISSECTOR_ASSERT(hfinfo->type == FT_OID);
2387 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2388 proto_tree_set_oid(new_fi, value_ptr, length);
2394 proto_tree_add_oid_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2395 gint start, gint length,
2396 const guint8* value_ptr,
2397 const char *format, ...)
2401 header_field_info *hfinfo;
2403 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2405 pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
2407 TRY_TO_FAKE_THIS_REPR(tree, pi);
2409 va_start(ap, format);
2410 proto_tree_set_representation_value(pi, format, ap);
2417 proto_tree_add_oid_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2418 gint start, gint length, const guint8* value_ptr,
2419 const char *format, ...)
2423 header_field_info *hfinfo;
2425 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2427 pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
2429 TRY_TO_FAKE_THIS_REPR(tree, pi);
2431 va_start(ap, format);
2432 proto_tree_set_representation(pi, format, ap);
2438 /* Set the FT_OID value */
2440 proto_tree_set_oid(field_info *fi, const guint8* value_ptr, gint length)
2444 DISSECTOR_ASSERT(value_ptr != NULL);
2446 bytes = g_byte_array_new();
2448 g_byte_array_append(bytes, value_ptr, length);
2450 fvalue_set(&fi->value, bytes, TRUE);
2454 proto_tree_set_oid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
2456 proto_tree_set_oid(fi, tvb_get_ptr(tvb, start, length), length);
2460 proto_tree_set_uint64(field_info *fi, guint64 value)
2462 fvalue_set_integer64(&fi->value, value);
2466 * NOTE: to support code written when proto_tree_add_item() took a
2467 * gboolean as its last argument, with FALSE meaning "big-endian"
2468 * and TRUE meaning "little-endian", we treat any non-zero value of
2469 * "encoding" as meaning "little-endian".
2472 proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start,
2473 guint length, const guint encoding)
2476 guint8* b = ep_tvb_memdup(tvb, start, length);
2481 default: DISSECTOR_ASSERT_NOT_REACHED();
2482 case 8: value <<= 8; value += *--b;
2483 case 7: value <<= 8; value += *--b;
2484 case 6: value <<= 8; value += *--b;
2485 case 5: value <<= 8; value += *--b;
2486 case 4: value <<= 8; value += *--b;
2487 case 3: value <<= 8; value += *--b;
2488 case 2: value <<= 8; value += *--b;
2489 case 1: value <<= 8; value += *--b;
2494 default: DISSECTOR_ASSERT_NOT_REACHED();
2495 case 8: value <<= 8; value += *b++;
2496 case 7: value <<= 8; value += *b++;
2497 case 6: value <<= 8; value += *b++;
2498 case 5: value <<= 8; value += *b++;
2499 case 4: value <<= 8; value += *b++;
2500 case 3: value <<= 8; value += *b++;
2501 case 2: value <<= 8; value += *b++;
2502 case 1: value <<= 8; value += *b++;
2507 proto_tree_set_uint64(fi, value);
2510 /* Add a FT_STRING or FT_STRINGZ to a proto_tree. Creates own copy of string,
2511 * and frees it when the proto_tree is destroyed. */
2513 proto_tree_add_string(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2514 gint length, const char* value)
2518 header_field_info *hfinfo;
2520 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2522 DISSECTOR_ASSERT(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ);
2524 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2525 DISSECTOR_ASSERT(length >= 0);
2526 proto_tree_set_string(new_fi, value);
2532 proto_tree_add_unicode_string(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2533 gint length, const char* value)
2535 DISSECTOR_ASSERT(g_utf8_validate(value, -1, NULL));
2536 return proto_tree_add_string_format_value(tree, hfindex, tvb, start, length, value, "%s", value);
2540 proto_tree_add_string_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2541 gint start, gint length, const char* value,
2547 header_field_info *hfinfo;
2549 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2551 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
2553 TRY_TO_FAKE_THIS_REPR(tree, pi);
2555 va_start(ap, format);
2556 proto_tree_set_representation_value(pi, format, ap);
2563 proto_tree_add_string_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2564 gint start, gint length, const char* value,
2565 const char *format, ...)
2569 header_field_info *hfinfo;
2571 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2573 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
2575 TRY_TO_FAKE_THIS_REPR(tree, pi);
2577 va_start(ap, format);
2578 proto_tree_set_representation(pi, format, ap);
2584 /* Appends string data to a FT_STRING or FT_STRINGZ, allowing progressive
2585 * field info update instead of only updating the representation as does
2586 * proto_item_append_text()
2589 proto_item_append_string(proto_item *pi, const char *str)
2591 field_info *fi = NULL;
2598 fi = PITEM_FINFO(pi);
2603 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
2605 * If we don't already have a representation,
2606 * generate the default representation.
2608 if (fi->rep == NULL) {
2609 ITEM_LABEL_NEW(fi->rep);
2610 proto_item_fill_label(fi, fi->rep->representation);
2613 curlen = strlen(fi->rep->representation);
2614 if (ITEM_LABEL_LENGTH > curlen) {
2615 g_strlcpy(fi->rep->representation + curlen,
2617 ITEM_LABEL_LENGTH - (gulong) curlen);
2622 /* Set the FT_STRING value */
2624 proto_tree_set_string(field_info *fi, const char* value)
2627 fvalue_set(&fi->value, (gpointer) value, FALSE);
2629 fvalue_set(&fi->value, (gpointer) "[ Null ]", FALSE);
2634 proto_tree_set_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length, gint encoding)
2639 length = tvb_ensure_length_remaining(tvb, start);
2642 string = tvb_get_ephemeral_string_enc(tvb, start, length, encoding);
2643 proto_tree_set_string(fi, string);
2647 /* Add a FT_AX25 to a proto_tree */
2649 proto_tree_add_ax25(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2650 const guint8* value)
2654 header_field_info *hfinfo;
2659 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2661 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2662 DISSECTOR_ASSERT(hfinfo->type == FT_AX25);
2664 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2665 proto_tree_set_ax25(new_fi, value);
2670 /* Set the FT_AX25 value */
2672 proto_tree_set_ax25(field_info *fi, const guint8* value)
2674 fvalue_set(&fi->value, (gpointer) value, FALSE);
2678 proto_tree_set_ax25_tvb(field_info *fi, tvbuff_t *tvb, gint start)
2680 proto_tree_set_ax25(fi, tvb_get_ptr(tvb, start, 7));
2684 /* Add a FT_ETHER to a proto_tree */
2686 proto_tree_add_ether(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2687 gint length, const guint8* value)
2691 header_field_info *hfinfo;
2693 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2695 DISSECTOR_ASSERT(hfinfo->type == FT_ETHER);
2697 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2698 proto_tree_set_ether(new_fi, value);
2704 proto_tree_add_ether_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2705 gint start, gint length, const guint8* value,
2706 const char *format, ...)
2710 header_field_info *hfinfo;
2712 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2714 pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
2716 TRY_TO_FAKE_THIS_REPR(tree, pi);
2718 va_start(ap, format);
2719 proto_tree_set_representation_value(pi, format, ap);
2726 proto_tree_add_ether_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2727 gint start, gint length, const guint8* value,
2728 const char *format, ...)
2732 header_field_info *hfinfo;
2734 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2736 pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
2738 TRY_TO_FAKE_THIS_REPR(tree, pi);
2740 va_start(ap, format);
2741 proto_tree_set_representation(pi, format, ap);
2747 /* Set the FT_ETHER value */
2749 proto_tree_set_ether(field_info *fi, const guint8* value)
2751 fvalue_set(&fi->value, (gpointer) value, FALSE);
2755 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start)
2757 proto_tree_set_ether(fi, tvb_get_ptr(tvb, start, FT_ETHER_LEN));
2760 /* Add a FT_BOOLEAN to a proto_tree */
2762 proto_tree_add_boolean(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2763 gint length, guint32 value)
2767 header_field_info *hfinfo;
2769 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2771 DISSECTOR_ASSERT(hfinfo->type == FT_BOOLEAN);
2773 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2774 proto_tree_set_boolean(new_fi, value);
2780 proto_tree_add_boolean_format_value(proto_tree *tree, int hfindex,
2781 tvbuff_t *tvb, gint start, gint length,
2782 guint32 value, const char *format, ...)
2786 header_field_info *hfinfo;
2788 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2790 pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
2792 TRY_TO_FAKE_THIS_REPR(tree, pi);
2794 va_start(ap, format);
2795 proto_tree_set_representation_value(pi, format, ap);
2802 proto_tree_add_boolean_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2803 gint start, gint length, guint32 value,
2804 const char *format, ...)
2808 header_field_info *hfinfo;
2810 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2812 pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
2814 TRY_TO_FAKE_THIS_REPR(tree, pi);
2816 va_start(ap, format);
2817 proto_tree_set_representation(pi, format, ap);
2823 /* Set the FT_BOOLEAN value */
2825 proto_tree_set_boolean(field_info *fi, guint32 value)
2827 proto_tree_set_uint(fi, value);
2830 /* Add a FT_FLOAT to a proto_tree */
2832 proto_tree_add_float(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2833 gint length, float value)
2837 header_field_info *hfinfo;
2839 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2841 DISSECTOR_ASSERT(hfinfo->type == FT_FLOAT);
2843 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2844 proto_tree_set_float(new_fi, value);
2850 proto_tree_add_float_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2851 gint start, gint length, float value,
2852 const char *format, ...)
2856 header_field_info *hfinfo;
2858 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2860 pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
2862 TRY_TO_FAKE_THIS_REPR(tree, pi);
2864 va_start(ap, format);
2865 proto_tree_set_representation_value(pi, format, ap);
2872 proto_tree_add_float_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2873 gint start, gint length, float value,
2874 const char *format, ...)
2878 header_field_info *hfinfo;
2880 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2882 pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
2884 TRY_TO_FAKE_THIS_REPR(tree, pi);
2886 va_start(ap, format);
2887 proto_tree_set_representation(pi, format, ap);
2893 /* Set the FT_FLOAT value */
2895 proto_tree_set_float(field_info *fi, float value)
2897 fvalue_set_floating(&fi->value, value);
2900 /* Add a FT_DOUBLE to a proto_tree */
2902 proto_tree_add_double(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2903 gint length, double value)
2907 header_field_info *hfinfo;
2909 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2911 DISSECTOR_ASSERT(hfinfo->type == FT_DOUBLE);
2913 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2914 proto_tree_set_double(new_fi, value);
2920 proto_tree_add_double_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2921 gint start, gint length, double value,
2922 const char *format, ...)
2926 header_field_info *hfinfo;
2928 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2930 pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
2932 TRY_TO_FAKE_THIS_REPR(tree, pi);
2934 va_start(ap, format);
2935 proto_tree_set_representation_value(pi, format, ap);
2942 proto_tree_add_double_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2943 gint start, gint length, double value,
2944 const char *format, ...)
2948 header_field_info *hfinfo;
2950 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2952 pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
2954 TRY_TO_FAKE_THIS_REPR(tree, pi);
2956 va_start(ap, format);
2957 proto_tree_set_representation(pi, format, ap);
2963 /* Set the FT_DOUBLE value */
2965 proto_tree_set_double(field_info *fi, double value)
2967 fvalue_set_floating(&fi->value, value);
2970 /* Add FT_UINT{8,16,24,32} to a proto_tree */
2972 proto_tree_add_uint(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2973 gint length, guint32 value)
2975 proto_item *pi = NULL;
2977 header_field_info *hfinfo;
2979 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2981 switch (hfinfo->type) {
2987 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length,
2989 proto_tree_set_uint(new_fi, value);
2993 DISSECTOR_ASSERT_NOT_REACHED();
3000 proto_tree_add_uint_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3001 gint start, gint length, guint32 value,
3002 const char *format, ...)
3006 header_field_info *hfinfo;
3008 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3010 pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
3012 TRY_TO_FAKE_THIS_REPR(tree, pi);
3014 va_start(ap, format);
3015 proto_tree_set_representation_value(pi, format, ap);
3022 proto_tree_add_uint_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3023 gint start, gint length, guint32 value,
3024 const char *format, ...)
3028 header_field_info *hfinfo;
3030 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3032 pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
3034 TRY_TO_FAKE_THIS_REPR(tree, pi);
3036 va_start(ap, format);
3037 proto_tree_set_representation(pi, format, ap);
3043 /* Set the FT_UINT{8,16,24,32} value */
3045 proto_tree_set_uint(field_info *fi, guint32 value)
3047 header_field_info *hfinfo;
3050 hfinfo = fi->hfinfo;
3053 if (hfinfo->bitmask) {
3054 /* Mask out irrelevant portions */
3055 integer &= hfinfo->bitmask;
3058 if (hfinfo->bitshift > 0) {
3059 integer >>= hfinfo->bitshift;
3063 fvalue_set_uinteger(&fi->value, integer);
3066 /* Add FT_UINT64 to a proto_tree */
3068 proto_tree_add_uint64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3069 gint length, guint64 value)
3071 proto_item *pi = NULL;
3073 header_field_info *hfinfo;
3075 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3077 DISSECTOR_ASSERT(hfinfo->type == FT_UINT64);
3079 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
3080 proto_tree_set_uint64(new_fi, value);
3086 proto_tree_add_uint64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3087 gint start, gint length, guint64 value,
3088 const char *format, ...)
3092 header_field_info *hfinfo;
3094 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3096 pi = proto_tree_add_uint64(tree, hfindex, tvb, start, length, value);
3098 TRY_TO_FAKE_THIS_REPR(tree, pi);
3100 va_start(ap, format);
3101 proto_tree_set_representation_value(pi, format, ap);
3108 proto_tree_add_uint64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3109 gint start, gint length, guint64 value,
3110 const char *format, ...)
3114 header_field_info *hfinfo;
3116 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3118 pi = proto_tree_add_uint64(tree, hfindex, tvb, start, length, value);
3120 TRY_TO_FAKE_THIS_REPR(tree, pi);
3122 va_start(ap, format);
3123 proto_tree_set_representation(pi, format, ap);
3129 /* Add FT_INT{8,16,24,32} to a proto_tree */
3131 proto_tree_add_int(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3132 gint length, gint32 value)
3134 proto_item *pi = NULL;
3136 header_field_info *hfinfo;
3138 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3140 switch (hfinfo->type) {
3145 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length,
3147 proto_tree_set_int(new_fi, value);
3151 DISSECTOR_ASSERT_NOT_REACHED();
3158 proto_tree_add_int_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3159 gint start, gint length, gint32 value,
3160 const char *format, ...)
3162 proto_item *pi = NULL;
3164 header_field_info *hfinfo;
3166 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3168 pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
3170 TRY_TO_FAKE_THIS_REPR(tree, pi);
3172 va_start(ap, format);
3173 proto_tree_set_representation_value(pi, format, ap);
3180 proto_tree_add_int_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3181 gint start, gint length, gint32 value,
3182 const char *format, ...)
3184 proto_item *pi = NULL;
3186 header_field_info *hfinfo;
3188 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3190 pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
3192 TRY_TO_FAKE_THIS_REPR(tree, pi);
3194 va_start(ap, format);
3195 proto_tree_set_representation(pi, format, ap);
3201 /* Set the FT_INT{8,16,24,32} value */
3203 proto_tree_set_int(field_info *fi, gint32 value)
3205 header_field_info *hfinfo;
3208 hfinfo = fi->hfinfo;
3209 integer = (guint32) value;
3211 if (hfinfo->bitmask) {
3212 /* Mask out irrelevant portions */
3213 integer &= hfinfo->bitmask;
3216 if (hfinfo->bitshift > 0) {
3217 integer >>= hfinfo->bitshift;
3221 fvalue_set_sinteger(&fi->value, integer);
3224 /* Add FT_INT64 to a proto_tree */
3226 proto_tree_add_int64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3227 gint length, gint64 value)
3229 proto_item *pi = NULL;
3231 header_field_info *hfinfo;
3233 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3235 DISSECTOR_ASSERT(hfinfo->type == FT_INT64);
3237 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
3238 proto_tree_set_uint64(new_fi, (guint64)value);
3244 proto_tree_add_int64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3245 gint start, gint length, gint64 value,
3246 const char *format, ...)
3250 header_field_info *hfinfo;
3252 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3254 pi = proto_tree_add_int64(tree, hfindex, tvb, start, length, value);
3256 TRY_TO_FAKE_THIS_REPR(tree, pi);
3258 va_start(ap, format);
3259 proto_tree_set_representation_value(pi, format, ap);
3266 proto_tree_add_int64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3267 gint start, gint length, gint64 value,
3268 const char *format, ...)
3272 header_field_info *hfinfo;
3274 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3276 pi = proto_tree_add_int64(tree, hfindex, tvb, start, length, value);
3278 TRY_TO_FAKE_THIS_REPR(tree, pi);
3280 va_start(ap, format);
3281 proto_tree_set_representation(pi, format, ap);
3286 /* Add a FT_EUI64 to a proto_tree */
3288 proto_tree_add_eui64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3289 gint length, const guint64 value)
3293 header_field_info *hfinfo;
3295 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3297 DISSECTOR_ASSERT(hfinfo->type == FT_EUI64);
3299 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
3300 proto_tree_set_eui64(new_fi, value);
3306 proto_tree_add_eui64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3307 gint start, gint length, const guint64 value,
3308 const char *format, ...)
3312 header_field_info *hfinfo;
3314 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3316 pi = proto_tree_add_eui64(tree, hfindex, tvb, start, length, value);
3318 TRY_TO_FAKE_THIS_REPR(tree, pi);
3320 va_start(ap, format);
3321 proto_tree_set_representation_value(pi, format, ap);
3328 proto_tree_add_eui64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3329 gint start, gint length, const guint64 value,
3330 const char *format, ...)
3334 header_field_info *hfinfo;
3336 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3338 pi = proto_tree_add_eui64(tree, hfindex, tvb, start, length, value);
3340 TRY_TO_FAKE_THIS_REPR(tree, pi);
3342 va_start(ap, format);
3343 proto_tree_set_representation(pi, format, ap);
3349 /* Set the FT_EUI64 value */
3351 proto_tree_set_eui64(field_info *fi, const guint64 value)
3353 fvalue_set_integer64(&fi->value, value);
3356 proto_tree_set_eui64_tvb(field_info *fi, tvbuff_t *tvb, gint start, const guint encoding)
3360 proto_tree_set_eui64(fi, tvb_get_letoh64(tvb, start));
3362 proto_tree_set_eui64(fi, tvb_get_ntoh64(tvb, start));
3366 /* Add a field_info struct to the proto_tree, encapsulating it in a proto_node */
3368 proto_tree_add_node(proto_tree *tree, field_info *fi)
3370 proto_node *pnode, *tnode, *sibling;
3374 * Make sure "tree" is ready to have subtrees under it, by
3375 * checking whether it's been given an ett_ value.
3377 * "PNODE_FINFO(tnode)" may be null; that's the case for the root
3378 * node of the protocol tree. That node is not displayed,
3379 * so it doesn't need an ett_ value to remember whether it
3383 tfi = PNODE_FINFO(tnode);
3384 if (tfi != NULL && (tfi->tree_type < 0 || tfi->tree_type >= num_tree_types)) {
3385 REPORT_DISSECTOR_BUG(ep_strdup_printf("\"%s\" - \"%s\" tfi->tree_type: %u invalid (%s:%u)",
3386 fi->hfinfo->name, fi->hfinfo->abbrev, tfi->tree_type, __FILE__, __LINE__));
3387 /* XXX - is it safe to continue here? */
3390 DISSECTOR_ASSERT(tfi == NULL ||
3391 (tfi->tree_type >= 0 && tfi->tree_type < num_tree_types));
3393 PROTO_NODE_NEW(pnode);
3394 pnode->parent = tnode;
3395 PNODE_FINFO(pnode) = fi;
3396 pnode->tree_data = PTREE_DATA(tree);
3398 if (tnode->last_child != NULL) {
3399 sibling = tnode->last_child;
3400 DISSECTOR_ASSERT(sibling->next == NULL);
3401 sibling->next = pnode;
3403 tnode->first_child = pnode;
3404 tnode->last_child = pnode;
3406 return (proto_item *)pnode;
3410 /* Generic way to allocate field_info and add to proto_tree.
3411 * Sets *pfi to address of newly-allocated field_info struct, if pfi is
3414 proto_tree_add_pi(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3415 gint *length, field_info **pfi)
3424 fi = alloc_field_info(tree, hfindex, tvb, start, length);
3425 pi = proto_tree_add_node(tree, fi);
3427 /* If the proto_tree wants to keep a record of this finfo
3428 * for quick lookup, then record it. */
3429 ptrs = proto_lookup_or_create_interesting_hfids(tree, fi->hfinfo);
3431 g_ptr_array_add(ptrs, fi);
3433 /* Does the caller want to know the fi pointer? */
3442 static header_field_info *
3443 get_hfi_and_length(int hfindex, tvbuff_t *tvb, const gint start, gint *length,
3446 header_field_info *hfinfo;
3447 gint length_remaining;
3450 * We only allow a null tvbuff if the item has a zero length,
3451 * i.e. if there's no data backing it.
3453 DISSECTOR_ASSERT(tvb != NULL || *length == 0);
3455 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
3458 * XXX - in some protocols, there are 32-bit unsigned length
3459 * fields, so lengths in protocol tree and tvbuff routines
3460 * should really be unsigned. We should have, for those
3461 * field types for which "to the end of the tvbuff" makes sense,
3462 * additional routines that take no length argument and
3463 * add fields that run to the end of the tvbuff.
3465 if (*length == -1) {
3467 * For FT_NONE, FT_PROTOCOL, FT_BYTES, and FT_STRING fields,
3468 * a length of -1 means "set the length to what remains in
3471 * The assumption is either that
3473 * 1) the length of the item can only be determined
3474 * by dissection (typically true of items with
3475 * subitems, which are probably FT_NONE or
3480 * 2) if the tvbuff is "short" (either due to a short
3481 * snapshot length or due to lack of reassembly of
3482 * fragments/segments/whatever), we want to display
3483 * what's available in the field (probably FT_BYTES
3484 * or FT_STRING) and then throw an exception later
3488 * 3) the field is defined to be "what's left in the
3491 * so we set the length to what remains in the tvbuff so
3492 * that, if we throw an exception while dissecting, it
3493 * has what is probably the right value.
3495 * For FT_STRINGZ, it means "the string is null-terminated,
3496 * not null-padded; set the length to the actual length
3497 * of the string", and if the tvbuff if short, we just
3498 * throw an exception.
3500 * It's not valid for any other type of field.
3502 switch (hfinfo->type) {
3506 * We allow this to be zero-length - for
3507 * example, an ONC RPC NULL procedure has
3508 * neither arguments nor reply, so the
3509 * payload for that protocol is empty.
3511 * However, if the length is negative, the
3512 * start offset is *past* the byte past the
3513 * end of the tvbuff, so we throw an
3516 *length = tvb_length_remaining(tvb, start);
3519 * Use "tvb_ensure_bytes_exist()"
3520 * to force the appropriate exception
3523 tvb_ensure_bytes_exist(tvb, start, 0);
3525 DISSECTOR_ASSERT(*length >= 0);
3531 *length = tvb_ensure_length_remaining(tvb, start);
3532 DISSECTOR_ASSERT(*length >= 0);
3537 * Leave the length as -1, so our caller knows
3543 DISSECTOR_ASSERT_NOT_REACHED();
3545 *item_length = *length;
3547 *item_length = *length;
3548 if (hfinfo->type == FT_PROTOCOL || hfinfo->type == FT_NONE) {
3550 * These types are for interior nodes of the
3551 * tree, and don't have data associated with
3552 * them; if the length is negative (XXX - see
3553 * above) or goes past the end of the tvbuff,
3554 * cut it short at the end of the tvbuff.
3555 * That way, if this field is selected in
3556 * Wireshark, we don't highlight stuff past
3557 * the end of the data.
3559 /* XXX - what to do, if we don't have a tvb? */
3561 length_remaining = tvb_length_remaining(tvb, start);
3562 if (*item_length < 0 ||
3563 (*item_length > 0 &&
3564 (length_remaining < *item_length)))
3565 *item_length = length_remaining;
3568 if (*item_length < 0) {
3569 THROW(ReportedBoundsError);
3577 new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
3578 const gint start, const gint item_length)
3584 fi->hfinfo = hfinfo;
3586 fi->start += (tvb)?tvb_raw_offset(tvb):0;
3587 fi->length = item_length;
3590 if (!PTREE_DATA(tree)->visible)
3591 FI_SET_FLAG(fi, FI_HIDDEN);
3592 fvalue_init(&fi->value, fi->hfinfo->type);
3595 /* add the data source tvbuff */
3596 fi->ds_tvb = tvb ? tvb_get_ds_tvb(tvb) : NULL;
3598 fi->appendix_start = 0;
3599 fi->appendix_length = 0;
3605 alloc_field_info(proto_tree *tree, int hfindex, tvbuff_t *tvb, const gint start,
3608 header_field_info *hfinfo;
3611 hfinfo = get_hfi_and_length(hfindex, tvb, start, length, &item_length);
3612 return new_field_info(tree, hfinfo, tvb, start, item_length);
3615 /* If the protocol tree is to be visible, set the representation of a
3616 proto_tree entry with the name of the field for the item and with
3617 the value formatted with the supplied printf-style format and
3620 proto_tree_set_representation_value(proto_item *pi, const char *format, va_list ap)
3622 int ret; /*tmp return value */
3623 field_info *fi = PITEM_FINFO(pi);
3624 header_field_info *hf;
3626 DISSECTOR_ASSERT(fi);
3630 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
3631 ITEM_LABEL_NEW(fi->rep);
3632 if (hf->bitmask && (hf->type == FT_BOOLEAN || IS_FT_UINT(hf->type))) {
3636 val = fvalue_get_uinteger(&fi->value);
3637 if (hf->bitshift > 0) {
3638 val <<= hf->bitshift;
3640 decode_bitfield_value(tmpbuf, val, hf->bitmask, hfinfo_bitwidth(hf));
3641 /* put in the hf name */
3642 ret = g_snprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
3643 "%s%s: ", tmpbuf, fi->hfinfo->name);
3645 /* put in the hf name */
3646 ret = g_snprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
3647 "%s: ", fi->hfinfo->name);
3650 /* If possible, Put in the value of the string */
3651 if (ret < ITEM_LABEL_LENGTH) {
3652 ret += g_vsnprintf(fi->rep->representation + ret,
3653 ITEM_LABEL_LENGTH - ret, format, ap);
3655 if (ret >= ITEM_LABEL_LENGTH) {
3656 /* Uh oh, we don't have enough room. Tell the user
3657 * that the field is truncated.
3661 /* Argh, we cannot reuse 'ap' here. So make a copy
3662 * of what we formatted for (re)use below.
3664 oldrep = g_strdup(fi->rep->representation);
3666 g_snprintf(fi->rep->representation,
3675 /* If the protocol tree is to be visible, set the representation of a
3676 proto_tree entry with the representation formatted with the supplied
3677 printf-style format and argument list. */
3679 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap)
3681 int ret; /*tmp return value */
3682 field_info *fi = PITEM_FINFO(pi);
3684 DISSECTOR_ASSERT(fi);
3686 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
3687 ITEM_LABEL_NEW(fi->rep);
3688 ret = g_vsnprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
3690 if (ret >= ITEM_LABEL_LENGTH) {
3691 /* Uh oh, we don't have enough room. Tell the user
3692 * that the field is truncated.
3696 /* Argh, we cannot reuse 'ap' here. So make a copy
3697 * of what we formatted for (re)use below.
3699 oldrep = g_strdup(fi->rep->representation);
3701 g_snprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
3702 "[truncated] %s", oldrep);
3709 protoo_strlcpy(gchar *dest, const gchar *src, gsize dest_size)
3711 gsize res = g_strlcpy(dest, src, dest_size);
3713 if (res > dest_size)
3718 /* -------------------------- */
3720 proto_custom_set(proto_tree* tree, const int field_id, gint occurrence,
3721 gchar *result, gchar *expr, const int size)
3727 struct e_in6_addr *ipv6;
3729 guint32 n_addr; /* network-order IPv4 address */
3731 const true_false_string *tfstring;
3733 int len, prev_len = 0, last, i, offset_r = 0, offset_e = 0;
3735 field_info *finfo = NULL;
3736 header_field_info* hfinfo;
3737 const gchar *abbrev = NULL;
3739 g_assert(field_id >= 0);
3741 hfinfo = proto_registrar_get_nth((guint)field_id);
3743 /* do we need to rewind ? */
3747 if (occurrence < 0) {
3748 /* Search other direction */
3749 while (hfinfo->same_name_prev) {
3750 hfinfo = hfinfo->same_name_prev;
3755 finfos = proto_get_finfo_ptr_array(tree, hfinfo->id);
3757 if (!finfos || !(len = g_ptr_array_len(finfos))) {
3758 if (occurrence < 0) {
3759 hfinfo = hfinfo->same_name_next;
3761 hfinfo = hfinfo->same_name_prev;
3766 /* Are there enough occurrences of the field? */
3767 if (((occurrence - prev_len) > len) || ((occurrence + prev_len) < -len)) {
3768 if (occurrence < 0) {
3769 hfinfo = hfinfo->same_name_next;
3771 hfinfo = hfinfo->same_name_prev;
3777 /* Calculate single index or set outer bounderies */
3778 if (occurrence < 0) {
3779 i = occurrence + len + prev_len;
3781 } else if (occurrence > 0) {
3782 i = occurrence - 1 - prev_len;
3789 prev_len += len; /* Count handled occurrences */
3792 finfo = g_ptr_array_index(finfos, i);
3794 if (offset_r && (offset_r < (size - 2)))
3795 result[offset_r++] = ',';
3797 if (offset_e && (offset_e < (size - 2)))
3798 expr[offset_e++] = ',';
3800 switch (hfinfo->type) {
3802 case FT_NONE: /* Nothing to add */
3803 if (offset_r == 0) {
3805 } else if (result[offset_r-1] == ',') {
3806 result[offset_r-1] = '\0';
3811 /* prevent multiple "yes" entries by setting result directly */
3812 g_strlcpy(result, "Yes", size);
3817 bytes = fvalue_get(&finfo->value);
3818 offset_r += protoo_strlcpy(result+offset_r,
3820 fvalue_length(&finfo->value)),
3824 case FT_ABSOLUTE_TIME:
3825 offset_r += protoo_strlcpy(result+offset_r,
3826 abs_time_to_str(fvalue_get(&finfo->value),
3827 hfinfo->display, TRUE),
3831 case FT_RELATIVE_TIME:
3832 offset_r += protoo_strlcpy(result+offset_r,
3833 rel_time_to_secs_str(fvalue_get(&finfo->value)),
3838 u_integer = fvalue_get_uinteger(&finfo->value);
3839 tfstring = (const true_false_string *)&tfs_true_false;
3840 if (hfinfo->strings) {
3841 tfstring = (const struct true_false_string*) hfinfo->strings;
3843 offset_r += protoo_strlcpy(result+offset_r,
3845 tfstring->true_string :
3846 tfstring->false_string, size-offset_r);
3848 g_snprintf(expr+offset_e, size-offset_e, "%u",
3849 fvalue_get_uinteger(&finfo->value) ? 1 : 0);
3850 offset_e = (int)strlen(expr);
3858 u_integer = fvalue_get_uinteger(&finfo->value);
3859 if ((hfinfo->display & BASE_DISPLAY_E_MASK) == BASE_CUSTOM) {
3860 gchar tmp[ITEM_LABEL_LENGTH];
3861 custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hfinfo->strings;
3863 DISSECTOR_ASSERT(fmtfunc);
3864 fmtfunc(tmp, u_integer);
3865 g_snprintf(result+offset_r, size-offset_r, "%s", tmp);
3866 } else if (hfinfo->strings) {
3867 if (hfinfo->display & BASE_RANGE_STRING) {
3868 g_strlcpy(result+offset_r,
3869 rval_to_str(u_integer, hfinfo->strings, "%u"),
3871 } else if (hfinfo->display & BASE_EXT_STRING) {
3872 g_strlcpy(result+offset_r,
3873 val_to_str_ext(u_integer,
3874 (value_string_ext *)(hfinfo->strings),
3875 "%u"), size-offset_r);
3877 g_strlcpy(result+offset_r,
3878 val_to_str(u_integer, cVALS(hfinfo->strings), "%u"),
3881 } else if (IS_BASE_DUAL(hfinfo->display)) {
3882 g_snprintf(result+offset_r, size-offset_r,
3883 hfinfo_uint_value_format(hfinfo), u_integer, u_integer);
3885 g_snprintf(result+offset_r, size-offset_r,
3886 hfinfo_uint_value_format(hfinfo), u_integer);
3889 if (hfinfo->strings && (hfinfo->display & BASE_DISPLAY_E_MASK) == BASE_NONE) {
3890 g_snprintf(expr+offset_e, size-offset_e,
3891 "\"%s\"", result+offset_r);
3893 g_snprintf(expr+offset_e, size-offset_e,
3894 hfinfo_numeric_value_format(hfinfo),
3895 fvalue_get_uinteger(&finfo->value));
3898 offset_r = (int)strlen(result);
3899 offset_e = (int)strlen(expr);
3903 /* XXX: Should handle BASE_CUSTOM ? */
3904 g_snprintf(result+offset_r, size-offset_r,
3905 "%" G_GINT64_MODIFIER "d",
3906 fvalue_get_integer64(&finfo->value));
3907 offset_r = (int)strlen(result);
3910 g_snprintf(result+offset_r, size-offset_r,
3911 /* XXX: Should handle BASE_CUSTOM ? */
3912 "%" G_GINT64_MODIFIER "u",
3913 fvalue_get_integer64(&finfo->value));
3914 offset_r = (int)strlen(result);
3917 offset_r += protoo_strlcpy(result+offset_r,
3918 eui64_to_str(fvalue_get_integer64(&finfo->value)),
3921 /* XXX - make these just FT_INT? */
3926 integer = fvalue_get_sinteger(&finfo->value);
3927 if ((hfinfo->display & BASE_DISPLAY_E_MASK) == BASE_CUSTOM) {
3928 gchar tmp[ITEM_LABEL_LENGTH];
3929 custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hfinfo->strings;
3931 DISSECTOR_ASSERT(fmtfunc);
3932 fmtfunc(tmp, integer);
3933 g_snprintf(result+offset_r, size-offset_r, "%s", tmp);
3934 } else if (hfinfo->strings) {
3935 if (hfinfo->display & BASE_RANGE_STRING) {
3936 g_strlcpy(result+offset_r,
3937 rval_to_str(integer, hfinfo->strings, "%d"),
3939 } else if (hfinfo->display & BASE_EXT_STRING) {
3940 g_strlcpy(result+offset_r,
3941 val_to_str_ext(integer,
3942 (value_string_ext *)(hfinfo->strings),
3946 g_strlcpy(result+offset_r,
3947 val_to_str(integer, cVALS(hfinfo->strings), "%d"),
3950 } else if (IS_BASE_DUAL(hfinfo->display)) {
3951 g_snprintf(result+offset_r, size-offset_r,
3952 hfinfo_int_value_format(hfinfo), integer, integer);
3954 g_snprintf(result+offset_r, size-offset_r,
3955 hfinfo_int_value_format(hfinfo), integer);
3958 if (hfinfo->strings && (hfinfo->display & BASE_DISPLAY_E_MASK) == BASE_NONE) {
3959 g_snprintf(expr+offset_e, size-offset_e, "\"%s\"", result+offset_r);
3961 g_snprintf(expr+offset_e, size-offset_e,
3962 hfinfo_numeric_value_format(hfinfo),
3963 fvalue_get_sinteger(&finfo->value));
3966 offset_r = (int)strlen(result);
3967 offset_e = (int)strlen(expr);
3971 ipv4 = fvalue_get(&finfo->value);
3972 n_addr = ipv4_get_net_order_addr(ipv4);
3973 offset_r += protoo_strlcpy(result+offset_r,
3974 ip_to_str((guint8 *)&n_addr),
3979 ipv6 = fvalue_get(&finfo->value);
3980 SET_ADDRESS (&addr, AT_IPv6, sizeof(struct e_in6_addr), ipv6);
3981 address_to_str_buf(&addr, result+offset_r, size-offset_r);
3982 offset_r = (int)strlen(result);
3986 offset_r += protoo_strlcpy(result+offset_r,
3987 bytes_to_str_punct(fvalue_get(&finfo->value),
3993 offset_r += protoo_strlcpy(result+offset_r,
3994 guid_to_str((e_guid_t *)fvalue_get(&finfo->value)),
3999 bytes = fvalue_get(&finfo->value);
4000 offset_r += protoo_strlcpy(result+offset_r,
4001 oid_resolved_from_encoded(bytes,
4002 fvalue_length(&finfo->value)),
4004 offset_e += protoo_strlcpy(expr+offset_e,
4005 oid_encoded2string(bytes, fvalue_length(&finfo->value)),
4010 g_snprintf(result+offset_r, size-offset_r,
4011 "%." STRINGIFY(FLT_DIG) "g", fvalue_get_floating(&finfo->value));
4012 offset_r = (int)strlen(result);
4016 g_snprintf(result+offset_r, size-offset_r,
4017 "%." STRINGIFY(DBL_DIG) "g", fvalue_get_floating(&finfo->value));
4018 offset_r = (int)strlen(result);
4023 case FT_UINT_STRING:
4024 bytes = fvalue_get(&finfo->value);
4025 offset_r += protoo_strlcpy(result+offset_r,
4026 format_text(bytes, strlen(bytes)),
4030 case FT_IPXNET: /*XXX really No column custom ?*/
4033 g_error("hfinfo->type %d (%s) not handled\n",
4035 ftype_name(hfinfo->type));
4036 DISSECTOR_ASSERT_NOT_REACHED();
4042 switch (hfinfo->type) {
4055 /* for these types, "expr" is filled in the loop above */
4059 /* for all others, just copy "result" to "expr" */
4060 g_strlcpy(expr, result, size);
4065 /* Store abbrev for return value */
4066 abbrev = hfinfo->abbrev;
4069 if (occurrence == 0) {
4070 /* Fetch next hfinfo with same name (abbrev) */
4071 hfinfo = hfinfo->same_name_prev;
4077 return abbrev ? abbrev : "";
4081 /* Set text of proto_item after having already been created. */
4083 proto_item_set_text(proto_item *pi, const char *format, ...)
4085 field_info *fi = NULL;
4092 fi = PITEM_FINFO(pi);
4097 ITEM_LABEL_FREE(fi->rep);
4100 va_start(ap, format);
4101 proto_tree_set_representation(pi, format, ap);
4105 /* Append to text of proto_item after having already been created. */
4107 proto_item_append_text(proto_item *pi, const char *format, ...)
4109 field_info *fi = NULL;
4117 fi = PITEM_FINFO(pi);
4122 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
4124 * If we don't already have a representation,
4125 * generate the default representation.
4127 if (fi->rep == NULL) {
4128 ITEM_LABEL_NEW(fi->rep);
4129 proto_item_fill_label(fi, fi->rep->representation);
4132 curlen = strlen(fi->rep->representation);
4133 if (ITEM_LABEL_LENGTH > curlen) {
4134 va_start(ap, format);
4135 g_vsnprintf(fi->rep->representation + curlen,
4136 ITEM_LABEL_LENGTH - (gulong) curlen, format, ap);
4142 /* Prepend to text of proto_item after having already been created. */
4144 proto_item_prepend_text(proto_item *pi, const char *format, ...)
4146 field_info *fi = NULL;
4147 char representation[ITEM_LABEL_LENGTH];
4154 fi = PITEM_FINFO(pi);
4159 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
4161 * If we don't already have a representation,
4162 * generate the default representation.
4164 if (fi->rep == NULL) {
4165 ITEM_LABEL_NEW(fi->rep);
4166 proto_item_fill_label(fi, fi->rep->representation);
4169 g_strlcpy(representation, fi->rep->representation, ITEM_LABEL_LENGTH);
4170 va_start(ap, format);
4171 g_vsnprintf(fi->rep->representation,
4172 ITEM_LABEL_LENGTH, format, ap);
4174 g_strlcat(fi->rep->representation, representation, ITEM_LABEL_LENGTH);
4179 proto_item_set_len(proto_item *pi, const gint length)
4186 fi = PITEM_FINFO(pi);
4190 DISSECTOR_ASSERT(length >= 0);
4191 fi->length = length;
4194 * You cannot just make the "len" field of a GByteArray
4195 * larger, if there's no data to back that length;
4196 * you can only make it smaller.
4198 if (fi->value.ftype->ftype == FT_BYTES && length <= (gint)fi->value.value.bytes->len)
4199 fi->value.value.bytes->len = length;
4203 * Sets the length of the item based on its start and on the specified
4204 * offset, which is the offset past the end of the item; as the start
4205 * in the item is relative to the beginning of the data source tvbuff,
4206 * we need to pass in a tvbuff - the end offset is relative to the beginning
4210 proto_item_set_end(proto_item *pi, tvbuff_t *tvb, gint end)
4217 fi = PITEM_FINFO(pi);
4221 end += tvb_raw_offset(tvb);
4222 DISSECTOR_ASSERT(end >= fi->start);
4223 fi->length = end - fi->start;
4227 proto_item_get_len(const proto_item *pi)
4229 field_info *fi = PITEM_FINFO(pi);
4230 return fi ? fi->length : -1;
4234 /** clear flags according to the mask and set new flag values */
4235 #define FI_REPLACE_FLAGS(fi, mask, flags_in) { \
4236 (fi->flags = (fi)->flags & ~(mask)); \
4237 (fi->flags = (fi)->flags | (flags_in)); \
4241 proto_item_set_expert_flags(proto_item *pi, const int group, const guint severity)
4243 if (pi == NULL || PITEM_FINFO(pi) == NULL)
4246 /* only change things if severity is worse or at least equal than before */
4247 if (severity >= FI_GET_FLAG(PITEM_FINFO(pi), PI_SEVERITY_MASK)) {
4248 FI_REPLACE_FLAGS(PITEM_FINFO(pi), PI_GROUP_MASK, group);
4249 FI_REPLACE_FLAGS(PITEM_FINFO(pi), PI_SEVERITY_MASK, severity);
4258 proto_tree_create_root(packet_info *pinfo)
4262 /* Initialize the proto_node */
4263 PROTO_NODE_NEW(pnode);
4264 pnode->parent = NULL;
4265 PNODE_FINFO(pnode) = NULL;
4266 pnode->tree_data = g_new(tree_data_t, 1);
4268 /* Make sure we can access pinfo everywhere */
4269 pnode->tree_data->pinfo = pinfo;
4271 /* Don't initialize the tree_data_t. Wait until we know we need it */
4272 pnode->tree_data->interesting_hfids = NULL;
4274 /* Set the default to FALSE so it's easier to
4275 * find errors; if we expect to see the protocol tree
4276 * but for some reason the default 'visible' is not
4277 * changed, then we'll find out very quickly. */
4278 pnode->tree_data->visible = FALSE;
4280 /* Make sure that we fake protocols (if possible) */
4281 pnode->tree_data->fake_protocols = TRUE;
4283 /* Keep track of the number of children */
4284 pnode->tree_data->count = 0;
4286 pnode->tree_data->fi_tmp = NULL;
4288 return (proto_tree *)pnode;
4292 /* "prime" a proto_tree with a single hfid that a dfilter
4293 * is interested in. */
4295 proto_tree_prime_hfid(proto_tree *tree _U_, const gint hfid)
4297 header_field_info *hfinfo;
4299 PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
4300 /* this field is referenced by a filter so increase the refcount.
4301 also increase the refcount for the parent, i.e the protocol.
4303 hfinfo->ref_type = HF_REF_TYPE_DIRECT;
4304 /* only increase the refcount if there is a parent.
4305 if this is a protocol and not a field then parent will be -1
4306 and there is no parent to add any refcounting for.
4308 if (hfinfo->parent != -1) {
4309 header_field_info *parent_hfinfo;
4310 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
4312 /* Mark parent as indirectly referenced unless it is already directly
4313 * referenced, i.e. the user has specified the parent in a filter.
4315 if (parent_hfinfo->ref_type != HF_REF_TYPE_DIRECT)
4316 parent_hfinfo->ref_type = HF_REF_TYPE_INDIRECT;
4321 proto_item_add_subtree(proto_item *pi, const gint idx) {
4327 DISSECTOR_ASSERT(idx >= 0 && idx < num_tree_types);
4329 fi = PITEM_FINFO(pi);
4331 return (proto_tree *)pi;
4333 fi->tree_type = idx;
4335 return (proto_tree *)pi;
4339 proto_item_get_subtree(const proto_item *pi) {
4344 fi = PITEM_FINFO(pi);
4345 if ( (!fi) || (fi->tree_type == -1) )
4347 return (proto_tree *)pi;
4351 proto_item_get_parent(const proto_item *ti) {
4358 proto_item_get_parent_nth(proto_item *ti, int gen) {
4371 proto_tree_get_parent(const proto_tree *tree) {
4374 return (proto_item *)tree;
4378 proto_tree_get_root(proto_tree *tree) {
4381 while (tree->parent) {
4382 tree = tree->parent;
4388 proto_tree_move_item(proto_tree *tree, proto_item *fixed_item,
4389 proto_item *item_to_move)
4392 /* Revert part of: http://anonsvn.wireshark.org/viewvc?view=rev&revision=32443
4393 * See https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=5500
4395 /* This function doesn't generate any values. It only reorganizes the prococol tree
4396 * so we can bail out immediately if it isn't visible. */
4397 if (!tree || !PTREE_DATA(tree)->visible)
4400 DISSECTOR_ASSERT(item_to_move->parent == tree);
4401 DISSECTOR_ASSERT(fixed_item->parent == tree);
4403 /*** cut item_to_move out ***/
4405 /* is item_to_move the first? */
4406 if (tree->first_child == item_to_move) {
4407 /* simply change first child to next */
4408 tree->first_child = item_to_move->next;
4410 DISSECTOR_ASSERT(tree->last_child != item_to_move);
4412 proto_item *curr_item;
4413 /* find previous and change it's next */
4414 for(curr_item = tree->first_child; curr_item != NULL; curr_item = curr_item->next) {
4415 if (curr_item->next == item_to_move) {
4420 DISSECTOR_ASSERT(curr_item);
4422 curr_item->next = item_to_move->next;
4424 /* fix last_child if required */
4425 if (tree->last_child == item_to_move) {
4426 tree->last_child = curr_item;
4430 /*** insert to_move after fixed ***/
4431 item_to_move->next = fixed_item->next;
4432 fixed_item->next = item_to_move;
4433 if (tree->last_child == fixed_item) {
4434 tree->last_child = item_to_move;
4439 proto_tree_set_appendix(proto_tree *tree, tvbuff_t *tvb, gint start,
4447 fi = PTREE_FINFO(tree);
4451 start += tvb_raw_offset(tvb);
4452 DISSECTOR_ASSERT(start >= 0);
4453 DISSECTOR_ASSERT(length >= 0);
4455 fi->appendix_start = start;
4456 fi->appendix_length = length;
4460 proto_register_protocol(const char *name, const char *short_name,
4461 const char *filter_name)
4463 protocol_t *protocol;
4464 header_field_info *hfinfo;
4466 char *existing_name;
4470 gboolean found_invalid;
4473 * Make sure there's not already a protocol with any of those
4474 * names. Crash if there is, as that's an error in the code
4475 * or an inappropriate plugin.
4476 * This situation has to be fixed to not register more than one
4477 * protocol with the same name.
4479 * This is done by reducing the number of strcmp (and alike) calls
4480 * as much as possible, as this significally slows down startup time.
4482 * Drawback: As a hash value is used to reduce insert time,
4483 * this might lead to a hash collision.
4484 * However, although we have somewhat over 1000 protocols, we're using
4485 * a 32 bit int so this is very, very unlikely.
4488 key = g_malloc (sizeof(gint));
4489 *key = wrs_str_hash(name);
4491 existing_name = g_hash_table_lookup(proto_names, key);
4492 if (existing_name != NULL) {
4493 /* g_error will terminate the program */
4494 g_error("Duplicate protocol name \"%s\"!"
4495 " This might be caused by an inappropriate plugin or a development error.", name);
4497 g_hash_table_insert(proto_names, key, (gpointer)name);
4499 existing_name = g_hash_table_lookup(proto_short_names, (gpointer)short_name);
4500 if (existing_name != NULL) {
4501 g_error("Duplicate protocol short_name \"%s\"!"
4502 " This might be caused by an inappropriate plugin or a development error.", short_name);
4504 g_hash_table_insert(proto_short_names, (gpointer)short_name, (gpointer)short_name);
4506 found_invalid = FALSE;
4507 for (i = 0; filter_name[i]; i++) {
4509 if (!(islower(c) || isdigit(c) || c == '-' || c == '_' || c == '.')) {
4510 found_invalid = TRUE;
4513 if (found_invalid) {
4514 g_error("Protocol filter name \"%s\" has one or more invalid characters."
4515 " Allowed are lower characters, digits, '-', '_' and '.'."
4516 " This might be caused by an inappropriate plugin or a development error.", filter_name);
4518 existing_name = g_hash_table_lookup(proto_filter_names, (gpointer)filter_name);
4519 if (existing_name != NULL) {
4520 g_error("Duplicate protocol filter_name \"%s\"!"
4521 " This might be caused by an inappropriate plugin or a development error.", filter_name);
4523 g_hash_table_insert(proto_filter_names, (gpointer)filter_name, (gpointer)filter_name);
4525 /* Add this protocol to the list of known protocols; the list
4526 is sorted by protocol short name. */
4527 protocol = g_new(protocol_t, 1);
4528 protocol->name = name;
4529 protocol->short_name = short_name;
4530 protocol->filter_name = filter_name;
4531 protocol->fields = NULL;
4532 protocol->is_enabled = TRUE; /* protocol is enabled by default */
4533 protocol->can_toggle = TRUE;
4534 protocol->is_private = FALSE;
4535 /* list will be sorted later by name, when all protocols completed registering */
4536 protocols = g_list_prepend(protocols, protocol);
4538 /* Here we allocate a new header_field_info struct */
4539 hfinfo = g_slice_new(header_field_info);
4540 hfinfo->name = name;
4541 hfinfo->abbrev = filter_name;
4542 hfinfo->type = FT_PROTOCOL;
4543 hfinfo->display = BASE_NONE;
4544 hfinfo->strings = protocol;
4545 hfinfo->bitmask = 0;
4546 hfinfo->bitshift = 0;
4547 hfinfo->ref_type = HF_REF_TYPE_NONE;
4548 hfinfo->blurb = NULL;
4549 hfinfo->parent = -1; /* this field differentiates protos and fields */
4551 proto_id = proto_register_field_init(hfinfo, hfinfo->parent);
4552 protocol->proto_id = proto_id;
4557 proto_mark_private(const int proto_id)
4559 protocol_t *protocol = find_protocol_by_id(proto_id);
4561 protocol->is_private = TRUE;
4565 proto_is_private(const int proto_id)
4567 protocol_t *protocol = find_protocol_by_id(proto_id);
4569 return protocol->is_private;
4575 * Routines to use to iterate over the protocols.
4576 * The argument passed to the iterator routines is an opaque cookie to
4577 * their callers; it's the GList pointer for the current element in
4579 * The ID of the protocol is returned, or -1 if there is no protocol.
4582 proto_get_first_protocol(void **cookie)
4584 protocol_t *protocol;
4586 if (protocols == NULL)
4588 *cookie = protocols;
4589 protocol = protocols->data;
4590 return protocol->proto_id;
4594 proto_get_data_protocol(void *cookie)
4596 GList *list_item = cookie;
4598 protocol_t *protocol = list_item->data;
4599 return protocol->proto_id;
4603 proto_get_next_protocol(void **cookie)
4605 GList *list_item = *cookie;
4606 protocol_t *protocol;
4608 list_item = g_list_next(list_item);
4609 if (list_item == NULL)
4611 *cookie = list_item;
4612 protocol = list_item->data;
4613 return protocol->proto_id;
4617 proto_get_first_protocol_field(const int proto_id, void **cookie)
4619 protocol_t *protocol = find_protocol_by_id(proto_id);
4620 hf_register_info *ptr;
4622 if ((protocol == NULL) || (protocol->fields == NULL))
4625 *cookie = protocol->fields;
4626 ptr = protocol->fields->data;
4627 return &ptr->hfinfo;
4631 proto_get_next_protocol_field(void **cookie)
4633 GList *list_item = *cookie;
4634 hf_register_info *ptr;
4636 list_item = g_list_next(list_item);
4637 if (list_item == NULL)
4640 *cookie = list_item;
4641 ptr = list_item->data;
4642 return &ptr->hfinfo;
4646 find_protocol_by_id(const int proto_id)
4648 header_field_info *hfinfo;
4653 PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
4654 DISSECTOR_ASSERT(hfinfo->type == FT_PROTOCOL);
4655 return (protocol_t *)hfinfo->strings;
4658 static gint compare_filter_name(gconstpointer proto_arg,
4659 gconstpointer filter_name)
4661 const protocol_t *protocol = proto_arg;
4662 const gchar *f_name = filter_name;
4664 return (strcmp(protocol->filter_name, f_name));
4668 proto_get_id(const protocol_t *protocol)
4670 return protocol->proto_id;
4673 int proto_get_id_by_filter_name(const gchar* filter_name)
4676 protocol_t *protocol;
4678 list_entry = g_list_find_custom(protocols, filter_name,
4679 compare_filter_name);
4681 if (list_entry == NULL)
4683 protocol = list_entry->data;
4684 return protocol->proto_id;
4688 proto_get_protocol_name(const int proto_id)
4690 protocol_t *protocol;
4692 protocol = find_protocol_by_id(proto_id);
4694 if (protocol == NULL)
4696 return protocol->name;
4700 proto_get_protocol_short_name(const protocol_t *protocol)
4702 if (protocol == NULL)
4704 return protocol->short_name;
4708 proto_get_protocol_long_name(const protocol_t *protocol)
4710 if (protocol == NULL)
4712 return protocol->name;
4716 proto_get_protocol_filter_name(const int proto_id)
4718 protocol_t *protocol;
4720 protocol = find_protocol_by_id(proto_id);
4721 if (protocol == NULL)
4723 return protocol->filter_name;
4727 proto_is_protocol_enabled(const protocol_t *protocol)
4729 return protocol->is_enabled;
4733 proto_can_toggle_protocol(const int proto_id)
4735 protocol_t *protocol;
4737 protocol = find_protocol_by_id(proto_id);
4738 return protocol->can_toggle;
4742 proto_set_decoding(const int proto_id, const gboolean enabled)
4744 protocol_t *protocol;
4746 protocol = find_protocol_by_id(proto_id);
4747 DISSECTOR_ASSERT(protocol->can_toggle);
4748 protocol->is_enabled = enabled;
4752 proto_enable_all(void)
4754 protocol_t *protocol;
4755 GList *list_item = protocols;
4757 if (protocols == NULL)
4761 protocol = list_item->data;
4762 if (protocol->can_toggle)
4763 protocol->is_enabled = TRUE;
4764 list_item = g_list_next(list_item);
4769 proto_set_cant_toggle(const int proto_id)
4771 protocol_t *protocol;
4773 protocol = find_protocol_by_id(proto_id);
4774 protocol->can_toggle = FALSE;
4777 /* for use with static arrays only, since we don't allocate our own copies
4778 of the header_field_info struct contained within the hf_register_info struct */
4780 proto_register_field_array(const int parent, hf_register_info *hf, const int num_records)
4783 hf_register_info *ptr = hf;
4786 proto = find_protocol_by_id(parent);
4787 for (i = 0; i < num_records; i++, ptr++) {
4789 * Make sure we haven't registered this yet.
4790 * Most fields have variables associated with them
4791 * that are initialized to -1; some have array elements,
4792 * or possibly uninitialized variables, so we also allow
4793 * 0 (which is unlikely to be the field ID we get back
4794 * from "proto_register_field_init()").
4796 if (*ptr->p_id != -1 && *ptr->p_id != 0) {
4798 "Duplicate field detected in call to proto_register_field_array: %s is already registered\n",
4799 ptr->hfinfo.abbrev);
4803 if (proto != NULL) {
4804 if (proto->fields == NULL) {
4805 proto->fields = g_list_append(NULL, ptr);
4806 proto->last_field = proto->fields;
4809 g_list_append(proto->last_field, ptr)->next;
4812 field_id = proto_register_field_init(&ptr->hfinfo, parent);
4813 *ptr->p_id = field_id;
4817 /* unregister already registered fields */
4819 proto_unregister_field (const int parent, gint hf_id)
4821 hf_register_info *hf;
4825 if (hf_id == -1 || hf_id == 0)
4828 proto = find_protocol_by_id (parent);
4829 if (!proto || !proto->fields) {
4833 for (field = g_list_first (proto->fields); field; field = g_list_next (field)) {
4835 if (*hf->p_id == hf_id) {
4836 /* Found the hf_id in this protocol */
4837 g_tree_steal (gpa_name_tree, hf->hfinfo.abbrev);
4838 proto->fields = g_list_remove_link (proto->fields, field);
4839 proto->last_field = g_list_last (proto->fields);
4845 /* chars allowed in field abbrev */
4847 const guchar fld_abbrev_chars[256] = {
4848 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00-0x0F */
4849 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10-0x1F */
4850 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, /* 0x20-0x2F '-', '.' */
4851 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 0x30-0x3F '0'-'9' */
4852 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x40-0x4F 'A'-'O' */
4853 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 0x50-0x5F 'P'-'Z', '_' */
4854 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x60-0x6F 'a'-'o' */
4855 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 0x70-0x7F 'p'-'z' */
4856 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80-0x8F */
4857 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90-0x9F */
4858 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xA0-0xAF */
4859 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xB0-0xBF */
4860 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xC0-0xCF */
4861 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xD0-0xDF */
4862 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xE0-0xEF */
4863 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xF0-0xFF */
4866 static const value_string hf_types[] = {
4867 { FT_NONE, "FT_NONE" },
4868 { FT_PROTOCOL, "FT_PROTOCOL" },
4869 { FT_BOOLEAN, "FT_BOOLEAN" },
4870 { FT_UINT8, "FT_UINT8" },
4871 { FT_UINT16, "FT_UINT16" },
4872 { FT_UINT24, "FT_UINT24" },
4873 { FT_UINT32, "FT_UINT32" },
4874 { FT_UINT64, "FT_UINT64" },
4875 { FT_INT8, "FT_INT8" },
4876 { FT_INT16, "FT_INT16" },
4877 { FT_INT24, "FT_INT24" },
4878 { FT_INT32, "FT_INT32" },
4879 { FT_INT64, "FT_INT64" },
4880 { FT_EUI64, "FT_EUI64" },
4881 { FT_FLOAT, "FT_FLOAT" },
4882 { FT_DOUBLE, "FT_DOUBLE" },
4883 { FT_ABSOLUTE_TIME, "FT_ABSOLUTE_TIME" },
4884 { FT_RELATIVE_TIME, "FT_RELATIVE_TIME" },
4885 { FT_STRING, "FT_STRING" },
4886 { FT_STRINGZ, "FT_STRINGZ" },
4887 { FT_UINT_STRING, "FT_UINT_STRING" },
4888 { FT_ETHER, "FT_ETHER" },
4889 { FT_BYTES, "FT_BYTES" },
4890 { FT_UINT_BYTES, "FT_UINT_BYTES" },
4891 { FT_IPv4, "FT_IPv4" },
4892 { FT_IPv6, "FT_IPv6" },
4893 { FT_IPXNET, "FT_IPXNET" },
4894 { FT_FRAMENUM, "FT_FRAMENUM" },
4895 { FT_PCRE, "FT_PCR" },
4896 { FT_GUID, "FT_GUID" },
4897 { FT_OID, "FT_OID" },
4900 static const value_string hf_display[] = {
4901 { BASE_NONE, "BASE_NONE" },
4902 { BASE_DEC, "BASE_DEC" },
4903 { BASE_HEX, "BASE_HEX" },
4904 { BASE_OCT, "BASE_OCT" },
4905 { BASE_DEC_HEX, "BASE_DEC_HEX" },
4906 { BASE_HEX_DEC, "BASE_HEX_DEC" },
4907 { BASE_CUSTOM, "BASE_CUSTOM" },
4908 { BASE_NONE|BASE_RANGE_STRING, "BASE_NONE|BASE_RANGE_STRING" },
4909 { BASE_DEC|BASE_RANGE_STRING, "BASE_DEC|BASE_RANGE_STRING" },
4910 { BASE_HEX|BASE_RANGE_STRING, "BASE_HEX|BASE_RANGE_STRING" },
4911 { BASE_OCT|BASE_RANGE_STRING, "BASE_OCT|BASE_RANGE_STRING" },
4912 { BASE_DEC_HEX|BASE_RANGE_STRING, "BASE_DEC_HEX|BASE_RANGE_STRING" },
4913 { BASE_HEX_DEC|BASE_RANGE_STRING, "BASE_HEX_DEC|BASE_RANGE_STRING" },
4914 { BASE_CUSTOM|BASE_RANGE_STRING, "BASE_CUSTOM|BASE_RANGE_STRING" },
4915 { ABSOLUTE_TIME_LOCAL, "ABSOLUTE_TIME_LOCAL" },
4916 { ABSOLUTE_TIME_UTC, "ABSOLUTE_TIME_UTC" },
4917 { ABSOLUTE_TIME_DOY_UTC, "ABSOLUTE_TIME_DOY_UTC" },
4920 /* temporary function containing assert part for easier profiling */
4922 tmp_fld_check_assert(header_field_info *hfinfo)
4925 /* The field must have a name (with length > 0) */
4926 if (!hfinfo->name || !hfinfo->name[0]) {
4928 /* Try to identify the field */
4929 g_error("Field (abbrev='%s') does not have a name\n",
4933 g_error("Field does not have a name (nor an abbreviation)\n");
4936 /* fields with an empty string for an abbreviation aren't filterable */
4937 if (!hfinfo->abbrev || !hfinfo->abbrev[0])
4938 g_error("Field '%s' does not have an abbreviation\n", hfinfo->name);
4940 /* These types of fields are allowed to have value_strings,
4941 * true_false_strings or a protocol_t struct
4943 if (hfinfo->strings != NULL && !(
4944 (hfinfo->type == FT_UINT8) ||
4945 (hfinfo->type == FT_UINT16) ||
4946 (hfinfo->type == FT_UINT24) ||
4947 (hfinfo->type == FT_UINT32) ||
4948 (hfinfo->type == FT_INT8) ||
4949 (hfinfo->type == FT_INT16) ||
4950 (hfinfo->type == FT_INT24) ||
4951 (hfinfo->type == FT_INT32) ||
4952 (hfinfo->type == FT_BOOLEAN) ||
4953 (hfinfo->type == FT_PROTOCOL) ||
4954 (hfinfo->type == FT_FRAMENUM) ))
4955 g_error("Field '%s' (%s) has a 'strings' value but is of type %s"
4956 " (which is not allowed to have strings)\n",
4957 hfinfo->name, hfinfo->abbrev,
4958 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"));
4960 /* TODO: This check may slow down startup, and output quite a few warnings.
4961 It would be good to be able to enable this (and possibly other checks?)
4962 in non-release builds. */
4964 /* Check for duplicate value_string values.
4965 There are lots that have the same value *and* string, so for now only
4966 report those that have same value but different string. */
4967 if ((hfinfo->strings != NULL) &&
4968 !(hfinfo->display & BASE_RANGE_STRING) &&
4969 !((hfinfo->display & BASE_DISPLAY_E_MASK) == BASE_CUSTOM) &&
4971 (hfinfo->type == FT_UINT8) ||
4972 (hfinfo->type == FT_UINT16) ||
4973 (hfinfo->type == FT_UINT24) ||
4974 (hfinfo->type == FT_UINT32) ||
4975 (hfinfo->type == FT_INT8) ||
4976 (hfinfo->type == FT_INT16) ||
4977 (hfinfo->type == FT_INT24) ||
4978 (hfinfo->type == FT_INT32) ||
4979 (hfinfo->type == FT_FRAMENUM) )) {
4982 const value_string *start_values;
4983 const value_string *current;
4985 if (hfinfo->display & BASE_EXT_STRING)
4986 start_values = VALUE_STRING_EXT_VS_P(((const value_string_ext*)hfinfo->strings));
4988 start_values = (const value_string*)hfinfo->strings;
4989 current = start_values;
4991 for (n=0; current; n++, current++) {
4992 /* Drop out if we reached the end. */
4993 if ((current->value == 0) && (current->strptr == NULL)) {
4997 /* Check value against all previous */
4998 for (m=0; m < n; m++) {
4999 /* There are lots of duplicates with the same string,
5000 so only report if different... */
5001 if ((start_values[m].value == current->value) &&
5002 (strcmp(start_values[m].strptr, current->strptr) != 0)) {
5003 g_warning("Field '%s' (%s) has a conflicting entry in its"
5004 " value_string: %u is at indices %u (%s) and %u (%s))\n",
5005 hfinfo->name, hfinfo->abbrev,
5006 current->value, m, start_values[m].strptr, n, current->strptr);
5014 switch (hfinfo->type) {
5021 /* Hexadecimal and octal are, in printf() and everywhere
5022 * else, unsigned so don't allow dissectors to register a
5023 * signed field to be displayed unsigned. (Else how would
5024 * we display negative values?)
5026 * If you want to take out this check, be sure to fix
5027 * hfinfo_numeric_format() so that it does not assert out
5028 * when trying to construct a hexadecimal representation of
5031 if (hfinfo->display == BASE_HEX ||
5032 hfinfo->display == BASE_OCT)
5033 g_error("Field '%s' (%s) is signed (%s) but is being displayed unsigned (%s)\n",
5034 hfinfo->name, hfinfo->abbrev,
5035 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"),
5036 val_to_str(hfinfo->display, hf_display, "(Bit count: %d)"));
5043 /* Require integral types (other than frame number,
5044 * which is always displayed in decimal) to have a
5046 * If there is a strings value then this base is not
5047 * normally used except when constructing a display
5048 * filter for a value not found in the strings lookup.
5050 switch (hfinfo->display & BASE_DISPLAY_E_MASK) {
5056 case BASE_CUSTOM: /* hfinfo_numeric_value_format() treats this as decimal */
5059 g_error("Field '%s' (%s) is an integral value (%s)"
5060 " but is being displayed as %s\n",
5061 hfinfo->name, hfinfo->abbrev,
5062 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"),
5063 val_to_str(hfinfo->display, hf_display, "(Unknown: 0x%x)"));
5069 if (hfinfo->display != BASE_NONE)
5070 g_error("Field '%s' (%s) is an %s but is being displayed as %s instead of BASE_NONE\n",
5071 hfinfo->name, hfinfo->abbrev,
5072 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"),
5073 val_to_str(hfinfo->display, hf_display, "(Bit count: %d)"));
5074 if (hfinfo->bitmask != 0)
5075 g_error("Field '%s' (%s) is an %s but has a bitmask\n",
5076 hfinfo->name, hfinfo->abbrev,
5077 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"));
5083 case FT_ABSOLUTE_TIME:
5084 if (!(hfinfo->display == ABSOLUTE_TIME_LOCAL ||
5085 hfinfo->display == ABSOLUTE_TIME_UTC ||
5086 hfinfo->display == ABSOLUTE_TIME_DOY_UTC))
5087 g_error("Field '%s' (%s) is a %s but is being displayed as %s instead of as a time\n",
5088 hfinfo->name, hfinfo->abbrev,
5089 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"),
5090 val_to_str(hfinfo->display, hf_display, "(Bit count: %d)"));
5091 if (hfinfo->bitmask != 0)
5092 g_error("Field '%s' (%s) is an %s but has a bitmask\n",
5093 hfinfo->name, hfinfo->abbrev,
5094 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"));
5098 if (hfinfo->display != BASE_NONE)
5099 g_error("Field '%s' (%s) is an %s but is being displayed as %s instead of BASE_NONE\n",
5100 hfinfo->name, hfinfo->abbrev,
5101 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"),
5102 val_to_str(hfinfo->display, hf_display, "(Bit count: %d)"));
5103 if (hfinfo->bitmask != 0)
5104 g_error("Field '%s' (%s) is an %s but has a bitmask\n",
5105 hfinfo->name, hfinfo->abbrev,
5106 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"));
5107 if (hfinfo->strings != NULL)
5108 g_error("Field '%s' (%s) is an %s but has a strings value\n",
5109 hfinfo->name, hfinfo->abbrev,
5110 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"));
5115 #define PROTO_PRE_ALLOC_HF_FIELDS_MEM 120000
5117 proto_register_field_init(header_field_info *hfinfo, const int parent)
5120 tmp_fld_check_assert(hfinfo);
5122 /* if this is a bitfield, compute bitshift */
5123 if (hfinfo->bitmask) {
5124 hfinfo->bitshift = wrs_count_bitshift(hfinfo->bitmask);
5127 hfinfo->parent = parent;
5128 hfinfo->same_name_next = NULL;
5129 hfinfo->same_name_prev = NULL;
5131 /* if we always add and never delete, then id == len - 1 is correct */
5132 if (gpa_hfinfo.len >= gpa_hfinfo.allocated_len) {
5133 if (!gpa_hfinfo.hfi) {
5134 gpa_hfinfo.allocated_len = PROTO_PRE_ALLOC_HF_FIELDS_MEM;
5135 gpa_hfinfo.hfi = g_malloc(sizeof(header_field_info *)*PROTO_PRE_ALLOC_HF_FIELDS_MEM);
5137 gpa_hfinfo.allocated_len += 1000;
5138 gpa_hfinfo.hfi = g_realloc(gpa_hfinfo.hfi,
5139 sizeof(header_field_info *)*gpa_hfinfo.allocated_len);
5140 /*g_warning("gpa_hfinfo.allocated_len %u", gpa_hfinfo.allocated_len);*/
5143 gpa_hfinfo.hfi[gpa_hfinfo.len] = hfinfo;
5145 hfinfo->id = gpa_hfinfo.len - 1;
5147 /* if we have real names, enter this field in the name tree */
5148 if ((hfinfo->name[0] != 0) && (hfinfo->abbrev[0] != 0 )) {
5150 header_field_info *same_name_next_hfinfo;
5153 /* Check that the filter name (abbreviation) is legal;
5154 * it must contain only alphanumerics, '-', "_", and ".". */
5155 c = wrs_check_charset(fld_abbrev_chars, hfinfo->abbrev);
5157 fprintf(stderr, "Invalid character '%c' in filter name '%s'\n", c, hfinfo->abbrev);
5158 DISSECTOR_ASSERT(!c);
5161 /* We allow multiple hfinfo's to be registered under the same
5162 * abbreviation. This was done for X.25, as, depending
5163 * on whether it's modulo-8 or modulo-128 operation,
5164 * some bitfield fields may be in different bits of
5165 * a byte, and we want to be able to refer to that field
5166 * with one name regardless of whether the packets
5167 * are modulo-8 or modulo-128 packets. */
5169 same_name_hfinfo = NULL;
5171 g_tree_insert(gpa_name_tree, (gpointer) (hfinfo->abbrev), hfinfo);
5172 /* GLIB 2.x - if it is already present
5173 * the previous hfinfo with the same name is saved
5174 * to same_name_hfinfo by value destroy callback */
5175 if (same_name_hfinfo) {
5176 /* There's already a field with this name.
5177 * Put it after that field in the list of
5178 * fields with this name, then allow the code
5179 * after this if{} block to replace the old
5180 * hfinfo with the new hfinfo in the GTree. Thus,
5181 * we end up with a linked-list of same-named hfinfo's,
5182 * with the root of the list being the hfinfo in the GTree */
5183 same_name_next_hfinfo =
5184 same_name_hfinfo->same_name_next;
5186 hfinfo->same_name_next = same_name_next_hfinfo;
5187 if (same_name_next_hfinfo)
5188 same_name_next_hfinfo->same_name_prev = hfinfo;
5190 same_name_hfinfo->same_name_next = hfinfo;
5191 hfinfo->same_name_prev = same_name_hfinfo;
5199 proto_register_subtree_array(gint *const *indices, const int num_indices)
5202 gint *const *ptr = indices;
5205 * If we've already allocated the array of tree types, expand
5206 * it; this lets plugins such as mate add tree types after
5207 * the initial startup. (If we haven't already allocated it,
5208 * we don't allocate it; on the first pass, we just assign
5209 * ett values and keep track of how many we've assigned, and
5210 * when we're finished registering all dissectors we allocate
5211 * the array, so that we do only one allocation rather than
5212 * wasting CPU time and memory by growing the array for each
5213 * dissector that registers ett values.)
5215 if (tree_is_expanded != NULL) {
5217 g_realloc(tree_is_expanded,
5218 (num_tree_types + num_indices)*sizeof (gboolean));
5219 memset(tree_is_expanded + num_tree_types, 0,
5220 num_indices*sizeof (gboolean));
5224 * Assign "num_indices" subtree numbers starting at "num_tree_types",
5225 * returning the indices through the pointers in the array whose
5226 * first element is pointed to by "indices", and update
5227 * "num_tree_types" appropriately.
5229 for (i = 0; i < num_indices; i++, ptr++, num_tree_types++) {
5231 /* g_error will terminate the program */
5232 g_error("register_subtree_array: subtree item type (ett_...) not -1 !"
5233 " This is a development error:"
5234 " Either the subtree item type has already been assigned or"
5235 " was not initialized to -1.");
5237 **ptr = num_tree_types;
5242 label_fill_descr(char *label_str, const header_field_info *hfinfo, const char *text, const char *descr)
5246 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH, "%s: %s (%s)", hfinfo->name, text, descr);
5247 if (ret >= ITEM_LABEL_LENGTH) {
5248 /* Uh oh, we don't have enough room. Tell the user that the field is truncated. */
5249 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH, "%s [truncated]: %s (%s)", hfinfo->name, text, descr);
5256 label_fill(char *label_str, const header_field_info *hfinfo, const char *text)
5260 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH, "%s: %s", hfinfo->name, text);
5261 if (ret >= ITEM_LABEL_LENGTH) {
5262 /* Uh oh, we don't have enough room. Tell the user that the field is truncated. */
5263 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH, "%s [truncated]: %s", hfinfo->name, text);
5270 proto_item_fill_label(field_info *fi, gchar *label_str)
5272 header_field_info *hfinfo;
5278 guint32 n_addr; /* network-order IPv4 address */
5284 /* XXX: Check validity of hfinfo->type */
5288 hfinfo = fi->hfinfo;
5290 switch (hfinfo->type) {
5293 g_strlcpy(label_str, hfinfo->name, ITEM_LABEL_LENGTH);
5297 fill_label_boolean(fi, label_str);
5302 bytes = fvalue_get(&fi->value);
5303 label_fill(label_str, hfinfo,
5304 (bytes) ? bytes_to_str(bytes, fvalue_length(&fi->value)) : "<MISSING>");
5307 /* Four types of integers to take care of:
5308 * Bitfield, with val_string
5309 * Bitfield, w/o val_string
5310 * Non-bitfield, with val_string
5311 * Non-bitfield, w/o val_string
5317 if (hfinfo->bitmask) {
5318 fill_label_bitfield(fi, label_str);
5320 fill_label_uint(fi, label_str);
5325 fill_label_uint(fi, label_str);
5329 fill_label_uint64(fi, label_str);
5336 DISSECTOR_ASSERT(!hfinfo->bitmask);
5337 fill_label_int(fi, label_str);
5341 fill_label_int64(fi, label_str);
5345 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5346 "%s: %." STRINGIFY(FLT_DIG) "g",
5347 hfinfo->name, fvalue_get_floating(&fi->value));
5351 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5352 "%s: %." STRINGIFY(DBL_DIG) "g",
5353 hfinfo->name, fvalue_get_floating(&fi->value));
5356 case FT_ABSOLUTE_TIME:
5357 label_fill(label_str, hfinfo,
5358 abs_time_to_str(fvalue_get(&fi->value), hfinfo->display, TRUE));
5361 case FT_RELATIVE_TIME:
5362 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5363 "%s: %s seconds", hfinfo->name,
5364 rel_time_to_secs_str(fvalue_get(&fi->value)));
5368 integer = fvalue_get_uinteger(&fi->value);
5369 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5370 "%s: %s (0x%08X)", hfinfo->name,
5371 get_ipxnet_name(integer), integer);
5375 bytes = fvalue_get(&fi->value);
5376 label_fill_descr(label_str, hfinfo,
5377 get_ax25_name(bytes),
5378 ax25_to_str(bytes));
5382 bytes = fvalue_get(&fi->value);
5383 label_fill_descr(label_str, hfinfo,
5384 get_ether_name(bytes),
5385 ether_to_str(bytes));
5389 ipv4 = fvalue_get(&fi->value);
5390 n_addr = ipv4_get_net_order_addr(ipv4);
5391 label_fill_descr(label_str, hfinfo,
5392 get_hostname(n_addr),
5393 ip_to_str((guint8*)&n_addr));
5397 bytes = fvalue_get(&fi->value);
5398 label_fill_descr(label_str, hfinfo,
5399 get_hostname6((struct e_in6_addr *)bytes),
5400 ip6_to_str((struct e_in6_addr*)bytes));
5404 guid = fvalue_get(&fi->value);
5405 label_fill(label_str, hfinfo, guid_to_str(guid));
5409 bytes = fvalue_get(&fi->value);
5410 name = oid_resolved_from_encoded(bytes, fvalue_length(&fi->value));
5412 label_fill_descr(label_str, hfinfo,
5413 oid_encoded2string(bytes, fvalue_length(&fi->value)), name);
5415 label_fill(label_str, hfinfo,
5416 oid_encoded2string(bytes, fvalue_length(&fi->value)));
5420 integer64 = fvalue_get_integer64(&fi->value);
5421 label_fill_descr(label_str, hfinfo,
5422 get_eui64_name(integer64),
5423 eui64_to_str(integer64));
5427 case FT_UINT_STRING:
5428 bytes = fvalue_get(&fi->value);
5429 label_fill(label_str, hfinfo, format_text(bytes, strlen(bytes)));
5433 g_error("hfinfo->type %d (%s) not handled\n",
5434 hfinfo->type, ftype_name(hfinfo->type));
5435 DISSECTOR_ASSERT_NOT_REACHED();
5441 fill_label_boolean(field_info *fi, gchar *label_str)
5443 char *p = label_str;
5444 int bitfield_byte_length = 0, bitwidth;
5445 guint32 unshifted_value;
5448 header_field_info *hfinfo = fi->hfinfo;
5449 const true_false_string *tfstring = (const true_false_string *)&tfs_true_false;
5451 if (hfinfo->strings) {
5452 tfstring = (const struct true_false_string*) hfinfo->strings;
5455 value = fvalue_get_uinteger(&fi->value);
5456 if (hfinfo->bitmask) {
5457 /* Figure out the bit width */
5458 bitwidth = hfinfo_bitwidth(hfinfo);
5461 unshifted_value = value;
5462 if (hfinfo->bitshift > 0) {
5463 unshifted_value <<= hfinfo->bitshift;
5466 /* Create the bitfield first */
5467 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
5468 bitfield_byte_length = (int) (p - label_str);
5471 /* Fill in the textual info */
5472 g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
5473 "%s: %s", hfinfo->name,
5474 value ? tfstring->true_string : tfstring->false_string);
5477 /* Fills data for bitfield ints with val_strings */
5479 fill_label_bitfield(field_info *fi, gchar *label_str)
5481 const char *format = NULL;
5483 int bitfield_byte_length, bitwidth;
5484 guint32 unshifted_value;
5487 header_field_info *hfinfo = fi->hfinfo;
5489 /* Figure out the bit width */
5490 bitwidth = hfinfo_bitwidth(hfinfo);
5493 unshifted_value = fvalue_get_uinteger(&fi->value);
5494 value = unshifted_value;
5495 if (hfinfo->bitshift > 0) {
5496 unshifted_value <<= hfinfo->bitshift;
5499 /* Create the bitfield first */
5500 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
5501 bitfield_byte_length = (int) (p - label_str);
5503 /* Fill in the textual info using stored (shifted) value */
5504 if (hfinfo->display == BASE_CUSTOM) {
5505 gchar tmp[ITEM_LABEL_LENGTH];
5506 custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hfinfo->strings;
5508 DISSECTOR_ASSERT(fmtfunc);
5509 fmtfunc(tmp, value);
5510 g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
5511 "%s: %s", hfinfo->name, tmp);
5513 else if (hfinfo->strings) {
5514 format = hfinfo_uint_vals_format(hfinfo);
5515 if (hfinfo->display & BASE_RANGE_STRING) {
5516 g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
5517 format, hfinfo->name,
5518 rval_to_str(value, hfinfo->strings, "Unknown"), value);
5519 } else if (hfinfo->display & BASE_EXT_STRING) {
5520 g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
5521 format, hfinfo->name,
5522 val_to_str_ext_const(value, (value_string_ext *) hfinfo->strings, "Unknown"), value);
5524 g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
5525 format, hfinfo->name,
5526 val_to_str_const(value, cVALS(hfinfo->strings), "Unknown"), value);
5530 format = hfinfo_uint_format(hfinfo);
5531 if (IS_BASE_DUAL(hfinfo->display)) {
5532 g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
5533 format, hfinfo->name, value, value);
5535 g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
5536 format, hfinfo->name, value);
5542 fill_label_uint(field_info *fi, gchar *label_str)
5544 const char *format = NULL;
5545 header_field_info *hfinfo = fi->hfinfo;
5548 value = fvalue_get_uinteger(&fi->value);
5550 /* Fill in the textual info */
5551 if (hfinfo->display == BASE_CUSTOM) {
5552 gchar tmp[ITEM_LABEL_LENGTH];
5553 custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hfinfo->strings;
5555 DISSECTOR_ASSERT(fmtfunc);
5556 fmtfunc(tmp, value);
5557 label_fill(label_str, hfinfo, tmp);
5559 else if (hfinfo->strings) {
5560 format = hfinfo_uint_vals_format(hfinfo);
5561 if (hfinfo->display & BASE_RANGE_STRING) {
5562 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5563 format, hfinfo->name,
5564 rval_to_str(value, hfinfo->strings, "Unknown"), value);
5565 } else if (hfinfo->display & BASE_EXT_STRING) {
5566 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5567 format, hfinfo->name,
5568 val_to_str_ext_const(value, (value_string_ext *) hfinfo->strings, "Unknown"), value);
5570 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5571 format, hfinfo->name,
5572 val_to_str_const(value, cVALS(hfinfo->strings), "Unknown"), value);
5576 format = hfinfo_uint_format(hfinfo);
5577 if (IS_BASE_DUAL(hfinfo->display)) {
5578 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5579 format, hfinfo->name, value, value);
5581 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5582 format, hfinfo->name, value);
5588 fill_label_uint64(field_info *fi, gchar *label_str)
5590 const char *format = NULL;
5591 header_field_info *hfinfo = fi->hfinfo;
5594 /* Pick the proper format string */
5595 format = hfinfo_uint64_format(hfinfo);
5596 value = fvalue_get_integer64(&fi->value);
5598 /* Fill in the textual info */
5599 if (IS_BASE_DUAL(hfinfo->display)) {
5600 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5601 format, hfinfo->name, value, value);
5603 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5604 format, hfinfo->name, value);
5609 fill_label_int(field_info *fi, gchar *label_str)
5611 const char *format = NULL;
5612 header_field_info *hfinfo = fi->hfinfo;
5615 value = fvalue_get_sinteger(&fi->value);
5617 /* Fill in the textual info */
5618 if (hfinfo->display == BASE_CUSTOM) {
5619 gchar tmp[ITEM_LABEL_LENGTH];
5620 custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hfinfo->strings;
5622 DISSECTOR_ASSERT(fmtfunc);
5623 fmtfunc(tmp, value);
5624 label_fill(label_str, hfinfo, tmp);
5626 else if (hfinfo->strings) {
5627 format = hfinfo_int_vals_format(hfinfo);
5628 if (hfinfo->display & BASE_RANGE_STRING) {
5629 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5630 format, hfinfo->name,
5631 rval_to_str(value, hfinfo->strings, "Unknown"), value);
5632 } else if (hfinfo->display & BASE_EXT_STRING) {
5633 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5634 format, hfinfo->name,
5635 val_to_str_ext_const(value, (value_string_ext *) hfinfo->strings, "Unknown"), value);
5637 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5638 format, hfinfo->name,
5639 val_to_str_const(value, cVALS(hfinfo->strings), "Unknown"), value);
5643 format = hfinfo_int_format(hfinfo);
5644 if (IS_BASE_DUAL(hfinfo->display)) {
5645 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5646 format, hfinfo->name, value, value);
5648 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5649 format, hfinfo->name, value);
5655 fill_label_int64(field_info *fi, gchar *label_str)
5657 const char *format = NULL;
5658 header_field_info *hfinfo = fi->hfinfo;
5661 /* Pick the proper format string */
5662 format = hfinfo_int64_format(hfinfo);
5663 value = fvalue_get_integer64(&fi->value);
5665 /* Fill in the textual info */
5666 if (IS_BASE_DUAL(hfinfo->display)) {
5667 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5668 format, hfinfo->name, value, value);
5670 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5671 format, hfinfo->name, value);
5676 hfinfo_bitwidth(const header_field_info *hfinfo)
5680 if (!hfinfo->bitmask) {
5684 switch (hfinfo->type) {
5702 bitwidth = hfinfo->display; /* hacky? :) */
5705 DISSECTOR_ASSERT_NOT_REACHED();
5712 hfinfo_uint_vals_format(const header_field_info *hfinfo)
5714 const char *format = NULL;
5716 /* Get the underlying BASE_ value */
5717 switch (hfinfo->display & BASE_DISPLAY_E_MASK) {
5723 format = "%s: %s (%u)";
5725 case BASE_OCT: /* I'm lazy */
5726 format = "%s: %s (%#o)";
5730 switch (hfinfo->type) {
5732 format = "%s: %s (0x%02x)";
5735 format = "%s: %s (0x%04x)";
5738 format = "%s: %s (0x%06x)";
5741 format = "%s: %s (0x%08x)";
5744 DISSECTOR_ASSERT_NOT_REACHED();
5749 DISSECTOR_ASSERT_NOT_REACHED();
5756 hfinfo_uint_format(const header_field_info *hfinfo)
5758 const char *format = NULL;
5760 /* Pick the proper format string */
5761 if (hfinfo->type == FT_FRAMENUM) {
5763 * Frame numbers are always displayed in decimal.
5767 switch (hfinfo->display) {
5772 switch (hfinfo->type) {
5774 format = "%s: %u (0x%02x)";
5777 format = "%s: %u (0x%04x)";
5780 format = "%s: %u (0x%06x)";
5783 format = "%s: %u (0x%08x)";
5786 DISSECTOR_ASSERT_NOT_REACHED();
5790 case BASE_OCT: /* I'm lazy */
5794 switch (hfinfo->type) {
5796 format = "%s: 0x%02x";
5799 format = "%s: 0x%04x";
5802 format = "%s: 0x%06x";
5805 format = "%s: 0x%08x";
5808 DISSECTOR_ASSERT_NOT_REACHED();
5813 switch (hfinfo->type) {
5815 format = "%s: 0x%02x (%u)";
5818 format = "%s: 0x%04x (%u)";
5821 format = "%s: 0x%06x (%u)";
5824 format = "%s: 0x%08x (%u)";
5827 DISSECTOR_ASSERT_NOT_REACHED();
5832 DISSECTOR_ASSERT_NOT_REACHED();
5840 hfinfo_uint_value_format(const header_field_info *hfinfo)
5842 const char *format = NULL;
5844 /* Pick the proper format string */
5845 if (hfinfo->type == FT_FRAMENUM) {
5847 * Frame numbers are always displayed in decimal.
5851 switch (hfinfo->display) {
5856 switch (hfinfo->type) {
5858 format = "%u (0x%02x)";
5861 format = "%u (0x%04x)";
5864 format = "%u (0x%06x)";
5867 format = "%u (0x%08x)";
5870 DISSECTOR_ASSERT_NOT_REACHED();
5878 switch (hfinfo->type) {
5892 DISSECTOR_ASSERT_NOT_REACHED();
5897 switch (hfinfo->type) {
5899 format = "0x%02x (%u)";
5902 format = "0x%04x (%u)";
5905 format = "0x%06x (%u)";
5908 format = "0x%08x (%u)";
5911 DISSECTOR_ASSERT_NOT_REACHED();
5916 DISSECTOR_ASSERT_NOT_REACHED();
5924 hfinfo_int_vals_format(const header_field_info *hfinfo)
5926 const char *format = NULL;
5928 /* Get the underlying BASE_ value */
5929 switch (hfinfo->display & BASE_DISPLAY_E_MASK) {
5935 format = "%s: %s (%d)";
5937 case BASE_OCT: /* I'm lazy */
5938 format = "%s: %s (%#o)";
5942 switch (hfinfo->type) {
5944 format = "%s: %s (0x%02x)";
5947 format = "%s: %s (0x%04x)";
5950 format = "%s: %s (0x%06x)";
5953 format = "%s: %s (0x%08x)";
5956 DISSECTOR_ASSERT_NOT_REACHED();
5961 DISSECTOR_ASSERT_NOT_REACHED();
5968 hfinfo_uint64_format(const header_field_info *hfinfo)
5970 const char *format = NULL;
5972 /* Pick the proper format string */
5973 switch (hfinfo->display) {
5975 format = "%s: %" G_GINT64_MODIFIER "u";
5978 format = "%s: %" G_GINT64_MODIFIER "u (0x%016" G_GINT64_MODIFIER "x)";
5980 case BASE_OCT: /* I'm lazy */
5981 format = "%s: %#" G_GINT64_MODIFIER "o";
5984 format = "%s: 0x%016" G_GINT64_MODIFIER "x";
5987 format = "%s: 0x%016" G_GINT64_MODIFIER "x (%" G_GINT64_MODIFIER "u)";
5990 DISSECTOR_ASSERT_NOT_REACHED();
5997 hfinfo_int_format(const header_field_info *hfinfo)
5999 const char *format = NULL;
6001 /* Pick the proper format string */
6002 switch (hfinfo->display) {
6007 switch (hfinfo->type) {
6009 format = "%s: %d (0x%02x)";
6012 format = "%s: %d (0x%04x)";
6015 format = "%s: %d (0x%06x)";
6018 format = "%s: %d (0x%08x)";
6021 DISSECTOR_ASSERT_NOT_REACHED();
6025 case BASE_OCT: /* I'm lazy */
6029 switch (hfinfo->type) {
6031 format = "%s: 0x%02x";
6034 format = "%s: 0x%04x";
6037 format = "%s: 0x%06x";
6040 format = "%s: 0x%08x";
6043 DISSECTOR_ASSERT_NOT_REACHED();
6048 switch (hfinfo->type) {
6050 format = "%s: 0x%02x (%d)";
6053 format = "%s: 0x%04x (%d)";
6056 format = "%s: 0x%06x (%d)";
6059 format = "%s: 0x%08x (%d)";
6062 DISSECTOR_ASSERT_NOT_REACHED();
6067 DISSECTOR_ASSERT_NOT_REACHED();
6074 hfinfo_int_value_format(const header_field_info *hfinfo)
6076 const char *format = NULL;
6078 /* Pick the proper format string */
6079 switch (hfinfo->display) {
6084 switch (hfinfo->type) {
6086 format = "%d (0x%02x)";
6089 format = "%d (0x%04x)";
6092 format = "%d (0x%06x)";
6095 format = "%d (0x%08x)";
6098 DISSECTOR_ASSERT_NOT_REACHED();
6106 switch (hfinfo->type) {
6120 DISSECTOR_ASSERT_NOT_REACHED();
6125 switch (hfinfo->type) {
6127 format = "0x%02x (%d)";
6130 format = "0x%04x (%d)";
6133 format = "0x%06x (%d)";
6136 format = "0x%08x (%d)";
6139 DISSECTOR_ASSERT_NOT_REACHED();
6144 DISSECTOR_ASSERT_NOT_REACHED();
6151 hfinfo_int64_format(const header_field_info *hfinfo)
6153 const char *format = NULL;
6155 /* Pick the proper format string */
6156 switch (hfinfo->display) {
6158 format = "%s: %" G_GINT64_MODIFIER "d";
6161 format = "%s: %" G_GINT64_MODIFIER "d (0x%016" G_GINT64_MODIFIER "x)";
6163 case BASE_OCT: /* I'm lazy */
6164 format = "%s: %#" G_GINT64_MODIFIER "o";
6167 format = "%s: 0x%016" G_GINT64_MODIFIER "x";
6170 format = "%s: 0x%016" G_GINT64_MODIFIER "x (%" G_GINT64_MODIFIER "d)";
6173 DISSECTOR_ASSERT_NOT_REACHED();
6180 proto_registrar_n(void)
6182 return gpa_hfinfo.len;
6186 proto_registrar_get_name(const int n)
6188 header_field_info *hfinfo;
6190 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
6191 return hfinfo->name;
6195 proto_registrar_get_abbrev(const int n)
6197 header_field_info *hfinfo;
6199 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
6200 return hfinfo->abbrev;
6204 proto_registrar_get_ftype(const int n)
6206 header_field_info *hfinfo;
6208 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
6209 return hfinfo->type;
6213 proto_registrar_get_parent(const int n)
6215 header_field_info *hfinfo;
6217 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
6218 return hfinfo->parent;
6222 proto_registrar_is_protocol(const int n)
6224 header_field_info *hfinfo;
6226 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
6227 return (hfinfo->parent == -1 ? TRUE : FALSE);
6230 /* Returns length of field in packet (not necessarily the length
6231 * in our internal representation, as in the case of IPv4).
6232 * 0 means undeterminable at time of registration
6233 * -1 means the field is not registered. */
6235 proto_registrar_get_length(const int n)
6237 header_field_info *hfinfo;
6239 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
6240 return ftype_length(hfinfo->type);
6243 /* Looks for a protocol or a field in a proto_tree. Returns TRUE if
6244 * it exists anywhere, or FALSE if it exists nowhere. */
6246 proto_check_for_protocol_or_field(const proto_tree* tree, const int id)
6248 GPtrArray *ptrs = proto_get_finfo_ptr_array(tree, id);
6253 else if (g_ptr_array_len(ptrs) > 0) {
6261 /* Return GPtrArray* of field_info pointers for all hfindex that appear in tree.
6262 * This only works if the hfindex was "primed" before the dissection
6263 * took place, as we just pass back the already-created GPtrArray*.
6264 * The caller should *not* free the GPtrArray*; proto_tree_free_node()
6267 proto_get_finfo_ptr_array(const proto_tree *tree, const int id)
6272 if (PTREE_DATA(tree)->interesting_hfids != NULL)
6273 return g_hash_table_lookup(PTREE_DATA(tree)->interesting_hfids,
6274 GINT_TO_POINTER(id));
6280 proto_tracking_interesting_fields(const proto_tree *tree)
6285 return (PTREE_DATA(tree)->interesting_hfids != NULL);
6288 /* Helper struct for proto_find_info() and proto_all_finfos() */
6294 /* Helper function for proto_find_info() */
6296 find_finfo(proto_node *node, gpointer data)
6298 field_info *fi = PNODE_FINFO(node);
6299 if (fi && fi->hfinfo) {
6300 if (fi->hfinfo->id == ((ffdata_t*)data)->id) {
6301 g_ptr_array_add(((ffdata_t*)data)->array, fi);
6305 /* Don't stop traversing. */
6309 /* Return GPtrArray* of field_info pointers for all hfindex that appear in a tree.
6310 * This works on any proto_tree, primed or unprimed, but actually searches
6311 * the tree, so it is slower than using proto_get_finfo_ptr_array on a primed tree.
6312 * The caller does need to free the returned GPtrArray with
6313 * g_ptr_array_free(<array>, TRUE).
6316 proto_find_finfo(proto_tree *tree, const int id)
6320 ffdata.array = g_ptr_array_new();
6323 proto_tree_traverse_pre_order(tree, find_finfo, &ffdata);
6325 return ffdata.array;
6328 /* Helper function for proto_all_finfos() */
6330 every_finfo(proto_node *node, gpointer data)
6332 field_info *fi = PNODE_FINFO(node);
6333 if (fi && fi->hfinfo) {
6334 g_ptr_array_add(((ffdata_t*)data)->array, fi);
6337 /* Don't stop traversing. */
6341 /* Return GPtrArray* of field_info pointers containing all hfindexes that appear in a tree. */
6343 proto_all_finfos(proto_tree *tree)
6347 ffdata.array = g_ptr_array_new();
6350 proto_tree_traverse_pre_order(tree, every_finfo, &ffdata);
6352 return ffdata.array;
6363 check_for_offset(proto_node *node, const gpointer data)
6365 field_info *fi = PNODE_FINFO(node);
6366 offset_search_t *offsearch = data;
6368 /* !fi == the top most container node which holds nothing */
6369 if (fi && !PROTO_ITEM_IS_HIDDEN(node) && fi->ds_tvb && offsearch->tvb == fi->ds_tvb) {
6370 if (offsearch->offset >= (guint) fi->start &&
6371 offsearch->offset < (guint) (fi->start + fi->length)) {
6373 offsearch->finfo = fi;
6374 return FALSE; /* keep traversing */
6377 return FALSE; /* keep traversing */
6380 /* Search a proto_tree backwards (from leaves to root) looking for the field
6381 * whose start/length occupies 'offset' */
6382 /* XXX - I couldn't find an easy way to search backwards, so I search
6383 * forwards, w/o stopping. Therefore, the last finfo I find will the be
6384 * the one I want to return to the user. This algorithm is inefficient
6385 * and could be re-done, but I'd have to handle all the children and
6386 * siblings of each node myself. When I have more time I'll do that.
6389 proto_find_field_from_offset(proto_tree *tree, guint offset, tvbuff_t *tvb)
6391 offset_search_t offsearch;
6393 offsearch.offset = offset;
6394 offsearch.finfo = NULL;
6395 offsearch.tvb = tvb;
6397 proto_tree_traverse_pre_order(tree, check_for_offset, &offsearch);
6399 return offsearch.finfo;
6402 /* Dumps the protocols in the registration database to stdout. An independent
6403 * program can take this output and format it into nice tables or HTML or
6406 * There is one record per line. The fields are tab-delimited.
6408 * Field 1 = protocol name
6409 * Field 2 = protocol short name
6410 * Field 3 = protocol filter name
6413 proto_registrar_dump_protocols(void)
6415 protocol_t *protocol;
6417 void *cookie = NULL;
6420 i = proto_get_first_protocol(&cookie);
6422 protocol = find_protocol_by_id(i);
6423 printf("%s\t%s\t%s\n", protocol->name, protocol->short_name,
6424 protocol->filter_name);
6425 i = proto_get_next_protocol(&cookie);
6429 /* Dumps the value_strings, extended value string headers, range_strings
6430 * or true/false strings for fields that have them.
6431 * There is one record per line. Fields are tab-delimited.
6432 * There are four types of records: Value String, Extended Value String Header,
6433 * Range String and True/False String. The first field, 'V', 'E', 'R' or 'T', indicates
6434 * the type of record.
6436 * Note that a record will be generated only if the value_string,... is referenced
6437 * in a registered hfinfo entry.
6443 * Field 2 = Field abbreviation to which this value string corresponds
6444 * Field 3 = Integer value
6447 * Extended Value String Headers
6448 * -----------------------------
6450 * Field 2 = Field abbreviation to which this extended value string header corresponds
6451 * Field 3 = Extended Value String "Name"
6452 * Field 4 = Number of entries in the associated value_string array
6453 * Field 5 = Access Type: "Linear Search", "Binary Search", "Direct (indexed) Access"
6458 * Field 2 = Field abbreviation to which this range string corresponds
6459 * Field 3 = Integer value: lower bound
6460 * Field 4 = Integer value: upper bound
6463 * True/False Strings
6464 * ------------------
6466 * Field 2 = Field abbreviation to which this true/false string corresponds
6467 * Field 3 = True String
6468 * Field 4 = False String
6471 proto_registrar_dump_values(void)
6473 header_field_info *hfinfo;
6475 const value_string *vals;
6476 const range_string *range;
6477 const true_false_string *tfs;
6479 len = gpa_hfinfo.len;
6480 for (i = 0; i < len ; i++) {
6481 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
6483 if (hfinfo->id == hf_text_only) {
6487 /* ignore protocols */
6488 if (proto_registrar_is_protocol(i)) {
6491 /* process header fields */
6494 * If this field isn't at the head of the list of
6495 * fields with this name, skip this field - all
6496 * fields with the same name are really just versions
6497 * of the same field stored in different bits, and
6498 * should have the same type/radix/value list, and
6499 * just differ in their bit masks. (If a field isn't
6500 * a bitfield, but can be, say, 1 or 2 bytes long,
6501 * it can just be made FT_UINT16, meaning the
6502 * *maximum* length is 2 bytes, and be used
6505 if (hfinfo->same_name_prev != NULL)
6512 if (hfinfo->strings != NULL) {
6513 if ((hfinfo->display & BASE_DISPLAY_E_MASK) != BASE_CUSTOM &&
6514 (hfinfo->type == FT_UINT8 ||
6515 hfinfo->type == FT_UINT16 ||
6516 hfinfo->type == FT_UINT24 ||
6517 hfinfo->type == FT_UINT32 ||
6518 hfinfo->type == FT_UINT64 ||
6519 hfinfo->type == FT_INT8 ||
6520 hfinfo->type == FT_INT16 ||
6521 hfinfo->type == FT_INT24 ||
6522 hfinfo->type == FT_INT32 ||
6523 hfinfo->type == FT_INT64)) {
6525 if (hfinfo->display & BASE_EXT_STRING) {
6526 vals = VALUE_STRING_EXT_VS_P((value_string_ext *)hfinfo->strings);
6527 } else if ((hfinfo->display & BASE_RANGE_STRING) == 0) {
6528 vals = hfinfo->strings;
6530 range = hfinfo->strings;
6533 else if (hfinfo->type == FT_BOOLEAN) {
6534 tfs = hfinfo->strings;
6538 /* Print value strings? */
6540 if (hfinfo->display & BASE_EXT_STRING) {
6541 value_string_ext *vse_p = (value_string_ext *)hfinfo->strings;
6542 if (!value_string_ext_validate(vse_p)) {
6543 g_warning("Invalid value_string_ext ptr for: %s", hfinfo->abbrev);
6546 match_strval_ext(0, vse_p); /* "prime" the extended value_string */
6547 printf("E\t%s\t%d\t%s\t%s\n",
6549 VALUE_STRING_EXT_VS_NUM_ENTRIES(vse_p),
6550 VALUE_STRING_EXT_VS_NAME(vse_p),
6551 value_string_ext_match_type_str(vse_p));
6554 while (vals[vi].strptr) {
6555 /* Print in the proper base */
6556 if (hfinfo->display == BASE_HEX) {
6557 printf("V\t%s\t0x%x\t%s\n",
6563 printf("V\t%s\t%u\t%s\n",
6572 /* print range strings? */
6575 while (range[vi].strptr) {
6576 /* Print in the proper base */
6577 if ((hfinfo->display & BASE_DISPLAY_E_MASK) == BASE_HEX) {
6578 printf("R\t%s\t0x%x\t0x%x\t%s\n",
6580 range[vi].value_min,
6581 range[vi].value_max,
6585 printf("R\t%s\t%u\t%u\t%s\n",
6587 range[vi].value_min,
6588 range[vi].value_max,
6595 /* Print true/false strings? */
6597 printf("T\t%s\t%s\t%s\n", hfinfo->abbrev,
6598 tfs->true_string, tfs->false_string);
6604 /* Dumps the contents of the registration database to stdout. An independent
6605 * program can take this output and format it into nice tables or HTML or
6608 * There is one record per line. Each record is either a protocol or a header
6609 * field, differentiated by the first field. The fields are tab-delimited.
6614 * Field 2 = descriptive protocol name
6615 * Field 3 = protocol abbreviation
6621 * Field 2 = descriptive field name
6622 * Field 3 = field abbreviation
6623 * Field 4 = type ( textual representation of the the ftenum type )
6624 * Field 5 = parent protocol abbreviation
6625 * Field 6 = blurb describing field
6629 * Field 2 = descriptive field name
6630 * Field 3 = field abbreviation
6631 * Field 4 = type ( textual representation of the the ftenum type )
6632 * Field 5 = parent protocol abbreviation
6633 * Field 6 = blurb describing field
6634 * Field 7 = base for display (for integer types); "parent bitfield width" for FT_BOOLEAN
6635 * Field 8 = blurb describing field (yes, apparently we repeated this accidentally)
6639 * Field 2 = descriptive field name
6640 * Field 3 = field abbreviation
6641 * Field 4 = type ( textual representation of the the ftenum type )
6642 * Field 5 = parent protocol abbreviation
6643 * Field 6 = blurb describing field
6644 * Field 7 = base for display (for integer types); "parent bitfield width" for FT_BOOLEAN
6645 * Field 8 = bitmask: format: hex: 0x....
6648 proto_registrar_dump_fields(const int format)
6650 header_field_info *hfinfo, *parent_hfinfo;
6652 const char *enum_name;
6653 const char *base_name;
6657 len = gpa_hfinfo.len;
6658 for (i = 0; i < len ; i++) {
6659 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
6662 * Skip the pseudo-field for "proto_tree_add_text()" since
6663 * we don't want it in the list of filterable fields.
6665 if (hfinfo->id == hf_text_only)
6668 /* format for protocols */
6669 if (proto_registrar_is_protocol(i)) {
6670 printf("P\t%s\t%s\n", hfinfo->name, hfinfo->abbrev);
6672 /* format for header fields */
6675 * If this field isn't at the head of the list of
6676 * fields with this name, skip this field - all
6677 * fields with the same name are really just versions
6678 * of the same field stored in different bits, and
6679 * should have the same type/radix/value list, and
6680 * just differ in their bit masks. (If a field isn't
6681 * a bitfield, but can be, say, 1 or 2 bytes long,
6682 * it can just be made FT_UINT16, meaning the
6683 * *maximum* length is 2 bytes, and be used
6686 if (hfinfo->same_name_prev != NULL)
6689 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
6691 enum_name = ftype_name(hfinfo->type);
6695 if (hfinfo->type == FT_UINT8 ||
6696 hfinfo->type == FT_UINT16 ||
6697 hfinfo->type == FT_UINT24 ||
6698 hfinfo->type == FT_UINT32 ||
6699 hfinfo->type == FT_UINT64 ||
6700 hfinfo->type == FT_INT8 ||
6701 hfinfo->type == FT_INT16 ||
6702 hfinfo->type == FT_INT24 ||
6703 hfinfo->type == FT_INT32 ||
6704 hfinfo->type == FT_INT64) {
6707 switch (hfinfo->display & BASE_DISPLAY_E_MASK) {
6709 base_name = "BASE_NONE";
6712 base_name = "BASE_DEC";
6715 base_name = "BASE_HEX";
6718 base_name = "BASE_OCT";
6721 base_name = "BASE_DEC_HEX";
6724 base_name = "BASE_HEX_DEC";
6727 base_name = "BASE_CUSTOM";
6733 } else if (hfinfo->type == FT_BOOLEAN) {
6734 /* For FT_BOOLEAN: 'display' can be "parent bitfield width" */
6735 g_snprintf(width, sizeof(width), "%d", hfinfo->display);
6740 blurb = hfinfo->blurb;
6743 else if (strlen(blurb) == 0)
6746 printf("F\t%s\t%s\t%s\t%s\t%s\n",
6747 hfinfo->name, hfinfo->abbrev, enum_name,
6748 parent_hfinfo->abbrev, blurb);
6750 else if (format == 2) {
6751 printf("F\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n",
6752 hfinfo->name, hfinfo->abbrev, enum_name,
6753 parent_hfinfo->abbrev, blurb,
6756 else if (format == 3) {
6757 printf("F\t%s\t%s\t%s\t%s\t%s\t%s\t0x%x\n",
6758 hfinfo->name, hfinfo->abbrev, enum_name,
6759 parent_hfinfo->abbrev, blurb,
6760 base_name, hfinfo->bitmask);
6763 g_assert_not_reached();
6769 /* Dumps field types and descriptive names to stdout. An independent
6770 * program can take this output and format it into nice tables or HTML or
6773 * There is one record per line. The fields are tab-delimited.
6775 * Field 1 = field type name, e.g. FT_UINT8
6776 * Field 2 = descriptive name, e.g. "Unsigned, 1 byte"
6779 proto_registrar_dump_ftypes(void)
6783 for (fte = 0; fte < FT_NUM_TYPES; fte++) {
6784 printf("%s\t%s\n", ftype_name(fte), ftype_pretty_name(fte));
6789 hfinfo_numeric_format(const header_field_info *hfinfo)
6791 const char *format = NULL;
6793 /* Pick the proper format string */
6794 if (hfinfo->type == FT_FRAMENUM) {
6796 * Frame numbers are always displayed in decimal.
6798 format = "%s == %u";
6800 /* Get the underlying BASE_ value */
6801 switch (hfinfo->display & BASE_DISPLAY_E_MASK) {
6804 case BASE_OCT: /* I'm lazy */
6806 switch (hfinfo->type) {
6811 format = "%s == %u";
6814 format = "%s == %" G_GINT64_MODIFIER "u";
6820 format = "%s == %d";
6823 format = "%s == %" G_GINT64_MODIFIER "d";
6826 DISSECTOR_ASSERT_NOT_REACHED();
6832 switch (hfinfo->type) {
6835 format = "%s == 0x%02x";
6839 format = "%s == 0x%04x";
6843 format = "%s == 0x%06x";
6847 format = "%s == 0x%08x";
6851 format = "%s == 0x%016" G_GINT64_MODIFIER "x";
6854 DISSECTOR_ASSERT_NOT_REACHED();
6859 DISSECTOR_ASSERT_NOT_REACHED();
6867 hfinfo_numeric_value_format(const header_field_info *hfinfo)
6869 const char *format = NULL;
6871 /* Pick the proper format string */
6872 if (hfinfo->type == FT_FRAMENUM) {
6874 * Frame numbers are always displayed in decimal.
6878 /* Get the underlying BASE_ value */
6879 switch (hfinfo->display & BASE_DISPLAY_E_MASK) {
6883 case BASE_OCT: /* I'm lazy */
6885 switch (hfinfo->type) {
6893 format = "%" G_GINT64_MODIFIER "u";
6902 format = "%" G_GINT64_MODIFIER "d";
6905 DISSECTOR_ASSERT_NOT_REACHED();
6911 switch (hfinfo->type) {
6930 format = "0x%016" G_GINT64_MODIFIER "x";
6933 DISSECTOR_ASSERT_NOT_REACHED();
6938 DISSECTOR_ASSERT_NOT_REACHED();
6945 /* This function indicates whether it's possible to construct a
6946 * "match selected" display filter string for the specified field,
6947 * returns an indication of whether it's possible, and, if it's
6948 * possible and "filter" is non-null, constructs the filter and
6949 * sets "*filter" to point to it.
6950 * You do not need to [g_]free() this string since it will be automatically
6951 * freed once the next packet is dissected.
6954 construct_match_selected_string(field_info *finfo, epan_dissect_t *edt,
6957 header_field_info *hfinfo;
6963 gint start, length, length_remaining;
6965 gchar is_signed_num = FALSE;
6967 hfinfo = finfo->hfinfo;
6968 DISSECTOR_ASSERT(hfinfo);
6969 abbrev_len = (int) strlen(hfinfo->abbrev);
6971 if (hfinfo->strings && (hfinfo->display & BASE_DISPLAY_E_MASK) == BASE_NONE) {
6972 const gchar *str = NULL;
6974 switch (hfinfo->type) {
6980 if (hfinfo->display & BASE_RANGE_STRING) {
6981 str = match_strrval(fvalue_get_sinteger(&finfo->value), hfinfo->strings);
6982 } else if (hfinfo->display & BASE_EXT_STRING) {
6983 str = match_strval_ext(fvalue_get_sinteger(&finfo->value), hfinfo->strings);
6985 str = match_strval(fvalue_get_sinteger(&finfo->value), hfinfo->strings);
6993 if (hfinfo->display & BASE_RANGE_STRING) {
6994 str = match_strrval(fvalue_get_uinteger(&finfo->value), hfinfo->strings);
6995 } else if (hfinfo->display & BASE_EXT_STRING) {
6996 str = match_strval_ext(fvalue_get_uinteger(&finfo->value), hfinfo->strings);
6998 str = match_strval(fvalue_get_uinteger(&finfo->value), hfinfo->strings);
7006 if (str != NULL && filter != NULL) {
7007 *filter = ep_strdup_printf("%s == \"%s\"", hfinfo->abbrev, str);
7013 * XXX - we can't use the "val_to_string_repr" and "string_repr_len"
7014 * functions for FT_UINT and FT_INT types, as we choose the base in
7015 * the string expression based on the display base of the field.
7017 * Note that the base does matter, as this is also used for
7018 * the protocolinfo tap.
7020 * It might be nice to use them in "proto_item_fill_label()"
7021 * as well, although, there, you'd have to deal with the base
7022 * *and* with resolved values for addresses.
7024 * Perhaps we need two different val_to_string routines, one
7025 * to generate items for display filters and one to generate
7026 * strings for display, and pass to both of them the
7027 * "display" and "strings" values in the header_field_info
7028 * structure for the field, so they can get the base and,
7029 * if the field is Boolean or an enumerated integer type,
7030 * the tables used to generate human-readable values.
7032 switch (hfinfo->type) {
7038 is_signed_num = TRUE;
7044 if (filter != NULL) {
7045 format = hfinfo_numeric_format(hfinfo);
7046 if (is_signed_num) {
7047 *filter = ep_strdup_printf(format,
7049 fvalue_get_sinteger(&finfo->value));
7051 *filter = ep_strdup_printf(format,
7053 fvalue_get_uinteger(&finfo->value));
7059 DISSECTOR_ASSERT(!is_signed_num);
7060 if (filter != NULL) {
7061 format = hfinfo_numeric_format(hfinfo);
7062 *filter = ep_strdup_printf(format,
7064 fvalue_get_uinteger(&finfo->value));
7070 if (filter != NULL) {
7071 format = hfinfo_numeric_format(hfinfo);
7072 *filter = ep_strdup_printf(format,
7074 fvalue_get_integer64(&finfo->value));
7080 *filter = ep_strdup(finfo->hfinfo->abbrev);
7085 * If the length is 0, just match the name of the
7088 * (Also check for negative values, just in case,
7089 * as we'll cast it to an unsigned value later.)
7091 length = finfo->length;
7094 *filter = ep_strdup(finfo->hfinfo->abbrev);
7101 * This doesn't have a value, so we'd match
7102 * on the raw bytes at this address.
7104 * Should we be allowed to access to the raw bytes?
7105 * If "edt" is NULL, the answer is "no".
7111 * Is this field part of the raw frame tvbuff?
7112 * If not, we can't use "frame[N:M]" to match
7115 * XXX - should this be frame-relative, or
7116 * protocol-relative?
7118 * XXX - does this fallback for non-registered
7119 * fields even make sense?
7121 if (finfo->ds_tvb != edt->tvb)
7122 return FALSE; /* you lose */
7125 * Don't go past the end of that tvbuff.
7127 length_remaining = tvb_length_remaining(finfo->ds_tvb, finfo->start);
7128 if (length > length_remaining)
7129 length = length_remaining;
7133 if (filter != NULL) {
7134 start = finfo->start;
7135 buf_len = 32 + length * 3;
7136 *filter = ep_alloc0(buf_len);
7139 ptr += g_snprintf(ptr, (gulong) (buf_len-(ptr-*filter)),
7140 "frame[%d:%d] == ", finfo->start, length);
7141 for (i=0; i<length; i++) {
7142 c = tvb_get_guint8(finfo->ds_tvb, start);
7145 ptr += g_snprintf(ptr, (gulong) (buf_len-(ptr-*filter)), "%02x", c);
7148 ptr += g_snprintf(ptr, (gulong) (buf_len-(ptr-*filter)), ":%02x", c);
7155 /* FT_PCRE never appears as a type for a registered field. It is
7156 * only used internally. */
7157 DISSECTOR_ASSERT_NOT_REACHED();
7160 /* By default, use the fvalue's "to_string_repr" method. */
7162 /* Figure out the string length needed.
7163 * The ft_repr length.
7164 * 4 bytes for " == ".
7165 * 1 byte for trailing NUL.
7167 if (filter != NULL) {
7168 dfilter_len = fvalue_string_repr_len(&finfo->value,
7170 dfilter_len += abbrev_len + 4 + 1;
7171 *filter = ep_alloc0(dfilter_len);
7173 /* Create the string */
7174 g_snprintf(*filter, dfilter_len, "%s == ",
7176 fvalue_to_string_repr(&finfo->value,
7178 &(*filter)[abbrev_len + 4]);
7187 * Returns TRUE if we can do a "match selected" on the field, FALSE
7191 proto_can_match_selected(field_info *finfo, epan_dissect_t *edt)
7193 return construct_match_selected_string(finfo, edt, NULL);
7196 /* This function attempts to construct a "match selected" display filter
7197 * string for the specified field; if it can do so, it returns a pointer
7198 * to the string, otherwise it returns NULL.
7200 * The string is allocated with packet lifetime scope.
7201 * You do not need to [g_]free() this string since it will be automatically
7202 * freed once the next packet is dissected.
7205 proto_construct_match_selected_string(field_info *finfo, epan_dissect_t *edt)
7209 if (!construct_match_selected_string(finfo, edt, &filter))
7214 /* This function is common code for both proto_tree_add_bitmask() and
7215 * proto_tree_add_bitmask_text() functions.
7218 /* NOTE: to support code written when proto_tree_add_bitmask() and
7219 * proto_tree_add_bitmask_text took a
7220 * gboolean as its last argument, with FALSE meaning "big-endian"
7221 * and TRUE meaning "little-endian", we treat any non-zero value of
7222 * "encoding" as meaning "little-endian".
7225 proto_item_add_bitmask_tree(proto_item *item, tvbuff_t *tvb, const int offset,
7226 const int len, const gint ett, const int **fields,
7227 const guint encoding, const int flags,
7232 proto_tree *tree = NULL;
7233 header_field_info *hf;
7238 value = tvb_get_guint8(tvb, offset);
7241 value = encoding ? tvb_get_letohs(tvb, offset) :
7242 tvb_get_ntohs(tvb, offset);
7245 value = encoding ? tvb_get_letoh24(tvb, offset) :
7246 tvb_get_ntoh24(tvb, offset);
7249 value = encoding ? tvb_get_letohl(tvb, offset) :
7250 tvb_get_ntohl(tvb, offset);
7253 g_assert_not_reached();
7256 tree = proto_item_add_subtree(item, ett);
7258 proto_tree_add_item(tree, **fields, tvb, offset, len, encoding);
7259 if (flags & BMT_NO_APPEND) {
7263 hf = proto_registrar_get_nth(**fields);
7264 DISSECTOR_ASSERT(hf->bitmask != 0);
7265 tmpval = (value & hf->bitmask) >> hf->bitshift;
7276 DISSECTOR_ASSERT(len == ftype_length(hf->type));
7278 if (hf->display == BASE_CUSTOM) {
7279 gchar lbl[ITEM_LABEL_LENGTH];
7280 custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hf->strings;
7282 DISSECTOR_ASSERT(fmtfunc);
7283 fmtfunc(lbl, tmpval);
7284 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
7288 else if (hf->strings) {
7289 if (hf->display & BASE_RANGE_STRING) {
7290 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
7291 hf->name, rval_to_str(tmpval, hf->strings, "Unknown"));
7292 } else if (hf->display & BASE_EXT_STRING) {
7293 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
7294 hf->name, val_to_str_ext_const(tmpval, (value_string_ext *) (hf->strings), "Unknown"));
7296 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
7297 hf->name, val_to_str_const(tmpval, cVALS(hf->strings), "Unknown"));
7301 else if (!(flags & BMT_NO_INT)) {
7303 proto_item_append_text(item, ", ");
7306 fmt = IS_FT_INT(hf->type) ? hfinfo_int_format(hf) : hfinfo_uint_format(hf);
7307 if (IS_BASE_DUAL(hf->display)) {
7308 proto_item_append_text(item, fmt, hf->name, tmpval, tmpval);
7310 proto_item_append_text(item, fmt, hf->name, tmpval);
7317 DISSECTOR_ASSERT(len * 8 == hf->display);
7319 if (hf->strings && !(flags & BMT_NO_TFS)) {
7320 /* If we have true/false strings, emit full - otherwise messages
7322 const struct true_false_string *tfs =
7323 (const struct true_false_string *)hf->strings;
7326 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
7327 hf->name, tfs->true_string);
7329 } else if (!(flags & BMT_NO_FALSE)) {
7330 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
7331 hf->name, tfs->false_string);
7334 } else if (hf->bitmask & value) {
7335 /* If the flag is set, show the name */
7336 proto_item_append_text(item, "%s%s", first ? "" : ", ", hf->name);
7341 g_assert_not_reached();
7350 /* This function will dissect a sequence of bytes that describe a
7352 * hf_hdr is a 8/16/24/32 bit integer that describes the bitmask to be dissected.
7353 * This field will form an expansion under which the individual fields of the
7354 * bitmask is dissected and displayed.
7355 * This field must be of the type FT_[U]INT{8|16|24|32}.
7357 * fields is an array of pointers to int that lists all the fields of the
7358 * bitmask. These fields can be either of the type FT_BOOLEAN for flags
7359 * or another integer of the same type/size as hf_hdr with a mask specified.
7360 * This array is terminated by a NULL entry.
7362 * FT_BOOLEAN bits that are set to 1 will have the name added to the expansion.
7363 * FT_integer fields that have a value_string attached will have the
7364 * matched string displayed on the expansion line.
7367 proto_tree_add_bitmask(proto_tree *parent_tree, tvbuff_t *tvb,
7368 const guint offset, const int hf_hdr,
7369 const gint ett, const int **fields,
7370 const guint encoding)
7372 proto_item *item = NULL;
7373 header_field_info *hf;
7376 hf = proto_registrar_get_nth(hf_hdr);
7377 DISSECTOR_ASSERT(IS_FT_INT(hf->type) || IS_FT_UINT(hf->type));
7378 len = ftype_length(hf->type);
7381 item = proto_tree_add_item(parent_tree, hf_hdr, tvb, offset, len, encoding);
7382 proto_item_add_bitmask_tree(item, tvb, offset, len, ett, fields, encoding,
7383 BMT_NO_INT|BMT_NO_TFS, FALSE);
7389 /* The same as proto_tree_add_bitmask(), but using an arbitrary text as a top-level item */
7391 proto_tree_add_bitmask_text(proto_tree *parent_tree, tvbuff_t *tvb,
7392 const guint offset, const guint len,
7393 const char *name, const char *fallback,
7394 const gint ett, const int **fields,
7395 const guint encoding, const int flags)
7397 proto_item *item = NULL;
7400 item = proto_tree_add_text(parent_tree, tvb, offset, len, "%s", name ? name : "");
7401 if (proto_item_add_bitmask_tree(item, tvb, offset, len, ett, fields, encoding,
7402 flags, TRUE) && fallback) {
7403 /* Still at first item - append 'fallback' text if any */
7404 proto_item_append_text(item, "%s", fallback);
7412 proto_tree_add_bits_item(proto_tree *tree, const int hf_index, tvbuff_t *tvb,
7413 const guint bit_offset, const gint no_of_bits,
7414 const guint encoding)
7416 header_field_info *hfinfo;
7418 TRY_TO_FAKE_THIS_ITEM(tree, hf_index, hfinfo);
7420 return proto_tree_add_bits_ret_val(tree, hf_index, tvb, bit_offset, no_of_bits, NULL, encoding);
7424 * This function will dissect a sequence of bits that does not need to be byte aligned; the bits
7425 * set will be shown in the tree as ..10 10.. and the integer value returned if return_value is set.
7426 * Offset should be given in bits from the start of the tvb.
7430 _proto_tree_add_bits_ret_val(proto_tree *tree, const int hf_index, tvbuff_t *tvb,
7431 const guint bit_offset, const gint no_of_bits,
7432 guint64 *return_value, const guint encoding)
7438 char lbl_str[ITEM_LABEL_LENGTH];
7442 header_field_info *hf_field;
7444 const true_false_string *tfstring;
7446 /* We can't fake it just yet. We have to fill in the 'return_value' parameter */
7447 PROTO_REGISTRAR_GET_NTH(hf_index, hf_field);
7449 if (hf_field->bitmask != 0) {
7450 REPORT_DISSECTOR_BUG(ep_strdup_printf("Incompatible use of proto_tree_add_bits_ret_val"
7451 " with field '%s' (%s) with bitmask != 0",
7452 hf_field->abbrev, hf_field->name));
7455 DISSECTOR_ASSERT(no_of_bits > 0);
7457 /* Byte align offset */
7458 offset = bit_offset>>3;
7461 * Calculate the number of octets used to hold the bits
7463 tot_no_bits = ((bit_offset&0x7) + no_of_bits);
7464 length = tot_no_bits>>3;
7465 /* If we are using part of the next octet, increase length by 1 */
7466 if (tot_no_bits & 0x07)
7469 if (no_of_bits < 65) {
7470 value = tvb_get_bits64(tvb, bit_offset, no_of_bits, encoding);
7472 DISSECTOR_ASSERT_NOT_REACHED();
7476 /* Sign extend for signed types */
7477 switch (hf_field->type) {
7483 if (value & (G_GINT64_CONSTANT(1) << (no_of_bits-1)))
7484 value |= (G_GINT64_CONSTANT(-1) << no_of_bits);
7492 *return_value = value;
7495 /* Coast clear. Try and fake it */
7496 TRY_TO_FAKE_THIS_ITEM(tree, hf_index, hf_field);
7498 bf_str = decode_bits_in_field(bit_offset, no_of_bits, value);
7500 switch (hf_field->type) {
7503 tfstring = (const true_false_string *) &tfs_true_false;
7504 if (hf_field->strings)
7505 tfstring = (const true_false_string *)hf_field->strings;
7506 return proto_tree_add_boolean_format(tree, hf_index, tvb, offset, length, (guint32)value,
7508 bf_str, hf_field->name,
7509 (guint32)value ? tfstring->true_string : tfstring->false_string);
7516 pi = proto_tree_add_uint(tree, hf_index, tvb, offset, length, (guint32)value);
7517 fill_label_uint(PITEM_FINFO(pi), lbl_str);
7524 pi = proto_tree_add_int(tree, hf_index, tvb, offset, length, (gint32)value);
7525 fill_label_int(PITEM_FINFO(pi), lbl_str);
7529 pi = proto_tree_add_uint64(tree, hf_index, tvb, offset, length, value);
7530 fill_label_uint64(PITEM_FINFO(pi), lbl_str);
7534 pi = proto_tree_add_int64(tree, hf_index, tvb, offset, length, (gint64)value);
7535 fill_label_int64(PITEM_FINFO(pi), lbl_str);
7539 DISSECTOR_ASSERT_NOT_REACHED();
7544 proto_item_set_text(pi, "%s = %s", bf_str, lbl_str);
7549 proto_tree_add_split_bits_item_ret_val(proto_tree *tree, const int hf_index, tvbuff_t *tvb,
7550 const guint bit_offset, const crumb_spec_t *crumb_spec,
7551 guint64 *return_value)
7556 guint mask_initial_bit_offset;
7557 guint mask_greatest_bit_offset;
7561 char lbl_str[ITEM_LABEL_LENGTH];
7563 guint64 composite_bitmask;
7564 guint64 composite_bitmap;
7566 header_field_info *hf_field;
7567 const true_false_string *tfstring;
7569 /* We can't fake it just yet. We have to fill in the 'return_value' parameter */
7570 PROTO_REGISTRAR_GET_NTH(hf_index, hf_field);
7572 if (hf_field->bitmask != 0) {
7573 REPORT_DISSECTOR_BUG(ep_strdup_printf(
7574 "Incompatible use of proto_tree_add_split_bits_item_ret_val"
7575 " with field '%s' (%s) with bitmask != 0",
7576 hf_field->abbrev, hf_field->name));
7579 mask_initial_bit_offset = bit_offset % 8;
7584 mask_greatest_bit_offset = 0;
7585 composite_bitmask = 0;
7586 composite_bitmap = 0;
7588 while (crumb_spec[i].crumb_bit_length != 0) {
7589 guint64 crumb_mask, crumb_value;
7590 guint8 crumb_end_bit_offset;
7592 DISSECTOR_ASSERT(i < 64);
7593 crumb_value = tvb_get_bits64(tvb,
7594 bit_offset + crumb_spec[i].crumb_bit_offset,
7595 crumb_spec[i].crumb_bit_length,
7597 value += crumb_value;
7598 no_of_bits += crumb_spec[i].crumb_bit_length;
7600 /* The bitmask is 64 bit, left-aligned, starting at the first bit of the
7601 octet containing the initial offset.
7602 If the mask is beyond 32 bits, then give up on bit map display.
7603 This could be improved in future, probably showing a table
7604 of 32 or 64 bits per row */
7605 if (mask_greatest_bit_offset < 32) {
7606 crumb_end_bit_offset = mask_initial_bit_offset
7607 + crumb_spec[i].crumb_bit_offset
7608 + crumb_spec[i].crumb_bit_length;
7609 crumb_mask = (G_GUINT64_CONSTANT(1) << crumb_spec[i].crumb_bit_length) - 1;
7611 if (crumb_end_bit_offset > mask_greatest_bit_offset) {
7612 mask_greatest_bit_offset = crumb_end_bit_offset;
7614 composite_bitmask |= (crumb_mask << (64 - crumb_end_bit_offset));
7615 composite_bitmap |= (crumb_value << (64 - crumb_end_bit_offset));
7617 /* Shift left for the next segment */
7618 value <<= crumb_spec[++i].crumb_bit_length;
7621 /* Sign extend for signed types */
7622 switch (hf_field->type) {
7628 if (value & no_of_bits && (G_GINT64_CONSTANT(1) << (no_of_bits-1)))
7629 value |= (G_GINT64_CONSTANT(-1) << no_of_bits);
7636 *return_value = value;
7639 /* Coast clear. Try and fake it */
7640 TRY_TO_FAKE_THIS_ITEM(tree, hf_index, hf_field);
7642 /* initialise the format string */
7643 bf_str = ep_alloc(256);
7646 octet_offset = bit_offset >> 3;
7648 /* Round up mask length to nearest octet */
7649 octet_length = ((mask_greatest_bit_offset + 7) >> 3);
7650 mask_greatest_bit_offset = octet_length << 3;
7652 /* As noted above, we currently only produce a bitmap if the crumbs span less than 4 octets of the tvb.
7653 It would be a useful enhancement to eliminate this restriction. */
7654 if (mask_greatest_bit_offset <= 32) {
7655 other_decode_bitfield_value(bf_str,
7656 (guint32)(composite_bitmap >> (64 - mask_greatest_bit_offset)),
7657 (guint32)(composite_bitmask >> (64 - mask_greatest_bit_offset)),
7658 mask_greatest_bit_offset);
7661 switch (hf_field->type) {
7662 case FT_BOOLEAN: /* it is a bit odd to have a boolean encoded as split-bits, but possible, I suppose? */
7664 tfstring = (const true_false_string *) &tfs_true_false;
7665 if (hf_field->strings)
7666 tfstring = (const true_false_string *) hf_field->strings;
7667 return proto_tree_add_boolean_format(tree, hf_index,
7668 tvb, octet_offset, octet_length, (guint32)value,
7670 bf_str, hf_field->name,
7671 (guint32)value ? tfstring->true_string : tfstring->false_string);
7678 pi = proto_tree_add_uint(tree, hf_index, tvb, octet_offset, octet_length, (guint32)value);
7679 fill_label_uint(PITEM_FINFO(pi), lbl_str);
7686 pi = proto_tree_add_int(tree, hf_index, tvb, octet_offset, octet_length, (gint32)value);
7687 fill_label_int(PITEM_FINFO(pi), lbl_str);
7691 pi = proto_tree_add_uint64(tree, hf_index, tvb, octet_offset, octet_length, value);
7692 fill_label_uint64(PITEM_FINFO(pi), lbl_str);
7696 pi = proto_tree_add_int64(tree, hf_index, tvb, octet_offset, octet_length, (gint64)value);
7697 fill_label_int64(PITEM_FINFO(pi), lbl_str);
7701 DISSECTOR_ASSERT_NOT_REACHED();
7705 proto_item_set_text(pi, "%s = %s", bf_str, lbl_str);
7710 proto_tree_add_split_bits_crumb(proto_tree *tree, const int hf_index, tvbuff_t *tvb, const guint bit_offset,
7711 const crumb_spec_t *crumb_spec, guint16 crumb_index)
7713 header_field_info *hf_info;
7715 PROTO_REGISTRAR_GET_NTH(hf_index, hf_info);
7716 proto_tree_add_text(tree, tvb,
7718 ((bit_offset + crumb_spec[crumb_index].crumb_bit_length - 1) >> 3) - (bit_offset >> 3) + 1,
7719 "%s crumb %d of %s (decoded above)",
7720 decode_bits_in_field(bit_offset, crumb_spec[crumb_index].crumb_bit_length,
7723 crumb_spec[crumb_index].crumb_bit_length,
7730 proto_tree_add_bits_ret_val(proto_tree *tree, const int hf_index, tvbuff_t *tvb,
7731 const guint bit_offset, const gint no_of_bits,
7732 guint64 *return_value, const guint encoding)
7736 if ((item = _proto_tree_add_bits_ret_val(tree, hf_index, tvb,
7737 bit_offset, no_of_bits,
7738 return_value, encoding))) {
7739 FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_OFFSET(bit_offset));
7740 FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_SIZE(no_of_bits));
7746 _proto_tree_add_bits_format_value(proto_tree *tree, const int hf_index,
7747 tvbuff_t *tvb, const guint bit_offset,
7748 const gint no_of_bits, void *value_ptr,
7756 header_field_info *hf_field;
7758 /* We do not have to return a value, try to fake it as soon as possible */
7759 TRY_TO_FAKE_THIS_ITEM(tree, hf_index, hf_field);
7761 if (hf_field->bitmask != 0) {
7762 REPORT_DISSECTOR_BUG(ep_strdup_printf(
7763 "Incompatible use of proto_tree_add_bits_format_value"
7764 " with field '%s' (%s) with bitmask != 0",
7765 hf_field->abbrev, hf_field->name));
7768 DISSECTOR_ASSERT(no_of_bits > 0);
7770 /* Byte align offset */
7771 offset = bit_offset>>3;
7774 * Calculate the number of octets used to hold the bits
7776 tot_no_bits = ((bit_offset&0x7) + no_of_bits);
7777 length = tot_no_bits>>3;
7778 /* If we are using part of the next octet, increase length by 1 */
7779 if (tot_no_bits & 0x07)
7782 if (no_of_bits < 65) {
7783 value = tvb_get_bits64(tvb, bit_offset, no_of_bits, ENC_BIG_ENDIAN);
7785 DISSECTOR_ASSERT_NOT_REACHED();
7789 str = decode_bits_in_field(bit_offset, no_of_bits, value);
7792 strcat(str, hf_field->name);
7795 * This function does not receive an actual value but a dimensionless pointer to that value.
7796 * For this reason, the type of the header field is examined in order to determine
7797 * what kind of value we should read from this address.
7798 * The caller of this function must make sure that for the specific header field type the address of
7799 * a compatible value is provided.
7801 switch (hf_field->type) {
7803 return proto_tree_add_boolean_format(tree, hf_index, tvb, offset, length, *(guint32 *)value_ptr,
7804 "%s: %s", str, value_str);
7811 return proto_tree_add_uint_format(tree, hf_index, tvb, offset, length, *(guint32 *)value_ptr,
7812 "%s: %s", str, value_str);
7816 return proto_tree_add_uint64_format(tree, hf_index, tvb, offset, length, *(guint64 *)value_ptr,
7817 "%s: %s", str, value_str);
7824 return proto_tree_add_int_format(tree, hf_index, tvb, offset, length, *(gint32 *)value_ptr,
7825 "%s: %s", str, value_str);
7829 return proto_tree_add_int64_format(tree, hf_index, tvb, offset, length, *(gint64 *)value_ptr,
7830 "%s: %s", str, value_str);
7834 return proto_tree_add_float_format(tree, hf_index, tvb, offset, length, *(float *)value_ptr,
7835 "%s: %s", str, value_str);
7839 DISSECTOR_ASSERT_NOT_REACHED();
7846 proto_tree_add_bits_format_value(proto_tree *tree, const int hf_index,
7847 tvbuff_t *tvb, const guint bit_offset,
7848 const gint no_of_bits, void *value_ptr,
7853 if ((item = _proto_tree_add_bits_format_value(tree, hf_index,
7854 tvb, bit_offset, no_of_bits,
7855 value_ptr, value_str))) {
7856 FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_OFFSET(bit_offset));
7857 FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_SIZE(no_of_bits));
7862 #define CREATE_VALUE_STRING(dst,format,ap) \
7863 va_start(ap, format); \
7864 dst = ep_strdup_vprintf(format, ap); \
7868 proto_tree_add_uint_bits_format_value(proto_tree *tree, const int hf_index,
7869 tvbuff_t *tvb, const guint bit_offset,
7870 const gint no_of_bits, guint32 value,
7871 const char *format, ...)
7875 header_field_info *hf_field;
7877 TRY_TO_FAKE_THIS_ITEM(tree, hf_index, hf_field);
7879 switch (hf_field->type) {
7887 DISSECTOR_ASSERT_NOT_REACHED();
7892 CREATE_VALUE_STRING(dst, format, ap);
7894 return proto_tree_add_bits_format_value(tree, hf_index, tvb, bit_offset, no_of_bits, &value, dst);
7898 proto_tree_add_float_bits_format_value(proto_tree *tree, const int hf_index,
7899 tvbuff_t *tvb, const guint bit_offset,
7900 const gint no_of_bits, float value,
7901 const char *format, ...)
7905 header_field_info *hf_field;
7907 TRY_TO_FAKE_THIS_ITEM(tree, hf_index, hf_field);
7909 DISSECTOR_ASSERT(hf_field->type == FT_FLOAT);
7911 CREATE_VALUE_STRING(dst, format, ap);
7913 return proto_tree_add_bits_format_value(tree, hf_index, tvb, bit_offset, no_of_bits, &value, dst);
7917 proto_tree_add_int_bits_format_value(proto_tree *tree, const int hf_index,
7918 tvbuff_t *tvb, const guint bit_offset,
7919 const gint no_of_bits, gint32 value,
7920 const char *format, ...)
7924 header_field_info *hf_field;
7926 TRY_TO_FAKE_THIS_ITEM(tree, hf_index, hf_field);
7928 switch (hf_field->type) {
7936 DISSECTOR_ASSERT_NOT_REACHED();
7941 CREATE_VALUE_STRING(dst, format, ap);
7943 return proto_tree_add_bits_format_value(tree, hf_index, tvb, bit_offset, no_of_bits, &value, dst);
7947 proto_tree_add_boolean_bits_format_value(proto_tree *tree, const int hf_index,
7948 tvbuff_t *tvb, const guint bit_offset,
7949 const gint no_of_bits, guint32 value,
7950 const char *format, ...)
7954 header_field_info *hf_field;
7956 TRY_TO_FAKE_THIS_ITEM(tree, hf_index, hf_field);
7958 DISSECTOR_ASSERT(hf_field->type == FT_BOOLEAN);
7960 CREATE_VALUE_STRING(dst, format, ap);
7962 return proto_tree_add_bits_format_value(tree, hf_index, tvb, bit_offset, no_of_bits, &value, dst);
7966 proto_check_field_name(const gchar *field_name)
7968 return wrs_check_charset(fld_abbrev_chars, field_name);