2 * Routines for protocol tree
4 * Wireshark - Network traffic analyzer
5 * By Gerald Combs <gerald@wireshark.org>
6 * Copyright 1998 Gerald Combs
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
32 #include <wsutil/bits_ctz.h>
33 #include <wsutil/bits_count_ones.h>
34 #include <wsutil/sign_ext.h>
36 #include <ftypes/ftypes-int.h>
39 #include "exceptions.h"
40 #include "ptvcursor.h"
42 #include "addr_resolv.h"
45 #include "epan_dissect.h"
48 #include "wmem/wmem.h"
50 #include "asm_utils.h"
51 #include "column-utils.h"
52 #include "to_str-int.h"
54 #include "osi-utils.h"
56 #include "show_exception.h"
58 #include <wsutil/plugins.h>
60 #define SUBTREE_ONCE_ALLOCATION_NUMBER 8
61 #define SUBTREE_MAX_LEVELS 256
62 /* Throw an exception if we exceed this many tree items. */
63 /* XXX - This should probably be a preference */
64 #define MAX_TREE_ITEMS (1 * 1000 * 1000)
67 typedef struct __subtree_lvl {
74 subtree_lvl *pushed_tree;
75 guint8 pushed_tree_index;
76 guint8 pushed_tree_max;
82 #define cVALS(x) (const value_string*)(x)
84 /** See inlined comments.
85 @param tree the tree to append this item to
86 @param hfindex field index
87 @param hfinfo header_field
88 @param free_block a code block to call to free resources if this returns
89 @return the header field matching 'hfinfo' */
90 #define TRY_TO_FAKE_THIS_ITEM_OR_FREE(tree, hfindex, hfinfo, free_block) \
91 /* If this item is not referenced we don't have to do much work \
92 at all but we should still return a node so that field items \
93 below this node (think proto_item_add_subtree()) will still \
94 have somewhere to attach to or else filtering will not work \
95 (they would be ignored since tree would be NULL). \
96 DON'T try to fake a node where PTREE_FINFO(tree) is NULL \
97 since dissectors that want to do proto_item_set_len() or \
98 other operations that dereference this would crash. \
99 We fake FT_PROTOCOL unless some clients have requested us \
106 PTREE_DATA(tree)->count++; \
107 if (PTREE_DATA(tree)->count > MAX_TREE_ITEMS) { \
109 if (getenv("WIRESHARK_ABORT_ON_TOO_MANY_ITEMS") != NULL) \
110 g_error("More than %d items in the tree -- possible infinite loop", MAX_TREE_ITEMS); \
111 /* Let the exception handler add items to the tree */ \
112 PTREE_DATA(tree)->count = 0; \
113 THROW_MESSAGE(DissectorError, \
114 ep_strdup_printf("More than %d items in the tree -- possible infinite loop", MAX_TREE_ITEMS)); \
116 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo); \
117 if (!(PTREE_DATA(tree)->visible)) { \
118 if (PTREE_FINFO(tree)) { \
119 if ((hfinfo->ref_type != HF_REF_TYPE_DIRECT) \
120 && (hfinfo->type != FT_PROTOCOL || \
121 PTREE_DATA(tree)->fake_protocols)) { \
123 /* just return tree back to the caller */\
129 /** See inlined comments.
130 @param tree the tree to append this item to
131 @param hfindex field index
132 @param hfinfo header_field
133 @return the header field matching 'hfinfo' */
134 #define TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo) \
135 TRY_TO_FAKE_THIS_ITEM_OR_FREE(tree, hfindex, hfinfo, ((void)0))
138 /** See inlined comments.
139 @param pi the created protocol item we're about to return */
140 #define TRY_TO_FAKE_THIS_REPR(pi) \
142 if (!(PTREE_DATA(pi)->visible)) { \
143 /* If the tree (GUI) isn't visible it's pointless for us to generate the protocol \
144 * items string representation */ \
147 /* Same as above but returning void */
148 #define TRY_TO_FAKE_THIS_REPR_VOID(pi) \
151 if (!(PTREE_DATA(pi)->visible)) { \
152 /* If the tree (GUI) isn't visible it's pointless for us to generate the protocol \
153 * items string representation */ \
157 static const char *hf_try_val_to_str(guint32 value, const header_field_info *hfinfo);
159 static void label_mark_truncated(char *label_str, gsize name_pos);
160 #define LABEL_MARK_TRUNCATED_START(label_str) label_mark_truncated(label_str, 0)
162 static void fill_label_boolean(field_info *fi, gchar *label_str);
163 static void fill_label_bitfield(field_info *fi, gchar *label_str, gboolean is_signed);
164 static void fill_label_number(field_info *fi, gchar *label_str, gboolean is_signed);
165 static void fill_label_number64(field_info *fi, gchar *label_str, gboolean is_signed);
167 static const char *hfinfo_number_value_format_display(const header_field_info *hfinfo, int display, char buf[32], guint32 value);
168 static const char *hfinfo_number_vals_format(const header_field_info *hfinfo, char buf[32], guint32 value);
169 static const char *hfinfo_number_value_format(const header_field_info *hfinfo, char buf[32], guint32 value);
170 static const char *hfinfo_numeric_value_format(const header_field_info *hfinfo, char buf[32], guint32 value);
172 static const char* hfinfo_uint64_format(const header_field_info *hfinfo);
173 static const char* hfinfo_int64_format(const header_field_info *hfinfo);
176 proto_tree_add_node(proto_tree *tree, field_info *fi);
179 get_hfi_length(header_field_info *hfinfo, tvbuff_t *tvb, const gint start, gint *length,
183 new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
184 const gint start, const gint item_length);
187 proto_tree_add_pi(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
188 gint start, gint *length);
191 proto_tree_set_representation_value(proto_item *pi, const char *format, va_list ap);
193 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap);
196 proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb);
198 proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length);
200 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length);
202 proto_tree_set_bytes_gbytearray(field_info *fi, const GByteArray *value);
204 proto_tree_set_time(field_info *fi, const nstime_t *value_ptr);
206 proto_tree_set_string(field_info *fi, const char* value);
208 proto_tree_set_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length, gint encoding);
210 proto_tree_set_ax25(field_info *fi, const guint8* value);
212 proto_tree_set_ax25_tvb(field_info *fi, tvbuff_t *tvb, gint start);
214 proto_tree_set_vines(field_info *fi, const guint8* value);
216 proto_tree_set_vines_tvb(field_info *fi, tvbuff_t *tvb, gint start);
218 proto_tree_set_ether(field_info *fi, const guint8* value);
220 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start);
222 proto_tree_set_ipxnet(field_info *fi, guint32 value);
224 proto_tree_set_ipv4(field_info *fi, guint32 value);
226 proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr);
228 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
230 proto_tree_set_guid(field_info *fi, const e_guid_t *value_ptr);
232 proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, gint start, const guint encoding);
234 proto_tree_set_oid(field_info *fi, const guint8* value_ptr, gint length);
236 proto_tree_set_oid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
238 proto_tree_set_system_id(field_info *fi, const guint8* value_ptr, gint length);
240 proto_tree_set_system_id_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
242 proto_tree_set_boolean(field_info *fi, guint32 value);
244 proto_tree_set_float(field_info *fi, float value);
246 proto_tree_set_double(field_info *fi, double value);
248 proto_tree_set_uint(field_info *fi, guint32 value);
250 proto_tree_set_int(field_info *fi, gint32 value);
252 proto_tree_set_uint64(field_info *fi, guint64 value);
254 proto_tree_set_eui64(field_info *fi, const guint64 value);
256 proto_tree_set_eui64_tvb(field_info *fi, tvbuff_t *tvb, gint start, const guint encoding);
258 /* Handle type length mismatch (now filterable) expert info */
259 static int proto_type_length_mismatch = -1;
260 static expert_field ei_type_length_mismatch_error = EI_INIT;
261 static expert_field ei_type_length_mismatch_warn = EI_INIT;
262 static void register_type_length_mismatch(void);
264 /* Handle number string decoding errors with expert info */
265 static int proto_number_string_decoding_error = -1;
266 static expert_field ei_number_string_decoding_failed_error = EI_INIT;
267 static expert_field ei_number_string_decoding_erange_error = EI_INIT;
268 static void register_number_string_decoding_error(void);
270 static int proto_register_field_init(header_field_info *hfinfo, const int parent);
272 /* special-case header field used within proto.c */
273 static header_field_info hfi_text_only =
274 { "Text item", "text", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL };
275 int hf_text_only = -1;
277 /* Structure for information about a protocol */
279 const char *name; /* long description */
280 const char *short_name; /* short description */
281 const char *filter_name; /* name of this protocol in filters */
282 GPtrArray *fields; /* fields for this protocol */
283 int proto_id; /* field ID for this protocol */
284 gboolean is_enabled; /* TRUE if protocol is enabled */
285 gboolean can_toggle; /* TRUE if is_enabled can be changed */
286 gboolean is_private; /* TRUE is protocol is private */
289 /* List of all protocols */
290 static GList *protocols = NULL;
292 /* Contains information about a field when a dissector calls
293 * proto_tree_add_item. */
294 #define FIELD_INFO_NEW(pool, fi) fi = wmem_new(pool, field_info)
295 #define FIELD_INFO_FREE(pool, fi) wmem_free(pool, fi)
297 /* Contains the space for proto_nodes. */
298 #define PROTO_NODE_INIT(node) \
299 node->first_child = NULL; \
300 node->last_child = NULL; \
303 #define PROTO_NODE_FREE(pool, node) \
304 wmem_free(pool, node)
306 /* String space for protocol and field items for the GUI */
307 #define ITEM_LABEL_NEW(pool, il) \
308 il = wmem_new(pool, item_label_t);
309 #define ITEM_LABEL_FREE(pool, il) \
312 #define PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo) \
313 if((guint)hfindex >= gpa_hfinfo.len && getenv("WIRESHARK_ABORT_ON_DISSECTOR_BUG")) \
314 g_error("Unregistered hf! index=%d", hfindex); \
315 DISSECTOR_ASSERT_HINT((guint)hfindex < gpa_hfinfo.len, "Unregistered hf!"); \
316 hfinfo = gpa_hfinfo.hfi[hfindex];
318 /* List which stores protocols and fields that have been registered */
319 typedef struct _gpa_hfinfo_t {
321 guint32 allocated_len;
322 header_field_info **hfi;
325 static gpa_hfinfo_t gpa_hfinfo;
327 /* Hash table of abbreviations and IDs */
328 static GHashTable *gpa_name_map = NULL;
329 static header_field_info *same_name_hfinfo;
331 static void save_same_name_hfinfo(gpointer data)
333 same_name_hfinfo = (header_field_info*)data;
336 /* Points to the first element of an array of bits, indexed by
337 a subtree item type; that array element is TRUE if subtrees of
338 an item of that type are to be expanded. */
339 static guint32 *tree_is_expanded;
341 /* Number of elements in that array. */
344 /* Name hashtables for fast detection of duplicate names */
345 static GHashTable* proto_names = NULL;
346 static GHashTable* proto_short_names = NULL;
347 static GHashTable* proto_filter_names = NULL;
350 proto_compare_name(gconstpointer p1_arg, gconstpointer p2_arg)
352 const protocol_t *p1 = (const protocol_t *)p1_arg;
353 const protocol_t *p2 = (const protocol_t *)p2_arg;
355 return g_ascii_strcasecmp(p1->short_name, p2->short_name);
360 * List of dissector plugins.
363 void (*register_protoinfo)(void); /* routine to call to register protocol information */
364 void (*reg_handoff)(void); /* routine to call to register dissector handoff */
367 static GSList *dissector_plugins = NULL;
370 * Callback for each plugin found.
373 check_for_dissector_plugin(GModule *handle)
376 void (*register_protoinfo)(void);
377 void (*reg_handoff)(void);
378 dissector_plugin *plugin;
381 * Do we have a register routine?
383 if (g_module_symbol(handle, "plugin_register", &gp))
384 register_protoinfo = (void (*)(void))gp;
386 register_protoinfo = NULL;
389 * Do we have a reg_handoff routine?
391 if (g_module_symbol(handle, "plugin_reg_handoff", &gp))
392 reg_handoff = (void (*)(void))gp;
397 * If we have neither, we're not a dissector plugin.
399 if (register_protoinfo == NULL && reg_handoff == NULL)
403 * Add this one to the list of dissector plugins.
405 plugin = (dissector_plugin *)g_malloc(sizeof (dissector_plugin));
406 plugin->register_protoinfo = register_protoinfo;
407 plugin->reg_handoff = reg_handoff;
408 dissector_plugins = g_slist_append(dissector_plugins, plugin);
413 register_dissector_plugin(gpointer data, gpointer user_data _U_)
415 dissector_plugin *plugin = (dissector_plugin *)data;
417 if (plugin->register_protoinfo)
418 (plugin->register_protoinfo)();
422 reg_handoff_dissector_plugin(gpointer data, gpointer user_data _U_)
424 dissector_plugin *plugin = (dissector_plugin *)data;
426 if (plugin->reg_handoff)
427 (plugin->reg_handoff)();
431 * Register dissector plugin type.
434 register_dissector_plugin_type(void)
436 add_plugin_type("dissector", check_for_dissector_plugin);
438 #endif /* HAVE_PLUGINS */
440 /* initialize data structures and register protocols and fields */
442 proto_init(void (register_all_protocols_func)(register_cb cb, gpointer client_data),
443 void (register_all_handoffs_func)(register_cb cb, gpointer client_data),
445 gpointer client_data)
449 proto_names = g_hash_table_new_full(g_int_hash, g_int_equal, g_free, NULL);
450 proto_short_names = g_hash_table_new(wrs_str_hash, g_str_equal);
451 proto_filter_names = g_hash_table_new(wrs_str_hash, g_str_equal);
454 gpa_hfinfo.allocated_len = 0;
455 gpa_hfinfo.hfi = NULL;
456 gpa_name_map = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, save_same_name_hfinfo);
458 /* Initialize the ftype subsystem */
461 /* Register one special-case FT_TEXT_ONLY field for use when
462 converting wireshark to new-style proto_tree. These fields
463 are merely strings on the GUI tree; they are not filterable */
464 hf_text_only = proto_register_field_init(&hfi_text_only, -1);
466 /* Register the pseudo-protocols used for exceptions. */
467 register_show_exception();
468 register_type_length_mismatch();
469 register_number_string_decoding_error();
471 /* Have each built-in dissector register its protocols, fields,
472 dissector tables, and dissectors to be called through a
473 handle, and do whatever one-time initialization it needs to
475 register_all_protocols_func(cb, client_data);
478 /* Now call the registration routines for all disssector
481 (*cb)(RA_PLUGIN_REGISTER, NULL, client_data);
482 g_slist_foreach(dissector_plugins, register_dissector_plugin, NULL);
485 /* Now call the "handoff registration" routines of all built-in
486 dissectors; those routines register the dissector in other
487 dissectors' handoff tables, and fetch any dissector handles
489 register_all_handoffs_func(cb, client_data);
492 /* Now do the same with plugins. */
494 (*cb)(RA_PLUGIN_HANDOFF, NULL, client_data);
495 g_slist_foreach(dissector_plugins, reg_handoff_dissector_plugin, NULL);
498 /* sort the protocols by protocol name */
499 protocols = g_list_sort(protocols, proto_compare_name);
501 /* We've assigned all the subtree type values; allocate the array
502 for them, and zero it out. */
503 tree_is_expanded = g_new0(guint32, (num_tree_types/32)+1);
509 /* Free the abbrev/ID GTree */
511 g_hash_table_destroy(gpa_name_map);
516 protocol_t *protocol = (protocol_t *)protocols->data;
517 header_field_info *hfinfo;
518 PROTO_REGISTRAR_GET_NTH(protocol->proto_id, hfinfo);
519 DISSECTOR_ASSERT(protocol->proto_id == hfinfo->id);
521 g_slice_free(header_field_info, hfinfo);
522 g_ptr_array_free(protocol->fields, TRUE);
523 protocols = g_list_remove(protocols, protocol);
528 g_hash_table_destroy(proto_names);
532 if (proto_short_names) {
533 g_hash_table_destroy(proto_short_names);
534 proto_short_names = NULL;
537 if (proto_filter_names) {
538 g_hash_table_destroy(proto_filter_names);
539 proto_filter_names = NULL;
542 if (gpa_hfinfo.allocated_len) {
544 gpa_hfinfo.allocated_len = 0;
545 g_free(gpa_hfinfo.hfi);
546 gpa_hfinfo.hfi = NULL;
548 g_free(tree_is_expanded);
549 tree_is_expanded = NULL;
553 proto_tree_traverse_pre_order(proto_tree *tree, proto_tree_traverse_func func,
556 proto_node *pnode = tree;
560 if (func(pnode, data))
563 child = pnode->first_child;
564 while (child != NULL) {
566 * The routine we call might modify the child, e.g. by
567 * freeing it, so we get the child's successor before
568 * calling that routine.
571 child = current->next;
572 if (proto_tree_traverse_pre_order((proto_tree *)current, func, data))
580 proto_tree_traverse_post_order(proto_tree *tree, proto_tree_traverse_func func,
583 proto_node *pnode = tree;
587 child = pnode->first_child;
588 while (child != NULL) {
590 * The routine we call might modify the child, e.g. by
591 * freeing it, so we get the child's successor before
592 * calling that routine.
595 child = current->next;
596 if (proto_tree_traverse_post_order((proto_tree *)current, func, data))
599 if (func(pnode, data))
606 proto_tree_children_foreach(proto_tree *tree, proto_tree_foreach_func func,
609 proto_node *node = tree;
615 node = node->first_child;
616 while (node != NULL) {
618 node = current->next;
619 func((proto_tree *)current, data);
624 free_GPtrArray_value(gpointer key, gpointer value, gpointer user_data _U_)
626 GPtrArray *ptrs = (GPtrArray *)value;
627 gint hfid = (gint)(long)key;
628 header_field_info *hfinfo;
630 PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
631 if (hfinfo->ref_type != HF_REF_TYPE_NONE) {
632 /* when a field is referenced by a filter this also
633 affects the refcount for the parent protocol so we need
634 to adjust the refcount for the parent as well
636 if (hfinfo->parent != -1) {
637 header_field_info *parent_hfinfo;
638 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
639 parent_hfinfo->ref_type = HF_REF_TYPE_NONE;
641 hfinfo->ref_type = HF_REF_TYPE_NONE;
644 g_ptr_array_free(ptrs, TRUE);
648 proto_tree_free_node(proto_node *node, gpointer data _U_)
650 field_info *finfo = PNODE_FINFO(node);
652 proto_tree_children_foreach(node, proto_tree_free_node, NULL);
654 FVALUE_CLEANUP(&finfo->value);
658 proto_tree_reset(proto_tree *tree)
660 tree_data_t *tree_data = PTREE_DATA(tree);
662 proto_tree_children_foreach(tree, proto_tree_free_node, NULL);
665 if (tree_data->interesting_hfids) {
666 /* Free all the GPtrArray's in the interesting_hfids hash. */
667 g_hash_table_foreach(tree_data->interesting_hfids,
668 free_GPtrArray_value, NULL);
670 /* And then remove all values. */
671 g_hash_table_remove_all(tree_data->interesting_hfids);
674 /* Reset track of the number of children */
675 tree_data->count = 0;
677 PROTO_NODE_INIT(tree);
680 /* frees the resources that the dissection a proto_tree uses */
682 proto_tree_free(proto_tree *tree)
684 tree_data_t *tree_data = PTREE_DATA(tree);
686 proto_tree_children_foreach(tree, proto_tree_free_node, NULL);
689 if (tree_data->interesting_hfids) {
690 /* Free all the GPtrArray's in the interesting_hfids hash. */
691 g_hash_table_foreach(tree_data->interesting_hfids,
692 free_GPtrArray_value, NULL);
694 /* And then destroy the hash. */
695 g_hash_table_destroy(tree_data->interesting_hfids);
698 g_slice_free(tree_data_t, tree_data);
700 g_slice_free(proto_tree, tree);
703 /* Is the parsing being done for a visible proto_tree or an invisible one?
704 * By setting this correctly, the proto_tree creation is sped up by not
705 * having to call g_vsnprintf and copy strings around.
708 proto_tree_set_visible(proto_tree *tree, gboolean visible)
710 gboolean old_visible = PTREE_DATA(tree)->visible;
712 PTREE_DATA(tree)->visible = visible;
718 proto_tree_set_fake_protocols(proto_tree *tree, gboolean fake_protocols)
720 PTREE_DATA(tree)->fake_protocols = fake_protocols;
723 /* Assume dissector set only its protocol fields.
724 This function is called by dissectors and allows the speeding up of filtering
725 in wireshark; if this function returns FALSE it is safe to reset tree to NULL
726 and thus skip calling most of the expensive proto_tree_add_...()
728 If the tree is visible we implicitly assume the field is referenced.
731 proto_field_is_referenced(proto_tree *tree, int proto_id)
733 register header_field_info *hfinfo;
739 if (PTREE_DATA(tree)->visible)
742 PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
743 if (hfinfo->ref_type != HF_REF_TYPE_NONE)
746 if (hfinfo->type == FT_PROTOCOL && !PTREE_DATA(tree)->fake_protocols)
753 /* Finds a record in the hfinfo array by id. */
755 proto_registrar_get_nth(guint hfindex)
757 register header_field_info *hfinfo;
759 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
764 /* Prefix initialization
765 * this allows for a dissector to register a display filter name prefix
766 * so that it can delay the initialization of the hf array as long as
770 /* compute a hash for the part before the dot of a display filter */
772 prefix_hash (gconstpointer key) {
773 /* end the string at the dot and compute its hash */
774 gchar* copy = g_strdup((const gchar *)key);
785 tmp = g_str_hash(copy);
790 /* are both strings equal up to the end or the dot? */
792 prefix_equal (gconstpointer ap, gconstpointer bp) {
793 const gchar* a = (const gchar *)ap;
794 const gchar* b = (const gchar *)bp;
800 if ( (ac == '.' || ac == '\0') && (bc == '.' || bc == '\0') ) return TRUE;
802 if ( (ac == '.' || ac == '\0') && ! (bc == '.' || bc == '\0') ) return FALSE;
803 if ( (bc == '.' || bc == '\0') && ! (ac == '.' || ac == '\0') ) return FALSE;
805 if (ac != bc) return FALSE;
812 /* indexed by prefix, contains initializers */
813 static GHashTable* prefixes = NULL;
816 /* Register a new prefix for "delayed" initialization of field arrays */
818 proto_register_prefix(const char *prefix, prefix_initializer_t pi ) {
820 prefixes = g_hash_table_new(prefix_hash, prefix_equal);
823 g_hash_table_insert(prefixes, (gpointer)prefix, pi);
826 /* helper to call all prefix initializers */
828 initialize_prefix(gpointer k, gpointer v, gpointer u _U_) {
829 ((prefix_initializer_t)v)((const char *)k);
833 /** Initialize every remaining uninitialized prefix. */
835 proto_initialize_all_prefixes(void) {
836 g_hash_table_foreach_remove(prefixes, initialize_prefix, NULL);
839 /* Finds a record in the hfinfo array by name.
840 * If it fails to find it in the already registered fields,
841 * it tries to find and call an initializer in the prefixes
842 * table and if so it looks again.
845 proto_registrar_get_byname(const char *field_name)
847 header_field_info *hfinfo;
848 prefix_initializer_t pi;
853 hfinfo = (header_field_info *)g_hash_table_lookup(gpa_name_map, field_name);
861 if ((pi = (prefix_initializer_t)g_hash_table_lookup(prefixes, field_name) ) != NULL) {
863 g_hash_table_remove(prefixes, field_name);
868 return (header_field_info *)g_hash_table_lookup(gpa_name_map, field_name);
872 proto_registrar_get_id_byname(const char *field_name)
874 header_field_info *hfinfo;
876 hfinfo = proto_registrar_get_byname(field_name);
886 ptvcursor_new_subtree_levels(ptvcursor_t *ptvc)
888 subtree_lvl *pushed_tree;
890 DISSECTOR_ASSERT(ptvc->pushed_tree_max <= SUBTREE_MAX_LEVELS-SUBTREE_ONCE_ALLOCATION_NUMBER);
891 ptvc->pushed_tree_max += SUBTREE_ONCE_ALLOCATION_NUMBER;
893 pushed_tree = (subtree_lvl *)ep_alloc(sizeof(subtree_lvl) * ptvc->pushed_tree_max);
894 DISSECTOR_ASSERT(pushed_tree != NULL);
895 if (ptvc->pushed_tree)
896 memcpy(pushed_tree, ptvc->pushed_tree, ptvc->pushed_tree_max - SUBTREE_ONCE_ALLOCATION_NUMBER);
897 ptvc->pushed_tree = pushed_tree;
901 ptvcursor_free_subtree_levels(ptvcursor_t *ptvc)
903 ptvc->pushed_tree = NULL;
904 ptvc->pushed_tree_max = 0;
905 DISSECTOR_ASSERT(ptvc->pushed_tree_index == 0);
906 ptvc->pushed_tree_index = 0;
909 /* Allocates an initializes a ptvcursor_t with 3 variables:
910 * proto_tree, tvbuff, and offset. */
912 ptvcursor_new(proto_tree *tree, tvbuff_t *tvb, gint offset)
916 ptvc = (ptvcursor_t *)ep_alloc(sizeof(ptvcursor_t));
919 ptvc->offset = offset;
920 ptvc->pushed_tree = NULL;
921 ptvc->pushed_tree_max = 0;
922 ptvc->pushed_tree_index = 0;
927 /* Frees memory for ptvcursor_t, but nothing deeper than that. */
929 ptvcursor_free(ptvcursor_t *ptvc)
931 ptvcursor_free_subtree_levels(ptvc);
935 /* Returns tvbuff. */
937 ptvcursor_tvbuff(ptvcursor_t *ptvc)
942 /* Returns current offset. */
944 ptvcursor_current_offset(ptvcursor_t *ptvc)
950 ptvcursor_tree(ptvcursor_t *ptvc)
959 ptvcursor_set_tree(ptvcursor_t *ptvc, proto_tree *tree)
964 /* creates a subtree, sets it as the working tree and pushes the old working tree */
966 ptvcursor_push_subtree(ptvcursor_t *ptvc, proto_item *it, gint ett_subtree)
968 subtree_lvl *subtree;
969 if (ptvc->pushed_tree_index >= ptvc->pushed_tree_max)
970 ptvcursor_new_subtree_levels(ptvc);
972 subtree = ptvc->pushed_tree + ptvc->pushed_tree_index;
973 subtree->tree = ptvc->tree;
975 ptvc->pushed_tree_index++;
976 return ptvcursor_set_subtree(ptvc, it, ett_subtree);
981 ptvcursor_pop_subtree(ptvcursor_t *ptvc)
983 subtree_lvl *subtree;
985 if (ptvc->pushed_tree_index <= 0)
988 ptvc->pushed_tree_index--;
989 subtree = ptvc->pushed_tree + ptvc->pushed_tree_index;
990 if (subtree->it != NULL)
991 proto_item_set_len(subtree->it, ptvcursor_current_offset(ptvc) - subtree->cursor_offset);
993 ptvc->tree = subtree->tree;
996 /* saves the current tvb offset and the item in the current subtree level */
998 ptvcursor_subtree_set_item(ptvcursor_t *ptvc, proto_item *it)
1000 subtree_lvl *subtree;
1002 DISSECTOR_ASSERT(ptvc->pushed_tree_index > 0);
1004 subtree = ptvc->pushed_tree + ptvc->pushed_tree_index - 1;
1006 subtree->cursor_offset = ptvcursor_current_offset(ptvc);
1009 /* Creates a subtree and adds it to the cursor as the working tree but does not
1010 * save the old working tree */
1012 ptvcursor_set_subtree(ptvcursor_t *ptvc, proto_item *it, gint ett_subtree)
1014 ptvc->tree = proto_item_add_subtree(it, ett_subtree);
1019 ptvcursor_add_subtree_item(ptvcursor_t *ptvc, proto_item *it, gint ett_subtree, gint length)
1021 ptvcursor_push_subtree(ptvc, it, ett_subtree);
1022 if (length == SUBTREE_UNDEFINED_LENGTH)
1023 ptvcursor_subtree_set_item(ptvc, it);
1024 return ptvcursor_tree(ptvc);
1027 /* Add an item to the tree and create a subtree
1028 * If the length is unknown, length may be defined as SUBTREE_UNDEFINED_LENGTH.
1029 * In this case, when the subtree will be closed, the parent item length will
1030 * be equal to the advancement of the cursor since the creation of the subtree.
1033 ptvcursor_add_with_subtree(ptvcursor_t *ptvc, int hfindex, gint length,
1034 const guint encoding, gint ett_subtree)
1038 it = ptvcursor_add_no_advance(ptvc, hfindex, length, encoding);
1039 return ptvcursor_add_subtree_item(ptvc, it, ett_subtree, length);
1043 proto_tree_add_text_node(proto_tree *tree, tvbuff_t *tvb, gint start, gint length);
1045 /* Add a text node to the tree and create a subtree
1046 * If the length is unknown, length may be defined as SUBTREE_UNDEFINED_LENGTH.
1047 * In this case, when the subtree will be closed, the item length will be equal
1048 * to the advancement of the cursor since the creation of the subtree.
1051 ptvcursor_add_text_with_subtree(ptvcursor_t *ptvc, gint length,
1052 gint ett_subtree, const char *format, ...)
1056 header_field_info *hfinfo;
1059 tree = ptvcursor_tree(ptvc);
1061 TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
1063 pi = proto_tree_add_text_node(tree, ptvcursor_tvbuff(ptvc),
1064 ptvcursor_current_offset(ptvc), length);
1066 TRY_TO_FAKE_THIS_REPR(pi);
1068 va_start(ap, format);
1069 proto_tree_set_representation(pi, format, ap);
1072 return ptvcursor_add_subtree_item(ptvc, pi, ett_subtree, length);
1075 /* Add a text-only node, leaving it to our caller to fill the text in */
1077 proto_tree_add_text_node(proto_tree *tree, tvbuff_t *tvb, gint start, gint length)
1084 pi = proto_tree_add_pi(tree, &hfi_text_only, tvb, start, &length);
1089 /* (DEPRECATED) Add a text-only node to the proto_tree */
1091 proto_tree_add_text(proto_tree *tree, tvbuff_t *tvb, gint start, gint length,
1092 const char *format, ...)
1096 header_field_info *hfinfo;
1098 TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
1100 pi = proto_tree_add_text_node(tree, tvb, start, length);
1102 TRY_TO_FAKE_THIS_REPR(pi);
1104 va_start(ap, format);
1105 proto_tree_set_representation(pi, format, ap);
1111 /* (DEPRECATED) Add a text-only node to the proto_tree (va_list version) */
1113 proto_tree_add_text_valist(proto_tree *tree, tvbuff_t *tvb, gint start,
1114 gint length, const char *format, va_list ap)
1117 header_field_info *hfinfo;
1119 TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
1121 pi = proto_tree_add_text_node(tree, tvb, start, length);
1123 TRY_TO_FAKE_THIS_REPR(pi);
1125 proto_tree_set_representation(pi, format, ap);
1130 /* Add a text-only node that creates a subtree underneath.
1131 * proto_tree_add_text + proto_item_add_subtree
1134 proto_tree_add_subtree(proto_tree *tree, tvbuff_t *tvb, gint start, gint length, gint idx, proto_item **tree_item, const char *text)
1136 return proto_tree_add_subtree_format(tree, tvb, start, length, idx, tree_item, "%s", text);
1139 /* Add a text-only node that creates a subtree underneath.
1140 * proto_tree_add_text + proto_item_add_subtree
1143 proto_tree_add_subtree_format(proto_tree *tree, tvbuff_t *tvb, gint start, gint length, gint idx, proto_item **tree_item, const char *format, ...)
1149 va_start(ap, format);
1150 pi = proto_tree_add_text_valist(tree, tvb, start, length, format, ap);
1153 if (tree_item != NULL)
1156 pt = proto_item_add_subtree(pi, idx);
1161 /* Add a text-only node for debugging purposes. The caller doesn't need
1162 * to worry about tvbuff, start, or length. Debug message gets sent to
1165 proto_tree_add_debug_text(proto_tree *tree, const char *format, ...)
1170 pi = proto_tree_add_text_node(tree, NULL, 0, 0);
1173 va_start(ap, format);
1174 proto_tree_set_representation(pi, format, ap);
1177 va_start(ap, format);
1178 vprintf(format, ap);
1186 proto_tree_add_format_text(proto_tree *tree, tvbuff_t *tvb, gint start, gint length)
1189 header_field_info *hfinfo;
1191 TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
1193 pi = proto_tree_add_text_node(tree, tvb, start, length);
1195 TRY_TO_FAKE_THIS_REPR(pi);
1197 proto_item_set_text(pi, "%s", tvb_format_text(tvb, start, length));
1203 proto_tree_add_format_wsp_text(proto_tree *tree, tvbuff_t *tvb, gint start, gint length)
1206 header_field_info *hfinfo;
1208 TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
1210 pi = proto_tree_add_text_node(tree, tvb, start, length);
1212 TRY_TO_FAKE_THIS_REPR(pi);
1214 proto_item_set_text(pi, "%s", tvb_format_text_wsp(tvb, start, length));
1219 void proto_report_dissector_bug(const char *message)
1221 if (getenv("WIRESHARK_ABORT_ON_DISSECTOR_BUG") != NULL)
1224 THROW_MESSAGE(DissectorError, message);
1227 /* We could probably get away with changing is_error to a minimum length value. */
1229 report_type_length_mismatch(proto_tree *tree, const gchar *descr, int length, gboolean is_error) {
1232 expert_add_info_format(NULL, tree, &ei_type_length_mismatch_error, "Trying to fetch %s with length %d", descr, length);
1234 expert_add_info_format(NULL, tree, &ei_type_length_mismatch_warn, "Trying to fetch %s with length %d", descr, length);
1238 THROW(ReportedBoundsError);
1243 get_uint_value(proto_tree *tree, tvbuff_t *tvb, gint offset, gint length, const guint encoding)
1246 gboolean length_error;
1251 value = tvb_get_guint8(tvb, offset);
1255 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letohs(tvb, offset)
1256 : tvb_get_ntohs(tvb, offset);
1260 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letoh24(tvb, offset)
1261 : tvb_get_ntoh24(tvb, offset);
1265 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letohl(tvb, offset)
1266 : tvb_get_ntohl(tvb, offset);
1271 length_error = TRUE;
1274 length_error = FALSE;
1275 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letohl(tvb, offset)
1276 : tvb_get_ntohl(tvb, offset);
1278 report_type_length_mismatch(tree, "an unsigned integer", length, length_error);
1285 * NOTE: to support code written when proto_tree_add_item() took a
1286 * gboolean as its last argument, with FALSE meaning "big-endian"
1287 * and TRUE meaning "little-endian", we treat any non-zero value of
1288 * "encoding" as meaning "little-endian".
1290 static inline guint64
1291 get_uint64_value(proto_tree *tree, tvbuff_t *tvb, gint offset, guint length, const guint encoding)
1294 gboolean length_error;
1299 value = tvb_get_guint8(tvb, offset);
1303 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letohs(tvb, offset)
1304 : tvb_get_ntohs(tvb, offset);
1308 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letoh24(tvb, offset)
1309 : tvb_get_ntoh24(tvb, offset);
1313 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letohl(tvb, offset)
1314 : tvb_get_ntohl(tvb, offset);
1318 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letoh40(tvb, offset)
1319 : tvb_get_ntoh40(tvb, offset);
1323 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letoh48(tvb, offset)
1324 : tvb_get_ntoh48(tvb, offset);
1328 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letoh56(tvb, offset)
1329 : tvb_get_ntoh56(tvb, offset);
1333 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letoh64(tvb, offset)
1334 : tvb_get_ntoh64(tvb, offset);
1339 length_error = TRUE;
1342 length_error = FALSE;
1343 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letoh64(tvb, offset)
1344 : tvb_get_ntoh64(tvb, offset);
1346 report_type_length_mismatch(tree, "an unsigned integer", length, length_error);
1353 * NOTE: to support code written when proto_tree_add_item() took a
1354 * gboolean as its last argument, with FALSE meaning "big-endian"
1355 * and TRUE meaning "little-endian", we treat any non-zero value of
1356 * "encoding" as meaning "little-endian".
1359 get_int_value(proto_tree *tree, tvbuff_t *tvb, gint offset, gint length, const guint encoding)
1362 gboolean length_error;
1367 value = (gint8)tvb_get_guint8(tvb, offset);
1371 value = (gint16) (encoding ? tvb_get_letohs(tvb, offset)
1372 : tvb_get_ntohs(tvb, offset));
1376 value = encoding ? tvb_get_letoh24(tvb, offset)
1377 : tvb_get_ntoh24(tvb, offset);
1378 if (value & 0x00800000) {
1379 /* Sign bit is set; sign-extend it. */
1380 value |= 0xFF000000;
1385 value = encoding ? tvb_get_letohl(tvb, offset)
1386 : tvb_get_ntohl(tvb, offset);
1391 length_error = TRUE;
1394 length_error = FALSE;
1395 value = encoding ? tvb_get_letohl(tvb, offset)
1396 : tvb_get_ntohl(tvb, offset);
1398 report_type_length_mismatch(tree, "a signed integer", length, length_error);
1404 /* Note: this returns an unsigned int64, but with the appropriate bit(s) set to
1405 * be cast-able as a gint64. This is weird, but what the code has always done.
1407 static inline guint64
1408 get_int64_value(proto_tree *tree, tvbuff_t *tvb, gint start, guint length, const guint encoding)
1410 guint64 value = get_uint64_value(tree, tvb, start, length, encoding);
1415 value = ws_sign_ext64(value, 56);
1418 value = ws_sign_ext64(value, 48);
1421 value = ws_sign_ext64(value, 40);
1424 value = ws_sign_ext64(value, 32);
1427 value = ws_sign_ext64(value, 24);
1430 value = ws_sign_ext64(value, 16);
1433 value = ws_sign_ext64(value, 8);
1440 /* this can be called when there is no tree, so don't add that as a param */
1442 get_time_value(tvbuff_t *tvb, const gint start, const gint length, const guint encoding,
1443 nstime_t *time_stamp, const gboolean is_relative)
1448 /* relative timestamps don't do TOD/NTP */
1450 (encoding != (ENC_TIME_TIMESPEC|ENC_BIG_ENDIAN)) &&
1451 (encoding != (ENC_TIME_TIMESPEC|ENC_LITTLE_ENDIAN)) )
1453 /* XXX: I think this should call REPORT_DISSECTOR_BUG(), but
1454 the existing code didn't do that, so I'm not either */
1460 case ENC_TIME_TIMESPEC|ENC_BIG_ENDIAN:
1462 * 4-byte UNIX epoch, possibly followed by
1463 * 4-byte fractional time in nanoseconds,
1466 time_stamp->secs = (time_t)tvb_get_ntohl(tvb, start);
1468 time_stamp->nsecs = tvb_get_ntohl(tvb, start+4);
1470 time_stamp->nsecs = 0;
1473 case ENC_TIME_TIMESPEC|ENC_LITTLE_ENDIAN:
1475 * 4-byte UNIX epoch, possibly followed by
1476 * 4-byte fractional time in nanoseconds,
1477 * both little-endian.
1479 time_stamp->secs = (time_t)tvb_get_letohl(tvb, start);
1481 time_stamp->nsecs = tvb_get_letohl(tvb, start+4);
1483 time_stamp->nsecs = 0;
1486 case ENC_TIME_TOD|ENC_BIG_ENDIAN:
1488 * TOD time stamp, big-endian.
1490 /* XXX - where should this go? */
1491 #define TOD_BASETIME G_GUINT64_CONSTANT(2208988800)
1493 todsecs = tvb_get_ntoh64(tvb, start) >> 12;
1494 time_stamp->secs = (time_t)((todsecs / 1000000) - TOD_BASETIME);
1495 time_stamp->nsecs = (int)((todsecs % 1000000) * 1000);
1498 case ENC_TIME_TOD|ENC_LITTLE_ENDIAN:
1500 * TOD time stamp, big-endian.
1502 todsecs = tvb_get_letoh64(tvb, start) >> 12 ;
1503 time_stamp->secs = (time_t)((todsecs / 1000000) - TOD_BASETIME);
1504 time_stamp->nsecs = (int)((todsecs % 1000000) * 1000);
1507 case ENC_TIME_NTP|ENC_BIG_ENDIAN:
1509 * NTP time stamp, big-endian.
1512 /* XXX - where should this go? */
1513 #define NTP_BASETIME G_GUINT64_CONSTANT(2208988800)
1515 /* We need a temporary variable here so the unsigned math
1516 * works correctly (for years > 2036 according to RFC 2030
1519 tmpsecs = tvb_get_ntohl(tvb, start);
1521 time_stamp->secs = (time_t)(tmpsecs - (guint32)NTP_BASETIME);
1523 time_stamp->secs = tmpsecs; /* 0 */
1527 * We're using nanoseconds here (and we will
1528 * display nanoseconds), but NTP's timestamps
1529 * have a precision in microseconds or greater.
1530 * Round to 1 microsecond.
1532 time_stamp->nsecs = (int)(1000000*(tvb_get_ntohl(tvb, start+4)/4294967296.0));
1533 time_stamp->nsecs *= 1000;
1535 time_stamp->nsecs = 0;
1539 case ENC_TIME_NTP|ENC_LITTLE_ENDIAN:
1541 * NTP time stamp, big-endian.
1543 tmpsecs = tvb_get_letohl(tvb, start);
1545 time_stamp->secs = (time_t)(tmpsecs - (guint32)NTP_BASETIME);
1547 time_stamp->secs = tmpsecs; /* 0 */
1551 * We're using nanoseconds here (and we will
1552 * display nanoseconds), but NTP's timestamps
1553 * have a precision in microseconds or greater.
1554 * Round to 1 microsecond.
1556 time_stamp->nsecs = (int)(1000000*(tvb_get_letohl(tvb, start+4)/4294967296.0));
1557 time_stamp->nsecs *= 1000;
1559 time_stamp->nsecs = 0;
1564 DISSECTOR_ASSERT_NOT_REACHED();
1570 tree_data_add_maybe_interesting_field(tree_data_t *tree_data, field_info *fi)
1572 const header_field_info *hfinfo = fi->hfinfo;
1574 if (hfinfo->ref_type == HF_REF_TYPE_DIRECT) {
1575 GPtrArray *ptrs = NULL;
1577 if (tree_data->interesting_hfids == NULL) {
1578 /* Initialize the hash because we now know that it is needed */
1579 tree_data->interesting_hfids =
1580 g_hash_table_new(g_direct_hash, NULL /* g_direct_equal */);
1581 } else if (g_hash_table_size(tree_data->interesting_hfids)) {
1582 ptrs = (GPtrArray *)g_hash_table_lookup(tree_data->interesting_hfids,
1583 GINT_TO_POINTER(hfinfo->id));
1587 /* First element triggers the creation of pointer array */
1588 ptrs = g_ptr_array_new();
1589 g_hash_table_insert(tree_data->interesting_hfids,
1590 GINT_TO_POINTER(hfinfo->id), ptrs);
1593 g_ptr_array_add(ptrs, fi);
1597 /* Add an item to a proto_tree, using the text label registered to that item;
1598 the item is extracted from the tvbuff handed to it. */
1600 proto_tree_new_item(field_info *new_fi, proto_tree *tree,
1601 tvbuff_t *tvb, gint start, gint length,
1609 nstime_t time_stamp;
1610 gboolean length_error;
1612 switch (new_fi->hfinfo->type) {
1614 /* no value to set for FT_NONE */
1618 proto_tree_set_protocol_tvb(new_fi, tvb);
1622 proto_tree_set_bytes_tvb(new_fi, tvb, start, length);
1627 * Map all non-zero values to little-endian for
1628 * backwards compatibility.
1631 encoding = ENC_LITTLE_ENDIAN;
1632 n = get_uint_value(tree, tvb, start, length, encoding);
1633 proto_tree_set_bytes_tvb(new_fi, tvb, start + length, n);
1635 /* Instead of calling proto_item_set_len(), since we don't yet
1636 * have a proto_item, we set the field_info's length ourselves. */
1637 new_fi->length = n + length;
1642 * Map all non-zero values to little-endian for
1643 * backwards compatibility.
1646 encoding = ENC_LITTLE_ENDIAN;
1647 proto_tree_set_boolean(new_fi,
1648 get_uint_value(tree, tvb, start, length, encoding));
1651 /* XXX - make these just FT_UINT? */
1657 * Map all non-zero values to little-endian for
1658 * backwards compatibility.
1661 encoding = ENC_LITTLE_ENDIAN;
1662 proto_tree_set_uint(new_fi,
1663 get_uint_value(tree, tvb, start, length, encoding));
1668 * Map all non-zero values to little-endian for
1669 * backwards compatibility.
1672 encoding = ENC_LITTLE_ENDIAN;
1673 proto_tree_set_uint64(new_fi,
1674 get_uint64_value(tree, tvb, start, length, encoding));
1677 /* XXX - make these just FT_INT? */
1683 * Map all non-zero values to little-endian for
1684 * backwards compatibility.
1687 encoding = ENC_LITTLE_ENDIAN;
1688 proto_tree_set_int(new_fi,
1689 get_int_value(tree, tvb, start, length, encoding));
1694 * Map all non-zero values to little-endian for
1695 * backwards compatibility.
1698 encoding = ENC_LITTLE_ENDIAN;
1699 proto_tree_set_uint64(new_fi,
1700 get_int64_value(tree, tvb, start, length, encoding));
1705 * Map all non-zero values to little-endian for
1706 * backwards compatibility.
1709 encoding = ENC_LITTLE_ENDIAN;
1710 if (length != FT_IPv4_LEN) {
1711 length_error = length < FT_IPv4_LEN ? TRUE : FALSE;
1712 report_type_length_mismatch(tree, "an IPv4 address", length, length_error);
1714 value = tvb_get_ipv4(tvb, start);
1716 * NOTE: to support code written when
1717 * proto_tree_add_item() took a gboolean as its
1718 * last argument, with FALSE meaning "big-endian"
1719 * and TRUE meaning "little-endian", we treat any
1720 * non-zero value of "encoding" as meaning
1723 proto_tree_set_ipv4(new_fi, encoding ? GUINT32_SWAP_LE_BE(value) : value);
1727 if (length != FT_IPXNET_LEN) {
1728 length_error = length < FT_IPXNET_LEN ? TRUE : FALSE;
1729 report_type_length_mismatch(tree, "an IPXNET address", length, length_error);
1731 proto_tree_set_ipxnet(new_fi,
1732 get_uint_value(tree, tvb, start, FT_IPXNET_LEN, ENC_BIG_ENDIAN));
1736 if (length != FT_IPv6_LEN) {
1737 length_error = length < FT_IPv6_LEN ? TRUE : FALSE;
1738 report_type_length_mismatch(tree, "an IPv6 address", length, length_error);
1740 proto_tree_set_ipv6_tvb(new_fi, tvb, start, length);
1745 length_error = length < 7 ? TRUE : FALSE;
1746 report_type_length_mismatch(tree, "an AX.25 address", length, length_error);
1748 proto_tree_set_ax25_tvb(new_fi, tvb, start);
1752 if (length != VINES_ADDR_LEN) {
1753 length_error = length < VINES_ADDR_LEN ? TRUE : FALSE;
1754 report_type_length_mismatch(tree, "a Vines address", length, length_error);
1756 proto_tree_set_vines_tvb(new_fi, tvb, start);
1760 if (length != FT_ETHER_LEN) {
1761 length_error = length < FT_ETHER_LEN ? TRUE : FALSE;
1762 report_type_length_mismatch(tree, "a MAC address", length, length_error);
1764 proto_tree_set_ether_tvb(new_fi, tvb, start);
1769 * Map all non-zero values to little-endian for
1770 * backwards compatibility.
1773 encoding = ENC_LITTLE_ENDIAN;
1774 if (length != FT_EUI64_LEN) {
1775 length_error = length < FT_EUI64_LEN ? TRUE : FALSE;
1776 report_type_length_mismatch(tree, "an EUI-64 address", length, length_error);
1778 proto_tree_set_eui64_tvb(new_fi, tvb, start, encoding);
1782 * Map all non-zero values to little-endian for
1783 * backwards compatibility.
1786 encoding = ENC_LITTLE_ENDIAN;
1787 if (length != FT_GUID_LEN) {
1788 length_error = length < FT_GUID_LEN ? TRUE : FALSE;
1789 report_type_length_mismatch(tree, "a GUID", length, length_error);
1791 proto_tree_set_guid_tvb(new_fi, tvb, start, encoding);
1796 proto_tree_set_oid_tvb(new_fi, tvb, start, length);
1800 proto_tree_set_system_id_tvb(new_fi, tvb, start, length);
1805 * NOTE: to support code written when
1806 * proto_tree_add_item() took a gboolean as its
1807 * last argument, with FALSE meaning "big-endian"
1808 * and TRUE meaning "little-endian", we treat any
1809 * non-zero value of "encoding" as meaning
1812 * At some point in the future, we might
1813 * support non-IEEE-binary floating-point
1814 * formats in the encoding as well
1815 * (IEEE decimal, System/3x0, VAX).
1818 encoding = ENC_LITTLE_ENDIAN;
1820 length_error = length < 4 ? TRUE : FALSE;
1821 report_type_length_mismatch(tree, "a single-precision floating point number", length, length_error);
1824 floatval = tvb_get_letohieee_float(tvb, start);
1826 floatval = tvb_get_ntohieee_float(tvb, start);
1827 proto_tree_set_float(new_fi, floatval);
1832 * NOTE: to support code written when
1833 * proto_tree_add_item() took a gboolean as its
1834 * last argument, with FALSE meaning "big-endian"
1835 * and TRUE meaning "little-endian", we treat any
1836 * non-zero value of "encoding" as meaning
1839 * At some point in the future, we might
1840 * support non-IEEE-binary floating-point
1841 * formats in the encoding as well
1842 * (IEEE decimal, System/3x0, VAX).
1844 if (encoding == TRUE)
1845 encoding = ENC_LITTLE_ENDIAN;
1847 length_error = length < 8 ? TRUE : FALSE;
1848 report_type_length_mismatch(tree, "a double-precision floating point number", length, length_error);
1851 doubleval = tvb_get_letohieee_double(tvb, start);
1853 doubleval = tvb_get_ntohieee_double(tvb, start);
1854 proto_tree_set_double(new_fi, doubleval);
1858 proto_tree_set_string_tvb(new_fi, tvb, start, length,
1864 report_type_length_mismatch(tree, "a string", length, TRUE);
1866 /* Instead of calling proto_item_set_len(),
1867 * since we don't yet have a proto_item, we
1868 * set the field_info's length ourselves.
1870 * XXX - our caller can't use that length to
1871 * advance an offset unless they arrange that
1872 * there always be a protocol tree into which
1873 * we're putting this item.
1876 /* This can throw an exception */
1877 string = tvb_get_stringz_enc(wmem_packet_scope(), tvb, start, &length, encoding);
1878 } else if (length == 0) {
1881 /* In this case, length signifies
1882 * the length of the string.
1884 * This could either be a null-padded
1885 * string, which doesn't necessarily
1886 * have a '\0' at the end, or a
1887 * null-terminated string, with a
1888 * trailing '\0'. (Yes, there are
1889 * cases where you have a string
1890 * that's both counted and null-
1893 * In the first case, we must
1894 * allocate a buffer of length
1895 * "length+1", to make room for
1898 * In the second case, we don't
1899 * assume that there is a trailing
1900 * '\0' there, as the packet might
1901 * be malformed. (XXX - should we
1902 * throw an exception if there's no
1903 * trailing '\0'?) Therefore, we
1904 * allocate a buffer of length
1905 * "length+1", and put in a trailing
1906 * '\0', just to be safe.
1908 * (XXX - this would change if
1909 * we made string values counted
1910 * rather than null-terminated.)
1912 string = tvb_get_string_enc(wmem_packet_scope(), tvb, start, length, encoding);
1914 new_fi->length = length;
1915 proto_tree_set_string(new_fi, string);
1918 case FT_UINT_STRING:
1920 * NOTE: to support code written when
1921 * proto_tree_add_item() took a gboolean as its
1922 * last argument, with FALSE meaning "big-endian"
1923 * and TRUE meaning "little-endian", if the
1924 * encoding value is TRUE, treat that as
1925 * ASCII with a little-endian length.
1927 * This won't work for code that passes
1928 * arbitrary non-zero values; that code
1929 * will need to be fixed.
1931 if (encoding == TRUE)
1932 encoding = ENC_ASCII|ENC_LITTLE_ENDIAN;
1933 n = get_uint_value(tree, tvb, start, length, encoding & ~ENC_CHARENCODING_MASK);
1934 proto_tree_set_string_tvb(new_fi, tvb, start + length, n,
1937 /* Instead of calling proto_item_set_len(), since we
1938 * don't yet have a proto_item, we set the
1939 * field_info's length ourselves.
1941 * XXX - our caller can't use that length to
1942 * advance an offset unless they arrange that
1943 * there always be a protocol tree into which
1944 * we're putting this item.
1946 new_fi->length = n + length;
1951 * XXX - currently, string values are null-
1952 * terminated, so a "zero-padded" string
1953 * isn't special. If we represent string
1954 * values as something that includes a counted
1955 * array of bytes, we'll need to strip
1958 proto_tree_set_string_tvb(new_fi, tvb, start, length,
1962 case FT_ABSOLUTE_TIME:
1964 * Absolute times can be in any of a number of
1965 * formats, and they can be big-endian or
1968 * Historically FT_TIMEs were only timespecs;
1969 * the only question was whether they were stored
1970 * in big- or little-endian format.
1972 * For backwards compatibility, we interpret an
1973 * encoding of 1 as meaning "little-endian timespec",
1974 * so that passing TRUE is interpreted as that.
1976 if (encoding == TRUE)
1977 encoding = ENC_TIME_TIMESPEC|ENC_LITTLE_ENDIAN;
1979 if (length != 8 && length != 4) {
1980 length_error = length < 4 ? TRUE : FALSE;
1981 report_type_length_mismatch(tree, "an absolute time value", length, length_error);
1984 get_time_value(tvb, start, length, encoding, &time_stamp, FALSE);
1986 proto_tree_set_time(new_fi, &time_stamp);
1989 case FT_RELATIVE_TIME:
1991 * Relative times can be in any of a number of
1992 * formats, and they can be big-endian or
1995 * Historically FT_TIMEs were only timespecs;
1996 * the only question was whether they were stored
1997 * in big- or little-endian format.
1999 * For backwards compatibility, we interpret an
2000 * encoding of 1 as meaning "little-endian timespec",
2001 * so that passing TRUE is interpreted as that.
2003 if (encoding == TRUE)
2004 encoding = ENC_TIME_TIMESPEC|ENC_LITTLE_ENDIAN;
2006 if (length != 8 && length != 4) {
2007 length_error = length < 4 ? TRUE : FALSE;
2008 report_type_length_mismatch(tree, "a relative time value", length, length_error);
2011 get_time_value(tvb, start, length, encoding, &time_stamp, TRUE);
2013 proto_tree_set_time(new_fi, &time_stamp);
2017 g_error("new_fi->hfinfo->type %d (%s) not handled\n",
2018 new_fi->hfinfo->type,
2019 ftype_name(new_fi->hfinfo->type));
2020 DISSECTOR_ASSERT_NOT_REACHED();
2023 FI_SET_FLAG(new_fi, (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN);
2025 /* Don't add new node to proto_tree until now so that any exceptions
2026 * raised by a tvbuff access method doesn't leave junk in the proto_tree. */
2027 /* XXX. wouldn't be better to add this item to tree, with some special flag (FI_EXCEPTION?)
2028 * to know which item caused exception? */
2029 pi = proto_tree_add_node(tree, new_fi);
2034 /* Gets data from tvbuff, adds it to proto_tree, increments offset,
2035 and returns proto_item* */
2037 ptvcursor_add(ptvcursor_t *ptvc, int hfindex, gint length,
2038 const guint encoding)
2041 header_field_info *hfinfo;
2046 /* We can't fake it just yet. We have to advance the cursor
2047 TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfindex, hfinfo); */
2049 offset = ptvc->offset;
2050 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2051 get_hfi_length(hfinfo, ptvc->tvb, offset, &length, &item_length);
2052 ptvc->offset += length;
2053 if (hfinfo->type == FT_UINT_BYTES || hfinfo->type == FT_UINT_STRING) {
2055 * The length of the rest of the item is in the first N
2056 * bytes of the item.
2058 n = get_uint_value(ptvc->tree, ptvc->tvb, offset, length, encoding);
2062 /* Coast clear. Try and fake it */
2063 TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfindex, hfinfo);
2065 new_fi = new_field_info(ptvc->tree, hfinfo, ptvc->tvb, offset, item_length);
2067 return proto_tree_new_item(new_fi, ptvc->tree, ptvc->tvb,
2068 offset, length, encoding);
2072 * Validates that field length bytes are available starting from
2073 * start (pos/neg). Throws an exception if they aren't.
2076 test_length(header_field_info *hfinfo, tvbuff_t *tvb,
2077 gint start, gint length)
2084 if (hfinfo->type == FT_STRINGZ) {
2085 /* If we're fetching until the end of the TVB, only validate
2086 * that the offset is within range.
2092 tvb_ensure_bytes_exist(tvb, start, size);
2095 /* Add an item to a proto_tree, using the text label registered to that item;
2096 the item is extracted from the tvbuff handed to it. */
2098 proto_tree_add_item_new(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
2099 const gint start, gint length, const guint encoding)
2104 DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");
2106 get_hfi_length(hfinfo, tvb, start, &length, &item_length);
2107 test_length(hfinfo, tvb, start, item_length);
2109 TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
2111 new_fi = new_field_info(tree, hfinfo, tvb, start, item_length);
2116 return proto_tree_new_item(new_fi, tree, tvb, start, length, encoding);
2120 proto_tree_add_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2121 const gint start, gint length, const guint encoding)
2123 register header_field_info *hfinfo;
2125 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2126 return proto_tree_add_item_new(tree, hfinfo, tvb, start, length, encoding);
2129 /* which FT_ types can use proto_tree_add_bytes_item() */
2130 static inline gboolean
2131 validate_proto_tree_add_bytes_ftype(const enum ftenum type)
2133 return (type == FT_BYTES ||
2134 type == FT_UINT_BYTES ||
2136 type == FT_REL_OID ||
2137 type == FT_SYSTEM_ID );
2140 /* Note: this does no validation that the byte array of an FT_OID or
2141 FT_REL_OID is actually valid; and neither does proto_tree_add_item(),
2142 so I think it's ok to continue not validating it?
2145 proto_tree_add_bytes_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2146 const gint start, gint length, const guint encoding,
2147 GByteArray *retval, gint *endoff, gint *err)
2150 GByteArray *bytes = retval;
2151 GByteArray *created_bytes = NULL;
2154 header_field_info *hfinfo;
2155 gboolean generate = (bytes || tree) ? TRUE : FALSE;
2157 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2159 DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");
2161 DISSECTOR_ASSERT_HINT(validate_proto_tree_add_bytes_ftype(hfinfo->type),
2162 "Called proto_tree_add_bytes_item but not a bytes-based FT_XXX type");
2164 /* length has to be -1 or > 0 regardless of encoding */
2165 /* invalid FT_UINT_BYTES length is caught in get_uint_value() */
2166 if (length < -1 || length == 0) {
2167 REPORT_DISSECTOR_BUG(wmem_strdup_printf(wmem_packet_scope(),
2168 "Invalid length %d passed to proto_tree_add_bytes_item for %s",
2169 length, ftype_name(hfinfo->type)));
2172 if (encoding & ENC_STR_NUM) {
2173 REPORT_DISSECTOR_BUG("Decoding number strings for byte arrays is not supported");
2176 if (generate && (encoding & ENC_STR_HEX)) {
2177 if (hfinfo->type == FT_UINT_BYTES) {
2178 /* can't decode FT_UINT_BYTES from strings */
2179 REPORT_DISSECTOR_BUG("proto_tree_add_bytes_item called for "
2180 "FT_UINT_BYTES type, but as ENC_STR_HEX");
2184 /* caller doesn't care about return value, but we need it to
2185 call tvb_get_string_bytes() and set the tree later */
2186 bytes = created_bytes = g_byte_array_new();
2189 /* bytes might be NULL after this, but can't add expert error until later */
2190 bytes = tvb_get_string_bytes(tvb, start, length, encoding, bytes, endoff);
2192 /* grab the errno now before it gets overwritten */
2195 else if (generate) {
2196 tvb_ensure_bytes_exist(tvb, start, length);
2199 /* caller doesn't care about return value, but we need it to
2200 call tvb_get_string_bytes() and set the tree later */
2201 bytes = created_bytes = g_byte_array_new();
2204 if (hfinfo->type == FT_UINT_BYTES) {
2205 n = length; /* n is now the "header" length */
2206 length = get_uint_value(tree, tvb, start, n, encoding);
2207 /* length is now the value's length; only store the value in the array */
2208 g_byte_array_append(bytes, tvb_get_ptr(tvb, start + n, length), length);
2210 else if (length > 0) {
2211 g_byte_array_append(bytes, tvb_get_ptr(tvb, start, length), length);
2215 *endoff = start + n + length;
2218 if (err) *err = saved_err;
2220 TRY_TO_FAKE_THIS_ITEM_OR_FREE(tree, hfinfo->id, hfinfo,
2223 g_byte_array_free(created_bytes, TRUE);
2224 created_bytes = NULL;
2228 /* n will be zero except when it's a FT_UINT_BYTES */
2229 new_fi = new_field_info(tree, hfinfo, tvb, start, n + length);
2234 if (encoding & ENC_STRING) {
2235 if (saved_err == ERANGE)
2236 expert_add_info(NULL, tree, &ei_number_string_decoding_erange_error);
2237 else if (!bytes || saved_err != 0)
2238 expert_add_info(NULL, tree, &ei_number_string_decoding_failed_error);
2241 proto_tree_set_bytes_gbytearray(new_fi, bytes);
2244 g_byte_array_free(created_bytes, TRUE);
2247 /* n will be zero except when it's a FT_UINT_BYTES */
2248 proto_tree_set_bytes_tvb(new_fi, tvb, start + n, length);
2251 (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN);
2254 return proto_tree_add_node(tree, new_fi);
2259 proto_tree_add_time_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2260 const gint start, gint length, const guint encoding,
2261 nstime_t *retval, gint *endoff, gint *err)
2264 nstime_t time_stamp;
2266 header_field_info *hfinfo;
2268 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2270 DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");
2272 DISSECTOR_ASSERT_HINT((hfinfo->type == FT_ABSOLUTE_TIME ||
2273 hfinfo->type == FT_RELATIVE_TIME),
2274 "Called proto_tree_add_time_item but not a FT_XXX_TIME");
2276 /* length has to be -1 or > 0 regardless of encoding */
2277 if (length < -1 || length == 0) {
2278 REPORT_DISSECTOR_BUG(wmem_strdup_printf(wmem_packet_scope(),
2279 "Invalid length %d passed to proto_tree_add_time_item", length));
2282 time_stamp.secs = 0;
2283 time_stamp.nsecs = 0;
2285 if (encoding & ENC_STR_TIME_MASK) {
2286 tvb_get_string_time(tvb, start, length, encoding, &time_stamp, endoff);
2287 /* grab the errno now before it gets overwritten */
2291 const gboolean is_relative = (hfinfo->type == FT_RELATIVE_TIME) ? TRUE : FALSE;
2293 if (length != 8 && length != 4) {
2294 const gboolean length_error = length < 4 ? TRUE : FALSE;
2296 report_type_length_mismatch(tree, "a relative time value", length, length_error);
2298 report_type_length_mismatch(tree, "an absolute time value", length, length_error);
2301 tvb_ensure_bytes_exist(tvb, start, length);
2302 get_time_value(tvb, start, length, encoding, &time_stamp, is_relative);
2303 if (endoff) *endoff = length;
2306 if (err) *err = saved_err;
2309 retval->secs = time_stamp.secs;
2310 retval->nsecs = time_stamp.nsecs;
2313 TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
2315 new_fi = new_field_info(tree, hfinfo, tvb, start, length);
2320 proto_tree_set_time(new_fi, &time_stamp);
2322 if (encoding & ENC_STRING) {
2323 if (saved_err == ERANGE)
2324 expert_add_info(NULL, tree, &ei_number_string_decoding_erange_error);
2325 else if (saved_err == EDOM)
2326 expert_add_info(NULL, tree, &ei_number_string_decoding_failed_error);
2330 (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN);
2333 return proto_tree_add_node(tree, new_fi);
2336 /* Add a FT_NONE to a proto_tree */
2338 proto_tree_add_none_format(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
2339 const gint start, gint length, const char *format,
2344 header_field_info *hfinfo;
2346 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2348 DISSECTOR_ASSERT(hfinfo->type == FT_NONE);
2350 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
2352 TRY_TO_FAKE_THIS_REPR(pi);
2354 va_start(ap, format);
2355 proto_tree_set_representation(pi, format, ap);
2358 /* no value to set for FT_NONE */
2362 /* Gets data from tvbuff, adds it to proto_tree, *DOES NOT* increment
2363 * offset, and returns proto_item* */
2365 ptvcursor_add_no_advance(ptvcursor_t* ptvc, int hf, gint length,
2366 const guint encoding)
2370 item = proto_tree_add_item(ptvc->tree, hf, ptvc->tvb, ptvc->offset,
2376 /* Advance the ptvcursor's offset within its tvbuff without
2377 * adding anything to the proto_tree. */
2379 ptvcursor_advance(ptvcursor_t* ptvc, gint length)
2381 ptvc->offset += length;
2386 proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb)
2388 fvalue_set_tvbuff(&fi->value, tvb);
2391 /* Add a FT_PROTOCOL to a proto_tree */
2393 proto_tree_add_protocol_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2394 gint start, gint length, const char *format, ...)
2398 header_field_info *hfinfo;
2400 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2402 DISSECTOR_ASSERT(hfinfo->type == FT_PROTOCOL);
2404 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
2406 proto_tree_set_protocol_tvb(PNODE_FINFO(pi), (start == 0 ? tvb : tvb_new_subset_length(tvb, start, length)));
2408 TRY_TO_FAKE_THIS_REPR(pi);
2410 va_start(ap, format);
2411 proto_tree_set_representation(pi, format, ap);
2418 /* Add a FT_BYTES to a proto_tree */
2420 proto_tree_add_bytes(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2421 gint length, const guint8 *start_ptr)
2424 header_field_info *hfinfo;
2427 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2428 get_hfi_length(hfinfo, tvb, start, &length, &item_length);
2429 test_length(hfinfo, tvb, start, item_length);
2431 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2433 DISSECTOR_ASSERT(hfinfo->type == FT_BYTES);
2435 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
2436 proto_tree_set_bytes(PNODE_FINFO(pi), start_ptr, length);
2442 proto_tree_add_bytes_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2443 gint start, gint length,
2444 const guint8 *start_ptr,
2445 const char *format, ...)
2449 header_field_info *hfinfo;
2452 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2453 get_hfi_length(hfinfo, tvb, start, &length, &item_length);
2454 test_length(hfinfo, tvb, start, item_length);
2456 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2459 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length,
2462 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length,
2463 tvb_get_ptr(tvb, start, length));
2465 va_start(ap, format);
2466 proto_tree_set_representation_value(pi, format, ap);
2473 proto_tree_add_bytes_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2474 gint start, gint length, const guint8 *start_ptr,
2475 const char *format, ...)
2479 header_field_info *hfinfo;
2482 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2483 get_hfi_length(hfinfo, tvb, start, &length, &item_length);
2484 test_length(hfinfo, tvb, start, item_length);
2486 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2489 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length,
2492 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length,
2493 tvb_get_ptr(tvb, start, length));
2495 TRY_TO_FAKE_THIS_REPR(pi);
2497 va_start(ap, format);
2498 proto_tree_set_representation(pi, format, ap);
2505 proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length)
2509 DISSECTOR_ASSERT(start_ptr != NULL || length == 0);
2511 bytes = g_byte_array_new();
2513 g_byte_array_append(bytes, start_ptr, length);
2515 fvalue_set_byte_array(&fi->value, bytes);
2520 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length)
2522 proto_tree_set_bytes(fi, tvb_get_ptr(tvb, offset, length), length);
2526 proto_tree_set_bytes_gbytearray(field_info *fi, const GByteArray *value)
2530 DISSECTOR_ASSERT(value != NULL);
2532 bytes = byte_array_dup(value);
2534 fvalue_set_byte_array(&fi->value, bytes);
2537 /* Add a FT_*TIME to a proto_tree */
2539 proto_tree_add_time(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2540 gint length, const nstime_t *value_ptr)
2543 header_field_info *hfinfo;
2545 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2547 DISSECTOR_ASSERT(hfinfo->type == FT_ABSOLUTE_TIME ||
2548 hfinfo->type == FT_RELATIVE_TIME);
2550 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
2551 proto_tree_set_time(PNODE_FINFO(pi), value_ptr);
2557 proto_tree_add_time_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2558 gint start, gint length, nstime_t *value_ptr,
2559 const char *format, ...)
2564 pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
2566 va_start(ap, format);
2567 proto_tree_set_representation_value(pi, format, ap);
2575 proto_tree_add_time_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2576 gint start, gint length, nstime_t *value_ptr,
2577 const char *format, ...)
2582 pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
2584 TRY_TO_FAKE_THIS_REPR(pi);
2586 va_start(ap, format);
2587 proto_tree_set_representation(pi, format, ap);
2594 /* Set the FT_*TIME value */
2596 proto_tree_set_time(field_info *fi, const nstime_t *value_ptr)
2598 DISSECTOR_ASSERT(value_ptr != NULL);
2600 fvalue_set_time(&fi->value, value_ptr);
2603 /* Add a FT_IPXNET to a proto_tree */
2605 proto_tree_add_ipxnet(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2606 gint length, guint32 value)
2609 header_field_info *hfinfo;
2611 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2613 DISSECTOR_ASSERT(hfinfo->type == FT_IPXNET);
2615 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
2616 proto_tree_set_ipxnet(PNODE_FINFO(pi), value);
2622 proto_tree_add_ipxnet_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2623 gint start, gint length, guint32 value,
2624 const char *format, ...)
2629 pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
2631 va_start(ap, format);
2632 proto_tree_set_representation_value(pi, format, ap);
2640 proto_tree_add_ipxnet_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2641 gint start, gint length, guint32 value,
2642 const char *format, ...)
2647 pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
2649 TRY_TO_FAKE_THIS_REPR(pi);
2651 va_start(ap, format);
2652 proto_tree_set_representation(pi, format, ap);
2659 /* Set the FT_IPXNET value */
2661 proto_tree_set_ipxnet(field_info *fi, guint32 value)
2663 fvalue_set_uinteger(&fi->value, value);
2666 /* Add a FT_IPv4 to a proto_tree */
2668 proto_tree_add_ipv4(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2669 gint length, guint32 value)
2672 header_field_info *hfinfo;
2674 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2676 DISSECTOR_ASSERT(hfinfo->type == FT_IPv4);
2678 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
2679 proto_tree_set_ipv4(PNODE_FINFO(pi), value);
2685 proto_tree_add_ipv4_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2686 gint start, gint length, guint32 value,
2687 const char *format, ...)
2692 pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
2694 va_start(ap, format);
2695 proto_tree_set_representation_value(pi, format, ap);
2703 proto_tree_add_ipv4_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2704 gint start, gint length, guint32 value,
2705 const char *format, ...)
2710 pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
2712 TRY_TO_FAKE_THIS_REPR(pi);
2714 va_start(ap, format);
2715 proto_tree_set_representation(pi, format, ap);
2722 /* Set the FT_IPv4 value */
2724 proto_tree_set_ipv4(field_info *fi, guint32 value)
2726 fvalue_set_uinteger(&fi->value, value);
2729 /* Add a FT_IPv6 to a proto_tree */
2731 proto_tree_add_ipv6(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2732 gint length, const guint8* value_ptr)
2735 header_field_info *hfinfo;
2737 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2739 DISSECTOR_ASSERT(hfinfo->type == FT_IPv6);
2741 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
2742 proto_tree_set_ipv6(PNODE_FINFO(pi), value_ptr);
2748 proto_tree_add_ipv6_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2749 gint start, gint length,
2750 const guint8* value_ptr,
2751 const char *format, ...)
2756 pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
2758 va_start(ap, format);
2759 proto_tree_set_representation_value(pi, format, ap);
2767 proto_tree_add_ipv6_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2768 gint start, gint length, const guint8* value_ptr,
2769 const char *format, ...)
2774 pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
2776 TRY_TO_FAKE_THIS_REPR(pi);
2778 va_start(ap, format);
2779 proto_tree_set_representation(pi, format, ap);
2786 /* Set the FT_IPv6 value */
2788 proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr)
2790 DISSECTOR_ASSERT(value_ptr != NULL);
2791 fvalue_set_bytes(&fi->value, value_ptr);
2795 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
2797 proto_tree_set_ipv6(fi, tvb_get_ptr(tvb, start, length));
2800 /* Add a FT_GUID to a proto_tree */
2802 proto_tree_add_guid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2803 gint length, const e_guid_t *value_ptr)
2806 header_field_info *hfinfo;
2808 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2810 DISSECTOR_ASSERT(hfinfo->type == FT_GUID);
2812 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
2813 proto_tree_set_guid(PNODE_FINFO(pi), value_ptr);
2819 proto_tree_add_guid_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2820 gint start, gint length,
2821 const e_guid_t *value_ptr,
2822 const char *format, ...)
2827 pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
2829 va_start(ap, format);
2830 proto_tree_set_representation_value(pi, format, ap);
2838 proto_tree_add_guid_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2839 gint start, gint length, const e_guid_t *value_ptr,
2840 const char *format, ...)
2845 pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
2847 TRY_TO_FAKE_THIS_REPR(pi);
2849 va_start(ap, format);
2850 proto_tree_set_representation(pi, format, ap);
2857 /* Set the FT_GUID value */
2859 proto_tree_set_guid(field_info *fi, const e_guid_t *value_ptr)
2861 DISSECTOR_ASSERT(value_ptr != NULL);
2862 fvalue_set_guid(&fi->value, value_ptr);
2866 proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, gint start,
2867 const guint encoding)
2871 tvb_get_guid(tvb, start, &guid, encoding);
2872 proto_tree_set_guid(fi, &guid);
2875 /* Add a FT_OID to a proto_tree */
2877 proto_tree_add_oid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2878 gint length, const guint8* value_ptr)
2881 header_field_info *hfinfo;
2883 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2885 DISSECTOR_ASSERT(hfinfo->type == FT_OID);
2887 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
2888 proto_tree_set_oid(PNODE_FINFO(pi), value_ptr, length);
2894 proto_tree_add_oid_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2895 gint start, gint length,
2896 const guint8* value_ptr,
2897 const char *format, ...)
2902 pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
2904 va_start(ap, format);
2905 proto_tree_set_representation_value(pi, format, ap);
2913 proto_tree_add_oid_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2914 gint start, gint length, const guint8* value_ptr,
2915 const char *format, ...)
2920 pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
2922 TRY_TO_FAKE_THIS_REPR(pi);
2924 va_start(ap, format);
2925 proto_tree_set_representation(pi, format, ap);
2932 /* Set the FT_OID value */
2934 proto_tree_set_oid(field_info *fi, const guint8* value_ptr, gint length)
2938 DISSECTOR_ASSERT(value_ptr != NULL || length == 0);
2940 bytes = g_byte_array_new();
2942 g_byte_array_append(bytes, value_ptr, length);
2944 fvalue_set_byte_array(&fi->value, bytes);
2948 proto_tree_set_oid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
2950 proto_tree_set_oid(fi, tvb_get_ptr(tvb, start, length), length);
2953 /* Set the FT_SYSTEM_ID value */
2955 proto_tree_set_system_id(field_info *fi, const guint8* value_ptr, gint length)
2959 DISSECTOR_ASSERT(value_ptr != NULL || length == 0);
2961 bytes = g_byte_array_new();
2963 g_byte_array_append(bytes, value_ptr, length);
2965 fvalue_set_byte_array(&fi->value, bytes);
2969 proto_tree_set_system_id_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
2971 proto_tree_set_system_id(fi, tvb_get_ptr(tvb, start, length), length);
2975 proto_tree_set_uint64(field_info *fi, guint64 value)
2977 fvalue_set_integer64(&fi->value, value);
2980 /* Add a FT_STRING, FT_STRINGZ, or FT_STRINGZPAD to a proto_tree. Creates
2981 * own copy of string, and frees it when the proto_tree is destroyed. */
2983 proto_tree_add_string(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2984 gint length, const char* value)
2987 header_field_info *hfinfo;
2989 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2991 DISSECTOR_ASSERT(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ || hfinfo->type == FT_STRINGZPAD);
2993 if (hfinfo->display == STR_UNICODE) {
2994 DISSECTOR_ASSERT(g_utf8_validate(value, -1, NULL));
2997 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
2998 DISSECTOR_ASSERT(length >= 0);
2999 proto_tree_set_string(PNODE_FINFO(pi), value);
3005 proto_tree_add_string_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3006 gint start, gint length, const char* value,
3013 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
3015 va_start(ap, format);
3016 proto_tree_set_representation_value(pi, format, ap);
3024 proto_tree_add_string_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3025 gint start, gint length, const char* value,
3026 const char *format, ...)
3031 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
3033 TRY_TO_FAKE_THIS_REPR(pi);
3035 va_start(ap, format);
3036 proto_tree_set_representation(pi, format, ap);
3043 /* Appends string data to a FT_STRING, FT_STRINGZ, or FT_STRINGZPAD,
3044 * allowing progressive field info update instead of only updating the
3045 * representation as does proto_item_append_text()
3047 /* NOTE: this function will break with the TRY_TO_FAKE_THIS_ITEM()
3048 * speed optimization.
3049 * Currently only WSP use this function so it is not that bad but try to
3050 * avoid using this one if possible.
3051 * IF you must use this function you MUST also disable the
3052 * TRY_TO_FAKE_THIS_ITEM() optimization for your dissector/function
3053 * using proto_item_append_string().
3054 * Do that by faking that the tree is visible by calling
3055 * proto_tree_set_visible(tree, TRUE) (see packet-wsp.c)
3056 * BEFORE you create the item you are later going to use
3057 * proto_item_append_string() on.
3060 proto_item_append_string(proto_item *pi, const char *str)
3063 header_field_info *hfinfo;
3064 const gchar *old_str, *new_str;
3071 fi = PITEM_FINFO(pi);
3072 DISSECTOR_ASSERT_HINT(fi, "proto_tree_set_visible(tree, TRUE) should have been called previously");
3074 hfinfo = fi->hfinfo;
3075 if (hfinfo->type == FT_PROTOCOL) {
3076 /* TRY_TO_FAKE_THIS_ITEM() speed optimization: silently skip */
3079 DISSECTOR_ASSERT(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ || hfinfo->type == FT_STRINGZPAD);
3080 old_str = (guint8 *)fvalue_get(&fi->value);
3081 if (old_str && old_str[0])
3082 new_str = ep_strconcat(old_str, str, NULL);
3085 fvalue_set_string(&fi->value, new_str);
3088 /* Set the FT_STRING value */
3090 proto_tree_set_string(field_info *fi, const char* value)
3093 fvalue_set_string(&fi->value, value);
3095 fvalue_set_string(&fi->value, "[ Null ]");
3100 proto_tree_set_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length, gint encoding)
3105 length = tvb_ensure_captured_length_remaining(tvb, start);
3108 string = tvb_get_string_enc(wmem_packet_scope(), tvb, start, length, encoding);
3109 proto_tree_set_string(fi, string);
3113 /* Add a FT_AX25 to a proto_tree */
3115 proto_tree_add_ax25(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
3116 const guint8* value)
3119 header_field_info *hfinfo;
3121 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3123 DISSECTOR_ASSERT(hfinfo->type == FT_AX25);
3125 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
3126 proto_tree_set_ax25(PNODE_FINFO(pi), value);
3131 /* Set the FT_AX25 value */
3133 proto_tree_set_ax25(field_info *fi, const guint8* value)
3135 fvalue_set_bytes(&fi->value, value);
3139 proto_tree_set_ax25_tvb(field_info *fi, tvbuff_t *tvb, gint start)
3141 proto_tree_set_ax25(fi, tvb_get_ptr(tvb, start, 7));
3144 /* Set the FT_VINES value */
3146 proto_tree_set_vines(field_info *fi, const guint8* value)
3148 fvalue_set_bytes(&fi->value, value);
3152 proto_tree_set_vines_tvb(field_info *fi, tvbuff_t *tvb, gint start)
3154 proto_tree_set_vines(fi, tvb_get_ptr(tvb, start, FT_VINES_ADDR_LEN));
3157 /* Add a FT_ETHER to a proto_tree */
3159 proto_tree_add_ether(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3160 gint length, const guint8* value)
3163 header_field_info *hfinfo;
3165 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3167 DISSECTOR_ASSERT(hfinfo->type == FT_ETHER);
3169 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
3170 proto_tree_set_ether(PNODE_FINFO(pi), value);
3176 proto_tree_add_ether_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3177 gint start, gint length, const guint8* value,
3178 const char *format, ...)
3183 pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
3185 va_start(ap, format);
3186 proto_tree_set_representation_value(pi, format, ap);
3194 proto_tree_add_ether_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3195 gint start, gint length, const guint8* value,
3196 const char *format, ...)
3201 pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
3203 TRY_TO_FAKE_THIS_REPR(pi);
3205 va_start(ap, format);
3206 proto_tree_set_representation(pi, format, ap);
3213 /* Set the FT_ETHER value */
3215 proto_tree_set_ether(field_info *fi, const guint8* value)
3217 fvalue_set_bytes(&fi->value, value);
3221 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start)
3223 proto_tree_set_ether(fi, tvb_get_ptr(tvb, start, FT_ETHER_LEN));
3226 /* Add a FT_BOOLEAN to a proto_tree */
3228 proto_tree_add_boolean(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3229 gint length, guint32 value)
3232 header_field_info *hfinfo;
3234 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3236 DISSECTOR_ASSERT(hfinfo->type == FT_BOOLEAN);
3238 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
3239 proto_tree_set_boolean(PNODE_FINFO(pi), value);
3245 proto_tree_add_boolean_format_value(proto_tree *tree, int hfindex,
3246 tvbuff_t *tvb, gint start, gint length,
3247 guint32 value, const char *format, ...)
3252 pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
3254 va_start(ap, format);
3255 proto_tree_set_representation_value(pi, format, ap);
3263 proto_tree_add_boolean_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3264 gint start, gint length, guint32 value,
3265 const char *format, ...)
3270 pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
3272 TRY_TO_FAKE_THIS_REPR(pi);
3274 va_start(ap, format);
3275 proto_tree_set_representation(pi, format, ap);
3282 /* Set the FT_BOOLEAN value */
3284 proto_tree_set_boolean(field_info *fi, guint32 value)
3286 proto_tree_set_uint(fi, value);
3289 /* Add a FT_FLOAT to a proto_tree */
3291 proto_tree_add_float(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3292 gint length, float value)
3295 header_field_info *hfinfo;
3297 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3299 DISSECTOR_ASSERT(hfinfo->type == FT_FLOAT);
3301 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
3302 proto_tree_set_float(PNODE_FINFO(pi), value);
3308 proto_tree_add_float_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3309 gint start, gint length, float value,
3310 const char *format, ...)
3315 pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
3317 va_start(ap, format);
3318 proto_tree_set_representation_value(pi, format, ap);
3326 proto_tree_add_float_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3327 gint start, gint length, float value,
3328 const char *format, ...)
3333 pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
3335 TRY_TO_FAKE_THIS_REPR(pi);
3337 va_start(ap, format);
3338 proto_tree_set_representation(pi, format, ap);
3345 /* Set the FT_FLOAT value */
3347 proto_tree_set_float(field_info *fi, float value)
3349 fvalue_set_floating(&fi->value, value);
3352 /* Add a FT_DOUBLE to a proto_tree */
3354 proto_tree_add_double(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3355 gint length, double value)
3358 header_field_info *hfinfo;
3360 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3362 DISSECTOR_ASSERT(hfinfo->type == FT_DOUBLE);
3364 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
3365 proto_tree_set_double(PNODE_FINFO(pi), value);
3371 proto_tree_add_double_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3372 gint start, gint length, double value,
3373 const char *format, ...)
3378 pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
3380 va_start(ap, format);
3381 proto_tree_set_representation_value(pi, format, ap);
3389 proto_tree_add_double_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3390 gint start, gint length, double value,
3391 const char *format, ...)
3396 pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
3398 TRY_TO_FAKE_THIS_REPR(pi);
3400 va_start(ap, format);
3401 proto_tree_set_representation(pi, format, ap);
3408 /* Set the FT_DOUBLE value */
3410 proto_tree_set_double(field_info *fi, double value)
3412 fvalue_set_floating(&fi->value, value);
3415 /* Add FT_UINT{8,16,24,32} to a proto_tree */
3417 proto_tree_add_uint(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3418 gint length, guint32 value)
3420 proto_item *pi = NULL;
3421 header_field_info *hfinfo;
3423 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3425 switch (hfinfo->type) {
3431 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
3432 proto_tree_set_uint(PNODE_FINFO(pi), value);
3436 DISSECTOR_ASSERT_NOT_REACHED();
3443 proto_tree_add_uint_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3444 gint start, gint length, guint32 value,
3445 const char *format, ...)
3450 pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
3452 va_start(ap, format);
3453 proto_tree_set_representation_value(pi, format, ap);
3461 proto_tree_add_uint_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3462 gint start, gint length, guint32 value,
3463 const char *format, ...)
3468 pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
3470 TRY_TO_FAKE_THIS_REPR(pi);
3472 va_start(ap, format);
3473 proto_tree_set_representation(pi, format, ap);
3480 /* Set the FT_UINT{8,16,24,32} value */
3482 proto_tree_set_uint(field_info *fi, guint32 value)
3484 header_field_info *hfinfo;
3487 hfinfo = fi->hfinfo;
3490 if (hfinfo->bitmask) {
3491 /* Mask out irrelevant portions */
3492 integer &= hfinfo->bitmask;
3495 integer >>= hfinfo_bitshift(hfinfo);
3498 fvalue_set_uinteger(&fi->value, integer);
3501 /* Add FT_UINT64 to a proto_tree */
3503 proto_tree_add_uint64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3504 gint length, guint64 value)
3507 header_field_info *hfinfo;
3509 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3511 DISSECTOR_ASSERT(hfinfo->type == FT_UINT64);
3513 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
3514 proto_tree_set_uint64(PNODE_FINFO(pi), value);
3520 proto_tree_add_uint64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3521 gint start, gint length, guint64 value,
3522 const char *format, ...)
3527 pi = proto_tree_add_uint64(tree, hfindex, tvb, start, length, value);
3529 va_start(ap, format);
3530 proto_tree_set_representation_value(pi, format, ap);
3538 proto_tree_add_uint64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3539 gint start, gint length, guint64 value,
3540 const char *format, ...)
3545 pi = proto_tree_add_uint64(tree, hfindex, tvb, start, length, value);
3547 TRY_TO_FAKE_THIS_REPR(pi);
3549 va_start(ap, format);
3550 proto_tree_set_representation(pi, format, ap);
3557 /* Add FT_INT{8,16,24,32} to a proto_tree */
3559 proto_tree_add_int(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3560 gint length, gint32 value)
3562 proto_item *pi = NULL;
3563 header_field_info *hfinfo;
3565 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3567 switch (hfinfo->type) {
3572 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
3573 proto_tree_set_int(PNODE_FINFO(pi), value);
3577 DISSECTOR_ASSERT_NOT_REACHED();
3584 proto_tree_add_int_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3585 gint start, gint length, gint32 value,
3586 const char *format, ...)
3591 pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
3593 va_start(ap, format);
3594 proto_tree_set_representation_value(pi, format, ap);
3602 proto_tree_add_int_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3603 gint start, gint length, gint32 value,
3604 const char *format, ...)
3609 pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
3611 TRY_TO_FAKE_THIS_REPR(pi);
3613 va_start(ap, format);
3614 proto_tree_set_representation(pi, format, ap);
3621 /* Set the FT_INT{8,16,24,32} value */
3623 proto_tree_set_int(field_info *fi, gint32 value)
3625 header_field_info *hfinfo;
3629 hfinfo = fi->hfinfo;
3630 integer = (guint32) value;
3632 if (hfinfo->bitmask) {
3633 /* Mask out irrelevant portions */
3634 integer &= hfinfo->bitmask;
3637 integer >>= hfinfo_bitshift(hfinfo);
3639 no_of_bits = ws_count_ones(hfinfo->bitmask);
3640 integer = ws_sign_ext32(integer, no_of_bits);
3643 fvalue_set_sinteger(&fi->value, integer);
3646 /* Add FT_INT64 to a proto_tree */
3648 proto_tree_add_int64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3649 gint length, gint64 value)
3652 header_field_info *hfinfo;
3654 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3656 DISSECTOR_ASSERT(hfinfo->type == FT_INT64);
3658 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
3659 proto_tree_set_uint64(PNODE_FINFO(pi), (guint64)value);
3665 proto_tree_add_int64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3666 gint start, gint length, gint64 value,
3667 const char *format, ...)
3672 pi = proto_tree_add_int64(tree, hfindex, tvb, start, length, value);
3674 va_start(ap, format);
3675 proto_tree_set_representation_value(pi, format, ap);
3683 proto_tree_add_int64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3684 gint start, gint length, gint64 value,
3685 const char *format, ...)
3690 pi = proto_tree_add_int64(tree, hfindex, tvb, start, length, value);
3692 TRY_TO_FAKE_THIS_REPR(pi);
3694 va_start(ap, format);
3695 proto_tree_set_representation(pi, format, ap);
3701 /* Add a FT_EUI64 to a proto_tree */
3703 proto_tree_add_eui64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3704 gint length, const guint64 value)
3707 header_field_info *hfinfo;
3709 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3711 DISSECTOR_ASSERT(hfinfo->type == FT_EUI64);
3713 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
3714 proto_tree_set_eui64(PNODE_FINFO(pi), value);
3720 proto_tree_add_eui64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3721 gint start, gint length, const guint64 value,
3722 const char *format, ...)
3727 pi = proto_tree_add_eui64(tree, hfindex, tvb, start, length, value);
3729 va_start(ap, format);
3730 proto_tree_set_representation_value(pi, format, ap);
3738 proto_tree_add_eui64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3739 gint start, gint length, const guint64 value,
3740 const char *format, ...)
3745 pi = proto_tree_add_eui64(tree, hfindex, tvb, start, length, value);
3747 TRY_TO_FAKE_THIS_REPR(pi);
3749 va_start(ap, format);
3750 proto_tree_set_representation(pi, format, ap);
3757 /* Set the FT_EUI64 value */
3759 proto_tree_set_eui64(field_info *fi, const guint64 value)
3761 fvalue_set_integer64(&fi->value, value);
3764 proto_tree_set_eui64_tvb(field_info *fi, tvbuff_t *tvb, gint start, const guint encoding)
3768 proto_tree_set_eui64(fi, tvb_get_letoh64(tvb, start));
3770 proto_tree_set_eui64(fi, tvb_get_ntoh64(tvb, start));
3774 /* Add a field_info struct to the proto_tree, encapsulating it in a proto_node */
3776 proto_tree_add_node(proto_tree *tree, field_info *fi)
3778 proto_node *pnode, *tnode, *sibling;
3782 * Make sure "tree" is ready to have subtrees under it, by
3783 * checking whether it's been given an ett_ value.
3785 * "PNODE_FINFO(tnode)" may be null; that's the case for the root
3786 * node of the protocol tree. That node is not displayed,
3787 * so it doesn't need an ett_ value to remember whether it
3791 tfi = PNODE_FINFO(tnode);
3792 if (tfi != NULL && (tfi->tree_type < 0 || tfi->tree_type >= num_tree_types)) {
3793 REPORT_DISSECTOR_BUG(ep_strdup_printf("\"%s\" - \"%s\" tfi->tree_type: %u invalid (%s:%u)",
3794 fi->hfinfo->name, fi->hfinfo->abbrev, tfi->tree_type, __FILE__, __LINE__));
3795 /* XXX - is it safe to continue here? */
3798 pnode = wmem_new(PNODE_POOL(tree), proto_node);
3799 PROTO_NODE_INIT(pnode);
3800 pnode->parent = tnode;
3801 PNODE_FINFO(pnode) = fi;
3802 pnode->tree_data = PTREE_DATA(tree);
3804 if (tnode->last_child != NULL) {
3805 sibling = tnode->last_child;
3806 DISSECTOR_ASSERT(sibling->next == NULL);
3807 sibling->next = pnode;
3809 tnode->first_child = pnode;
3810 tnode->last_child = pnode;
3812 tree_data_add_maybe_interesting_field(pnode->tree_data, fi);
3814 return (proto_item *)pnode;
3818 /* Generic way to allocate field_info and add to proto_tree.
3819 * Sets *pfi to address of newly-allocated field_info struct */
3821 proto_tree_add_pi(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb, gint start,
3828 get_hfi_length(hfinfo, tvb, start, length, &item_length);
3829 fi = new_field_info(tree, hfinfo, tvb, start, item_length);
3830 pi = proto_tree_add_node(tree, fi);
3837 get_hfi_length(header_field_info *hfinfo, tvbuff_t *tvb, const gint start, gint *length,
3840 gint length_remaining;
3843 * We only allow a null tvbuff if the item has a zero length,
3844 * i.e. if there's no data backing it.
3846 DISSECTOR_ASSERT(tvb != NULL || *length == 0);
3849 * XXX - in some protocols, there are 32-bit unsigned length
3850 * fields, so lengths in protocol tree and tvbuff routines
3851 * should really be unsigned. We should have, for those
3852 * field types for which "to the end of the tvbuff" makes sense,
3853 * additional routines that take no length argument and
3854 * add fields that run to the end of the tvbuff.
3856 if (*length == -1) {
3858 * For FT_NONE, FT_PROTOCOL, FT_BYTES, FT_STRING, and
3859 * FT_STRINGZPAD fields, a length of -1 means "set the
3860 * length to what remains in the tvbuff".
3862 * The assumption is either that
3864 * 1) the length of the item can only be determined
3865 * by dissection (typically true of items with
3866 * subitems, which are probably FT_NONE or
3871 * 2) if the tvbuff is "short" (either due to a short
3872 * snapshot length or due to lack of reassembly of
3873 * fragments/segments/whatever), we want to display
3874 * what's available in the field (probably FT_BYTES
3875 * or FT_STRING) and then throw an exception later
3879 * 3) the field is defined to be "what's left in the
3882 * so we set the length to what remains in the tvbuff so
3883 * that, if we throw an exception while dissecting, it
3884 * has what is probably the right value.
3886 * For FT_STRINGZ, it means "the string is null-terminated,
3887 * not null-padded; set the length to the actual length
3888 * of the string", and if the tvbuff if short, we just
3889 * throw an exception.
3891 * It's not valid for any other type of field. For those
3892 * fields, we treat -1 the same way we treat other
3893 * negative values - we assume the length is a Really
3894 * Big Positive Number, and throw a ReportedBoundsError
3895 * exception, under the assumption that the Really Big
3896 * Length would run past the end of the packet.
3898 switch (hfinfo->type) {
3906 * We allow FT_PROTOCOLs to be zero-length -
3907 * for example, an ONC RPC NULL procedure has
3908 * neither arguments nor reply, so the
3909 * payload for that protocol is empty.
3911 * We also allow the others to be zero-length -
3912 * because that's the way the code has been for a
3915 * However, we want to ensure that the start
3916 * offset is not *past* the byte past the end
3917 * of the tvbuff: we throw an exception in that
3920 *length = tvb_ensure_captured_length_remaining(tvb, start);
3921 DISSECTOR_ASSERT(*length >= 0);
3926 * Leave the length as -1, so our caller knows
3932 THROW(ReportedBoundsError);
3933 DISSECTOR_ASSERT_NOT_REACHED();
3935 *item_length = *length;
3937 *item_length = *length;
3938 if (hfinfo->type == FT_PROTOCOL || hfinfo->type == FT_NONE) {
3940 * These types are for interior nodes of the
3941 * tree, and don't have data associated with
3942 * them; if the length is negative (XXX - see
3943 * above) or goes past the end of the tvbuff,
3944 * cut it short at the end of the tvbuff.
3945 * That way, if this field is selected in
3946 * Wireshark, we don't highlight stuff past
3947 * the end of the data.
3949 /* XXX - what to do, if we don't have a tvb? */
3951 length_remaining = tvb_captured_length_remaining(tvb, start);
3952 if (*item_length < 0 ||
3953 (*item_length > 0 &&
3954 (length_remaining < *item_length)))
3955 *item_length = length_remaining;
3958 if (*item_length < 0) {
3959 THROW(ReportedBoundsError);
3965 new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
3966 const gint start, const gint item_length)
3970 FIELD_INFO_NEW(PNODE_POOL(tree), fi);
3972 fi->hfinfo = hfinfo;
3974 fi->start += (tvb)?tvb_raw_offset(tvb):0;
3975 fi->length = item_length;
3978 if (!PTREE_DATA(tree)->visible)
3979 FI_SET_FLAG(fi, FI_HIDDEN);
3980 fvalue_init(&fi->value, fi->hfinfo->type);
3983 /* add the data source tvbuff */
3984 fi->ds_tvb = tvb ? tvb_get_ds_tvb(tvb) : NULL;
3986 fi->appendix_start = 0;
3987 fi->appendix_length = 0;
3992 /* If the protocol tree is to be visible, set the representation of a
3993 proto_tree entry with the name of the field for the item and with
3994 the value formatted with the supplied printf-style format and
3997 proto_tree_set_representation_value(proto_item *pi, const char *format, va_list ap)
4001 /* If the tree (GUI) or item isn't visible it's pointless for us to generate the protocol
4002 * items string representation */
4003 if (PTREE_DATA(pi)->visible && !PROTO_ITEM_IS_HIDDEN(pi)) {
4005 field_info *fi = PITEM_FINFO(pi);
4006 header_field_info *hf;
4008 DISSECTOR_ASSERT(fi);
4012 ITEM_LABEL_NEW(PNODE_POOL(pi), fi->rep);
4013 if (hf->bitmask && (hf->type == FT_BOOLEAN || IS_FT_UINT(hf->type))) {
4017 val = fvalue_get_uinteger(&fi->value);
4018 val <<= hfinfo_bitshift(hf);
4020 p = decode_bitfield_value(fi->rep->representation, val, hf->bitmask, hfinfo_bitwidth(hf));
4021 ret = (int) (p - fi->rep->representation);
4024 /* put in the hf name */
4025 ret += g_snprintf(fi->rep->representation + ret, ITEM_LABEL_LENGTH - ret, "%s: ", hf->name);
4027 /* If possible, Put in the value of the string */
4028 if (ret < ITEM_LABEL_LENGTH) {
4029 ret += g_vsnprintf(fi->rep->representation + ret,
4030 ITEM_LABEL_LENGTH - ret, format, ap);
4032 if (ret >= ITEM_LABEL_LENGTH) {
4033 /* Uh oh, we don't have enough room. Tell the user
4034 * that the field is truncated.
4036 LABEL_MARK_TRUNCATED_START(fi->rep->representation);
4041 /* If the protocol tree is to be visible, set the representation of a
4042 proto_tree entry with the representation formatted with the supplied
4043 printf-style format and argument list. */
4045 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap)
4047 int ret; /*tmp return value */
4048 field_info *fi = PITEM_FINFO(pi);
4050 DISSECTOR_ASSERT(fi);
4052 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
4053 ITEM_LABEL_NEW(PNODE_POOL(pi), fi->rep);
4054 ret = g_vsnprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
4056 if (ret >= ITEM_LABEL_LENGTH) {
4057 /* Uh oh, we don't have enough room. Tell the user
4058 * that the field is truncated.
4060 LABEL_MARK_TRUNCATED_START(fi->rep->representation);
4066 hfinfo_format_text(const header_field_info *hfinfo, const guchar *string)
4068 switch (hfinfo->display) {
4070 return format_text(string, strlen(string));
4073 return format_text_wsp(string, strlen(string));
4076 /* XXX, format_unicode_text() */
4080 return format_text(string, strlen(string));
4084 protoo_strlcpy(gchar *dest, const gchar *src, gsize dest_size)
4086 gsize res = g_strlcpy(dest, src, dest_size);
4088 if (res > dest_size)
4093 static header_field_info *
4094 hfinfo_same_name_get_prev(const header_field_info *hfinfo)
4096 header_field_info *dup_hfinfo;
4098 if (hfinfo->same_name_prev_id == -1)
4100 PROTO_REGISTRAR_GET_NTH(hfinfo->same_name_prev_id, dup_hfinfo);
4104 /* -------------------------- */
4106 proto_custom_set(proto_tree* tree, const int field_id, gint occurrence,
4107 gchar *result, gchar *expr, const int size)
4112 struct e_in6_addr *ipv6;
4114 guint32 n_addr; /* network-order IPv4 address */
4116 const true_false_string *tfstring;
4118 int len, prev_len = 0, last, i, offset_r = 0, offset_e = 0;
4120 field_info *finfo = NULL;
4121 header_field_info* hfinfo;
4122 const gchar *abbrev = NULL;
4124 const char *hf_str_val;
4125 char number_buf[32];
4126 const char *number_out;
4129 g_assert(field_id >= 0);
4131 PROTO_REGISTRAR_GET_NTH((guint)field_id, hfinfo);
4133 /* do we need to rewind ? */
4137 if (occurrence < 0) {
4138 /* Search other direction */
4139 while (hfinfo->same_name_prev_id != -1) {
4140 PROTO_REGISTRAR_GET_NTH(hfinfo->same_name_prev_id, hfinfo);
4145 finfos = proto_get_finfo_ptr_array(tree, hfinfo->id);
4147 if (!finfos || !(len = g_ptr_array_len(finfos))) {
4148 if (occurrence < 0) {
4149 hfinfo = hfinfo->same_name_next;
4151 hfinfo = hfinfo_same_name_get_prev(hfinfo);
4156 /* Are there enough occurrences of the field? */
4157 if (((occurrence - prev_len) > len) || ((occurrence + prev_len) < -len)) {
4158 if (occurrence < 0) {
4159 hfinfo = hfinfo->same_name_next;
4161 hfinfo = hfinfo_same_name_get_prev(hfinfo);
4167 /* Calculate single index or set outer bounderies */
4168 if (occurrence < 0) {
4169 i = occurrence + len + prev_len;
4171 } else if (occurrence > 0) {
4172 i = occurrence - 1 - prev_len;
4179 prev_len += len; /* Count handled occurrences */
4182 finfo = (field_info *)g_ptr_array_index(finfos, i);
4184 if (offset_r && (offset_r < (size - 2)))
4185 result[offset_r++] = ',';
4187 if (offset_e && (offset_e < (size - 2)))
4188 expr[offset_e++] = ',';
4190 switch (hfinfo->type) {
4192 case FT_NONE: /* Nothing to add */
4193 if (offset_r == 0) {
4195 } else if (result[offset_r-1] == ',') {
4196 result[offset_r-1] = '\0';
4201 /* prevent multiple "yes" entries by setting result directly */
4202 g_strlcpy(result, "Yes", size);
4207 bytes = (guint8 *)fvalue_get(&finfo->value);
4208 offset_r += protoo_strlcpy(result+offset_r,
4209 bytes ? bytes_to_ep_str(bytes, fvalue_length(&finfo->value)) : "<MISSING>",
4213 case FT_ABSOLUTE_TIME:
4214 tmpbuf = abs_time_to_str(NULL, (const nstime_t *)fvalue_get(&finfo->value), (absolute_time_display_e)hfinfo->display, TRUE);
4215 offset_r += protoo_strlcpy(result+offset_r,
4218 wmem_free(NULL, tmpbuf);
4221 case FT_RELATIVE_TIME:
4222 tmpbuf = rel_time_to_secs_str(NULL, (const nstime_t *)fvalue_get(&finfo->value));
4223 offset_r += protoo_strlcpy(result+offset_r,
4226 wmem_free(NULL, tmpbuf);
4230 number = fvalue_get_uinteger(&finfo->value);
4231 tfstring = (const true_false_string *)&tfs_true_false;
4232 if (hfinfo->strings) {
4233 tfstring = (const struct true_false_string*) hfinfo->strings;
4235 offset_r += protoo_strlcpy(result+offset_r,
4237 tfstring->true_string :
4238 tfstring->false_string, size-offset_r);
4240 offset_e += protoo_strlcpy(expr+offset_e,
4241 number ? "1" : "0", size-offset_e);
4244 /* XXX - make these just FT_NUMBER? */
4255 number = IS_FT_INT(hfinfo->type) ?
4256 (guint32) fvalue_get_sinteger(&finfo->value) :
4257 fvalue_get_uinteger(&finfo->value);
4259 if ((hfinfo->display & FIELD_DISPLAY_E_MASK) == BASE_CUSTOM) {
4260 gchar tmp[ITEM_LABEL_LENGTH];
4261 custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hfinfo->strings;
4263 DISSECTOR_ASSERT(fmtfunc);
4264 fmtfunc(tmp, number);
4266 offset_r += protoo_strlcpy(result+offset_r, tmp, size-offset_r);
4268 } else if (hfinfo->strings) {
4269 number_out = hf_str_val = hf_try_val_to_str(number, hfinfo);
4272 number_out = hfinfo_number_value_format_display(hfinfo, BASE_DEC, number_buf, number);
4274 offset_r += protoo_strlcpy(result+offset_r, number_out, size-offset_r);
4277 number_out = hfinfo_number_value_format(hfinfo, number_buf, number);
4279 offset_r += protoo_strlcpy(result+offset_r, number_out, size-offset_r);
4282 if (hf_str_val && (hfinfo->display & FIELD_DISPLAY_E_MASK) == BASE_NONE) {
4283 g_snprintf(expr+offset_e, size-offset_e, "\"%s\"", hf_str_val);
4285 number_out = hfinfo_numeric_value_format(hfinfo, number_buf, number);
4287 g_strlcpy(expr+offset_e, number_out, size-offset_e);
4290 offset_e = (int)strlen(expr);
4294 /* XXX: Should handle BASE_CUSTOM ? */
4295 g_snprintf(result+offset_r, size-offset_r,
4296 "%" G_GINT64_MODIFIER "d",
4297 fvalue_get_integer64(&finfo->value));
4298 offset_r = (int)strlen(result);
4301 g_snprintf(result+offset_r, size-offset_r,
4302 /* XXX: Should handle BASE_CUSTOM ? */
4303 "%" G_GINT64_MODIFIER "u",
4304 fvalue_get_integer64(&finfo->value));
4305 offset_r = (int)strlen(result);
4308 offset_r += protoo_strlcpy(result+offset_r,
4309 eui64_to_str(fvalue_get_integer64(&finfo->value)),
4314 ipv4 = (ipv4_addr *)fvalue_get(&finfo->value);
4315 n_addr = ipv4_get_net_order_addr(ipv4);
4316 offset_r += protoo_strlcpy(result+offset_r,
4317 ip_to_str((guint8 *)&n_addr),
4322 ipv6 = (struct e_in6_addr *)fvalue_get(&finfo->value);
4323 SET_ADDRESS (&addr, AT_IPv6, sizeof(struct e_in6_addr), ipv6);
4324 address_to_str_buf(&addr, result+offset_r, size-offset_r);
4325 offset_r = (int)strlen(result);
4329 offset_r += protoo_strlcpy(result+offset_r,
4330 bytes_to_ep_str_punct((const guint8 *)fvalue_get(&finfo->value),
4336 offset_r += protoo_strlcpy(result+offset_r,
4337 guid_to_ep_str((e_guid_t *)fvalue_get(&finfo->value)),
4342 bytes = (guint8 *)fvalue_get(&finfo->value);
4343 offset_r += protoo_strlcpy(result+offset_r,
4344 rel_oid_resolved_from_encoded(bytes,
4345 fvalue_length(&finfo->value)),
4347 offset_e += protoo_strlcpy(expr+offset_e,
4348 rel_oid_encoded2string(bytes, fvalue_length(&finfo->value)),
4353 bytes = (guint8 *)fvalue_get(&finfo->value);
4354 offset_r += protoo_strlcpy(result+offset_r,
4355 oid_resolved_from_encoded(bytes,
4356 fvalue_length(&finfo->value)),
4358 offset_e += protoo_strlcpy(expr+offset_e,
4359 oid_encoded2string(bytes, fvalue_length(&finfo->value)),
4364 bytes = (guint8 *)fvalue_get(&finfo->value);
4365 offset_r += protoo_strlcpy(result+offset_r,
4366 print_system_id(bytes, fvalue_length(&finfo->value)),
4368 offset_e += protoo_strlcpy(expr+offset_e,
4369 print_system_id(bytes, fvalue_length(&finfo->value)),
4374 g_snprintf(result+offset_r, size-offset_r,
4375 "%." G_STRINGIFY(FLT_DIG) "g", fvalue_get_floating(&finfo->value));
4376 offset_r = (int)strlen(result);
4380 g_snprintf(result+offset_r, size-offset_r,
4381 "%." G_STRINGIFY(DBL_DIG) "g", fvalue_get_floating(&finfo->value));
4382 offset_r = (int)strlen(result);
4387 case FT_UINT_STRING:
4389 bytes = (guint8 *)fvalue_get(&finfo->value);
4390 offset_r += protoo_strlcpy(result+offset_r,
4391 hfinfo_format_text(hfinfo, bytes),
4395 case FT_IPXNET: /*XXX really No column custom ?*/
4398 g_error("hfinfo->type %d (%s) not handled\n",
4400 ftype_name(hfinfo->type));
4401 DISSECTOR_ASSERT_NOT_REACHED();
4407 switch (hfinfo->type) {
4422 /* for these types, "expr" is filled in the loop above */
4426 /* for all others, just copy "result" to "expr" */
4427 g_strlcpy(expr, result, size);
4432 /* Store abbrev for return value */
4433 abbrev = hfinfo->abbrev;
4436 if (occurrence == 0) {
4437 /* Fetch next hfinfo with same name (abbrev) */
4438 hfinfo = hfinfo_same_name_get_prev(hfinfo);
4444 return abbrev ? abbrev : "";
4448 /* Set text of proto_item after having already been created. */
4450 proto_item_set_text(proto_item *pi, const char *format, ...)
4452 field_info *fi = NULL;
4455 TRY_TO_FAKE_THIS_REPR_VOID(pi);
4457 fi = PITEM_FINFO(pi);
4462 ITEM_LABEL_FREE(PNODE_POOL(pi), fi->rep);
4466 va_start(ap, format);
4467 proto_tree_set_representation(pi, format, ap);
4471 /* Append to text of proto_item after having already been created. */
4473 proto_item_append_text(proto_item *pi, const char *format, ...)
4475 field_info *fi = NULL;
4479 TRY_TO_FAKE_THIS_REPR_VOID(pi);
4481 fi = PITEM_FINFO(pi);
4486 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
4488 * If we don't already have a representation,
4489 * generate the default representation.
4491 if (fi->rep == NULL) {
4492 ITEM_LABEL_NEW(PNODE_POOL(pi), fi->rep);
4493 proto_item_fill_label(fi, fi->rep->representation);
4496 curlen = strlen(fi->rep->representation);
4497 if (ITEM_LABEL_LENGTH > curlen) {
4498 va_start(ap, format);
4499 g_vsnprintf(fi->rep->representation + curlen,
4500 ITEM_LABEL_LENGTH - (gulong) curlen, format, ap);
4506 /* Prepend to text of proto_item after having already been created. */
4508 proto_item_prepend_text(proto_item *pi, const char *format, ...)
4510 field_info *fi = NULL;
4511 char representation[ITEM_LABEL_LENGTH];
4514 TRY_TO_FAKE_THIS_REPR_VOID(pi);
4516 fi = PITEM_FINFO(pi);
4521 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
4523 * If we don't already have a representation,
4524 * generate the default representation.
4526 if (fi->rep == NULL) {
4527 ITEM_LABEL_NEW(PNODE_POOL(pi), fi->rep);
4528 proto_item_fill_label(fi, representation);
4530 g_strlcpy(representation, fi->rep->representation, ITEM_LABEL_LENGTH);
4532 va_start(ap, format);
4533 g_vsnprintf(fi->rep->representation,
4534 ITEM_LABEL_LENGTH, format, ap);
4536 g_strlcat(fi->rep->representation, representation, ITEM_LABEL_LENGTH);
4541 proto_item_set_len(proto_item *pi, const gint length)
4545 TRY_TO_FAKE_THIS_REPR_VOID(pi);
4547 fi = PITEM_FINFO(pi);
4551 DISSECTOR_ASSERT(length >= 0);
4552 fi->length = length;
4555 * You cannot just make the "len" field of a GByteArray
4556 * larger, if there's no data to back that length;
4557 * you can only make it smaller.
4559 if (fi->value.ftype->ftype == FT_BYTES && length <= (gint)fi->value.value.bytes->len)
4560 fi->value.value.bytes->len = length;
4564 * Sets the length of the item based on its start and on the specified
4565 * offset, which is the offset past the end of the item; as the start
4566 * in the item is relative to the beginning of the data source tvbuff,
4567 * we need to pass in a tvbuff - the end offset is relative to the beginning
4571 proto_item_set_end(proto_item *pi, tvbuff_t *tvb, gint end)
4575 TRY_TO_FAKE_THIS_REPR_VOID(pi);
4577 fi = PITEM_FINFO(pi);
4581 end += tvb_raw_offset(tvb);
4582 DISSECTOR_ASSERT(end >= fi->start);
4583 fi->length = end - fi->start;
4587 proto_item_get_len(const proto_item *pi)
4589 field_info *fi = PITEM_FINFO(pi);
4590 return fi ? fi->length : -1;
4594 proto_tree_create_root(packet_info *pinfo)
4598 /* Initialize the proto_node */
4599 pnode = g_slice_new(proto_tree);
4600 PROTO_NODE_INIT(pnode);
4601 pnode->parent = NULL;
4602 PNODE_FINFO(pnode) = NULL;
4603 pnode->tree_data = g_slice_new(tree_data_t);
4605 /* Make sure we can access pinfo everywhere */
4606 pnode->tree_data->pinfo = pinfo;
4608 /* Don't initialize the tree_data_t. Wait until we know we need it */
4609 pnode->tree_data->interesting_hfids = NULL;
4611 /* Set the default to FALSE so it's easier to
4612 * find errors; if we expect to see the protocol tree
4613 * but for some reason the default 'visible' is not
4614 * changed, then we'll find out very quickly. */
4615 pnode->tree_data->visible = FALSE;
4617 /* Make sure that we fake protocols (if possible) */
4618 pnode->tree_data->fake_protocols = TRUE;
4620 /* Keep track of the number of children */
4621 pnode->tree_data->count = 0;
4623 return (proto_tree *)pnode;
4627 /* "prime" a proto_tree with a single hfid that a dfilter
4628 * is interested in. */
4630 proto_tree_prime_hfid(proto_tree *tree _U_, const gint hfid)
4632 header_field_info *hfinfo;
4634 PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
4635 /* this field is referenced by a filter so increase the refcount.
4636 also increase the refcount for the parent, i.e the protocol.
4638 hfinfo->ref_type = HF_REF_TYPE_DIRECT;
4639 /* only increase the refcount if there is a parent.
4640 if this is a protocol and not a field then parent will be -1
4641 and there is no parent to add any refcounting for.
4643 if (hfinfo->parent != -1) {
4644 header_field_info *parent_hfinfo;
4645 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
4647 /* Mark parent as indirectly referenced unless it is already directly
4648 * referenced, i.e. the user has specified the parent in a filter.
4650 if (parent_hfinfo->ref_type != HF_REF_TYPE_DIRECT)
4651 parent_hfinfo->ref_type = HF_REF_TYPE_INDIRECT;
4656 proto_item_add_subtree(proto_item *pi, const gint idx) {
4662 DISSECTOR_ASSERT(idx >= 0 && idx < num_tree_types);
4664 fi = PITEM_FINFO(pi);
4666 return (proto_tree *)pi;
4668 fi->tree_type = idx;
4670 return (proto_tree *)pi;
4674 proto_item_get_subtree(proto_item *pi) {
4679 fi = PITEM_FINFO(pi);
4680 if ( (!fi) || (fi->tree_type == -1) )
4682 return (proto_tree *)pi;
4686 proto_item_get_parent(const proto_item *ti) {
4693 proto_item_get_parent_nth(proto_item *ti, int gen) {
4706 proto_tree_get_parent(proto_tree *tree) {
4709 return (proto_item *)tree;
4713 proto_tree_get_root(proto_tree *tree) {
4716 while (tree->parent) {
4717 tree = tree->parent;
4723 proto_tree_move_item(proto_tree *tree, proto_item *fixed_item,
4724 proto_item *item_to_move)
4727 /* Revert part of: http://anonsvn.wireshark.org/viewvc?view=rev&revision=32443
4728 * See https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=5500
4730 /* This function doesn't generate any values. It only reorganizes the prococol tree
4731 * so we can bail out immediately if it isn't visible. */
4732 if (!tree || !PTREE_DATA(tree)->visible)
4735 DISSECTOR_ASSERT(item_to_move->parent == tree);
4736 DISSECTOR_ASSERT(fixed_item->parent == tree);
4738 /*** cut item_to_move out ***/
4740 /* is item_to_move the first? */
4741 if (tree->first_child == item_to_move) {
4742 /* simply change first child to next */
4743 tree->first_child = item_to_move->next;
4745 DISSECTOR_ASSERT(tree->last_child != item_to_move);
4747 proto_item *curr_item;
4748 /* find previous and change it's next */
4749 for(curr_item = tree->first_child; curr_item != NULL; curr_item = curr_item->next) {
4750 if (curr_item->next == item_to_move) {
4755 DISSECTOR_ASSERT(curr_item);
4757 curr_item->next = item_to_move->next;
4759 /* fix last_child if required */
4760 if (tree->last_child == item_to_move) {
4761 tree->last_child = curr_item;
4765 /*** insert to_move after fixed ***/
4766 item_to_move->next = fixed_item->next;
4767 fixed_item->next = item_to_move;
4768 if (tree->last_child == fixed_item) {
4769 tree->last_child = item_to_move;
4774 proto_tree_set_appendix(proto_tree *tree, tvbuff_t *tvb, gint start,
4782 fi = PTREE_FINFO(tree);
4786 start += tvb_raw_offset(tvb);
4787 DISSECTOR_ASSERT(start >= 0);
4788 DISSECTOR_ASSERT(length >= 0);
4790 fi->appendix_start = start;
4791 fi->appendix_length = length;
4795 proto_register_protocol(const char *name, const char *short_name,
4796 const char *filter_name)
4798 protocol_t *protocol;
4799 const protocol_t *existing_protocol = NULL;
4800 header_field_info *hfinfo;
4802 const char *existing_name;
4806 gboolean found_invalid;
4809 * Make sure there's not already a protocol with any of those
4810 * names. Crash if there is, as that's an error in the code
4811 * or an inappropriate plugin.
4812 * This situation has to be fixed to not register more than one
4813 * protocol with the same name.
4815 * This is done by reducing the number of strcmp (and alike) calls
4816 * as much as possible, as this significally slows down startup time.
4818 * Drawback: As a hash value is used to reduce insert time,
4819 * this might lead to a hash collision.
4820 * However, although we have somewhat over 1000 protocols, we're using
4821 * a 32 bit int so this is very, very unlikely.
4824 key = (gint *)g_malloc (sizeof(gint));
4825 *key = wrs_str_hash(name);
4827 existing_name = (const char *)g_hash_table_lookup(proto_names, key);
4828 if (existing_name != NULL) {
4829 /* g_error will terminate the program */
4830 g_error("Duplicate protocol name \"%s\"!"
4831 " This might be caused by an inappropriate plugin or a development error.", name);
4833 g_hash_table_insert(proto_names, key, (gpointer)name);
4835 existing_protocol = (const protocol_t *)g_hash_table_lookup(proto_short_names, (gpointer)short_name);
4836 if (existing_protocol != NULL) {
4837 g_error("Duplicate protocol short_name \"%s\"!"
4838 " This might be caused by an inappropriate plugin or a development error.", short_name);
4841 found_invalid = FALSE;
4842 for (i = 0; filter_name[i]; i++) {
4844 if (!(islower(c) || isdigit(c) || c == '-' || c == '_' || c == '.')) {
4845 found_invalid = TRUE;
4848 if (found_invalid) {
4849 g_error("Protocol filter name \"%s\" has one or more invalid characters."
4850 " Allowed are lower characters, digits, '-', '_' and '.'."
4851 " This might be caused by an inappropriate plugin or a development error.", filter_name);
4853 existing_protocol = (const protocol_t *)g_hash_table_lookup(proto_filter_names, (gpointer)filter_name);
4854 if (existing_protocol != NULL) {
4855 g_error("Duplicate protocol filter_name \"%s\"!"
4856 " This might be caused by an inappropriate plugin or a development error.", filter_name);
4859 /* Add this protocol to the list of known protocols; the list
4860 is sorted by protocol short name. */
4861 protocol = g_new(protocol_t, 1);
4862 protocol->name = name;
4863 protocol->short_name = short_name;
4864 protocol->filter_name = filter_name;
4865 protocol->fields = g_ptr_array_new();
4866 protocol->is_enabled = TRUE; /* protocol is enabled by default */
4867 protocol->can_toggle = TRUE;
4868 protocol->is_private = FALSE;
4869 /* list will be sorted later by name, when all protocols completed registering */
4870 protocols = g_list_prepend(protocols, protocol);
4871 g_hash_table_insert(proto_filter_names, (gpointer)filter_name, protocol);
4872 g_hash_table_insert(proto_short_names, (gpointer)short_name, protocol);
4874 /* Here we allocate a new header_field_info struct */
4875 hfinfo = g_slice_new(header_field_info);
4876 hfinfo->name = name;
4877 hfinfo->abbrev = filter_name;
4878 hfinfo->type = FT_PROTOCOL;
4879 hfinfo->display = BASE_NONE;
4880 hfinfo->strings = protocol;
4881 hfinfo->bitmask = 0;
4882 hfinfo->ref_type = HF_REF_TYPE_NONE;
4883 hfinfo->blurb = NULL;
4884 hfinfo->parent = -1; /* this field differentiates protos and fields */
4886 proto_id = proto_register_field_init(hfinfo, hfinfo->parent);
4887 protocol->proto_id = proto_id;
4892 proto_mark_private(const int proto_id)
4894 protocol_t *protocol = find_protocol_by_id(proto_id);
4896 protocol->is_private = TRUE;
4900 proto_is_private(const int proto_id)
4902 protocol_t *protocol = find_protocol_by_id(proto_id);
4904 return protocol->is_private;
4910 * Routines to use to iterate over the protocols.
4911 * The argument passed to the iterator routines is an opaque cookie to
4912 * their callers; it's the GList pointer for the current element in
4914 * The ID of the protocol is returned, or -1 if there is no protocol.
4917 proto_get_first_protocol(void **cookie)
4919 protocol_t *protocol;
4921 if (protocols == NULL)
4923 *cookie = protocols;
4924 protocol = (protocol_t *)protocols->data;
4925 return protocol->proto_id;
4929 proto_get_data_protocol(void *cookie)
4931 GList *list_item = (GList *)cookie;
4933 protocol_t *protocol = (protocol_t *)list_item->data;
4934 return protocol->proto_id;
4938 proto_get_next_protocol(void **cookie)
4940 GList *list_item = (GList *)*cookie;
4941 protocol_t *protocol;
4943 list_item = g_list_next(list_item);
4944 if (list_item == NULL)
4946 *cookie = list_item;
4947 protocol = (protocol_t *)list_item->data;
4948 return protocol->proto_id;
4951 /* XXX: Unfortunately certain functions in proto_hier_tree_model.c
4952 assume that the cookie stored by
4953 proto_get_(first|next)_protocol_field() will never have a
4954 value of NULL. So, to preserve this semantic, the cookie value
4955 below is adjusted so that the cookie value stored is 1 + the
4956 current (zero-based) array index.
4959 proto_get_first_protocol_field(const int proto_id, void **cookie)
4961 protocol_t *protocol = find_protocol_by_id(proto_id);
4963 if ((protocol == NULL) || (protocol->fields->len == 0))
4966 *cookie = GUINT_TO_POINTER(0 + 1);
4967 return (header_field_info *)g_ptr_array_index(protocol->fields, 0);
4971 proto_get_next_protocol_field(const int proto_id, void **cookie)
4973 protocol_t *protocol = find_protocol_by_id(proto_id);
4974 guint i = GPOINTER_TO_UINT(*cookie) - 1;
4978 if (i >= protocol->fields->len)
4981 *cookie = GUINT_TO_POINTER(i + 1);
4982 return (header_field_info *)g_ptr_array_index(protocol->fields, i);
4986 find_protocol_by_id(const int proto_id)
4988 header_field_info *hfinfo;
4993 PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
4994 DISSECTOR_ASSERT(hfinfo->type == FT_PROTOCOL);
4995 return (protocol_t *)hfinfo->strings;
4999 proto_get_id(const protocol_t *protocol)
5001 return protocol->proto_id;
5005 proto_get_id_by_filter_name(const gchar *filter_name)
5007 const protocol_t *protocol = NULL;
5009 DISSECTOR_ASSERT_HINT(filter_name, "No filter name present");
5011 protocol = (const protocol_t *)g_hash_table_lookup(proto_filter_names, (gpointer)filter_name);
5013 if (protocol == NULL)
5015 return protocol->proto_id;
5019 proto_get_id_by_short_name(const gchar *short_name)
5021 const protocol_t *protocol = NULL;
5023 DISSECTOR_ASSERT_HINT(short_name, "No short name present");
5025 protocol = (const protocol_t *)g_hash_table_lookup(proto_short_names, (gpointer)short_name);
5027 if (protocol == NULL)
5029 return protocol->proto_id;
5033 proto_get_protocol_name(const int proto_id)
5035 protocol_t *protocol;
5037 protocol = find_protocol_by_id(proto_id);
5039 if (protocol == NULL)
5041 return protocol->name;
5045 proto_get_protocol_short_name(const protocol_t *protocol)
5047 if (protocol == NULL)
5049 return protocol->short_name;
5053 proto_get_protocol_long_name(const protocol_t *protocol)
5055 if (protocol == NULL)
5057 return protocol->name;
5061 proto_get_protocol_filter_name(const int proto_id)
5063 protocol_t *protocol;
5065 protocol = find_protocol_by_id(proto_id);
5066 if (protocol == NULL)
5068 return protocol->filter_name;
5072 proto_get_frame_protocols(const wmem_list_t *layers, gboolean *is_ip,
5073 gboolean *is_tcp, gboolean *is_udp,
5074 gboolean *is_sctp, gboolean *is_ssl)
5076 wmem_list_frame_t *protos = wmem_list_head(layers);
5078 const char *proto_name;
5080 /* Walk the list of a available protocols in the packet and
5081 find "major" ones. */
5082 /* It might make more sense to assemble and return a bitfield. */
5083 while (protos != NULL)
5085 proto_id = GPOINTER_TO_INT(wmem_list_frame_data(protos));
5086 proto_name = proto_get_protocol_filter_name(proto_id);
5088 if (is_ip && ((!strcmp(proto_name, "ip")) ||
5089 (!strcmp(proto_name, "ipv6")))) {
5091 } else if (is_tcp && !strcmp(proto_name, "tcp")) {
5093 } else if (is_udp && !strcmp(proto_name, "udp")) {
5095 } else if (is_sctp && !strcmp(proto_name, "sctp")) {
5097 } else if (is_ssl && !strcmp(proto_name, "ssl")) {
5101 protos = wmem_list_frame_next(protos);
5106 proto_is_protocol_enabled(const protocol_t *protocol)
5108 return protocol->is_enabled;
5112 proto_can_toggle_protocol(const int proto_id)
5114 protocol_t *protocol;
5116 protocol = find_protocol_by_id(proto_id);
5117 return protocol->can_toggle;
5121 proto_set_decoding(const int proto_id, const gboolean enabled)
5123 protocol_t *protocol;
5125 protocol = find_protocol_by_id(proto_id);
5126 DISSECTOR_ASSERT(protocol->can_toggle);
5127 protocol->is_enabled = enabled;
5131 proto_enable_all(void)
5133 protocol_t *protocol;
5134 GList *list_item = protocols;
5136 if (protocols == NULL)
5140 protocol = (protocol_t *)list_item->data;
5141 if (protocol->can_toggle)
5142 protocol->is_enabled = TRUE;
5143 list_item = g_list_next(list_item);
5148 proto_set_cant_toggle(const int proto_id)
5150 protocol_t *protocol;
5152 protocol = find_protocol_by_id(proto_id);
5153 protocol->can_toggle = FALSE;
5157 proto_register_field_common(protocol_t *proto, header_field_info *hfi, const int parent)
5159 if (proto != NULL) {
5160 g_ptr_array_add(proto->fields, hfi);
5163 return proto_register_field_init(hfi, parent);
5166 /* for use with static arrays only, since we don't allocate our own copies
5167 of the header_field_info struct contained within the hf_register_info struct */
5169 proto_register_field_array(const int parent, hf_register_info *hf, const int num_records)
5171 hf_register_info *ptr = hf;
5175 proto = find_protocol_by_id(parent);
5176 for (i = 0; i < num_records; i++, ptr++) {
5178 * Make sure we haven't registered this yet.
5179 * Most fields have variables associated with them
5180 * that are initialized to -1; some have array elements,
5181 * or possibly uninitialized variables, so we also allow
5182 * 0 (which is unlikely to be the field ID we get back
5183 * from "proto_register_field_init()").
5185 if (*ptr->p_id != -1 && *ptr->p_id != 0) {
5187 "Duplicate field detected in call to proto_register_field_array: %s is already registered\n",
5188 ptr->hfinfo.abbrev);
5192 *ptr->p_id = proto_register_field_common(proto, &ptr->hfinfo, parent);
5197 proto_register_fields_section(const int parent, header_field_info *hfi, const int num_records)
5202 proto = find_protocol_by_id(parent);
5203 for (i = 0; i < num_records; i++) {
5205 * Make sure we haven't registered this yet.
5207 if (hfi[i].id != -1) {
5209 "Duplicate field detected in call to proto_register_fields: %s is already registered\n",
5214 proto_register_field_common(proto, &hfi[i], parent);
5219 proto_register_fields_manual(const int parent, header_field_info **hfi, const int num_records)
5224 proto = find_protocol_by_id(parent);
5225 for (i = 0; i < num_records; i++) {
5227 * Make sure we haven't registered this yet.
5229 if (hfi[i]->id != -1) {
5231 "Duplicate field detected in call to proto_register_fields: %s is already registered\n",
5236 proto_register_field_common(proto, hfi[i], parent);
5240 /* unregister already registered fields */
5242 proto_unregister_field (const int parent, gint hf_id)
5244 hf_register_info *hf;
5248 if (hf_id == -1 || hf_id == 0)
5251 proto = find_protocol_by_id (parent);
5252 if (!proto || proto->fields->len == 0) {
5256 for (i = 0; i < proto->fields->len; i++) {
5257 hf = (hf_register_info *)g_ptr_array_index(proto->fields, i);
5258 if (*hf->p_id == hf_id) {
5259 /* Found the hf_id in this protocol */
5260 g_hash_table_steal(gpa_name_map, hf->hfinfo.abbrev);
5261 g_ptr_array_remove_index_fast(proto->fields, i);
5267 /* chars allowed in field abbrev */
5269 const guchar fld_abbrev_chars[256] = {
5270 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00-0x0F */
5271 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10-0x1F */
5272 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, /* 0x20-0x2F '-', '.' */
5273 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 0x30-0x3F '0'-'9' */
5274 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x40-0x4F 'A'-'O' */
5275 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 0x50-0x5F 'P'-'Z', '_' */
5276 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x60-0x6F 'a'-'o' */
5277 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 0x70-0x7F 'p'-'z' */
5278 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80-0x8F */
5279 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90-0x9F */
5280 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xA0-0xAF */
5281 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xB0-0xBF */
5282 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xC0-0xCF */
5283 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xD0-0xDF */
5284 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xE0-0xEF */
5285 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xF0-0xFF */
5288 static const value_string hf_display[] = {
5289 { BASE_NONE, "BASE_NONE" },
5290 { BASE_DEC, "BASE_DEC" },
5291 { BASE_HEX, "BASE_HEX" },
5292 { BASE_OCT, "BASE_OCT" },
5293 { BASE_DEC_HEX, "BASE_DEC_HEX" },
5294 { BASE_HEX_DEC, "BASE_HEX_DEC" },
5295 { BASE_CUSTOM, "BASE_CUSTOM" },
5296 { BASE_NONE|BASE_RANGE_STRING, "BASE_NONE|BASE_RANGE_STRING" },
5297 { BASE_DEC|BASE_RANGE_STRING, "BASE_DEC|BASE_RANGE_STRING" },
5298 { BASE_HEX|BASE_RANGE_STRING, "BASE_HEX|BASE_RANGE_STRING" },
5299 { BASE_OCT|BASE_RANGE_STRING, "BASE_OCT|BASE_RANGE_STRING" },
5300 { BASE_DEC_HEX|BASE_RANGE_STRING, "BASE_DEC_HEX|BASE_RANGE_STRING" },
5301 { BASE_HEX_DEC|BASE_RANGE_STRING, "BASE_HEX_DEC|BASE_RANGE_STRING" },
5302 { BASE_CUSTOM|BASE_RANGE_STRING, "BASE_CUSTOM|BASE_RANGE_STRING" },
5303 { BASE_NONE|BASE_VAL64_STRING, "BASE_NONE|BASE_VAL64_STRING" },
5304 { BASE_DEC|BASE_VAL64_STRING, "BASE_DEC|BASE_VAL64_STRING" },
5305 { BASE_HEX|BASE_VAL64_STRING, "BASE_HEX|BASE_VAL64_STRING" },
5306 { BASE_OCT|BASE_VAL64_STRING, "BASE_OCT|BASE_VAL64_STRING" },
5307 { BASE_DEC_HEX|BASE_VAL64_STRING, "BASE_DEC_HEX|BASE_VAL64_STRING" },
5308 { BASE_HEX_DEC|BASE_VAL64_STRING, "BASE_HEX_DEC|BASE_VAL64_STRING" },
5309 { BASE_CUSTOM|BASE_VAL64_STRING, "BASE_CUSTOM|BASE_VAL64_STRING" },
5310 /* { STR_ASCII, "STR_ASCII" }, */
5311 { STR_UNICODE, "STR_UNICODE" },
5312 { ABSOLUTE_TIME_LOCAL, "ABSOLUTE_TIME_LOCAL" },
5313 { ABSOLUTE_TIME_UTC, "ABSOLUTE_TIME_UTC" },
5314 { ABSOLUTE_TIME_DOY_UTC, "ABSOLUTE_TIME_DOY_UTC" },
5317 /* temporary function containing assert part for easier profiling */
5319 tmp_fld_check_assert(header_field_info *hfinfo)
5322 /* The field must have a name (with length > 0) */
5323 if (!hfinfo->name || !hfinfo->name[0]) {
5325 /* Try to identify the field */
5326 g_error("Field (abbrev='%s') does not have a name\n",
5330 g_error("Field does not have a name (nor an abbreviation)\n");
5333 /* fields with an empty string for an abbreviation aren't filterable */
5334 if (!hfinfo->abbrev || !hfinfo->abbrev[0])
5335 g_error("Field '%s' does not have an abbreviation\n", hfinfo->name);
5337 /* These types of fields are allowed to have value_strings,
5338 * true_false_strings or a protocol_t struct
5340 if (hfinfo->strings != NULL && !(
5341 (hfinfo->type == FT_UINT8) ||
5342 (hfinfo->type == FT_UINT16) ||
5343 (hfinfo->type == FT_UINT24) ||
5344 (hfinfo->type == FT_UINT32) ||
5345 (hfinfo->type == FT_UINT64) ||
5346 (hfinfo->type == FT_INT8) ||
5347 (hfinfo->type == FT_INT16) ||
5348 (hfinfo->type == FT_INT24) ||
5349 (hfinfo->type == FT_INT32) ||
5350 (hfinfo->type == FT_INT64) ||
5351 (hfinfo->type == FT_BOOLEAN) ||
5352 (hfinfo->type == FT_PROTOCOL) ))
5353 g_error("Field '%s' (%s) has a 'strings' value but is of type %s"
5354 " (which is not allowed to have strings)\n",
5355 hfinfo->name, hfinfo->abbrev, ftype_name(hfinfo->type));
5357 /* TODO: This check may slow down startup, and output quite a few warnings.
5358 It would be good to be able to enable this (and possibly other checks?)
5359 in non-release builds. */
5361 /* Check for duplicate value_string values.
5362 There are lots that have the same value *and* string, so for now only
5363 report those that have same value but different string. */
5364 if ((hfinfo->strings != NULL) &&
5365 !(hfinfo->display & BASE_RANGE_STRING) &&
5366 !((hfinfo->display & FIELD_DISPLAY_E_MASK) == BASE_CUSTOM) &&
5368 (hfinfo->type == FT_UINT8) ||
5369 (hfinfo->type == FT_UINT16) ||
5370 (hfinfo->type == FT_UINT24) ||
5371 (hfinfo->type == FT_UINT32) ||
5372 (hfinfo->type == FT_INT8) ||
5373 (hfinfo->type == FT_INT16) ||
5374 (hfinfo->type == FT_INT24) ||
5375 (hfinfo->type == FT_INT32) ||
5376 (hfinfo->type == FT_FRAMENUM) )) {
5379 const value_string *start_values;
5380 const value_string *current;
5382 if (hfinfo->display & BASE_EXT_STRING)
5383 start_values = VALUE_STRING_EXT_VS_P(((const value_string_ext*)hfinfo->strings));
5385 start_values = (const value_string*)hfinfo->strings;
5386 current = start_values;
5388 for (n=0; current; n++, current++) {
5389 /* Drop out if we reached the end. */
5390 if ((current->value == 0) && (current->strptr == NULL)) {
5394 /* Check value against all previous */
5395 for (m=0; m < n; m++) {
5396 /* There are lots of duplicates with the same string,
5397 so only report if different... */
5398 if ((start_values[m].value == current->value) &&
5399 (strcmp(start_values[m].strptr, current->strptr) != 0)) {
5400 g_warning("Field '%s' (%s) has a conflicting entry in its"
5401 " value_string: %u is at indices %u (%s) and %u (%s))\n",
5402 hfinfo->name, hfinfo->abbrev,
5403 current->value, m, start_values[m].strptr, n, current->strptr);
5411 switch (hfinfo->type) {
5418 /* Hexadecimal and octal are, in printf() and everywhere
5419 * else, unsigned so don't allow dissectors to register a
5420 * signed field to be displayed unsigned. (Else how would
5421 * we display negative values?)
5423 switch (hfinfo->display & FIELD_DISPLAY_E_MASK) {
5428 g_error("Field '%s' (%s) is signed (%s) but is being displayed unsigned (%s)\n",
5429 hfinfo->name, hfinfo->abbrev,
5430 ftype_name(hfinfo->type),
5431 val_to_str(hfinfo->display, hf_display, "(Bit count: %d)"));
5439 /* Require integral types (other than frame number,
5440 * which is always displayed in decimal) to have a
5442 * If there is a strings value then this base is not
5443 * normally used except when constructing a display
5444 * filter for a value not found in the strings lookup.
5446 switch (hfinfo->display & FIELD_DISPLAY_E_MASK) {
5452 case BASE_CUSTOM: /* hfinfo_numeric_value_format() treats this as decimal */
5455 g_error("Field '%s' (%s) is an integral value (%s)"
5456 " but is being displayed as %s\n",
5457 hfinfo->name, hfinfo->abbrev,
5458 ftype_name(hfinfo->type),
5459 val_to_str(hfinfo->display, hf_display, "(Unknown: 0x%x)"));
5465 if (hfinfo->display != BASE_NONE)
5466 g_error("Field '%s' (%s) is an %s but is being displayed as %s instead of BASE_NONE\n",
5467 hfinfo->name, hfinfo->abbrev,
5468 ftype_name(hfinfo->type),
5469 val_to_str(hfinfo->display, hf_display, "(Bit count: %d)"));
5470 if (hfinfo->bitmask != 0)
5471 g_error("Field '%s' (%s) is an %s but has a bitmask\n",
5472 hfinfo->name, hfinfo->abbrev,
5473 ftype_name(hfinfo->type));
5479 case FT_ABSOLUTE_TIME:
5480 if (!(hfinfo->display == ABSOLUTE_TIME_LOCAL ||
5481 hfinfo->display == ABSOLUTE_TIME_UTC ||
5482 hfinfo->display == ABSOLUTE_TIME_DOY_UTC))
5483 g_error("Field '%s' (%s) is a %s but is being displayed as %s instead of as a time\n",
5484 hfinfo->name, hfinfo->abbrev,
5485 ftype_name(hfinfo->type),
5486 val_to_str(hfinfo->display, hf_display, "(Bit count: %d)"));
5487 if (hfinfo->bitmask != 0)
5488 g_error("Field '%s' (%s) is an %s but has a bitmask\n",
5489 hfinfo->name, hfinfo->abbrev,
5490 ftype_name(hfinfo->type));
5495 case FT_UINT_STRING:
5497 switch (hfinfo->display) {
5503 g_error("Field '%s' (%s) is an string value (%s)"
5504 " but is being displayed as %s\n",
5505 hfinfo->name, hfinfo->abbrev,
5506 ftype_name(hfinfo->type),
5507 val_to_str(hfinfo->display, hf_display, "(Unknown: 0x%x)"));
5510 if (hfinfo->bitmask != 0)
5511 g_error("Field '%s' (%s) is an %s but has a bitmask\n",
5512 hfinfo->name, hfinfo->abbrev,
5513 ftype_name(hfinfo->type));
5514 if (hfinfo->strings != NULL)
5515 g_error("Field '%s' (%s) is an %s but has a strings value\n",
5516 hfinfo->name, hfinfo->abbrev,
5517 ftype_name(hfinfo->type));
5521 if (hfinfo->display != BASE_NONE)
5522 g_error("Field '%s' (%s) is an %s but is being displayed as %s instead of BASE_NONE\n",
5523 hfinfo->name, hfinfo->abbrev,
5524 ftype_name(hfinfo->type),
5525 val_to_str(hfinfo->display, hf_display, "(Bit count: %d)"));
5526 if (hfinfo->bitmask != 0)
5527 g_error("Field '%s' (%s) is an %s but has a bitmask\n",
5528 hfinfo->name, hfinfo->abbrev,
5529 ftype_name(hfinfo->type));
5530 if (hfinfo->strings != NULL)
5531 g_error("Field '%s' (%s) is an %s but has a strings value\n",
5532 hfinfo->name, hfinfo->abbrev,
5533 ftype_name(hfinfo->type));
5539 register_type_length_mismatch(void)
5541 static ei_register_info ei[] = {
5542 { &ei_type_length_mismatch_error, { "_ws.type_length.mismatch", PI_MALFORMED, PI_ERROR, "Trying to fetch X with length Y", EXPFILL }},
5543 { &ei_type_length_mismatch_warn, { "_ws.type_length.mismatch", PI_MALFORMED, PI_WARN, "Trying to fetch X with length Y", EXPFILL }},
5546 expert_module_t* expert_type_length_mismatch;
5548 proto_type_length_mismatch = proto_register_protocol("Type Length Mismatch", "Type length mismatch", "_ws.type_length");
5550 expert_type_length_mismatch = expert_register_protocol(proto_type_length_mismatch);
5551 expert_register_field_array(expert_type_length_mismatch, ei, array_length(ei));
5553 /* "Type Length Mismatch" isn't really a protocol, it's an error indication;
5554 disabling them makes no sense. */
5555 proto_set_cant_toggle(proto_type_length_mismatch);
5559 register_number_string_decoding_error(void)
5561 static ei_register_info ei[] = {
5562 { &ei_number_string_decoding_failed_error,
5563 { "_ws.number_string.decoding_error.failed", PI_MALFORMED, PI_ERROR,
5564 "Failed to decode number from string", EXPFILL
5567 { &ei_number_string_decoding_erange_error,
5568 { "_ws.number_string.decoding_error.erange", PI_MALFORMED, PI_ERROR,
5569 "Decoded number from string is out of valid range", EXPFILL
5574 expert_module_t* expert_number_string_decoding_error;
5576 proto_number_string_decoding_error =
5577 proto_register_protocol("Number-String Decoding Error",
5578 "Number-string decoding error",
5579 "_ws.number_string.decoding_error");
5581 expert_number_string_decoding_error =
5582 expert_register_protocol(proto_number_string_decoding_error);
5583 expert_register_field_array(expert_number_string_decoding_error, ei, array_length(ei));
5585 /* "Number-String Decoding Error" isn't really a protocol, it's an error indication;
5586 disabling them makes no sense. */
5587 proto_set_cant_toggle(proto_number_string_decoding_error);
5590 #define PROTO_PRE_ALLOC_HF_FIELDS_MEM (144000+PRE_ALLOC_EXPERT_FIELDS_MEM)
5592 proto_register_field_init(header_field_info *hfinfo, const int parent)
5595 tmp_fld_check_assert(hfinfo);
5597 hfinfo->parent = parent;
5598 hfinfo->same_name_next = NULL;
5599 hfinfo->same_name_prev_id = -1;
5601 /* if we always add and never delete, then id == len - 1 is correct */
5602 if (gpa_hfinfo.len >= gpa_hfinfo.allocated_len) {
5603 if (!gpa_hfinfo.hfi) {
5604 gpa_hfinfo.allocated_len = PROTO_PRE_ALLOC_HF_FIELDS_MEM;
5605 gpa_hfinfo.hfi = (header_field_info **)g_malloc(sizeof(header_field_info *)*PROTO_PRE_ALLOC_HF_FIELDS_MEM);
5607 gpa_hfinfo.allocated_len += 1000;
5608 gpa_hfinfo.hfi = (header_field_info **)g_realloc(gpa_hfinfo.hfi,
5609 sizeof(header_field_info *)*gpa_hfinfo.allocated_len);
5610 /*g_warning("gpa_hfinfo.allocated_len %u", gpa_hfinfo.allocated_len);*/
5613 gpa_hfinfo.hfi[gpa_hfinfo.len] = hfinfo;
5615 hfinfo->id = gpa_hfinfo.len - 1;
5617 /* if we have real names, enter this field in the name tree */
5618 if ((hfinfo->name[0] != 0) && (hfinfo->abbrev[0] != 0 )) {
5620 header_field_info *same_name_next_hfinfo;
5623 /* Check that the filter name (abbreviation) is legal;
5624 * it must contain only alphanumerics, '-', "_", and ".". */
5625 c = wrs_check_charset(fld_abbrev_chars, hfinfo->abbrev);
5627 fprintf(stderr, "Invalid character '%c' in filter name '%s'\n", c, hfinfo->abbrev);
5628 DISSECTOR_ASSERT_NOT_REACHED();
5631 /* We allow multiple hfinfo's to be registered under the same
5632 * abbreviation. This was done for X.25, as, depending
5633 * on whether it's modulo-8 or modulo-128 operation,
5634 * some bitfield fields may be in different bits of
5635 * a byte, and we want to be able to refer to that field
5636 * with one name regardless of whether the packets
5637 * are modulo-8 or modulo-128 packets. */
5639 same_name_hfinfo = NULL;
5641 g_hash_table_insert(gpa_name_map, (gpointer) (hfinfo->abbrev), hfinfo);
5642 /* GLIB 2.x - if it is already present
5643 * the previous hfinfo with the same name is saved
5644 * to same_name_hfinfo by value destroy callback */
5645 if (same_name_hfinfo) {
5646 /* There's already a field with this name.
5647 * Put it after that field in the list of
5648 * fields with this name, then allow the code
5649 * after this if{} block to replace the old
5650 * hfinfo with the new hfinfo in the GTree. Thus,
5651 * we end up with a linked-list of same-named hfinfo's,
5652 * with the root of the list being the hfinfo in the GTree */
5653 same_name_next_hfinfo =
5654 same_name_hfinfo->same_name_next;
5656 hfinfo->same_name_next = same_name_next_hfinfo;
5657 if (same_name_next_hfinfo)
5658 same_name_next_hfinfo->same_name_prev_id = hfinfo->id;
5660 same_name_hfinfo->same_name_next = hfinfo;
5661 hfinfo->same_name_prev_id = same_name_hfinfo->id;
5669 proto_register_subtree_array(gint *const *indices, const int num_indices)
5672 gint *const *ptr = indices;
5675 * If we've already allocated the array of tree types, expand
5676 * it; this lets plugins such as mate add tree types after
5677 * the initial startup. (If we haven't already allocated it,
5678 * we don't allocate it; on the first pass, we just assign
5679 * ett values and keep track of how many we've assigned, and
5680 * when we're finished registering all dissectors we allocate
5681 * the array, so that we do only one allocation rather than
5682 * wasting CPU time and memory by growing the array for each
5683 * dissector that registers ett values.)
5685 if (tree_is_expanded != NULL) {
5686 tree_is_expanded = (guint32 *)g_realloc(tree_is_expanded, (1+((num_tree_types + num_indices)/32)) * sizeof(guint32));
5688 /* set new items to 0 */
5689 /* XXX, slow!!! optimize when needed (align 'i' to 32, and set rest of guint32 to 0) */
5690 for (i = num_tree_types; i < num_tree_types + num_indices; i++)
5691 tree_is_expanded[i >> 5] &= ~(1 << (i & 31));
5695 * Assign "num_indices" subtree numbers starting at "num_tree_types",
5696 * returning the indices through the pointers in the array whose
5697 * first element is pointed to by "indices", and update
5698 * "num_tree_types" appropriately.
5700 for (i = 0; i < num_indices; i++, ptr++, num_tree_types++) {
5702 /* g_error will terminate the program */
5703 g_error("register_subtree_array: subtree item type (ett_...) not -1 !"
5704 " This is a development error:"
5705 " Either the subtree item type has already been assigned or"
5706 " was not initialized to -1.");
5708 **ptr = num_tree_types;
5713 label_concat(char *label_str, gsize pos, const char *str)
5715 if (pos < ITEM_LABEL_LENGTH)
5716 pos += g_strlcpy(label_str + pos, str, ITEM_LABEL_LENGTH - pos);
5722 label_mark_truncated(char *label_str, gsize name_pos)
5724 static const char trunc_str[] = " [truncated]";
5725 const size_t trunc_len = sizeof(trunc_str)-1;
5728 /* ..... field_name: dataaaaaaaaaaaaa
5732 * ..... field_name [truncated]: dataaaaaaaaaaaaa
5734 * name_pos==0 means that we have only data or only a field_name
5737 if (name_pos < ITEM_LABEL_LENGTH - trunc_len) {
5738 memmove(label_str + name_pos + trunc_len, label_str + name_pos, ITEM_LABEL_LENGTH - name_pos - trunc_len);
5739 memcpy(label_str + name_pos, trunc_str, trunc_len);
5741 /* in general, label_str is UTF-8
5742 we can truncate it only at the beginning of a new character
5743 we go backwards from the byte right after our buffer and
5744 find the next starting byte of a UTF-8 character, this is
5746 there's no need to use g_utf8_find_prev_char(), the search
5747 will always succeed since we copied trunc_str into the
5749 last_char = g_utf8_prev_char(&label_str[ITEM_LABEL_LENGTH]);
5752 } else if (name_pos < ITEM_LABEL_LENGTH)
5753 g_strlcpy(label_str + name_pos, trunc_str, ITEM_LABEL_LENGTH - name_pos);
5757 label_fill(char *label_str, gsize pos, const header_field_info *hfinfo, const char *text)
5761 /* "%s: %s", hfinfo->name, text */
5762 name_pos = pos = label_concat(label_str, pos, hfinfo->name);
5763 pos = label_concat(label_str, pos, ": ");
5764 pos = label_concat(label_str, pos, text ? text : "(null)");
5766 if (pos >= ITEM_LABEL_LENGTH) {
5767 /* Uh oh, we don't have enough room. Tell the user that the field is truncated. */
5768 label_mark_truncated(label_str, name_pos);
5775 label_fill_descr(char *label_str, gsize pos, const header_field_info *hfinfo, const char *text, const char *descr)
5779 /* "%s: %s (%s)", hfinfo->name, text, descr */
5780 name_pos = pos = label_concat(label_str, pos, hfinfo->name);
5781 pos = label_concat(label_str, pos, ": ");
5782 pos = label_concat(label_str, pos, text ? text : "(null)");
5783 pos = label_concat(label_str, pos, " (");
5784 pos = label_concat(label_str, pos, descr ? descr : "(null)");
5785 pos = label_concat(label_str, pos, ")");
5787 if (pos >= ITEM_LABEL_LENGTH) {
5788 /* Uh oh, we don't have enough room. Tell the user that the field is truncated. */
5789 label_mark_truncated(label_str, name_pos);
5796 proto_item_fill_label(field_info *fi, gchar *label_str)
5798 header_field_info *hfinfo;
5804 guint32 n_addr; /* network-order IPv4 address */
5812 /* XXX: Check validity of hfinfo->type */
5816 hfinfo = fi->hfinfo;
5818 switch (hfinfo->type) {
5821 g_strlcpy(label_str, hfinfo->name, ITEM_LABEL_LENGTH);
5825 fill_label_boolean(fi, label_str);
5830 bytes = (guint8 *)fvalue_get(&fi->value);
5831 label_fill(label_str, 0, hfinfo,
5832 (bytes) ? bytes_to_ep_str(bytes, fvalue_length(&fi->value)) : "<MISSING>");
5835 /* Four types of integers to take care of:
5836 * Bitfield, with val_string
5837 * Bitfield, w/o val_string
5838 * Non-bitfield, with val_string
5839 * Non-bitfield, w/o val_string
5845 if (hfinfo->bitmask) {
5846 fill_label_bitfield(fi, label_str, FALSE);
5848 fill_label_number(fi, label_str, FALSE);
5853 fill_label_number(fi, label_str, FALSE);
5857 fill_label_number64(fi, label_str, FALSE);
5864 if (hfinfo->bitmask) {
5865 fill_label_bitfield(fi, label_str, TRUE);
5867 fill_label_number(fi, label_str, TRUE);
5872 fill_label_number64(fi, label_str, TRUE);
5876 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5877 "%s: %." G_STRINGIFY(FLT_DIG) "g",
5878 hfinfo->name, fvalue_get_floating(&fi->value));
5882 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5883 "%s: %." G_STRINGIFY(DBL_DIG) "g",
5884 hfinfo->name, fvalue_get_floating(&fi->value));
5887 case FT_ABSOLUTE_TIME:
5888 tmp = abs_time_to_str(NULL, (const nstime_t *)fvalue_get(&fi->value), (absolute_time_display_e)hfinfo->display, TRUE);
5889 label_fill(label_str, 0, hfinfo, tmp);
5890 wmem_free(NULL, tmp);
5893 case FT_RELATIVE_TIME:
5894 tmp = rel_time_to_secs_str(NULL, (const nstime_t *)fvalue_get(&fi->value));
5895 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5896 "%s: %s seconds", hfinfo->name, tmp);
5897 wmem_free(NULL, tmp);
5901 integer = fvalue_get_uinteger(&fi->value);
5902 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5903 "%s: %s (0x%08X)", hfinfo->name,
5904 get_ipxnet_name(integer), integer);
5908 bytes = (guint8 *)fvalue_get(&fi->value);
5909 label_fill_descr(label_str, 0, hfinfo,
5910 get_ax25_name(bytes),
5911 ax25_to_str(bytes));
5915 addr.type = AT_VINES;
5916 addr.len = VINES_ADDR_LEN;
5917 addr.data = (guint8 *)fvalue_get(&fi->value);
5919 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5920 "%s: %s", hfinfo->name,
5921 ep_address_to_str( &addr ));
5925 bytes = (guint8 *)fvalue_get(&fi->value);
5926 label_fill_descr(label_str, 0, hfinfo,
5927 get_ether_name(bytes),
5928 ether_to_str(bytes));
5932 ipv4 = (ipv4_addr *)fvalue_get(&fi->value);
5933 n_addr = ipv4_get_net_order_addr(ipv4);
5934 label_fill_descr(label_str, 0, hfinfo,
5935 get_hostname(n_addr),
5936 ip_to_str((guint8*)&n_addr));
5940 bytes = (guint8 *)fvalue_get(&fi->value);
5941 label_fill_descr(label_str, 0, hfinfo,
5942 get_hostname6((struct e_in6_addr *)bytes),
5943 ip6_to_str((struct e_in6_addr*)bytes));
5947 guid = (e_guid_t *)fvalue_get(&fi->value);
5948 label_fill(label_str, 0, hfinfo, guid_to_ep_str(guid));
5952 bytes = (guint8 *)fvalue_get(&fi->value);
5953 name = oid_resolved_from_encoded(bytes, fvalue_length(&fi->value));
5955 label_fill_descr(label_str, 0, hfinfo,
5956 oid_encoded2string(bytes, fvalue_length(&fi->value)), name);
5958 label_fill(label_str, 0, hfinfo,
5959 oid_encoded2string(bytes, fvalue_length(&fi->value)));
5964 bytes = (guint8 *)fvalue_get(&fi->value);
5965 name = rel_oid_resolved_from_encoded(bytes, fvalue_length(&fi->value));
5967 label_fill_descr(label_str, 0, hfinfo,
5968 rel_oid_encoded2string(bytes, fvalue_length(&fi->value)), name);
5970 label_fill(label_str, 0, hfinfo,
5971 rel_oid_encoded2string(bytes, fvalue_length(&fi->value)));
5976 bytes = (guint8 *)fvalue_get(&fi->value);
5977 label_fill(label_str, 0, hfinfo, print_system_id(bytes, fvalue_length(&fi->value)));
5981 integer64 = fvalue_get_integer64(&fi->value);
5982 label_fill_descr(label_str, 0, hfinfo,
5983 ep_eui64_to_display(integer64),
5984 eui64_to_str(integer64));
5988 case FT_UINT_STRING:
5990 bytes = (guint8 *)fvalue_get(&fi->value);
5991 label_fill(label_str, 0, hfinfo, hfinfo_format_text(hfinfo, bytes));
5995 g_error("hfinfo->type %d (%s) not handled\n",
5996 hfinfo->type, ftype_name(hfinfo->type));
5997 DISSECTOR_ASSERT_NOT_REACHED();
6003 fill_label_boolean(field_info *fi, gchar *label_str)
6005 char *p = label_str;
6006 int bitfield_byte_length = 0, bitwidth;
6007 guint32 unshifted_value;
6010 header_field_info *hfinfo = fi->hfinfo;
6011 const true_false_string *tfstring = (const true_false_string *)&tfs_true_false;
6013 if (hfinfo->strings) {
6014 tfstring = (const struct true_false_string*) hfinfo->strings;
6017 value = fvalue_get_uinteger(&fi->value);
6018 if (hfinfo->bitmask) {
6019 /* Figure out the bit width */
6020 bitwidth = hfinfo_bitwidth(hfinfo);
6023 unshifted_value = value;
6024 unshifted_value <<= hfinfo_bitshift(hfinfo);
6026 /* Create the bitfield first */
6027 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
6028 bitfield_byte_length = (int) (p - label_str);
6031 /* Fill in the textual info */
6032 label_fill(label_str, bitfield_byte_length, hfinfo, value ? tfstring->true_string : tfstring->false_string);
6036 hf_try_val_to_str(guint32 value, const header_field_info *hfinfo)
6038 if (hfinfo->display & BASE_RANGE_STRING)
6039 return try_rval_to_str(value, (const range_string *) hfinfo->strings);
6041 if (hfinfo->display & BASE_EXT_STRING)
6042 return try_val_to_str_ext(value, (value_string_ext *) hfinfo->strings);
6044 if (hfinfo->display & BASE_VAL64_STRING)
6045 return try_val64_to_str(value, (const val64_string *) hfinfo->strings);
6047 return try_val_to_str(value, (const value_string *) hfinfo->strings);
6051 hf_try_val64_to_str(guint64 value, const header_field_info *hfinfo)
6053 if (hfinfo->display & BASE_VAL64_STRING)
6054 return try_val64_to_str(value, (const val64_string *) hfinfo->strings);
6056 /* If this is reached somebody registered a 64-bit field with a 32-bit
6057 * value-string, which isn't right. */
6058 DISSECTOR_ASSERT_NOT_REACHED();
6060 /* This is necessary to squelch MSVC errors; is there
6061 any way to tell it that DISSECTOR_ASSERT_NOT_REACHED()
6067 hf_try_val_to_str_const(guint32 value, const header_field_info *hfinfo, const char *unknown_str)
6069 const char *str = hf_try_val_to_str(value, hfinfo);
6071 return (str) ? str : unknown_str;
6075 hf_try_val64_to_str_const(guint64 value, const header_field_info *hfinfo, const char *unknown_str)
6077 const char *str = hf_try_val64_to_str(value, hfinfo);
6079 return (str) ? str : unknown_str;
6082 /* Fills data for bitfield ints with val_strings */
6084 fill_label_bitfield(field_info *fi, gchar *label_str, gboolean is_signed)
6087 int bitfield_byte_length, bitwidth;
6088 guint32 unshifted_value;
6094 header_field_info *hfinfo = fi->hfinfo;
6096 /* Figure out the bit width */
6097 bitwidth = hfinfo_bitwidth(hfinfo);
6101 unshifted_value = fvalue_get_sinteger(&fi->value);
6103 unshifted_value = fvalue_get_uinteger(&fi->value);
6105 value = unshifted_value;
6106 if (hfinfo->bitmask) {
6107 unshifted_value <<= hfinfo_bitshift(hfinfo);
6110 /* Create the bitfield first */
6111 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
6112 bitfield_byte_length = (int) (p - label_str);
6114 /* Fill in the textual info using stored (shifted) value */
6115 if (hfinfo->display == BASE_CUSTOM) {
6116 gchar tmp[ITEM_LABEL_LENGTH];
6117 const custom_fmt_func_t fmtfunc = (const custom_fmt_func_t)hfinfo->strings;
6119 DISSECTOR_ASSERT(fmtfunc);
6120 fmtfunc(tmp, value);
6121 label_fill(label_str, bitfield_byte_length, hfinfo, tmp);
6123 else if (hfinfo->strings) {
6124 const char *val_str = hf_try_val_to_str_const(value, hfinfo, "Unknown");
6126 out = hfinfo_number_vals_format(hfinfo, buf, value);
6127 if (out == NULL) /* BASE_NONE so don't put integer in descr */
6128 label_fill(label_str, bitfield_byte_length, hfinfo, val_str);
6130 label_fill_descr(label_str, bitfield_byte_length, hfinfo, val_str, out);
6133 out = hfinfo_number_value_format(hfinfo, buf, value);
6135 label_fill(label_str, bitfield_byte_length, hfinfo, out);
6140 fill_label_number(field_info *fi, gchar *label_str, gboolean is_signed)
6142 header_field_info *hfinfo = fi->hfinfo;
6149 value = fvalue_get_sinteger(&fi->value);
6151 value = fvalue_get_uinteger(&fi->value);
6153 /* Fill in the textual info */
6154 if (hfinfo->display == BASE_CUSTOM) {
6155 gchar tmp[ITEM_LABEL_LENGTH];
6156 const custom_fmt_func_t fmtfunc = (const custom_fmt_func_t)hfinfo->strings;
6158 DISSECTOR_ASSERT(fmtfunc);
6159 fmtfunc(tmp, value);
6160 label_fill(label_str, 0, hfinfo, tmp);
6162 else if (hfinfo->strings) {
6163 const char *val_str = hf_try_val_to_str_const(value, hfinfo, "Unknown");
6165 out = hfinfo_number_vals_format(hfinfo, buf, value);
6166 if (out == NULL) /* BASE_NONE so don't put integer in descr */
6167 label_fill(label_str, 0, hfinfo, val_str);
6169 label_fill_descr(label_str, 0, hfinfo, val_str, out);
6172 out = hfinfo_number_value_format(hfinfo, buf, value);
6174 label_fill(label_str, 0, hfinfo, out);
6179 fill_label_number64(field_info *fi, gchar *label_str, gboolean is_signed)
6181 const char *format = NULL;
6182 header_field_info *hfinfo = fi->hfinfo;
6184 char tmp[ITEM_LABEL_LENGTH+1];
6186 /* Pick the proper format string */
6188 format = hfinfo_int64_format(hfinfo);
6190 format = hfinfo_uint64_format(hfinfo);
6192 value = fvalue_get_integer64(&fi->value);
6194 /* Format the temporary string */
6195 if (IS_BASE_DUAL(hfinfo->display))
6196 g_snprintf(tmp, ITEM_LABEL_LENGTH, format, value, value);
6198 g_snprintf(tmp, ITEM_LABEL_LENGTH, format, value);
6200 if (hfinfo->strings) {
6201 const char *val_str = hf_try_val64_to_str_const(value, hfinfo, "Unknown");
6203 if ((hfinfo->display & FIELD_DISPLAY_E_MASK) == BASE_NONE) {
6204 label_fill(label_str, 0, hfinfo, val_str);
6207 label_fill_descr(label_str, 0, hfinfo, val_str, tmp);
6211 label_fill(label_str, 0, hfinfo, tmp);
6216 hfinfo_bitshift(const header_field_info *hfinfo)
6218 return ws_ctz(hfinfo->bitmask);
6222 hfinfo_bitwidth(const header_field_info *hfinfo)
6226 if (!hfinfo->bitmask) {
6230 switch (hfinfo->type) {
6248 bitwidth = hfinfo->display; /* hacky? :) */
6251 DISSECTOR_ASSERT_NOT_REACHED();
6258 _hfinfo_type_hex_octet(int type)
6278 DISSECTOR_ASSERT_NOT_REACHED();
6285 hfinfo_number_value_format_display(const header_field_info *hfinfo, int display, char buf[32], guint32 value)
6287 char *ptr = &buf[31];
6288 gboolean isint = IS_FT_INT(hfinfo->type);
6291 /* Properly format value */
6294 return isint ? int_to_str_back(ptr, (gint32) value) : uint_to_str_back(ptr, value);
6298 ptr = hex_to_str_back(ptr, _hfinfo_type_hex_octet(hfinfo->type), value);
6301 ptr = isint ? int_to_str_back(ptr, (gint32) value) : uint_to_str_back(ptr, value);
6305 return oct_to_str_back(ptr, value);
6308 return hex_to_str_back(ptr, _hfinfo_type_hex_octet(hfinfo->type), value);
6312 ptr = isint ? int_to_str_back(ptr, (gint32) value) : uint_to_str_back(ptr, value);
6315 ptr = hex_to_str_back(ptr, _hfinfo_type_hex_octet(hfinfo->type), value);
6319 DISSECTOR_ASSERT_NOT_REACHED();
6326 hfinfo_number_value_format(const header_field_info *hfinfo, char buf[32], guint32 value)
6328 int display = hfinfo->display;
6330 if (hfinfo->type == FT_FRAMENUM) {
6332 * Frame numbers are always displayed in decimal.
6337 return hfinfo_number_value_format_display(hfinfo, display, buf, value);
6341 hfinfo_numeric_value_format(const header_field_info *hfinfo, char buf[32], guint32 value)
6343 /* Get the underlying BASE_ value */
6344 int display = hfinfo->display & FIELD_DISPLAY_E_MASK;
6346 if (hfinfo->type == FT_FRAMENUM) {
6348 * Frame numbers are always displayed in decimal.
6355 /* case BASE_DEC: */
6357 case BASE_OCT: /* XXX, why we're changing BASE_OCT to BASE_DEC? */
6362 /* case BASE_HEX: */
6368 return hfinfo_number_value_format_display(hfinfo, display, buf, value);
6372 hfinfo_number_vals_format(const header_field_info *hfinfo, char buf[32], guint32 value)
6374 /* Get the underlying BASE_ value */
6375 int display = hfinfo->display & FIELD_DISPLAY_E_MASK;
6377 if (display == BASE_NONE)
6380 if (display == BASE_DEC_HEX)
6382 if (display == BASE_HEX_DEC)
6385 return hfinfo_number_value_format_display(hfinfo, display, buf, value);
6389 hfinfo_uint64_format(const header_field_info *hfinfo)
6391 const char *format = NULL;
6393 /* Pick the proper format string */
6394 switch (hfinfo->display & FIELD_DISPLAY_E_MASK) {
6396 format = "%" G_GINT64_MODIFIER "u";
6399 format = "%" G_GINT64_MODIFIER "u (0x%016" G_GINT64_MODIFIER "x)";
6401 case BASE_OCT: /* I'm lazy */
6402 format = "%#" G_GINT64_MODIFIER "o";
6405 format = "0x%016" G_GINT64_MODIFIER "x";
6408 format = "0x%016" G_GINT64_MODIFIER "x (%" G_GINT64_MODIFIER "u)";
6411 DISSECTOR_ASSERT_NOT_REACHED();
6418 hfinfo_int64_format(const header_field_info *hfinfo)
6420 const char *format = NULL;
6422 /* Pick the proper format string */
6423 switch (hfinfo->display & FIELD_DISPLAY_E_MASK) {
6425 format = "%" G_GINT64_MODIFIER "d";
6428 format = "%" G_GINT64_MODIFIER "d (0x%016" G_GINT64_MODIFIER "x)";
6430 case BASE_OCT: /* I'm lazy */
6431 format = "%#" G_GINT64_MODIFIER "o";
6434 format = "0x%016" G_GINT64_MODIFIER "x";
6437 format = "0x%016" G_GINT64_MODIFIER "x (%" G_GINT64_MODIFIER "d)";
6440 DISSECTOR_ASSERT_NOT_REACHED();
6447 proto_registrar_n(void)
6449 return gpa_hfinfo.len;
6453 proto_registrar_get_name(const int n)
6455 header_field_info *hfinfo;
6457 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
6458 return hfinfo->name;
6462 proto_registrar_get_abbrev(const int n)
6464 header_field_info *hfinfo;
6466 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
6467 return hfinfo->abbrev;
6471 proto_registrar_get_ftype(const int n)
6473 header_field_info *hfinfo;
6475 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
6476 return hfinfo->type;
6480 proto_registrar_get_parent(const int n)
6482 header_field_info *hfinfo;
6484 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
6485 return hfinfo->parent;
6489 proto_registrar_is_protocol(const int n)
6491 header_field_info *hfinfo;
6493 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
6494 return (hfinfo->parent == -1 ? TRUE : FALSE);
6497 /* Returns length of field in packet (not necessarily the length
6498 * in our internal representation, as in the case of IPv4).
6499 * 0 means undeterminable at time of registration
6500 * -1 means the field is not registered. */
6502 proto_registrar_get_length(const int n)
6504 header_field_info *hfinfo;
6506 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
6507 return ftype_length(hfinfo->type);
6510 /* Looks for a protocol or a field in a proto_tree. Returns TRUE if
6511 * it exists anywhere, or FALSE if it exists nowhere. */
6513 proto_check_for_protocol_or_field(const proto_tree* tree, const int id)
6515 GPtrArray *ptrs = proto_get_finfo_ptr_array(tree, id);
6520 else if (g_ptr_array_len(ptrs) > 0) {
6528 /* Return GPtrArray* of field_info pointers for all hfindex that appear in tree.
6529 * This only works if the hfindex was "primed" before the dissection
6530 * took place, as we just pass back the already-created GPtrArray*.
6531 * The caller should *not* free the GPtrArray*; proto_tree_free_node()
6534 proto_get_finfo_ptr_array(const proto_tree *tree, const int id)
6539 if (PTREE_DATA(tree)->interesting_hfids != NULL)
6540 return (GPtrArray *)g_hash_table_lookup(PTREE_DATA(tree)->interesting_hfids,
6541 GINT_TO_POINTER(id));
6547 proto_tracking_interesting_fields(const proto_tree *tree)
6549 GHashTable *interesting_hfids;
6554 interesting_hfids = PTREE_DATA(tree)->interesting_hfids;
6556 return (interesting_hfids != NULL) && g_hash_table_size(interesting_hfids);
6559 /* Helper struct for proto_find_info() and proto_all_finfos() */
6565 /* Helper function for proto_find_info() */
6567 find_finfo(proto_node *node, gpointer data)
6569 field_info *fi = PNODE_FINFO(node);
6570 if (fi && fi->hfinfo) {
6571 if (fi->hfinfo->id == ((ffdata_t*)data)->id) {
6572 g_ptr_array_add(((ffdata_t*)data)->array, fi);
6576 /* Don't stop traversing. */
6580 /* Return GPtrArray* of field_info pointers for all hfindex that appear in a tree.
6581 * This works on any proto_tree, primed or unprimed, but actually searches
6582 * the tree, so it is slower than using proto_get_finfo_ptr_array on a primed tree.
6583 * The caller does need to free the returned GPtrArray with
6584 * g_ptr_array_free(<array>, TRUE).
6587 proto_find_finfo(proto_tree *tree, const int id)
6591 ffdata.array = g_ptr_array_new();
6594 proto_tree_traverse_pre_order(tree, find_finfo, &ffdata);
6596 return ffdata.array;
6599 /* Helper function for proto_all_finfos() */
6601 every_finfo(proto_node *node, gpointer data)
6603 field_info *fi = PNODE_FINFO(node);
6604 if (fi && fi->hfinfo) {
6605 g_ptr_array_add(((ffdata_t*)data)->array, fi);
6608 /* Don't stop traversing. */
6612 /* Return GPtrArray* of field_info pointers containing all hfindexes that appear in a tree. */
6614 proto_all_finfos(proto_tree *tree)
6618 ffdata.array = g_ptr_array_new();
6621 proto_tree_traverse_pre_order(tree, every_finfo, &ffdata);
6623 return ffdata.array;
6634 check_for_offset(proto_node *node, const gpointer data)
6636 field_info *fi = PNODE_FINFO(node);
6637 offset_search_t *offsearch = (offset_search_t *)data;
6639 /* !fi == the top most container node which holds nothing */
6640 if (fi && !PROTO_ITEM_IS_HIDDEN(node) && fi->ds_tvb && offsearch->tvb == fi->ds_tvb) {
6641 if (offsearch->offset >= (guint) fi->start &&
6642 offsearch->offset < (guint) (fi->start + fi->length)) {
6644 offsearch->finfo = fi;
6645 return FALSE; /* keep traversing */
6648 return FALSE; /* keep traversing */
6651 /* Search a proto_tree backwards (from leaves to root) looking for the field
6652 * whose start/length occupies 'offset' */
6653 /* XXX - I couldn't find an easy way to search backwards, so I search
6654 * forwards, w/o stopping. Therefore, the last finfo I find will the be
6655 * the one I want to return to the user. This algorithm is inefficient
6656 * and could be re-done, but I'd have to handle all the children and
6657 * siblings of each node myself. When I have more time I'll do that.
6660 proto_find_field_from_offset(proto_tree *tree, guint offset, tvbuff_t *tvb)
6662 offset_search_t offsearch;
6664 offsearch.offset = offset;
6665 offsearch.finfo = NULL;
6666 offsearch.tvb = tvb;
6668 proto_tree_traverse_pre_order(tree, check_for_offset, &offsearch);
6670 return offsearch.finfo;
6673 /* Dumps the protocols in the registration database to stdout. An independent
6674 * program can take this output and format it into nice tables or HTML or
6677 * There is one record per line. The fields are tab-delimited.
6679 * Field 1 = protocol name
6680 * Field 2 = protocol short name
6681 * Field 3 = protocol filter name
6684 proto_registrar_dump_protocols(void)
6686 protocol_t *protocol;
6688 void *cookie = NULL;
6691 i = proto_get_first_protocol(&cookie);
6693 protocol = find_protocol_by_id(i);
6694 printf("%s\t%s\t%s\n", protocol->name, protocol->short_name,
6695 protocol->filter_name);
6696 i = proto_get_next_protocol(&cookie);
6700 /* Dumps the value_strings, extended value string headers, range_strings
6701 * or true/false strings for fields that have them.
6702 * There is one record per line. Fields are tab-delimited.
6703 * There are four types of records: Value String, Extended Value String Header,
6704 * Range String and True/False String. The first field, 'V', 'E', 'R' or 'T', indicates
6705 * the type of record.
6707 * Note that a record will be generated only if the value_string,... is referenced
6708 * in a registered hfinfo entry.
6714 * Field 2 = Field abbreviation to which this value string corresponds
6715 * Field 3 = Integer value
6718 * Extended Value String Headers
6719 * -----------------------------
6721 * Field 2 = Field abbreviation to which this extended value string header corresponds
6722 * Field 3 = Extended Value String "Name"
6723 * Field 4 = Number of entries in the associated value_string array
6724 * Field 5 = Access Type: "Linear Search", "Binary Search", "Direct (indexed) Access"
6729 * Field 2 = Field abbreviation to which this range string corresponds
6730 * Field 3 = Integer value: lower bound
6731 * Field 4 = Integer value: upper bound
6734 * True/False Strings
6735 * ------------------
6737 * Field 2 = Field abbreviation to which this true/false string corresponds
6738 * Field 3 = True String
6739 * Field 4 = False String
6742 proto_registrar_dump_values(void)
6744 header_field_info *hfinfo;
6746 const value_string *vals;
6747 const val64_string *vals64;
6748 const range_string *range;
6749 const true_false_string *tfs;
6751 len = gpa_hfinfo.len;
6752 for (i = 0; i < len ; i++) {
6753 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
6755 if (hfinfo->id == hf_text_only) {
6759 /* ignore protocols */
6760 if (proto_registrar_is_protocol(i)) {
6763 /* process header fields */
6766 * If this field isn't at the head of the list of
6767 * fields with this name, skip this field - all
6768 * fields with the same name are really just versions
6769 * of the same field stored in different bits, and
6770 * should have the same type/radix/value list, and
6771 * just differ in their bit masks. (If a field isn't
6772 * a bitfield, but can be, say, 1 or 2 bytes long,
6773 * it can just be made FT_UINT16, meaning the
6774 * *maximum* length is 2 bytes, and be used
6777 if (hfinfo->same_name_prev_id != -1)
6785 if (hfinfo->strings != NULL) {
6786 if ((hfinfo->display & FIELD_DISPLAY_E_MASK) != BASE_CUSTOM &&
6787 (hfinfo->type == FT_UINT8 ||
6788 hfinfo->type == FT_UINT16 ||
6789 hfinfo->type == FT_UINT24 ||
6790 hfinfo->type == FT_UINT32 ||
6791 hfinfo->type == FT_UINT64 ||
6792 hfinfo->type == FT_INT8 ||
6793 hfinfo->type == FT_INT16 ||
6794 hfinfo->type == FT_INT24 ||
6795 hfinfo->type == FT_INT32 ||
6796 hfinfo->type == FT_INT64)) {
6798 if (hfinfo->display & BASE_RANGE_STRING) {
6799 range = (const range_string *)hfinfo->strings;
6800 } else if (hfinfo->display & BASE_EXT_STRING) {
6801 vals = VALUE_STRING_EXT_VS_P((value_string_ext *)hfinfo->strings);
6802 } else if (hfinfo->display & BASE_VAL64_STRING) {
6803 vals64 = (const val64_string *)hfinfo->strings;
6805 vals = (const value_string *)hfinfo->strings;
6808 else if (hfinfo->type == FT_BOOLEAN) {
6809 tfs = (const struct true_false_string *)hfinfo->strings;
6813 /* Print value strings? */
6815 if (hfinfo->display & BASE_EXT_STRING) {
6816 value_string_ext *vse_p = (value_string_ext *)hfinfo->strings;
6817 if (!value_string_ext_validate(vse_p)) {
6818 g_warning("Invalid value_string_ext ptr for: %s", hfinfo->abbrev);
6821 try_val_to_str_ext(0, vse_p); /* "prime" the extended value_string */
6822 printf("E\t%s\t%d\t%s\t%s\n",
6824 VALUE_STRING_EXT_VS_NUM_ENTRIES(vse_p),
6825 VALUE_STRING_EXT_VS_NAME(vse_p),
6826 value_string_ext_match_type_str(vse_p));
6829 while (vals[vi].strptr) {
6830 /* Print in the proper base */
6831 if (hfinfo->display == BASE_HEX) {
6832 printf("V\t%s\t0x%x\t%s\n",
6838 printf("V\t%s\t%u\t%s\n",
6848 while (vals64[vi].strptr) {
6849 printf("V64\t%s\t%" G_GINT64_MODIFIER "u\t%s\n",
6857 /* print range strings? */
6860 while (range[vi].strptr) {
6861 /* Print in the proper base */
6862 if ((hfinfo->display & FIELD_DISPLAY_E_MASK) == BASE_HEX) {
6863 printf("R\t%s\t0x%x\t0x%x\t%s\n",
6865 range[vi].value_min,
6866 range[vi].value_max,
6870 printf("R\t%s\t%u\t%u\t%s\n",
6872 range[vi].value_min,
6873 range[vi].value_max,
6880 /* Print true/false strings? */
6882 printf("T\t%s\t%s\t%s\n", hfinfo->abbrev,
6883 tfs->true_string, tfs->false_string);
6889 /* Dumps the contents of the registration database to stdout. An independent
6890 * program can take this output and format it into nice tables or HTML or
6893 * There is one record per line. Each record is either a protocol or a header
6894 * field, differentiated by the first field. The fields are tab-delimited.
6899 * Field 2 = descriptive protocol name
6900 * Field 3 = protocol abbreviation
6905 * Field 2 = descriptive field name
6906 * Field 3 = field abbreviation
6907 * Field 4 = type ( textual representation of the the ftenum type )
6908 * Field 5 = parent protocol abbreviation
6909 * Field 6 = base for display (for integer types); "parent bitfield width" for FT_BOOLEAN
6910 * Field 7 = bitmask: format: hex: 0x....
6911 * Field 8 = blurb describing field
6914 proto_registrar_dump_fields(void)
6916 header_field_info *hfinfo, *parent_hfinfo;
6918 const char *enum_name;
6919 const char *base_name;
6923 len = gpa_hfinfo.len;
6924 for (i = 0; i < len ; i++) {
6925 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
6928 * Skip the pseudo-field for "proto_tree_add_text()" since
6929 * we don't want it in the list of filterable fields.
6931 if (hfinfo->id == hf_text_only)
6934 /* format for protocols */
6935 if (proto_registrar_is_protocol(i)) {
6936 printf("P\t%s\t%s\n", hfinfo->name, hfinfo->abbrev);
6938 /* format for header fields */
6941 * If this field isn't at the head of the list of
6942 * fields with this name, skip this field - all
6943 * fields with the same name are really just versions
6944 * of the same field stored in different bits, and
6945 * should have the same type/radix/value list, and
6946 * just differ in their bit masks. (If a field isn't
6947 * a bitfield, but can be, say, 1 or 2 bytes long,
6948 * it can just be made FT_UINT16, meaning the
6949 * *maximum* length is 2 bytes, and be used
6952 if (hfinfo->same_name_prev_id != -1)
6955 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
6957 enum_name = ftype_name(hfinfo->type);
6960 if (hfinfo->type == FT_UINT8 ||
6961 hfinfo->type == FT_UINT16 ||
6962 hfinfo->type == FT_UINT24 ||
6963 hfinfo->type == FT_UINT32 ||
6964 hfinfo->type == FT_UINT64 ||
6965 hfinfo->type == FT_INT8 ||
6966 hfinfo->type == FT_INT16 ||
6967 hfinfo->type == FT_INT24 ||
6968 hfinfo->type == FT_INT32 ||
6969 hfinfo->type == FT_INT64) {
6971 switch (hfinfo->display & FIELD_DISPLAY_E_MASK) {
6973 base_name = "BASE_NONE";
6976 base_name = "BASE_DEC";
6979 base_name = "BASE_HEX";
6982 base_name = "BASE_OCT";
6985 base_name = "BASE_DEC_HEX";
6988 base_name = "BASE_HEX_DEC";
6991 base_name = "BASE_CUSTOM";
6997 } else if (hfinfo->type == FT_BOOLEAN) {
6998 /* For FT_BOOLEAN: 'display' can be "parent bitfield width" */
6999 g_snprintf(width, sizeof(width), "%d", hfinfo->display);
7003 blurb = hfinfo->blurb;
7006 else if (strlen(blurb) == 0)
7009 printf("F\t%s\t%s\t%s\t%s\t%s\t0x%x\t%s\n",
7010 hfinfo->name, hfinfo->abbrev, enum_name,
7011 parent_hfinfo->abbrev, base_name, hfinfo->bitmask, blurb);
7016 /* Dumps field types and descriptive names to stdout. An independent
7017 * program can take this output and format it into nice tables or HTML or
7020 * There is one record per line. The fields are tab-delimited.
7022 * Field 1 = field type name, e.g. FT_UINT8
7023 * Field 2 = descriptive name, e.g. "Unsigned, 1 byte"
7026 proto_registrar_dump_ftypes(void)
7030 for (fte = 0; fte < FT_NUM_TYPES; fte++) {
7031 printf("%s\t%s\n", ftype_name((ftenum_t)fte), ftype_pretty_name((ftenum_t)fte));
7036 hfinfo_numeric_format(const header_field_info *hfinfo)
7038 const char *format = NULL;
7040 /* Get the underlying BASE_ value */
7041 switch (hfinfo->display & FIELD_DISPLAY_E_MASK) {
7044 case BASE_OCT: /* I'm lazy */
7046 switch (hfinfo->type) {
7048 format = "%s == %" G_GINT64_MODIFIER "u";
7051 format = "%s == %" G_GINT64_MODIFIER "d";
7054 DISSECTOR_ASSERT_NOT_REACHED();
7060 switch (hfinfo->type) {
7063 format = "%s == 0x%016" G_GINT64_MODIFIER "x";
7066 DISSECTOR_ASSERT_NOT_REACHED();
7071 DISSECTOR_ASSERT_NOT_REACHED();
7077 /* This function indicates whether it's possible to construct a
7078 * "match selected" display filter string for the specified field,
7079 * returns an indication of whether it's possible, and, if it's
7080 * possible and "filter" is non-null, constructs the filter and
7081 * sets "*filter" to point to it.
7082 * You do not need to [g_]free() this string since it will be automatically
7083 * freed once the next packet is dissected.
7086 construct_match_selected_string(field_info *finfo, epan_dissect_t *edt,
7089 header_field_info *hfinfo;
7094 gint start, length, length_remaining;
7096 gchar is_signed_num = FALSE;
7101 hfinfo = finfo->hfinfo;
7102 DISSECTOR_ASSERT(hfinfo);
7103 abbrev_len = (int) strlen(hfinfo->abbrev);
7105 if (hfinfo->strings && (hfinfo->display & FIELD_DISPLAY_E_MASK) == BASE_NONE) {
7106 const gchar *str = NULL;
7108 switch (hfinfo->type) {
7114 str = hf_try_val_to_str(fvalue_get_sinteger(&finfo->value), hfinfo);
7121 str = hf_try_val_to_str(fvalue_get_uinteger(&finfo->value), hfinfo);
7128 if (str != NULL && filter != NULL) {
7129 *filter = ep_strdup_printf("%s == \"%s\"", hfinfo->abbrev, str);
7135 * XXX - we can't use the "val_to_string_repr" and "string_repr_len"
7136 * functions for FT_UINT and FT_INT types, as we choose the base in
7137 * the string expression based on the display base of the field.
7139 * Note that the base does matter, as this is also used for
7140 * the protocolinfo tap.
7142 * It might be nice to use them in "proto_item_fill_label()"
7143 * as well, although, there, you'd have to deal with the base
7144 * *and* with resolved values for addresses.
7146 * Perhaps we need two different val_to_string routines, one
7147 * to generate items for display filters and one to generate
7148 * strings for display, and pass to both of them the
7149 * "display" and "strings" values in the header_field_info
7150 * structure for the field, so they can get the base and,
7151 * if the field is Boolean or an enumerated integer type,
7152 * the tables used to generate human-readable values.
7154 switch (hfinfo->type) {
7160 is_signed_num = TRUE;
7167 if (filter != NULL) {
7174 number = fvalue_get_sinteger(&finfo->value);
7176 number = fvalue_get_uinteger(&finfo->value);
7178 out = hfinfo_numeric_value_format(hfinfo, buf, number);
7180 *filter = ep_strdup_printf("%s == %s", hfinfo->abbrev, out);
7186 if (filter != NULL) {
7187 const char *format = hfinfo_numeric_format(hfinfo);
7189 *filter = ep_strdup_printf(format,
7191 fvalue_get_integer64(&finfo->value));
7197 *filter = ep_strdup(finfo->hfinfo->abbrev);
7202 * If the length is 0, just match the name of the
7205 * (Also check for negative values, just in case,
7206 * as we'll cast it to an unsigned value later.)
7208 length = finfo->length;
7211 *filter = ep_strdup(finfo->hfinfo->abbrev);
7218 * This doesn't have a value, so we'd match
7219 * on the raw bytes at this address.
7221 * Should we be allowed to access to the raw bytes?
7222 * If "edt" is NULL, the answer is "no".
7228 * Is this field part of the raw frame tvbuff?
7229 * If not, we can't use "frame[N:M]" to match
7232 * XXX - should this be frame-relative, or
7233 * protocol-relative?
7235 * XXX - does this fallback for non-registered
7236 * fields even make sense?
7238 if (finfo->ds_tvb != edt->tvb)
7239 return FALSE; /* you lose */
7242 * Don't go past the end of that tvbuff.
7244 length_remaining = tvb_captured_length_remaining(finfo->ds_tvb, finfo->start);
7245 if (length > length_remaining)
7246 length = length_remaining;
7250 if (filter != NULL) {
7251 start = finfo->start;
7252 buf_len = 32 + length * 3;
7253 *filter = (char *)ep_alloc0(buf_len);
7256 ptr += g_snprintf(ptr, (gulong) (buf_len-(ptr-*filter)),
7257 "frame[%d:%d] == ", finfo->start, length);
7258 for (i=0; i<length; i++) {
7259 c = tvb_get_guint8(finfo->ds_tvb, start);
7262 ptr += g_snprintf(ptr, (gulong) (buf_len-(ptr-*filter)), "%02x", c);
7265 ptr += g_snprintf(ptr, (gulong) (buf_len-(ptr-*filter)), ":%02x", c);
7272 /* FT_PCRE never appears as a type for a registered field. It is
7273 * only used internally. */
7274 DISSECTOR_ASSERT_NOT_REACHED();
7277 /* By default, use the fvalue's "to_string_repr" method. */
7279 /* Figure out the string length needed.
7280 * The ft_repr length.
7281 * 4 bytes for " == ".
7282 * 1 byte for trailing NUL.
7284 if (filter != NULL) {
7285 dfilter_len = fvalue_string_repr_len(&finfo->value,
7287 dfilter_len += abbrev_len + 4 + 1;
7288 *filter = (char *)ep_alloc0(dfilter_len);
7290 /* Create the string */
7291 g_snprintf(*filter, dfilter_len, "%s == ",
7293 fvalue_to_string_repr(&finfo->value,
7295 &(*filter)[abbrev_len + 4]);
7304 * Returns TRUE if we can do a "match selected" on the field, FALSE
7308 proto_can_match_selected(field_info *finfo, epan_dissect_t *edt)
7310 return construct_match_selected_string(finfo, edt, NULL);
7313 /* This function attempts to construct a "match selected" display filter
7314 * string for the specified field; if it can do so, it returns a pointer
7315 * to the string, otherwise it returns NULL.
7317 * The string is allocated with packet lifetime scope.
7318 * You do not need to [g_]free() this string since it will be automatically
7319 * freed once the next packet is dissected.
7322 proto_construct_match_selected_string(field_info *finfo, epan_dissect_t *edt)
7326 if (!construct_match_selected_string(finfo, edt, &filter))
7331 /* This function is common code for both proto_tree_add_bitmask() and
7332 * proto_tree_add_bitmask_text() functions.
7335 /* NOTE: to support code written when proto_tree_add_bitmask() and
7336 * proto_tree_add_bitmask_text took a
7337 * gboolean as its last argument, with FALSE meaning "big-endian"
7338 * and TRUE meaning "little-endian", we treat any non-zero value of
7339 * "encoding" as meaning "little-endian".
7342 proto_item_add_bitmask_tree(proto_item *item, tvbuff_t *tvb, const int offset,
7343 const int len, const gint ett, const int **fields,
7344 const guint encoding, const int flags,
7348 guint32 available_bits = 0;
7350 proto_tree *tree = NULL;
7351 header_field_info *hf;
7355 value = tvb_get_guint8(tvb, offset);
7356 available_bits = 0xFF;
7359 value = encoding ? tvb_get_letohs(tvb, offset) :
7360 tvb_get_ntohs(tvb, offset);
7361 available_bits = 0xFFFF;
7364 value = encoding ? tvb_get_letoh24(tvb, offset) :
7365 tvb_get_ntoh24(tvb, offset);
7366 available_bits = 0xFFFFFF;
7369 value = encoding ? tvb_get_letohl(tvb, offset) :
7370 tvb_get_ntohl(tvb, offset);
7371 available_bits = 0xFFFFFFFF;
7374 g_assert_not_reached();
7377 tree = proto_item_add_subtree(item, ett);
7379 guint32 present_bits;
7380 PROTO_REGISTRAR_GET_NTH(**fields,hf);
7381 DISSECTOR_ASSERT(hf->bitmask != 0);
7383 /* Skip fields that aren't fully present */
7384 present_bits = available_bits & hf->bitmask;
7385 if (present_bits != hf->bitmask) {
7390 proto_tree_add_item(tree, **fields, tvb, offset, len, encoding);
7391 if (flags & BMT_NO_APPEND) {
7395 tmpval = (value & hf->bitmask) >> hfinfo_bitshift(hf);
7406 if (hf->display == BASE_CUSTOM) {
7407 gchar lbl[ITEM_LABEL_LENGTH];
7408 const custom_fmt_func_t fmtfunc = (const custom_fmt_func_t)hf->strings;
7410 DISSECTOR_ASSERT(fmtfunc);
7411 fmtfunc(lbl, tmpval);
7412 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
7416 else if (hf->strings) {
7417 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
7418 hf->name, hf_try_val_to_str_const(tmpval, hf, "Unknown"));
7421 else if (!(flags & BMT_NO_INT)) {
7426 proto_item_append_text(item, ", ");
7429 out = hfinfo_number_value_format(hf, buf, tmpval);
7430 proto_item_append_text(item, "%s: %s", hf->name, out);
7436 if (hf->strings && !(flags & BMT_NO_TFS)) {
7437 /* If we have true/false strings, emit full - otherwise messages
7439 const struct true_false_string *tfs =
7440 (const struct true_false_string *)hf->strings;
7443 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
7444 hf->name, tfs->true_string);
7446 } else if (!(flags & BMT_NO_FALSE)) {
7447 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
7448 hf->name, tfs->false_string);
7451 } else if (hf->bitmask & value) {
7452 /* If the flag is set, show the name */
7453 proto_item_append_text(item, "%s%s", first ? "" : ", ", hf->name);
7458 g_assert_not_reached();
7467 /* This function will dissect a sequence of bytes that describe a
7469 * hf_hdr is a 8/16/24/32 bit integer that describes the bitmask to be dissected.
7470 * This field will form an expansion under which the individual fields of the
7471 * bitmask is dissected and displayed.
7472 * This field must be of the type FT_[U]INT{8|16|24|32}.
7474 * fields is an array of pointers to int that lists all the fields of the
7475 * bitmask. These fields can be either of the type FT_BOOLEAN for flags
7476 * or another integer of the same type/size as hf_hdr with a mask specified.
7477 * This array is terminated by a NULL entry.
7479 * FT_BOOLEAN bits that are set to 1 will have the name added to the expansion.
7480 * FT_integer fields that have a value_string attached will have the
7481 * matched string displayed on the expansion line.
7484 proto_tree_add_bitmask(proto_tree *parent_tree, tvbuff_t *tvb,
7485 const guint offset, const int hf_hdr,
7486 const gint ett, const int **fields,
7487 const guint encoding)
7489 proto_item *item = NULL;
7490 header_field_info *hf;
7493 PROTO_REGISTRAR_GET_NTH(hf_hdr,hf);
7494 DISSECTOR_ASSERT(IS_FT_INT(hf->type) || IS_FT_UINT(hf->type));
7495 len = ftype_length(hf->type);
7498 item = proto_tree_add_item(parent_tree, hf_hdr, tvb, offset, len, encoding);
7499 proto_item_add_bitmask_tree(item, tvb, offset, len, ett, fields, encoding,
7500 BMT_NO_INT|BMT_NO_TFS, FALSE);
7506 /* The same as proto_tree_add_bitmask(), but using a caller-supplied length.
7507 * This is intended to support bitmask fields whose lengths can vary, perhaps
7508 * as the underlying standard evolves over time.
7509 * With this API there is the possibility of being called to display more or
7510 * less data than the dissector was coded to support.
7511 * In such cases, it is assumed that bitmasks are extended on the MSb end.
7512 * Thus when presented with "too much" or "too little" data, MSbits will be
7513 * ignored or MSfields sacrificed.
7515 * Only fields for which all defined bits are available are displayed.
7518 proto_tree_add_bitmask_len(proto_tree *parent_tree, tvbuff_t *tvb,
7519 const guint offset, const guint len, const int hf_hdr,
7520 const gint ett, const int **fields, struct expert_field* exp,
7521 const guint encoding)
7523 proto_item *item = NULL;
7524 header_field_info *hf;
7525 guint decodable_len;
7526 guint decodable_offset;
7527 guint32 decodable_value;
7529 PROTO_REGISTRAR_GET_NTH(hf_hdr, hf);
7530 DISSECTOR_ASSERT(IS_FT_INT(hf->type) || IS_FT_UINT(hf->type));
7532 decodable_offset = offset;
7533 decodable_len = MIN(len, (guint) ftype_length(hf->type));
7535 /* If we are ftype_length-limited,
7536 * make sure we decode as many LSBs as possible.
7538 if (encoding == ENC_BIG_ENDIAN) {
7539 decodable_offset += (len - decodable_len);
7543 decodable_value = get_uint_value(parent_tree, tvb, decodable_offset,
7544 decodable_len, encoding);
7546 /* The root item covers all the bytes even if we can't decode them all */
7547 item = proto_tree_add_uint(parent_tree, hf_hdr, tvb, offset, len,
7551 if (decodable_len < len) {
7552 /* Dissector likely requires updating for new protocol revision */
7553 expert_add_info_format(NULL, item, exp,
7554 "Only least-significant %d of %d bytes decoded",
7555 decodable_len, len);
7559 proto_item_add_bitmask_tree(item, tvb, decodable_offset, decodable_len,
7560 ett, fields, encoding, BMT_NO_INT|BMT_NO_TFS, FALSE);
7566 /* The same as proto_tree_add_bitmask(), but using an arbitrary text as a top-level item */
7568 proto_tree_add_bitmask_text(proto_tree *parent_tree, tvbuff_t *tvb,
7569 const guint offset, const guint len,
7570 const char *name, const char *fallback,
7571 const gint ett, const int **fields,
7572 const guint encoding, const int flags)
7574 proto_item *item = NULL;
7577 item = proto_tree_add_text(parent_tree, tvb, offset, len, "%s", name ? name : "");
7578 if (proto_item_add_bitmask_tree(item, tvb, offset, len, ett, fields, encoding,
7579 flags, TRUE) && fallback) {
7580 /* Still at first item - append 'fallback' text if any */
7581 proto_item_append_text(item, "%s", fallback);
7589 proto_tree_add_bits_item(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
7590 const guint bit_offset, const gint no_of_bits,
7591 const guint encoding)
7593 header_field_info *hfinfo;
7597 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
7599 octet_length = (no_of_bits + 7) >> 3;
7600 octet_offset = bit_offset >> 3;
7601 test_length(hfinfo, tvb, octet_offset, octet_length);
7603 /* Yes, we try to fake this item again in proto_tree_add_bits_ret_val()
7604 * but only after doing a bunch more work (which we can, in the common
7605 * case, shortcut here).
7607 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
7609 return proto_tree_add_bits_ret_val(tree, hfindex, tvb, bit_offset, no_of_bits, NULL, encoding);
7613 * This function will dissect a sequence of bits that does not need to be byte aligned; the bits
7614 * set will be shown in the tree as ..10 10.. and the integer value returned if return_value is set.
7615 * Offset should be given in bits from the start of the tvb.
7619 _proto_tree_add_bits_ret_val(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
7620 const guint bit_offset, const gint no_of_bits,
7621 guint64 *return_value, const guint encoding)
7627 char lbl_str[ITEM_LABEL_LENGTH];
7631 header_field_info *hf_field;
7633 const true_false_string *tfstring;
7635 /* We can't fake it just yet. We have to fill in the 'return_value' parameter */
7636 PROTO_REGISTRAR_GET_NTH(hfindex, hf_field);
7638 if (hf_field->bitmask != 0) {
7639 REPORT_DISSECTOR_BUG(ep_strdup_printf("Incompatible use of proto_tree_add_bits_ret_val"
7640 " with field '%s' (%s) with bitmask != 0",
7641 hf_field->abbrev, hf_field->name));
7644 DISSECTOR_ASSERT(no_of_bits > 0);
7646 /* Byte align offset */
7647 offset = bit_offset>>3;
7650 * Calculate the number of octets used to hold the bits
7652 tot_no_bits = ((bit_offset&0x7) + no_of_bits);
7653 length = (tot_no_bits + 7) >> 3;
7655 if (no_of_bits < 65) {
7656 value = tvb_get_bits64(tvb, bit_offset, no_of_bits, encoding);
7658 DISSECTOR_ASSERT_NOT_REACHED();
7662 /* Sign extend for signed types */
7663 switch (hf_field->type) {
7669 value = ws_sign_ext64(value, no_of_bits);
7677 *return_value = value;
7680 /* Coast clear. Try and fake it */
7681 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
7683 bf_str = decode_bits_in_field(bit_offset, no_of_bits, value);
7685 switch (hf_field->type) {
7688 tfstring = (const true_false_string *) &tfs_true_false;
7689 if (hf_field->strings)
7690 tfstring = (const true_false_string *)hf_field->strings;
7691 return proto_tree_add_boolean_format(tree, hfindex, tvb, offset, length, (guint32)value,
7693 bf_str, hf_field->name,
7694 (guint32)value ? tfstring->true_string : tfstring->false_string);
7701 pi = proto_tree_add_uint(tree, hfindex, tvb, offset, length, (guint32)value);
7702 fill_label_number(PITEM_FINFO(pi), lbl_str, FALSE);
7709 pi = proto_tree_add_int(tree, hfindex, tvb, offset, length, (gint32)value);
7710 fill_label_number(PITEM_FINFO(pi), lbl_str, TRUE);
7714 pi = proto_tree_add_uint64(tree, hfindex, tvb, offset, length, value);
7715 fill_label_number64(PITEM_FINFO(pi), lbl_str, FALSE);
7719 pi = proto_tree_add_int64(tree, hfindex, tvb, offset, length, (gint64)value);
7720 fill_label_number64(PITEM_FINFO(pi), lbl_str, TRUE);
7724 DISSECTOR_ASSERT_NOT_REACHED();
7729 proto_item_set_text(pi, "%s = %s", bf_str, lbl_str);
7734 proto_tree_add_split_bits_item_ret_val(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
7735 const guint bit_offset, const crumb_spec_t *crumb_spec,
7736 guint64 *return_value)
7741 guint mask_initial_bit_offset;
7742 guint mask_greatest_bit_offset;
7746 char lbl_str[ITEM_LABEL_LENGTH];
7748 guint64 composite_bitmask;
7749 guint64 composite_bitmap;
7751 header_field_info *hf_field;
7752 const true_false_string *tfstring;
7754 /* We can't fake it just yet. We have to fill in the 'return_value' parameter */
7755 PROTO_REGISTRAR_GET_NTH(hfindex, hf_field);
7757 if (hf_field->bitmask != 0) {
7758 REPORT_DISSECTOR_BUG(ep_strdup_printf(
7759 "Incompatible use of proto_tree_add_split_bits_item_ret_val"
7760 " with field '%s' (%s) with bitmask != 0",
7761 hf_field->abbrev, hf_field->name));
7764 mask_initial_bit_offset = bit_offset % 8;
7769 mask_greatest_bit_offset = 0;
7770 composite_bitmask = 0;
7771 composite_bitmap = 0;
7773 while (crumb_spec[i].crumb_bit_length != 0) {
7774 guint64 crumb_mask, crumb_value;
7775 guint8 crumb_end_bit_offset;
7777 DISSECTOR_ASSERT(i < 64);
7778 crumb_value = tvb_get_bits64(tvb,
7779 bit_offset + crumb_spec[i].crumb_bit_offset,
7780 crumb_spec[i].crumb_bit_length,
7782 value += crumb_value;
7783 no_of_bits += crumb_spec[i].crumb_bit_length;
7785 /* The bitmask is 64 bit, left-aligned, starting at the first bit of the
7786 octet containing the initial offset.
7787 If the mask is beyond 32 bits, then give up on bit map display.
7788 This could be improved in future, probably showing a table
7789 of 32 or 64 bits per row */
7790 if (mask_greatest_bit_offset < 32) {
7791 crumb_end_bit_offset = mask_initial_bit_offset
7792 + crumb_spec[i].crumb_bit_offset
7793 + crumb_spec[i].crumb_bit_length;
7794 crumb_mask = (G_GUINT64_CONSTANT(1) << crumb_spec[i].crumb_bit_length) - 1;
7796 if (crumb_end_bit_offset > mask_greatest_bit_offset) {
7797 mask_greatest_bit_offset = crumb_end_bit_offset;
7799 composite_bitmask |= (crumb_mask << (64 - crumb_end_bit_offset));
7800 composite_bitmap |= (crumb_value << (64 - crumb_end_bit_offset));
7802 /* Shift left for the next segment */
7803 value <<= crumb_spec[++i].crumb_bit_length;
7806 /* Sign extend for signed types */
7807 switch (hf_field->type) {
7813 value = ws_sign_ext64(value, no_of_bits);
7820 *return_value = value;
7823 /* Coast clear. Try and fake it */
7824 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
7826 /* initialise the format string */
7827 bf_str = (char *)ep_alloc(256);
7830 octet_offset = bit_offset >> 3;
7832 /* Round up mask length to nearest octet */
7833 octet_length = ((mask_greatest_bit_offset + 7) >> 3);
7834 mask_greatest_bit_offset = octet_length << 3;
7836 /* As noted above, we currently only produce a bitmap if the crumbs span less than 4 octets of the tvb.
7837 It would be a useful enhancement to eliminate this restriction. */
7838 if (mask_greatest_bit_offset <= 32) {
7839 other_decode_bitfield_value(bf_str,
7840 (guint32)(composite_bitmap >> (64 - mask_greatest_bit_offset)),
7841 (guint32)(composite_bitmask >> (64 - mask_greatest_bit_offset)),
7842 mask_greatest_bit_offset);
7845 switch (hf_field->type) {
7846 case FT_BOOLEAN: /* it is a bit odd to have a boolean encoded as split-bits, but possible, I suppose? */
7848 tfstring = (const true_false_string *) &tfs_true_false;
7849 if (hf_field->strings)
7850 tfstring = (const true_false_string *) hf_field->strings;
7851 return proto_tree_add_boolean_format(tree, hfindex,
7852 tvb, octet_offset, octet_length, (guint32)value,
7854 bf_str, hf_field->name,
7855 (guint32)value ? tfstring->true_string : tfstring->false_string);
7862 pi = proto_tree_add_uint(tree, hfindex, tvb, octet_offset, octet_length, (guint32)value);
7863 fill_label_number(PITEM_FINFO(pi), lbl_str, FALSE);
7870 pi = proto_tree_add_int(tree, hfindex, tvb, octet_offset, octet_length, (gint32)value);
7871 fill_label_number(PITEM_FINFO(pi), lbl_str, TRUE);
7875 pi = proto_tree_add_uint64(tree, hfindex, tvb, octet_offset, octet_length, value);
7876 fill_label_number64(PITEM_FINFO(pi), lbl_str, FALSE);
7880 pi = proto_tree_add_int64(tree, hfindex, tvb, octet_offset, octet_length, (gint64)value);
7881 fill_label_number64(PITEM_FINFO(pi), lbl_str, TRUE);
7885 DISSECTOR_ASSERT_NOT_REACHED();
7889 proto_item_set_text(pi, "%s = %s", bf_str, lbl_str);
7894 proto_tree_add_split_bits_crumb(proto_tree *tree, const int hfindex, tvbuff_t *tvb, const guint bit_offset,
7895 const crumb_spec_t *crumb_spec, guint16 crumb_index)
7897 header_field_info *hfinfo;
7899 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
7900 proto_tree_add_text(tree, tvb,
7902 ((bit_offset + crumb_spec[crumb_index].crumb_bit_length - 1) >> 3) - (bit_offset >> 3) + 1,
7903 "%s crumb %d of %s (decoded above)",
7904 decode_bits_in_field(bit_offset, crumb_spec[crumb_index].crumb_bit_length,
7907 crumb_spec[crumb_index].crumb_bit_length,
7914 proto_tree_add_bits_ret_val(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
7915 const guint bit_offset, const gint no_of_bits,
7916 guint64 *return_value, const guint encoding)
7920 if ((item = _proto_tree_add_bits_ret_val(tree, hfindex, tvb,
7921 bit_offset, no_of_bits,
7922 return_value, encoding))) {
7923 FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_OFFSET(bit_offset));
7924 FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_SIZE(no_of_bits));
7930 _proto_tree_add_bits_format_value(proto_tree *tree, const int hfindex,
7931 tvbuff_t *tvb, const guint bit_offset,
7932 const gint no_of_bits, void *value_ptr,
7940 header_field_info *hf_field;
7942 /* We do not have to return a value, try to fake it as soon as possible */
7943 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
7945 if (hf_field->bitmask != 0) {
7946 REPORT_DISSECTOR_BUG(ep_strdup_printf(
7947 "Incompatible use of proto_tree_add_bits_format_value"
7948 " with field '%s' (%s) with bitmask != 0",
7949 hf_field->abbrev, hf_field->name));
7952 DISSECTOR_ASSERT(no_of_bits > 0);
7954 /* Byte align offset */
7955 offset = bit_offset>>3;
7958 * Calculate the number of octets used to hold the bits
7960 tot_no_bits = ((bit_offset&0x7) + no_of_bits);
7961 length = tot_no_bits>>3;
7962 /* If we are using part of the next octet, increase length by 1 */
7963 if (tot_no_bits & 0x07)
7966 if (no_of_bits < 65) {
7967 value = tvb_get_bits64(tvb, bit_offset, no_of_bits, ENC_BIG_ENDIAN);
7969 DISSECTOR_ASSERT_NOT_REACHED();
7973 str = decode_bits_in_field(bit_offset, no_of_bits, value);
7975 g_strlcat(str, " = ", 256+64);
7976 g_strlcat(str, hf_field->name, 256+64);
7979 * This function does not receive an actual value but a dimensionless pointer to that value.
7980 * For this reason, the type of the header field is examined in order to determine
7981 * what kind of value we should read from this address.
7982 * The caller of this function must make sure that for the specific header field type the address of
7983 * a compatible value is provided.
7985 switch (hf_field->type) {
7987 return proto_tree_add_boolean_format(tree, hfindex, tvb, offset, length, *(guint32 *)value_ptr,
7988 "%s: %s", str, value_str);
7995 return proto_tree_add_uint_format(tree, hfindex, tvb, offset, length, *(guint32 *)value_ptr,
7996 "%s: %s", str, value_str);
8000 return proto_tree_add_uint64_format(tree, hfindex, tvb, offset, length, *(guint64 *)value_ptr,
8001 "%s: %s", str, value_str);
8008 return proto_tree_add_int_format(tree, hfindex, tvb, offset, length, *(gint32 *)value_ptr,
8009 "%s: %s", str, value_str);
8013 return proto_tree_add_int64_format(tree, hfindex, tvb, offset, length, *(gint64 *)value_ptr,
8014 "%s: %s", str, value_str);
8018 return proto_tree_add_float_format(tree, hfindex, tvb, offset, length, *(float *)value_ptr,
8019 "%s: %s", str, value_str);
8023 DISSECTOR_ASSERT_NOT_REACHED();
8030 proto_tree_add_bits_format_value(proto_tree *tree, const int hfindex,
8031 tvbuff_t *tvb, const guint bit_offset,
8032 const gint no_of_bits, void *value_ptr,
8037 if ((item = _proto_tree_add_bits_format_value(tree, hfindex,
8038 tvb, bit_offset, no_of_bits,
8039 value_ptr, value_str))) {
8040 FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_OFFSET(bit_offset));
8041 FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_SIZE(no_of_bits));
8046 #define CREATE_VALUE_STRING(dst,format,ap) \
8047 va_start(ap, format); \
8048 dst = ep_strdup_vprintf(format, ap); \
8052 proto_tree_add_uint_bits_format_value(proto_tree *tree, const int hfindex,
8053 tvbuff_t *tvb, const guint bit_offset,
8054 const gint no_of_bits, guint32 value,
8055 const char *format, ...)
8059 header_field_info *hf_field;
8061 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
8063 switch (hf_field->type) {
8071 DISSECTOR_ASSERT_NOT_REACHED();
8076 CREATE_VALUE_STRING(dst, format, ap);
8078 return proto_tree_add_bits_format_value(tree, hfindex, tvb, bit_offset, no_of_bits, &value, dst);
8082 proto_tree_add_float_bits_format_value(proto_tree *tree, const int hfindex,
8083 tvbuff_t *tvb, const guint bit_offset,
8084 const gint no_of_bits, float value,
8085 const char *format, ...)
8089 header_field_info *hf_field;
8091 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
8093 DISSECTOR_ASSERT(hf_field->type == FT_FLOAT);
8095 CREATE_VALUE_STRING(dst, format, ap);
8097 return proto_tree_add_bits_format_value(tree, hfindex, tvb, bit_offset, no_of_bits, &value, dst);
8101 proto_tree_add_int_bits_format_value(proto_tree *tree, const int hfindex,
8102 tvbuff_t *tvb, const guint bit_offset,
8103 const gint no_of_bits, gint32 value,
8104 const char *format, ...)
8108 header_field_info *hf_field;
8110 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
8112 switch (hf_field->type) {
8120 DISSECTOR_ASSERT_NOT_REACHED();
8125 CREATE_VALUE_STRING(dst, format, ap);
8127 return proto_tree_add_bits_format_value(tree, hfindex, tvb, bit_offset, no_of_bits, &value, dst);
8131 proto_tree_add_boolean_bits_format_value(proto_tree *tree, const int hfindex,
8132 tvbuff_t *tvb, const guint bit_offset,
8133 const gint no_of_bits, guint32 value,
8134 const char *format, ...)
8138 header_field_info *hf_field;
8140 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
8142 DISSECTOR_ASSERT(hf_field->type == FT_BOOLEAN);
8144 CREATE_VALUE_STRING(dst, format, ap);
8146 return proto_tree_add_bits_format_value(tree, hfindex, tvb, bit_offset, no_of_bits, &value, dst);
8150 proto_tree_add_ts_23_038_7bits_item(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
8151 const guint bit_offset, const gint no_of_chars)
8154 header_field_info *hfinfo;
8159 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
8161 DISSECTOR_ASSERT(hfinfo->type == FT_STRING);
8163 byte_length = (((no_of_chars + 1) * 7) + (bit_offset & 0x07)) >> 3;
8164 byte_offset = bit_offset >> 3;
8166 string = tvb_get_ts_23_038_7bits_string(wmem_packet_scope(), tvb, bit_offset, no_of_chars);
8168 if (hfinfo->display == STR_UNICODE) {
8169 DISSECTOR_ASSERT(g_utf8_validate(string, -1, NULL));
8172 pi = proto_tree_add_pi(tree, hfinfo, tvb, byte_offset, &byte_length);
8173 DISSECTOR_ASSERT(byte_length >= 0);
8174 proto_tree_set_string(PNODE_FINFO(pi), string);
8180 proto_tree_add_ascii_7bits_item(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
8181 const guint bit_offset, const gint no_of_chars)
8184 header_field_info *hfinfo;
8189 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
8191 DISSECTOR_ASSERT(hfinfo->type == FT_STRING);
8193 byte_length = (((no_of_chars + 1) * 7) + (bit_offset & 0x07)) >> 3;
8194 byte_offset = bit_offset >> 3;
8196 string = tvb_get_ascii_7bits_string(wmem_packet_scope(), tvb, bit_offset, no_of_chars);
8198 if (hfinfo->display == STR_UNICODE) {
8199 DISSECTOR_ASSERT(g_utf8_validate(string, -1, NULL));
8202 pi = proto_tree_add_pi(tree, hfinfo, tvb, byte_offset, &byte_length);
8203 DISSECTOR_ASSERT(byte_length >= 0);
8204 proto_tree_set_string(PNODE_FINFO(pi), string);
8210 proto_check_field_name(const gchar *field_name)
8212 return wrs_check_charset(fld_abbrev_chars, field_name);
8216 tree_expanded(int tree_type)
8218 g_assert(tree_type >= 0 && tree_type < num_tree_types);
8219 return tree_is_expanded[tree_type >> 5] & (1 << (tree_type & 31));
8223 tree_expanded_set(int tree_type, gboolean value)
8225 g_assert(tree_type >= 0 && tree_type < num_tree_types);
8228 tree_is_expanded[tree_type >> 5] |= (1 << (tree_type & 31));
8230 tree_is_expanded[tree_type >> 5] &= ~(1 << (tree_type & 31));
8234 * Editor modelines - http://www.wireshark.org/tools/modelines.html
8239 * indent-tabs-mode: t
8242 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
8243 * :indentSize=8:tabSize=8:noTabs=false: