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 #define cVALS(x) (const value_string*)(x)
76 /** See inlined comments.
77 @param tree the tree to append this item to
78 @param hfindex field index
79 @param hfinfo header_field
80 @return the header field matching 'hfinfo' */
81 #define TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo) \
82 /* If this item is not referenced we dont have to do much work \
83 at all but we should still return a node so that field items \
84 below this node (think proto_item_add_subtree()) will still \
85 have somewhere to attach to or else filtering will not work \
86 (they would be ignored since tree would be NULL). \
87 DONT try to fake a node where PTREE_FINFO(tree) is NULL \
88 since dissectors that want to do proto_item_set_len() or \
89 other operations that dereference this would crash. \
90 We fake FT_PROTOCOL unless some clients have requested us \
95 PTREE_DATA(tree)->count++; \
96 if (PTREE_DATA(tree)->count > MAX_TREE_ITEMS) { \
97 if (getenv("WIRESHARK_ABORT_ON_TOO_MANY_ITEMS") != NULL) \
98 g_error("More than %d items in the tree -- possible infinite loop", MAX_TREE_ITEMS); \
99 /* Let the exception handler add items to the tree */ \
100 PTREE_DATA(tree)->count = 0; \
101 THROW_MESSAGE(DissectorError, \
102 ep_strdup_printf("More than %d items in the tree -- possible infinite loop", MAX_TREE_ITEMS)); \
104 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo); \
105 if (!(PTREE_DATA(tree)->visible)) { \
106 if (PTREE_FINFO(tree)) { \
107 if ((hfinfo->ref_type != HF_REF_TYPE_DIRECT) \
108 && (hfinfo->type != FT_PROTOCOL || \
109 PTREE_DATA(tree)->fake_protocols)) { \
110 /* just return tree back to the caller */\
116 /** See inlined comments.
117 @param pi the created protocol item we're about to return */
118 #define TRY_TO_FAKE_THIS_REPR(pi) \
120 if (!(PTREE_DATA(pi)->visible)) { \
121 /* If the tree (GUI) isn't visible it's pointless for us to generate the protocol \
122 * items string representation */ \
126 static const char *hf_try_val_to_str(guint32 value, const header_field_info *hfinfo);
128 static void fill_label_boolean(field_info *fi, gchar *label_str);
129 static void fill_label_bitfield(field_info *fi, gchar *label_str);
130 static void fill_label_number(field_info *fi, gchar *label_str, gboolean is_signed);
131 static void fill_label_number64(field_info *fi, gchar *label_str, gboolean is_signed);
133 static const char *hfinfo_number_value_format_display(const header_field_info *hfinfo, int display, char buf[32], guint32 value);
134 static const char *hfinfo_number_vals_format(const header_field_info *hfinfo, char buf[32], guint32 value);
135 static const char *hfinfo_number_value_format(const header_field_info *hfinfo, char buf[32], guint32 value);
136 static const char *hfinfo_numeric_value_format(const header_field_info *hfinfo, char buf[32], guint32 value);
138 static const char* hfinfo_uint64_format(const header_field_info *hfinfo);
139 static const char* hfinfo_int64_format(const header_field_info *hfinfo);
142 proto_tree_add_node(proto_tree *tree, field_info *fi);
145 get_hfi_length(header_field_info *hfinfo, tvbuff_t *tvb, const gint start, gint *length,
149 new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
150 const gint start, const gint item_length);
153 alloc_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
154 const gint start, gint *length);
157 proto_tree_add_pi(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
158 gint start, gint *length);
161 proto_tree_set_representation_value(proto_item *pi, const char *format, va_list ap);
163 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap);
166 proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb);
168 proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length);
170 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length);
172 proto_tree_set_time(field_info *fi, nstime_t *value_ptr);
174 proto_tree_set_string(field_info *fi, const char* value);
176 proto_tree_set_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length, gint encoding);
178 proto_tree_set_ax25(field_info *fi, const guint8* value);
180 proto_tree_set_ax25_tvb(field_info *fi, tvbuff_t *tvb, gint start);
182 proto_tree_set_vines(field_info *fi, const guint8* value);
184 proto_tree_set_vines_tvb(field_info *fi, tvbuff_t *tvb, gint start);
186 proto_tree_set_ether(field_info *fi, const guint8* value);
188 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start);
190 proto_tree_set_ipxnet(field_info *fi, guint32 value);
192 proto_tree_set_ipv4(field_info *fi, guint32 value);
194 proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr);
196 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
198 proto_tree_set_guid(field_info *fi, const e_guid_t *value_ptr);
200 proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, gint start, const guint encoding);
202 proto_tree_set_oid(field_info *fi, const guint8* value_ptr, gint length);
204 proto_tree_set_oid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
206 proto_tree_set_boolean(field_info *fi, guint32 value);
208 proto_tree_set_float(field_info *fi, float value);
210 proto_tree_set_double(field_info *fi, double value);
212 proto_tree_set_uint(field_info *fi, guint32 value);
214 proto_tree_set_int(field_info *fi, gint32 value);
216 proto_tree_set_uint64(field_info *fi, guint64 value);
218 proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start, guint length, const guint encoding);
220 proto_tree_set_eui64(field_info *fi, const guint64 value);
222 proto_tree_set_eui64_tvb(field_info *fi, tvbuff_t *tvb, gint start, const guint encoding);
224 proto_item_add_bitmask_tree(proto_item *item, tvbuff_t *tvb, const int offset,
225 const int len, const gint ett, const gint **fields,
226 const guint encoding, const int flags,
229 static int proto_register_field_init(header_field_info *hfinfo, const int parent);
231 /* special-case header field used within proto.c */
232 static header_field_info hfi_text_only =
233 { "Text item", "text", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL };
234 int hf_text_only = -1;
236 /* Structure for information about a protocol */
238 const char *name; /* long description */
239 const char *short_name; /* short description */
240 const char *filter_name; /* name of this protocol in filters */
241 int proto_id; /* field ID for this protocol */
242 GSList *fields; /* fields for this protocol */
243 GSList *last_field; /* pointer to end of list of fields */
244 gboolean is_enabled; /* TRUE if protocol is enabled */
245 gboolean can_toggle; /* TRUE if is_enabled can be changed */
246 gboolean is_private; /* TRUE is protocol is private */
249 /* List of all protocols */
250 static GList *protocols = NULL;
252 #define INITIAL_NUM_PROTOCOL_HFINFO 1500
254 /* Contains information about a field when a dissector calls
255 * proto_tree_add_item. */
256 #define FIELD_INFO_NEW(fi) fi = g_slice_new(field_info)
257 #define FIELD_INFO_FREE(fi) g_slice_free(field_info, fi)
259 /* Contains the space for proto_nodes. */
260 #define PROTO_NODE_NEW(node) \
261 node = g_slice_new(proto_node); \
262 node->first_child = NULL; \
263 node->last_child = NULL; \
266 #define PROTO_NODE_FREE(node) \
267 g_slice_free(proto_node, node)
269 /* String space for protocol and field items for the GUI */
270 #define ITEM_LABEL_NEW(il) \
271 il = g_slice_new(item_label_t);
272 #define ITEM_LABEL_FREE(il) \
273 g_slice_free(item_label_t, il);
275 #define PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo) \
276 if((guint)hfindex >= gpa_hfinfo.len && getenv("WIRESHARK_ABORT_ON_DISSECTOR_BUG")) \
277 g_error("Unregistered hf! index=%d", hfindex); \
278 DISSECTOR_ASSERT_HINT((guint)hfindex < gpa_hfinfo.len, "Unregistered hf!"); \
279 hfinfo = gpa_hfinfo.hfi[hfindex];
281 /* List which stores protocols and fields that have been registered */
282 typedef struct _gpa_hfinfo_t {
284 guint32 allocated_len;
285 header_field_info **hfi;
288 static gpa_hfinfo_t gpa_hfinfo;
290 /* Balanced tree of abbreviations and IDs */
291 static GTree *gpa_name_tree = NULL;
292 static header_field_info *same_name_hfinfo;
294 static void save_same_name_hfinfo(gpointer data)
296 same_name_hfinfo = (header_field_info*)data;
299 /* Points to the first element of an array of bits, indexed by
300 a subtree item type; that array element is TRUE if subtrees of
301 an item of that type are to be expanded. */
302 static guint32 *tree_is_expanded;
304 /* Number of elements in that array. */
307 /* Name hashtables for fast detection of duplicate names */
308 static GHashTable* proto_names = NULL;
309 static GHashTable* proto_short_names = NULL;
310 static GHashTable* proto_filter_names = NULL;
313 proto_compare_name(gconstpointer p1_arg, gconstpointer p2_arg)
315 const protocol_t *p1 = (const protocol_t *)p1_arg;
316 const protocol_t *p2 = (const protocol_t *)p2_arg;
318 return g_ascii_strcasecmp(p1->short_name, p2->short_name);
322 /* initialize data structures and register protocols and fields */
324 proto_init(void (register_all_protocols_func)(register_cb cb, gpointer client_data),
325 void (register_all_handoffs_func)(register_cb cb, gpointer client_data),
327 gpointer client_data)
331 proto_names = g_hash_table_new_full(g_int_hash, g_int_equal, g_free, NULL);
332 proto_short_names = g_hash_table_new(wrs_str_hash, g_str_equal);
333 proto_filter_names = g_hash_table_new(wrs_str_hash, g_str_equal);
336 gpa_hfinfo.allocated_len = 0;
337 gpa_hfinfo.hfi = NULL;
338 gpa_name_tree = g_tree_new_full(wrs_strcmp_with_data, NULL, NULL, save_same_name_hfinfo);
340 /* Initialize the ftype subsystem */
343 /* Register one special-case FT_TEXT_ONLY field for use when
344 converting wireshark to new-style proto_tree. These fields
345 are merely strings on the GUI tree; they are not filterable */
346 hf_text_only = proto_register_field_init(&hfi_text_only, -1);
348 /* Register the pseudo-protocols used for exceptions. */
349 register_show_exception();
351 /* Have each built-in dissector register its protocols, fields,
352 dissector tables, and dissectors to be called through a
353 handle, and do whatever one-time initialization it needs to
355 register_all_protocols_func(cb, client_data);
357 /* Now scan for python protocols */
359 (*cb)(RA_PYTHON_REGISTER, NULL, client_data);
360 register_all_py_protocols_func();
364 /* Now scan for plugins and load all the ones we find, calling
365 their register routines to do the stuff described above. */
367 (*cb)(RA_PLUGIN_REGISTER, NULL, client_data);
369 register_all_plugin_registrations();
372 /* Now call the "handoff registration" routines of all built-in
373 dissectors; those routines register the dissector in other
374 dissectors' handoff tables, and fetch any dissector handles
376 register_all_handoffs_func(cb, client_data);
379 /* Now do the same with python dissectors */
381 (*cb)(RA_PYTHON_HANDOFF, NULL, client_data);
382 register_all_py_handoffs_func();
386 /* Now do the same with plugins. */
388 (*cb)(RA_PLUGIN_HANDOFF, NULL, client_data);
389 register_all_plugin_handoffs();
392 /* sort the protocols by protocol name */
393 protocols = g_list_sort(protocols, proto_compare_name);
395 /* We've assigned all the subtree type values; allocate the array
396 for them, and zero it out. */
397 tree_is_expanded = g_new0(guint32, (num_tree_types/32)+1);
403 /* Free the abbrev/ID GTree */
405 g_tree_destroy(gpa_name_tree);
406 gpa_name_tree = NULL;
410 protocol_t *protocol = (protocol_t *)protocols->data;
411 header_field_info *hfinfo;
412 PROTO_REGISTRAR_GET_NTH(protocol->proto_id, hfinfo);
413 DISSECTOR_ASSERT(protocol->proto_id == hfinfo->id);
415 g_slice_free(header_field_info, hfinfo);
416 g_slist_free(protocol->fields);
417 protocols = g_list_remove(protocols, protocol);
422 g_hash_table_destroy(proto_names);
426 if (proto_short_names) {
427 g_hash_table_destroy(proto_short_names);
428 proto_short_names = NULL;
431 if (proto_filter_names) {
432 g_hash_table_destroy(proto_filter_names);
433 proto_filter_names = NULL;
436 if (gpa_hfinfo.allocated_len) {
438 gpa_hfinfo.allocated_len = 0;
439 g_free(gpa_hfinfo.hfi);
440 gpa_hfinfo.hfi = NULL;
442 g_free(tree_is_expanded);
443 tree_is_expanded = NULL;
447 proto_tree_traverse_pre_order(proto_tree *tree, proto_tree_traverse_func func,
450 proto_node *pnode = tree;
454 if (func(pnode, data))
457 child = pnode->first_child;
458 while (child != NULL) {
460 * The routine we call might modify the child, e.g. by
461 * freeing it, so we get the child's successor before
462 * calling that routine.
465 child = current->next;
466 if (proto_tree_traverse_pre_order((proto_tree *)current, func, data))
474 proto_tree_traverse_post_order(proto_tree *tree, proto_tree_traverse_func func,
477 proto_node *pnode = tree;
481 child = pnode->first_child;
482 while (child != NULL) {
484 * The routine we call might modify the child, e.g. by
485 * freeing it, so we get the child's successor before
486 * calling that routine.
489 child = current->next;
490 if (proto_tree_traverse_post_order((proto_tree *)current, func, data))
493 if (func(pnode, data))
500 proto_tree_children_foreach(proto_tree *tree, proto_tree_foreach_func func,
503 proto_node *node = tree;
509 node = node->first_child;
510 while (node != NULL) {
512 node = current->next;
513 func((proto_tree *)current, data);
518 free_GPtrArray_value(gpointer key, gpointer value, gpointer user_data _U_)
520 GPtrArray *ptrs = (GPtrArray *)value;
521 gint hfid = (gint)(long)key;
522 header_field_info *hfinfo;
524 PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
525 if (hfinfo->ref_type != HF_REF_TYPE_NONE) {
526 /* when a field is referenced by a filter this also
527 affects the refcount for the parent protocol so we need
528 to adjust the refcount for the parent as well
530 if (hfinfo->parent != -1) {
531 header_field_info *parent_hfinfo;
532 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
533 parent_hfinfo->ref_type = HF_REF_TYPE_NONE;
535 hfinfo->ref_type = HF_REF_TYPE_NONE;
538 g_ptr_array_free(ptrs, TRUE);
542 free_node_tree_data(tree_data_t *tree_data)
544 if (tree_data->interesting_hfids) {
545 /* Free all the GPtrArray's in the interesting_hfids hash. */
546 g_hash_table_foreach(tree_data->interesting_hfids,
547 free_GPtrArray_value, NULL);
549 /* And then destroy the hash. */
550 g_hash_table_destroy(tree_data->interesting_hfids);
552 if (tree_data->fi_tmp)
553 FIELD_INFO_FREE(tree_data->fi_tmp);
555 /* And finally the tree_data_t itself. */
559 #define FREE_NODE_FIELD_INFO(finfo) \
561 ITEM_LABEL_FREE(finfo->rep); \
563 FVALUE_CLEANUP(&finfo->value); \
564 FIELD_INFO_FREE(finfo);
567 proto_tree_free_node(proto_node *node, gpointer data _U_)
569 field_info *finfo = PNODE_FINFO(node);
571 proto_tree_children_foreach(node, proto_tree_free_node, NULL);
573 /* free the field_info data. */
574 FREE_NODE_FIELD_INFO(finfo);
577 /* Free the proto_node. */
578 PROTO_NODE_FREE(node);
581 /* frees the resources that the dissection a proto_tree uses */
583 proto_tree_free(proto_tree *tree)
585 tree_data_t *tree_data = PTREE_DATA(tree);
587 proto_tree_children_foreach(tree, proto_tree_free_node, NULL);
590 PROTO_NODE_FREE(tree);
593 free_node_tree_data(tree_data);
596 /* Is the parsing being done for a visible proto_tree or an invisible one?
597 * By setting this correctly, the proto_tree creation is sped up by not
598 * having to call g_vsnprintf and copy strings around.
601 proto_tree_set_visible(proto_tree *tree, gboolean visible)
603 gboolean old_visible = PTREE_DATA(tree)->visible;
605 PTREE_DATA(tree)->visible = visible;
611 proto_tree_set_fake_protocols(proto_tree *tree, gboolean fake_protocols)
613 PTREE_DATA(tree)->fake_protocols = fake_protocols;
616 /* Assume dissector set only its protocol fields.
617 This function is called by dissectors and allows the speeding up of filtering
618 in wireshark; if this function returns FALSE it is safe to reset tree to NULL
619 and thus skip calling most of the expensive proto_tree_add_...()
621 If the tree is visible we implicitly assume the field is referenced.
624 proto_field_is_referenced(proto_tree *tree, int proto_id)
626 register header_field_info *hfinfo;
632 if (PTREE_DATA(tree)->visible)
635 PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
636 if (hfinfo->ref_type != HF_REF_TYPE_NONE)
639 if (hfinfo->type == FT_PROTOCOL && !PTREE_DATA(tree)->fake_protocols)
646 /* Finds a record in the hfinfo array by id. */
648 proto_registrar_get_nth(guint hfindex)
650 register header_field_info *hfinfo;
652 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
657 /* Prefix initialization
658 * this allows for a dissector to register a display filter name prefix
659 * so that it can delay the initialization of the hf array as long as
663 /* compute a hash for the part before the dot of a display filter */
665 prefix_hash (gconstpointer key) {
666 /* end the string at the dot and compute its hash */
667 gchar* copy = ep_strdup((const gchar *)key);
677 return g_str_hash(copy);
680 /* are both strings equal up to the end or the dot? */
682 prefix_equal (gconstpointer ap, gconstpointer bp) {
683 const gchar* a = (const gchar *)ap;
684 const gchar* b = (const gchar *)bp;
690 if ( (ac == '.' || ac == '\0') && (bc == '.' || bc == '\0') ) return TRUE;
692 if ( (ac == '.' || ac == '\0') && ! (bc == '.' || bc == '\0') ) return FALSE;
693 if ( (bc == '.' || bc == '\0') && ! (ac == '.' || ac == '\0') ) return FALSE;
695 if (ac != bc) return FALSE;
702 /* indexed by prefix, contains initializers */
703 static GHashTable* prefixes = NULL;
706 /* Register a new prefix for "delayed" initialization of field arrays */
708 proto_register_prefix(const char *prefix, prefix_initializer_t pi ) {
710 prefixes = g_hash_table_new(prefix_hash, prefix_equal);
713 g_hash_table_insert(prefixes, (gpointer)prefix, pi);
716 /* helper to call all prefix initializers */
718 initialize_prefix(gpointer k, gpointer v, gpointer u _U_) {
719 ((prefix_initializer_t)v)((const char *)k);
723 /** Initialize every remaining uninitialized prefix. */
725 proto_initialize_all_prefixes(void) {
726 g_hash_table_foreach_remove(prefixes, initialize_prefix, NULL);
729 /* Finds a record in the hfinfo array by name.
730 * If it fails to find it in the already registered fields,
731 * it tries to find and call an initializer in the prefixes
732 * table and if so it looks again.
735 proto_registrar_get_byname(const char *field_name)
737 header_field_info *hfinfo;
738 prefix_initializer_t pi;
743 hfinfo = (header_field_info *)g_tree_lookup(gpa_name_tree, field_name);
751 if ((pi = (prefix_initializer_t)g_hash_table_lookup(prefixes, field_name) ) != NULL) {
753 g_hash_table_remove(prefixes, field_name);
758 return (header_field_info *)g_tree_lookup(gpa_name_tree, field_name);
762 proto_registrar_get_id_byname(const char *field_name)
764 header_field_info *hfinfo;
766 hfinfo = proto_registrar_get_byname(field_name);
776 ptvcursor_new_subtree_levels(ptvcursor_t *ptvc)
778 subtree_lvl *pushed_tree;
780 DISSECTOR_ASSERT(ptvc->pushed_tree_max <= SUBTREE_MAX_LEVELS-SUBTREE_ONCE_ALLOCATION_NUMBER);
781 ptvc->pushed_tree_max += SUBTREE_ONCE_ALLOCATION_NUMBER;
783 pushed_tree = (subtree_lvl *)ep_alloc(sizeof(subtree_lvl) * ptvc->pushed_tree_max);
784 DISSECTOR_ASSERT(pushed_tree != NULL);
785 if (ptvc->pushed_tree)
786 memcpy(pushed_tree, ptvc->pushed_tree, ptvc->pushed_tree_max - SUBTREE_ONCE_ALLOCATION_NUMBER);
787 ptvc->pushed_tree = pushed_tree;
791 ptvcursor_free_subtree_levels(ptvcursor_t *ptvc)
793 ptvc->pushed_tree = NULL;
794 ptvc->pushed_tree_max = 0;
795 DISSECTOR_ASSERT(ptvc->pushed_tree_index == 0);
796 ptvc->pushed_tree_index = 0;
799 /* Allocates an initializes a ptvcursor_t with 3 variables:
800 * proto_tree, tvbuff, and offset. */
802 ptvcursor_new(proto_tree *tree, tvbuff_t *tvb, gint offset)
806 ptvc = (ptvcursor_t *)ep_alloc(sizeof(ptvcursor_t));
809 ptvc->offset = offset;
810 ptvc->pushed_tree = NULL;
811 ptvc->pushed_tree_max = 0;
812 ptvc->pushed_tree_index = 0;
817 /* Frees memory for ptvcursor_t, but nothing deeper than that. */
819 ptvcursor_free(ptvcursor_t *ptvc)
821 ptvcursor_free_subtree_levels(ptvc);
825 /* Returns tvbuff. */
827 ptvcursor_tvbuff(ptvcursor_t *ptvc)
832 /* Returns current offset. */
834 ptvcursor_current_offset(ptvcursor_t *ptvc)
840 ptvcursor_tree(ptvcursor_t *ptvc)
849 ptvcursor_set_tree(ptvcursor_t *ptvc, proto_tree *tree)
854 /* creates a subtree, sets it as the working tree and pushes the old working tree */
856 ptvcursor_push_subtree(ptvcursor_t *ptvc, proto_item *it, gint ett_subtree)
858 subtree_lvl *subtree;
859 if (ptvc->pushed_tree_index >= ptvc->pushed_tree_max)
860 ptvcursor_new_subtree_levels(ptvc);
862 subtree = ptvc->pushed_tree + ptvc->pushed_tree_index;
863 subtree->tree = ptvc->tree;
865 ptvc->pushed_tree_index++;
866 return ptvcursor_set_subtree(ptvc, it, ett_subtree);
871 ptvcursor_pop_subtree(ptvcursor_t *ptvc)
873 subtree_lvl *subtree;
875 if (ptvc->pushed_tree_index <= 0)
878 ptvc->pushed_tree_index--;
879 subtree = ptvc->pushed_tree + ptvc->pushed_tree_index;
880 if (subtree->it != NULL)
881 proto_item_set_len(subtree->it, ptvcursor_current_offset(ptvc) - subtree->cursor_offset);
883 ptvc->tree = subtree->tree;
886 /* saves the current tvb offset and the item in the current subtree level */
888 ptvcursor_subtree_set_item(ptvcursor_t *ptvc, proto_item *it)
890 subtree_lvl *subtree;
892 DISSECTOR_ASSERT(ptvc->pushed_tree_index > 0);
894 subtree = ptvc->pushed_tree + ptvc->pushed_tree_index - 1;
896 subtree->cursor_offset = ptvcursor_current_offset(ptvc);
899 /* Creates a subtree and adds it to the cursor as the working tree but does not
900 * save the old working tree */
902 ptvcursor_set_subtree(ptvcursor_t *ptvc, proto_item *it, gint ett_subtree)
904 ptvc->tree = proto_item_add_subtree(it, ett_subtree);
909 ptvcursor_add_subtree_item(ptvcursor_t *ptvc, proto_item *it, gint ett_subtree, gint length)
911 ptvcursor_push_subtree(ptvc, it, ett_subtree);
912 if (length == SUBTREE_UNDEFINED_LENGTH)
913 ptvcursor_subtree_set_item(ptvc, it);
914 return ptvcursor_tree(ptvc);
917 /* Add an item to the tree and create a subtree
918 * If the length is unknown, length may be defined as SUBTREE_UNDEFINED_LENGTH.
919 * In this case, when the subtree will be closed, the parent item length will
920 * be equal to the advancement of the cursor since the creation of the subtree.
923 ptvcursor_add_with_subtree(ptvcursor_t *ptvc, int hfindex, gint length,
924 const guint encoding, gint ett_subtree)
928 it = ptvcursor_add_no_advance(ptvc, hfindex, length, encoding);
929 return ptvcursor_add_subtree_item(ptvc, it, ett_subtree, length);
933 proto_tree_add_text_node(proto_tree *tree, tvbuff_t *tvb, gint start, gint length);
935 /* Add a text node to the tree and create a subtree
936 * If the length is unknown, length may be defined as SUBTREE_UNDEFINED_LENGTH.
937 * In this case, when the subtree will be closed, the item length will be equal
938 * to the advancement of the cursor since the creation of the subtree.
941 ptvcursor_add_text_with_subtree(ptvcursor_t *ptvc, gint length,
942 gint ett_subtree, const char *format, ...)
946 header_field_info *hfinfo;
949 tree = ptvcursor_tree(ptvc);
951 TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
953 pi = proto_tree_add_text_node(tree, ptvcursor_tvbuff(ptvc),
954 ptvcursor_current_offset(ptvc), length);
956 TRY_TO_FAKE_THIS_REPR(pi);
958 va_start(ap, format);
959 proto_tree_set_representation(pi, format, ap);
962 return ptvcursor_add_subtree_item(ptvc, pi, ett_subtree, length);
965 /* Add a text-only node, leaving it to our caller to fill the text in */
967 proto_tree_add_text_node(proto_tree *tree, tvbuff_t *tvb, gint start, gint length)
974 pi = proto_tree_add_pi(tree, &hfi_text_only, tvb, start, &length);
979 /* Add a text-only node to the proto_tree */
981 proto_tree_add_text(proto_tree *tree, tvbuff_t *tvb, gint start, gint length,
982 const char *format, ...)
986 header_field_info *hfinfo;
988 TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
990 pi = proto_tree_add_text_node(tree, tvb, start, length);
992 TRY_TO_FAKE_THIS_REPR(pi);
994 va_start(ap, format);
995 proto_tree_set_representation(pi, format, ap);
1001 /* Add a text-only node to the proto_tree (va_list version) */
1003 proto_tree_add_text_valist(proto_tree *tree, tvbuff_t *tvb, gint start,
1004 gint length, const char *format, va_list ap)
1007 header_field_info *hfinfo;
1009 TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
1011 pi = proto_tree_add_text_node(tree, tvb, start, length);
1013 TRY_TO_FAKE_THIS_REPR(pi);
1015 proto_tree_set_representation(pi, format, ap);
1020 /* Add a text-only node for debugging purposes. The caller doesn't need
1021 * to worry about tvbuff, start, or length. Debug message gets sent to
1024 proto_tree_add_debug_text(proto_tree *tree, const char *format, ...)
1029 pi = proto_tree_add_text_node(tree, NULL, 0, 0);
1032 va_start(ap, format);
1033 proto_tree_set_representation(pi, format, ap);
1036 va_start(ap, format);
1037 vprintf(format, ap);
1044 /* We could probably get away with changing is_error to a minimum length value. */
1046 report_type_length_mismatch(proto_tree *tree, const gchar *descr, int length, gboolean is_error) {
1048 tree_data_t *tree_data = PTREE_DATA(tree);
1049 field_info *fi_save = tree_data->fi_tmp;
1051 /* Keep the current item from getting freed by proto_tree_new_item. */
1052 tree_data->fi_tmp = NULL;
1054 expert_add_info_format(NULL, tree, PI_MALFORMED, is_error ? PI_ERROR : PI_WARN, "Trying to fetch %s with length %d", descr, length);
1056 tree_data->fi_tmp = fi_save;
1060 THROW(ReportedBoundsError);
1065 get_uint_value(proto_tree *tree, tvbuff_t *tvb, gint offset, gint length, const guint encoding)
1068 gboolean length_error;
1073 value = tvb_get_guint8(tvb, offset);
1077 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letohs(tvb, offset)
1078 : tvb_get_ntohs(tvb, offset);
1082 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letoh24(tvb, offset)
1083 : tvb_get_ntoh24(tvb, offset);
1087 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letohl(tvb, offset)
1088 : tvb_get_ntohl(tvb, offset);
1093 length_error = TRUE;
1096 length_error = FALSE;
1097 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letohl(tvb, offset)
1098 : tvb_get_ntohl(tvb, offset);
1100 report_type_length_mismatch(tree, "an unsigned integer", length, length_error);
1107 * NOTE: to support code written when proto_tree_add_item() took a
1108 * gboolean as its last argument, with FALSE meaning "big-endian"
1109 * and TRUE meaning "little-endian", we treat any non-zero value of
1110 * "encoding" as meaning "little-endian".
1113 get_int_value(proto_tree *tree, tvbuff_t *tvb, gint offset, gint length, const guint encoding)
1116 gboolean length_error;
1121 value = (gint8)tvb_get_guint8(tvb, offset);
1125 value = (gint16) (encoding ? tvb_get_letohs(tvb, offset)
1126 : tvb_get_ntohs(tvb, offset));
1130 value = encoding ? tvb_get_letoh24(tvb, offset)
1131 : tvb_get_ntoh24(tvb, offset);
1132 if (value & 0x00800000) {
1133 /* Sign bit is set; sign-extend it. */
1134 value |= 0xFF000000;
1139 value = encoding ? tvb_get_letohl(tvb, offset)
1140 : tvb_get_ntohl(tvb, offset);
1145 length_error = TRUE;
1148 length_error = FALSE;
1149 value = encoding ? tvb_get_letohl(tvb, offset)
1150 : tvb_get_ntohl(tvb, offset);
1152 report_type_length_mismatch(tree, "a signed integer", length, length_error);
1159 tree_data_add_maybe_interesting_field(tree_data_t *tree_data, field_info *fi)
1161 const header_field_info *hfinfo = fi->hfinfo;
1163 if (hfinfo->ref_type == HF_REF_TYPE_DIRECT) {
1164 GPtrArray *ptrs = NULL;
1166 if (tree_data->interesting_hfids == NULL) {
1167 /* Initialize the hash because we now know that it is needed */
1168 tree_data->interesting_hfids =
1169 g_hash_table_new(g_direct_hash, NULL /* g_direct_equal */);
1171 ptrs = (GPtrArray *)g_hash_table_lookup(tree_data->interesting_hfids,
1172 GINT_TO_POINTER(hfinfo->id));
1174 /* First element triggers the creation of pointer array */
1175 ptrs = g_ptr_array_new();
1176 g_hash_table_insert(tree_data->interesting_hfids,
1177 GINT_TO_POINTER(hfinfo->id), ptrs);
1180 g_ptr_array_add(ptrs, fi);
1184 /* Add an item to a proto_tree, using the text label registered to that item;
1185 the item is extracted from the tvbuff handed to it. */
1187 proto_tree_new_item(field_info *new_fi, proto_tree *tree,
1188 tvbuff_t *tvb, gint start, gint length,
1191 tree_data_t *tree_data = PTREE_DATA(tree);
1197 nstime_t time_stamp;
1199 gboolean length_error;
1201 /* there is a possibility here that we might raise an exception
1202 * and thus would lose track of the field_info.
1203 * store it in a temp so that if we come here again we can reclaim
1204 * the field_info without leaking memory.
1206 if (tree_data->fi_tmp) {
1207 /* oops, last one we got must have been lost due
1209 * good thing we saved it, now we can reverse the
1210 * memory leak and reclaim it.
1212 FIELD_INFO_FREE(tree_data->fi_tmp);
1214 /* we might throw an exception, keep track of this one
1215 * across the "dangerous" section below.
1217 tree_data->fi_tmp = new_fi;
1219 switch (new_fi->hfinfo->type) {
1221 /* no value to set for FT_NONE */
1225 proto_tree_set_protocol_tvb(new_fi, tvb);
1229 proto_tree_set_bytes_tvb(new_fi, tvb, start, length);
1234 * Map all non-zero values to little-endian for
1235 * backwards compatibility.
1238 encoding = ENC_LITTLE_ENDIAN;
1239 n = get_uint_value(tree, tvb, start, length, encoding);
1240 proto_tree_set_bytes_tvb(new_fi, tvb, start + length, n);
1242 /* Instead of calling proto_item_set_len(), since we don't yet
1243 * have a proto_item, we set the field_info's length ourselves. */
1244 new_fi->length = n + length;
1249 * Map all non-zero values to little-endian for
1250 * backwards compatibility.
1253 encoding = ENC_LITTLE_ENDIAN;
1254 proto_tree_set_boolean(new_fi,
1255 get_uint_value(tree, tvb, start, length, encoding));
1258 /* XXX - make these just FT_UINT? */
1264 * Map all non-zero values to little-endian for
1265 * backwards compatibility.
1268 encoding = ENC_LITTLE_ENDIAN;
1269 proto_tree_set_uint(new_fi,
1270 get_uint_value(tree, tvb, start, length, encoding));
1276 * Map all non-zero values to little-endian for
1277 * backwards compatibility.
1280 encoding = ENC_LITTLE_ENDIAN;
1281 if (length < 1 || length > 8) {
1282 length_error = length < 1 ? TRUE : FALSE;
1283 report_type_length_mismatch(tree, "a 64-bit integer", length, length_error);
1285 proto_tree_set_uint64_tvb(new_fi, tvb, start, length, encoding);
1288 /* XXX - make these just FT_INT? */
1294 * Map all non-zero values to little-endian for
1295 * backwards compatibility.
1298 encoding = ENC_LITTLE_ENDIAN;
1299 proto_tree_set_int(new_fi,
1300 get_int_value(tree, tvb, start, length, encoding));
1305 * Map all non-zero values to little-endian for
1306 * backwards compatibility.
1309 encoding = ENC_LITTLE_ENDIAN;
1310 if (length != FT_IPv4_LEN) {
1311 length_error = length < FT_IPv4_LEN ? TRUE : FALSE;
1312 report_type_length_mismatch(tree, "an IPv4 address", length, length_error);
1314 value = tvb_get_ipv4(tvb, start);
1316 * NOTE: to support code written when
1317 * proto_tree_add_item() took a gboolean as its
1318 * last argument, with FALSE meaning "big-endian"
1319 * and TRUE meaning "little-endian", we treat any
1320 * non-zero value of "encoding" as meaning
1323 proto_tree_set_ipv4(new_fi, encoding ? GUINT32_SWAP_LE_BE(value) : value);
1327 if (length != FT_IPXNET_LEN) {
1328 length_error = length < FT_IPXNET_LEN ? TRUE : FALSE;
1329 report_type_length_mismatch(tree, "an IPXNET address", length, length_error);
1331 proto_tree_set_ipxnet(new_fi,
1332 get_uint_value(tree, tvb, start, FT_IPXNET_LEN, ENC_BIG_ENDIAN));
1336 if (length != FT_IPv6_LEN) {
1337 length_error = length < FT_IPv6_LEN ? TRUE : FALSE;
1338 report_type_length_mismatch(tree, "an IPv6 address", length, length_error);
1340 proto_tree_set_ipv6_tvb(new_fi, tvb, start, length);
1345 length_error = length < 7 ? TRUE : FALSE;
1346 report_type_length_mismatch(tree, "an AX.25 address", length, length_error);
1348 proto_tree_set_ax25_tvb(new_fi, tvb, start);
1352 if (length != VINES_ADDR_LEN) {
1353 length_error = length < VINES_ADDR_LEN ? TRUE : FALSE;
1354 report_type_length_mismatch(tree, "a Vines address", length, length_error);
1356 proto_tree_set_vines_tvb(new_fi, tvb, start);
1360 if (length != FT_ETHER_LEN) {
1361 length_error = length < FT_ETHER_LEN ? TRUE : FALSE;
1362 report_type_length_mismatch(tree, "an Ethernet", length, length_error);
1364 proto_tree_set_ether_tvb(new_fi, tvb, start);
1369 * Map all non-zero values to little-endian for
1370 * backwards compatibility.
1373 encoding = ENC_LITTLE_ENDIAN;
1374 if (length != FT_EUI64_LEN) {
1375 length_error = length < FT_EUI64_LEN ? TRUE : FALSE;
1376 report_type_length_mismatch(tree, "an EUI-64 address", length, length_error);
1378 proto_tree_set_eui64_tvb(new_fi, tvb, start, encoding);
1382 * Map all non-zero values to little-endian for
1383 * backwards compatibility.
1386 encoding = ENC_LITTLE_ENDIAN;
1387 if (length != FT_GUID_LEN) {
1388 length_error = length < FT_GUID_LEN ? TRUE : FALSE;
1389 report_type_length_mismatch(tree, "a GUID", length, length_error);
1391 proto_tree_set_guid_tvb(new_fi, tvb, start, encoding);
1395 proto_tree_set_oid_tvb(new_fi, tvb, start, length);
1400 * NOTE: to support code written when
1401 * proto_tree_add_item() took a gboolean as its
1402 * last argument, with FALSE meaning "big-endian"
1403 * and TRUE meaning "little-endian", we treat any
1404 * non-zero value of "encoding" as meaning
1407 * At some point in the future, we might
1408 * support non-IEEE-binary floating-point
1409 * formats in the encoding as well
1410 * (IEEE decimal, System/3x0, VAX).
1413 encoding = ENC_LITTLE_ENDIAN;
1415 length_error = length < 4 ? TRUE : FALSE;
1416 report_type_length_mismatch(tree, "a single-precision floating point number", length, length_error);
1419 floatval = tvb_get_letohieee_float(tvb, start);
1421 floatval = tvb_get_ntohieee_float(tvb, start);
1422 proto_tree_set_float(new_fi, floatval);
1427 * NOTE: to support code written when
1428 * proto_tree_add_item() took a gboolean as its
1429 * last argument, with FALSE meaning "big-endian"
1430 * and TRUE meaning "little-endian", we treat any
1431 * non-zero value of "encoding" as meaning
1434 * At some point in the future, we might
1435 * support non-IEEE-binary floating-point
1436 * formats in the encoding as well
1437 * (IEEE decimal, System/3x0, VAX).
1439 if (encoding == TRUE)
1440 encoding = ENC_LITTLE_ENDIAN;
1442 length_error = length < 8 ? TRUE : FALSE;
1443 report_type_length_mismatch(tree, "a double-precision floating point number", length, length_error);
1446 doubleval = tvb_get_letohieee_double(tvb, start);
1448 doubleval = tvb_get_ntohieee_double(tvb, start);
1449 proto_tree_set_double(new_fi, doubleval);
1453 proto_tree_set_string_tvb(new_fi, tvb, start, length,
1459 report_type_length_mismatch(tree, "a string", length, TRUE);
1461 /* Instead of calling proto_item_set_len(),
1462 * since we don't yet have a proto_item, we
1463 * set the field_info's length ourselves.
1465 * XXX - our caller can't use that length to
1466 * advance an offset unless they arrange that
1467 * there always be a protocol tree into which
1468 * we're putting this item.
1471 /* This can throw an exception */
1472 string = tvb_get_stringz_enc(tvb, start, &length, encoding);
1473 } else if (length == 0) {
1476 /* In this case, length signifies
1477 * the length of the string.
1479 * This could either be a null-padded
1480 * string, which doesn't necessarily
1481 * have a '\0' at the end, or a
1482 * null-terminated string, with a
1483 * trailing '\0'. (Yes, there are
1484 * cases where you have a string
1485 * that's both counted and null-
1488 * In the first case, we must
1489 * allocate a buffer of length
1490 * "length+1", to make room for
1493 * In the second case, we don't
1494 * assume that there is a trailing
1495 * '\0' there, as the packet might
1496 * be malformed. (XXX - should we
1497 * throw an exception if there's no
1498 * trailing '\0'?) Therefore, we
1499 * allocate a buffer of length
1500 * "length+1", and put in a trailing
1501 * '\0', just to be safe.
1503 * (XXX - this would change if
1504 * we made string values counted
1505 * rather than null-terminated.)
1507 string = tvb_get_ephemeral_string_enc(tvb, start, length, encoding);
1509 new_fi->length = length;
1510 proto_tree_set_string(new_fi, string);
1513 case FT_UINT_STRING:
1515 * NOTE: to support code written when
1516 * proto_tree_add_item() took a gboolean as its
1517 * last argument, with FALSE meaning "big-endian"
1518 * and TRUE meaning "little-endian", if the
1519 * encoding value is TRUE, treat that as
1520 * ASCII with a little-endian length.
1522 * This won't work for code that passes
1523 * arbitrary non-zero values; that code
1524 * will need to be fixed.
1526 if (encoding == TRUE)
1527 encoding = ENC_ASCII|ENC_LITTLE_ENDIAN;
1528 n = get_uint_value(tree, tvb, start, length, encoding & ~ENC_CHARENCODING_MASK);
1529 proto_tree_set_string_tvb(new_fi, tvb, start + length, n,
1532 /* Instead of calling proto_item_set_len(), since we
1533 * don't yet have a proto_item, we set the
1534 * field_info's length ourselves.
1536 * XXX - our caller can't use that length to
1537 * advance an offset unless they arrange that
1538 * there always be a protocol tree into which
1539 * we're putting this item.
1541 new_fi->length = n + length;
1544 case FT_ABSOLUTE_TIME:
1546 * Absolute times can be in any of a number of
1547 * formats, and they can be big-endian or
1550 * Historically FT_TIMEs were only timespecs;
1551 * the only question was whether they were stored
1552 * in big- or little-endian format.
1554 * For backwards compatibility, we interpret an
1555 * encoding of 1 as meaning "little-endian timespec",
1556 * so that passing TRUE is interpreted as that.
1558 if (encoding == TRUE)
1559 encoding = ENC_TIME_TIMESPEC|ENC_LITTLE_ENDIAN;
1561 if (length != 8 && length != 4) {
1562 length_error = length < 4 ? TRUE : FALSE;
1563 report_type_length_mismatch(tree, "an absolute time value", length, length_error);
1568 case ENC_TIME_TIMESPEC|ENC_BIG_ENDIAN:
1570 * 4-byte UNIX epoch, possibly followed by
1571 * 4-byte fractional time in nanoseconds,
1574 time_stamp.secs = tvb_get_ntohl(tvb, start);
1576 time_stamp.nsecs = tvb_get_ntohl(tvb, start+4);
1578 time_stamp.nsecs = 0;
1581 case ENC_TIME_TIMESPEC|ENC_LITTLE_ENDIAN:
1583 * 4-byte UNIX epoch, possibly followed by
1584 * 4-byte fractional time in nanoseconds,
1585 * both little-endian.
1587 time_stamp.secs = tvb_get_letohl(tvb, start);
1589 time_stamp.nsecs = tvb_get_letohl(tvb, start+4);
1591 time_stamp.nsecs = 0;
1594 case ENC_TIME_NTP|ENC_BIG_ENDIAN:
1596 * NTP time stamp, big-endian.
1599 /* XXX - where should this go? */
1600 #define NTP_BASETIME 2208988800ul
1602 /* We need a temporary variable here so the unsigned math
1603 * works correctly (for years > 2036 according to RFC 2030
1606 tmpsecs = tvb_get_ntohl(tvb, start);
1608 time_stamp.secs = tmpsecs - (guint32)NTP_BASETIME;
1610 time_stamp.secs = tmpsecs; /* 0 */
1614 * We're using nanoseconds here (and we will
1615 * display nanoseconds), but NTP's timestamps
1616 * have a precision in microseconds or greater.
1617 * Round to 1 microsecond.
1619 time_stamp.nsecs = (int)(1000000*(tvb_get_ntohl(tvb, start+4)/4294967296.0));
1620 time_stamp.nsecs *= 1000;
1622 time_stamp.nsecs = 0;
1626 case ENC_TIME_NTP|ENC_LITTLE_ENDIAN:
1628 * NTP time stamp, big-endian.
1630 tmpsecs = tvb_get_letohl(tvb, start);
1632 time_stamp.secs = tmpsecs - (guint32)NTP_BASETIME;
1634 time_stamp.secs = tmpsecs; /* 0 */
1638 * We're using nanoseconds here (and we will
1639 * display nanoseconds), but NTP's timestamps
1640 * have a precision in microseconds or greater.
1641 * Round to 1 microsecond.
1643 time_stamp.nsecs = (int)(1000000*(tvb_get_letohl(tvb, start+4)/4294967296.0));
1644 time_stamp.nsecs *= 1000;
1646 time_stamp.nsecs = 0;
1651 DISSECTOR_ASSERT_NOT_REACHED();
1652 time_stamp.secs = 0;
1653 time_stamp.nsecs = 0;
1656 proto_tree_set_time(new_fi, &time_stamp);
1659 case FT_RELATIVE_TIME:
1661 * Relative times can be in any of a number of
1662 * formats, and they can be big-endian or
1665 * Historically FT_TIMEs were only timespecs;
1666 * the only question was whether they were stored
1667 * in big- or little-endian format.
1669 * For backwards compatibility, we interpret an
1670 * encoding of 1 as meaning "little-endian timespec",
1671 * so that passing TRUE is interpreted as that.
1673 if (encoding == TRUE)
1674 encoding = ENC_TIME_TIMESPEC|ENC_LITTLE_ENDIAN;
1677 if (length != 8 && length != 4) {
1678 length_error = length < 4 ? TRUE : FALSE;
1679 report_type_length_mismatch(tree, "a relative time value", length, length_error);
1682 case ENC_TIME_TIMESPEC|ENC_BIG_ENDIAN:
1684 * 4-byte UNIX epoch, possibly followed by
1685 * 4-byte fractional time in nanoseconds,
1688 time_stamp.secs = tvb_get_ntohl(tvb, start);
1690 time_stamp.nsecs = tvb_get_ntohl(tvb, start+4);
1692 time_stamp.nsecs = 0;
1695 case ENC_TIME_TIMESPEC|ENC_LITTLE_ENDIAN:
1697 * 4-byte UNIX epoch, possibly followed by
1698 * 4-byte fractional time in nanoseconds,
1699 * both little-endian.
1701 time_stamp.secs = tvb_get_letohl(tvb, start);
1703 time_stamp.nsecs = tvb_get_letohl(tvb, start+4);
1705 time_stamp.nsecs = 0;
1708 proto_tree_set_time(new_fi, &time_stamp);
1712 g_error("new_fi->hfinfo->type %d (%s) not handled\n",
1713 new_fi->hfinfo->type,
1714 ftype_name(new_fi->hfinfo->type));
1715 DISSECTOR_ASSERT_NOT_REACHED();
1718 FI_SET_FLAG(new_fi, (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN);
1720 /* Don't add new node to proto_tree until now so that any exceptions
1721 * raised by a tvbuff access method doesn't leave junk in the proto_tree. */
1722 /* XXX. wouldn't be better to add this item to tree, with some special flag (FI_EXCEPTION?)
1723 * to know which item caused exception? */
1724 pi = proto_tree_add_node(tree, new_fi);
1726 /* we did not raise an exception so we dont have to remember this
1727 * field_info struct any more.
1729 tree_data->fi_tmp = NULL;
1734 /* Gets data from tvbuff, adds it to proto_tree, increments offset,
1735 and returns proto_item* */
1737 ptvcursor_add(ptvcursor_t *ptvc, int hfindex, gint length,
1738 const guint encoding)
1741 header_field_info *hfinfo;
1746 /* We can't fake it just yet. We have to advance the cursor
1747 TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfindex, hfinfo); */
1749 offset = ptvc->offset;
1750 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1751 get_hfi_length(hfinfo, ptvc->tvb, offset, &length, &item_length);
1752 ptvc->offset += length;
1753 if (hfinfo->type == FT_UINT_BYTES || hfinfo->type == FT_UINT_STRING) {
1755 * The length of the rest of the item is in the first N
1756 * bytes of the item.
1758 n = get_uint_value(ptvc->tree, ptvc->tvb, offset, length, encoding);
1762 /* Coast clear. Try and fake it */
1763 TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfindex, hfinfo);
1765 new_fi = new_field_info(ptvc->tree, hfinfo, ptvc->tvb, offset, item_length);
1767 return proto_tree_new_item(new_fi, ptvc->tree, ptvc->tvb,
1768 offset, length, encoding);
1772 * Validates that field length bytes are available starting from
1773 * start (pos/neg). Throws an exception if they aren't.
1776 test_length(header_field_info *hfinfo, proto_tree *tree, tvbuff_t *tvb,
1777 gint start, gint length, const guint encoding)
1784 if (hfinfo->type == FT_UINT_BYTES || hfinfo->type == FT_UINT_STRING) {
1787 n = get_uint_value(tree, tvb, start, length, encoding);
1789 /* If n > size + n then we have an integer overflow, so
1790 * set size to -1, which will force the
1791 * tvb_ensure_bytes_exist call below to throw a
1792 * ReportedBoundsError
1799 } else if (hfinfo->type == FT_STRINGZ) {
1800 /* If we're fetching until the end of the TVB, only validate
1801 * that the offset is within range.
1807 tvb_ensure_bytes_exist(tvb, start, size);
1810 /* Add an item to a proto_tree, using the text label registered to that item;
1811 the item is extracted from the tvbuff handed to it. */
1813 proto_tree_add_item_new(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
1814 const gint start, gint length, const guint encoding)
1819 DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");
1821 get_hfi_length(hfinfo, tvb, start, &length, &item_length);
1822 test_length(hfinfo, tree, tvb, start, item_length, encoding);
1824 TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
1826 new_fi = new_field_info(tree, hfinfo, tvb, start, item_length);
1831 return proto_tree_new_item(new_fi, tree, tvb, start, length, encoding);
1835 proto_tree_add_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1836 const gint start, gint length, const guint encoding)
1838 return proto_tree_add_item_new(tree, proto_registrar_get_nth(hfindex), tvb, start, length, encoding);
1841 /* Add a FT_NONE to a proto_tree */
1843 proto_tree_add_none_format(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
1844 const gint start, gint length, const char *format,
1849 header_field_info *hfinfo;
1851 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1853 DISSECTOR_ASSERT(hfinfo->type == FT_NONE);
1855 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
1857 TRY_TO_FAKE_THIS_REPR(pi);
1859 va_start(ap, format);
1860 proto_tree_set_representation(pi, format, ap);
1863 /* no value to set for FT_NONE */
1867 /* Gets data from tvbuff, adds it to proto_tree, *DOES NOT* increment
1868 * offset, and returns proto_item* */
1870 ptvcursor_add_no_advance(ptvcursor_t* ptvc, int hf, gint length,
1871 const guint encoding)
1875 item = proto_tree_add_item(ptvc->tree, hf, ptvc->tvb, ptvc->offset,
1881 /* Advance the ptvcursor's offset within its tvbuff without
1882 * adding anything to the proto_tree. */
1884 ptvcursor_advance(ptvcursor_t* ptvc, gint length)
1886 ptvc->offset += length;
1891 proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb)
1893 fvalue_set(&fi->value, tvb, TRUE);
1896 /* Add a FT_PROTOCOL to a proto_tree */
1898 proto_tree_add_protocol_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1899 gint start, gint length, const char *format, ...)
1903 header_field_info *hfinfo;
1905 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1907 DISSECTOR_ASSERT(hfinfo->type == FT_PROTOCOL);
1909 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
1911 proto_tree_set_protocol_tvb(PNODE_FINFO(pi), (start == 0 ? tvb : tvb_new_subset(tvb, start, length, length)));
1913 TRY_TO_FAKE_THIS_REPR(pi);
1915 va_start(ap, format);
1916 proto_tree_set_representation(pi, format, ap);
1923 /* Add a FT_BYTES to a proto_tree */
1925 proto_tree_add_bytes(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1926 gint length, const guint8 *start_ptr)
1929 header_field_info *hfinfo;
1931 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1933 DISSECTOR_ASSERT(hfinfo->type == FT_BYTES);
1935 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
1936 proto_tree_set_bytes(PNODE_FINFO(pi), start_ptr, length);
1942 proto_tree_add_bytes_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1943 gint start, gint length,
1944 const guint8 *start_ptr,
1945 const char *format, ...)
1949 header_field_info *hfinfo;
1951 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1954 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length,
1957 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length,
1958 tvb_get_ptr(tvb, start, length));
1960 va_start(ap, format);
1961 proto_tree_set_representation_value(pi, format, ap);
1968 proto_tree_add_bytes_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1969 gint start, gint length, const guint8 *start_ptr,
1970 const char *format, ...)
1974 header_field_info *hfinfo;
1976 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1979 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length,
1982 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length,
1983 tvb_get_ptr(tvb, start, length));
1985 TRY_TO_FAKE_THIS_REPR(pi);
1987 va_start(ap, format);
1988 proto_tree_set_representation(pi, format, ap);
1995 proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length)
1999 bytes = g_byte_array_new();
2001 g_byte_array_append(bytes, start_ptr, length);
2003 fvalue_set(&fi->value, bytes, TRUE);
2008 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length)
2010 proto_tree_set_bytes(fi, tvb_get_ptr(tvb, offset, length), length);
2013 /* Add a FT_*TIME to a proto_tree */
2015 proto_tree_add_time(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2016 gint length, nstime_t *value_ptr)
2019 header_field_info *hfinfo;
2021 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2023 DISSECTOR_ASSERT(hfinfo->type == FT_ABSOLUTE_TIME ||
2024 hfinfo->type == FT_RELATIVE_TIME);
2026 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
2027 proto_tree_set_time(PNODE_FINFO(pi), value_ptr);
2033 proto_tree_add_time_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2034 gint start, gint length, nstime_t *value_ptr,
2035 const char *format, ...)
2040 pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
2042 va_start(ap, format);
2043 proto_tree_set_representation_value(pi, format, ap);
2051 proto_tree_add_time_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2052 gint start, gint length, nstime_t *value_ptr,
2053 const char *format, ...)
2058 pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
2060 TRY_TO_FAKE_THIS_REPR(pi);
2062 va_start(ap, format);
2063 proto_tree_set_representation(pi, format, ap);
2070 /* Set the FT_*TIME value */
2072 proto_tree_set_time(field_info *fi, nstime_t *value_ptr)
2074 DISSECTOR_ASSERT(value_ptr != NULL);
2076 fvalue_set(&fi->value, value_ptr, FALSE);
2079 /* Add a FT_IPXNET to a proto_tree */
2081 proto_tree_add_ipxnet(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2082 gint length, guint32 value)
2085 header_field_info *hfinfo;
2087 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2089 DISSECTOR_ASSERT(hfinfo->type == FT_IPXNET);
2091 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
2092 proto_tree_set_ipxnet(PNODE_FINFO(pi), value);
2098 proto_tree_add_ipxnet_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2099 gint start, gint length, guint32 value,
2100 const char *format, ...)
2105 pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
2107 va_start(ap, format);
2108 proto_tree_set_representation_value(pi, format, ap);
2116 proto_tree_add_ipxnet_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2117 gint start, gint length, guint32 value,
2118 const char *format, ...)
2123 pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
2125 TRY_TO_FAKE_THIS_REPR(pi);
2127 va_start(ap, format);
2128 proto_tree_set_representation(pi, format, ap);
2135 /* Set the FT_IPXNET value */
2137 proto_tree_set_ipxnet(field_info *fi, guint32 value)
2139 fvalue_set_uinteger(&fi->value, value);
2142 /* Add a FT_IPv4 to a proto_tree */
2144 proto_tree_add_ipv4(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2145 gint length, guint32 value)
2148 header_field_info *hfinfo;
2150 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2152 DISSECTOR_ASSERT(hfinfo->type == FT_IPv4);
2154 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
2155 proto_tree_set_ipv4(PNODE_FINFO(pi), value);
2161 proto_tree_add_ipv4_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2162 gint start, gint length, guint32 value,
2163 const char *format, ...)
2168 pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
2170 va_start(ap, format);
2171 proto_tree_set_representation_value(pi, format, ap);
2179 proto_tree_add_ipv4_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2180 gint start, gint length, guint32 value,
2181 const char *format, ...)
2186 pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
2188 TRY_TO_FAKE_THIS_REPR(pi);
2190 va_start(ap, format);
2191 proto_tree_set_representation(pi, format, ap);
2198 /* Set the FT_IPv4 value */
2200 proto_tree_set_ipv4(field_info *fi, guint32 value)
2202 fvalue_set_uinteger(&fi->value, value);
2205 /* Add a FT_IPv6 to a proto_tree */
2207 proto_tree_add_ipv6(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2208 gint length, const guint8* value_ptr)
2211 header_field_info *hfinfo;
2213 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2215 DISSECTOR_ASSERT(hfinfo->type == FT_IPv6);
2217 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
2218 proto_tree_set_ipv6(PNODE_FINFO(pi), value_ptr);
2224 proto_tree_add_ipv6_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2225 gint start, gint length,
2226 const guint8* value_ptr,
2227 const char *format, ...)
2232 pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
2234 va_start(ap, format);
2235 proto_tree_set_representation_value(pi, format, ap);
2243 proto_tree_add_ipv6_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2244 gint start, gint length, const guint8* value_ptr,
2245 const char *format, ...)
2250 pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
2252 TRY_TO_FAKE_THIS_REPR(pi);
2254 va_start(ap, format);
2255 proto_tree_set_representation(pi, format, ap);
2262 /* Set the FT_IPv6 value */
2264 proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr)
2266 DISSECTOR_ASSERT(value_ptr != NULL);
2267 fvalue_set(&fi->value, (gpointer) value_ptr, FALSE);
2271 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
2273 proto_tree_set_ipv6(fi, tvb_get_ptr(tvb, start, length));
2276 /* Add a FT_GUID to a proto_tree */
2278 proto_tree_add_guid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2279 gint length, const e_guid_t *value_ptr)
2282 header_field_info *hfinfo;
2284 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2286 DISSECTOR_ASSERT(hfinfo->type == FT_GUID);
2288 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
2289 proto_tree_set_guid(PNODE_FINFO(pi), value_ptr);
2295 proto_tree_add_guid_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2296 gint start, gint length,
2297 const e_guid_t *value_ptr,
2298 const char *format, ...)
2303 pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
2305 va_start(ap, format);
2306 proto_tree_set_representation_value(pi, format, ap);
2314 proto_tree_add_guid_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2315 gint start, gint length, const e_guid_t *value_ptr,
2316 const char *format, ...)
2321 pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
2323 TRY_TO_FAKE_THIS_REPR(pi);
2325 va_start(ap, format);
2326 proto_tree_set_representation(pi, format, ap);
2333 /* Set the FT_GUID value */
2335 proto_tree_set_guid(field_info *fi, const e_guid_t *value_ptr)
2337 DISSECTOR_ASSERT(value_ptr != NULL);
2338 fvalue_set(&fi->value, (gpointer) value_ptr, FALSE);
2342 proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, gint start,
2343 const guint encoding)
2347 tvb_get_guid(tvb, start, &guid, encoding);
2348 proto_tree_set_guid(fi, &guid);
2351 /* Add a FT_OID to a proto_tree */
2353 proto_tree_add_oid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2354 gint length, const guint8* value_ptr)
2357 header_field_info *hfinfo;
2359 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2361 DISSECTOR_ASSERT(hfinfo->type == FT_OID);
2363 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
2364 proto_tree_set_oid(PNODE_FINFO(pi), value_ptr, length);
2370 proto_tree_add_oid_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2371 gint start, gint length,
2372 const guint8* value_ptr,
2373 const char *format, ...)
2378 pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
2380 va_start(ap, format);
2381 proto_tree_set_representation_value(pi, format, ap);
2389 proto_tree_add_oid_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2390 gint start, gint length, const guint8* value_ptr,
2391 const char *format, ...)
2396 pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
2398 TRY_TO_FAKE_THIS_REPR(pi);
2400 va_start(ap, format);
2401 proto_tree_set_representation(pi, format, ap);
2408 /* Set the FT_OID value */
2410 proto_tree_set_oid(field_info *fi, const guint8* value_ptr, gint length)
2414 DISSECTOR_ASSERT(value_ptr != NULL);
2416 bytes = g_byte_array_new();
2418 g_byte_array_append(bytes, value_ptr, length);
2420 fvalue_set(&fi->value, bytes, TRUE);
2424 proto_tree_set_oid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
2426 proto_tree_set_oid(fi, tvb_get_ptr(tvb, start, length), length);
2430 proto_tree_set_uint64(field_info *fi, guint64 value)
2432 fvalue_set_integer64(&fi->value, value);
2436 * NOTE: to support code written when proto_tree_add_item() took a
2437 * gboolean as its last argument, with FALSE meaning "big-endian"
2438 * and TRUE meaning "little-endian", we treat any non-zero value of
2439 * "encoding" as meaning "little-endian".
2442 proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start,
2443 guint length, const guint encoding)
2446 guint8* b = (guint8 *)ep_tvb_memdup(tvb, start, length);
2451 default: DISSECTOR_ASSERT_NOT_REACHED();
2452 case 8: value <<= 8; value += *--b;
2453 case 7: value <<= 8; value += *--b;
2454 case 6: value <<= 8; value += *--b;
2455 case 5: value <<= 8; value += *--b;
2456 case 4: value <<= 8; value += *--b;
2457 case 3: value <<= 8; value += *--b;
2458 case 2: value <<= 8; value += *--b;
2459 case 1: value <<= 8; value += *--b;
2464 default: DISSECTOR_ASSERT_NOT_REACHED();
2465 case 8: value <<= 8; value += *b++;
2466 case 7: value <<= 8; value += *b++;
2467 case 6: value <<= 8; value += *b++;
2468 case 5: value <<= 8; value += *b++;
2469 case 4: value <<= 8; value += *b++;
2470 case 3: value <<= 8; value += *b++;
2471 case 2: value <<= 8; value += *b++;
2472 case 1: value <<= 8; value += *b++;
2477 proto_tree_set_uint64(fi, value);
2480 /* Add a FT_STRING or FT_STRINGZ to a proto_tree. Creates own copy of string,
2481 * and frees it when the proto_tree is destroyed. */
2483 proto_tree_add_string(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2484 gint length, const char* value)
2487 header_field_info *hfinfo;
2489 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2491 DISSECTOR_ASSERT(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ);
2493 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
2494 DISSECTOR_ASSERT(length >= 0);
2495 proto_tree_set_string(PNODE_FINFO(pi), value);
2501 proto_tree_add_unicode_string(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2502 gint length, const char* value)
2504 DISSECTOR_ASSERT(g_utf8_validate(value, -1, NULL));
2505 return proto_tree_add_string_format_value(tree, hfindex, tvb, start, length, value, "%s", value);
2509 proto_tree_add_string_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2510 gint start, gint length, const char* value,
2517 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
2519 va_start(ap, format);
2520 proto_tree_set_representation_value(pi, format, ap);
2528 proto_tree_add_string_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2529 gint start, gint length, const char* value,
2530 const char *format, ...)
2535 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
2537 TRY_TO_FAKE_THIS_REPR(pi);
2539 va_start(ap, format);
2540 proto_tree_set_representation(pi, format, ap);
2547 /* Appends string data to a FT_STRING or FT_STRINGZ, allowing progressive
2548 * field info update instead of only updating the representation as does
2549 * proto_item_append_text()
2551 /* NOTE: this function will break with the TRY_TO_FAKE_THIS_ITEM()
2552 * speed optimization.
2553 * Currently only WSP use this function so it is not that bad but try to
2554 * avoid using this one if possible.
2555 * IF you must use this function you MUST also disable the
2556 * TRY_TO_FAKE_THIS_ITEM() optimization for your dissector/function
2557 * using proto_item_append_string().
2558 * Do that by faking that the tree is visible by calling
2559 * proto_tree_set_visible(tree, TRUE) (see packet-wsp.c)
2560 * BEFORE you create the item you are later going to use
2561 * proto_item_append_string() on.
2564 proto_item_append_string(proto_item *pi, const char *str)
2567 header_field_info *hfinfo;
2568 const gchar *old_str, *new_str;
2575 fi = PITEM_FINFO(pi);
2576 DISSECTOR_ASSERT_HINT(fi, "proto_tree_set_visible(tree, TRUE) should have been called previously");
2578 hfinfo = fi->hfinfo;
2579 if (hfinfo->type == FT_PROTOCOL) {
2580 /* TRY_TO_FAKE_THIS_ITEM() speed optimization: silently skip */
2583 DISSECTOR_ASSERT(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ);
2584 old_str = (guint8 *)fvalue_get(&fi->value);
2585 if (old_str && old_str[0])
2586 new_str = ep_strconcat(old_str, str, NULL);
2589 fvalue_set(&fi->value, (gpointer) new_str, FALSE);
2592 /* Set the FT_STRING value */
2594 proto_tree_set_string(field_info *fi, const char* value)
2597 fvalue_set(&fi->value, (gpointer) value, FALSE);
2599 fvalue_set(&fi->value, (gpointer) "[ Null ]", FALSE);
2604 proto_tree_set_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length, gint encoding)
2609 length = tvb_ensure_length_remaining(tvb, start);
2612 string = tvb_get_ephemeral_string_enc(tvb, start, length, encoding);
2613 proto_tree_set_string(fi, string);
2617 /* Add a FT_AX25 to a proto_tree */
2619 proto_tree_add_ax25(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2620 const guint8* value)
2623 header_field_info *hfinfo;
2625 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2627 DISSECTOR_ASSERT(hfinfo->type == FT_AX25);
2629 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
2630 proto_tree_set_ax25(PNODE_FINFO(pi), value);
2635 /* Set the FT_AX25 value */
2637 proto_tree_set_ax25(field_info *fi, const guint8* value)
2639 fvalue_set(&fi->value, (gpointer) value, FALSE);
2643 proto_tree_set_ax25_tvb(field_info *fi, tvbuff_t *tvb, gint start)
2645 proto_tree_set_ax25(fi, tvb_get_ptr(tvb, start, 7));
2648 /* Set the FT_VINES value */
2650 proto_tree_set_vines(field_info *fi, const guint8* value)
2652 fvalue_set(&fi->value, (gpointer) value, FALSE);
2656 proto_tree_set_vines_tvb(field_info *fi, tvbuff_t *tvb, gint start)
2658 proto_tree_set_vines(fi, tvb_get_ptr(tvb, start, FT_VINES_ADDR_LEN));
2661 /* Add a FT_ETHER to a proto_tree */
2663 proto_tree_add_ether(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2664 gint length, const guint8* value)
2667 header_field_info *hfinfo;
2669 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2671 DISSECTOR_ASSERT(hfinfo->type == FT_ETHER);
2673 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
2674 proto_tree_set_ether(PNODE_FINFO(pi), value);
2680 proto_tree_add_ether_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2681 gint start, gint length, const guint8* value,
2682 const char *format, ...)
2687 pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
2689 va_start(ap, format);
2690 proto_tree_set_representation_value(pi, format, ap);
2698 proto_tree_add_ether_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2699 gint start, gint length, const guint8* value,
2700 const char *format, ...)
2705 pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
2707 TRY_TO_FAKE_THIS_REPR(pi);
2709 va_start(ap, format);
2710 proto_tree_set_representation(pi, format, ap);
2717 /* Set the FT_ETHER value */
2719 proto_tree_set_ether(field_info *fi, const guint8* value)
2721 fvalue_set(&fi->value, (gpointer) value, FALSE);
2725 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start)
2727 proto_tree_set_ether(fi, tvb_get_ptr(tvb, start, FT_ETHER_LEN));
2730 /* Add a FT_BOOLEAN to a proto_tree */
2732 proto_tree_add_boolean(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2733 gint length, guint32 value)
2736 header_field_info *hfinfo;
2738 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2740 DISSECTOR_ASSERT(hfinfo->type == FT_BOOLEAN);
2742 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
2743 proto_tree_set_boolean(PNODE_FINFO(pi), value);
2749 proto_tree_add_boolean_format_value(proto_tree *tree, int hfindex,
2750 tvbuff_t *tvb, gint start, gint length,
2751 guint32 value, const char *format, ...)
2756 pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
2758 va_start(ap, format);
2759 proto_tree_set_representation_value(pi, format, ap);
2767 proto_tree_add_boolean_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2768 gint start, gint length, guint32 value,
2769 const char *format, ...)
2774 pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
2776 TRY_TO_FAKE_THIS_REPR(pi);
2778 va_start(ap, format);
2779 proto_tree_set_representation(pi, format, ap);
2786 /* Set the FT_BOOLEAN value */
2788 proto_tree_set_boolean(field_info *fi, guint32 value)
2790 proto_tree_set_uint(fi, value);
2793 /* Add a FT_FLOAT to a proto_tree */
2795 proto_tree_add_float(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2796 gint length, float value)
2799 header_field_info *hfinfo;
2801 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2803 DISSECTOR_ASSERT(hfinfo->type == FT_FLOAT);
2805 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
2806 proto_tree_set_float(PNODE_FINFO(pi), value);
2812 proto_tree_add_float_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2813 gint start, gint length, float value,
2814 const char *format, ...)
2819 pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
2821 va_start(ap, format);
2822 proto_tree_set_representation_value(pi, format, ap);
2830 proto_tree_add_float_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2831 gint start, gint length, float value,
2832 const char *format, ...)
2837 pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
2839 TRY_TO_FAKE_THIS_REPR(pi);
2841 va_start(ap, format);
2842 proto_tree_set_representation(pi, format, ap);
2849 /* Set the FT_FLOAT value */
2851 proto_tree_set_float(field_info *fi, float value)
2853 fvalue_set_floating(&fi->value, value);
2856 /* Add a FT_DOUBLE to a proto_tree */
2858 proto_tree_add_double(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2859 gint length, double value)
2862 header_field_info *hfinfo;
2864 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2866 DISSECTOR_ASSERT(hfinfo->type == FT_DOUBLE);
2868 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
2869 proto_tree_set_double(PNODE_FINFO(pi), value);
2875 proto_tree_add_double_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2876 gint start, gint length, double value,
2877 const char *format, ...)
2882 pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
2884 va_start(ap, format);
2885 proto_tree_set_representation_value(pi, format, ap);
2893 proto_tree_add_double_format(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 TRY_TO_FAKE_THIS_REPR(pi);
2904 va_start(ap, format);
2905 proto_tree_set_representation(pi, format, ap);
2912 /* Set the FT_DOUBLE value */
2914 proto_tree_set_double(field_info *fi, double value)
2916 fvalue_set_floating(&fi->value, value);
2919 /* Add FT_UINT{8,16,24,32} to a proto_tree */
2921 proto_tree_add_uint(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2922 gint length, guint32 value)
2924 proto_item *pi = NULL;
2925 header_field_info *hfinfo;
2927 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2929 switch (hfinfo->type) {
2935 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
2936 proto_tree_set_uint(PNODE_FINFO(pi), value);
2940 DISSECTOR_ASSERT_NOT_REACHED();
2947 proto_tree_add_uint_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2948 gint start, gint length, guint32 value,
2949 const char *format, ...)
2954 pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
2956 va_start(ap, format);
2957 proto_tree_set_representation_value(pi, format, ap);
2965 proto_tree_add_uint_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2966 gint start, gint length, guint32 value,
2967 const char *format, ...)
2972 pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
2974 TRY_TO_FAKE_THIS_REPR(pi);
2976 va_start(ap, format);
2977 proto_tree_set_representation(pi, format, ap);
2984 /* Set the FT_UINT{8,16,24,32} value */
2986 proto_tree_set_uint(field_info *fi, guint32 value)
2988 header_field_info *hfinfo;
2991 hfinfo = fi->hfinfo;
2994 if (hfinfo->bitmask) {
2995 /* Mask out irrelevant portions */
2996 integer &= hfinfo->bitmask;
2999 integer >>= hfinfo_bitshift(hfinfo);
3002 fvalue_set_uinteger(&fi->value, integer);
3005 /* Add FT_UINT64 to a proto_tree */
3007 proto_tree_add_uint64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3008 gint length, guint64 value)
3011 header_field_info *hfinfo;
3013 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3015 DISSECTOR_ASSERT(hfinfo->type == FT_UINT64);
3017 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
3018 proto_tree_set_uint64(PNODE_FINFO(pi), value);
3024 proto_tree_add_uint64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3025 gint start, gint length, guint64 value,
3026 const char *format, ...)
3031 pi = proto_tree_add_uint64(tree, hfindex, tvb, start, length, value);
3033 va_start(ap, format);
3034 proto_tree_set_representation_value(pi, format, ap);
3042 proto_tree_add_uint64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3043 gint start, gint length, guint64 value,
3044 const char *format, ...)
3049 pi = proto_tree_add_uint64(tree, hfindex, tvb, start, length, value);
3051 TRY_TO_FAKE_THIS_REPR(pi);
3053 va_start(ap, format);
3054 proto_tree_set_representation(pi, format, ap);
3061 /* Add FT_INT{8,16,24,32} to a proto_tree */
3063 proto_tree_add_int(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3064 gint length, gint32 value)
3066 proto_item *pi = NULL;
3067 header_field_info *hfinfo;
3069 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3071 switch (hfinfo->type) {
3076 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
3077 proto_tree_set_int(PNODE_FINFO(pi), value);
3081 DISSECTOR_ASSERT_NOT_REACHED();
3088 proto_tree_add_int_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3089 gint start, gint length, gint32 value,
3090 const char *format, ...)
3095 pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
3097 va_start(ap, format);
3098 proto_tree_set_representation_value(pi, format, ap);
3106 proto_tree_add_int_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3107 gint start, gint length, gint32 value,
3108 const char *format, ...)
3113 pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
3115 TRY_TO_FAKE_THIS_REPR(pi);
3117 va_start(ap, format);
3118 proto_tree_set_representation(pi, format, ap);
3125 /* Set the FT_INT{8,16,24,32} value */
3127 proto_tree_set_int(field_info *fi, gint32 value)
3129 header_field_info *hfinfo;
3132 hfinfo = fi->hfinfo;
3133 integer = (guint32) value;
3135 if (hfinfo->bitmask) {
3136 /* Mask out irrelevant portions */
3137 integer &= hfinfo->bitmask;
3140 integer >>= hfinfo_bitshift(hfinfo);
3143 fvalue_set_sinteger(&fi->value, integer);
3146 /* Add FT_INT64 to a proto_tree */
3148 proto_tree_add_int64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3149 gint length, gint64 value)
3152 header_field_info *hfinfo;
3154 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3156 DISSECTOR_ASSERT(hfinfo->type == FT_INT64);
3158 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
3159 proto_tree_set_uint64(PNODE_FINFO(pi), (guint64)value);
3165 proto_tree_add_int64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3166 gint start, gint length, gint64 value,
3167 const char *format, ...)
3172 pi = proto_tree_add_int64(tree, hfindex, tvb, start, length, value);
3174 va_start(ap, format);
3175 proto_tree_set_representation_value(pi, format, ap);
3183 proto_tree_add_int64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3184 gint start, gint length, gint64 value,
3185 const char *format, ...)
3190 pi = proto_tree_add_int64(tree, hfindex, tvb, start, length, value);
3192 TRY_TO_FAKE_THIS_REPR(pi);
3194 va_start(ap, format);
3195 proto_tree_set_representation(pi, format, ap);
3201 /* Add a FT_EUI64 to a proto_tree */
3203 proto_tree_add_eui64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3204 gint length, const guint64 value)
3207 header_field_info *hfinfo;
3209 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3211 DISSECTOR_ASSERT(hfinfo->type == FT_EUI64);
3213 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
3214 proto_tree_set_eui64(PNODE_FINFO(pi), value);
3220 proto_tree_add_eui64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3221 gint start, gint length, const guint64 value,
3222 const char *format, ...)
3227 pi = proto_tree_add_eui64(tree, hfindex, tvb, start, length, value);
3229 va_start(ap, format);
3230 proto_tree_set_representation_value(pi, format, ap);
3238 proto_tree_add_eui64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3239 gint start, gint length, const guint64 value,
3240 const char *format, ...)
3245 pi = proto_tree_add_eui64(tree, hfindex, tvb, start, length, value);
3247 TRY_TO_FAKE_THIS_REPR(pi);
3249 va_start(ap, format);
3250 proto_tree_set_representation(pi, format, ap);
3257 /* Set the FT_EUI64 value */
3259 proto_tree_set_eui64(field_info *fi, const guint64 value)
3261 fvalue_set_integer64(&fi->value, value);
3264 proto_tree_set_eui64_tvb(field_info *fi, tvbuff_t *tvb, gint start, const guint encoding)
3268 proto_tree_set_eui64(fi, tvb_get_letoh64(tvb, start));
3270 proto_tree_set_eui64(fi, tvb_get_ntoh64(tvb, start));
3274 /* Add a field_info struct to the proto_tree, encapsulating it in a proto_node */
3276 proto_tree_add_node(proto_tree *tree, field_info *fi)
3278 proto_node *pnode, *tnode, *sibling;
3282 * Make sure "tree" is ready to have subtrees under it, by
3283 * checking whether it's been given an ett_ value.
3285 * "PNODE_FINFO(tnode)" may be null; that's the case for the root
3286 * node of the protocol tree. That node is not displayed,
3287 * so it doesn't need an ett_ value to remember whether it
3291 tfi = PNODE_FINFO(tnode);
3292 if (tfi != NULL && (tfi->tree_type < 0 || tfi->tree_type >= num_tree_types)) {
3293 REPORT_DISSECTOR_BUG(ep_strdup_printf("\"%s\" - \"%s\" tfi->tree_type: %u invalid (%s:%u)",
3294 fi->hfinfo->name, fi->hfinfo->abbrev, tfi->tree_type, __FILE__, __LINE__));
3295 /* XXX - is it safe to continue here? */
3298 PROTO_NODE_NEW(pnode);
3299 pnode->parent = tnode;
3300 PNODE_FINFO(pnode) = fi;
3301 pnode->tree_data = PTREE_DATA(tree);
3303 if (tnode->last_child != NULL) {
3304 sibling = tnode->last_child;
3305 DISSECTOR_ASSERT(sibling->next == NULL);
3306 sibling->next = pnode;
3308 tnode->first_child = pnode;
3309 tnode->last_child = pnode;
3311 tree_data_add_maybe_interesting_field(pnode->tree_data, fi);
3313 return (proto_item *)pnode;
3317 /* Generic way to allocate field_info and add to proto_tree.
3318 * Sets *pfi to address of newly-allocated field_info struct */
3320 proto_tree_add_pi(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb, gint start,
3326 fi = alloc_field_info(tree, hfinfo, tvb, start, length);
3327 pi = proto_tree_add_node(tree, fi);
3334 get_hfi_length(header_field_info *hfinfo, tvbuff_t *tvb, const gint start, gint *length,
3337 gint length_remaining;
3340 * We only allow a null tvbuff if the item has a zero length,
3341 * i.e. if there's no data backing it.
3343 DISSECTOR_ASSERT(tvb != NULL || *length == 0);
3346 * XXX - in some protocols, there are 32-bit unsigned length
3347 * fields, so lengths in protocol tree and tvbuff routines
3348 * should really be unsigned. We should have, for those
3349 * field types for which "to the end of the tvbuff" makes sense,
3350 * additional routines that take no length argument and
3351 * add fields that run to the end of the tvbuff.
3353 if (*length == -1) {
3355 * For FT_NONE, FT_PROTOCOL, FT_BYTES, and FT_STRING fields,
3356 * a length of -1 means "set the length to what remains in
3359 * The assumption is either that
3361 * 1) the length of the item can only be determined
3362 * by dissection (typically true of items with
3363 * subitems, which are probably FT_NONE or
3368 * 2) if the tvbuff is "short" (either due to a short
3369 * snapshot length or due to lack of reassembly of
3370 * fragments/segments/whatever), we want to display
3371 * what's available in the field (probably FT_BYTES
3372 * or FT_STRING) and then throw an exception later
3376 * 3) the field is defined to be "what's left in the
3379 * so we set the length to what remains in the tvbuff so
3380 * that, if we throw an exception while dissecting, it
3381 * has what is probably the right value.
3383 * For FT_STRINGZ, it means "the string is null-terminated,
3384 * not null-padded; set the length to the actual length
3385 * of the string", and if the tvbuff if short, we just
3386 * throw an exception.
3388 * It's not valid for any other type of field.
3390 switch (hfinfo->type) {
3394 * We allow this to be zero-length - for
3395 * example, an ONC RPC NULL procedure has
3396 * neither arguments nor reply, so the
3397 * payload for that protocol is empty.
3399 * However, if the length is negative, the
3400 * start offset is *past* the byte past the
3401 * end of the tvbuff, so we throw an
3404 *length = tvb_length_remaining(tvb, start);
3407 * Use "tvb_ensure_bytes_exist()"
3408 * to force the appropriate exception
3411 tvb_ensure_bytes_exist(tvb, start, 0);
3413 DISSECTOR_ASSERT(*length >= 0);
3419 *length = tvb_ensure_length_remaining(tvb, start);
3420 DISSECTOR_ASSERT(*length >= 0);
3425 * Leave the length as -1, so our caller knows
3431 DISSECTOR_ASSERT_NOT_REACHED();
3433 *item_length = *length;
3435 *item_length = *length;
3436 if (hfinfo->type == FT_PROTOCOL || hfinfo->type == FT_NONE) {
3438 * These types are for interior nodes of the
3439 * tree, and don't have data associated with
3440 * them; if the length is negative (XXX - see
3441 * above) or goes past the end of the tvbuff,
3442 * cut it short at the end of the tvbuff.
3443 * That way, if this field is selected in
3444 * Wireshark, we don't highlight stuff past
3445 * the end of the data.
3447 /* XXX - what to do, if we don't have a tvb? */
3449 length_remaining = tvb_length_remaining(tvb, start);
3450 if (*item_length < 0 ||
3451 (*item_length > 0 &&
3452 (length_remaining < *item_length)))
3453 *item_length = length_remaining;
3456 if (*item_length < 0) {
3457 THROW(ReportedBoundsError);
3463 new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
3464 const gint start, const gint item_length)
3470 fi->hfinfo = hfinfo;
3472 fi->start += (tvb)?tvb_raw_offset(tvb):0;
3473 fi->length = item_length;
3476 if (!PTREE_DATA(tree)->visible)
3477 FI_SET_FLAG(fi, FI_HIDDEN);
3478 fvalue_init(&fi->value, fi->hfinfo->type);
3481 /* add the data source tvbuff */
3482 fi->ds_tvb = tvb ? tvb_get_ds_tvb(tvb) : NULL;
3484 fi->appendix_start = 0;
3485 fi->appendix_length = 0;
3491 alloc_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb, const gint start,
3496 get_hfi_length(hfinfo, tvb, start, length, &item_length);
3497 return new_field_info(tree, hfinfo, tvb, start, item_length);
3501 label_mark_truncated_start(char *label_str)
3503 static const char trunc_str[] = "[truncated] ";
3504 const size_t trunc_len = sizeof(trunc_str)-1;
3506 memmove(label_str + trunc_len, label_str, ITEM_LABEL_LENGTH - trunc_len);
3507 memcpy(label_str, trunc_str, trunc_len);
3508 label_str[ITEM_LABEL_LENGTH-1] = '\0';
3511 /* If the protocol tree is to be visible, set the representation of a
3512 proto_tree entry with the name of the field for the item and with
3513 the value formatted with the supplied printf-style format and
3516 proto_tree_set_representation_value(proto_item *pi, const char *format, va_list ap)
3520 /* If the tree (GUI) or item isn't visible it's pointless for us to generate the protocol
3521 * items string representation */
3522 if (PTREE_DATA(pi)->visible && !PROTO_ITEM_IS_HIDDEN(pi)) {
3524 field_info *fi = PITEM_FINFO(pi);
3525 header_field_info *hf;
3527 DISSECTOR_ASSERT(fi);
3531 ITEM_LABEL_NEW(fi->rep);
3532 if (hf->bitmask && (hf->type == FT_BOOLEAN || IS_FT_UINT(hf->type))) {
3536 val = fvalue_get_uinteger(&fi->value);
3537 val <<= hfinfo_bitshift(hf);
3539 p = decode_bitfield_value(fi->rep->representation, val, hf->bitmask, hfinfo_bitwidth(hf));
3540 ret = (int) (p - fi->rep->representation);
3543 /* put in the hf name */
3544 ret += g_snprintf(fi->rep->representation + ret, ITEM_LABEL_LENGTH - ret, "%s: ", hf->name);
3546 /* If possible, Put in the value of the string */
3547 if (ret < ITEM_LABEL_LENGTH) {
3548 ret += g_vsnprintf(fi->rep->representation + ret,
3549 ITEM_LABEL_LENGTH - ret, format, ap);
3551 if (ret >= ITEM_LABEL_LENGTH) {
3552 /* Uh oh, we don't have enough room. Tell the user
3553 * that the field is truncated.
3555 /* XXX, label_mark_truncated() ? */
3556 label_mark_truncated_start(fi->rep->representation);
3561 /* If the protocol tree is to be visible, set the representation of a
3562 proto_tree entry with the representation formatted with the supplied
3563 printf-style format and argument list. */
3565 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap)
3567 int ret; /*tmp return value */
3568 field_info *fi = PITEM_FINFO(pi);
3570 DISSECTOR_ASSERT(fi);
3572 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
3573 ITEM_LABEL_NEW(fi->rep);
3574 ret = g_vsnprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
3576 if (ret >= ITEM_LABEL_LENGTH) {
3577 /* Uh oh, we don't have enough room. Tell the user
3578 * that the field is truncated.
3580 label_mark_truncated_start(fi->rep->representation);
3586 protoo_strlcpy(gchar *dest, const gchar *src, gsize dest_size)
3588 gsize res = g_strlcpy(dest, src, dest_size);
3590 if (res > dest_size)
3595 static header_field_info *
3596 hfinfo_same_name_get_prev(const header_field_info *hfinfo)
3598 if (hfinfo->same_name_prev_id == -1)
3600 return proto_registrar_get_nth(hfinfo->same_name_prev_id);
3603 /* -------------------------- */
3605 proto_custom_set(proto_tree* tree, const int field_id, gint occurrence,
3606 gchar *result, gchar *expr, const int size)
3611 struct e_in6_addr *ipv6;
3613 guint32 n_addr; /* network-order IPv4 address */
3615 const true_false_string *tfstring;
3617 int len, prev_len = 0, last, i, offset_r = 0, offset_e = 0;
3619 field_info *finfo = NULL;
3620 header_field_info* hfinfo;
3621 const gchar *abbrev = NULL;
3623 const char *hf_str_val;
3624 char number_buf[32];
3625 const char *number_out;
3627 g_assert(field_id >= 0);
3629 hfinfo = proto_registrar_get_nth((guint)field_id);
3631 /* do we need to rewind ? */
3635 if (occurrence < 0) {
3636 /* Search other direction */
3637 while (hfinfo->same_name_prev_id != -1) {
3638 hfinfo = proto_registrar_get_nth(hfinfo->same_name_prev_id);
3643 finfos = proto_get_finfo_ptr_array(tree, hfinfo->id);
3645 if (!finfos || !(len = g_ptr_array_len(finfos))) {
3646 if (occurrence < 0) {
3647 hfinfo = hfinfo->same_name_next;
3649 hfinfo = hfinfo_same_name_get_prev(hfinfo);
3654 /* Are there enough occurrences of the field? */
3655 if (((occurrence - prev_len) > len) || ((occurrence + prev_len) < -len)) {
3656 if (occurrence < 0) {
3657 hfinfo = hfinfo->same_name_next;
3659 hfinfo = hfinfo_same_name_get_prev(hfinfo);
3665 /* Calculate single index or set outer bounderies */
3666 if (occurrence < 0) {
3667 i = occurrence + len + prev_len;
3669 } else if (occurrence > 0) {
3670 i = occurrence - 1 - prev_len;
3677 prev_len += len; /* Count handled occurrences */
3680 finfo = (field_info *)g_ptr_array_index(finfos, i);
3682 if (offset_r && (offset_r < (size - 2)))
3683 result[offset_r++] = ',';
3685 if (offset_e && (offset_e < (size - 2)))
3686 expr[offset_e++] = ',';
3688 switch (hfinfo->type) {
3690 case FT_NONE: /* Nothing to add */
3691 if (offset_r == 0) {
3693 } else if (result[offset_r-1] == ',') {
3694 result[offset_r-1] = '\0';
3699 /* prevent multiple "yes" entries by setting result directly */
3700 g_strlcpy(result, "Yes", size);
3705 bytes = (guint8 *)fvalue_get(&finfo->value);
3706 offset_r += protoo_strlcpy(result+offset_r,
3708 fvalue_length(&finfo->value)),
3712 case FT_ABSOLUTE_TIME:
3713 offset_r += protoo_strlcpy(result+offset_r,
3714 abs_time_to_str((const nstime_t *)fvalue_get(&finfo->value),
3715 (absolute_time_display_e)hfinfo->display, TRUE),
3719 case FT_RELATIVE_TIME:
3720 offset_r += protoo_strlcpy(result+offset_r,
3721 rel_time_to_secs_str((const nstime_t *)fvalue_get(&finfo->value)),
3726 number = fvalue_get_uinteger(&finfo->value);
3727 tfstring = (const true_false_string *)&tfs_true_false;
3728 if (hfinfo->strings) {
3729 tfstring = (const struct true_false_string*) hfinfo->strings;
3731 offset_r += protoo_strlcpy(result+offset_r,
3733 tfstring->true_string :
3734 tfstring->false_string, size-offset_r);
3736 offset_e += protoo_strlcpy(expr+offset_e,
3737 number ? "1" : "0", size-offset_e);
3740 /* XXX - make these just FT_NUMBER? */
3751 number = IS_FT_INT(hfinfo->type) ?
3752 (guint32) fvalue_get_sinteger(&finfo->value) :
3753 fvalue_get_uinteger(&finfo->value);
3755 if ((hfinfo->display & BASE_DISPLAY_E_MASK) == BASE_CUSTOM) {
3756 gchar tmp[ITEM_LABEL_LENGTH];
3757 custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hfinfo->strings;
3759 DISSECTOR_ASSERT(fmtfunc);
3760 fmtfunc(tmp, number);
3762 offset_r += protoo_strlcpy(result+offset_r, tmp, size-offset_r);
3764 } else if (hfinfo->strings) {
3765 number_out = hf_str_val = hf_try_val_to_str(number, hfinfo);
3768 number_out = hfinfo_number_value_format_display(hfinfo, BASE_DEC, number_buf, number);
3770 offset_r += protoo_strlcpy(result+offset_r, number_out, size-offset_r);
3773 number_out = hfinfo_number_value_format(hfinfo, number_buf, number);
3775 offset_r += protoo_strlcpy(result+offset_r, number_out, size-offset_r);
3778 if (hf_str_val && (hfinfo->display & BASE_DISPLAY_E_MASK) == BASE_NONE) {
3779 g_snprintf(expr+offset_e, size-offset_e, "\"%s\"", hf_str_val);
3781 number_out = hfinfo_numeric_value_format(hfinfo, number_buf, number);
3783 g_strlcpy(expr+offset_e, number_out, size-offset_e);
3786 offset_e = (int)strlen(expr);
3790 /* XXX: Should handle BASE_CUSTOM ? */
3791 g_snprintf(result+offset_r, size-offset_r,
3792 "%" G_GINT64_MODIFIER "d",
3793 fvalue_get_integer64(&finfo->value));
3794 offset_r = (int)strlen(result);
3797 g_snprintf(result+offset_r, size-offset_r,
3798 /* XXX: Should handle BASE_CUSTOM ? */
3799 "%" G_GINT64_MODIFIER "u",
3800 fvalue_get_integer64(&finfo->value));
3801 offset_r = (int)strlen(result);
3804 offset_r += protoo_strlcpy(result+offset_r,
3805 eui64_to_str(fvalue_get_integer64(&finfo->value)),
3810 ipv4 = (ipv4_addr *)fvalue_get(&finfo->value);
3811 n_addr = ipv4_get_net_order_addr(ipv4);
3812 offset_r += protoo_strlcpy(result+offset_r,
3813 ip_to_str((guint8 *)&n_addr),
3818 ipv6 = (struct e_in6_addr *)fvalue_get(&finfo->value);
3819 SET_ADDRESS (&addr, AT_IPv6, sizeof(struct e_in6_addr), ipv6);
3820 address_to_str_buf(&addr, result+offset_r, size-offset_r);
3821 offset_r = (int)strlen(result);
3825 offset_r += protoo_strlcpy(result+offset_r,
3826 bytes_to_str_punct((const guint8 *)fvalue_get(&finfo->value),
3832 offset_r += protoo_strlcpy(result+offset_r,
3833 guid_to_str((e_guid_t *)fvalue_get(&finfo->value)),
3838 bytes = (guint8 *)fvalue_get(&finfo->value);
3839 offset_r += protoo_strlcpy(result+offset_r,
3840 oid_resolved_from_encoded(bytes,
3841 fvalue_length(&finfo->value)),
3843 offset_e += protoo_strlcpy(expr+offset_e,
3844 oid_encoded2string(bytes, fvalue_length(&finfo->value)),
3849 g_snprintf(result+offset_r, size-offset_r,
3850 "%." STRINGIFY(FLT_DIG) "g", fvalue_get_floating(&finfo->value));
3851 offset_r = (int)strlen(result);
3855 g_snprintf(result+offset_r, size-offset_r,
3856 "%." STRINGIFY(DBL_DIG) "g", fvalue_get_floating(&finfo->value));
3857 offset_r = (int)strlen(result);
3862 case FT_UINT_STRING:
3863 bytes = (guint8 *)fvalue_get(&finfo->value);
3864 offset_r += protoo_strlcpy(result+offset_r,
3865 format_text(bytes, strlen(bytes)),
3869 case FT_IPXNET: /*XXX really No column custom ?*/
3872 g_error("hfinfo->type %d (%s) not handled\n",
3874 ftype_name(hfinfo->type));
3875 DISSECTOR_ASSERT_NOT_REACHED();
3881 switch (hfinfo->type) {
3894 /* for these types, "expr" is filled in the loop above */
3898 /* for all others, just copy "result" to "expr" */
3899 g_strlcpy(expr, result, size);
3904 /* Store abbrev for return value */
3905 abbrev = hfinfo->abbrev;
3908 if (occurrence == 0) {
3909 /* Fetch next hfinfo with same name (abbrev) */
3910 hfinfo = hfinfo_same_name_get_prev(hfinfo);
3916 return abbrev ? abbrev : "";
3920 /* Set text of proto_item after having already been created. */
3922 proto_item_set_text(proto_item *pi, const char *format, ...)
3924 field_info *fi = NULL;
3931 fi = PITEM_FINFO(pi);
3936 ITEM_LABEL_FREE(fi->rep);
3940 va_start(ap, format);
3941 proto_tree_set_representation(pi, format, ap);
3945 /* Append to text of proto_item after having already been created. */
3947 proto_item_append_text(proto_item *pi, const char *format, ...)
3949 field_info *fi = NULL;
3957 fi = PITEM_FINFO(pi);
3962 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
3964 * If we don't already have a representation,
3965 * generate the default representation.
3967 if (fi->rep == NULL) {
3968 ITEM_LABEL_NEW(fi->rep);
3969 proto_item_fill_label(fi, fi->rep->representation);
3972 curlen = strlen(fi->rep->representation);
3973 if (ITEM_LABEL_LENGTH > curlen) {
3974 va_start(ap, format);
3975 g_vsnprintf(fi->rep->representation + curlen,
3976 ITEM_LABEL_LENGTH - (gulong) curlen, format, ap);
3982 /* Prepend to text of proto_item after having already been created. */
3984 proto_item_prepend_text(proto_item *pi, const char *format, ...)
3986 field_info *fi = NULL;
3987 char representation[ITEM_LABEL_LENGTH];
3994 fi = PITEM_FINFO(pi);
3999 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
4001 * If we don't already have a representation,
4002 * generate the default representation.
4004 if (fi->rep == NULL) {
4005 ITEM_LABEL_NEW(fi->rep);
4006 proto_item_fill_label(fi, representation);
4008 g_strlcpy(representation, fi->rep->representation, ITEM_LABEL_LENGTH);
4010 va_start(ap, format);
4011 g_vsnprintf(fi->rep->representation,
4012 ITEM_LABEL_LENGTH, format, ap);
4014 g_strlcat(fi->rep->representation, representation, ITEM_LABEL_LENGTH);
4019 proto_item_set_len(proto_item *pi, const gint length)
4026 fi = PITEM_FINFO(pi);
4030 DISSECTOR_ASSERT(length >= 0);
4031 fi->length = length;
4034 * You cannot just make the "len" field of a GByteArray
4035 * larger, if there's no data to back that length;
4036 * you can only make it smaller.
4038 if (fi->value.ftype->ftype == FT_BYTES && length <= (gint)fi->value.value.bytes->len)
4039 fi->value.value.bytes->len = length;
4043 * Sets the length of the item based on its start and on the specified
4044 * offset, which is the offset past the end of the item; as the start
4045 * in the item is relative to the beginning of the data source tvbuff,
4046 * we need to pass in a tvbuff - the end offset is relative to the beginning
4050 proto_item_set_end(proto_item *pi, tvbuff_t *tvb, gint end)
4057 fi = PITEM_FINFO(pi);
4061 end += tvb_raw_offset(tvb);
4062 DISSECTOR_ASSERT(end >= fi->start);
4063 fi->length = end - fi->start;
4067 proto_item_get_len(const proto_item *pi)
4069 field_info *fi = PITEM_FINFO(pi);
4070 return fi ? fi->length : -1;
4074 proto_tree_create_root(packet_info *pinfo)
4078 /* Initialize the proto_node */
4079 PROTO_NODE_NEW(pnode);
4080 pnode->parent = NULL;
4081 PNODE_FINFO(pnode) = NULL;
4082 pnode->tree_data = g_new(tree_data_t, 1);
4084 /* Make sure we can access pinfo everywhere */
4085 pnode->tree_data->pinfo = pinfo;
4087 /* Don't initialize the tree_data_t. Wait until we know we need it */
4088 pnode->tree_data->interesting_hfids = NULL;
4090 /* Set the default to FALSE so it's easier to
4091 * find errors; if we expect to see the protocol tree
4092 * but for some reason the default 'visible' is not
4093 * changed, then we'll find out very quickly. */
4094 pnode->tree_data->visible = FALSE;
4096 /* Make sure that we fake protocols (if possible) */
4097 pnode->tree_data->fake_protocols = TRUE;
4099 /* Keep track of the number of children */
4100 pnode->tree_data->count = 0;
4102 pnode->tree_data->fi_tmp = NULL;
4104 return (proto_tree *)pnode;
4108 /* "prime" a proto_tree with a single hfid that a dfilter
4109 * is interested in. */
4111 proto_tree_prime_hfid(proto_tree *tree _U_, const gint hfid)
4113 header_field_info *hfinfo;
4115 PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
4116 /* this field is referenced by a filter so increase the refcount.
4117 also increase the refcount for the parent, i.e the protocol.
4119 hfinfo->ref_type = HF_REF_TYPE_DIRECT;
4120 /* only increase the refcount if there is a parent.
4121 if this is a protocol and not a field then parent will be -1
4122 and there is no parent to add any refcounting for.
4124 if (hfinfo->parent != -1) {
4125 header_field_info *parent_hfinfo;
4126 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
4128 /* Mark parent as indirectly referenced unless it is already directly
4129 * referenced, i.e. the user has specified the parent in a filter.
4131 if (parent_hfinfo->ref_type != HF_REF_TYPE_DIRECT)
4132 parent_hfinfo->ref_type = HF_REF_TYPE_INDIRECT;
4137 proto_item_add_subtree(proto_item *pi, const gint idx) {
4143 DISSECTOR_ASSERT(idx >= 0 && idx < num_tree_types);
4145 fi = PITEM_FINFO(pi);
4147 return (proto_tree *)pi;
4149 fi->tree_type = idx;
4151 return (proto_tree *)pi;
4155 proto_item_get_subtree(const proto_item *pi) {
4160 fi = PITEM_FINFO(pi);
4161 if ( (!fi) || (fi->tree_type == -1) )
4163 return (proto_tree *)pi;
4167 proto_item_get_parent(const proto_item *ti) {
4174 proto_item_get_parent_nth(proto_item *ti, int gen) {
4187 proto_tree_get_parent(const proto_tree *tree) {
4190 return (proto_item *)tree;
4194 proto_tree_get_root(proto_tree *tree) {
4197 while (tree->parent) {
4198 tree = tree->parent;
4204 proto_tree_move_item(proto_tree *tree, proto_item *fixed_item,
4205 proto_item *item_to_move)
4208 /* Revert part of: http://anonsvn.wireshark.org/viewvc?view=rev&revision=32443
4209 * See https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=5500
4211 /* This function doesn't generate any values. It only reorganizes the prococol tree
4212 * so we can bail out immediately if it isn't visible. */
4213 if (!tree || !PTREE_DATA(tree)->visible)
4216 DISSECTOR_ASSERT(item_to_move->parent == tree);
4217 DISSECTOR_ASSERT(fixed_item->parent == tree);
4219 /*** cut item_to_move out ***/
4221 /* is item_to_move the first? */
4222 if (tree->first_child == item_to_move) {
4223 /* simply change first child to next */
4224 tree->first_child = item_to_move->next;
4226 DISSECTOR_ASSERT(tree->last_child != item_to_move);
4228 proto_item *curr_item;
4229 /* find previous and change it's next */
4230 for(curr_item = tree->first_child; curr_item != NULL; curr_item = curr_item->next) {
4231 if (curr_item->next == item_to_move) {
4236 DISSECTOR_ASSERT(curr_item);
4238 curr_item->next = item_to_move->next;
4240 /* fix last_child if required */
4241 if (tree->last_child == item_to_move) {
4242 tree->last_child = curr_item;
4246 /*** insert to_move after fixed ***/
4247 item_to_move->next = fixed_item->next;
4248 fixed_item->next = item_to_move;
4249 if (tree->last_child == fixed_item) {
4250 tree->last_child = item_to_move;
4255 proto_tree_set_appendix(proto_tree *tree, tvbuff_t *tvb, gint start,
4263 fi = PTREE_FINFO(tree);
4267 start += tvb_raw_offset(tvb);
4268 DISSECTOR_ASSERT(start >= 0);
4269 DISSECTOR_ASSERT(length >= 0);
4271 fi->appendix_start = start;
4272 fi->appendix_length = length;
4276 proto_register_protocol(const char *name, const char *short_name,
4277 const char *filter_name)
4279 protocol_t *protocol;
4280 header_field_info *hfinfo;
4282 char *existing_name;
4286 gboolean found_invalid;
4289 * Make sure there's not already a protocol with any of those
4290 * names. Crash if there is, as that's an error in the code
4291 * or an inappropriate plugin.
4292 * This situation has to be fixed to not register more than one
4293 * protocol with the same name.
4295 * This is done by reducing the number of strcmp (and alike) calls
4296 * as much as possible, as this significally slows down startup time.
4298 * Drawback: As a hash value is used to reduce insert time,
4299 * this might lead to a hash collision.
4300 * However, although we have somewhat over 1000 protocols, we're using
4301 * a 32 bit int so this is very, very unlikely.
4304 key = (gint *)g_malloc (sizeof(gint));
4305 *key = wrs_str_hash(name);
4307 existing_name = (char *)g_hash_table_lookup(proto_names, key);
4308 if (existing_name != NULL) {
4309 /* g_error will terminate the program */
4310 g_error("Duplicate protocol name \"%s\"!"
4311 " This might be caused by an inappropriate plugin or a development error.", name);
4313 g_hash_table_insert(proto_names, key, (gpointer)name);
4315 existing_name = (char *)g_hash_table_lookup(proto_short_names, (gpointer)short_name);
4316 if (existing_name != NULL) {
4317 g_error("Duplicate protocol short_name \"%s\"!"
4318 " This might be caused by an inappropriate plugin or a development error.", short_name);
4320 g_hash_table_insert(proto_short_names, (gpointer)short_name, (gpointer)short_name);
4322 found_invalid = FALSE;
4323 for (i = 0; filter_name[i]; i++) {
4325 if (!(islower(c) || isdigit(c) || c == '-' || c == '_' || c == '.')) {
4326 found_invalid = TRUE;
4329 if (found_invalid) {
4330 g_error("Protocol filter name \"%s\" has one or more invalid characters."
4331 " Allowed are lower characters, digits, '-', '_' and '.'."
4332 " This might be caused by an inappropriate plugin or a development error.", filter_name);
4334 existing_name = (char *)g_hash_table_lookup(proto_filter_names, (gpointer)filter_name);
4335 if (existing_name != NULL) {
4336 g_error("Duplicate protocol filter_name \"%s\"!"
4337 " This might be caused by an inappropriate plugin or a development error.", filter_name);
4339 g_hash_table_insert(proto_filter_names, (gpointer)filter_name, (gpointer)filter_name);
4341 /* Add this protocol to the list of known protocols; the list
4342 is sorted by protocol short name. */
4343 protocol = g_new(protocol_t, 1);
4344 protocol->name = name;
4345 protocol->short_name = short_name;
4346 protocol->filter_name = filter_name;
4347 protocol->fields = NULL;
4348 protocol->is_enabled = TRUE; /* protocol is enabled by default */
4349 protocol->can_toggle = TRUE;
4350 protocol->is_private = FALSE;
4351 /* list will be sorted later by name, when all protocols completed registering */
4352 protocols = g_list_prepend(protocols, protocol);
4354 /* Here we allocate a new header_field_info struct */
4355 hfinfo = g_slice_new(header_field_info);
4356 hfinfo->name = name;
4357 hfinfo->abbrev = filter_name;
4358 hfinfo->type = FT_PROTOCOL;
4359 hfinfo->display = BASE_NONE;
4360 hfinfo->strings = protocol;
4361 hfinfo->bitmask = 0;
4362 hfinfo->ref_type = HF_REF_TYPE_NONE;
4363 hfinfo->blurb = NULL;
4364 hfinfo->parent = -1; /* this field differentiates protos and fields */
4366 proto_id = proto_register_field_init(hfinfo, hfinfo->parent);
4367 protocol->proto_id = proto_id;
4372 proto_mark_private(const int proto_id)
4374 protocol_t *protocol = find_protocol_by_id(proto_id);
4376 protocol->is_private = TRUE;
4380 proto_is_private(const int proto_id)
4382 protocol_t *protocol = find_protocol_by_id(proto_id);
4384 return protocol->is_private;
4390 * Routines to use to iterate over the protocols.
4391 * The argument passed to the iterator routines is an opaque cookie to
4392 * their callers; it's the GList pointer for the current element in
4394 * The ID of the protocol is returned, or -1 if there is no protocol.
4397 proto_get_first_protocol(void **cookie)
4399 protocol_t *protocol;
4401 if (protocols == NULL)
4403 *cookie = protocols;
4404 protocol = (protocol_t *)protocols->data;
4405 return protocol->proto_id;
4409 proto_get_data_protocol(void *cookie)
4411 GList *list_item = (GList *)cookie;
4413 protocol_t *protocol = (protocol_t *)list_item->data;
4414 return protocol->proto_id;
4418 proto_get_next_protocol(void **cookie)
4420 GList *list_item = (GList *)*cookie;
4421 protocol_t *protocol;
4423 list_item = g_list_next(list_item);
4424 if (list_item == NULL)
4426 *cookie = list_item;
4427 protocol = (protocol_t *)list_item->data;
4428 return protocol->proto_id;
4432 proto_get_first_protocol_field(const int proto_id, void **cookie)
4434 protocol_t *protocol = find_protocol_by_id(proto_id);
4436 if ((protocol == NULL) || (protocol->fields == NULL))
4439 *cookie = protocol->fields;
4440 return (header_field_info *)protocol->fields->data;
4444 proto_get_next_protocol_field(void **cookie)
4446 GSList *list_item = (GSList *)*cookie;
4448 list_item = g_slist_next(list_item);
4449 if (list_item == NULL)
4452 *cookie = list_item;
4453 return (header_field_info *)list_item->data;
4457 find_protocol_by_id(const int proto_id)
4459 header_field_info *hfinfo;
4464 PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
4465 DISSECTOR_ASSERT(hfinfo->type == FT_PROTOCOL);
4466 return (protocol_t *)hfinfo->strings;
4469 static gint compare_filter_name(gconstpointer proto_arg,
4470 gconstpointer filter_name)
4472 const protocol_t *protocol = (const protocol_t *)proto_arg;
4473 const gchar *f_name = (const gchar *)filter_name;
4475 return (strcmp(protocol->filter_name, f_name));
4479 proto_get_id(const protocol_t *protocol)
4481 return protocol->proto_id;
4484 int proto_get_id_by_filter_name(const gchar* filter_name)
4487 protocol_t *protocol;
4490 fprintf(stderr, "No filter name present");
4491 DISSECTOR_ASSERT(filter_name);
4494 list_entry = g_list_find_custom(protocols, filter_name,
4495 compare_filter_name);
4497 if (list_entry == NULL)
4499 protocol = (protocol_t *)list_entry->data;
4500 return protocol->proto_id;
4504 proto_get_protocol_name(const int proto_id)
4506 protocol_t *protocol;
4508 protocol = find_protocol_by_id(proto_id);
4510 if (protocol == NULL)
4512 return protocol->name;
4516 proto_get_protocol_short_name(const protocol_t *protocol)
4518 if (protocol == NULL)
4520 return protocol->short_name;
4524 proto_get_protocol_long_name(const protocol_t *protocol)
4526 if (protocol == NULL)
4528 return protocol->name;
4532 proto_get_protocol_filter_name(const int proto_id)
4534 protocol_t *protocol;
4536 protocol = find_protocol_by_id(proto_id);
4537 if (protocol == NULL)
4539 return protocol->filter_name;
4543 proto_is_protocol_enabled(const protocol_t *protocol)
4545 return protocol->is_enabled;
4549 proto_can_toggle_protocol(const int proto_id)
4551 protocol_t *protocol;
4553 protocol = find_protocol_by_id(proto_id);
4554 return protocol->can_toggle;
4558 proto_set_decoding(const int proto_id, const gboolean enabled)
4560 protocol_t *protocol;
4562 protocol = find_protocol_by_id(proto_id);
4563 DISSECTOR_ASSERT(protocol->can_toggle);
4564 protocol->is_enabled = enabled;
4568 proto_enable_all(void)
4570 protocol_t *protocol;
4571 GList *list_item = protocols;
4573 if (protocols == NULL)
4577 protocol = (protocol_t *)list_item->data;
4578 if (protocol->can_toggle)
4579 protocol->is_enabled = TRUE;
4580 list_item = g_list_next(list_item);
4585 proto_set_cant_toggle(const int proto_id)
4587 protocol_t *protocol;
4589 protocol = find_protocol_by_id(proto_id);
4590 protocol->can_toggle = FALSE;
4593 /* for use with static arrays only, since we don't allocate our own copies
4594 of the header_field_info struct contained within the hf_register_info struct */
4596 proto_register_field_array(const int parent, hf_register_info *hf, const int num_records)
4599 hf_register_info *ptr = hf;
4602 proto = find_protocol_by_id(parent);
4603 for (i = 0; i < num_records; i++, ptr++) {
4605 * Make sure we haven't registered this yet.
4606 * Most fields have variables associated with them
4607 * that are initialized to -1; some have array elements,
4608 * or possibly uninitialized variables, so we also allow
4609 * 0 (which is unlikely to be the field ID we get back
4610 * from "proto_register_field_init()").
4612 if (*ptr->p_id != -1 && *ptr->p_id != 0) {
4614 "Duplicate field detected in call to proto_register_field_array: %s is already registered\n",
4615 ptr->hfinfo.abbrev);
4619 if (proto != NULL) {
4620 if (proto->fields == NULL) {
4621 proto->fields = g_slist_append(NULL, &ptr->hfinfo);
4622 proto->last_field = proto->fields;
4625 g_slist_append(proto->last_field, &ptr->hfinfo)->next;
4628 field_id = proto_register_field_init(&ptr->hfinfo, parent);
4629 *ptr->p_id = field_id;
4634 proto_register_fields(const int parent, header_field_info **hfi, const int num_records)
4639 proto = find_protocol_by_id(parent);
4640 for (i = 0; i < num_records; i++) {
4642 * Make sure we haven't registered this yet.
4644 if (hfi[i]->id != -1) {
4646 "Duplicate field detected in call to proto_register_field_array: %s is already registered\n",
4651 if (proto != NULL) {
4652 if (proto->fields == NULL) {
4653 proto->fields = g_slist_append(NULL, hfi[i]);
4654 proto->last_field = proto->fields;
4657 g_slist_append(proto->last_field, hfi[i])->next;
4660 proto_register_field_init(hfi[i], parent);
4664 /* unregister already registered fields */
4666 proto_unregister_field (const int parent, gint hf_id)
4668 hf_register_info *hf;
4672 if (hf_id == -1 || hf_id == 0)
4675 proto = find_protocol_by_id (parent);
4676 if (!proto || !proto->fields) {
4680 for (field = proto->fields; field; field = field->next) {
4681 hf = (hf_register_info *)field->data;
4682 if (*hf->p_id == hf_id) {
4683 /* Found the hf_id in this protocol */
4684 g_tree_steal (gpa_name_tree, hf->hfinfo.abbrev);
4685 /* XXX, memleak? g_slist_delete_link() */
4686 proto->fields = g_slist_remove_link (proto->fields, field);
4687 proto->last_field = g_slist_last (proto->fields);
4693 /* chars allowed in field abbrev */
4695 const guchar fld_abbrev_chars[256] = {
4696 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00-0x0F */
4697 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10-0x1F */
4698 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, /* 0x20-0x2F '-', '.' */
4699 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 0x30-0x3F '0'-'9' */
4700 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x40-0x4F 'A'-'O' */
4701 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 0x50-0x5F 'P'-'Z', '_' */
4702 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x60-0x6F 'a'-'o' */
4703 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 0x70-0x7F 'p'-'z' */
4704 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80-0x8F */
4705 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90-0x9F */
4706 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xA0-0xAF */
4707 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xB0-0xBF */
4708 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xC0-0xCF */
4709 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xD0-0xDF */
4710 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xE0-0xEF */
4711 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xF0-0xFF */
4714 static const value_string hf_types[] = {
4715 { FT_NONE, "FT_NONE" },
4716 { FT_PROTOCOL, "FT_PROTOCOL" },
4717 { FT_BOOLEAN, "FT_BOOLEAN" },
4718 { FT_UINT8, "FT_UINT8" },
4719 { FT_UINT16, "FT_UINT16" },
4720 { FT_UINT24, "FT_UINT24" },
4721 { FT_UINT32, "FT_UINT32" },
4722 { FT_UINT64, "FT_UINT64" },
4723 { FT_INT8, "FT_INT8" },
4724 { FT_INT16, "FT_INT16" },
4725 { FT_INT24, "FT_INT24" },
4726 { FT_INT32, "FT_INT32" },
4727 { FT_INT64, "FT_INT64" },
4728 { FT_EUI64, "FT_EUI64" },
4729 { FT_FLOAT, "FT_FLOAT" },
4730 { FT_DOUBLE, "FT_DOUBLE" },
4731 { FT_ABSOLUTE_TIME, "FT_ABSOLUTE_TIME" },
4732 { FT_RELATIVE_TIME, "FT_RELATIVE_TIME" },
4733 { FT_STRING, "FT_STRING" },
4734 { FT_STRINGZ, "FT_STRINGZ" },
4735 { FT_UINT_STRING, "FT_UINT_STRING" },
4736 { FT_ETHER, "FT_ETHER" },
4737 { FT_BYTES, "FT_BYTES" },
4738 { FT_UINT_BYTES, "FT_UINT_BYTES" },
4739 { FT_IPv4, "FT_IPv4" },
4740 { FT_IPv6, "FT_IPv6" },
4741 { FT_IPXNET, "FT_IPXNET" },
4742 { FT_FRAMENUM, "FT_FRAMENUM" },
4743 { FT_PCRE, "FT_PCR" },
4744 { FT_GUID, "FT_GUID" },
4745 { FT_OID, "FT_OID" },
4748 static const value_string hf_display[] = {
4749 { BASE_NONE, "BASE_NONE" },
4750 { BASE_DEC, "BASE_DEC" },
4751 { BASE_HEX, "BASE_HEX" },
4752 { BASE_OCT, "BASE_OCT" },
4753 { BASE_DEC_HEX, "BASE_DEC_HEX" },
4754 { BASE_HEX_DEC, "BASE_HEX_DEC" },
4755 { BASE_CUSTOM, "BASE_CUSTOM" },
4756 { BASE_NONE|BASE_RANGE_STRING, "BASE_NONE|BASE_RANGE_STRING" },
4757 { BASE_DEC|BASE_RANGE_STRING, "BASE_DEC|BASE_RANGE_STRING" },
4758 { BASE_HEX|BASE_RANGE_STRING, "BASE_HEX|BASE_RANGE_STRING" },
4759 { BASE_OCT|BASE_RANGE_STRING, "BASE_OCT|BASE_RANGE_STRING" },
4760 { BASE_DEC_HEX|BASE_RANGE_STRING, "BASE_DEC_HEX|BASE_RANGE_STRING" },
4761 { BASE_HEX_DEC|BASE_RANGE_STRING, "BASE_HEX_DEC|BASE_RANGE_STRING" },
4762 { BASE_CUSTOM|BASE_RANGE_STRING, "BASE_CUSTOM|BASE_RANGE_STRING" },
4763 { BASE_NONE|BASE_VAL64_STRING, "BASE_NONE|BASE_VAL64_STRING" },
4764 { BASE_DEC|BASE_VAL64_STRING, "BASE_DEC|BASE_VAL64_STRING" },
4765 { BASE_HEX|BASE_VAL64_STRING, "BASE_HEX|BASE_VAL64_STRING" },
4766 { BASE_OCT|BASE_VAL64_STRING, "BASE_OCT|BASE_VAL64_STRING" },
4767 { BASE_DEC_HEX|BASE_VAL64_STRING, "BASE_DEC_HEX|BASE_VAL64_STRING" },
4768 { BASE_HEX_DEC|BASE_VAL64_STRING, "BASE_HEX_DEC|BASE_VAL64_STRING" },
4769 { BASE_CUSTOM|BASE_VAL64_STRING, "BASE_CUSTOM|BASE_VAL64_STRING" },
4770 { ABSOLUTE_TIME_LOCAL, "ABSOLUTE_TIME_LOCAL" },
4771 { ABSOLUTE_TIME_UTC, "ABSOLUTE_TIME_UTC" },
4772 { ABSOLUTE_TIME_DOY_UTC, "ABSOLUTE_TIME_DOY_UTC" },
4775 /* temporary function containing assert part for easier profiling */
4777 tmp_fld_check_assert(header_field_info *hfinfo)
4780 /* The field must have a name (with length > 0) */
4781 if (!hfinfo->name || !hfinfo->name[0]) {
4783 /* Try to identify the field */
4784 g_error("Field (abbrev='%s') does not have a name\n",
4788 g_error("Field does not have a name (nor an abbreviation)\n");
4791 /* fields with an empty string for an abbreviation aren't filterable */
4792 if (!hfinfo->abbrev || !hfinfo->abbrev[0])
4793 g_error("Field '%s' does not have an abbreviation\n", hfinfo->name);
4795 /* These types of fields are allowed to have value_strings,
4796 * true_false_strings or a protocol_t struct
4798 if (hfinfo->strings != NULL && !(
4799 (hfinfo->type == FT_UINT8) ||
4800 (hfinfo->type == FT_UINT16) ||
4801 (hfinfo->type == FT_UINT24) ||
4802 (hfinfo->type == FT_UINT32) ||
4803 (hfinfo->type == FT_UINT64) ||
4804 (hfinfo->type == FT_INT8) ||
4805 (hfinfo->type == FT_INT16) ||
4806 (hfinfo->type == FT_INT24) ||
4807 (hfinfo->type == FT_INT32) ||
4808 (hfinfo->type == FT_INT64) ||
4809 (hfinfo->type == FT_BOOLEAN) ||
4810 (hfinfo->type == FT_PROTOCOL) ))
4811 g_error("Field '%s' (%s) has a 'strings' value but is of type %s"
4812 " (which is not allowed to have strings)\n",
4813 hfinfo->name, hfinfo->abbrev,
4814 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"));
4816 /* TODO: This check may slow down startup, and output quite a few warnings.
4817 It would be good to be able to enable this (and possibly other checks?)
4818 in non-release builds. */
4820 /* Check for duplicate value_string values.
4821 There are lots that have the same value *and* string, so for now only
4822 report those that have same value but different string. */
4823 if ((hfinfo->strings != NULL) &&
4824 !(hfinfo->display & BASE_RANGE_STRING) &&
4825 !((hfinfo->display & BASE_DISPLAY_E_MASK) == BASE_CUSTOM) &&
4827 (hfinfo->type == FT_UINT8) ||
4828 (hfinfo->type == FT_UINT16) ||
4829 (hfinfo->type == FT_UINT24) ||
4830 (hfinfo->type == FT_UINT32) ||
4831 (hfinfo->type == FT_INT8) ||
4832 (hfinfo->type == FT_INT16) ||
4833 (hfinfo->type == FT_INT24) ||
4834 (hfinfo->type == FT_INT32) ||
4835 (hfinfo->type == FT_FRAMENUM) )) {
4838 const value_string *start_values;
4839 const value_string *current;
4841 if (hfinfo->display & BASE_EXT_STRING)
4842 start_values = VALUE_STRING_EXT_VS_P(((const value_string_ext*)hfinfo->strings));
4844 start_values = (const value_string*)hfinfo->strings;
4845 current = start_values;
4847 for (n=0; current; n++, current++) {
4848 /* Drop out if we reached the end. */
4849 if ((current->value == 0) && (current->strptr == NULL)) {
4853 /* Check value against all previous */
4854 for (m=0; m < n; m++) {
4855 /* There are lots of duplicates with the same string,
4856 so only report if different... */
4857 if ((start_values[m].value == current->value) &&
4858 (strcmp(start_values[m].strptr, current->strptr) != 0)) {
4859 g_warning("Field '%s' (%s) has a conflicting entry in its"
4860 " value_string: %u is at indices %u (%s) and %u (%s))\n",
4861 hfinfo->name, hfinfo->abbrev,
4862 current->value, m, start_values[m].strptr, n, current->strptr);
4870 switch (hfinfo->type) {
4877 /* Hexadecimal and octal are, in printf() and everywhere
4878 * else, unsigned so don't allow dissectors to register a
4879 * signed field to be displayed unsigned. (Else how would
4880 * we display negative values?)
4882 switch (hfinfo->display & BASE_DISPLAY_E_MASK) {
4887 g_error("Field '%s' (%s) is signed (%s) but is being displayed unsigned (%s)\n",
4888 hfinfo->name, hfinfo->abbrev,
4889 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"),
4890 val_to_str(hfinfo->display, hf_display, "(Bit count: %d)"));
4898 /* Require integral types (other than frame number,
4899 * which is always displayed in decimal) to have a
4901 * If there is a strings value then this base is not
4902 * normally used except when constructing a display
4903 * filter for a value not found in the strings lookup.
4905 switch (hfinfo->display & BASE_DISPLAY_E_MASK) {
4911 case BASE_CUSTOM: /* hfinfo_numeric_value_format() treats this as decimal */
4914 g_error("Field '%s' (%s) is an integral value (%s)"
4915 " but is being displayed as %s\n",
4916 hfinfo->name, hfinfo->abbrev,
4917 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"),
4918 val_to_str(hfinfo->display, hf_display, "(Unknown: 0x%x)"));
4924 if (hfinfo->display != BASE_NONE)
4925 g_error("Field '%s' (%s) is an %s but is being displayed as %s instead of BASE_NONE\n",
4926 hfinfo->name, hfinfo->abbrev,
4927 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"),
4928 val_to_str(hfinfo->display, hf_display, "(Bit count: %d)"));
4929 if (hfinfo->bitmask != 0)
4930 g_error("Field '%s' (%s) is an %s but has a bitmask\n",
4931 hfinfo->name, hfinfo->abbrev,
4932 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"));
4938 case FT_ABSOLUTE_TIME:
4939 if (!(hfinfo->display == ABSOLUTE_TIME_LOCAL ||
4940 hfinfo->display == ABSOLUTE_TIME_UTC ||
4941 hfinfo->display == ABSOLUTE_TIME_DOY_UTC))
4942 g_error("Field '%s' (%s) is a %s but is being displayed as %s instead of as a time\n",
4943 hfinfo->name, hfinfo->abbrev,
4944 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"),
4945 val_to_str(hfinfo->display, hf_display, "(Bit count: %d)"));
4946 if (hfinfo->bitmask != 0)
4947 g_error("Field '%s' (%s) is an %s but has a bitmask\n",
4948 hfinfo->name, hfinfo->abbrev,
4949 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"));
4953 if (hfinfo->display != BASE_NONE)
4954 g_error("Field '%s' (%s) is an %s but is being displayed as %s instead of BASE_NONE\n",
4955 hfinfo->name, hfinfo->abbrev,
4956 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"),
4957 val_to_str(hfinfo->display, hf_display, "(Bit count: %d)"));
4958 if (hfinfo->bitmask != 0)
4959 g_error("Field '%s' (%s) is an %s but has a bitmask\n",
4960 hfinfo->name, hfinfo->abbrev,
4961 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"));
4962 if (hfinfo->strings != NULL)
4963 g_error("Field '%s' (%s) is an %s but has a strings value\n",
4964 hfinfo->name, hfinfo->abbrev,
4965 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"));
4970 #define PROTO_PRE_ALLOC_HF_FIELDS_MEM (120000+PRE_ALLOC_EXPERT_FIELDS_MEM)
4972 proto_register_field_init(header_field_info *hfinfo, const int parent)
4975 tmp_fld_check_assert(hfinfo);
4977 hfinfo->parent = parent;
4978 hfinfo->same_name_next = NULL;
4979 hfinfo->same_name_prev_id = -1;
4981 /* if we always add and never delete, then id == len - 1 is correct */
4982 if (gpa_hfinfo.len >= gpa_hfinfo.allocated_len) {
4983 if (!gpa_hfinfo.hfi) {
4984 gpa_hfinfo.allocated_len = PROTO_PRE_ALLOC_HF_FIELDS_MEM;
4985 gpa_hfinfo.hfi = (header_field_info **)g_malloc(sizeof(header_field_info *)*PROTO_PRE_ALLOC_HF_FIELDS_MEM);
4987 gpa_hfinfo.allocated_len += 1000;
4988 gpa_hfinfo.hfi = (header_field_info **)g_realloc(gpa_hfinfo.hfi,
4989 sizeof(header_field_info *)*gpa_hfinfo.allocated_len);
4990 /*g_warning("gpa_hfinfo.allocated_len %u", gpa_hfinfo.allocated_len);*/
4993 gpa_hfinfo.hfi[gpa_hfinfo.len] = hfinfo;
4995 hfinfo->id = gpa_hfinfo.len - 1;
4997 /* if we have real names, enter this field in the name tree */
4998 if ((hfinfo->name[0] != 0) && (hfinfo->abbrev[0] != 0 )) {
5000 header_field_info *same_name_next_hfinfo;
5003 /* Check that the filter name (abbreviation) is legal;
5004 * it must contain only alphanumerics, '-', "_", and ".". */
5005 c = wrs_check_charset(fld_abbrev_chars, hfinfo->abbrev);
5007 fprintf(stderr, "Invalid character '%c' in filter name '%s'\n", c, hfinfo->abbrev);
5008 DISSECTOR_ASSERT(!c);
5011 /* We allow multiple hfinfo's to be registered under the same
5012 * abbreviation. This was done for X.25, as, depending
5013 * on whether it's modulo-8 or modulo-128 operation,
5014 * some bitfield fields may be in different bits of
5015 * a byte, and we want to be able to refer to that field
5016 * with one name regardless of whether the packets
5017 * are modulo-8 or modulo-128 packets. */
5019 same_name_hfinfo = NULL;
5021 g_tree_insert(gpa_name_tree, (gpointer) (hfinfo->abbrev), hfinfo);
5022 /* GLIB 2.x - if it is already present
5023 * the previous hfinfo with the same name is saved
5024 * to same_name_hfinfo by value destroy callback */
5025 if (same_name_hfinfo) {
5026 /* There's already a field with this name.
5027 * Put it after that field in the list of
5028 * fields with this name, then allow the code
5029 * after this if{} block to replace the old
5030 * hfinfo with the new hfinfo in the GTree. Thus,
5031 * we end up with a linked-list of same-named hfinfo's,
5032 * with the root of the list being the hfinfo in the GTree */
5033 same_name_next_hfinfo =
5034 same_name_hfinfo->same_name_next;
5036 hfinfo->same_name_next = same_name_next_hfinfo;
5037 if (same_name_next_hfinfo)
5038 same_name_next_hfinfo->same_name_prev_id = hfinfo->id;
5040 same_name_hfinfo->same_name_next = hfinfo;
5041 hfinfo->same_name_prev_id = same_name_hfinfo->id;
5049 proto_register_subtree_array(gint *const *indices, const int num_indices)
5052 gint *const *ptr = indices;
5055 * If we've already allocated the array of tree types, expand
5056 * it; this lets plugins such as mate add tree types after
5057 * the initial startup. (If we haven't already allocated it,
5058 * we don't allocate it; on the first pass, we just assign
5059 * ett values and keep track of how many we've assigned, and
5060 * when we're finished registering all dissectors we allocate
5061 * the array, so that we do only one allocation rather than
5062 * wasting CPU time and memory by growing the array for each
5063 * dissector that registers ett values.)
5065 if (tree_is_expanded != NULL) {
5066 tree_is_expanded = (guint32 *)g_realloc(tree_is_expanded, (1+((num_tree_types + num_indices)/32)) * sizeof(guint32));
5068 /* set new items to 0 */
5069 /* XXX, slow!!! optimize when needed (align 'i' to 32, and set rest of guint32 to 0) */
5070 for (i = num_tree_types; i < num_tree_types + num_indices; i++)
5071 tree_is_expanded[i >> 5] &= ~(1 << (i & 31));
5075 * Assign "num_indices" subtree numbers starting at "num_tree_types",
5076 * returning the indices through the pointers in the array whose
5077 * first element is pointed to by "indices", and update
5078 * "num_tree_types" appropriately.
5080 for (i = 0; i < num_indices; i++, ptr++, num_tree_types++) {
5082 /* g_error will terminate the program */
5083 g_error("register_subtree_array: subtree item type (ett_...) not -1 !"
5084 " This is a development error:"
5085 " Either the subtree item type has already been assigned or"
5086 " was not initialized to -1.");
5088 **ptr = num_tree_types;
5093 label_concat(char *label_str, gsize pos, const char *str)
5095 if (pos < ITEM_LABEL_LENGTH)
5096 pos += g_strlcpy(label_str + pos, str, ITEM_LABEL_LENGTH - pos);
5102 label_mark_truncated(char *label_str, gsize name_pos)
5104 static const char trunc_str[] = " [truncated]";
5105 const size_t trunc_len = sizeof(trunc_str)-1;
5107 /* ..... field_name: dataaaaaaaaaaaaa
5111 * ..... field_name [truncated]: dataaaaaaaaaaaaa */
5113 if (name_pos < ITEM_LABEL_LENGTH - trunc_len) {
5114 memmove(label_str + name_pos + trunc_len, label_str + name_pos, ITEM_LABEL_LENGTH - name_pos - trunc_len);
5115 memcpy(label_str + name_pos, trunc_str, trunc_len);
5116 label_str[ITEM_LABEL_LENGTH-1] = '\0';
5118 } else if (name_pos < ITEM_LABEL_LENGTH)
5119 g_strlcpy(label_str + name_pos, trunc_str, ITEM_LABEL_LENGTH - name_pos);
5123 label_fill(char *label_str, gsize pos, const header_field_info *hfinfo, const char *text)
5127 /* "%s: %s", hfinfo->name, text */
5128 name_pos = pos = label_concat(label_str, pos, hfinfo->name);
5129 pos = label_concat(label_str, pos, ": ");
5130 pos = label_concat(label_str, pos, text ? text : "(null)");
5132 if (pos >= ITEM_LABEL_LENGTH) {
5133 /* Uh oh, we don't have enough room. Tell the user that the field is truncated. */
5134 label_mark_truncated(label_str, name_pos);
5141 label_fill_descr(char *label_str, gsize pos, const header_field_info *hfinfo, const char *text, const char *descr)
5145 /* "%s: %s (%s)", hfinfo->name, text, descr */
5146 name_pos = pos = label_concat(label_str, pos, hfinfo->name);
5147 pos = label_concat(label_str, pos, ": ");
5148 pos = label_concat(label_str, pos, text ? text : "(null)");
5149 pos = label_concat(label_str, pos, " (");
5150 pos = label_concat(label_str, pos, descr ? descr : "(null)");
5151 pos = label_concat(label_str, pos, ")");
5153 if (pos >= ITEM_LABEL_LENGTH) {
5154 /* Uh oh, we don't have enough room. Tell the user that the field is truncated. */
5155 label_mark_truncated(label_str, name_pos);
5162 proto_item_fill_label(field_info *fi, gchar *label_str)
5164 header_field_info *hfinfo;
5170 guint32 n_addr; /* network-order IPv4 address */
5177 /* XXX: Check validity of hfinfo->type */
5181 hfinfo = fi->hfinfo;
5183 switch (hfinfo->type) {
5186 g_strlcpy(label_str, hfinfo->name, ITEM_LABEL_LENGTH);
5190 fill_label_boolean(fi, label_str);
5195 bytes = (guint8 *)fvalue_get(&fi->value);
5196 label_fill(label_str, 0, hfinfo,
5197 (bytes) ? bytes_to_str(bytes, fvalue_length(&fi->value)) : "<MISSING>");
5200 /* Four types of integers to take care of:
5201 * Bitfield, with val_string
5202 * Bitfield, w/o val_string
5203 * Non-bitfield, with val_string
5204 * Non-bitfield, w/o val_string
5210 if (hfinfo->bitmask) {
5211 fill_label_bitfield(fi, label_str);
5213 fill_label_number(fi, label_str, FALSE);
5218 fill_label_number(fi, label_str, FALSE);
5222 fill_label_number64(fi, label_str, FALSE);
5229 DISSECTOR_ASSERT(!hfinfo->bitmask);
5230 fill_label_number(fi, label_str, TRUE);
5234 fill_label_number64(fi, label_str, TRUE);
5238 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5239 "%s: %." STRINGIFY(FLT_DIG) "g",
5240 hfinfo->name, fvalue_get_floating(&fi->value));
5244 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5245 "%s: %." STRINGIFY(DBL_DIG) "g",
5246 hfinfo->name, fvalue_get_floating(&fi->value));
5249 case FT_ABSOLUTE_TIME:
5250 label_fill(label_str, 0, hfinfo,
5251 abs_time_to_str((const nstime_t *)fvalue_get(&fi->value),
5252 (absolute_time_display_e)hfinfo->display, TRUE));
5255 case FT_RELATIVE_TIME:
5256 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5257 "%s: %s seconds", hfinfo->name,
5258 rel_time_to_secs_str((const nstime_t *)fvalue_get(&fi->value)));
5262 integer = fvalue_get_uinteger(&fi->value);
5263 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5264 "%s: %s (0x%08X)", hfinfo->name,
5265 get_ipxnet_name(integer), integer);
5269 bytes = (guint8 *)fvalue_get(&fi->value);
5270 label_fill_descr(label_str, 0, hfinfo,
5271 get_ax25_name(bytes),
5272 ax25_to_str(bytes));
5276 addr.type = AT_VINES;
5277 addr.len = VINES_ADDR_LEN;
5278 addr.data = (guint8 *)fvalue_get(&fi->value);
5280 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5281 "%s: %s", hfinfo->name,
5282 address_to_str( &addr ));
5286 bytes = (guint8 *)fvalue_get(&fi->value);
5287 label_fill_descr(label_str, 0, hfinfo,
5288 get_ether_name(bytes),
5289 ether_to_str(bytes));
5293 ipv4 = (ipv4_addr *)fvalue_get(&fi->value);
5294 n_addr = ipv4_get_net_order_addr(ipv4);
5295 label_fill_descr(label_str, 0, hfinfo,
5296 get_hostname(n_addr),
5297 ip_to_str((guint8*)&n_addr));
5301 bytes = (guint8 *)fvalue_get(&fi->value);
5302 label_fill_descr(label_str, 0, hfinfo,
5303 get_hostname6((struct e_in6_addr *)bytes),
5304 ip6_to_str((struct e_in6_addr*)bytes));
5308 guid = (e_guid_t *)fvalue_get(&fi->value);
5309 label_fill(label_str, 0, hfinfo, guid_to_str(guid));
5313 bytes = (guint8 *)fvalue_get(&fi->value);
5314 name = oid_resolved_from_encoded(bytes, fvalue_length(&fi->value));
5316 label_fill_descr(label_str, 0, hfinfo,
5317 oid_encoded2string(bytes, fvalue_length(&fi->value)), name);
5319 label_fill(label_str, 0, hfinfo,
5320 oid_encoded2string(bytes, fvalue_length(&fi->value)));
5324 integer64 = fvalue_get_integer64(&fi->value);
5325 label_fill_descr(label_str, 0, hfinfo,
5326 get_eui64_name(integer64),
5327 eui64_to_str(integer64));
5331 case FT_UINT_STRING:
5332 bytes = (guint8 *)fvalue_get(&fi->value);
5333 label_fill(label_str, 0, hfinfo, format_text(bytes, strlen(bytes)));
5337 g_error("hfinfo->type %d (%s) not handled\n",
5338 hfinfo->type, ftype_name(hfinfo->type));
5339 DISSECTOR_ASSERT_NOT_REACHED();
5345 fill_label_boolean(field_info *fi, gchar *label_str)
5347 char *p = label_str;
5348 int bitfield_byte_length = 0, bitwidth;
5349 guint32 unshifted_value;
5352 header_field_info *hfinfo = fi->hfinfo;
5353 const true_false_string *tfstring = (const true_false_string *)&tfs_true_false;
5355 if (hfinfo->strings) {
5356 tfstring = (const struct true_false_string*) hfinfo->strings;
5359 value = fvalue_get_uinteger(&fi->value);
5360 if (hfinfo->bitmask) {
5361 /* Figure out the bit width */
5362 bitwidth = hfinfo_bitwidth(hfinfo);
5365 unshifted_value = value;
5366 unshifted_value <<= hfinfo_bitshift(hfinfo);
5368 /* Create the bitfield first */
5369 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
5370 bitfield_byte_length = (int) (p - label_str);
5373 /* Fill in the textual info */
5374 label_fill(label_str, bitfield_byte_length, hfinfo, value ? tfstring->true_string : tfstring->false_string);
5378 hf_try_val_to_str(guint32 value, const header_field_info *hfinfo)
5380 if (hfinfo->display & BASE_RANGE_STRING)
5381 return try_rval_to_str(value, (const range_string *) hfinfo->strings);
5383 if (hfinfo->display & BASE_EXT_STRING)
5384 return try_val_to_str_ext(value, (const value_string_ext *) hfinfo->strings);
5386 if (hfinfo->display & BASE_VAL64_STRING)
5387 return try_val64_to_str(value, (const val64_string *) hfinfo->strings);
5389 return try_val_to_str(value, (const value_string *) hfinfo->strings);
5393 hf_try_val64_to_str(guint64 value, const header_field_info *hfinfo)
5395 if (hfinfo->display & BASE_VAL64_STRING)
5396 return try_val64_to_str(value, (const val64_string *) hfinfo->strings);
5398 /* If this is reached somebody registered a 64-bit field with a 32-bit
5399 * value-string, which isn't right. */
5400 DISSECTOR_ASSERT_NOT_REACHED();
5402 /* This is necessary to squelch MSVC errors; is there
5403 any way to tell it that DISSECTOR_ASSERT_NOT_REACHED()
5409 hf_try_val_to_str_const(guint32 value, const header_field_info *hfinfo, const char *unknown_str)
5411 const char *str = hf_try_val_to_str(value, hfinfo);
5413 return (str) ? str : unknown_str;
5417 hf_try_val64_to_str_const(guint64 value, const header_field_info *hfinfo, const char *unknown_str)
5419 const char *str = hf_try_val64_to_str(value, hfinfo);
5421 return (str) ? str : unknown_str;
5424 /* Fills data for bitfield ints with val_strings */
5426 fill_label_bitfield(field_info *fi, gchar *label_str)
5429 int bitfield_byte_length, bitwidth;
5430 guint32 unshifted_value;
5436 header_field_info *hfinfo = fi->hfinfo;
5438 /* Figure out the bit width */
5439 bitwidth = hfinfo_bitwidth(hfinfo);
5442 unshifted_value = fvalue_get_uinteger(&fi->value);
5443 value = unshifted_value;
5444 if (hfinfo->bitmask) {
5445 unshifted_value <<= hfinfo_bitshift(hfinfo);
5448 /* Create the bitfield first */
5449 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
5450 bitfield_byte_length = (int) (p - label_str);
5452 /* Fill in the textual info using stored (shifted) value */
5453 if (hfinfo->display == BASE_CUSTOM) {
5454 gchar tmp[ITEM_LABEL_LENGTH];
5455 const custom_fmt_func_t fmtfunc = (const custom_fmt_func_t)hfinfo->strings;
5457 DISSECTOR_ASSERT(fmtfunc);
5458 fmtfunc(tmp, value);
5459 label_fill(label_str, bitfield_byte_length, hfinfo, tmp);
5461 else if (hfinfo->strings) {
5462 const char *val_str = hf_try_val_to_str_const(value, hfinfo, "Unknown");
5464 out = hfinfo_number_vals_format(hfinfo, buf, value);
5465 if (out == NULL) /* BASE_NONE so don't put integer in descr */
5466 label_fill(label_str, bitfield_byte_length, hfinfo, val_str);
5468 label_fill_descr(label_str, bitfield_byte_length, hfinfo, val_str, out);
5471 out = hfinfo_number_value_format(hfinfo, buf, value);
5473 label_fill(label_str, bitfield_byte_length, hfinfo, out);
5478 fill_label_number(field_info *fi, gchar *label_str, gboolean is_signed)
5480 header_field_info *hfinfo = fi->hfinfo;
5487 value = fvalue_get_sinteger(&fi->value);
5489 value = fvalue_get_uinteger(&fi->value);
5491 /* Fill in the textual info */
5492 if (hfinfo->display == BASE_CUSTOM) {
5493 gchar tmp[ITEM_LABEL_LENGTH];
5494 const custom_fmt_func_t fmtfunc = (const custom_fmt_func_t)hfinfo->strings;
5496 DISSECTOR_ASSERT(fmtfunc);
5497 fmtfunc(tmp, value);
5498 label_fill(label_str, 0, hfinfo, tmp);
5500 else if (hfinfo->strings) {
5501 const char *val_str = hf_try_val_to_str_const(value, hfinfo, "Unknown");
5503 out = hfinfo_number_vals_format(hfinfo, buf, value);
5504 if (out == NULL) /* BASE_NONE so don't put integer in descr */
5505 label_fill(label_str, 0, hfinfo, val_str);
5507 label_fill_descr(label_str, 0, hfinfo, val_str, out);
5510 out = hfinfo_number_value_format(hfinfo, buf, value);
5512 label_fill(label_str, 0, hfinfo, out);
5517 fill_label_number64(field_info *fi, gchar *label_str, gboolean is_signed)
5519 const char *format = NULL;
5520 header_field_info *hfinfo = fi->hfinfo;
5522 char tmp[ITEM_LABEL_LENGTH+1];
5524 /* Pick the proper format string */
5526 format = hfinfo_int64_format(hfinfo);
5528 format = hfinfo_uint64_format(hfinfo);
5530 value = fvalue_get_integer64(&fi->value);
5532 /* Format the temporary string */
5533 if (IS_BASE_DUAL(hfinfo->display))
5534 g_snprintf(tmp, ITEM_LABEL_LENGTH, format, value, value);
5536 g_snprintf(tmp, ITEM_LABEL_LENGTH, format, value);
5538 if (hfinfo->strings) {
5539 const char *val_str = hf_try_val64_to_str_const(value, hfinfo, "Unknown");
5541 if ((hfinfo->display & BASE_DISPLAY_E_MASK) == BASE_NONE) {
5542 label_fill(label_str, 0, hfinfo, val_str);
5545 label_fill_descr(label_str, 0, hfinfo, val_str, tmp);
5549 label_fill(label_str, 0, hfinfo, tmp);
5554 hfinfo_bitshift(const header_field_info *hfinfo)
5556 const guint32 bitmask = hfinfo->bitmask;
5558 #if defined(__GNUC__) && ((__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4))
5559 g_assert(bitmask != 0);
5561 return __builtin_ctz(bitmask);
5563 /* From http://graphics.stanford.edu/~seander/bithacks.html#ZerosOnRightMultLookup */
5564 static const int table[32] = {
5565 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
5566 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9
5569 return table[((guint32)((bitmask & -(gint32)bitmask) * 0x077CB531U)) >> 27];
5574 hfinfo_bitwidth(const header_field_info *hfinfo)
5578 if (!hfinfo->bitmask) {
5582 switch (hfinfo->type) {
5600 bitwidth = hfinfo->display; /* hacky? :) */
5603 DISSECTOR_ASSERT_NOT_REACHED();
5610 _hfinfo_type_hex_octet(int type)
5630 DISSECTOR_ASSERT_NOT_REACHED();
5636 /* private to_str.c API don't export to .h! */
5637 char *oct_to_str_back(char *ptr, guint32 value);
5638 char *hex_to_str_back(char *ptr, int pad, guint32 value);
5639 char *uint_to_str_back(char *ptr, guint32 value);
5640 char *int_to_str_back(char *ptr, gint32 value);
5643 hfinfo_number_value_format_display(const header_field_info *hfinfo, int display, char buf[32], guint32 value)
5645 char *ptr = &buf[31];
5646 gboolean isint = IS_FT_INT(hfinfo->type);
5649 /* Properly format value */
5652 return isint ? int_to_str_back(ptr, (gint32) value) : uint_to_str_back(ptr, value);
5656 ptr = hex_to_str_back(ptr, _hfinfo_type_hex_octet(hfinfo->type), value);
5659 ptr = isint ? int_to_str_back(ptr, (gint32) value) : uint_to_str_back(ptr, value);
5663 return oct_to_str_back(ptr, value);
5666 return hex_to_str_back(ptr, _hfinfo_type_hex_octet(hfinfo->type), value);
5670 ptr = 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);
5677 DISSECTOR_ASSERT_NOT_REACHED();
5684 hfinfo_number_value_format(const header_field_info *hfinfo, char buf[32], guint32 value)
5686 int display = hfinfo->display;
5688 if (hfinfo->type == FT_FRAMENUM) {
5690 * Frame numbers are always displayed in decimal.
5695 return hfinfo_number_value_format_display(hfinfo, display, buf, value);
5699 hfinfo_numeric_value_format(const header_field_info *hfinfo, char buf[32], guint32 value)
5701 /* Get the underlying BASE_ value */
5702 int display = hfinfo->display & BASE_DISPLAY_E_MASK;
5704 if (hfinfo->type == FT_FRAMENUM) {
5706 * Frame numbers are always displayed in decimal.
5713 /* case BASE_DEC: */
5715 case BASE_OCT: /* XXX, why we're changing BASE_OCT to BASE_DEC? */
5720 /* case BASE_HEX: */
5726 return hfinfo_number_value_format_display(hfinfo, display, buf, value);
5730 hfinfo_number_vals_format(const header_field_info *hfinfo, char buf[32], guint32 value)
5732 /* Get the underlying BASE_ value */
5733 int display = hfinfo->display & BASE_DISPLAY_E_MASK;
5735 if (display == BASE_NONE)
5738 if (display == BASE_DEC_HEX)
5740 if (display == BASE_HEX_DEC)
5743 return hfinfo_number_value_format_display(hfinfo, display, buf, value);
5747 hfinfo_uint64_format(const header_field_info *hfinfo)
5749 const char *format = NULL;
5751 /* Pick the proper format string */
5752 switch (hfinfo->display & BASE_DISPLAY_E_MASK) {
5754 format = "%" G_GINT64_MODIFIER "u";
5757 format = "%" G_GINT64_MODIFIER "u (0x%016" G_GINT64_MODIFIER "x)";
5759 case BASE_OCT: /* I'm lazy */
5760 format = "%#" G_GINT64_MODIFIER "o";
5763 format = "0x%016" G_GINT64_MODIFIER "x";
5766 format = "0x%016" G_GINT64_MODIFIER "x (%" G_GINT64_MODIFIER "u)";
5769 DISSECTOR_ASSERT_NOT_REACHED();
5776 hfinfo_int64_format(const header_field_info *hfinfo)
5778 const char *format = NULL;
5780 /* Pick the proper format string */
5781 switch (hfinfo->display & BASE_DISPLAY_E_MASK) {
5783 format = "%" G_GINT64_MODIFIER "d";
5786 format = "%" G_GINT64_MODIFIER "d (0x%016" G_GINT64_MODIFIER "x)";
5788 case BASE_OCT: /* I'm lazy */
5789 format = "%#" G_GINT64_MODIFIER "o";
5792 format = "0x%016" G_GINT64_MODIFIER "x";
5795 format = "0x%016" G_GINT64_MODIFIER "x (%" G_GINT64_MODIFIER "d)";
5798 DISSECTOR_ASSERT_NOT_REACHED();
5805 proto_registrar_n(void)
5807 return gpa_hfinfo.len;
5811 proto_registrar_get_name(const int n)
5813 header_field_info *hfinfo;
5815 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
5816 return hfinfo->name;
5820 proto_registrar_get_abbrev(const int n)
5822 header_field_info *hfinfo;
5824 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
5825 return hfinfo->abbrev;
5829 proto_registrar_get_ftype(const int n)
5831 header_field_info *hfinfo;
5833 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
5834 return hfinfo->type;
5838 proto_registrar_get_parent(const int n)
5840 header_field_info *hfinfo;
5842 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
5843 return hfinfo->parent;
5847 proto_registrar_is_protocol(const int n)
5849 header_field_info *hfinfo;
5851 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
5852 return (hfinfo->parent == -1 ? TRUE : FALSE);
5855 /* Returns length of field in packet (not necessarily the length
5856 * in our internal representation, as in the case of IPv4).
5857 * 0 means undeterminable at time of registration
5858 * -1 means the field is not registered. */
5860 proto_registrar_get_length(const int n)
5862 header_field_info *hfinfo;
5864 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
5865 return ftype_length(hfinfo->type);
5868 /* Looks for a protocol or a field in a proto_tree. Returns TRUE if
5869 * it exists anywhere, or FALSE if it exists nowhere. */
5871 proto_check_for_protocol_or_field(const proto_tree* tree, const int id)
5873 GPtrArray *ptrs = proto_get_finfo_ptr_array(tree, id);
5878 else if (g_ptr_array_len(ptrs) > 0) {
5886 /* Return GPtrArray* of field_info pointers for all hfindex that appear in tree.
5887 * This only works if the hfindex was "primed" before the dissection
5888 * took place, as we just pass back the already-created GPtrArray*.
5889 * The caller should *not* free the GPtrArray*; proto_tree_free_node()
5892 proto_get_finfo_ptr_array(const proto_tree *tree, const int id)
5897 if (PTREE_DATA(tree)->interesting_hfids != NULL)
5898 return (GPtrArray *)g_hash_table_lookup(PTREE_DATA(tree)->interesting_hfids,
5899 GINT_TO_POINTER(id));
5905 proto_tracking_interesting_fields(const proto_tree *tree)
5910 return (PTREE_DATA(tree)->interesting_hfids != NULL);
5913 /* Helper struct for proto_find_info() and proto_all_finfos() */
5919 /* Helper function for proto_find_info() */
5921 find_finfo(proto_node *node, gpointer data)
5923 field_info *fi = PNODE_FINFO(node);
5924 if (fi && fi->hfinfo) {
5925 if (fi->hfinfo->id == ((ffdata_t*)data)->id) {
5926 g_ptr_array_add(((ffdata_t*)data)->array, fi);
5930 /* Don't stop traversing. */
5934 /* Return GPtrArray* of field_info pointers for all hfindex that appear in a tree.
5935 * This works on any proto_tree, primed or unprimed, but actually searches
5936 * the tree, so it is slower than using proto_get_finfo_ptr_array on a primed tree.
5937 * The caller does need to free the returned GPtrArray with
5938 * g_ptr_array_free(<array>, TRUE).
5941 proto_find_finfo(proto_tree *tree, const int id)
5945 ffdata.array = g_ptr_array_new();
5948 proto_tree_traverse_pre_order(tree, find_finfo, &ffdata);
5950 return ffdata.array;
5953 /* Helper function for proto_all_finfos() */
5955 every_finfo(proto_node *node, gpointer data)
5957 field_info *fi = PNODE_FINFO(node);
5958 if (fi && fi->hfinfo) {
5959 g_ptr_array_add(((ffdata_t*)data)->array, fi);
5962 /* Don't stop traversing. */
5966 /* Return GPtrArray* of field_info pointers containing all hfindexes that appear in a tree. */
5968 proto_all_finfos(proto_tree *tree)
5972 ffdata.array = g_ptr_array_new();
5975 proto_tree_traverse_pre_order(tree, every_finfo, &ffdata);
5977 return ffdata.array;
5988 check_for_offset(proto_node *node, const gpointer data)
5990 field_info *fi = PNODE_FINFO(node);
5991 offset_search_t *offsearch = (offset_search_t *)data;
5993 /* !fi == the top most container node which holds nothing */
5994 if (fi && !PROTO_ITEM_IS_HIDDEN(node) && fi->ds_tvb && offsearch->tvb == fi->ds_tvb) {
5995 if (offsearch->offset >= (guint) fi->start &&
5996 offsearch->offset < (guint) (fi->start + fi->length)) {
5998 offsearch->finfo = fi;
5999 return FALSE; /* keep traversing */
6002 return FALSE; /* keep traversing */
6005 /* Search a proto_tree backwards (from leaves to root) looking for the field
6006 * whose start/length occupies 'offset' */
6007 /* XXX - I couldn't find an easy way to search backwards, so I search
6008 * forwards, w/o stopping. Therefore, the last finfo I find will the be
6009 * the one I want to return to the user. This algorithm is inefficient
6010 * and could be re-done, but I'd have to handle all the children and
6011 * siblings of each node myself. When I have more time I'll do that.
6014 proto_find_field_from_offset(proto_tree *tree, guint offset, tvbuff_t *tvb)
6016 offset_search_t offsearch;
6018 offsearch.offset = offset;
6019 offsearch.finfo = NULL;
6020 offsearch.tvb = tvb;
6022 proto_tree_traverse_pre_order(tree, check_for_offset, &offsearch);
6024 return offsearch.finfo;
6027 /* Dumps the protocols in the registration database to stdout. An independent
6028 * program can take this output and format it into nice tables or HTML or
6031 * There is one record per line. The fields are tab-delimited.
6033 * Field 1 = protocol name
6034 * Field 2 = protocol short name
6035 * Field 3 = protocol filter name
6038 proto_registrar_dump_protocols(void)
6040 protocol_t *protocol;
6042 void *cookie = NULL;
6045 i = proto_get_first_protocol(&cookie);
6047 protocol = find_protocol_by_id(i);
6048 printf("%s\t%s\t%s\n", protocol->name, protocol->short_name,
6049 protocol->filter_name);
6050 i = proto_get_next_protocol(&cookie);
6054 /* Dumps the value_strings, extended value string headers, range_strings
6055 * or true/false strings for fields that have them.
6056 * There is one record per line. Fields are tab-delimited.
6057 * There are four types of records: Value String, Extended Value String Header,
6058 * Range String and True/False String. The first field, 'V', 'E', 'R' or 'T', indicates
6059 * the type of record.
6061 * Note that a record will be generated only if the value_string,... is referenced
6062 * in a registered hfinfo entry.
6068 * Field 2 = Field abbreviation to which this value string corresponds
6069 * Field 3 = Integer value
6072 * Extended Value String Headers
6073 * -----------------------------
6075 * Field 2 = Field abbreviation to which this extended value string header corresponds
6076 * Field 3 = Extended Value String "Name"
6077 * Field 4 = Number of entries in the associated value_string array
6078 * Field 5 = Access Type: "Linear Search", "Binary Search", "Direct (indexed) Access"
6083 * Field 2 = Field abbreviation to which this range string corresponds
6084 * Field 3 = Integer value: lower bound
6085 * Field 4 = Integer value: upper bound
6088 * True/False Strings
6089 * ------------------
6091 * Field 2 = Field abbreviation to which this true/false string corresponds
6092 * Field 3 = True String
6093 * Field 4 = False String
6096 proto_registrar_dump_values(void)
6098 header_field_info *hfinfo;
6100 const value_string *vals;
6101 const val64_string *vals64;
6102 const range_string *range;
6103 const true_false_string *tfs;
6105 len = gpa_hfinfo.len;
6106 for (i = 0; i < len ; i++) {
6107 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
6109 if (hfinfo->id == hf_text_only) {
6113 /* ignore protocols */
6114 if (proto_registrar_is_protocol(i)) {
6117 /* process header fields */
6120 * If this field isn't at the head of the list of
6121 * fields with this name, skip this field - all
6122 * fields with the same name are really just versions
6123 * of the same field stored in different bits, and
6124 * should have the same type/radix/value list, and
6125 * just differ in their bit masks. (If a field isn't
6126 * a bitfield, but can be, say, 1 or 2 bytes long,
6127 * it can just be made FT_UINT16, meaning the
6128 * *maximum* length is 2 bytes, and be used
6131 if (hfinfo->same_name_prev_id != -1)
6139 if (hfinfo->strings != NULL) {
6140 if ((hfinfo->display & BASE_DISPLAY_E_MASK) != BASE_CUSTOM &&
6141 (hfinfo->type == FT_UINT8 ||
6142 hfinfo->type == FT_UINT16 ||
6143 hfinfo->type == FT_UINT24 ||
6144 hfinfo->type == FT_UINT32 ||
6145 hfinfo->type == FT_UINT64 ||
6146 hfinfo->type == FT_INT8 ||
6147 hfinfo->type == FT_INT16 ||
6148 hfinfo->type == FT_INT24 ||
6149 hfinfo->type == FT_INT32 ||
6150 hfinfo->type == FT_INT64)) {
6152 if (hfinfo->display & BASE_EXT_STRING) {
6153 vals = VALUE_STRING_EXT_VS_P((const value_string_ext *)hfinfo->strings);
6154 } else if ((hfinfo->display & BASE_RANGE_STRING) == 0) {
6155 vals = (const value_string *)hfinfo->strings;
6156 } else if ((hfinfo->display & BASE_VAL64_STRING) == 0) {
6157 vals64 = (const val64_string *)hfinfo->strings;
6159 range = (const range_string *)hfinfo->strings;
6162 else if (hfinfo->type == FT_BOOLEAN) {
6163 tfs = (const struct true_false_string *)hfinfo->strings;
6167 /* Print value strings? */
6169 if (hfinfo->display & BASE_EXT_STRING) {
6170 const value_string_ext *vse_p = (const value_string_ext *)hfinfo->strings;
6171 if (!value_string_ext_validate(vse_p)) {
6172 g_warning("Invalid value_string_ext ptr for: %s", hfinfo->abbrev);
6175 try_val_to_str_ext(0, vse_p); /* "prime" the extended value_string */
6176 printf("E\t%s\t%d\t%s\t%s\n",
6178 VALUE_STRING_EXT_VS_NUM_ENTRIES(vse_p),
6179 VALUE_STRING_EXT_VS_NAME(vse_p),
6180 value_string_ext_match_type_str(vse_p));
6183 while (vals[vi].strptr) {
6184 /* Print in the proper base */
6185 if (hfinfo->display == BASE_HEX) {
6186 printf("V\t%s\t0x%x\t%s\n",
6192 printf("V\t%s\t%u\t%s\n",
6202 while (vals64[vi].strptr) {
6203 printf("V64\t%s\t%" G_GINT64_MODIFIER "u\t%s\n",
6211 /* print range strings? */
6214 while (range[vi].strptr) {
6215 /* Print in the proper base */
6216 if ((hfinfo->display & BASE_DISPLAY_E_MASK) == BASE_HEX) {
6217 printf("R\t%s\t0x%x\t0x%x\t%s\n",
6219 range[vi].value_min,
6220 range[vi].value_max,
6224 printf("R\t%s\t%u\t%u\t%s\n",
6226 range[vi].value_min,
6227 range[vi].value_max,
6234 /* Print true/false strings? */
6236 printf("T\t%s\t%s\t%s\n", hfinfo->abbrev,
6237 tfs->true_string, tfs->false_string);
6243 /* Dumps the contents of the registration database to stdout. An independent
6244 * program can take this output and format it into nice tables or HTML or
6247 * There is one record per line. Each record is either a protocol or a header
6248 * field, differentiated by the first field. The fields are tab-delimited.
6253 * Field 2 = descriptive protocol name
6254 * Field 3 = protocol abbreviation
6259 * Field 2 = descriptive field name
6260 * Field 3 = field abbreviation
6261 * Field 4 = type ( textual representation of the the ftenum type )
6262 * Field 5 = parent protocol abbreviation
6263 * Field 6 = base for display (for integer types); "parent bitfield width" for FT_BOOLEAN
6264 * Field 7 = bitmask: format: hex: 0x....
6265 * Field 8 = blurb describing field
6268 proto_registrar_dump_fields(void)
6270 header_field_info *hfinfo, *parent_hfinfo;
6272 const char *enum_name;
6273 const char *base_name;
6277 len = gpa_hfinfo.len;
6278 for (i = 0; i < len ; i++) {
6279 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
6282 * Skip the pseudo-field for "proto_tree_add_text()" since
6283 * we don't want it in the list of filterable fields.
6285 if (hfinfo->id == hf_text_only)
6288 /* format for protocols */
6289 if (proto_registrar_is_protocol(i)) {
6290 printf("P\t%s\t%s\n", hfinfo->name, hfinfo->abbrev);
6292 /* format for header fields */
6295 * If this field isn't at the head of the list of
6296 * fields with this name, skip this field - all
6297 * fields with the same name are really just versions
6298 * of the same field stored in different bits, and
6299 * should have the same type/radix/value list, and
6300 * just differ in their bit masks. (If a field isn't
6301 * a bitfield, but can be, say, 1 or 2 bytes long,
6302 * it can just be made FT_UINT16, meaning the
6303 * *maximum* length is 2 bytes, and be used
6306 if (hfinfo->same_name_prev_id != -1)
6309 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
6311 enum_name = ftype_name(hfinfo->type);
6314 if (hfinfo->type == FT_UINT8 ||
6315 hfinfo->type == FT_UINT16 ||
6316 hfinfo->type == FT_UINT24 ||
6317 hfinfo->type == FT_UINT32 ||
6318 hfinfo->type == FT_UINT64 ||
6319 hfinfo->type == FT_INT8 ||
6320 hfinfo->type == FT_INT16 ||
6321 hfinfo->type == FT_INT24 ||
6322 hfinfo->type == FT_INT32 ||
6323 hfinfo->type == FT_INT64) {
6325 switch (hfinfo->display & BASE_DISPLAY_E_MASK) {
6327 base_name = "BASE_NONE";
6330 base_name = "BASE_DEC";
6333 base_name = "BASE_HEX";
6336 base_name = "BASE_OCT";
6339 base_name = "BASE_DEC_HEX";
6342 base_name = "BASE_HEX_DEC";
6345 base_name = "BASE_CUSTOM";
6351 } else if (hfinfo->type == FT_BOOLEAN) {
6352 /* For FT_BOOLEAN: 'display' can be "parent bitfield width" */
6353 g_snprintf(width, sizeof(width), "%d", hfinfo->display);
6357 blurb = hfinfo->blurb;
6360 else if (strlen(blurb) == 0)
6363 printf("F\t%s\t%s\t%s\t%s\t%s\t0x%x\t%s\n",
6364 hfinfo->name, hfinfo->abbrev, enum_name,
6365 parent_hfinfo->abbrev, base_name, hfinfo->bitmask, blurb);
6370 /* Dumps field types and descriptive names to stdout. An independent
6371 * program can take this output and format it into nice tables or HTML or
6374 * There is one record per line. The fields are tab-delimited.
6376 * Field 1 = field type name, e.g. FT_UINT8
6377 * Field 2 = descriptive name, e.g. "Unsigned, 1 byte"
6380 proto_registrar_dump_ftypes(void)
6384 for (fte = 0; fte < FT_NUM_TYPES; fte++) {
6385 printf("%s\t%s\n", ftype_name((ftenum_t)fte), ftype_pretty_name((ftenum_t)fte));
6390 hfinfo_numeric_format(const header_field_info *hfinfo)
6392 const char *format = NULL;
6394 /* Get the underlying BASE_ value */
6395 switch (hfinfo->display & BASE_DISPLAY_E_MASK) {
6398 case BASE_OCT: /* I'm lazy */
6400 switch (hfinfo->type) {
6402 format = "%s == %" G_GINT64_MODIFIER "u";
6405 format = "%s == %" G_GINT64_MODIFIER "d";
6408 DISSECTOR_ASSERT_NOT_REACHED();
6414 switch (hfinfo->type) {
6417 format = "%s == 0x%016" G_GINT64_MODIFIER "x";
6420 DISSECTOR_ASSERT_NOT_REACHED();
6425 DISSECTOR_ASSERT_NOT_REACHED();
6431 /* This function indicates whether it's possible to construct a
6432 * "match selected" display filter string for the specified field,
6433 * returns an indication of whether it's possible, and, if it's
6434 * possible and "filter" is non-null, constructs the filter and
6435 * sets "*filter" to point to it.
6436 * You do not need to [g_]free() this string since it will be automatically
6437 * freed once the next packet is dissected.
6440 construct_match_selected_string(field_info *finfo, epan_dissect_t *edt,
6443 header_field_info *hfinfo;
6448 gint start, length, length_remaining;
6450 gchar is_signed_num = FALSE;
6455 hfinfo = finfo->hfinfo;
6456 DISSECTOR_ASSERT(hfinfo);
6457 abbrev_len = (int) strlen(hfinfo->abbrev);
6459 if (hfinfo->strings && (hfinfo->display & BASE_DISPLAY_E_MASK) == BASE_NONE) {
6460 const gchar *str = NULL;
6462 switch (hfinfo->type) {
6468 str = hf_try_val_to_str(fvalue_get_sinteger(&finfo->value), hfinfo);
6475 str = hf_try_val_to_str(fvalue_get_uinteger(&finfo->value), hfinfo);
6482 if (str != NULL && filter != NULL) {
6483 *filter = ep_strdup_printf("%s == \"%s\"", hfinfo->abbrev, str);
6489 * XXX - we can't use the "val_to_string_repr" and "string_repr_len"
6490 * functions for FT_UINT and FT_INT types, as we choose the base in
6491 * the string expression based on the display base of the field.
6493 * Note that the base does matter, as this is also used for
6494 * the protocolinfo tap.
6496 * It might be nice to use them in "proto_item_fill_label()"
6497 * as well, although, there, you'd have to deal with the base
6498 * *and* with resolved values for addresses.
6500 * Perhaps we need two different val_to_string routines, one
6501 * to generate items for display filters and one to generate
6502 * strings for display, and pass to both of them the
6503 * "display" and "strings" values in the header_field_info
6504 * structure for the field, so they can get the base and,
6505 * if the field is Boolean or an enumerated integer type,
6506 * the tables used to generate human-readable values.
6508 switch (hfinfo->type) {
6514 is_signed_num = TRUE;
6521 if (filter != NULL) {
6528 number = fvalue_get_sinteger(&finfo->value);
6530 number = fvalue_get_uinteger(&finfo->value);
6532 out = hfinfo_numeric_value_format(hfinfo, buf, number);
6534 *filter = ep_strdup_printf("%s == %s", hfinfo->abbrev, out);
6540 if (filter != NULL) {
6541 const char *format = hfinfo_numeric_format(hfinfo);
6543 *filter = ep_strdup_printf(format,
6545 fvalue_get_integer64(&finfo->value));
6551 *filter = ep_strdup(finfo->hfinfo->abbrev);
6556 * If the length is 0, just match the name of the
6559 * (Also check for negative values, just in case,
6560 * as we'll cast it to an unsigned value later.)
6562 length = finfo->length;
6565 *filter = ep_strdup(finfo->hfinfo->abbrev);
6572 * This doesn't have a value, so we'd match
6573 * on the raw bytes at this address.
6575 * Should we be allowed to access to the raw bytes?
6576 * If "edt" is NULL, the answer is "no".
6582 * Is this field part of the raw frame tvbuff?
6583 * If not, we can't use "frame[N:M]" to match
6586 * XXX - should this be frame-relative, or
6587 * protocol-relative?
6589 * XXX - does this fallback for non-registered
6590 * fields even make sense?
6592 if (finfo->ds_tvb != edt->tvb)
6593 return FALSE; /* you lose */
6596 * Don't go past the end of that tvbuff.
6598 length_remaining = tvb_length_remaining(finfo->ds_tvb, finfo->start);
6599 if (length > length_remaining)
6600 length = length_remaining;
6604 if (filter != NULL) {
6605 start = finfo->start;
6606 buf_len = 32 + length * 3;
6607 *filter = (char *)ep_alloc0(buf_len);
6610 ptr += g_snprintf(ptr, (gulong) (buf_len-(ptr-*filter)),
6611 "frame[%d:%d] == ", finfo->start, length);
6612 for (i=0; i<length; i++) {
6613 c = tvb_get_guint8(finfo->ds_tvb, start);
6616 ptr += g_snprintf(ptr, (gulong) (buf_len-(ptr-*filter)), "%02x", c);
6619 ptr += g_snprintf(ptr, (gulong) (buf_len-(ptr-*filter)), ":%02x", c);
6626 /* FT_PCRE never appears as a type for a registered field. It is
6627 * only used internally. */
6628 DISSECTOR_ASSERT_NOT_REACHED();
6631 /* By default, use the fvalue's "to_string_repr" method. */
6633 /* Figure out the string length needed.
6634 * The ft_repr length.
6635 * 4 bytes for " == ".
6636 * 1 byte for trailing NUL.
6638 if (filter != NULL) {
6639 dfilter_len = fvalue_string_repr_len(&finfo->value,
6641 dfilter_len += abbrev_len + 4 + 1;
6642 *filter = (char *)ep_alloc0(dfilter_len);
6644 /* Create the string */
6645 g_snprintf(*filter, dfilter_len, "%s == ",
6647 fvalue_to_string_repr(&finfo->value,
6649 &(*filter)[abbrev_len + 4]);
6658 * Returns TRUE if we can do a "match selected" on the field, FALSE
6662 proto_can_match_selected(field_info *finfo, epan_dissect_t *edt)
6664 return construct_match_selected_string(finfo, edt, NULL);
6667 /* This function attempts to construct a "match selected" display filter
6668 * string for the specified field; if it can do so, it returns a pointer
6669 * to the string, otherwise it returns NULL.
6671 * The string is allocated with packet lifetime scope.
6672 * You do not need to [g_]free() this string since it will be automatically
6673 * freed once the next packet is dissected.
6676 proto_construct_match_selected_string(field_info *finfo, epan_dissect_t *edt)
6680 if (!construct_match_selected_string(finfo, edt, &filter))
6685 /* This function is common code for both proto_tree_add_bitmask() and
6686 * proto_tree_add_bitmask_text() functions.
6689 /* NOTE: to support code written when proto_tree_add_bitmask() and
6690 * proto_tree_add_bitmask_text took a
6691 * gboolean as its last argument, with FALSE meaning "big-endian"
6692 * and TRUE meaning "little-endian", we treat any non-zero value of
6693 * "encoding" as meaning "little-endian".
6696 proto_item_add_bitmask_tree(proto_item *item, tvbuff_t *tvb, const int offset,
6697 const int len, const gint ett, const int **fields,
6698 const guint encoding, const int flags,
6702 guint32 available_bits = 0;
6704 proto_tree *tree = NULL;
6705 header_field_info *hf;
6709 value = tvb_get_guint8(tvb, offset);
6710 available_bits = 0xFF;
6713 value = encoding ? tvb_get_letohs(tvb, offset) :
6714 tvb_get_ntohs(tvb, offset);
6715 available_bits = 0xFFFF;
6718 value = encoding ? tvb_get_letoh24(tvb, offset) :
6719 tvb_get_ntoh24(tvb, offset);
6720 available_bits = 0xFFFFFF;
6723 value = encoding ? tvb_get_letohl(tvb, offset) :
6724 tvb_get_ntohl(tvb, offset);
6725 available_bits = 0xFFFFFFFF;
6728 g_assert_not_reached();
6731 tree = proto_item_add_subtree(item, ett);
6733 guint32 present_bits;
6734 hf = proto_registrar_get_nth(**fields);
6735 DISSECTOR_ASSERT(hf->bitmask != 0);
6737 /* Skip fields that aren't fully present */
6738 present_bits = available_bits & hf->bitmask;
6739 if (present_bits != hf->bitmask) {
6744 proto_tree_add_item(tree, **fields, tvb, offset, len, encoding);
6745 if (flags & BMT_NO_APPEND) {
6749 tmpval = (value & hf->bitmask) >> hfinfo_bitshift(hf);
6760 if (hf->display == BASE_CUSTOM) {
6761 gchar lbl[ITEM_LABEL_LENGTH];
6762 const custom_fmt_func_t fmtfunc = (const custom_fmt_func_t)hf->strings;
6764 DISSECTOR_ASSERT(fmtfunc);
6765 fmtfunc(lbl, tmpval);
6766 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
6770 else if (hf->strings) {
6771 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
6772 hf->name, hf_try_val_to_str_const(tmpval, hf, "Unknown"));
6775 else if (!(flags & BMT_NO_INT)) {
6780 proto_item_append_text(item, ", ");
6783 out = hfinfo_number_value_format(hf, buf, tmpval);
6784 proto_item_append_text(item, "%s: %s", hf->name, out);
6790 if (hf->strings && !(flags & BMT_NO_TFS)) {
6791 /* If we have true/false strings, emit full - otherwise messages
6793 const struct true_false_string *tfs =
6794 (const struct true_false_string *)hf->strings;
6797 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
6798 hf->name, tfs->true_string);
6800 } else if (!(flags & BMT_NO_FALSE)) {
6801 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
6802 hf->name, tfs->false_string);
6805 } else if (hf->bitmask & value) {
6806 /* If the flag is set, show the name */
6807 proto_item_append_text(item, "%s%s", first ? "" : ", ", hf->name);
6812 g_assert_not_reached();
6821 /* This function will dissect a sequence of bytes that describe a
6823 * hf_hdr is a 8/16/24/32 bit integer that describes the bitmask to be dissected.
6824 * This field will form an expansion under which the individual fields of the
6825 * bitmask is dissected and displayed.
6826 * This field must be of the type FT_[U]INT{8|16|24|32}.
6828 * fields is an array of pointers to int that lists all the fields of the
6829 * bitmask. These fields can be either of the type FT_BOOLEAN for flags
6830 * or another integer of the same type/size as hf_hdr with a mask specified.
6831 * This array is terminated by a NULL entry.
6833 * FT_BOOLEAN bits that are set to 1 will have the name added to the expansion.
6834 * FT_integer fields that have a value_string attached will have the
6835 * matched string displayed on the expansion line.
6838 proto_tree_add_bitmask(proto_tree *parent_tree, tvbuff_t *tvb,
6839 const guint offset, const int hf_hdr,
6840 const gint ett, const int **fields,
6841 const guint encoding)
6843 proto_item *item = NULL;
6844 header_field_info *hf;
6847 hf = proto_registrar_get_nth(hf_hdr);
6848 DISSECTOR_ASSERT(IS_FT_INT(hf->type) || IS_FT_UINT(hf->type));
6849 len = ftype_length(hf->type);
6852 item = proto_tree_add_item(parent_tree, hf_hdr, tvb, offset, len, encoding);
6853 proto_item_add_bitmask_tree(item, tvb, offset, len, ett, fields, encoding,
6854 BMT_NO_INT|BMT_NO_TFS, FALSE);
6860 /* The same as proto_tree_add_bitmask(), but using a caller-supplied length.
6861 * This is intended to support bitmask fields whose lengths can vary, perhaps
6862 * as the underlying standard evolves over time.
6863 * With this API there is the possibility of being called to display more or
6864 * less data than the dissector was coded to support.
6865 * In such cases, it is assumed that bitmasks are extended on the MSb end.
6866 * Thus when presented with "too much" or "too little" data, MSbits will be
6867 * ignored or MSfields sacrificed.
6869 * Only fields for which all defined bits are available are displayed.
6872 proto_tree_add_bitmask_len(proto_tree *parent_tree, tvbuff_t *tvb,
6873 const guint offset, const guint len, const int hf_hdr,
6874 const gint ett, const int **fields,
6875 const guint encoding)
6877 proto_item *item = NULL;
6878 header_field_info *hf;
6880 hf = proto_registrar_get_nth(hf_hdr);
6881 DISSECTOR_ASSERT(IS_FT_INT(hf->type) || IS_FT_UINT(hf->type));
6884 guint decodable_len;
6885 guint decodable_offset;
6886 guint32 decodable_value;
6888 decodable_offset = offset;
6889 decodable_len = MIN(len, (guint) ftype_length(hf->type));
6891 /* If we are ftype_length-limited,
6892 * make sure we decode as many LSBs as possible.
6894 if (encoding == ENC_BIG_ENDIAN) {
6895 decodable_offset += (len - decodable_len);
6898 decodable_value = get_uint_value(parent_tree, tvb, decodable_offset,
6899 decodable_len, encoding);
6901 /* The root item covers all the bytes even if we can't decode them all */
6902 item = proto_tree_add_uint(parent_tree, hf_hdr, tvb, offset, len,
6905 if (decodable_len < len) {
6906 /* Dissector likely requires updating for new protocol revision */
6907 expert_add_info_format(NULL, item, PI_UNDECODED, PI_WARN,
6908 "Only least-significant %d of %d bytes decoded",
6909 decodable_len, len);
6912 proto_item_add_bitmask_tree(item, tvb, decodable_offset, decodable_len,
6913 ett, fields, encoding, BMT_NO_INT|BMT_NO_TFS, FALSE);
6919 /* The same as proto_tree_add_bitmask(), but using an arbitrary text as a top-level item */
6921 proto_tree_add_bitmask_text(proto_tree *parent_tree, tvbuff_t *tvb,
6922 const guint offset, const guint len,
6923 const char *name, const char *fallback,
6924 const gint ett, const int **fields,
6925 const guint encoding, const int flags)
6927 proto_item *item = NULL;
6930 item = proto_tree_add_text(parent_tree, tvb, offset, len, "%s", name ? name : "");
6931 if (proto_item_add_bitmask_tree(item, tvb, offset, len, ett, fields, encoding,
6932 flags, TRUE) && fallback) {
6933 /* Still at first item - append 'fallback' text if any */
6934 proto_item_append_text(item, "%s", fallback);
6942 proto_tree_add_bits_item(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
6943 const guint bit_offset, const gint no_of_bits,
6944 const guint encoding)
6946 header_field_info *hfinfo;
6950 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
6952 octet_length = (no_of_bits + 7) >> 3;
6953 octet_offset = bit_offset >> 3;
6954 test_length(hfinfo, tree, tvb, octet_offset, octet_length, encoding);
6956 /* Yes, we try to fake this item again in proto_tree_add_bits_ret_val()
6957 * but only after doing a bunch more work (which we can, in the common
6958 * case, shortcut here).
6960 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
6962 return proto_tree_add_bits_ret_val(tree, hfindex, tvb, bit_offset, no_of_bits, NULL, encoding);
6966 * This function will dissect a sequence of bits that does not need to be byte aligned; the bits
6967 * set will be shown in the tree as ..10 10.. and the integer value returned if return_value is set.
6968 * Offset should be given in bits from the start of the tvb.
6972 _proto_tree_add_bits_ret_val(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
6973 const guint bit_offset, const gint no_of_bits,
6974 guint64 *return_value, const guint encoding)
6980 char lbl_str[ITEM_LABEL_LENGTH];
6984 header_field_info *hf_field;
6986 const true_false_string *tfstring;
6988 /* We can't fake it just yet. We have to fill in the 'return_value' parameter */
6989 PROTO_REGISTRAR_GET_NTH(hfindex, hf_field);
6991 if (hf_field->bitmask != 0) {
6992 REPORT_DISSECTOR_BUG(ep_strdup_printf("Incompatible use of proto_tree_add_bits_ret_val"
6993 " with field '%s' (%s) with bitmask != 0",
6994 hf_field->abbrev, hf_field->name));
6997 DISSECTOR_ASSERT(no_of_bits > 0);
6999 /* Byte align offset */
7000 offset = bit_offset>>3;
7003 * Calculate the number of octets used to hold the bits
7005 tot_no_bits = ((bit_offset&0x7) + no_of_bits);
7006 length = (tot_no_bits + 7) >> 3;
7008 if (no_of_bits < 65) {
7009 value = tvb_get_bits64(tvb, bit_offset, no_of_bits, encoding);
7011 DISSECTOR_ASSERT_NOT_REACHED();
7015 /* Sign extend for signed types */
7016 switch (hf_field->type) {
7022 if (value & (G_GINT64_CONSTANT(1) << (no_of_bits-1)))
7023 value |= (G_GINT64_CONSTANT(-1) << no_of_bits);
7031 *return_value = value;
7034 /* Coast clear. Try and fake it */
7035 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
7037 bf_str = decode_bits_in_field(bit_offset, no_of_bits, value);
7039 switch (hf_field->type) {
7042 tfstring = (const true_false_string *) &tfs_true_false;
7043 if (hf_field->strings)
7044 tfstring = (const true_false_string *)hf_field->strings;
7045 return proto_tree_add_boolean_format(tree, hfindex, tvb, offset, length, (guint32)value,
7047 bf_str, hf_field->name,
7048 (guint32)value ? tfstring->true_string : tfstring->false_string);
7055 pi = proto_tree_add_uint(tree, hfindex, tvb, offset, length, (guint32)value);
7056 fill_label_number(PITEM_FINFO(pi), lbl_str, FALSE);
7063 pi = proto_tree_add_int(tree, hfindex, tvb, offset, length, (gint32)value);
7064 fill_label_number(PITEM_FINFO(pi), lbl_str, TRUE);
7068 pi = proto_tree_add_uint64(tree, hfindex, tvb, offset, length, value);
7069 fill_label_number64(PITEM_FINFO(pi), lbl_str, FALSE);
7073 pi = proto_tree_add_int64(tree, hfindex, tvb, offset, length, (gint64)value);
7074 fill_label_number64(PITEM_FINFO(pi), lbl_str, TRUE);
7078 DISSECTOR_ASSERT_NOT_REACHED();
7083 proto_item_set_text(pi, "%s = %s", bf_str, lbl_str);
7088 proto_tree_add_split_bits_item_ret_val(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
7089 const guint bit_offset, const crumb_spec_t *crumb_spec,
7090 guint64 *return_value)
7095 guint mask_initial_bit_offset;
7096 guint mask_greatest_bit_offset;
7100 char lbl_str[ITEM_LABEL_LENGTH];
7102 guint64 composite_bitmask;
7103 guint64 composite_bitmap;
7105 header_field_info *hf_field;
7106 const true_false_string *tfstring;
7108 /* We can't fake it just yet. We have to fill in the 'return_value' parameter */
7109 PROTO_REGISTRAR_GET_NTH(hfindex, hf_field);
7111 if (hf_field->bitmask != 0) {
7112 REPORT_DISSECTOR_BUG(ep_strdup_printf(
7113 "Incompatible use of proto_tree_add_split_bits_item_ret_val"
7114 " with field '%s' (%s) with bitmask != 0",
7115 hf_field->abbrev, hf_field->name));
7118 mask_initial_bit_offset = bit_offset % 8;
7123 mask_greatest_bit_offset = 0;
7124 composite_bitmask = 0;
7125 composite_bitmap = 0;
7127 while (crumb_spec[i].crumb_bit_length != 0) {
7128 guint64 crumb_mask, crumb_value;
7129 guint8 crumb_end_bit_offset;
7131 DISSECTOR_ASSERT(i < 64);
7132 crumb_value = tvb_get_bits64(tvb,
7133 bit_offset + crumb_spec[i].crumb_bit_offset,
7134 crumb_spec[i].crumb_bit_length,
7136 value += crumb_value;
7137 no_of_bits += crumb_spec[i].crumb_bit_length;
7139 /* The bitmask is 64 bit, left-aligned, starting at the first bit of the
7140 octet containing the initial offset.
7141 If the mask is beyond 32 bits, then give up on bit map display.
7142 This could be improved in future, probably showing a table
7143 of 32 or 64 bits per row */
7144 if (mask_greatest_bit_offset < 32) {
7145 crumb_end_bit_offset = mask_initial_bit_offset
7146 + crumb_spec[i].crumb_bit_offset
7147 + crumb_spec[i].crumb_bit_length;
7148 crumb_mask = (G_GUINT64_CONSTANT(1) << crumb_spec[i].crumb_bit_length) - 1;
7150 if (crumb_end_bit_offset > mask_greatest_bit_offset) {
7151 mask_greatest_bit_offset = crumb_end_bit_offset;
7153 composite_bitmask |= (crumb_mask << (64 - crumb_end_bit_offset));
7154 composite_bitmap |= (crumb_value << (64 - crumb_end_bit_offset));
7156 /* Shift left for the next segment */
7157 value <<= crumb_spec[++i].crumb_bit_length;
7160 /* Sign extend for signed types */
7161 switch (hf_field->type) {
7167 if (no_of_bits && (value & (G_GINT64_CONSTANT(1) << (no_of_bits-1))))
7168 value |= (G_GINT64_CONSTANT(-1) << no_of_bits);
7175 *return_value = value;
7178 /* Coast clear. Try and fake it */
7179 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
7181 /* initialise the format string */
7182 bf_str = (char *)ep_alloc(256);
7185 octet_offset = bit_offset >> 3;
7187 /* Round up mask length to nearest octet */
7188 octet_length = ((mask_greatest_bit_offset + 7) >> 3);
7189 mask_greatest_bit_offset = octet_length << 3;
7191 /* As noted above, we currently only produce a bitmap if the crumbs span less than 4 octets of the tvb.
7192 It would be a useful enhancement to eliminate this restriction. */
7193 if (mask_greatest_bit_offset <= 32) {
7194 other_decode_bitfield_value(bf_str,
7195 (guint32)(composite_bitmap >> (64 - mask_greatest_bit_offset)),
7196 (guint32)(composite_bitmask >> (64 - mask_greatest_bit_offset)),
7197 mask_greatest_bit_offset);
7200 switch (hf_field->type) {
7201 case FT_BOOLEAN: /* it is a bit odd to have a boolean encoded as split-bits, but possible, I suppose? */
7203 tfstring = (const true_false_string *) &tfs_true_false;
7204 if (hf_field->strings)
7205 tfstring = (const true_false_string *) hf_field->strings;
7206 return proto_tree_add_boolean_format(tree, hfindex,
7207 tvb, octet_offset, octet_length, (guint32)value,
7209 bf_str, hf_field->name,
7210 (guint32)value ? tfstring->true_string : tfstring->false_string);
7217 pi = proto_tree_add_uint(tree, hfindex, tvb, octet_offset, octet_length, (guint32)value);
7218 fill_label_number(PITEM_FINFO(pi), lbl_str, FALSE);
7225 pi = proto_tree_add_int(tree, hfindex, tvb, octet_offset, octet_length, (gint32)value);
7226 fill_label_number(PITEM_FINFO(pi), lbl_str, TRUE);
7230 pi = proto_tree_add_uint64(tree, hfindex, tvb, octet_offset, octet_length, value);
7231 fill_label_number64(PITEM_FINFO(pi), lbl_str, FALSE);
7235 pi = proto_tree_add_int64(tree, hfindex, tvb, octet_offset, octet_length, (gint64)value);
7236 fill_label_number64(PITEM_FINFO(pi), lbl_str, TRUE);
7240 DISSECTOR_ASSERT_NOT_REACHED();
7244 proto_item_set_text(pi, "%s = %s", bf_str, lbl_str);
7249 proto_tree_add_split_bits_crumb(proto_tree *tree, const int hfindex, tvbuff_t *tvb, const guint bit_offset,
7250 const crumb_spec_t *crumb_spec, guint16 crumb_index)
7252 header_field_info *hfinfo;
7254 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
7255 proto_tree_add_text(tree, tvb,
7257 ((bit_offset + crumb_spec[crumb_index].crumb_bit_length - 1) >> 3) - (bit_offset >> 3) + 1,
7258 "%s crumb %d of %s (decoded above)",
7259 decode_bits_in_field(bit_offset, crumb_spec[crumb_index].crumb_bit_length,
7262 crumb_spec[crumb_index].crumb_bit_length,
7269 proto_tree_add_bits_ret_val(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
7270 const guint bit_offset, const gint no_of_bits,
7271 guint64 *return_value, const guint encoding)
7275 if ((item = _proto_tree_add_bits_ret_val(tree, hfindex, tvb,
7276 bit_offset, no_of_bits,
7277 return_value, encoding))) {
7278 FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_OFFSET(bit_offset));
7279 FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_SIZE(no_of_bits));
7285 _proto_tree_add_bits_format_value(proto_tree *tree, const int hfindex,
7286 tvbuff_t *tvb, const guint bit_offset,
7287 const gint no_of_bits, void *value_ptr,
7295 header_field_info *hf_field;
7297 /* We do not have to return a value, try to fake it as soon as possible */
7298 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
7300 if (hf_field->bitmask != 0) {
7301 REPORT_DISSECTOR_BUG(ep_strdup_printf(
7302 "Incompatible use of proto_tree_add_bits_format_value"
7303 " with field '%s' (%s) with bitmask != 0",
7304 hf_field->abbrev, hf_field->name));
7307 DISSECTOR_ASSERT(no_of_bits > 0);
7309 /* Byte align offset */
7310 offset = bit_offset>>3;
7313 * Calculate the number of octets used to hold the bits
7315 tot_no_bits = ((bit_offset&0x7) + no_of_bits);
7316 length = tot_no_bits>>3;
7317 /* If we are using part of the next octet, increase length by 1 */
7318 if (tot_no_bits & 0x07)
7321 if (no_of_bits < 65) {
7322 value = tvb_get_bits64(tvb, bit_offset, no_of_bits, ENC_BIG_ENDIAN);
7324 DISSECTOR_ASSERT_NOT_REACHED();
7328 str = decode_bits_in_field(bit_offset, no_of_bits, value);
7331 strcat(str, hf_field->name);
7334 * This function does not receive an actual value but a dimensionless pointer to that value.
7335 * For this reason, the type of the header field is examined in order to determine
7336 * what kind of value we should read from this address.
7337 * The caller of this function must make sure that for the specific header field type the address of
7338 * a compatible value is provided.
7340 switch (hf_field->type) {
7342 return proto_tree_add_boolean_format(tree, hfindex, tvb, offset, length, *(guint32 *)value_ptr,
7343 "%s: %s", str, value_str);
7350 return proto_tree_add_uint_format(tree, hfindex, tvb, offset, length, *(guint32 *)value_ptr,
7351 "%s: %s", str, value_str);
7355 return proto_tree_add_uint64_format(tree, hfindex, tvb, offset, length, *(guint64 *)value_ptr,
7356 "%s: %s", str, value_str);
7363 return proto_tree_add_int_format(tree, hfindex, tvb, offset, length, *(gint32 *)value_ptr,
7364 "%s: %s", str, value_str);
7368 return proto_tree_add_int64_format(tree, hfindex, tvb, offset, length, *(gint64 *)value_ptr,
7369 "%s: %s", str, value_str);
7373 return proto_tree_add_float_format(tree, hfindex, tvb, offset, length, *(float *)value_ptr,
7374 "%s: %s", str, value_str);
7378 DISSECTOR_ASSERT_NOT_REACHED();
7385 proto_tree_add_bits_format_value(proto_tree *tree, const int hfindex,
7386 tvbuff_t *tvb, const guint bit_offset,
7387 const gint no_of_bits, void *value_ptr,
7392 if ((item = _proto_tree_add_bits_format_value(tree, hfindex,
7393 tvb, bit_offset, no_of_bits,
7394 value_ptr, value_str))) {
7395 FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_OFFSET(bit_offset));
7396 FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_SIZE(no_of_bits));
7401 #define CREATE_VALUE_STRING(dst,format,ap) \
7402 va_start(ap, format); \
7403 dst = ep_strdup_vprintf(format, ap); \
7407 proto_tree_add_uint_bits_format_value(proto_tree *tree, const int hfindex,
7408 tvbuff_t *tvb, const guint bit_offset,
7409 const gint no_of_bits, guint32 value,
7410 const char *format, ...)
7414 header_field_info *hf_field;
7416 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
7418 switch (hf_field->type) {
7426 DISSECTOR_ASSERT_NOT_REACHED();
7431 CREATE_VALUE_STRING(dst, format, ap);
7433 return proto_tree_add_bits_format_value(tree, hfindex, tvb, bit_offset, no_of_bits, &value, dst);
7437 proto_tree_add_float_bits_format_value(proto_tree *tree, const int hfindex,
7438 tvbuff_t *tvb, const guint bit_offset,
7439 const gint no_of_bits, float value,
7440 const char *format, ...)
7444 header_field_info *hf_field;
7446 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
7448 DISSECTOR_ASSERT(hf_field->type == FT_FLOAT);
7450 CREATE_VALUE_STRING(dst, format, ap);
7452 return proto_tree_add_bits_format_value(tree, hfindex, tvb, bit_offset, no_of_bits, &value, dst);
7456 proto_tree_add_int_bits_format_value(proto_tree *tree, const int hfindex,
7457 tvbuff_t *tvb, const guint bit_offset,
7458 const gint no_of_bits, gint32 value,
7459 const char *format, ...)
7463 header_field_info *hf_field;
7465 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
7467 switch (hf_field->type) {
7475 DISSECTOR_ASSERT_NOT_REACHED();
7480 CREATE_VALUE_STRING(dst, format, ap);
7482 return proto_tree_add_bits_format_value(tree, hfindex, tvb, bit_offset, no_of_bits, &value, dst);
7486 proto_tree_add_boolean_bits_format_value(proto_tree *tree, const int hfindex,
7487 tvbuff_t *tvb, const guint bit_offset,
7488 const gint no_of_bits, guint32 value,
7489 const char *format, ...)
7493 header_field_info *hf_field;
7495 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
7497 DISSECTOR_ASSERT(hf_field->type == FT_BOOLEAN);
7499 CREATE_VALUE_STRING(dst, format, ap);
7501 return proto_tree_add_bits_format_value(tree, hfindex, tvb, bit_offset, no_of_bits, &value, dst);
7505 proto_check_field_name(const gchar *field_name)
7507 return wrs_check_charset(fld_abbrev_chars, field_name);
7511 tree_expanded(int tree_type)
7513 g_assert(tree_type >= 0 && tree_type < num_tree_types);
7514 return tree_is_expanded[tree_type >> 5] & (1 << (tree_type & 31));
7518 tree_expanded_set(int tree_type, gboolean value)
7520 g_assert(tree_type >= 0 && tree_type < num_tree_types);
7523 tree_is_expanded[tree_type >> 5] |= (1 << (tree_type & 31));
7525 tree_is_expanded[tree_type >> 5] &= ~(1 << (tree_type & 31));
7529 * Editor modelines - http://www.wireshark.org/tools/modelines.html
7534 * indent-tabs-mode: t
7537 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
7538 * :indentSize=8:tabSize=8:noTabs=false: