2 * Routines for protocol tree
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
34 #include "ptvcursor.h"
36 #include "addr_resolv.h"
40 #include "epan_dissect.h"
44 #include "asm_utils.h"
45 #include "column-utils.h"
48 #include "show_exception.h"
50 #include "wspython/wspy_register.h"
52 #define SUBTREE_ONCE_ALLOCATION_NUMBER 8
53 #define SUBTREE_MAX_LEVELS 256
54 /* Throw an exception if we exceed this many tree items. */
55 /* XXX - This should probably be a preference */
56 #define MAX_TREE_ITEMS (1 * 1000 * 1000)
59 typedef struct __subtree_lvl {
66 subtree_lvl *pushed_tree;
67 guint8 pushed_tree_index;
68 guint8 pushed_tree_max;
74 /* Candidates for assembler */
76 wrs_count_bitshift(const guint32 bitmask)
80 while ((bitmask & (1 << bitshift)) == 0)
85 #define cVALS(x) (const value_string*)(x)
87 /** See inlined comments.
88 @param tree the tree to append this item to
89 @param hfindex field index
90 @param hfinfo header_field
91 @return the header field matching 'hfinfo' */
92 #define TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo) \
93 /* If this item is not referenced we dont have to do much work \
94 at all but we should still return a node so that field items \
95 below this node (think proto_item_add_subtree()) will still \
96 have somewhere to attach to or else filtering will not work \
97 (they would be ignored since tree would be NULL). \
98 DONT try to fake a node where PTREE_FINFO(tree) is NULL \
99 since dissectors that want to do proto_item_set_len() or \
100 other operations that dereference this would crash. \
101 We fake FT_PROTOCOL unless some clients have requested us \
106 PTREE_DATA(tree)->count++; \
107 if (PTREE_DATA(tree)->count > MAX_TREE_ITEMS) { \
108 if (getenv("WIRESHARK_ABORT_ON_TOO_MANY_ITEMS") != NULL) \
109 g_error("More than %d items in the tree -- possible infinite loop", MAX_TREE_ITEMS); \
110 /* Let the exception handler add items to the tree */ \
111 PTREE_DATA(tree)->count = 0; \
112 THROW_MESSAGE(DissectorError, \
113 ep_strdup_printf("More than %d items in the tree -- possible infinite loop", MAX_TREE_ITEMS)); \
115 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo); \
116 if (!(PTREE_DATA(tree)->visible)) { \
117 if (PTREE_FINFO(tree)) { \
118 if ((hfinfo->ref_type != HF_REF_TYPE_DIRECT) \
119 && (hfinfo->type != FT_PROTOCOL || \
120 PTREE_DATA(tree)->fake_protocols)) { \
121 /* just return tree back to the caller */\
127 /** See inlined comments.
128 @param pi the created protocol item we're about to return */
129 #define TRY_TO_FAKE_THIS_REPR(pi) \
131 if (!(PTREE_DATA(pi)->visible)) { \
132 /* If the tree (GUI) isn't visible it's pointless for us to generate the protocol \
133 * items string representation */ \
137 static const char *hf_try_val_to_str(guint32 value, const header_field_info *hfinfo);
139 static void fill_label_boolean(field_info *fi, gchar *label_str);
140 static void fill_label_bitfield(field_info *fi, gchar *label_str);
141 static void fill_label_number(field_info *fi, gchar *label_str, gboolean is_signed);
142 static void fill_label_number64(field_info *fi, gchar *label_str, gboolean is_signed);
144 static const char *hfinfo_number_value_format_display(const header_field_info *hfinfo, int display, char buf[32], guint32 value);
145 static const char *hfinfo_number_vals_format(const header_field_info *hfinfo, char buf[32], guint32 value);
146 static const char *hfinfo_number_value_format(const header_field_info *hfinfo, char buf[32], guint32 value);
147 static const char *hfinfo_numeric_value_format(const header_field_info *hfinfo, char buf[32], guint32 value);
149 static const char* hfinfo_uint64_format(const header_field_info *hfinfo);
150 static const char* hfinfo_int64_format(const header_field_info *hfinfo);
153 proto_tree_add_node(proto_tree *tree, field_info *fi);
156 get_hfi_length(header_field_info *hfinfo, tvbuff_t *tvb, const gint start, gint *length,
160 new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
161 const gint start, const gint item_length);
164 alloc_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
165 const gint start, gint *length);
168 proto_tree_add_pi(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
169 gint start, gint *length, field_info **pfi);
172 proto_tree_set_representation_value(proto_item *pi, const char *format, va_list ap);
174 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap);
177 proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb);
179 proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length);
181 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length);
183 proto_tree_set_time(field_info *fi, nstime_t *value_ptr);
185 proto_tree_set_string(field_info *fi, const char* value);
187 proto_tree_set_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length, gint encoding);
189 proto_tree_set_ax25(field_info *fi, const guint8* value);
191 proto_tree_set_ax25_tvb(field_info *fi, tvbuff_t *tvb, gint start);
193 proto_tree_set_vines(field_info *fi, const guint8* value);
195 proto_tree_set_vines_tvb(field_info *fi, tvbuff_t *tvb, gint start);
197 proto_tree_set_ether(field_info *fi, const guint8* value);
199 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start);
201 proto_tree_set_ipxnet(field_info *fi, guint32 value);
203 proto_tree_set_ipv4(field_info *fi, guint32 value);
205 proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr);
207 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
209 proto_tree_set_guid(field_info *fi, const e_guid_t *value_ptr);
211 proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, gint start, const guint encoding);
213 proto_tree_set_oid(field_info *fi, const guint8* value_ptr, gint length);
215 proto_tree_set_oid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
217 proto_tree_set_boolean(field_info *fi, guint32 value);
219 proto_tree_set_float(field_info *fi, float value);
221 proto_tree_set_double(field_info *fi, double value);
223 proto_tree_set_uint(field_info *fi, guint32 value);
225 proto_tree_set_int(field_info *fi, gint32 value);
227 proto_tree_set_uint64(field_info *fi, guint64 value);
229 proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start, guint length, const guint encoding);
231 proto_tree_set_eui64(field_info *fi, const guint64 value);
233 proto_tree_set_eui64_tvb(field_info *fi, tvbuff_t *tvb, gint start, const guint encoding);
235 proto_item_add_bitmask_tree(proto_item *item, tvbuff_t *tvb, const int offset,
236 const int len, const gint ett, const gint **fields,
237 const guint encoding, const int flags,
240 static int proto_register_field_init(header_field_info *hfinfo, const int parent);
242 /* special-case header field used within proto.c */
243 static header_field_info hfi_text_only =
244 { "Text item", "text", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL };
245 int hf_text_only = -1;
247 /* Structure for information about a protocol */
249 const char *name; /* long description */
250 const char *short_name; /* short description */
251 const char *filter_name; /* name of this protocol in filters */
252 int proto_id; /* field ID for this protocol */
253 GSList *fields; /* fields for this protocol */
254 GSList *last_field; /* pointer to end of list of fields */
255 gboolean is_enabled; /* TRUE if protocol is enabled */
256 gboolean can_toggle; /* TRUE if is_enabled can be changed */
257 gboolean is_private; /* TRUE is protocol is private */
260 /* List of all protocols */
261 static GList *protocols = NULL;
263 #define INITIAL_NUM_PROTOCOL_HFINFO 1500
265 /* Contains information about a field when a dissector calls
266 * proto_tree_add_item. */
267 #define FIELD_INFO_NEW(fi) fi = g_slice_new(field_info)
268 #define FIELD_INFO_FREE(fi) g_slice_free(field_info, fi)
270 /* Contains the space for proto_nodes. */
271 #define PROTO_NODE_NEW(node) \
272 node = g_slice_new(proto_node); \
273 node->first_child = NULL; \
274 node->last_child = NULL; \
277 #define PROTO_NODE_FREE(node) \
278 g_slice_free(proto_node, node)
280 /* String space for protocol and field items for the GUI */
281 #define ITEM_LABEL_NEW(il) \
282 il = g_slice_new(item_label_t);
283 #define ITEM_LABEL_FREE(il) \
284 g_slice_free(item_label_t, il);
286 #define PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo) \
287 if((guint)hfindex >= gpa_hfinfo.len && getenv("WIRESHARK_ABORT_ON_DISSECTOR_BUG")) \
288 g_error("Unregistered hf! index=%d", hfindex); \
289 DISSECTOR_ASSERT_HINT((guint)hfindex < gpa_hfinfo.len, "Unregistered hf!"); \
290 hfinfo = gpa_hfinfo.hfi[hfindex];
292 /* List which stores protocols and fields that have been registered */
293 typedef struct _gpa_hfinfo_t {
295 guint32 allocated_len;
296 header_field_info **hfi;
299 static gpa_hfinfo_t gpa_hfinfo;
301 /* Balanced tree of abbreviations and IDs */
302 static GTree *gpa_name_tree = NULL;
303 static header_field_info *same_name_hfinfo;
305 static void save_same_name_hfinfo(gpointer data)
307 same_name_hfinfo = (header_field_info*)data;
310 /* Points to the first element of an array of bits, indexed by
311 a subtree item type; that array element is TRUE if subtrees of
312 an item of that type are to be expanded. */
313 static guint32 *tree_is_expanded;
315 /* Number of elements in that array. */
318 /* Name hashtables for fast detection of duplicate names */
319 static GHashTable* proto_names = NULL;
320 static GHashTable* proto_short_names = NULL;
321 static GHashTable* proto_filter_names = NULL;
324 proto_compare_name(gconstpointer p1_arg, gconstpointer p2_arg)
326 const protocol_t *p1 = (const protocol_t *)p1_arg;
327 const protocol_t *p2 = (const protocol_t *)p2_arg;
329 return g_ascii_strcasecmp(p1->short_name, p2->short_name);
333 /* initialize data structures and register protocols and fields */
335 proto_init(void (register_all_protocols_func)(register_cb cb, gpointer client_data),
336 void (register_all_handoffs_func)(register_cb cb, gpointer client_data),
338 gpointer client_data)
342 proto_names = g_hash_table_new_full(g_int_hash, g_int_equal, g_free, NULL);
343 proto_short_names = g_hash_table_new(wrs_str_hash, g_str_equal);
344 proto_filter_names = g_hash_table_new(wrs_str_hash, g_str_equal);
347 gpa_hfinfo.allocated_len = 0;
348 gpa_hfinfo.hfi = NULL;
349 gpa_name_tree = g_tree_new_full(wrs_strcmp_with_data, NULL, NULL, save_same_name_hfinfo);
351 /* Initialize the ftype subsystem */
354 /* Register one special-case FT_TEXT_ONLY field for use when
355 converting wireshark to new-style proto_tree. These fields
356 are merely strings on the GUI tree; they are not filterable */
357 hf_text_only = proto_register_field_init(&hfi_text_only, -1);
359 /* Register the pseudo-protocols used for exceptions. */
360 register_show_exception();
362 /* Have each built-in dissector register its protocols, fields,
363 dissector tables, and dissectors to be called through a
364 handle, and do whatever one-time initialization it needs to
366 register_all_protocols_func(cb, client_data);
368 /* Now scan for python protocols */
370 (*cb)(RA_PYTHON_REGISTER, NULL, client_data);
371 register_all_py_protocols_func();
375 /* Now scan for plugins and load all the ones we find, calling
376 their register routines to do the stuff described above. */
378 (*cb)(RA_PLUGIN_REGISTER, NULL, client_data);
380 register_all_plugin_registrations();
383 /* Now call the "handoff registration" routines of all built-in
384 dissectors; those routines register the dissector in other
385 dissectors' handoff tables, and fetch any dissector handles
387 register_all_handoffs_func(cb, client_data);
390 /* Now do the same with python dissectors */
392 (*cb)(RA_PYTHON_HANDOFF, NULL, client_data);
393 register_all_py_handoffs_func();
397 /* Now do the same with plugins. */
399 (*cb)(RA_PLUGIN_HANDOFF, NULL, client_data);
400 register_all_plugin_handoffs();
403 /* sort the protocols by protocol name */
404 protocols = g_list_sort(protocols, proto_compare_name);
406 /* We've assigned all the subtree type values; allocate the array
407 for them, and zero it out. */
408 tree_is_expanded = g_new0(guint32, (num_tree_types/32)+1);
414 /* Free the abbrev/ID GTree */
416 g_tree_destroy(gpa_name_tree);
417 gpa_name_tree = NULL;
421 protocol_t *protocol = (protocol_t *)protocols->data;
422 header_field_info *hfinfo;
423 PROTO_REGISTRAR_GET_NTH(protocol->proto_id, hfinfo);
424 DISSECTOR_ASSERT(protocol->proto_id == hfinfo->id);
426 g_slice_free(header_field_info, hfinfo);
427 g_slist_free(protocol->fields);
428 protocols = g_list_remove(protocols, protocol);
433 g_hash_table_destroy(proto_names);
437 if (proto_short_names) {
438 g_hash_table_destroy(proto_short_names);
439 proto_short_names = NULL;
442 if (proto_filter_names) {
443 g_hash_table_destroy(proto_filter_names);
444 proto_filter_names = NULL;
447 if (gpa_hfinfo.allocated_len) {
449 gpa_hfinfo.allocated_len = 0;
450 g_free(gpa_hfinfo.hfi);
451 gpa_hfinfo.hfi = NULL;
453 g_free(tree_is_expanded);
454 tree_is_expanded = NULL;
458 proto_tree_traverse_pre_order(proto_tree *tree, proto_tree_traverse_func func,
461 proto_node *pnode = tree;
465 if (func(pnode, data))
468 child = pnode->first_child;
469 while (child != NULL) {
471 * The routine we call might modify the child, e.g. by
472 * freeing it, so we get the child's successor before
473 * calling that routine.
476 child = current->next;
477 if (proto_tree_traverse_pre_order((proto_tree *)current, func, data))
485 proto_tree_traverse_post_order(proto_tree *tree, proto_tree_traverse_func func,
488 proto_node *pnode = tree;
492 child = pnode->first_child;
493 while (child != NULL) {
495 * The routine we call might modify the child, e.g. by
496 * freeing it, so we get the child's successor before
497 * calling that routine.
500 child = current->next;
501 if (proto_tree_traverse_post_order((proto_tree *)current, func, data))
504 if (func(pnode, data))
511 proto_tree_children_foreach(proto_tree *tree, proto_tree_foreach_func func,
514 proto_node *node = tree;
520 node = node->first_child;
521 while (node != NULL) {
523 node = current->next;
524 func((proto_tree *)current, data);
529 free_GPtrArray_value(gpointer key, gpointer value, gpointer user_data _U_)
531 GPtrArray *ptrs = (GPtrArray *)value;
532 gint hfid = (gint)(long)key;
533 header_field_info *hfinfo;
535 PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
536 if (hfinfo->ref_type != HF_REF_TYPE_NONE) {
537 /* when a field is referenced by a filter this also
538 affects the refcount for the parent protocol so we need
539 to adjust the refcount for the parent as well
541 if (hfinfo->parent != -1) {
542 header_field_info *parent_hfinfo;
543 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
544 parent_hfinfo->ref_type = HF_REF_TYPE_NONE;
546 hfinfo->ref_type = HF_REF_TYPE_NONE;
549 g_ptr_array_free(ptrs, TRUE);
553 free_node_tree_data(tree_data_t *tree_data)
555 if (tree_data->interesting_hfids) {
556 /* Free all the GPtrArray's in the interesting_hfids hash. */
557 g_hash_table_foreach(tree_data->interesting_hfids,
558 free_GPtrArray_value, NULL);
560 /* And then destroy the hash. */
561 g_hash_table_destroy(tree_data->interesting_hfids);
563 if (tree_data->fi_tmp)
564 FIELD_INFO_FREE(tree_data->fi_tmp);
566 /* And finally the tree_data_t itself. */
570 #define FREE_NODE_FIELD_INFO(finfo) \
572 ITEM_LABEL_FREE(finfo->rep); \
574 FVALUE_CLEANUP(&finfo->value); \
575 FIELD_INFO_FREE(finfo);
578 proto_tree_free_node(proto_node *node, gpointer data _U_)
580 field_info *finfo = PNODE_FINFO(node);
582 proto_tree_children_foreach(node, proto_tree_free_node, NULL);
584 /* free the field_info data. */
585 FREE_NODE_FIELD_INFO(finfo);
588 /* Free the proto_node. */
589 PROTO_NODE_FREE(node);
592 /* frees the resources that the dissection a proto_tree uses */
594 proto_tree_free(proto_tree *tree)
596 tree_data_t *tree_data = PTREE_DATA(tree);
598 proto_tree_children_foreach(tree, proto_tree_free_node, NULL);
601 PROTO_NODE_FREE(tree);
604 free_node_tree_data(tree_data);
607 /* Is the parsing being done for a visible proto_tree or an invisible one?
608 * By setting this correctly, the proto_tree creation is sped up by not
609 * having to call g_vsnprintf and copy strings around.
612 proto_tree_set_visible(proto_tree *tree, gboolean visible)
614 gboolean old_visible = PTREE_DATA(tree)->visible;
616 PTREE_DATA(tree)->visible = visible;
622 proto_tree_set_fake_protocols(proto_tree *tree, gboolean fake_protocols)
624 PTREE_DATA(tree)->fake_protocols = fake_protocols;
627 /* Assume dissector set only its protocol fields.
628 This function is called by dissectors and allows the speeding up of filtering
629 in wireshark; if this function returns FALSE it is safe to reset tree to NULL
630 and thus skip calling most of the expensive proto_tree_add_...()
632 If the tree is visible we implicitly assume the field is referenced.
635 proto_field_is_referenced(proto_tree *tree, int proto_id)
637 register header_field_info *hfinfo;
643 if (PTREE_DATA(tree)->visible)
646 PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
647 if (hfinfo->ref_type != HF_REF_TYPE_NONE)
650 if (hfinfo->type == FT_PROTOCOL && !PTREE_DATA(tree)->fake_protocols)
657 /* Finds a record in the hfinfo array by id. */
659 proto_registrar_get_nth(guint hfindex)
661 register header_field_info *hfinfo;
663 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
668 /* Prefix initialization
669 * this allows for a dissector to register a display filter name prefix
670 * so that it can delay the initialization of the hf array as long as
674 /* compute a hash for the part before the dot of a display filter */
676 prefix_hash (gconstpointer key) {
677 /* end the string at the dot and compute its hash */
678 gchar* copy = ep_strdup((const gchar *)key);
688 return g_str_hash(copy);
691 /* are both strings equal up to the end or the dot? */
693 prefix_equal (gconstpointer ap, gconstpointer bp) {
694 const gchar* a = (const gchar *)ap;
695 const gchar* b = (const gchar *)bp;
701 if ( (ac == '.' || ac == '\0') && (bc == '.' || bc == '\0') ) return TRUE;
703 if ( (ac == '.' || ac == '\0') && ! (bc == '.' || bc == '\0') ) return FALSE;
704 if ( (bc == '.' || bc == '\0') && ! (ac == '.' || ac == '\0') ) return FALSE;
706 if (ac != bc) return FALSE;
713 /* indexed by prefix, contains initializers */
714 static GHashTable* prefixes = NULL;
717 /* Register a new prefix for "delayed" initialization of field arrays */
719 proto_register_prefix(const char *prefix, prefix_initializer_t pi ) {
721 prefixes = g_hash_table_new(prefix_hash, prefix_equal);
724 g_hash_table_insert(prefixes, (gpointer)prefix, pi);
727 /* helper to call all prefix initializers */
729 initialize_prefix(gpointer k, gpointer v, gpointer u _U_) {
730 ((prefix_initializer_t)v)((const char *)k);
734 /** Initialize every remaining uninitialized prefix. */
736 proto_initialize_all_prefixes(void) {
737 g_hash_table_foreach_remove(prefixes, initialize_prefix, NULL);
740 /* Finds a record in the hfinfo array by name.
741 * If it fails to find it in the already registered fields,
742 * it tries to find and call an initializer in the prefixes
743 * table and if so it looks again.
746 proto_registrar_get_byname(const char *field_name)
748 header_field_info *hfinfo;
749 prefix_initializer_t pi;
754 hfinfo = (header_field_info *)g_tree_lookup(gpa_name_tree, field_name);
762 if ((pi = (prefix_initializer_t)g_hash_table_lookup(prefixes, field_name) ) != NULL) {
764 g_hash_table_remove(prefixes, field_name);
769 return (header_field_info *)g_tree_lookup(gpa_name_tree, field_name);
773 proto_registrar_get_id_byname(const char *field_name)
775 header_field_info *hfinfo;
777 hfinfo = proto_registrar_get_byname(field_name);
787 ptvcursor_new_subtree_levels(ptvcursor_t *ptvc)
789 subtree_lvl *pushed_tree;
791 DISSECTOR_ASSERT(ptvc->pushed_tree_max <= SUBTREE_MAX_LEVELS-SUBTREE_ONCE_ALLOCATION_NUMBER);
792 ptvc->pushed_tree_max += SUBTREE_ONCE_ALLOCATION_NUMBER;
794 pushed_tree = (subtree_lvl *)ep_alloc(sizeof(subtree_lvl) * ptvc->pushed_tree_max);
795 DISSECTOR_ASSERT(pushed_tree != NULL);
796 if (ptvc->pushed_tree)
797 memcpy(pushed_tree, ptvc->pushed_tree, ptvc->pushed_tree_max - SUBTREE_ONCE_ALLOCATION_NUMBER);
798 ptvc->pushed_tree = pushed_tree;
802 ptvcursor_free_subtree_levels(ptvcursor_t *ptvc)
804 ptvc->pushed_tree = NULL;
805 ptvc->pushed_tree_max = 0;
806 DISSECTOR_ASSERT(ptvc->pushed_tree_index == 0);
807 ptvc->pushed_tree_index = 0;
810 /* Allocates an initializes a ptvcursor_t with 3 variables:
811 * proto_tree, tvbuff, and offset. */
813 ptvcursor_new(proto_tree *tree, tvbuff_t *tvb, gint offset)
817 ptvc = (ptvcursor_t *)ep_alloc(sizeof(ptvcursor_t));
820 ptvc->offset = offset;
821 ptvc->pushed_tree = NULL;
822 ptvc->pushed_tree_max = 0;
823 ptvc->pushed_tree_index = 0;
828 /* Frees memory for ptvcursor_t, but nothing deeper than that. */
830 ptvcursor_free(ptvcursor_t *ptvc)
832 ptvcursor_free_subtree_levels(ptvc);
836 /* Returns tvbuff. */
838 ptvcursor_tvbuff(ptvcursor_t *ptvc)
843 /* Returns current offset. */
845 ptvcursor_current_offset(ptvcursor_t *ptvc)
851 ptvcursor_tree(ptvcursor_t *ptvc)
860 ptvcursor_set_tree(ptvcursor_t *ptvc, proto_tree *tree)
865 /* creates a subtree, sets it as the working tree and pushes the old working tree */
867 ptvcursor_push_subtree(ptvcursor_t *ptvc, proto_item *it, gint ett_subtree)
869 subtree_lvl *subtree;
870 if (ptvc->pushed_tree_index >= ptvc->pushed_tree_max)
871 ptvcursor_new_subtree_levels(ptvc);
873 subtree = ptvc->pushed_tree + ptvc->pushed_tree_index;
874 subtree->tree = ptvc->tree;
876 ptvc->pushed_tree_index++;
877 return ptvcursor_set_subtree(ptvc, it, ett_subtree);
882 ptvcursor_pop_subtree(ptvcursor_t *ptvc)
884 subtree_lvl *subtree;
886 if (ptvc->pushed_tree_index <= 0)
889 ptvc->pushed_tree_index--;
890 subtree = ptvc->pushed_tree + ptvc->pushed_tree_index;
891 if (subtree->it != NULL)
892 proto_item_set_len(subtree->it, ptvcursor_current_offset(ptvc) - subtree->cursor_offset);
894 ptvc->tree = subtree->tree;
897 /* saves the current tvb offset and the item in the current subtree level */
899 ptvcursor_subtree_set_item(ptvcursor_t *ptvc, proto_item *it)
901 subtree_lvl *subtree;
903 DISSECTOR_ASSERT(ptvc->pushed_tree_index > 0);
905 subtree = ptvc->pushed_tree + ptvc->pushed_tree_index - 1;
907 subtree->cursor_offset = ptvcursor_current_offset(ptvc);
910 /* Creates a subtree and adds it to the cursor as the working tree but does not
911 * save the old working tree */
913 ptvcursor_set_subtree(ptvcursor_t *ptvc, proto_item *it, gint ett_subtree)
915 ptvc->tree = proto_item_add_subtree(it, ett_subtree);
920 ptvcursor_add_subtree_item(ptvcursor_t *ptvc, proto_item *it, gint ett_subtree, gint length)
922 ptvcursor_push_subtree(ptvc, it, ett_subtree);
923 if (length == SUBTREE_UNDEFINED_LENGTH)
924 ptvcursor_subtree_set_item(ptvc, it);
925 return ptvcursor_tree(ptvc);
928 /* Add an item to the tree and create a subtree
929 * If the length is unknown, length may be defined as SUBTREE_UNDEFINED_LENGTH.
930 * In this case, when the subtree will be closed, the parent item length will
931 * be equal to the advancement of the cursor since the creation of the subtree.
934 ptvcursor_add_with_subtree(ptvcursor_t *ptvc, int hfindex, gint length,
935 const guint encoding, gint ett_subtree)
939 it = ptvcursor_add_no_advance(ptvc, hfindex, length, encoding);
940 return ptvcursor_add_subtree_item(ptvc, it, ett_subtree, length);
944 proto_tree_add_text_node(proto_tree *tree, tvbuff_t *tvb, gint start, gint length);
946 /* Add a text node to the tree and create a subtree
947 * If the length is unknown, length may be defined as SUBTREE_UNDEFINED_LENGTH.
948 * In this case, when the subtree will be closed, the item length will be equal
949 * to the advancement of the cursor since the creation of the subtree.
952 ptvcursor_add_text_with_subtree(ptvcursor_t *ptvc, gint length,
953 gint ett_subtree, const char *format, ...)
957 header_field_info *hfinfo;
960 tree = ptvcursor_tree(ptvc);
962 TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
964 pi = proto_tree_add_text_node(tree, ptvcursor_tvbuff(ptvc),
965 ptvcursor_current_offset(ptvc), length);
967 TRY_TO_FAKE_THIS_REPR(pi);
969 va_start(ap, format);
970 proto_tree_set_representation(pi, format, ap);
973 return ptvcursor_add_subtree_item(ptvc, pi, ett_subtree, length);
976 /* Add a text-only node, leaving it to our caller to fill the text in */
978 proto_tree_add_text_node(proto_tree *tree, tvbuff_t *tvb, gint start, gint length)
986 pi = proto_tree_add_pi(tree, &hfi_text_only, tvb, start, &length, &new_fi);
991 /* Add a text-only node to the proto_tree */
993 proto_tree_add_text(proto_tree *tree, tvbuff_t *tvb, gint start, gint length,
994 const char *format, ...)
998 header_field_info *hfinfo;
1000 TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
1002 pi = proto_tree_add_text_node(tree, tvb, start, length);
1004 TRY_TO_FAKE_THIS_REPR(pi);
1006 va_start(ap, format);
1007 proto_tree_set_representation(pi, format, ap);
1013 /* Add a text-only node to the proto_tree (va_list version) */
1015 proto_tree_add_text_valist(proto_tree *tree, tvbuff_t *tvb, gint start,
1016 gint length, const char *format, va_list ap)
1019 header_field_info *hfinfo;
1021 TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
1023 pi = proto_tree_add_text_node(tree, tvb, start, length);
1025 TRY_TO_FAKE_THIS_REPR(pi);
1027 proto_tree_set_representation(pi, format, ap);
1032 /* Add a text-only node for debugging purposes. The caller doesn't need
1033 * to worry about tvbuff, start, or length. Debug message gets sent to
1036 proto_tree_add_debug_text(proto_tree *tree, const char *format, ...)
1041 pi = proto_tree_add_text_node(tree, NULL, 0, 0);
1044 va_start(ap, format);
1045 proto_tree_set_representation(pi, format, ap);
1048 va_start(ap, format);
1049 vprintf(format, ap);
1056 /* We could probably get away with changing is_error to a minimum length value. */
1058 report_type_length_mismatch(proto_tree *tree, const gchar *descr, int length, gboolean is_error) {
1059 tree_data_t *tree_data = PTREE_DATA(tree);
1060 field_info *fi_save = tree_data->fi_tmp;
1062 /* Keep the current item from getting freed by proto_tree_new_item. */
1063 tree_data->fi_tmp = NULL;
1065 expert_add_info_format(NULL, tree, PI_MALFORMED, is_error ? PI_ERROR : PI_WARN, "Trying to fetch %s with length %d", descr, length);
1067 tree_data->fi_tmp = fi_save;
1070 THROW(ReportedBoundsError);
1075 get_uint_value(proto_tree *tree, tvbuff_t *tvb, gint offset, gint length, const guint encoding)
1078 gboolean length_error;
1083 value = tvb_get_guint8(tvb, offset);
1087 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letohs(tvb, offset)
1088 : tvb_get_ntohs(tvb, offset);
1092 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letoh24(tvb, offset)
1093 : tvb_get_ntoh24(tvb, offset);
1097 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letohl(tvb, offset)
1098 : tvb_get_ntohl(tvb, offset);
1103 length_error = TRUE;
1106 length_error = FALSE;
1107 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letohl(tvb, offset)
1108 : tvb_get_ntohl(tvb, offset);
1110 report_type_length_mismatch(tree, "an unsigned integer", length, length_error);
1117 * NOTE: to support code written when proto_tree_add_item() took a
1118 * gboolean as its last argument, with FALSE meaning "big-endian"
1119 * and TRUE meaning "little-endian", we treat any non-zero value of
1120 * "encoding" as meaning "little-endian".
1123 get_int_value(proto_tree *tree, tvbuff_t *tvb, gint offset, gint length, const guint encoding)
1126 gboolean length_error;
1131 value = (gint8)tvb_get_guint8(tvb, offset);
1135 value = (gint16) (encoding ? tvb_get_letohs(tvb, offset)
1136 : tvb_get_ntohs(tvb, offset));
1140 value = encoding ? tvb_get_letoh24(tvb, offset)
1141 : tvb_get_ntoh24(tvb, offset);
1142 if (value & 0x00800000) {
1143 /* Sign bit is set; sign-extend it. */
1144 value |= 0xFF000000;
1149 value = encoding ? tvb_get_letohl(tvb, offset)
1150 : tvb_get_ntohl(tvb, offset);
1155 length_error = TRUE;
1158 length_error = FALSE;
1159 value = encoding ? tvb_get_letohl(tvb, offset)
1160 : tvb_get_ntohl(tvb, offset);
1162 report_type_length_mismatch(tree, "a signed integer", length, length_error);
1169 tree_data_add_maybe_interesting_field(tree_data_t *tree_data, field_info *fi)
1171 const header_field_info *hfinfo = fi->hfinfo;
1173 if (hfinfo->ref_type == HF_REF_TYPE_DIRECT) {
1174 GPtrArray *ptrs = NULL;
1176 if (tree_data->interesting_hfids == NULL) {
1177 /* Initialize the hash because we now know that it is needed */
1178 tree_data->interesting_hfids =
1179 g_hash_table_new(g_direct_hash, NULL /* g_direct_equal */);
1181 ptrs = (GPtrArray *)g_hash_table_lookup(tree_data->interesting_hfids,
1182 GINT_TO_POINTER(hfinfo->id));
1184 /* First element triggers the creation of pointer array */
1185 ptrs = g_ptr_array_new();
1186 g_hash_table_insert(tree_data->interesting_hfids,
1187 GINT_TO_POINTER(hfinfo->id), ptrs);
1190 g_ptr_array_add(ptrs, fi);
1194 /* Add an item to a proto_tree, using the text label registered to that item;
1195 the item is extracted from the tvbuff handed to it. */
1197 proto_tree_new_item(field_info *new_fi, proto_tree *tree,
1198 tvbuff_t *tvb, gint start, gint length,
1201 tree_data_t *tree_data = PTREE_DATA(tree);
1207 nstime_t time_stamp;
1209 gboolean length_error;
1211 /* there is a possibility here that we might raise an exception
1212 * and thus would lose track of the field_info.
1213 * store it in a temp so that if we come here again we can reclaim
1214 * the field_info without leaking memory.
1216 if (tree_data->fi_tmp) {
1217 /* oops, last one we got must have been lost due
1219 * good thing we saved it, now we can reverse the
1220 * memory leak and reclaim it.
1222 FIELD_INFO_FREE(tree_data->fi_tmp);
1224 /* we might throw an exception, keep track of this one
1225 * across the "dangerous" section below.
1227 tree_data->fi_tmp = new_fi;
1229 switch (new_fi->hfinfo->type) {
1231 /* no value to set for FT_NONE */
1235 proto_tree_set_protocol_tvb(new_fi, tvb);
1239 proto_tree_set_bytes_tvb(new_fi, tvb, start, length);
1244 * Map all non-zero values to little-endian for
1245 * backwards compatibility.
1248 encoding = ENC_LITTLE_ENDIAN;
1249 n = get_uint_value(tree, tvb, start, length, encoding);
1250 proto_tree_set_bytes_tvb(new_fi, tvb, start + length, n);
1252 /* Instead of calling proto_item_set_len(), since we don't yet
1253 * have a proto_item, we set the field_info's length ourselves. */
1254 new_fi->length = n + length;
1259 * Map all non-zero values to little-endian for
1260 * backwards compatibility.
1263 encoding = ENC_LITTLE_ENDIAN;
1264 proto_tree_set_boolean(new_fi,
1265 get_uint_value(tree, tvb, start, length, encoding));
1268 /* XXX - make these just FT_UINT? */
1274 * Map all non-zero values to little-endian for
1275 * backwards compatibility.
1278 encoding = ENC_LITTLE_ENDIAN;
1279 proto_tree_set_uint(new_fi,
1280 get_uint_value(tree, tvb, start, length, encoding));
1286 * Map all non-zero values to little-endian for
1287 * backwards compatibility.
1290 encoding = ENC_LITTLE_ENDIAN;
1291 if (length < 1 || length > 8) {
1292 length_error = length < 1 ? TRUE : FALSE;
1293 report_type_length_mismatch(tree, "a 64-bit integer", length, length_error);
1295 proto_tree_set_uint64_tvb(new_fi, tvb, start, length, encoding);
1298 /* XXX - make these just FT_INT? */
1304 * Map all non-zero values to little-endian for
1305 * backwards compatibility.
1308 encoding = ENC_LITTLE_ENDIAN;
1309 proto_tree_set_int(new_fi,
1310 get_int_value(tree, tvb, start, length, encoding));
1315 * Map all non-zero values to little-endian for
1316 * backwards compatibility.
1319 encoding = ENC_LITTLE_ENDIAN;
1320 if (length != FT_IPv4_LEN) {
1321 length_error = length < FT_IPv4_LEN ? TRUE : FALSE;
1322 report_type_length_mismatch(tree, "an IPv4 address", length, length_error);
1324 value = tvb_get_ipv4(tvb, start);
1326 * NOTE: to support code written when
1327 * proto_tree_add_item() took a gboolean as its
1328 * last argument, with FALSE meaning "big-endian"
1329 * and TRUE meaning "little-endian", we treat any
1330 * non-zero value of "encoding" as meaning
1333 proto_tree_set_ipv4(new_fi, encoding ? GUINT32_SWAP_LE_BE(value) : value);
1337 if (length != FT_IPXNET_LEN) {
1338 length_error = length < FT_IPXNET_LEN ? TRUE : FALSE;
1339 report_type_length_mismatch(tree, "an IPXNET address", length, length_error);
1341 proto_tree_set_ipxnet(new_fi,
1342 get_uint_value(tree, tvb, start, FT_IPXNET_LEN, ENC_BIG_ENDIAN));
1346 if (length != FT_IPv6_LEN) {
1347 length_error = length < FT_IPv6_LEN ? TRUE : FALSE;
1348 report_type_length_mismatch(tree, "an IPv6 address", length, length_error);
1350 proto_tree_set_ipv6_tvb(new_fi, tvb, start, length);
1355 length_error = length < 7 ? TRUE : FALSE;
1356 report_type_length_mismatch(tree, "an AX.25 address", length, length_error);
1358 proto_tree_set_ax25_tvb(new_fi, tvb, start);
1362 if (length != VINES_ADDR_LEN) {
1363 length_error = length < VINES_ADDR_LEN ? TRUE : FALSE;
1364 report_type_length_mismatch(tree, "a Vines address", length, length_error);
1366 proto_tree_set_vines_tvb(new_fi, tvb, start);
1370 if (length != FT_ETHER_LEN) {
1371 length_error = length < FT_ETHER_LEN ? TRUE : FALSE;
1372 report_type_length_mismatch(tree, "an Ethernet", length, length_error);
1374 proto_tree_set_ether_tvb(new_fi, tvb, start);
1379 * Map all non-zero values to little-endian for
1380 * backwards compatibility.
1383 encoding = ENC_LITTLE_ENDIAN;
1384 if (length != FT_EUI64_LEN) {
1385 length_error = length < FT_EUI64_LEN ? TRUE : FALSE;
1386 report_type_length_mismatch(tree, "an EUI-64 address", length, length_error);
1388 proto_tree_set_eui64_tvb(new_fi, tvb, start, encoding);
1392 * Map all non-zero values to little-endian for
1393 * backwards compatibility.
1396 encoding = ENC_LITTLE_ENDIAN;
1397 if (length != FT_GUID_LEN) {
1398 length_error = length < FT_GUID_LEN ? TRUE : FALSE;
1399 report_type_length_mismatch(tree, "a GUID", length, length_error);
1401 proto_tree_set_guid_tvb(new_fi, tvb, start, encoding);
1405 proto_tree_set_oid_tvb(new_fi, tvb, start, length);
1410 * NOTE: to support code written when
1411 * proto_tree_add_item() took a gboolean as its
1412 * last argument, with FALSE meaning "big-endian"
1413 * and TRUE meaning "little-endian", we treat any
1414 * non-zero value of "encoding" as meaning
1417 * At some point in the future, we might
1418 * support non-IEEE-binary floating-point
1419 * formats in the encoding as well
1420 * (IEEE decimal, System/3x0, VAX).
1423 encoding = ENC_LITTLE_ENDIAN;
1425 length_error = length < 4 ? TRUE : FALSE;
1426 report_type_length_mismatch(tree, "a single-precision floating point number", length, length_error);
1429 floatval = tvb_get_letohieee_float(tvb, start);
1431 floatval = tvb_get_ntohieee_float(tvb, start);
1432 proto_tree_set_float(new_fi, floatval);
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).
1449 if (encoding == TRUE)
1450 encoding = ENC_LITTLE_ENDIAN;
1452 length_error = length < 8 ? TRUE : FALSE;
1453 report_type_length_mismatch(tree, "a double-precision floating point number", length, length_error);
1456 doubleval = tvb_get_letohieee_double(tvb, start);
1458 doubleval = tvb_get_ntohieee_double(tvb, start);
1459 proto_tree_set_double(new_fi, doubleval);
1463 proto_tree_set_string_tvb(new_fi, tvb, start, length,
1469 report_type_length_mismatch(tree, "a string", length, TRUE);
1471 /* Instead of calling proto_item_set_len(),
1472 * since we don't yet have a proto_item, we
1473 * set the field_info's length ourselves.
1475 * XXX - our caller can't use that length to
1476 * advance an offset unless they arrange that
1477 * there always be a protocol tree into which
1478 * we're putting this item.
1481 /* This can throw an exception */
1482 string = tvb_get_stringz_enc(tvb, start, &length, encoding);
1483 } else if (length == 0) {
1486 /* In this case, length signifies
1487 * the length of the string.
1489 * This could either be a null-padded
1490 * string, which doesn't necessarily
1491 * have a '\0' at the end, or a
1492 * null-terminated string, with a
1493 * trailing '\0'. (Yes, there are
1494 * cases where you have a string
1495 * that's both counted and null-
1498 * In the first case, we must
1499 * allocate a buffer of length
1500 * "length+1", to make room for
1503 * In the second case, we don't
1504 * assume that there is a trailing
1505 * '\0' there, as the packet might
1506 * be malformed. (XXX - should we
1507 * throw an exception if there's no
1508 * trailing '\0'?) Therefore, we
1509 * allocate a buffer of length
1510 * "length+1", and put in a trailing
1511 * '\0', just to be safe.
1513 * (XXX - this would change if
1514 * we made string values counted
1515 * rather than null-terminated.)
1517 string = tvb_get_ephemeral_string_enc(tvb, start, length, encoding);
1519 new_fi->length = length;
1520 proto_tree_set_string(new_fi, string);
1523 case FT_UINT_STRING:
1525 * NOTE: to support code written when
1526 * proto_tree_add_item() took a gboolean as its
1527 * last argument, with FALSE meaning "big-endian"
1528 * and TRUE meaning "little-endian", if the
1529 * encoding value is TRUE, treat that as
1530 * ASCII with a little-endian length.
1532 * This won't work for code that passes
1533 * arbitrary non-zero values; that code
1534 * will need to be fixed.
1536 if (encoding == TRUE)
1537 encoding = ENC_ASCII|ENC_LITTLE_ENDIAN;
1538 n = get_uint_value(tree, tvb, start, length, encoding & ~ENC_CHARENCODING_MASK);
1539 proto_tree_set_string_tvb(new_fi, tvb, start + length, n,
1542 /* Instead of calling proto_item_set_len(), since we
1543 * don't yet have a proto_item, we set the
1544 * field_info's length ourselves.
1546 * XXX - our caller can't use that length to
1547 * advance an offset unless they arrange that
1548 * there always be a protocol tree into which
1549 * we're putting this item.
1551 new_fi->length = n + length;
1554 case FT_ABSOLUTE_TIME:
1556 * Absolute times can be in any of a number of
1557 * formats, and they can be big-endian or
1560 * Historically FT_TIMEs were only timespecs;
1561 * the only question was whether they were stored
1562 * in big- or little-endian format.
1564 * For backwards compatibility, we interpret an
1565 * encoding of 1 as meaning "little-endian timespec",
1566 * so that passing TRUE is interpreted as that.
1568 if (encoding == TRUE)
1569 encoding = ENC_TIME_TIMESPEC|ENC_LITTLE_ENDIAN;
1571 if (length != 8 && length != 4) {
1572 length_error = length < 4 ? TRUE : FALSE;
1573 report_type_length_mismatch(tree, "an absolute time value", length, length_error);
1578 case ENC_TIME_TIMESPEC|ENC_BIG_ENDIAN:
1580 * 4-byte UNIX epoch, possibly followed by
1581 * 4-byte fractional time in nanoseconds,
1584 time_stamp.secs = tvb_get_ntohl(tvb, start);
1586 time_stamp.nsecs = tvb_get_ntohl(tvb, start+4);
1588 time_stamp.nsecs = 0;
1591 case ENC_TIME_TIMESPEC|ENC_LITTLE_ENDIAN:
1593 * 4-byte UNIX epoch, possibly followed by
1594 * 4-byte fractional time in nanoseconds,
1595 * both little-endian.
1597 time_stamp.secs = tvb_get_letohl(tvb, start);
1599 time_stamp.nsecs = tvb_get_letohl(tvb, start+4);
1601 time_stamp.nsecs = 0;
1604 case ENC_TIME_NTP|ENC_BIG_ENDIAN:
1606 * NTP time stamp, big-endian.
1609 /* XXX - where should this go? */
1610 #define NTP_BASETIME 2208988800ul
1612 /* We need a temporary variable here so the unsigned math
1613 * works correctly (for years > 2036 according to RFC 2030
1616 tmpsecs = tvb_get_ntohl(tvb, start);
1618 time_stamp.secs = tmpsecs - (guint32)NTP_BASETIME;
1620 time_stamp.secs = tmpsecs; /* 0 */
1624 * We're using nanoseconds here (and we will
1625 * display nanoseconds), but NTP's timestamps
1626 * have a precision in microseconds or greater.
1627 * Round to 1 microsecond.
1629 time_stamp.nsecs = (int)(1000000*(tvb_get_ntohl(tvb, start+4)/4294967296.0));
1630 time_stamp.nsecs *= 1000;
1632 time_stamp.nsecs = 0;
1636 case ENC_TIME_NTP|ENC_LITTLE_ENDIAN:
1638 * NTP time stamp, big-endian.
1640 tmpsecs = tvb_get_letohl(tvb, start);
1642 time_stamp.secs = tmpsecs - (guint32)NTP_BASETIME;
1644 time_stamp.secs = tmpsecs; /* 0 */
1648 * We're using nanoseconds here (and we will
1649 * display nanoseconds), but NTP's timestamps
1650 * have a precision in microseconds or greater.
1651 * Round to 1 microsecond.
1653 time_stamp.nsecs = (int)(1000000*(tvb_get_letohl(tvb, start+4)/4294967296.0));
1654 time_stamp.nsecs *= 1000;
1656 time_stamp.nsecs = 0;
1661 DISSECTOR_ASSERT_NOT_REACHED();
1662 time_stamp.secs = 0;
1663 time_stamp.nsecs = 0;
1666 proto_tree_set_time(new_fi, &time_stamp);
1669 case FT_RELATIVE_TIME:
1671 * Relative times can be in any of a number of
1672 * formats, and they can be big-endian or
1675 * Historically FT_TIMEs were only timespecs;
1676 * the only question was whether they were stored
1677 * in big- or little-endian format.
1679 * For backwards compatibility, we interpret an
1680 * encoding of 1 as meaning "little-endian timespec",
1681 * so that passing TRUE is interpreted as that.
1683 if (encoding == TRUE)
1684 encoding = ENC_TIME_TIMESPEC|ENC_LITTLE_ENDIAN;
1687 if (length != 8 && length != 4) {
1688 length_error = length < 4 ? TRUE : FALSE;
1689 report_type_length_mismatch(tree, "a relative time value", length, length_error);
1692 case ENC_TIME_TIMESPEC|ENC_BIG_ENDIAN:
1694 * 4-byte UNIX epoch, possibly followed by
1695 * 4-byte fractional time in nanoseconds,
1698 time_stamp.secs = tvb_get_ntohl(tvb, start);
1700 time_stamp.nsecs = tvb_get_ntohl(tvb, start+4);
1702 time_stamp.nsecs = 0;
1705 case ENC_TIME_TIMESPEC|ENC_LITTLE_ENDIAN:
1707 * 4-byte UNIX epoch, possibly followed by
1708 * 4-byte fractional time in nanoseconds,
1709 * both little-endian.
1711 time_stamp.secs = tvb_get_letohl(tvb, start);
1713 time_stamp.nsecs = tvb_get_letohl(tvb, start+4);
1715 time_stamp.nsecs = 0;
1718 proto_tree_set_time(new_fi, &time_stamp);
1722 g_error("new_fi->hfinfo->type %d (%s) not handled\n",
1723 new_fi->hfinfo->type,
1724 ftype_name(new_fi->hfinfo->type));
1725 DISSECTOR_ASSERT_NOT_REACHED();
1728 FI_SET_FLAG(new_fi, (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN);
1730 /* Don't add new node to proto_tree until now so that any exceptions
1731 * raised by a tvbuff access method doesn't leave junk in the proto_tree. */
1732 /* XXX. wouldn't be better to add this item to tree, with some special flag (FI_EXCEPTION?)
1733 * to know which item caused exception? */
1734 pi = proto_tree_add_node(tree, new_fi);
1736 /* we did not raise an exception so we dont have to remember this
1737 * field_info struct any more.
1739 tree_data->fi_tmp = NULL;
1744 /* Gets data from tvbuff, adds it to proto_tree, increments offset,
1745 and returns proto_item* */
1747 ptvcursor_add(ptvcursor_t *ptvc, int hfindex, gint length,
1748 const guint encoding)
1751 header_field_info *hfinfo;
1756 /* We can't fake it just yet. We have to advance the cursor
1757 TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfindex, hfinfo); */
1759 offset = ptvc->offset;
1760 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1761 get_hfi_length(hfinfo, ptvc->tvb, offset, &length, &item_length);
1762 ptvc->offset += length;
1763 if (hfinfo->type == FT_UINT_BYTES || hfinfo->type == FT_UINT_STRING) {
1765 * The length of the rest of the item is in the first N
1766 * bytes of the item.
1768 n = get_uint_value(ptvc->tree, ptvc->tvb, offset, length, encoding);
1772 /* Coast clear. Try and fake it */
1773 TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfindex, hfinfo);
1775 new_fi = new_field_info(ptvc->tree, hfinfo, ptvc->tvb, offset, item_length);
1777 return proto_tree_new_item(new_fi, ptvc->tree, ptvc->tvb,
1778 offset, length, encoding);
1782 * Validates that field length bytes are available starting from
1783 * start (pos/neg). Throws an exception if they aren't.
1786 test_length(header_field_info *hfinfo, proto_tree *tree, tvbuff_t *tvb,
1787 gint start, gint length, const guint encoding)
1794 if (hfinfo->type == FT_UINT_BYTES || hfinfo->type == FT_UINT_STRING) {
1797 n = get_uint_value(tree, tvb, start, length, encoding);
1799 /* If n > size + n then we have an integer overflow, so
1800 * set size to -1, which will force the
1801 * tvb_ensure_bytes_exist call below to throw a
1802 * ReportedBoundsError
1809 } else if (hfinfo->type == FT_STRINGZ) {
1810 /* If we're fetching until the end of the TVB, only validate
1811 * that the offset is within range.
1817 tvb_ensure_bytes_exist(tvb, start, size);
1820 /* Add an item to a proto_tree, using the text label registered to that item;
1821 the item is extracted from the tvbuff handed to it. */
1823 proto_tree_add_item(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
1824 const gint start, gint length, const guint encoding)
1827 header_field_info *hfinfo;
1830 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1831 get_hfi_length(hfinfo, tvb, start, &length, &item_length);
1832 test_length(hfinfo, tree, tvb, start, item_length, encoding);
1834 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1836 new_fi = new_field_info(tree, hfinfo, tvb, start, item_length);
1841 return proto_tree_new_item(new_fi, tree, tvb, start, length, encoding);
1844 /* Add a FT_NONE to a proto_tree */
1846 proto_tree_add_none_format(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
1847 const gint start, gint length, const char *format,
1852 header_field_info *hfinfo;
1855 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1857 DISSECTOR_ASSERT(hfinfo->type == FT_NONE);
1859 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length, &new_fi);
1861 TRY_TO_FAKE_THIS_REPR(pi);
1863 va_start(ap, format);
1864 proto_tree_set_representation(pi, format, ap);
1867 /* no value to set for FT_NONE */
1871 /* Gets data from tvbuff, adds it to proto_tree, *DOES NOT* increment
1872 * offset, and returns proto_item* */
1874 ptvcursor_add_no_advance(ptvcursor_t* ptvc, int hf, gint length,
1875 const guint encoding)
1879 item = proto_tree_add_item(ptvc->tree, hf, ptvc->tvb, ptvc->offset,
1885 /* Advance the ptvcursor's offset within its tvbuff without
1886 * adding anything to the proto_tree. */
1888 ptvcursor_advance(ptvcursor_t* ptvc, gint length)
1890 ptvc->offset += length;
1895 proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb)
1897 fvalue_set(&fi->value, tvb, TRUE);
1900 /* Add a FT_PROTOCOL to a proto_tree */
1902 proto_tree_add_protocol_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1903 gint start, gint length, const char *format, ...)
1908 header_field_info *hfinfo;
1910 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1912 DISSECTOR_ASSERT(hfinfo->type == FT_PROTOCOL);
1914 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length, &new_fi);
1916 proto_tree_set_protocol_tvb(new_fi, (start == 0 ? tvb : tvb_new_subset(tvb, start, length, length)));
1918 TRY_TO_FAKE_THIS_REPR(pi);
1920 va_start(ap, format);
1921 proto_tree_set_representation(pi, format, ap);
1928 /* Add a FT_BYTES to a proto_tree */
1930 proto_tree_add_bytes(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1931 gint length, const guint8 *start_ptr)
1935 header_field_info *hfinfo;
1937 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1939 DISSECTOR_ASSERT(hfinfo->type == FT_BYTES);
1941 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length, &new_fi);
1942 proto_tree_set_bytes(new_fi, start_ptr, length);
1948 proto_tree_add_bytes_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1949 gint start, gint length,
1950 const guint8 *start_ptr,
1951 const char *format, ...)
1955 header_field_info *hfinfo;
1957 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1960 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length,
1963 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length,
1964 tvb_get_ptr(tvb, start, length));
1966 va_start(ap, format);
1967 proto_tree_set_representation_value(pi, format, ap);
1974 proto_tree_add_bytes_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1975 gint start, gint length, const guint8 *start_ptr,
1976 const char *format, ...)
1980 header_field_info *hfinfo;
1982 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1985 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length,
1988 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length,
1989 tvb_get_ptr(tvb, start, length));
1991 TRY_TO_FAKE_THIS_REPR(pi);
1993 va_start(ap, format);
1994 proto_tree_set_representation(pi, format, ap);
2001 proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length)
2005 bytes = g_byte_array_new();
2007 g_byte_array_append(bytes, start_ptr, length);
2009 fvalue_set(&fi->value, bytes, TRUE);
2014 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length)
2016 proto_tree_set_bytes(fi, tvb_get_ptr(tvb, offset, length), length);
2019 /* Add a FT_*TIME to a proto_tree */
2021 proto_tree_add_time(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2022 gint length, nstime_t *value_ptr)
2026 header_field_info *hfinfo;
2028 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2030 DISSECTOR_ASSERT(hfinfo->type == FT_ABSOLUTE_TIME ||
2031 hfinfo->type == FT_RELATIVE_TIME);
2033 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length, &new_fi);
2034 proto_tree_set_time(new_fi, value_ptr);
2040 proto_tree_add_time_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2041 gint start, gint length, nstime_t *value_ptr,
2042 const char *format, ...)
2047 pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
2049 va_start(ap, format);
2050 proto_tree_set_representation_value(pi, format, ap);
2058 proto_tree_add_time_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2059 gint start, gint length, nstime_t *value_ptr,
2060 const char *format, ...)
2065 pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
2067 TRY_TO_FAKE_THIS_REPR(pi);
2069 va_start(ap, format);
2070 proto_tree_set_representation(pi, format, ap);
2077 /* Set the FT_*TIME value */
2079 proto_tree_set_time(field_info *fi, nstime_t *value_ptr)
2081 DISSECTOR_ASSERT(value_ptr != NULL);
2083 fvalue_set(&fi->value, value_ptr, FALSE);
2086 /* Add a FT_IPXNET to a proto_tree */
2088 proto_tree_add_ipxnet(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2089 gint length, guint32 value)
2093 header_field_info *hfinfo;
2095 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2097 DISSECTOR_ASSERT(hfinfo->type == FT_IPXNET);
2099 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length, &new_fi);
2100 proto_tree_set_ipxnet(new_fi, value);
2106 proto_tree_add_ipxnet_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2107 gint start, gint length, guint32 value,
2108 const char *format, ...)
2113 pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
2115 va_start(ap, format);
2116 proto_tree_set_representation_value(pi, format, ap);
2124 proto_tree_add_ipxnet_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2125 gint start, gint length, guint32 value,
2126 const char *format, ...)
2131 pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
2133 TRY_TO_FAKE_THIS_REPR(pi);
2135 va_start(ap, format);
2136 proto_tree_set_representation(pi, format, ap);
2143 /* Set the FT_IPXNET value */
2145 proto_tree_set_ipxnet(field_info *fi, guint32 value)
2147 fvalue_set_uinteger(&fi->value, value);
2150 /* Add a FT_IPv4 to a proto_tree */
2152 proto_tree_add_ipv4(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2153 gint length, guint32 value)
2157 header_field_info *hfinfo;
2159 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2161 DISSECTOR_ASSERT(hfinfo->type == FT_IPv4);
2163 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length, &new_fi);
2164 proto_tree_set_ipv4(new_fi, value);
2170 proto_tree_add_ipv4_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2171 gint start, gint length, guint32 value,
2172 const char *format, ...)
2177 pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
2179 va_start(ap, format);
2180 proto_tree_set_representation_value(pi, format, ap);
2188 proto_tree_add_ipv4_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2189 gint start, gint length, guint32 value,
2190 const char *format, ...)
2195 pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
2197 TRY_TO_FAKE_THIS_REPR(pi);
2199 va_start(ap, format);
2200 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, hfinfo, 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, ...)
2242 pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
2244 va_start(ap, format);
2245 proto_tree_set_representation_value(pi, format, ap);
2253 proto_tree_add_ipv6_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2254 gint start, gint length, const guint8* value_ptr,
2255 const char *format, ...)
2260 pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
2262 TRY_TO_FAKE_THIS_REPR(pi);
2264 va_start(ap, format);
2265 proto_tree_set_representation(pi, format, ap);
2272 /* Set the FT_IPv6 value */
2274 proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr)
2276 DISSECTOR_ASSERT(value_ptr != NULL);
2277 fvalue_set(&fi->value, (gpointer) value_ptr, FALSE);
2281 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
2283 proto_tree_set_ipv6(fi, tvb_get_ptr(tvb, start, length));
2286 /* Add a FT_GUID to a proto_tree */
2288 proto_tree_add_guid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2289 gint length, const e_guid_t *value_ptr)
2293 header_field_info *hfinfo;
2295 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2297 DISSECTOR_ASSERT(hfinfo->type == FT_GUID);
2299 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length, &new_fi);
2300 proto_tree_set_guid(new_fi, value_ptr);
2306 proto_tree_add_guid_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2307 gint start, gint length,
2308 const e_guid_t *value_ptr,
2309 const char *format, ...)
2314 pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
2316 va_start(ap, format);
2317 proto_tree_set_representation_value(pi, format, ap);
2325 proto_tree_add_guid_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2326 gint start, gint length, const e_guid_t *value_ptr,
2327 const char *format, ...)
2332 pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
2334 TRY_TO_FAKE_THIS_REPR(pi);
2336 va_start(ap, format);
2337 proto_tree_set_representation(pi, format, ap);
2344 /* Set the FT_GUID value */
2346 proto_tree_set_guid(field_info *fi, const e_guid_t *value_ptr)
2348 DISSECTOR_ASSERT(value_ptr != NULL);
2349 fvalue_set(&fi->value, (gpointer) value_ptr, FALSE);
2353 proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, gint start,
2354 const guint encoding)
2358 tvb_get_guid(tvb, start, &guid, encoding);
2359 proto_tree_set_guid(fi, &guid);
2362 /* Add a FT_OID to a proto_tree */
2364 proto_tree_add_oid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2365 gint length, const guint8* value_ptr)
2369 header_field_info *hfinfo;
2371 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2373 DISSECTOR_ASSERT(hfinfo->type == FT_OID);
2375 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length, &new_fi);
2376 proto_tree_set_oid(new_fi, value_ptr, length);
2382 proto_tree_add_oid_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2383 gint start, gint length,
2384 const guint8* value_ptr,
2385 const char *format, ...)
2390 pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
2392 va_start(ap, format);
2393 proto_tree_set_representation_value(pi, format, ap);
2401 proto_tree_add_oid_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2402 gint start, gint length, const guint8* value_ptr,
2403 const char *format, ...)
2408 pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
2410 TRY_TO_FAKE_THIS_REPR(pi);
2412 va_start(ap, format);
2413 proto_tree_set_representation(pi, format, ap);
2420 /* Set the FT_OID value */
2422 proto_tree_set_oid(field_info *fi, const guint8* value_ptr, gint length)
2426 DISSECTOR_ASSERT(value_ptr != NULL);
2428 bytes = g_byte_array_new();
2430 g_byte_array_append(bytes, value_ptr, length);
2432 fvalue_set(&fi->value, bytes, TRUE);
2436 proto_tree_set_oid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
2438 proto_tree_set_oid(fi, tvb_get_ptr(tvb, start, length), length);
2442 proto_tree_set_uint64(field_info *fi, guint64 value)
2444 fvalue_set_integer64(&fi->value, value);
2448 * NOTE: to support code written when proto_tree_add_item() took a
2449 * gboolean as its last argument, with FALSE meaning "big-endian"
2450 * and TRUE meaning "little-endian", we treat any non-zero value of
2451 * "encoding" as meaning "little-endian".
2454 proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start,
2455 guint length, const guint encoding)
2458 guint8* b = (guint8 *)ep_tvb_memdup(tvb, start, length);
2463 default: DISSECTOR_ASSERT_NOT_REACHED();
2464 case 8: value <<= 8; value += *--b;
2465 case 7: value <<= 8; value += *--b;
2466 case 6: value <<= 8; value += *--b;
2467 case 5: value <<= 8; value += *--b;
2468 case 4: value <<= 8; value += *--b;
2469 case 3: value <<= 8; value += *--b;
2470 case 2: value <<= 8; value += *--b;
2471 case 1: value <<= 8; value += *--b;
2476 default: DISSECTOR_ASSERT_NOT_REACHED();
2477 case 8: value <<= 8; value += *b++;
2478 case 7: value <<= 8; value += *b++;
2479 case 6: value <<= 8; value += *b++;
2480 case 5: value <<= 8; value += *b++;
2481 case 4: value <<= 8; value += *b++;
2482 case 3: value <<= 8; value += *b++;
2483 case 2: value <<= 8; value += *b++;
2484 case 1: value <<= 8; value += *b++;
2489 proto_tree_set_uint64(fi, value);
2492 /* Add a FT_STRING or FT_STRINGZ to a proto_tree. Creates own copy of string,
2493 * and frees it when the proto_tree is destroyed. */
2495 proto_tree_add_string(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2496 gint length, const char* value)
2500 header_field_info *hfinfo;
2502 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2504 DISSECTOR_ASSERT(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ);
2506 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length, &new_fi);
2507 DISSECTOR_ASSERT(length >= 0);
2508 proto_tree_set_string(new_fi, value);
2514 proto_tree_add_unicode_string(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2515 gint length, const char* value)
2517 DISSECTOR_ASSERT(g_utf8_validate(value, -1, NULL));
2518 return proto_tree_add_string_format_value(tree, hfindex, tvb, start, length, value, "%s", value);
2522 proto_tree_add_string_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2523 gint start, gint length, const char* value,
2530 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
2532 va_start(ap, format);
2533 proto_tree_set_representation_value(pi, format, ap);
2541 proto_tree_add_string_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2542 gint start, gint length, const char* value,
2543 const char *format, ...)
2548 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
2550 TRY_TO_FAKE_THIS_REPR(pi);
2552 va_start(ap, format);
2553 proto_tree_set_representation(pi, format, ap);
2560 /* Appends string data to a FT_STRING or FT_STRINGZ, allowing progressive
2561 * field info update instead of only updating the representation as does
2562 * proto_item_append_text()
2564 /* NOTE: this function will break with the TRY_TO_FAKE_THIS_ITEM()
2565 * speed optimization.
2566 * Currently only WSP use this function so it is not that bad but try to
2567 * avoid using this one if possible.
2568 * IF you must use this function you MUST also disable the
2569 * TRY_TO_FAKE_THIS_ITEM() optimization for your dissector/function
2570 * using proto_item_append_string().
2571 * Do that by faking that the tree is visible by calling
2572 * proto_tree_set_visible(tree, TRUE) (see packet-wsp.c)
2573 * BEFORE you create the item you are later going to use
2574 * proto_item_append_string() on.
2577 proto_item_append_string(proto_item *pi, const char *str)
2580 header_field_info *hfinfo;
2581 const gchar *old_str, *new_str;
2588 fi = PITEM_FINFO(pi);
2589 DISSECTOR_ASSERT_HINT(fi, "proto_tree_set_visible(tree, TRUE) should have been called previously");
2591 hfinfo = fi->hfinfo;
2592 if (hfinfo->type == FT_PROTOCOL) {
2593 /* TRY_TO_FAKE_THIS_ITEM() speed optimization: silently skip */
2596 DISSECTOR_ASSERT(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ);
2597 old_str = (guint8 *)fvalue_get(&fi->value);
2598 if (old_str && old_str[0])
2599 new_str = ep_strconcat(old_str, str, NULL);
2602 fvalue_set(&fi->value, (gpointer) new_str, FALSE);
2605 /* Set the FT_STRING value */
2607 proto_tree_set_string(field_info *fi, const char* value)
2610 fvalue_set(&fi->value, (gpointer) value, FALSE);
2612 fvalue_set(&fi->value, (gpointer) "[ Null ]", FALSE);
2617 proto_tree_set_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length, gint encoding)
2622 length = tvb_ensure_length_remaining(tvb, start);
2625 string = tvb_get_ephemeral_string_enc(tvb, start, length, encoding);
2626 proto_tree_set_string(fi, string);
2630 /* Add a FT_AX25 to a proto_tree */
2632 proto_tree_add_ax25(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2633 const guint8* value)
2637 header_field_info *hfinfo;
2639 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2641 DISSECTOR_ASSERT(hfinfo->type == FT_AX25);
2643 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length, &new_fi);
2644 proto_tree_set_ax25(new_fi, value);
2649 /* Set the FT_AX25 value */
2651 proto_tree_set_ax25(field_info *fi, const guint8* value)
2653 fvalue_set(&fi->value, (gpointer) value, FALSE);
2657 proto_tree_set_ax25_tvb(field_info *fi, tvbuff_t *tvb, gint start)
2659 proto_tree_set_ax25(fi, tvb_get_ptr(tvb, start, 7));
2662 /* Set the FT_VINES value */
2664 proto_tree_set_vines(field_info *fi, const guint8* value)
2666 fvalue_set(&fi->value, (gpointer) value, FALSE);
2670 proto_tree_set_vines_tvb(field_info *fi, tvbuff_t *tvb, gint start)
2672 proto_tree_set_vines(fi, tvb_get_ptr(tvb, start, FT_VINES_ADDR_LEN));
2675 /* Add a FT_ETHER to a proto_tree */
2677 proto_tree_add_ether(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2678 gint length, const guint8* value)
2682 header_field_info *hfinfo;
2684 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2686 DISSECTOR_ASSERT(hfinfo->type == FT_ETHER);
2688 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length, &new_fi);
2689 proto_tree_set_ether(new_fi, value);
2695 proto_tree_add_ether_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2696 gint start, gint length, const guint8* value,
2697 const char *format, ...)
2702 pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
2704 va_start(ap, format);
2705 proto_tree_set_representation_value(pi, format, ap);
2713 proto_tree_add_ether_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2714 gint start, gint length, const guint8* value,
2715 const char *format, ...)
2720 pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
2722 TRY_TO_FAKE_THIS_REPR(pi);
2724 va_start(ap, format);
2725 proto_tree_set_representation(pi, format, ap);
2732 /* Set the FT_ETHER value */
2734 proto_tree_set_ether(field_info *fi, const guint8* value)
2736 fvalue_set(&fi->value, (gpointer) value, FALSE);
2740 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start)
2742 proto_tree_set_ether(fi, tvb_get_ptr(tvb, start, FT_ETHER_LEN));
2745 /* Add a FT_BOOLEAN to a proto_tree */
2747 proto_tree_add_boolean(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2748 gint length, guint32 value)
2752 header_field_info *hfinfo;
2754 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2756 DISSECTOR_ASSERT(hfinfo->type == FT_BOOLEAN);
2758 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length, &new_fi);
2759 proto_tree_set_boolean(new_fi, value);
2765 proto_tree_add_boolean_format_value(proto_tree *tree, int hfindex,
2766 tvbuff_t *tvb, gint start, gint length,
2767 guint32 value, const char *format, ...)
2772 pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
2774 va_start(ap, format);
2775 proto_tree_set_representation_value(pi, format, ap);
2783 proto_tree_add_boolean_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2784 gint start, gint length, guint32 value,
2785 const char *format, ...)
2790 pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
2792 TRY_TO_FAKE_THIS_REPR(pi);
2794 va_start(ap, format);
2795 proto_tree_set_representation(pi, format, ap);
2802 /* Set the FT_BOOLEAN value */
2804 proto_tree_set_boolean(field_info *fi, guint32 value)
2806 proto_tree_set_uint(fi, value);
2809 /* Add a FT_FLOAT to a proto_tree */
2811 proto_tree_add_float(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2812 gint length, float value)
2816 header_field_info *hfinfo;
2818 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2820 DISSECTOR_ASSERT(hfinfo->type == FT_FLOAT);
2822 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length, &new_fi);
2823 proto_tree_set_float(new_fi, value);
2829 proto_tree_add_float_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2830 gint start, gint length, float value,
2831 const char *format, ...)
2836 pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
2838 va_start(ap, format);
2839 proto_tree_set_representation_value(pi, format, ap);
2847 proto_tree_add_float_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2848 gint start, gint length, float value,
2849 const char *format, ...)
2854 pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
2856 TRY_TO_FAKE_THIS_REPR(pi);
2858 va_start(ap, format);
2859 proto_tree_set_representation(pi, format, ap);
2866 /* Set the FT_FLOAT value */
2868 proto_tree_set_float(field_info *fi, float value)
2870 fvalue_set_floating(&fi->value, value);
2873 /* Add a FT_DOUBLE to a proto_tree */
2875 proto_tree_add_double(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2876 gint length, double value)
2880 header_field_info *hfinfo;
2882 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2884 DISSECTOR_ASSERT(hfinfo->type == FT_DOUBLE);
2886 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length, &new_fi);
2887 proto_tree_set_double(new_fi, value);
2893 proto_tree_add_double_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2894 gint start, gint length, double value,
2895 const char *format, ...)
2900 pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
2902 va_start(ap, format);
2903 proto_tree_set_representation_value(pi, format, ap);
2911 proto_tree_add_double_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2912 gint start, gint length, double value,
2913 const char *format, ...)
2918 pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
2920 TRY_TO_FAKE_THIS_REPR(pi);
2922 va_start(ap, format);
2923 proto_tree_set_representation(pi, format, ap);
2930 /* Set the FT_DOUBLE value */
2932 proto_tree_set_double(field_info *fi, double value)
2934 fvalue_set_floating(&fi->value, value);
2937 /* Add FT_UINT{8,16,24,32} to a proto_tree */
2939 proto_tree_add_uint(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2940 gint length, guint32 value)
2942 proto_item *pi = NULL;
2944 header_field_info *hfinfo;
2946 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2948 switch (hfinfo->type) {
2954 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length,
2956 proto_tree_set_uint(new_fi, value);
2960 DISSECTOR_ASSERT_NOT_REACHED();
2967 proto_tree_add_uint_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2968 gint start, gint length, guint32 value,
2969 const char *format, ...)
2974 pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
2976 va_start(ap, format);
2977 proto_tree_set_representation_value(pi, format, ap);
2985 proto_tree_add_uint_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2986 gint start, gint length, guint32 value,
2987 const char *format, ...)
2992 pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
2994 TRY_TO_FAKE_THIS_REPR(pi);
2996 va_start(ap, format);
2997 proto_tree_set_representation(pi, format, ap);
3004 /* Set the FT_UINT{8,16,24,32} value */
3006 proto_tree_set_uint(field_info *fi, guint32 value)
3008 header_field_info *hfinfo;
3011 hfinfo = fi->hfinfo;
3014 if (hfinfo->bitmask) {
3015 /* Mask out irrelevant portions */
3016 integer &= hfinfo->bitmask;
3019 if (hfinfo->bitshift > 0) {
3020 integer >>= hfinfo->bitshift;
3024 fvalue_set_uinteger(&fi->value, integer);
3027 /* Add FT_UINT64 to a proto_tree */
3029 proto_tree_add_uint64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3030 gint length, guint64 value)
3032 proto_item *pi = NULL;
3034 header_field_info *hfinfo;
3036 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3038 DISSECTOR_ASSERT(hfinfo->type == FT_UINT64);
3040 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length, &new_fi);
3041 proto_tree_set_uint64(new_fi, value);
3047 proto_tree_add_uint64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3048 gint start, gint length, guint64 value,
3049 const char *format, ...)
3054 pi = proto_tree_add_uint64(tree, hfindex, tvb, start, length, value);
3056 va_start(ap, format);
3057 proto_tree_set_representation_value(pi, format, ap);
3065 proto_tree_add_uint64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3066 gint start, gint length, guint64 value,
3067 const char *format, ...)
3072 pi = proto_tree_add_uint64(tree, hfindex, tvb, start, length, value);
3074 TRY_TO_FAKE_THIS_REPR(pi);
3076 va_start(ap, format);
3077 proto_tree_set_representation(pi, format, ap);
3084 /* Add FT_INT{8,16,24,32} to a proto_tree */
3086 proto_tree_add_int(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3087 gint length, gint32 value)
3089 proto_item *pi = NULL;
3091 header_field_info *hfinfo;
3093 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3095 switch (hfinfo->type) {
3100 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length,
3102 proto_tree_set_int(new_fi, value);
3106 DISSECTOR_ASSERT_NOT_REACHED();
3113 proto_tree_add_int_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3114 gint start, gint length, gint32 value,
3115 const char *format, ...)
3120 pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
3122 va_start(ap, format);
3123 proto_tree_set_representation_value(pi, format, ap);
3131 proto_tree_add_int_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3132 gint start, gint length, gint32 value,
3133 const char *format, ...)
3138 pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
3140 TRY_TO_FAKE_THIS_REPR(pi);
3142 va_start(ap, format);
3143 proto_tree_set_representation(pi, format, ap);
3150 /* Set the FT_INT{8,16,24,32} value */
3152 proto_tree_set_int(field_info *fi, gint32 value)
3154 header_field_info *hfinfo;
3157 hfinfo = fi->hfinfo;
3158 integer = (guint32) value;
3160 if (hfinfo->bitmask) {
3161 /* Mask out irrelevant portions */
3162 integer &= hfinfo->bitmask;
3165 if (hfinfo->bitshift > 0) {
3166 integer >>= hfinfo->bitshift;
3170 fvalue_set_sinteger(&fi->value, integer);
3173 /* Add FT_INT64 to a proto_tree */
3175 proto_tree_add_int64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3176 gint length, gint64 value)
3178 proto_item *pi = NULL;
3180 header_field_info *hfinfo;
3182 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3184 DISSECTOR_ASSERT(hfinfo->type == FT_INT64);
3186 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length, &new_fi);
3187 proto_tree_set_uint64(new_fi, (guint64)value);
3193 proto_tree_add_int64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3194 gint start, gint length, gint64 value,
3195 const char *format, ...)
3200 pi = proto_tree_add_int64(tree, hfindex, tvb, start, length, value);
3202 va_start(ap, format);
3203 proto_tree_set_representation_value(pi, format, ap);
3211 proto_tree_add_int64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3212 gint start, gint length, gint64 value,
3213 const char *format, ...)
3218 pi = proto_tree_add_int64(tree, hfindex, tvb, start, length, value);
3220 TRY_TO_FAKE_THIS_REPR(pi);
3222 va_start(ap, format);
3223 proto_tree_set_representation(pi, format, ap);
3229 /* Add a FT_EUI64 to a proto_tree */
3231 proto_tree_add_eui64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3232 gint length, const guint64 value)
3236 header_field_info *hfinfo;
3238 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3240 DISSECTOR_ASSERT(hfinfo->type == FT_EUI64);
3242 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length, &new_fi);
3243 proto_tree_set_eui64(new_fi, value);
3249 proto_tree_add_eui64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3250 gint start, gint length, const guint64 value,
3251 const char *format, ...)
3256 pi = proto_tree_add_eui64(tree, hfindex, tvb, start, length, value);
3258 va_start(ap, format);
3259 proto_tree_set_representation_value(pi, format, ap);
3267 proto_tree_add_eui64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3268 gint start, gint length, const guint64 value,
3269 const char *format, ...)
3274 pi = proto_tree_add_eui64(tree, hfindex, tvb, start, length, value);
3276 TRY_TO_FAKE_THIS_REPR(pi);
3278 va_start(ap, format);
3279 proto_tree_set_representation(pi, format, ap);
3286 /* Set the FT_EUI64 value */
3288 proto_tree_set_eui64(field_info *fi, const guint64 value)
3290 fvalue_set_integer64(&fi->value, value);
3293 proto_tree_set_eui64_tvb(field_info *fi, tvbuff_t *tvb, gint start, const guint encoding)
3297 proto_tree_set_eui64(fi, tvb_get_letoh64(tvb, start));
3299 proto_tree_set_eui64(fi, tvb_get_ntoh64(tvb, start));
3303 /* Add a field_info struct to the proto_tree, encapsulating it in a proto_node */
3305 proto_tree_add_node(proto_tree *tree, field_info *fi)
3307 proto_node *pnode, *tnode, *sibling;
3311 * Make sure "tree" is ready to have subtrees under it, by
3312 * checking whether it's been given an ett_ value.
3314 * "PNODE_FINFO(tnode)" may be null; that's the case for the root
3315 * node of the protocol tree. That node is not displayed,
3316 * so it doesn't need an ett_ value to remember whether it
3320 tfi = PNODE_FINFO(tnode);
3321 if (tfi != NULL && (tfi->tree_type < 0 || tfi->tree_type >= num_tree_types)) {
3322 REPORT_DISSECTOR_BUG(ep_strdup_printf("\"%s\" - \"%s\" tfi->tree_type: %u invalid (%s:%u)",
3323 fi->hfinfo->name, fi->hfinfo->abbrev, tfi->tree_type, __FILE__, __LINE__));
3324 /* XXX - is it safe to continue here? */
3327 PROTO_NODE_NEW(pnode);
3328 pnode->parent = tnode;
3329 PNODE_FINFO(pnode) = fi;
3330 pnode->tree_data = PTREE_DATA(tree);
3332 if (tnode->last_child != NULL) {
3333 sibling = tnode->last_child;
3334 DISSECTOR_ASSERT(sibling->next == NULL);
3335 sibling->next = pnode;
3337 tnode->first_child = pnode;
3338 tnode->last_child = pnode;
3340 tree_data_add_maybe_interesting_field(pnode->tree_data, fi);
3342 return (proto_item *)pnode;
3346 /* Generic way to allocate field_info and add to proto_tree.
3347 * Sets *pfi to address of newly-allocated field_info struct */
3349 proto_tree_add_pi(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb, gint start,
3350 gint *length, field_info **pfi)
3355 fi = alloc_field_info(tree, hfinfo, tvb, start, length);
3356 pi = proto_tree_add_node(tree, fi);
3365 get_hfi_length(header_field_info *hfinfo, tvbuff_t *tvb, const gint start, gint *length,
3368 gint length_remaining;
3371 * We only allow a null tvbuff if the item has a zero length,
3372 * i.e. if there's no data backing it.
3374 DISSECTOR_ASSERT(tvb != NULL || *length == 0);
3377 * XXX - in some protocols, there are 32-bit unsigned length
3378 * fields, so lengths in protocol tree and tvbuff routines
3379 * should really be unsigned. We should have, for those
3380 * field types for which "to the end of the tvbuff" makes sense,
3381 * additional routines that take no length argument and
3382 * add fields that run to the end of the tvbuff.
3384 if (*length == -1) {
3386 * For FT_NONE, FT_PROTOCOL, FT_BYTES, and FT_STRING fields,
3387 * a length of -1 means "set the length to what remains in
3390 * The assumption is either that
3392 * 1) the length of the item can only be determined
3393 * by dissection (typically true of items with
3394 * subitems, which are probably FT_NONE or
3399 * 2) if the tvbuff is "short" (either due to a short
3400 * snapshot length or due to lack of reassembly of
3401 * fragments/segments/whatever), we want to display
3402 * what's available in the field (probably FT_BYTES
3403 * or FT_STRING) and then throw an exception later
3407 * 3) the field is defined to be "what's left in the
3410 * so we set the length to what remains in the tvbuff so
3411 * that, if we throw an exception while dissecting, it
3412 * has what is probably the right value.
3414 * For FT_STRINGZ, it means "the string is null-terminated,
3415 * not null-padded; set the length to the actual length
3416 * of the string", and if the tvbuff if short, we just
3417 * throw an exception.
3419 * It's not valid for any other type of field.
3421 switch (hfinfo->type) {
3425 * We allow this to be zero-length - for
3426 * example, an ONC RPC NULL procedure has
3427 * neither arguments nor reply, so the
3428 * payload for that protocol is empty.
3430 * However, if the length is negative, the
3431 * start offset is *past* the byte past the
3432 * end of the tvbuff, so we throw an
3435 *length = tvb_length_remaining(tvb, start);
3438 * Use "tvb_ensure_bytes_exist()"
3439 * to force the appropriate exception
3442 tvb_ensure_bytes_exist(tvb, start, 0);
3444 DISSECTOR_ASSERT(*length >= 0);
3450 *length = tvb_ensure_length_remaining(tvb, start);
3451 DISSECTOR_ASSERT(*length >= 0);
3456 * Leave the length as -1, so our caller knows
3462 DISSECTOR_ASSERT_NOT_REACHED();
3464 *item_length = *length;
3466 *item_length = *length;
3467 if (hfinfo->type == FT_PROTOCOL || hfinfo->type == FT_NONE) {
3469 * These types are for interior nodes of the
3470 * tree, and don't have data associated with
3471 * them; if the length is negative (XXX - see
3472 * above) or goes past the end of the tvbuff,
3473 * cut it short at the end of the tvbuff.
3474 * That way, if this field is selected in
3475 * Wireshark, we don't highlight stuff past
3476 * the end of the data.
3478 /* XXX - what to do, if we don't have a tvb? */
3480 length_remaining = tvb_length_remaining(tvb, start);
3481 if (*item_length < 0 ||
3482 (*item_length > 0 &&
3483 (length_remaining < *item_length)))
3484 *item_length = length_remaining;
3487 if (*item_length < 0) {
3488 THROW(ReportedBoundsError);
3494 new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
3495 const gint start, const gint item_length)
3501 fi->hfinfo = hfinfo;
3503 fi->start += (tvb)?tvb_raw_offset(tvb):0;
3504 fi->length = item_length;
3507 if (!PTREE_DATA(tree)->visible)
3508 FI_SET_FLAG(fi, FI_HIDDEN);
3509 fvalue_init(&fi->value, fi->hfinfo->type);
3512 /* add the data source tvbuff */
3513 fi->ds_tvb = tvb ? tvb_get_ds_tvb(tvb) : NULL;
3515 fi->appendix_start = 0;
3516 fi->appendix_length = 0;
3522 alloc_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb, const gint start,
3527 get_hfi_length(hfinfo, tvb, start, length, &item_length);
3528 return new_field_info(tree, hfinfo, tvb, start, item_length);
3531 /* If the protocol tree is to be visible, set the representation of a
3532 proto_tree entry with the name of the field for the item and with
3533 the value formatted with the supplied printf-style format and
3536 proto_tree_set_representation_value(proto_item *pi, const char *format, va_list ap)
3540 /* If the tree (GUI) or item isn't visible it's pointless for us to generate the protocol
3541 * items string representation */
3542 if (PTREE_DATA(pi)->visible && !PROTO_ITEM_IS_HIDDEN(pi)) {
3544 field_info *fi = PITEM_FINFO(pi);
3545 header_field_info *hf;
3547 DISSECTOR_ASSERT(fi);
3551 ITEM_LABEL_NEW(fi->rep);
3552 if (hf->bitmask && (hf->type == FT_BOOLEAN || IS_FT_UINT(hf->type))) {
3556 val = fvalue_get_uinteger(&fi->value);
3557 if (hf->bitshift > 0)
3558 val <<= hf->bitshift;
3560 p = decode_bitfield_value(fi->rep->representation, val, hf->bitmask, hfinfo_bitwidth(hf));
3561 ret = (int) (p - fi->rep->representation);
3564 /* put in the hf name */
3565 ret += g_snprintf(fi->rep->representation + ret, ITEM_LABEL_LENGTH - ret, "%s: ", hf->name);
3567 /* If possible, Put in the value of the string */
3568 if (ret < ITEM_LABEL_LENGTH) {
3569 ret += g_vsnprintf(fi->rep->representation + ret,
3570 ITEM_LABEL_LENGTH - ret, format, ap);
3572 if (ret >= ITEM_LABEL_LENGTH) {
3573 /* Uh oh, we don't have enough room. Tell the user
3574 * that the field is truncated.
3578 /* Argh, we cannot reuse 'ap' here. So make a copy
3579 * of what we formatted for (re)use below.
3581 oldrep = g_strdup(fi->rep->representation);
3583 g_snprintf(fi->rep->representation,
3592 /* If the protocol tree is to be visible, set the representation of a
3593 proto_tree entry with the representation formatted with the supplied
3594 printf-style format and argument list. */
3596 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap)
3598 int ret; /*tmp return value */
3599 field_info *fi = PITEM_FINFO(pi);
3601 DISSECTOR_ASSERT(fi);
3603 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
3604 ITEM_LABEL_NEW(fi->rep);
3605 ret = g_vsnprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
3607 if (ret >= ITEM_LABEL_LENGTH) {
3608 /* Uh oh, we don't have enough room. Tell the user
3609 * that the field is truncated.
3613 /* Argh, we cannot reuse 'ap' here. So make a copy
3614 * of what we formatted for (re)use below.
3616 oldrep = g_strdup(fi->rep->representation);
3618 g_snprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
3619 "[truncated] %s", oldrep);
3626 protoo_strlcpy(gchar *dest, const gchar *src, gsize dest_size)
3628 gsize res = g_strlcpy(dest, src, dest_size);
3630 if (res > dest_size)
3635 /* -------------------------- */
3637 proto_custom_set(proto_tree* tree, const int field_id, gint occurrence,
3638 gchar *result, gchar *expr, const int size)
3643 struct e_in6_addr *ipv6;
3645 guint32 n_addr; /* network-order IPv4 address */
3647 const true_false_string *tfstring;
3649 int len, prev_len = 0, last, i, offset_r = 0, offset_e = 0;
3651 field_info *finfo = NULL;
3652 header_field_info* hfinfo;
3653 const gchar *abbrev = NULL;
3655 const char *hf_str_val;
3656 char number_buf[32];
3657 const char *number_out;
3659 g_assert(field_id >= 0);
3661 hfinfo = proto_registrar_get_nth((guint)field_id);
3663 /* do we need to rewind ? */
3667 if (occurrence < 0) {
3668 /* Search other direction */
3669 while (hfinfo->same_name_prev) {
3670 hfinfo = hfinfo->same_name_prev;
3675 finfos = proto_get_finfo_ptr_array(tree, hfinfo->id);
3677 if (!finfos || !(len = g_ptr_array_len(finfos))) {
3678 if (occurrence < 0) {
3679 hfinfo = hfinfo->same_name_next;
3681 hfinfo = hfinfo->same_name_prev;
3686 /* Are there enough occurrences of the field? */
3687 if (((occurrence - prev_len) > len) || ((occurrence + prev_len) < -len)) {
3688 if (occurrence < 0) {
3689 hfinfo = hfinfo->same_name_next;
3691 hfinfo = hfinfo->same_name_prev;
3697 /* Calculate single index or set outer bounderies */
3698 if (occurrence < 0) {
3699 i = occurrence + len + prev_len;
3701 } else if (occurrence > 0) {
3702 i = occurrence - 1 - prev_len;
3709 prev_len += len; /* Count handled occurrences */
3712 finfo = (field_info *)g_ptr_array_index(finfos, i);
3714 if (offset_r && (offset_r < (size - 2)))
3715 result[offset_r++] = ',';
3717 if (offset_e && (offset_e < (size - 2)))
3718 expr[offset_e++] = ',';
3720 switch (hfinfo->type) {
3722 case FT_NONE: /* Nothing to add */
3723 if (offset_r == 0) {
3725 } else if (result[offset_r-1] == ',') {
3726 result[offset_r-1] = '\0';
3731 /* prevent multiple "yes" entries by setting result directly */
3732 g_strlcpy(result, "Yes", size);
3737 bytes = (guint8 *)fvalue_get(&finfo->value);
3738 offset_r += protoo_strlcpy(result+offset_r,
3740 fvalue_length(&finfo->value)),
3744 case FT_ABSOLUTE_TIME:
3745 offset_r += protoo_strlcpy(result+offset_r,
3746 abs_time_to_str((const nstime_t *)fvalue_get(&finfo->value),
3747 (absolute_time_display_e)hfinfo->display, TRUE),
3751 case FT_RELATIVE_TIME:
3752 offset_r += protoo_strlcpy(result+offset_r,
3753 rel_time_to_secs_str((const nstime_t *)fvalue_get(&finfo->value)),
3758 number = fvalue_get_uinteger(&finfo->value);
3759 tfstring = (const true_false_string *)&tfs_true_false;
3760 if (hfinfo->strings) {
3761 tfstring = (const struct true_false_string*) hfinfo->strings;
3763 offset_r += protoo_strlcpy(result+offset_r,
3765 tfstring->true_string :
3766 tfstring->false_string, size-offset_r);
3768 offset_e += protoo_strlcpy(expr+offset_e,
3769 number ? "1" : "0", size-offset_e);
3772 /* XXX - make these just FT_NUMBER? */
3783 number = IS_FT_INT(hfinfo->type) ?
3784 (guint32) fvalue_get_sinteger(&finfo->value) :
3785 fvalue_get_uinteger(&finfo->value);
3787 if ((hfinfo->display & BASE_DISPLAY_E_MASK) == BASE_CUSTOM) {
3788 gchar tmp[ITEM_LABEL_LENGTH];
3789 custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hfinfo->strings;
3791 DISSECTOR_ASSERT(fmtfunc);
3792 fmtfunc(tmp, number);
3794 offset_r += protoo_strlcpy(result+offset_r, tmp, size-offset_r);
3796 } else if (hfinfo->strings) {
3797 number_out = hf_str_val = hf_try_val_to_str(number, hfinfo);
3800 number_out = hfinfo_number_value_format_display(hfinfo, BASE_DEC, number_buf, number);
3802 offset_r += protoo_strlcpy(result+offset_r, number_out, size-offset_r);
3805 number_out = hfinfo_number_value_format(hfinfo, number_buf, number);
3807 offset_r += protoo_strlcpy(result+offset_r, number_out, size-offset_r);
3810 if (hf_str_val && (hfinfo->display & BASE_DISPLAY_E_MASK) == BASE_NONE) {
3811 g_snprintf(expr+offset_e, size-offset_e, "\"%s\"", hf_str_val);
3813 number_out = hfinfo_numeric_value_format(hfinfo, number_buf, number);
3815 g_strlcpy(expr+offset_e, number_out, size-offset_e);
3818 offset_e = (int)strlen(expr);
3822 /* XXX: Should handle BASE_CUSTOM ? */
3823 g_snprintf(result+offset_r, size-offset_r,
3824 "%" G_GINT64_MODIFIER "d",
3825 fvalue_get_integer64(&finfo->value));
3826 offset_r = (int)strlen(result);
3829 g_snprintf(result+offset_r, size-offset_r,
3830 /* XXX: Should handle BASE_CUSTOM ? */
3831 "%" G_GINT64_MODIFIER "u",
3832 fvalue_get_integer64(&finfo->value));
3833 offset_r = (int)strlen(result);
3836 offset_r += protoo_strlcpy(result+offset_r,
3837 eui64_to_str(fvalue_get_integer64(&finfo->value)),
3842 ipv4 = (ipv4_addr *)fvalue_get(&finfo->value);
3843 n_addr = ipv4_get_net_order_addr(ipv4);
3844 offset_r += protoo_strlcpy(result+offset_r,
3845 ip_to_str((guint8 *)&n_addr),
3850 ipv6 = (struct e_in6_addr *)fvalue_get(&finfo->value);
3851 SET_ADDRESS (&addr, AT_IPv6, sizeof(struct e_in6_addr), ipv6);
3852 address_to_str_buf(&addr, result+offset_r, size-offset_r);
3853 offset_r = (int)strlen(result);
3857 offset_r += protoo_strlcpy(result+offset_r,
3858 bytes_to_str_punct((const guint8 *)fvalue_get(&finfo->value),
3864 offset_r += protoo_strlcpy(result+offset_r,
3865 guid_to_str((e_guid_t *)fvalue_get(&finfo->value)),
3870 bytes = (guint8 *)fvalue_get(&finfo->value);
3871 offset_r += protoo_strlcpy(result+offset_r,
3872 oid_resolved_from_encoded(bytes,
3873 fvalue_length(&finfo->value)),
3875 offset_e += protoo_strlcpy(expr+offset_e,
3876 oid_encoded2string(bytes, fvalue_length(&finfo->value)),
3881 g_snprintf(result+offset_r, size-offset_r,
3882 "%." STRINGIFY(FLT_DIG) "g", fvalue_get_floating(&finfo->value));
3883 offset_r = (int)strlen(result);
3887 g_snprintf(result+offset_r, size-offset_r,
3888 "%." STRINGIFY(DBL_DIG) "g", fvalue_get_floating(&finfo->value));
3889 offset_r = (int)strlen(result);
3894 case FT_UINT_STRING:
3895 bytes = (guint8 *)fvalue_get(&finfo->value);
3896 offset_r += protoo_strlcpy(result+offset_r,
3897 format_text(bytes, strlen(bytes)),
3901 case FT_IPXNET: /*XXX really No column custom ?*/
3904 g_error("hfinfo->type %d (%s) not handled\n",
3906 ftype_name(hfinfo->type));
3907 DISSECTOR_ASSERT_NOT_REACHED();
3913 switch (hfinfo->type) {
3926 /* for these types, "expr" is filled in the loop above */
3930 /* for all others, just copy "result" to "expr" */
3931 g_strlcpy(expr, result, size);
3936 /* Store abbrev for return value */
3937 abbrev = hfinfo->abbrev;
3940 if (occurrence == 0) {
3941 /* Fetch next hfinfo with same name (abbrev) */
3942 hfinfo = hfinfo->same_name_prev;
3948 return abbrev ? abbrev : "";
3952 /* Set text of proto_item after having already been created. */
3954 proto_item_set_text(proto_item *pi, const char *format, ...)
3956 field_info *fi = NULL;
3963 fi = PITEM_FINFO(pi);
3968 ITEM_LABEL_FREE(fi->rep);
3972 va_start(ap, format);
3973 proto_tree_set_representation(pi, format, ap);
3977 /* Append to text of proto_item after having already been created. */
3979 proto_item_append_text(proto_item *pi, const char *format, ...)
3981 field_info *fi = NULL;
3989 fi = PITEM_FINFO(pi);
3994 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
3996 * If we don't already have a representation,
3997 * generate the default representation.
3999 if (fi->rep == NULL) {
4000 ITEM_LABEL_NEW(fi->rep);
4001 proto_item_fill_label(fi, fi->rep->representation);
4004 curlen = strlen(fi->rep->representation);
4005 if (ITEM_LABEL_LENGTH > curlen) {
4006 va_start(ap, format);
4007 g_vsnprintf(fi->rep->representation + curlen,
4008 ITEM_LABEL_LENGTH - (gulong) curlen, format, ap);
4014 /* Prepend to text of proto_item after having already been created. */
4016 proto_item_prepend_text(proto_item *pi, const char *format, ...)
4018 field_info *fi = NULL;
4019 char representation[ITEM_LABEL_LENGTH];
4026 fi = PITEM_FINFO(pi);
4031 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
4033 * If we don't already have a representation,
4034 * generate the default representation.
4036 if (fi->rep == NULL) {
4037 ITEM_LABEL_NEW(fi->rep);
4038 proto_item_fill_label(fi, representation);
4040 g_strlcpy(representation, fi->rep->representation, ITEM_LABEL_LENGTH);
4042 va_start(ap, format);
4043 g_vsnprintf(fi->rep->representation,
4044 ITEM_LABEL_LENGTH, format, ap);
4046 g_strlcat(fi->rep->representation, representation, ITEM_LABEL_LENGTH);
4051 proto_item_set_len(proto_item *pi, const gint length)
4058 fi = PITEM_FINFO(pi);
4062 DISSECTOR_ASSERT(length >= 0);
4063 fi->length = length;
4066 * You cannot just make the "len" field of a GByteArray
4067 * larger, if there's no data to back that length;
4068 * you can only make it smaller.
4070 if (fi->value.ftype->ftype == FT_BYTES && length <= (gint)fi->value.value.bytes->len)
4071 fi->value.value.bytes->len = length;
4075 * Sets the length of the item based on its start and on the specified
4076 * offset, which is the offset past the end of the item; as the start
4077 * in the item is relative to the beginning of the data source tvbuff,
4078 * we need to pass in a tvbuff - the end offset is relative to the beginning
4082 proto_item_set_end(proto_item *pi, tvbuff_t *tvb, gint end)
4089 fi = PITEM_FINFO(pi);
4093 end += tvb_raw_offset(tvb);
4094 DISSECTOR_ASSERT(end >= fi->start);
4095 fi->length = end - fi->start;
4099 proto_item_get_len(const proto_item *pi)
4101 field_info *fi = PITEM_FINFO(pi);
4102 return fi ? fi->length : -1;
4106 /** clear flags according to the mask and set new flag values */
4107 #define FI_REPLACE_FLAGS(fi, mask, flags_in) { \
4108 (fi->flags = (fi)->flags & ~(mask)); \
4109 (fi->flags = (fi)->flags | (flags_in)); \
4113 proto_item_set_expert_flags(proto_item *pi, const int group, const guint severity)
4115 if (pi == NULL || PITEM_FINFO(pi) == NULL)
4118 /* only change things if severity is worse or at least equal than before */
4119 if (severity >= FI_GET_FLAG(PITEM_FINFO(pi), PI_SEVERITY_MASK)) {
4120 FI_REPLACE_FLAGS(PITEM_FINFO(pi), PI_GROUP_MASK, group);
4121 FI_REPLACE_FLAGS(PITEM_FINFO(pi), PI_SEVERITY_MASK, severity);
4130 proto_tree_create_root(packet_info *pinfo)
4134 /* Initialize the proto_node */
4135 PROTO_NODE_NEW(pnode);
4136 pnode->parent = NULL;
4137 PNODE_FINFO(pnode) = NULL;
4138 pnode->tree_data = g_new(tree_data_t, 1);
4140 /* Make sure we can access pinfo everywhere */
4141 pnode->tree_data->pinfo = pinfo;
4143 /* Don't initialize the tree_data_t. Wait until we know we need it */
4144 pnode->tree_data->interesting_hfids = NULL;
4146 /* Set the default to FALSE so it's easier to
4147 * find errors; if we expect to see the protocol tree
4148 * but for some reason the default 'visible' is not
4149 * changed, then we'll find out very quickly. */
4150 pnode->tree_data->visible = FALSE;
4152 /* Make sure that we fake protocols (if possible) */
4153 pnode->tree_data->fake_protocols = TRUE;
4155 /* Keep track of the number of children */
4156 pnode->tree_data->count = 0;
4158 pnode->tree_data->fi_tmp = NULL;
4160 return (proto_tree *)pnode;
4164 /* "prime" a proto_tree with a single hfid that a dfilter
4165 * is interested in. */
4167 proto_tree_prime_hfid(proto_tree *tree _U_, const gint hfid)
4169 header_field_info *hfinfo;
4171 PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
4172 /* this field is referenced by a filter so increase the refcount.
4173 also increase the refcount for the parent, i.e the protocol.
4175 hfinfo->ref_type = HF_REF_TYPE_DIRECT;
4176 /* only increase the refcount if there is a parent.
4177 if this is a protocol and not a field then parent will be -1
4178 and there is no parent to add any refcounting for.
4180 if (hfinfo->parent != -1) {
4181 header_field_info *parent_hfinfo;
4182 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
4184 /* Mark parent as indirectly referenced unless it is already directly
4185 * referenced, i.e. the user has specified the parent in a filter.
4187 if (parent_hfinfo->ref_type != HF_REF_TYPE_DIRECT)
4188 parent_hfinfo->ref_type = HF_REF_TYPE_INDIRECT;
4193 proto_item_add_subtree(proto_item *pi, const gint idx) {
4199 DISSECTOR_ASSERT(idx >= 0 && idx < num_tree_types);
4201 fi = PITEM_FINFO(pi);
4203 return (proto_tree *)pi;
4205 fi->tree_type = idx;
4207 return (proto_tree *)pi;
4211 proto_item_get_subtree(const proto_item *pi) {
4216 fi = PITEM_FINFO(pi);
4217 if ( (!fi) || (fi->tree_type == -1) )
4219 return (proto_tree *)pi;
4223 proto_item_get_parent(const proto_item *ti) {
4230 proto_item_get_parent_nth(proto_item *ti, int gen) {
4243 proto_tree_get_parent(const proto_tree *tree) {
4246 return (proto_item *)tree;
4250 proto_tree_get_root(proto_tree *tree) {
4253 while (tree->parent) {
4254 tree = tree->parent;
4260 proto_tree_move_item(proto_tree *tree, proto_item *fixed_item,
4261 proto_item *item_to_move)
4264 /* Revert part of: http://anonsvn.wireshark.org/viewvc?view=rev&revision=32443
4265 * See https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=5500
4267 /* This function doesn't generate any values. It only reorganizes the prococol tree
4268 * so we can bail out immediately if it isn't visible. */
4269 if (!tree || !PTREE_DATA(tree)->visible)
4272 DISSECTOR_ASSERT(item_to_move->parent == tree);
4273 DISSECTOR_ASSERT(fixed_item->parent == tree);
4275 /*** cut item_to_move out ***/
4277 /* is item_to_move the first? */
4278 if (tree->first_child == item_to_move) {
4279 /* simply change first child to next */
4280 tree->first_child = item_to_move->next;
4282 DISSECTOR_ASSERT(tree->last_child != item_to_move);
4284 proto_item *curr_item;
4285 /* find previous and change it's next */
4286 for(curr_item = tree->first_child; curr_item != NULL; curr_item = curr_item->next) {
4287 if (curr_item->next == item_to_move) {
4292 DISSECTOR_ASSERT(curr_item);
4294 curr_item->next = item_to_move->next;
4296 /* fix last_child if required */
4297 if (tree->last_child == item_to_move) {
4298 tree->last_child = curr_item;
4302 /*** insert to_move after fixed ***/
4303 item_to_move->next = fixed_item->next;
4304 fixed_item->next = item_to_move;
4305 if (tree->last_child == fixed_item) {
4306 tree->last_child = item_to_move;
4311 proto_tree_set_appendix(proto_tree *tree, tvbuff_t *tvb, gint start,
4319 fi = PTREE_FINFO(tree);
4323 start += tvb_raw_offset(tvb);
4324 DISSECTOR_ASSERT(start >= 0);
4325 DISSECTOR_ASSERT(length >= 0);
4327 fi->appendix_start = start;
4328 fi->appendix_length = length;
4332 proto_register_protocol(const char *name, const char *short_name,
4333 const char *filter_name)
4335 protocol_t *protocol;
4336 header_field_info *hfinfo;
4338 char *existing_name;
4342 gboolean found_invalid;
4345 * Make sure there's not already a protocol with any of those
4346 * names. Crash if there is, as that's an error in the code
4347 * or an inappropriate plugin.
4348 * This situation has to be fixed to not register more than one
4349 * protocol with the same name.
4351 * This is done by reducing the number of strcmp (and alike) calls
4352 * as much as possible, as this significally slows down startup time.
4354 * Drawback: As a hash value is used to reduce insert time,
4355 * this might lead to a hash collision.
4356 * However, although we have somewhat over 1000 protocols, we're using
4357 * a 32 bit int so this is very, very unlikely.
4360 key = (gint *)g_malloc (sizeof(gint));
4361 *key = wrs_str_hash(name);
4363 existing_name = (char *)g_hash_table_lookup(proto_names, key);
4364 if (existing_name != NULL) {
4365 /* g_error will terminate the program */
4366 g_error("Duplicate protocol name \"%s\"!"
4367 " This might be caused by an inappropriate plugin or a development error.", name);
4369 g_hash_table_insert(proto_names, key, (gpointer)name);
4371 existing_name = (char *)g_hash_table_lookup(proto_short_names, (gpointer)short_name);
4372 if (existing_name != NULL) {
4373 g_error("Duplicate protocol short_name \"%s\"!"
4374 " This might be caused by an inappropriate plugin or a development error.", short_name);
4376 g_hash_table_insert(proto_short_names, (gpointer)short_name, (gpointer)short_name);
4378 found_invalid = FALSE;
4379 for (i = 0; filter_name[i]; i++) {
4381 if (!(islower(c) || isdigit(c) || c == '-' || c == '_' || c == '.')) {
4382 found_invalid = TRUE;
4385 if (found_invalid) {
4386 g_error("Protocol filter name \"%s\" has one or more invalid characters."
4387 " Allowed are lower characters, digits, '-', '_' and '.'."
4388 " This might be caused by an inappropriate plugin or a development error.", filter_name);
4390 existing_name = (char *)g_hash_table_lookup(proto_filter_names, (gpointer)filter_name);
4391 if (existing_name != NULL) {
4392 g_error("Duplicate protocol filter_name \"%s\"!"
4393 " This might be caused by an inappropriate plugin or a development error.", filter_name);
4395 g_hash_table_insert(proto_filter_names, (gpointer)filter_name, (gpointer)filter_name);
4397 /* Add this protocol to the list of known protocols; the list
4398 is sorted by protocol short name. */
4399 protocol = g_new(protocol_t, 1);
4400 protocol->name = name;
4401 protocol->short_name = short_name;
4402 protocol->filter_name = filter_name;
4403 protocol->fields = NULL;
4404 protocol->is_enabled = TRUE; /* protocol is enabled by default */
4405 protocol->can_toggle = TRUE;
4406 protocol->is_private = FALSE;
4407 /* list will be sorted later by name, when all protocols completed registering */
4408 protocols = g_list_prepend(protocols, protocol);
4410 /* Here we allocate a new header_field_info struct */
4411 hfinfo = g_slice_new(header_field_info);
4412 hfinfo->name = name;
4413 hfinfo->abbrev = filter_name;
4414 hfinfo->type = FT_PROTOCOL;
4415 hfinfo->display = BASE_NONE;
4416 hfinfo->strings = protocol;
4417 hfinfo->bitmask = 0;
4418 hfinfo->bitshift = 0;
4419 hfinfo->ref_type = HF_REF_TYPE_NONE;
4420 hfinfo->blurb = NULL;
4421 hfinfo->parent = -1; /* this field differentiates protos and fields */
4423 proto_id = proto_register_field_init(hfinfo, hfinfo->parent);
4424 protocol->proto_id = proto_id;
4429 proto_mark_private(const int proto_id)
4431 protocol_t *protocol = find_protocol_by_id(proto_id);
4433 protocol->is_private = TRUE;
4437 proto_is_private(const int proto_id)
4439 protocol_t *protocol = find_protocol_by_id(proto_id);
4441 return protocol->is_private;
4447 * Routines to use to iterate over the protocols.
4448 * The argument passed to the iterator routines is an opaque cookie to
4449 * their callers; it's the GList pointer for the current element in
4451 * The ID of the protocol is returned, or -1 if there is no protocol.
4454 proto_get_first_protocol(void **cookie)
4456 protocol_t *protocol;
4458 if (protocols == NULL)
4460 *cookie = protocols;
4461 protocol = (protocol_t *)protocols->data;
4462 return protocol->proto_id;
4466 proto_get_data_protocol(void *cookie)
4468 GList *list_item = (GList *)cookie;
4470 protocol_t *protocol = (protocol_t *)list_item->data;
4471 return protocol->proto_id;
4475 proto_get_next_protocol(void **cookie)
4477 GList *list_item = (GList *)*cookie;
4478 protocol_t *protocol;
4480 list_item = g_list_next(list_item);
4481 if (list_item == NULL)
4483 *cookie = list_item;
4484 protocol = (protocol_t *)list_item->data;
4485 return protocol->proto_id;
4489 proto_get_first_protocol_field(const int proto_id, void **cookie)
4491 protocol_t *protocol = find_protocol_by_id(proto_id);
4492 hf_register_info *ptr;
4494 if ((protocol == NULL) || (protocol->fields == NULL))
4497 *cookie = protocol->fields;
4498 ptr = (hf_register_info *)protocol->fields->data;
4499 return &ptr->hfinfo;
4503 proto_get_next_protocol_field(void **cookie)
4505 GSList *list_item = (GSList *)*cookie;
4506 hf_register_info *ptr;
4508 list_item = g_slist_next(list_item);
4509 if (list_item == NULL)
4512 *cookie = list_item;
4513 ptr = (hf_register_info *)list_item->data;
4514 return &ptr->hfinfo;
4518 find_protocol_by_id(const int proto_id)
4520 header_field_info *hfinfo;
4525 PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
4526 DISSECTOR_ASSERT(hfinfo->type == FT_PROTOCOL);
4527 return (protocol_t *)hfinfo->strings;
4530 static gint compare_filter_name(gconstpointer proto_arg,
4531 gconstpointer filter_name)
4533 const protocol_t *protocol = (const protocol_t *)proto_arg;
4534 const gchar *f_name = (const gchar *)filter_name;
4536 return (strcmp(protocol->filter_name, f_name));
4540 proto_get_id(const protocol_t *protocol)
4542 return protocol->proto_id;
4545 int proto_get_id_by_filter_name(const gchar* filter_name)
4548 protocol_t *protocol;
4551 fprintf(stderr, "No filter name present");
4552 DISSECTOR_ASSERT(filter_name);
4555 list_entry = g_list_find_custom(protocols, filter_name,
4556 compare_filter_name);
4558 if (list_entry == NULL)
4560 protocol = (protocol_t *)list_entry->data;
4561 return protocol->proto_id;
4565 proto_get_protocol_name(const int proto_id)
4567 protocol_t *protocol;
4569 protocol = find_protocol_by_id(proto_id);
4571 if (protocol == NULL)
4573 return protocol->name;
4577 proto_get_protocol_short_name(const protocol_t *protocol)
4579 if (protocol == NULL)
4581 return protocol->short_name;
4585 proto_get_protocol_long_name(const protocol_t *protocol)
4587 if (protocol == NULL)
4589 return protocol->name;
4593 proto_get_protocol_filter_name(const int proto_id)
4595 protocol_t *protocol;
4597 protocol = find_protocol_by_id(proto_id);
4598 if (protocol == NULL)
4600 return protocol->filter_name;
4604 proto_is_protocol_enabled(const protocol_t *protocol)
4606 return protocol->is_enabled;
4610 proto_can_toggle_protocol(const int proto_id)
4612 protocol_t *protocol;
4614 protocol = find_protocol_by_id(proto_id);
4615 return protocol->can_toggle;
4619 proto_set_decoding(const int proto_id, const gboolean enabled)
4621 protocol_t *protocol;
4623 protocol = find_protocol_by_id(proto_id);
4624 DISSECTOR_ASSERT(protocol->can_toggle);
4625 protocol->is_enabled = enabled;
4629 proto_enable_all(void)
4631 protocol_t *protocol;
4632 GList *list_item = protocols;
4634 if (protocols == NULL)
4638 protocol = (protocol_t *)list_item->data;
4639 if (protocol->can_toggle)
4640 protocol->is_enabled = TRUE;
4641 list_item = g_list_next(list_item);
4646 proto_set_cant_toggle(const int proto_id)
4648 protocol_t *protocol;
4650 protocol = find_protocol_by_id(proto_id);
4651 protocol->can_toggle = FALSE;
4654 /* for use with static arrays only, since we don't allocate our own copies
4655 of the header_field_info struct contained within the hf_register_info struct */
4657 proto_register_field_array(const int parent, hf_register_info *hf, const int num_records)
4660 hf_register_info *ptr = hf;
4663 proto = find_protocol_by_id(parent);
4664 for (i = 0; i < num_records; i++, ptr++) {
4666 * Make sure we haven't registered this yet.
4667 * Most fields have variables associated with them
4668 * that are initialized to -1; some have array elements,
4669 * or possibly uninitialized variables, so we also allow
4670 * 0 (which is unlikely to be the field ID we get back
4671 * from "proto_register_field_init()").
4673 if (*ptr->p_id != -1 && *ptr->p_id != 0) {
4675 "Duplicate field detected in call to proto_register_field_array: %s is already registered\n",
4676 ptr->hfinfo.abbrev);
4680 if (proto != NULL) {
4681 if (proto->fields == NULL) {
4682 proto->fields = g_slist_append(NULL, ptr);
4683 proto->last_field = proto->fields;
4686 g_slist_append(proto->last_field, ptr)->next;
4689 field_id = proto_register_field_init(&ptr->hfinfo, parent);
4690 *ptr->p_id = field_id;
4694 /* unregister already registered fields */
4696 proto_unregister_field (const int parent, gint hf_id)
4698 hf_register_info *hf;
4702 if (hf_id == -1 || hf_id == 0)
4705 proto = find_protocol_by_id (parent);
4706 if (!proto || !proto->fields) {
4710 for (field = proto->fields; field; field = field->next) {
4711 hf = (hf_register_info *)field->data;
4712 if (*hf->p_id == hf_id) {
4713 /* Found the hf_id in this protocol */
4714 g_tree_steal (gpa_name_tree, hf->hfinfo.abbrev);
4715 /* XXX, memleak? g_slist_delete_link() */
4716 proto->fields = g_slist_remove_link (proto->fields, field);
4717 proto->last_field = g_slist_last (proto->fields);
4723 /* chars allowed in field abbrev */
4725 const guchar fld_abbrev_chars[256] = {
4726 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00-0x0F */
4727 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10-0x1F */
4728 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, /* 0x20-0x2F '-', '.' */
4729 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 0x30-0x3F '0'-'9' */
4730 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x40-0x4F 'A'-'O' */
4731 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 0x50-0x5F 'P'-'Z', '_' */
4732 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x60-0x6F 'a'-'o' */
4733 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 0x70-0x7F 'p'-'z' */
4734 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80-0x8F */
4735 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90-0x9F */
4736 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xA0-0xAF */
4737 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xB0-0xBF */
4738 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xC0-0xCF */
4739 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xD0-0xDF */
4740 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xE0-0xEF */
4741 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xF0-0xFF */
4744 static const value_string hf_types[] = {
4745 { FT_NONE, "FT_NONE" },
4746 { FT_PROTOCOL, "FT_PROTOCOL" },
4747 { FT_BOOLEAN, "FT_BOOLEAN" },
4748 { FT_UINT8, "FT_UINT8" },
4749 { FT_UINT16, "FT_UINT16" },
4750 { FT_UINT24, "FT_UINT24" },
4751 { FT_UINT32, "FT_UINT32" },
4752 { FT_UINT64, "FT_UINT64" },
4753 { FT_INT8, "FT_INT8" },
4754 { FT_INT16, "FT_INT16" },
4755 { FT_INT24, "FT_INT24" },
4756 { FT_INT32, "FT_INT32" },
4757 { FT_INT64, "FT_INT64" },
4758 { FT_EUI64, "FT_EUI64" },
4759 { FT_FLOAT, "FT_FLOAT" },
4760 { FT_DOUBLE, "FT_DOUBLE" },
4761 { FT_ABSOLUTE_TIME, "FT_ABSOLUTE_TIME" },
4762 { FT_RELATIVE_TIME, "FT_RELATIVE_TIME" },
4763 { FT_STRING, "FT_STRING" },
4764 { FT_STRINGZ, "FT_STRINGZ" },
4765 { FT_UINT_STRING, "FT_UINT_STRING" },
4766 { FT_ETHER, "FT_ETHER" },
4767 { FT_BYTES, "FT_BYTES" },
4768 { FT_UINT_BYTES, "FT_UINT_BYTES" },
4769 { FT_IPv4, "FT_IPv4" },
4770 { FT_IPv6, "FT_IPv6" },
4771 { FT_IPXNET, "FT_IPXNET" },
4772 { FT_FRAMENUM, "FT_FRAMENUM" },
4773 { FT_PCRE, "FT_PCR" },
4774 { FT_GUID, "FT_GUID" },
4775 { FT_OID, "FT_OID" },
4778 static const value_string hf_display[] = {
4779 { BASE_NONE, "BASE_NONE" },
4780 { BASE_DEC, "BASE_DEC" },
4781 { BASE_HEX, "BASE_HEX" },
4782 { BASE_OCT, "BASE_OCT" },
4783 { BASE_DEC_HEX, "BASE_DEC_HEX" },
4784 { BASE_HEX_DEC, "BASE_HEX_DEC" },
4785 { BASE_CUSTOM, "BASE_CUSTOM" },
4786 { BASE_NONE|BASE_RANGE_STRING, "BASE_NONE|BASE_RANGE_STRING" },
4787 { BASE_DEC|BASE_RANGE_STRING, "BASE_DEC|BASE_RANGE_STRING" },
4788 { BASE_HEX|BASE_RANGE_STRING, "BASE_HEX|BASE_RANGE_STRING" },
4789 { BASE_OCT|BASE_RANGE_STRING, "BASE_OCT|BASE_RANGE_STRING" },
4790 { BASE_DEC_HEX|BASE_RANGE_STRING, "BASE_DEC_HEX|BASE_RANGE_STRING" },
4791 { BASE_HEX_DEC|BASE_RANGE_STRING, "BASE_HEX_DEC|BASE_RANGE_STRING" },
4792 { BASE_CUSTOM|BASE_RANGE_STRING, "BASE_CUSTOM|BASE_RANGE_STRING" },
4793 { BASE_NONE|BASE_VAL64_STRING, "BASE_NONE|BASE_VAL64_STRING" },
4794 { BASE_DEC|BASE_VAL64_STRING, "BASE_DEC|BASE_VAL64_STRING" },
4795 { BASE_HEX|BASE_VAL64_STRING, "BASE_HEX|BASE_VAL64_STRING" },
4796 { BASE_OCT|BASE_VAL64_STRING, "BASE_OCT|BASE_VAL64_STRING" },
4797 { BASE_DEC_HEX|BASE_VAL64_STRING, "BASE_DEC_HEX|BASE_VAL64_STRING" },
4798 { BASE_HEX_DEC|BASE_VAL64_STRING, "BASE_HEX_DEC|BASE_VAL64_STRING" },
4799 { BASE_CUSTOM|BASE_VAL64_STRING, "BASE_CUSTOM|BASE_VAL64_STRING" },
4800 { ABSOLUTE_TIME_LOCAL, "ABSOLUTE_TIME_LOCAL" },
4801 { ABSOLUTE_TIME_UTC, "ABSOLUTE_TIME_UTC" },
4802 { ABSOLUTE_TIME_DOY_UTC, "ABSOLUTE_TIME_DOY_UTC" },
4805 /* temporary function containing assert part for easier profiling */
4807 tmp_fld_check_assert(header_field_info *hfinfo)
4810 /* The field must have a name (with length > 0) */
4811 if (!hfinfo->name || !hfinfo->name[0]) {
4813 /* Try to identify the field */
4814 g_error("Field (abbrev='%s') does not have a name\n",
4818 g_error("Field does not have a name (nor an abbreviation)\n");
4821 /* fields with an empty string for an abbreviation aren't filterable */
4822 if (!hfinfo->abbrev || !hfinfo->abbrev[0])
4823 g_error("Field '%s' does not have an abbreviation\n", hfinfo->name);
4825 /* These types of fields are allowed to have value_strings,
4826 * true_false_strings or a protocol_t struct
4828 if (hfinfo->strings != NULL && !(
4829 (hfinfo->type == FT_UINT8) ||
4830 (hfinfo->type == FT_UINT16) ||
4831 (hfinfo->type == FT_UINT24) ||
4832 (hfinfo->type == FT_UINT32) ||
4833 (hfinfo->type == FT_UINT64) ||
4834 (hfinfo->type == FT_INT8) ||
4835 (hfinfo->type == FT_INT16) ||
4836 (hfinfo->type == FT_INT24) ||
4837 (hfinfo->type == FT_INT32) ||
4838 (hfinfo->type == FT_INT64) ||
4839 (hfinfo->type == FT_BOOLEAN) ||
4840 (hfinfo->type == FT_PROTOCOL) ))
4841 g_error("Field '%s' (%s) has a 'strings' value but is of type %s"
4842 " (which is not allowed to have strings)\n",
4843 hfinfo->name, hfinfo->abbrev,
4844 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"));
4846 /* TODO: This check may slow down startup, and output quite a few warnings.
4847 It would be good to be able to enable this (and possibly other checks?)
4848 in non-release builds. */
4850 /* Check for duplicate value_string values.
4851 There are lots that have the same value *and* string, so for now only
4852 report those that have same value but different string. */
4853 if ((hfinfo->strings != NULL) &&
4854 !(hfinfo->display & BASE_RANGE_STRING) &&
4855 !((hfinfo->display & BASE_DISPLAY_E_MASK) == BASE_CUSTOM) &&
4857 (hfinfo->type == FT_UINT8) ||
4858 (hfinfo->type == FT_UINT16) ||
4859 (hfinfo->type == FT_UINT24) ||
4860 (hfinfo->type == FT_UINT32) ||
4861 (hfinfo->type == FT_INT8) ||
4862 (hfinfo->type == FT_INT16) ||
4863 (hfinfo->type == FT_INT24) ||
4864 (hfinfo->type == FT_INT32) ||
4865 (hfinfo->type == FT_FRAMENUM) )) {
4868 const value_string *start_values;
4869 const value_string *current;
4871 if (hfinfo->display & BASE_EXT_STRING)
4872 start_values = VALUE_STRING_EXT_VS_P(((const value_string_ext*)hfinfo->strings));
4874 start_values = (const value_string*)hfinfo->strings;
4875 current = start_values;
4877 for (n=0; current; n++, current++) {
4878 /* Drop out if we reached the end. */
4879 if ((current->value == 0) && (current->strptr == NULL)) {
4883 /* Check value against all previous */
4884 for (m=0; m < n; m++) {
4885 /* There are lots of duplicates with the same string,
4886 so only report if different... */
4887 if ((start_values[m].value == current->value) &&
4888 (strcmp(start_values[m].strptr, current->strptr) != 0)) {
4889 g_warning("Field '%s' (%s) has a conflicting entry in its"
4890 " value_string: %u is at indices %u (%s) and %u (%s))\n",
4891 hfinfo->name, hfinfo->abbrev,
4892 current->value, m, start_values[m].strptr, n, current->strptr);
4900 switch (hfinfo->type) {
4907 /* Hexadecimal and octal are, in printf() and everywhere
4908 * else, unsigned so don't allow dissectors to register a
4909 * signed field to be displayed unsigned. (Else how would
4910 * we display negative values?)
4912 switch (hfinfo->display & BASE_DISPLAY_E_MASK) {
4917 g_error("Field '%s' (%s) is signed (%s) but is being displayed unsigned (%s)\n",
4918 hfinfo->name, hfinfo->abbrev,
4919 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"),
4920 val_to_str(hfinfo->display, hf_display, "(Bit count: %d)"));
4928 /* Require integral types (other than frame number,
4929 * which is always displayed in decimal) to have a
4931 * If there is a strings value then this base is not
4932 * normally used except when constructing a display
4933 * filter for a value not found in the strings lookup.
4935 switch (hfinfo->display & BASE_DISPLAY_E_MASK) {
4941 case BASE_CUSTOM: /* hfinfo_numeric_value_format() treats this as decimal */
4944 g_error("Field '%s' (%s) is an integral value (%s)"
4945 " but is being displayed as %s\n",
4946 hfinfo->name, hfinfo->abbrev,
4947 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"),
4948 val_to_str(hfinfo->display, hf_display, "(Unknown: 0x%x)"));
4954 if (hfinfo->display != BASE_NONE)
4955 g_error("Field '%s' (%s) is an %s but is being displayed as %s instead of BASE_NONE\n",
4956 hfinfo->name, hfinfo->abbrev,
4957 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"),
4958 val_to_str(hfinfo->display, hf_display, "(Bit count: %d)"));
4959 if (hfinfo->bitmask != 0)
4960 g_error("Field '%s' (%s) is an %s but has a bitmask\n",
4961 hfinfo->name, hfinfo->abbrev,
4962 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"));
4968 case FT_ABSOLUTE_TIME:
4969 if (!(hfinfo->display == ABSOLUTE_TIME_LOCAL ||
4970 hfinfo->display == ABSOLUTE_TIME_UTC ||
4971 hfinfo->display == ABSOLUTE_TIME_DOY_UTC))
4972 g_error("Field '%s' (%s) is a %s but is being displayed as %s instead of as a time\n",
4973 hfinfo->name, hfinfo->abbrev,
4974 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"),
4975 val_to_str(hfinfo->display, hf_display, "(Bit count: %d)"));
4976 if (hfinfo->bitmask != 0)
4977 g_error("Field '%s' (%s) is an %s but has a bitmask\n",
4978 hfinfo->name, hfinfo->abbrev,
4979 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"));
4983 if (hfinfo->display != BASE_NONE)
4984 g_error("Field '%s' (%s) is an %s but is being displayed as %s instead of BASE_NONE\n",
4985 hfinfo->name, hfinfo->abbrev,
4986 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"),
4987 val_to_str(hfinfo->display, hf_display, "(Bit count: %d)"));
4988 if (hfinfo->bitmask != 0)
4989 g_error("Field '%s' (%s) is an %s but has a bitmask\n",
4990 hfinfo->name, hfinfo->abbrev,
4991 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"));
4992 if (hfinfo->strings != NULL)
4993 g_error("Field '%s' (%s) is an %s but has a strings value\n",
4994 hfinfo->name, hfinfo->abbrev,
4995 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"));
5000 #define PROTO_PRE_ALLOC_HF_FIELDS_MEM (120000+PRE_ALLOC_EXPERT_FIELDS_MEM)
5002 proto_register_field_init(header_field_info *hfinfo, const int parent)
5005 tmp_fld_check_assert(hfinfo);
5007 /* if this is a bitfield, compute bitshift */
5008 if (hfinfo->bitmask) {
5009 hfinfo->bitshift = wrs_count_bitshift(hfinfo->bitmask);
5012 hfinfo->parent = parent;
5013 hfinfo->same_name_next = NULL;
5014 hfinfo->same_name_prev = NULL;
5016 /* if we always add and never delete, then id == len - 1 is correct */
5017 if (gpa_hfinfo.len >= gpa_hfinfo.allocated_len) {
5018 if (!gpa_hfinfo.hfi) {
5019 gpa_hfinfo.allocated_len = PROTO_PRE_ALLOC_HF_FIELDS_MEM;
5020 gpa_hfinfo.hfi = (header_field_info **)g_malloc(sizeof(header_field_info *)*PROTO_PRE_ALLOC_HF_FIELDS_MEM);
5022 gpa_hfinfo.allocated_len += 1000;
5023 gpa_hfinfo.hfi = (header_field_info **)g_realloc(gpa_hfinfo.hfi,
5024 sizeof(header_field_info *)*gpa_hfinfo.allocated_len);
5025 /*g_warning("gpa_hfinfo.allocated_len %u", gpa_hfinfo.allocated_len);*/
5028 gpa_hfinfo.hfi[gpa_hfinfo.len] = hfinfo;
5030 hfinfo->id = gpa_hfinfo.len - 1;
5032 /* if we have real names, enter this field in the name tree */
5033 if ((hfinfo->name[0] != 0) && (hfinfo->abbrev[0] != 0 )) {
5035 header_field_info *same_name_next_hfinfo;
5038 /* Check that the filter name (abbreviation) is legal;
5039 * it must contain only alphanumerics, '-', "_", and ".". */
5040 c = wrs_check_charset(fld_abbrev_chars, hfinfo->abbrev);
5042 fprintf(stderr, "Invalid character '%c' in filter name '%s'\n", c, hfinfo->abbrev);
5043 DISSECTOR_ASSERT(!c);
5046 /* We allow multiple hfinfo's to be registered under the same
5047 * abbreviation. This was done for X.25, as, depending
5048 * on whether it's modulo-8 or modulo-128 operation,
5049 * some bitfield fields may be in different bits of
5050 * a byte, and we want to be able to refer to that field
5051 * with one name regardless of whether the packets
5052 * are modulo-8 or modulo-128 packets. */
5054 same_name_hfinfo = NULL;
5056 g_tree_insert(gpa_name_tree, (gpointer) (hfinfo->abbrev), hfinfo);
5057 /* GLIB 2.x - if it is already present
5058 * the previous hfinfo with the same name is saved
5059 * to same_name_hfinfo by value destroy callback */
5060 if (same_name_hfinfo) {
5061 /* There's already a field with this name.
5062 * Put it after that field in the list of
5063 * fields with this name, then allow the code
5064 * after this if{} block to replace the old
5065 * hfinfo with the new hfinfo in the GTree. Thus,
5066 * we end up with a linked-list of same-named hfinfo's,
5067 * with the root of the list being the hfinfo in the GTree */
5068 same_name_next_hfinfo =
5069 same_name_hfinfo->same_name_next;
5071 hfinfo->same_name_next = same_name_next_hfinfo;
5072 if (same_name_next_hfinfo)
5073 same_name_next_hfinfo->same_name_prev = hfinfo;
5075 same_name_hfinfo->same_name_next = hfinfo;
5076 hfinfo->same_name_prev = same_name_hfinfo;
5084 proto_register_subtree_array(gint *const *indices, const int num_indices)
5087 gint *const *ptr = indices;
5090 * If we've already allocated the array of tree types, expand
5091 * it; this lets plugins such as mate add tree types after
5092 * the initial startup. (If we haven't already allocated it,
5093 * we don't allocate it; on the first pass, we just assign
5094 * ett values and keep track of how many we've assigned, and
5095 * when we're finished registering all dissectors we allocate
5096 * the array, so that we do only one allocation rather than
5097 * wasting CPU time and memory by growing the array for each
5098 * dissector that registers ett values.)
5100 if (tree_is_expanded != NULL) {
5101 tree_is_expanded = (guint32 *)g_realloc(tree_is_expanded, (1+((num_tree_types + num_indices)/32)) * sizeof(guint32));
5103 /* set new items to 0 */
5104 /* XXX, slow!!! optimize when needed (align 'i' to 32, and set rest of guint32 to 0) */
5105 for (i = num_tree_types; i < num_tree_types + num_indices; i++)
5106 tree_is_expanded[i >> 5] &= ~(1 << (i & 31));
5110 * Assign "num_indices" subtree numbers starting at "num_tree_types",
5111 * returning the indices through the pointers in the array whose
5112 * first element is pointed to by "indices", and update
5113 * "num_tree_types" appropriately.
5115 for (i = 0; i < num_indices; i++, ptr++, num_tree_types++) {
5117 /* g_error will terminate the program */
5118 g_error("register_subtree_array: subtree item type (ett_...) not -1 !"
5119 " This is a development error:"
5120 " Either the subtree item type has already been assigned or"
5121 " was not initialized to -1.");
5123 **ptr = num_tree_types;
5128 label_concat(char *label_str, gsize pos, const char *str)
5130 if (pos < ITEM_LABEL_LENGTH)
5131 pos += g_strlcpy(label_str + pos, str, ITEM_LABEL_LENGTH - pos);
5137 label_mark_truncated(char *label_str, gsize name_pos)
5139 static const char trunc_str[] = " [truncated]";
5140 const size_t trunc_len = sizeof(trunc_str)-1;
5142 /* ..... field_name: dataaaaaaaaaaaaa
5146 * ..... field_name [truncated]: dataaaaaaaaaaaaa */
5148 if (name_pos < ITEM_LABEL_LENGTH - trunc_len) {
5149 memmove(label_str + name_pos + trunc_len, label_str + name_pos, ITEM_LABEL_LENGTH - name_pos - trunc_len);
5150 memcpy(label_str + name_pos, trunc_str, trunc_len);
5151 label_str[ITEM_LABEL_LENGTH-1] = '\0';
5153 } else if (name_pos < ITEM_LABEL_LENGTH)
5154 g_strlcpy(label_str + name_pos, trunc_str, ITEM_LABEL_LENGTH - name_pos);
5158 label_fill(char *label_str, gsize pos, const header_field_info *hfinfo, const char *text)
5162 /* "%s: %s", hfinfo->name, text */
5163 name_pos = pos = label_concat(label_str, pos, hfinfo->name);
5164 pos = label_concat(label_str, pos, ": ");
5165 pos = label_concat(label_str, pos, text ? text : "(null)");
5167 if (pos >= ITEM_LABEL_LENGTH) {
5168 /* Uh oh, we don't have enough room. Tell the user that the field is truncated. */
5169 label_mark_truncated(label_str, name_pos);
5176 label_fill_descr(char *label_str, gsize pos, const header_field_info *hfinfo, const char *text, const char *descr)
5180 /* "%s: %s (%s)", hfinfo->name, text, descr */
5181 name_pos = pos = label_concat(label_str, pos, hfinfo->name);
5182 pos = label_concat(label_str, pos, ": ");
5183 pos = label_concat(label_str, pos, text ? text : "(null)");
5184 pos = label_concat(label_str, pos, " (");
5185 pos = label_concat(label_str, pos, descr ? descr : "(null)");
5186 pos = label_concat(label_str, pos, ")");
5188 if (pos >= ITEM_LABEL_LENGTH) {
5189 /* Uh oh, we don't have enough room. Tell the user that the field is truncated. */
5190 label_mark_truncated(label_str, name_pos);
5197 proto_item_fill_label(field_info *fi, gchar *label_str)
5199 header_field_info *hfinfo;
5205 guint32 n_addr; /* network-order IPv4 address */
5212 /* XXX: Check validity of hfinfo->type */
5216 hfinfo = fi->hfinfo;
5218 switch (hfinfo->type) {
5221 g_strlcpy(label_str, hfinfo->name, ITEM_LABEL_LENGTH);
5225 fill_label_boolean(fi, label_str);
5230 bytes = (guint8 *)fvalue_get(&fi->value);
5231 label_fill(label_str, 0, hfinfo,
5232 (bytes) ? bytes_to_str(bytes, fvalue_length(&fi->value)) : "<MISSING>");
5235 /* Four types of integers to take care of:
5236 * Bitfield, with val_string
5237 * Bitfield, w/o val_string
5238 * Non-bitfield, with val_string
5239 * Non-bitfield, w/o val_string
5245 if (hfinfo->bitmask) {
5246 fill_label_bitfield(fi, label_str);
5248 fill_label_number(fi, label_str, FALSE);
5253 fill_label_number(fi, label_str, FALSE);
5257 fill_label_number64(fi, label_str, FALSE);
5264 DISSECTOR_ASSERT(!hfinfo->bitmask);
5265 fill_label_number(fi, label_str, TRUE);
5269 fill_label_number64(fi, label_str, TRUE);
5273 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5274 "%s: %." STRINGIFY(FLT_DIG) "g",
5275 hfinfo->name, fvalue_get_floating(&fi->value));
5279 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5280 "%s: %." STRINGIFY(DBL_DIG) "g",
5281 hfinfo->name, fvalue_get_floating(&fi->value));
5284 case FT_ABSOLUTE_TIME:
5285 label_fill(label_str, 0, hfinfo,
5286 abs_time_to_str((const nstime_t *)fvalue_get(&fi->value),
5287 (absolute_time_display_e)hfinfo->display, TRUE));
5290 case FT_RELATIVE_TIME:
5291 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5292 "%s: %s seconds", hfinfo->name,
5293 rel_time_to_secs_str((const nstime_t *)fvalue_get(&fi->value)));
5297 integer = fvalue_get_uinteger(&fi->value);
5298 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5299 "%s: %s (0x%08X)", hfinfo->name,
5300 get_ipxnet_name(integer), integer);
5304 bytes = (guint8 *)fvalue_get(&fi->value);
5305 label_fill_descr(label_str, 0, hfinfo,
5306 get_ax25_name(bytes),
5307 ax25_to_str(bytes));
5311 addr.type = AT_VINES;
5312 addr.len = VINES_ADDR_LEN;
5313 addr.data = (guint8 *)fvalue_get(&fi->value);
5315 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5316 "%s: %s", hfinfo->name,
5317 address_to_str( &addr ));
5321 bytes = (guint8 *)fvalue_get(&fi->value);
5322 label_fill_descr(label_str, 0, hfinfo,
5323 get_ether_name(bytes),
5324 ether_to_str(bytes));
5328 ipv4 = (ipv4_addr *)fvalue_get(&fi->value);
5329 n_addr = ipv4_get_net_order_addr(ipv4);
5330 label_fill_descr(label_str, 0, hfinfo,
5331 get_hostname(n_addr),
5332 ip_to_str((guint8*)&n_addr));
5336 bytes = (guint8 *)fvalue_get(&fi->value);
5337 label_fill_descr(label_str, 0, hfinfo,
5338 get_hostname6((struct e_in6_addr *)bytes),
5339 ip6_to_str((struct e_in6_addr*)bytes));
5343 guid = (e_guid_t *)fvalue_get(&fi->value);
5344 label_fill(label_str, 0, hfinfo, guid_to_str(guid));
5348 bytes = (guint8 *)fvalue_get(&fi->value);
5349 name = oid_resolved_from_encoded(bytes, fvalue_length(&fi->value));
5351 label_fill_descr(label_str, 0, hfinfo,
5352 oid_encoded2string(bytes, fvalue_length(&fi->value)), name);
5354 label_fill(label_str, 0, hfinfo,
5355 oid_encoded2string(bytes, fvalue_length(&fi->value)));
5359 integer64 = fvalue_get_integer64(&fi->value);
5360 label_fill_descr(label_str, 0, hfinfo,
5361 get_eui64_name(integer64),
5362 eui64_to_str(integer64));
5366 case FT_UINT_STRING:
5367 bytes = (guint8 *)fvalue_get(&fi->value);
5368 label_fill(label_str, 0, hfinfo, format_text(bytes, strlen(bytes)));
5372 g_error("hfinfo->type %d (%s) not handled\n",
5373 hfinfo->type, ftype_name(hfinfo->type));
5374 DISSECTOR_ASSERT_NOT_REACHED();
5380 fill_label_boolean(field_info *fi, gchar *label_str)
5382 char *p = label_str;
5383 int bitfield_byte_length = 0, bitwidth;
5384 guint32 unshifted_value;
5387 header_field_info *hfinfo = fi->hfinfo;
5388 const true_false_string *tfstring = (const true_false_string *)&tfs_true_false;
5390 if (hfinfo->strings) {
5391 tfstring = (const struct true_false_string*) hfinfo->strings;
5394 value = fvalue_get_uinteger(&fi->value);
5395 if (hfinfo->bitmask) {
5396 /* Figure out the bit width */
5397 bitwidth = hfinfo_bitwidth(hfinfo);
5400 unshifted_value = value;
5401 if (hfinfo->bitshift > 0) {
5402 unshifted_value <<= hfinfo->bitshift;
5405 /* Create the bitfield first */
5406 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
5407 bitfield_byte_length = (int) (p - label_str);
5410 /* Fill in the textual info */
5411 label_fill(label_str, bitfield_byte_length, hfinfo, value ? tfstring->true_string : tfstring->false_string);
5415 hf_try_val_to_str(guint32 value, const header_field_info *hfinfo)
5417 if (hfinfo->display & BASE_RANGE_STRING)
5418 return try_rval_to_str(value, (const range_string *) hfinfo->strings);
5420 if (hfinfo->display & BASE_EXT_STRING)
5421 return try_val_to_str_ext(value, (const value_string_ext *) hfinfo->strings);
5423 if (hfinfo->display & BASE_VAL64_STRING)
5424 return try_val64_to_str(value, (const val64_string *) hfinfo->strings);
5426 return try_val_to_str(value, (const value_string *) hfinfo->strings);
5430 hf_try_val64_to_str(guint64 value, const header_field_info *hfinfo)
5432 if (hfinfo->display & BASE_VAL64_STRING)
5433 return try_val64_to_str(value, (const val64_string *) hfinfo->strings);
5435 /* If this is reached somebody registered a 64-bit field with a 32-bit
5436 * value-string, which isn't right. */
5437 DISSECTOR_ASSERT_NOT_REACHED();
5439 /* This is necessary to squelch MSVC errors; is there
5440 any way to tell it that DISSECTOR_ASSERT_NOT_REACHED()
5446 hf_try_val_to_str_const(guint32 value, const header_field_info *hfinfo, const char *unknown_str)
5448 const char *str = hf_try_val_to_str(value, hfinfo);
5450 return (str) ? str : unknown_str;
5454 hf_try_val64_to_str_const(guint64 value, const header_field_info *hfinfo, const char *unknown_str)
5456 const char *str = hf_try_val64_to_str(value, hfinfo);
5458 return (str) ? str : unknown_str;
5461 /* Fills data for bitfield ints with val_strings */
5463 fill_label_bitfield(field_info *fi, gchar *label_str)
5466 int bitfield_byte_length, bitwidth;
5467 guint32 unshifted_value;
5473 header_field_info *hfinfo = fi->hfinfo;
5475 /* Figure out the bit width */
5476 bitwidth = hfinfo_bitwidth(hfinfo);
5479 unshifted_value = fvalue_get_uinteger(&fi->value);
5480 value = unshifted_value;
5481 if (hfinfo->bitshift > 0) {
5482 unshifted_value <<= hfinfo->bitshift;
5485 /* Create the bitfield first */
5486 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
5487 bitfield_byte_length = (int) (p - label_str);
5489 /* Fill in the textual info using stored (shifted) value */
5490 if (hfinfo->display == BASE_CUSTOM) {
5491 gchar tmp[ITEM_LABEL_LENGTH];
5492 const custom_fmt_func_t fmtfunc = (const custom_fmt_func_t)hfinfo->strings;
5494 DISSECTOR_ASSERT(fmtfunc);
5495 fmtfunc(tmp, value);
5496 label_fill(label_str, bitfield_byte_length, hfinfo, tmp);
5498 else if (hfinfo->strings) {
5499 const char *val_str = hf_try_val_to_str_const(value, hfinfo, "Unknown");
5501 out = hfinfo_number_vals_format(hfinfo, buf, value);
5502 if (out == NULL) /* BASE_NONE so don't put integer in descr */
5503 label_fill(label_str, bitfield_byte_length, hfinfo, val_str);
5505 label_fill_descr(label_str, bitfield_byte_length, hfinfo, val_str, out);
5508 out = hfinfo_number_value_format(hfinfo, buf, value);
5510 label_fill(label_str, bitfield_byte_length, hfinfo, out);
5515 fill_label_number(field_info *fi, gchar *label_str, gboolean is_signed)
5517 header_field_info *hfinfo = fi->hfinfo;
5524 value = fvalue_get_sinteger(&fi->value);
5526 value = fvalue_get_uinteger(&fi->value);
5528 /* Fill in the textual info */
5529 if (hfinfo->display == BASE_CUSTOM) {
5530 gchar tmp[ITEM_LABEL_LENGTH];
5531 const custom_fmt_func_t fmtfunc = (const custom_fmt_func_t)hfinfo->strings;
5533 DISSECTOR_ASSERT(fmtfunc);
5534 fmtfunc(tmp, value);
5535 label_fill(label_str, 0, hfinfo, tmp);
5537 else if (hfinfo->strings) {
5538 const char *val_str = hf_try_val_to_str_const(value, hfinfo, "Unknown");
5540 out = hfinfo_number_vals_format(hfinfo, buf, value);
5541 if (out == NULL) /* BASE_NONE so don't put integer in descr */
5542 label_fill(label_str, 0, hfinfo, val_str);
5544 label_fill_descr(label_str, 0, hfinfo, val_str, out);
5547 out = hfinfo_number_value_format(hfinfo, buf, value);
5549 label_fill(label_str, 0, hfinfo, out);
5554 fill_label_number64(field_info *fi, gchar *label_str, gboolean is_signed)
5556 const char *format = NULL;
5557 header_field_info *hfinfo = fi->hfinfo;
5559 char tmp[ITEM_LABEL_LENGTH+1];
5561 /* Pick the proper format string */
5563 format = hfinfo_int64_format(hfinfo);
5565 format = hfinfo_uint64_format(hfinfo);
5567 value = fvalue_get_integer64(&fi->value);
5569 /* Format the temporary string */
5570 if (IS_BASE_DUAL(hfinfo->display))
5571 g_snprintf(tmp, ITEM_LABEL_LENGTH, format, value, value);
5573 g_snprintf(tmp, ITEM_LABEL_LENGTH, format, value);
5575 if (hfinfo->strings) {
5576 const char *val_str = hf_try_val64_to_str_const(value, hfinfo, "Unknown");
5578 if ((hfinfo->display & BASE_DISPLAY_E_MASK) == BASE_NONE) {
5579 label_fill(label_str, 0, hfinfo, val_str);
5582 label_fill_descr(label_str, 0, hfinfo, val_str, tmp);
5586 label_fill(label_str, 0, hfinfo, tmp);
5591 hfinfo_bitwidth(const header_field_info *hfinfo)
5595 if (!hfinfo->bitmask) {
5599 switch (hfinfo->type) {
5617 bitwidth = hfinfo->display; /* hacky? :) */
5620 DISSECTOR_ASSERT_NOT_REACHED();
5627 _hfinfo_type_hex_octet(int type)
5647 DISSECTOR_ASSERT_NOT_REACHED();
5653 /* private to_str.c API don't export to .h! */
5654 char *oct_to_str_back(char *ptr, guint32 value);
5655 char *hex_to_str_back(char *ptr, int pad, guint32 value);
5656 char *uint_to_str_back(char *ptr, guint32 value);
5657 char *int_to_str_back(char *ptr, gint32 value);
5660 hfinfo_number_value_format_display(const header_field_info *hfinfo, int display, char buf[32], guint32 value)
5662 char *ptr = &buf[31];
5663 gboolean isint = IS_FT_INT(hfinfo->type);
5666 /* Properly format value */
5669 return isint ? int_to_str_back(ptr, (gint32) value) : uint_to_str_back(ptr, value);
5673 ptr = hex_to_str_back(ptr, _hfinfo_type_hex_octet(hfinfo->type), value);
5676 ptr = isint ? int_to_str_back(ptr, (gint32) value) : uint_to_str_back(ptr, value);
5680 return oct_to_str_back(ptr, value);
5683 return hex_to_str_back(ptr, _hfinfo_type_hex_octet(hfinfo->type), value);
5687 ptr = isint ? int_to_str_back(ptr, (gint32) value) : uint_to_str_back(ptr, value);
5690 ptr = hex_to_str_back(ptr, _hfinfo_type_hex_octet(hfinfo->type), value);
5694 DISSECTOR_ASSERT_NOT_REACHED();
5701 hfinfo_number_value_format(const header_field_info *hfinfo, char buf[32], guint32 value)
5703 int display = hfinfo->display;
5705 if (hfinfo->type == FT_FRAMENUM) {
5707 * Frame numbers are always displayed in decimal.
5712 return hfinfo_number_value_format_display(hfinfo, display, buf, value);
5716 hfinfo_numeric_value_format(const header_field_info *hfinfo, char buf[32], guint32 value)
5718 /* Get the underlying BASE_ value */
5719 int display = hfinfo->display & BASE_DISPLAY_E_MASK;
5721 if (hfinfo->type == FT_FRAMENUM) {
5723 * Frame numbers are always displayed in decimal.
5730 /* case BASE_DEC: */
5732 case BASE_OCT: /* XXX, why we're changing BASE_OCT to BASE_DEC? */
5737 /* case BASE_HEX: */
5743 return hfinfo_number_value_format_display(hfinfo, display, buf, value);
5747 hfinfo_number_vals_format(const header_field_info *hfinfo, char buf[32], guint32 value)
5749 /* Get the underlying BASE_ value */
5750 int display = hfinfo->display & BASE_DISPLAY_E_MASK;
5752 if (display == BASE_NONE)
5755 if (display == BASE_DEC_HEX)
5757 if (display == BASE_HEX_DEC)
5760 return hfinfo_number_value_format_display(hfinfo, display, buf, value);
5764 hfinfo_uint64_format(const header_field_info *hfinfo)
5766 const char *format = NULL;
5768 /* Pick the proper format string */
5769 switch (hfinfo->display & BASE_DISPLAY_E_MASK) {
5771 format = "%" G_GINT64_MODIFIER "u";
5774 format = "%" G_GINT64_MODIFIER "u (0x%016" G_GINT64_MODIFIER "x)";
5776 case BASE_OCT: /* I'm lazy */
5777 format = "%#" G_GINT64_MODIFIER "o";
5780 format = "0x%016" G_GINT64_MODIFIER "x";
5783 format = "0x%016" G_GINT64_MODIFIER "x (%" G_GINT64_MODIFIER "u)";
5786 DISSECTOR_ASSERT_NOT_REACHED();
5793 hfinfo_int64_format(const header_field_info *hfinfo)
5795 const char *format = NULL;
5797 /* Pick the proper format string */
5798 switch (hfinfo->display & BASE_DISPLAY_E_MASK) {
5800 format = "%" G_GINT64_MODIFIER "d";
5803 format = "%" G_GINT64_MODIFIER "d (0x%016" G_GINT64_MODIFIER "x)";
5805 case BASE_OCT: /* I'm lazy */
5806 format = "%#" G_GINT64_MODIFIER "o";
5809 format = "0x%016" G_GINT64_MODIFIER "x";
5812 format = "0x%016" G_GINT64_MODIFIER "x (%" G_GINT64_MODIFIER "d)";
5815 DISSECTOR_ASSERT_NOT_REACHED();
5822 proto_registrar_n(void)
5824 return gpa_hfinfo.len;
5828 proto_registrar_get_name(const int n)
5830 header_field_info *hfinfo;
5832 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
5833 return hfinfo->name;
5837 proto_registrar_get_abbrev(const int n)
5839 header_field_info *hfinfo;
5841 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
5842 return hfinfo->abbrev;
5846 proto_registrar_get_ftype(const int n)
5848 header_field_info *hfinfo;
5850 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
5851 return hfinfo->type;
5855 proto_registrar_get_parent(const int n)
5857 header_field_info *hfinfo;
5859 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
5860 return hfinfo->parent;
5864 proto_registrar_is_protocol(const int n)
5866 header_field_info *hfinfo;
5868 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
5869 return (hfinfo->parent == -1 ? TRUE : FALSE);
5872 /* Returns length of field in packet (not necessarily the length
5873 * in our internal representation, as in the case of IPv4).
5874 * 0 means undeterminable at time of registration
5875 * -1 means the field is not registered. */
5877 proto_registrar_get_length(const int n)
5879 header_field_info *hfinfo;
5881 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
5882 return ftype_length(hfinfo->type);
5885 /* Looks for a protocol or a field in a proto_tree. Returns TRUE if
5886 * it exists anywhere, or FALSE if it exists nowhere. */
5888 proto_check_for_protocol_or_field(const proto_tree* tree, const int id)
5890 GPtrArray *ptrs = proto_get_finfo_ptr_array(tree, id);
5895 else if (g_ptr_array_len(ptrs) > 0) {
5903 /* Return GPtrArray* of field_info pointers for all hfindex that appear in tree.
5904 * This only works if the hfindex was "primed" before the dissection
5905 * took place, as we just pass back the already-created GPtrArray*.
5906 * The caller should *not* free the GPtrArray*; proto_tree_free_node()
5909 proto_get_finfo_ptr_array(const proto_tree *tree, const int id)
5914 if (PTREE_DATA(tree)->interesting_hfids != NULL)
5915 return (GPtrArray *)g_hash_table_lookup(PTREE_DATA(tree)->interesting_hfids,
5916 GINT_TO_POINTER(id));
5922 proto_tracking_interesting_fields(const proto_tree *tree)
5927 return (PTREE_DATA(tree)->interesting_hfids != NULL);
5930 /* Helper struct for proto_find_info() and proto_all_finfos() */
5936 /* Helper function for proto_find_info() */
5938 find_finfo(proto_node *node, gpointer data)
5940 field_info *fi = PNODE_FINFO(node);
5941 if (fi && fi->hfinfo) {
5942 if (fi->hfinfo->id == ((ffdata_t*)data)->id) {
5943 g_ptr_array_add(((ffdata_t*)data)->array, fi);
5947 /* Don't stop traversing. */
5951 /* Return GPtrArray* of field_info pointers for all hfindex that appear in a tree.
5952 * This works on any proto_tree, primed or unprimed, but actually searches
5953 * the tree, so it is slower than using proto_get_finfo_ptr_array on a primed tree.
5954 * The caller does need to free the returned GPtrArray with
5955 * g_ptr_array_free(<array>, TRUE).
5958 proto_find_finfo(proto_tree *tree, const int id)
5962 ffdata.array = g_ptr_array_new();
5965 proto_tree_traverse_pre_order(tree, find_finfo, &ffdata);
5967 return ffdata.array;
5970 /* Helper function for proto_all_finfos() */
5972 every_finfo(proto_node *node, gpointer data)
5974 field_info *fi = PNODE_FINFO(node);
5975 if (fi && fi->hfinfo) {
5976 g_ptr_array_add(((ffdata_t*)data)->array, fi);
5979 /* Don't stop traversing. */
5983 /* Return GPtrArray* of field_info pointers containing all hfindexes that appear in a tree. */
5985 proto_all_finfos(proto_tree *tree)
5989 ffdata.array = g_ptr_array_new();
5992 proto_tree_traverse_pre_order(tree, every_finfo, &ffdata);
5994 return ffdata.array;
6005 check_for_offset(proto_node *node, const gpointer data)
6007 field_info *fi = PNODE_FINFO(node);
6008 offset_search_t *offsearch = (offset_search_t *)data;
6010 /* !fi == the top most container node which holds nothing */
6011 if (fi && !PROTO_ITEM_IS_HIDDEN(node) && fi->ds_tvb && offsearch->tvb == fi->ds_tvb) {
6012 if (offsearch->offset >= (guint) fi->start &&
6013 offsearch->offset < (guint) (fi->start + fi->length)) {
6015 offsearch->finfo = fi;
6016 return FALSE; /* keep traversing */
6019 return FALSE; /* keep traversing */
6022 /* Search a proto_tree backwards (from leaves to root) looking for the field
6023 * whose start/length occupies 'offset' */
6024 /* XXX - I couldn't find an easy way to search backwards, so I search
6025 * forwards, w/o stopping. Therefore, the last finfo I find will the be
6026 * the one I want to return to the user. This algorithm is inefficient
6027 * and could be re-done, but I'd have to handle all the children and
6028 * siblings of each node myself. When I have more time I'll do that.
6031 proto_find_field_from_offset(proto_tree *tree, guint offset, tvbuff_t *tvb)
6033 offset_search_t offsearch;
6035 offsearch.offset = offset;
6036 offsearch.finfo = NULL;
6037 offsearch.tvb = tvb;
6039 proto_tree_traverse_pre_order(tree, check_for_offset, &offsearch);
6041 return offsearch.finfo;
6044 /* Dumps the protocols in the registration database to stdout. An independent
6045 * program can take this output and format it into nice tables or HTML or
6048 * There is one record per line. The fields are tab-delimited.
6050 * Field 1 = protocol name
6051 * Field 2 = protocol short name
6052 * Field 3 = protocol filter name
6055 proto_registrar_dump_protocols(void)
6057 protocol_t *protocol;
6059 void *cookie = NULL;
6062 i = proto_get_first_protocol(&cookie);
6064 protocol = find_protocol_by_id(i);
6065 printf("%s\t%s\t%s\n", protocol->name, protocol->short_name,
6066 protocol->filter_name);
6067 i = proto_get_next_protocol(&cookie);
6071 /* Dumps the value_strings, extended value string headers, range_strings
6072 * or true/false strings for fields that have them.
6073 * There is one record per line. Fields are tab-delimited.
6074 * There are four types of records: Value String, Extended Value String Header,
6075 * Range String and True/False String. The first field, 'V', 'E', 'R' or 'T', indicates
6076 * the type of record.
6078 * Note that a record will be generated only if the value_string,... is referenced
6079 * in a registered hfinfo entry.
6085 * Field 2 = Field abbreviation to which this value string corresponds
6086 * Field 3 = Integer value
6089 * Extended Value String Headers
6090 * -----------------------------
6092 * Field 2 = Field abbreviation to which this extended value string header corresponds
6093 * Field 3 = Extended Value String "Name"
6094 * Field 4 = Number of entries in the associated value_string array
6095 * Field 5 = Access Type: "Linear Search", "Binary Search", "Direct (indexed) Access"
6100 * Field 2 = Field abbreviation to which this range string corresponds
6101 * Field 3 = Integer value: lower bound
6102 * Field 4 = Integer value: upper bound
6105 * True/False Strings
6106 * ------------------
6108 * Field 2 = Field abbreviation to which this true/false string corresponds
6109 * Field 3 = True String
6110 * Field 4 = False String
6113 proto_registrar_dump_values(void)
6115 header_field_info *hfinfo;
6117 const value_string *vals;
6118 const val64_string *vals64;
6119 const range_string *range;
6120 const true_false_string *tfs;
6122 len = gpa_hfinfo.len;
6123 for (i = 0; i < len ; i++) {
6124 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
6126 if (hfinfo->id == hf_text_only) {
6130 /* ignore protocols */
6131 if (proto_registrar_is_protocol(i)) {
6134 /* process header fields */
6137 * If this field isn't at the head of the list of
6138 * fields with this name, skip this field - all
6139 * fields with the same name are really just versions
6140 * of the same field stored in different bits, and
6141 * should have the same type/radix/value list, and
6142 * just differ in their bit masks. (If a field isn't
6143 * a bitfield, but can be, say, 1 or 2 bytes long,
6144 * it can just be made FT_UINT16, meaning the
6145 * *maximum* length is 2 bytes, and be used
6148 if (hfinfo->same_name_prev != NULL)
6156 if (hfinfo->strings != NULL) {
6157 if ((hfinfo->display & BASE_DISPLAY_E_MASK) != BASE_CUSTOM &&
6158 (hfinfo->type == FT_UINT8 ||
6159 hfinfo->type == FT_UINT16 ||
6160 hfinfo->type == FT_UINT24 ||
6161 hfinfo->type == FT_UINT32 ||
6162 hfinfo->type == FT_UINT64 ||
6163 hfinfo->type == FT_INT8 ||
6164 hfinfo->type == FT_INT16 ||
6165 hfinfo->type == FT_INT24 ||
6166 hfinfo->type == FT_INT32 ||
6167 hfinfo->type == FT_INT64)) {
6169 if (hfinfo->display & BASE_EXT_STRING) {
6170 vals = VALUE_STRING_EXT_VS_P((const value_string_ext *)hfinfo->strings);
6171 } else if ((hfinfo->display & BASE_RANGE_STRING) == 0) {
6172 vals = (const value_string *)hfinfo->strings;
6173 } else if ((hfinfo->display & BASE_VAL64_STRING) == 0) {
6174 vals64 = (const val64_string *)hfinfo->strings;
6176 range = (const range_string *)hfinfo->strings;
6179 else if (hfinfo->type == FT_BOOLEAN) {
6180 tfs = (const struct true_false_string *)hfinfo->strings;
6184 /* Print value strings? */
6186 if (hfinfo->display & BASE_EXT_STRING) {
6187 const value_string_ext *vse_p = (const value_string_ext *)hfinfo->strings;
6188 if (!value_string_ext_validate(vse_p)) {
6189 g_warning("Invalid value_string_ext ptr for: %s", hfinfo->abbrev);
6192 try_val_to_str_ext(0, vse_p); /* "prime" the extended value_string */
6193 printf("E\t%s\t%d\t%s\t%s\n",
6195 VALUE_STRING_EXT_VS_NUM_ENTRIES(vse_p),
6196 VALUE_STRING_EXT_VS_NAME(vse_p),
6197 value_string_ext_match_type_str(vse_p));
6200 while (vals[vi].strptr) {
6201 /* Print in the proper base */
6202 if (hfinfo->display == BASE_HEX) {
6203 printf("V\t%s\t0x%x\t%s\n",
6209 printf("V\t%s\t%u\t%s\n",
6219 while (vals64[vi].strptr) {
6220 printf("V64\t%s\t%" G_GINT64_MODIFIER "u\t%s\n",
6228 /* print range strings? */
6231 while (range[vi].strptr) {
6232 /* Print in the proper base */
6233 if ((hfinfo->display & BASE_DISPLAY_E_MASK) == BASE_HEX) {
6234 printf("R\t%s\t0x%x\t0x%x\t%s\n",
6236 range[vi].value_min,
6237 range[vi].value_max,
6241 printf("R\t%s\t%u\t%u\t%s\n",
6243 range[vi].value_min,
6244 range[vi].value_max,
6251 /* Print true/false strings? */
6253 printf("T\t%s\t%s\t%s\n", hfinfo->abbrev,
6254 tfs->true_string, tfs->false_string);
6260 /* Dumps the contents of the registration database to stdout. An independent
6261 * program can take this output and format it into nice tables or HTML or
6264 * There is one record per line. Each record is either a protocol or a header
6265 * field, differentiated by the first field. The fields are tab-delimited.
6270 * Field 2 = descriptive protocol name
6271 * Field 3 = protocol abbreviation
6276 * Field 2 = descriptive field name
6277 * Field 3 = field abbreviation
6278 * Field 4 = type ( textual representation of the the ftenum type )
6279 * Field 5 = parent protocol abbreviation
6280 * Field 6 = base for display (for integer types); "parent bitfield width" for FT_BOOLEAN
6281 * Field 7 = bitmask: format: hex: 0x....
6282 * Field 8 = blurb describing field
6285 proto_registrar_dump_fields(void)
6287 header_field_info *hfinfo, *parent_hfinfo;
6289 const char *enum_name;
6290 const char *base_name;
6294 len = gpa_hfinfo.len;
6295 for (i = 0; i < len ; i++) {
6296 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
6299 * Skip the pseudo-field for "proto_tree_add_text()" since
6300 * we don't want it in the list of filterable fields.
6302 if (hfinfo->id == hf_text_only)
6305 /* format for protocols */
6306 if (proto_registrar_is_protocol(i)) {
6307 printf("P\t%s\t%s\n", hfinfo->name, hfinfo->abbrev);
6309 /* format for header fields */
6312 * If this field isn't at the head of the list of
6313 * fields with this name, skip this field - all
6314 * fields with the same name are really just versions
6315 * of the same field stored in different bits, and
6316 * should have the same type/radix/value list, and
6317 * just differ in their bit masks. (If a field isn't
6318 * a bitfield, but can be, say, 1 or 2 bytes long,
6319 * it can just be made FT_UINT16, meaning the
6320 * *maximum* length is 2 bytes, and be used
6323 if (hfinfo->same_name_prev != NULL)
6326 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
6328 enum_name = ftype_name(hfinfo->type);
6331 if (hfinfo->type == FT_UINT8 ||
6332 hfinfo->type == FT_UINT16 ||
6333 hfinfo->type == FT_UINT24 ||
6334 hfinfo->type == FT_UINT32 ||
6335 hfinfo->type == FT_UINT64 ||
6336 hfinfo->type == FT_INT8 ||
6337 hfinfo->type == FT_INT16 ||
6338 hfinfo->type == FT_INT24 ||
6339 hfinfo->type == FT_INT32 ||
6340 hfinfo->type == FT_INT64) {
6342 switch (hfinfo->display & BASE_DISPLAY_E_MASK) {
6344 base_name = "BASE_NONE";
6347 base_name = "BASE_DEC";
6350 base_name = "BASE_HEX";
6353 base_name = "BASE_OCT";
6356 base_name = "BASE_DEC_HEX";
6359 base_name = "BASE_HEX_DEC";
6362 base_name = "BASE_CUSTOM";
6368 } else if (hfinfo->type == FT_BOOLEAN) {
6369 /* For FT_BOOLEAN: 'display' can be "parent bitfield width" */
6370 g_snprintf(width, sizeof(width), "%d", hfinfo->display);
6374 blurb = hfinfo->blurb;
6377 else if (strlen(blurb) == 0)
6380 printf("F\t%s\t%s\t%s\t%s\t%s\t0x%x\t%s\n",
6381 hfinfo->name, hfinfo->abbrev, enum_name,
6382 parent_hfinfo->abbrev, base_name, hfinfo->bitmask, blurb);
6387 /* Dumps field types and descriptive names to stdout. An independent
6388 * program can take this output and format it into nice tables or HTML or
6391 * There is one record per line. The fields are tab-delimited.
6393 * Field 1 = field type name, e.g. FT_UINT8
6394 * Field 2 = descriptive name, e.g. "Unsigned, 1 byte"
6397 proto_registrar_dump_ftypes(void)
6401 for (fte = 0; fte < FT_NUM_TYPES; fte++) {
6402 printf("%s\t%s\n", ftype_name((ftenum_t)fte), ftype_pretty_name((ftenum_t)fte));
6407 hfinfo_numeric_format(const header_field_info *hfinfo)
6409 const char *format = NULL;
6411 /* Get the underlying BASE_ value */
6412 switch (hfinfo->display & BASE_DISPLAY_E_MASK) {
6415 case BASE_OCT: /* I'm lazy */
6417 switch (hfinfo->type) {
6419 format = "%s == %" G_GINT64_MODIFIER "u";
6422 format = "%s == %" G_GINT64_MODIFIER "d";
6425 DISSECTOR_ASSERT_NOT_REACHED();
6431 switch (hfinfo->type) {
6434 format = "%s == 0x%016" G_GINT64_MODIFIER "x";
6437 DISSECTOR_ASSERT_NOT_REACHED();
6442 DISSECTOR_ASSERT_NOT_REACHED();
6448 /* This function indicates whether it's possible to construct a
6449 * "match selected" display filter string for the specified field,
6450 * returns an indication of whether it's possible, and, if it's
6451 * possible and "filter" is non-null, constructs the filter and
6452 * sets "*filter" to point to it.
6453 * You do not need to [g_]free() this string since it will be automatically
6454 * freed once the next packet is dissected.
6457 construct_match_selected_string(field_info *finfo, epan_dissect_t *edt,
6460 header_field_info *hfinfo;
6465 gint start, length, length_remaining;
6467 gchar is_signed_num = FALSE;
6472 hfinfo = finfo->hfinfo;
6473 DISSECTOR_ASSERT(hfinfo);
6474 abbrev_len = (int) strlen(hfinfo->abbrev);
6476 if (hfinfo->strings && (hfinfo->display & BASE_DISPLAY_E_MASK) == BASE_NONE) {
6477 const gchar *str = NULL;
6479 switch (hfinfo->type) {
6485 str = hf_try_val_to_str(fvalue_get_sinteger(&finfo->value), hfinfo);
6492 str = hf_try_val_to_str(fvalue_get_uinteger(&finfo->value), hfinfo);
6499 if (str != NULL && filter != NULL) {
6500 *filter = ep_strdup_printf("%s == \"%s\"", hfinfo->abbrev, str);
6506 * XXX - we can't use the "val_to_string_repr" and "string_repr_len"
6507 * functions for FT_UINT and FT_INT types, as we choose the base in
6508 * the string expression based on the display base of the field.
6510 * Note that the base does matter, as this is also used for
6511 * the protocolinfo tap.
6513 * It might be nice to use them in "proto_item_fill_label()"
6514 * as well, although, there, you'd have to deal with the base
6515 * *and* with resolved values for addresses.
6517 * Perhaps we need two different val_to_string routines, one
6518 * to generate items for display filters and one to generate
6519 * strings for display, and pass to both of them the
6520 * "display" and "strings" values in the header_field_info
6521 * structure for the field, so they can get the base and,
6522 * if the field is Boolean or an enumerated integer type,
6523 * the tables used to generate human-readable values.
6525 switch (hfinfo->type) {
6531 is_signed_num = TRUE;
6538 if (filter != NULL) {
6545 number = fvalue_get_sinteger(&finfo->value);
6547 number = fvalue_get_uinteger(&finfo->value);
6549 out = hfinfo_numeric_value_format(hfinfo, buf, number);
6551 *filter = ep_strdup_printf("%s == %s", hfinfo->abbrev, out);
6557 if (filter != NULL) {
6558 const char *format = hfinfo_numeric_format(hfinfo);
6560 *filter = ep_strdup_printf(format,
6562 fvalue_get_integer64(&finfo->value));
6568 *filter = ep_strdup(finfo->hfinfo->abbrev);
6573 * If the length is 0, just match the name of the
6576 * (Also check for negative values, just in case,
6577 * as we'll cast it to an unsigned value later.)
6579 length = finfo->length;
6582 *filter = ep_strdup(finfo->hfinfo->abbrev);
6589 * This doesn't have a value, so we'd match
6590 * on the raw bytes at this address.
6592 * Should we be allowed to access to the raw bytes?
6593 * If "edt" is NULL, the answer is "no".
6599 * Is this field part of the raw frame tvbuff?
6600 * If not, we can't use "frame[N:M]" to match
6603 * XXX - should this be frame-relative, or
6604 * protocol-relative?
6606 * XXX - does this fallback for non-registered
6607 * fields even make sense?
6609 if (finfo->ds_tvb != edt->tvb)
6610 return FALSE; /* you lose */
6613 * Don't go past the end of that tvbuff.
6615 length_remaining = tvb_length_remaining(finfo->ds_tvb, finfo->start);
6616 if (length > length_remaining)
6617 length = length_remaining;
6621 if (filter != NULL) {
6622 start = finfo->start;
6623 buf_len = 32 + length * 3;
6624 *filter = (char *)ep_alloc0(buf_len);
6627 ptr += g_snprintf(ptr, (gulong) (buf_len-(ptr-*filter)),
6628 "frame[%d:%d] == ", finfo->start, length);
6629 for (i=0; i<length; i++) {
6630 c = tvb_get_guint8(finfo->ds_tvb, start);
6633 ptr += g_snprintf(ptr, (gulong) (buf_len-(ptr-*filter)), "%02x", c);
6636 ptr += g_snprintf(ptr, (gulong) (buf_len-(ptr-*filter)), ":%02x", c);
6643 /* FT_PCRE never appears as a type for a registered field. It is
6644 * only used internally. */
6645 DISSECTOR_ASSERT_NOT_REACHED();
6648 /* By default, use the fvalue's "to_string_repr" method. */
6650 /* Figure out the string length needed.
6651 * The ft_repr length.
6652 * 4 bytes for " == ".
6653 * 1 byte for trailing NUL.
6655 if (filter != NULL) {
6656 dfilter_len = fvalue_string_repr_len(&finfo->value,
6658 dfilter_len += abbrev_len + 4 + 1;
6659 *filter = (char *)ep_alloc0(dfilter_len);
6661 /* Create the string */
6662 g_snprintf(*filter, dfilter_len, "%s == ",
6664 fvalue_to_string_repr(&finfo->value,
6666 &(*filter)[abbrev_len + 4]);
6675 * Returns TRUE if we can do a "match selected" on the field, FALSE
6679 proto_can_match_selected(field_info *finfo, epan_dissect_t *edt)
6681 return construct_match_selected_string(finfo, edt, NULL);
6684 /* This function attempts to construct a "match selected" display filter
6685 * string for the specified field; if it can do so, it returns a pointer
6686 * to the string, otherwise it returns NULL.
6688 * The string is allocated with packet lifetime scope.
6689 * You do not need to [g_]free() this string since it will be automatically
6690 * freed once the next packet is dissected.
6693 proto_construct_match_selected_string(field_info *finfo, epan_dissect_t *edt)
6697 if (!construct_match_selected_string(finfo, edt, &filter))
6702 /* This function is common code for both proto_tree_add_bitmask() and
6703 * proto_tree_add_bitmask_text() functions.
6706 /* NOTE: to support code written when proto_tree_add_bitmask() and
6707 * proto_tree_add_bitmask_text took a
6708 * gboolean as its last argument, with FALSE meaning "big-endian"
6709 * and TRUE meaning "little-endian", we treat any non-zero value of
6710 * "encoding" as meaning "little-endian".
6713 proto_item_add_bitmask_tree(proto_item *item, tvbuff_t *tvb, const int offset,
6714 const int len, const gint ett, const int **fields,
6715 const guint encoding, const int flags,
6719 guint32 available_bits = 0;
6721 proto_tree *tree = NULL;
6722 header_field_info *hf;
6726 value = tvb_get_guint8(tvb, offset);
6727 available_bits = 0xFF;
6730 value = encoding ? tvb_get_letohs(tvb, offset) :
6731 tvb_get_ntohs(tvb, offset);
6732 available_bits = 0xFFFF;
6735 value = encoding ? tvb_get_letoh24(tvb, offset) :
6736 tvb_get_ntoh24(tvb, offset);
6737 available_bits = 0xFFFFFF;
6740 value = encoding ? tvb_get_letohl(tvb, offset) :
6741 tvb_get_ntohl(tvb, offset);
6742 available_bits = 0xFFFFFFFF;
6745 g_assert_not_reached();
6748 tree = proto_item_add_subtree(item, ett);
6750 guint32 present_bits;
6751 hf = proto_registrar_get_nth(**fields);
6752 DISSECTOR_ASSERT(hf->bitmask != 0);
6754 /* Skip fields that aren't fully present */
6755 present_bits = available_bits & hf->bitmask;
6756 if (present_bits != hf->bitmask) {
6761 proto_tree_add_item(tree, **fields, tvb, offset, len, encoding);
6762 if (flags & BMT_NO_APPEND) {
6766 tmpval = (value & hf->bitmask) >> hf->bitshift;
6777 if (hf->display == BASE_CUSTOM) {
6778 gchar lbl[ITEM_LABEL_LENGTH];
6779 const custom_fmt_func_t fmtfunc = (const custom_fmt_func_t)hf->strings;
6781 DISSECTOR_ASSERT(fmtfunc);
6782 fmtfunc(lbl, tmpval);
6783 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
6787 else if (hf->strings) {
6788 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
6789 hf->name, hf_try_val_to_str_const(tmpval, hf, "Unknown"));
6792 else if (!(flags & BMT_NO_INT)) {
6797 proto_item_append_text(item, ", ");
6800 out = hfinfo_number_value_format(hf, buf, tmpval);
6801 proto_item_append_text(item, "%s: %s", hf->name, out);
6807 if (hf->strings && !(flags & BMT_NO_TFS)) {
6808 /* If we have true/false strings, emit full - otherwise messages
6810 const struct true_false_string *tfs =
6811 (const struct true_false_string *)hf->strings;
6814 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
6815 hf->name, tfs->true_string);
6817 } else if (!(flags & BMT_NO_FALSE)) {
6818 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
6819 hf->name, tfs->false_string);
6822 } else if (hf->bitmask & value) {
6823 /* If the flag is set, show the name */
6824 proto_item_append_text(item, "%s%s", first ? "" : ", ", hf->name);
6829 g_assert_not_reached();
6838 /* This function will dissect a sequence of bytes that describe a
6840 * hf_hdr is a 8/16/24/32 bit integer that describes the bitmask to be dissected.
6841 * This field will form an expansion under which the individual fields of the
6842 * bitmask is dissected and displayed.
6843 * This field must be of the type FT_[U]INT{8|16|24|32}.
6845 * fields is an array of pointers to int that lists all the fields of the
6846 * bitmask. These fields can be either of the type FT_BOOLEAN for flags
6847 * or another integer of the same type/size as hf_hdr with a mask specified.
6848 * This array is terminated by a NULL entry.
6850 * FT_BOOLEAN bits that are set to 1 will have the name added to the expansion.
6851 * FT_integer fields that have a value_string attached will have the
6852 * matched string displayed on the expansion line.
6855 proto_tree_add_bitmask(proto_tree *parent_tree, tvbuff_t *tvb,
6856 const guint offset, const int hf_hdr,
6857 const gint ett, const int **fields,
6858 const guint encoding)
6860 proto_item *item = NULL;
6861 header_field_info *hf;
6864 hf = proto_registrar_get_nth(hf_hdr);
6865 DISSECTOR_ASSERT(IS_FT_INT(hf->type) || IS_FT_UINT(hf->type));
6866 len = ftype_length(hf->type);
6869 item = proto_tree_add_item(parent_tree, hf_hdr, tvb, offset, len, encoding);
6870 proto_item_add_bitmask_tree(item, tvb, offset, len, ett, fields, encoding,
6871 BMT_NO_INT|BMT_NO_TFS, FALSE);
6877 /* The same as proto_tree_add_bitmask(), but using a caller-supplied length.
6878 * This is intended to support bitmask fields whose lengths can vary, perhaps
6879 * as the underlying standard evolves over time.
6880 * With this API there is the possibility of being called to display more or
6881 * less data than the dissector was coded to support.
6882 * In such cases, it is assumed that bitmasks are extended on the MSb end.
6883 * Thus when presented with "too much" or "too little" data, MSbits will be
6884 * ignored or MSfields sacrificed.
6886 * Only fields for which all defined bits are available are displayed.
6889 proto_tree_add_bitmask_len(proto_tree *parent_tree, tvbuff_t *tvb,
6890 const guint offset, const guint len, const int hf_hdr,
6891 const gint ett, const int **fields,
6892 const guint encoding)
6894 proto_item *item = NULL;
6895 header_field_info *hf;
6897 hf = proto_registrar_get_nth(hf_hdr);
6898 DISSECTOR_ASSERT(IS_FT_INT(hf->type) || IS_FT_UINT(hf->type));
6901 guint decodable_len;
6902 guint decodable_offset;
6903 guint32 decodable_value;
6905 decodable_offset = offset;
6906 decodable_len = MIN(len, (guint) ftype_length(hf->type));
6908 /* If we are ftype_length-limited,
6909 * make sure we decode as many LSBs as possible.
6911 if (encoding == ENC_BIG_ENDIAN) {
6912 decodable_offset += (len - decodable_len);
6915 decodable_value = get_uint_value(parent_tree, tvb, decodable_offset,
6916 decodable_len, encoding);
6918 /* The root item covers all the bytes even if we can't decode them all */
6919 item = proto_tree_add_uint(parent_tree, hf_hdr, tvb, offset, len,
6922 if (decodable_len < len) {
6923 /* Dissector likely requires updating for new protocol revision */
6924 expert_add_info_format(NULL, item, PI_UNDECODED, PI_WARN,
6925 "Only least-significant %d of %d bytes decoded",
6926 decodable_len, len);
6929 proto_item_add_bitmask_tree(item, tvb, decodable_offset, decodable_len,
6930 ett, fields, encoding, BMT_NO_INT|BMT_NO_TFS, FALSE);
6936 /* The same as proto_tree_add_bitmask(), but using an arbitrary text as a top-level item */
6938 proto_tree_add_bitmask_text(proto_tree *parent_tree, tvbuff_t *tvb,
6939 const guint offset, const guint len,
6940 const char *name, const char *fallback,
6941 const gint ett, const int **fields,
6942 const guint encoding, const int flags)
6944 proto_item *item = NULL;
6947 item = proto_tree_add_text(parent_tree, tvb, offset, len, "%s", name ? name : "");
6948 if (proto_item_add_bitmask_tree(item, tvb, offset, len, ett, fields, encoding,
6949 flags, TRUE) && fallback) {
6950 /* Still at first item - append 'fallback' text if any */
6951 proto_item_append_text(item, "%s", fallback);
6959 proto_tree_add_bits_item(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
6960 const guint bit_offset, const gint no_of_bits,
6961 const guint encoding)
6963 header_field_info *hfinfo;
6967 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
6969 octet_length = (no_of_bits + 7) >> 3;
6970 octet_offset = bit_offset >> 3;
6971 test_length(hfinfo, tree, tvb, octet_offset, octet_length, encoding);
6973 /* Yes, we try to fake this item again in proto_tree_add_bits_ret_val()
6974 * but only after doing a bunch more work (which we can, in the common
6975 * case, shortcut here).
6977 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
6979 return proto_tree_add_bits_ret_val(tree, hfindex, tvb, bit_offset, no_of_bits, NULL, encoding);
6983 * This function will dissect a sequence of bits that does not need to be byte aligned; the bits
6984 * set will be shown in the tree as ..10 10.. and the integer value returned if return_value is set.
6985 * Offset should be given in bits from the start of the tvb.
6989 _proto_tree_add_bits_ret_val(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
6990 const guint bit_offset, const gint no_of_bits,
6991 guint64 *return_value, const guint encoding)
6997 char lbl_str[ITEM_LABEL_LENGTH];
7001 header_field_info *hf_field;
7003 const true_false_string *tfstring;
7005 /* We can't fake it just yet. We have to fill in the 'return_value' parameter */
7006 PROTO_REGISTRAR_GET_NTH(hfindex, hf_field);
7008 if (hf_field->bitmask != 0) {
7009 REPORT_DISSECTOR_BUG(ep_strdup_printf("Incompatible use of proto_tree_add_bits_ret_val"
7010 " with field '%s' (%s) with bitmask != 0",
7011 hf_field->abbrev, hf_field->name));
7014 DISSECTOR_ASSERT(no_of_bits > 0);
7016 /* Byte align offset */
7017 offset = bit_offset>>3;
7020 * Calculate the number of octets used to hold the bits
7022 tot_no_bits = ((bit_offset&0x7) + no_of_bits);
7023 length = (tot_no_bits + 7) >> 3;
7025 if (no_of_bits < 65) {
7026 value = tvb_get_bits64(tvb, bit_offset, no_of_bits, encoding);
7028 DISSECTOR_ASSERT_NOT_REACHED();
7032 /* Sign extend for signed types */
7033 switch (hf_field->type) {
7039 if (value & (G_GINT64_CONSTANT(1) << (no_of_bits-1)))
7040 value |= (G_GINT64_CONSTANT(-1) << no_of_bits);
7048 *return_value = value;
7051 /* Coast clear. Try and fake it */
7052 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
7054 bf_str = decode_bits_in_field(bit_offset, no_of_bits, value);
7056 switch (hf_field->type) {
7059 tfstring = (const true_false_string *) &tfs_true_false;
7060 if (hf_field->strings)
7061 tfstring = (const true_false_string *)hf_field->strings;
7062 return proto_tree_add_boolean_format(tree, hfindex, tvb, offset, length, (guint32)value,
7064 bf_str, hf_field->name,
7065 (guint32)value ? tfstring->true_string : tfstring->false_string);
7072 pi = proto_tree_add_uint(tree, hfindex, tvb, offset, length, (guint32)value);
7073 fill_label_number(PITEM_FINFO(pi), lbl_str, FALSE);
7080 pi = proto_tree_add_int(tree, hfindex, tvb, offset, length, (gint32)value);
7081 fill_label_number(PITEM_FINFO(pi), lbl_str, TRUE);
7085 pi = proto_tree_add_uint64(tree, hfindex, tvb, offset, length, value);
7086 fill_label_number64(PITEM_FINFO(pi), lbl_str, FALSE);
7090 pi = proto_tree_add_int64(tree, hfindex, tvb, offset, length, (gint64)value);
7091 fill_label_number64(PITEM_FINFO(pi), lbl_str, TRUE);
7095 DISSECTOR_ASSERT_NOT_REACHED();
7100 proto_item_set_text(pi, "%s = %s", bf_str, lbl_str);
7105 proto_tree_add_split_bits_item_ret_val(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
7106 const guint bit_offset, const crumb_spec_t *crumb_spec,
7107 guint64 *return_value)
7112 guint mask_initial_bit_offset;
7113 guint mask_greatest_bit_offset;
7117 char lbl_str[ITEM_LABEL_LENGTH];
7119 guint64 composite_bitmask;
7120 guint64 composite_bitmap;
7122 header_field_info *hf_field;
7123 const true_false_string *tfstring;
7125 /* We can't fake it just yet. We have to fill in the 'return_value' parameter */
7126 PROTO_REGISTRAR_GET_NTH(hfindex, hf_field);
7128 if (hf_field->bitmask != 0) {
7129 REPORT_DISSECTOR_BUG(ep_strdup_printf(
7130 "Incompatible use of proto_tree_add_split_bits_item_ret_val"
7131 " with field '%s' (%s) with bitmask != 0",
7132 hf_field->abbrev, hf_field->name));
7135 mask_initial_bit_offset = bit_offset % 8;
7140 mask_greatest_bit_offset = 0;
7141 composite_bitmask = 0;
7142 composite_bitmap = 0;
7144 while (crumb_spec[i].crumb_bit_length != 0) {
7145 guint64 crumb_mask, crumb_value;
7146 guint8 crumb_end_bit_offset;
7148 DISSECTOR_ASSERT(i < 64);
7149 crumb_value = tvb_get_bits64(tvb,
7150 bit_offset + crumb_spec[i].crumb_bit_offset,
7151 crumb_spec[i].crumb_bit_length,
7153 value += crumb_value;
7154 no_of_bits += crumb_spec[i].crumb_bit_length;
7156 /* The bitmask is 64 bit, left-aligned, starting at the first bit of the
7157 octet containing the initial offset.
7158 If the mask is beyond 32 bits, then give up on bit map display.
7159 This could be improved in future, probably showing a table
7160 of 32 or 64 bits per row */
7161 if (mask_greatest_bit_offset < 32) {
7162 crumb_end_bit_offset = mask_initial_bit_offset
7163 + crumb_spec[i].crumb_bit_offset
7164 + crumb_spec[i].crumb_bit_length;
7165 crumb_mask = (G_GUINT64_CONSTANT(1) << crumb_spec[i].crumb_bit_length) - 1;
7167 if (crumb_end_bit_offset > mask_greatest_bit_offset) {
7168 mask_greatest_bit_offset = crumb_end_bit_offset;
7170 composite_bitmask |= (crumb_mask << (64 - crumb_end_bit_offset));
7171 composite_bitmap |= (crumb_value << (64 - crumb_end_bit_offset));
7173 /* Shift left for the next segment */
7174 value <<= crumb_spec[++i].crumb_bit_length;
7177 /* Sign extend for signed types */
7178 switch (hf_field->type) {
7184 if (no_of_bits && (value & (G_GINT64_CONSTANT(1) << (no_of_bits-1))))
7185 value |= (G_GINT64_CONSTANT(-1) << no_of_bits);
7192 *return_value = value;
7195 /* Coast clear. Try and fake it */
7196 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
7198 /* initialise the format string */
7199 bf_str = (char *)ep_alloc(256);
7202 octet_offset = bit_offset >> 3;
7204 /* Round up mask length to nearest octet */
7205 octet_length = ((mask_greatest_bit_offset + 7) >> 3);
7206 mask_greatest_bit_offset = octet_length << 3;
7208 /* As noted above, we currently only produce a bitmap if the crumbs span less than 4 octets of the tvb.
7209 It would be a useful enhancement to eliminate this restriction. */
7210 if (mask_greatest_bit_offset <= 32) {
7211 other_decode_bitfield_value(bf_str,
7212 (guint32)(composite_bitmap >> (64 - mask_greatest_bit_offset)),
7213 (guint32)(composite_bitmask >> (64 - mask_greatest_bit_offset)),
7214 mask_greatest_bit_offset);
7217 switch (hf_field->type) {
7218 case FT_BOOLEAN: /* it is a bit odd to have a boolean encoded as split-bits, but possible, I suppose? */
7220 tfstring = (const true_false_string *) &tfs_true_false;
7221 if (hf_field->strings)
7222 tfstring = (const true_false_string *) hf_field->strings;
7223 return proto_tree_add_boolean_format(tree, hfindex,
7224 tvb, octet_offset, octet_length, (guint32)value,
7226 bf_str, hf_field->name,
7227 (guint32)value ? tfstring->true_string : tfstring->false_string);
7234 pi = proto_tree_add_uint(tree, hfindex, tvb, octet_offset, octet_length, (guint32)value);
7235 fill_label_number(PITEM_FINFO(pi), lbl_str, FALSE);
7242 pi = proto_tree_add_int(tree, hfindex, tvb, octet_offset, octet_length, (gint32)value);
7243 fill_label_number(PITEM_FINFO(pi), lbl_str, TRUE);
7247 pi = proto_tree_add_uint64(tree, hfindex, tvb, octet_offset, octet_length, value);
7248 fill_label_number64(PITEM_FINFO(pi), lbl_str, FALSE);
7252 pi = proto_tree_add_int64(tree, hfindex, tvb, octet_offset, octet_length, (gint64)value);
7253 fill_label_number64(PITEM_FINFO(pi), lbl_str, TRUE);
7257 DISSECTOR_ASSERT_NOT_REACHED();
7261 proto_item_set_text(pi, "%s = %s", bf_str, lbl_str);
7266 proto_tree_add_split_bits_crumb(proto_tree *tree, const int hfindex, tvbuff_t *tvb, const guint bit_offset,
7267 const crumb_spec_t *crumb_spec, guint16 crumb_index)
7269 header_field_info *hfinfo;
7271 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
7272 proto_tree_add_text(tree, tvb,
7274 ((bit_offset + crumb_spec[crumb_index].crumb_bit_length - 1) >> 3) - (bit_offset >> 3) + 1,
7275 "%s crumb %d of %s (decoded above)",
7276 decode_bits_in_field(bit_offset, crumb_spec[crumb_index].crumb_bit_length,
7279 crumb_spec[crumb_index].crumb_bit_length,
7286 proto_tree_add_bits_ret_val(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
7287 const guint bit_offset, const gint no_of_bits,
7288 guint64 *return_value, const guint encoding)
7292 if ((item = _proto_tree_add_bits_ret_val(tree, hfindex, tvb,
7293 bit_offset, no_of_bits,
7294 return_value, encoding))) {
7295 FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_OFFSET(bit_offset));
7296 FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_SIZE(no_of_bits));
7302 _proto_tree_add_bits_format_value(proto_tree *tree, const int hfindex,
7303 tvbuff_t *tvb, const guint bit_offset,
7304 const gint no_of_bits, void *value_ptr,
7312 header_field_info *hf_field;
7314 /* We do not have to return a value, try to fake it as soon as possible */
7315 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
7317 if (hf_field->bitmask != 0) {
7318 REPORT_DISSECTOR_BUG(ep_strdup_printf(
7319 "Incompatible use of proto_tree_add_bits_format_value"
7320 " with field '%s' (%s) with bitmask != 0",
7321 hf_field->abbrev, hf_field->name));
7324 DISSECTOR_ASSERT(no_of_bits > 0);
7326 /* Byte align offset */
7327 offset = bit_offset>>3;
7330 * Calculate the number of octets used to hold the bits
7332 tot_no_bits = ((bit_offset&0x7) + no_of_bits);
7333 length = tot_no_bits>>3;
7334 /* If we are using part of the next octet, increase length by 1 */
7335 if (tot_no_bits & 0x07)
7338 if (no_of_bits < 65) {
7339 value = tvb_get_bits64(tvb, bit_offset, no_of_bits, ENC_BIG_ENDIAN);
7341 DISSECTOR_ASSERT_NOT_REACHED();
7345 str = decode_bits_in_field(bit_offset, no_of_bits, value);
7348 strcat(str, hf_field->name);
7351 * This function does not receive an actual value but a dimensionless pointer to that value.
7352 * For this reason, the type of the header field is examined in order to determine
7353 * what kind of value we should read from this address.
7354 * The caller of this function must make sure that for the specific header field type the address of
7355 * a compatible value is provided.
7357 switch (hf_field->type) {
7359 return proto_tree_add_boolean_format(tree, hfindex, tvb, offset, length, *(guint32 *)value_ptr,
7360 "%s: %s", str, value_str);
7367 return proto_tree_add_uint_format(tree, hfindex, tvb, offset, length, *(guint32 *)value_ptr,
7368 "%s: %s", str, value_str);
7372 return proto_tree_add_uint64_format(tree, hfindex, tvb, offset, length, *(guint64 *)value_ptr,
7373 "%s: %s", str, value_str);
7380 return proto_tree_add_int_format(tree, hfindex, tvb, offset, length, *(gint32 *)value_ptr,
7381 "%s: %s", str, value_str);
7385 return proto_tree_add_int64_format(tree, hfindex, tvb, offset, length, *(gint64 *)value_ptr,
7386 "%s: %s", str, value_str);
7390 return proto_tree_add_float_format(tree, hfindex, tvb, offset, length, *(float *)value_ptr,
7391 "%s: %s", str, value_str);
7395 DISSECTOR_ASSERT_NOT_REACHED();
7402 proto_tree_add_bits_format_value(proto_tree *tree, const int hfindex,
7403 tvbuff_t *tvb, const guint bit_offset,
7404 const gint no_of_bits, void *value_ptr,
7409 if ((item = _proto_tree_add_bits_format_value(tree, hfindex,
7410 tvb, bit_offset, no_of_bits,
7411 value_ptr, value_str))) {
7412 FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_OFFSET(bit_offset));
7413 FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_SIZE(no_of_bits));
7418 #define CREATE_VALUE_STRING(dst,format,ap) \
7419 va_start(ap, format); \
7420 dst = ep_strdup_vprintf(format, ap); \
7424 proto_tree_add_uint_bits_format_value(proto_tree *tree, const int hfindex,
7425 tvbuff_t *tvb, const guint bit_offset,
7426 const gint no_of_bits, guint32 value,
7427 const char *format, ...)
7431 header_field_info *hf_field;
7433 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
7435 switch (hf_field->type) {
7443 DISSECTOR_ASSERT_NOT_REACHED();
7448 CREATE_VALUE_STRING(dst, format, ap);
7450 return proto_tree_add_bits_format_value(tree, hfindex, tvb, bit_offset, no_of_bits, &value, dst);
7454 proto_tree_add_float_bits_format_value(proto_tree *tree, const int hfindex,
7455 tvbuff_t *tvb, const guint bit_offset,
7456 const gint no_of_bits, float value,
7457 const char *format, ...)
7461 header_field_info *hf_field;
7463 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
7465 DISSECTOR_ASSERT(hf_field->type == FT_FLOAT);
7467 CREATE_VALUE_STRING(dst, format, ap);
7469 return proto_tree_add_bits_format_value(tree, hfindex, tvb, bit_offset, no_of_bits, &value, dst);
7473 proto_tree_add_int_bits_format_value(proto_tree *tree, const int hfindex,
7474 tvbuff_t *tvb, const guint bit_offset,
7475 const gint no_of_bits, gint32 value,
7476 const char *format, ...)
7480 header_field_info *hf_field;
7482 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
7484 switch (hf_field->type) {
7492 DISSECTOR_ASSERT_NOT_REACHED();
7497 CREATE_VALUE_STRING(dst, format, ap);
7499 return proto_tree_add_bits_format_value(tree, hfindex, tvb, bit_offset, no_of_bits, &value, dst);
7503 proto_tree_add_boolean_bits_format_value(proto_tree *tree, const int hfindex,
7504 tvbuff_t *tvb, const guint bit_offset,
7505 const gint no_of_bits, guint32 value,
7506 const char *format, ...)
7510 header_field_info *hf_field;
7512 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
7514 DISSECTOR_ASSERT(hf_field->type == FT_BOOLEAN);
7516 CREATE_VALUE_STRING(dst, format, ap);
7518 return proto_tree_add_bits_format_value(tree, hfindex, tvb, bit_offset, no_of_bits, &value, dst);
7522 proto_check_field_name(const gchar *field_name)
7524 return wrs_check_charset(fld_abbrev_chars, field_name);
7528 tree_expanded(int tree_type)
7530 g_assert(tree_type >= 0 && tree_type < num_tree_types);
7531 return tree_is_expanded[tree_type >> 5] & (1 << (tree_type & 31));
7535 tree_expanded_set(int tree_type, gboolean value)
7537 g_assert(tree_type >= 0 && tree_type < num_tree_types);
7540 tree_is_expanded[tree_type >> 5] |= (1 << (tree_type & 31));
7542 tree_is_expanded[tree_type >> 5] &= ~(1 << (tree_type & 31));
7546 * Editor modelines - http://www.wireshark.org/tools/modelines.html
7551 * indent-tabs-mode: t
7554 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
7555 * :indentSize=8:tabSize=8:noTabs=false: