2 * Routines for protocol tree
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
33 #include <wsutil/bits_ctz.h>
34 #include <wsutil/bits_count_ones.h>
35 #include <wsutil/sign_ext.h>
37 #include <ftypes/ftypes-int.h>
40 #include "exceptions.h"
41 #include "ptvcursor.h"
43 #include "addr_resolv.h"
46 #include "epan_dissect.h"
49 #include "wmem/wmem.h"
51 #include "asm_utils.h"
52 #include "column-utils.h"
53 #include "to_str-int.h"
56 #include "show_exception.h"
58 #include "wspython/wspy_register.h"
60 #include <wsutil/plugins.h>
62 #define SUBTREE_ONCE_ALLOCATION_NUMBER 8
63 #define SUBTREE_MAX_LEVELS 256
64 /* Throw an exception if we exceed this many tree items. */
65 /* XXX - This should probably be a preference */
66 #define MAX_TREE_ITEMS (1 * 1000 * 1000)
69 typedef struct __subtree_lvl {
76 subtree_lvl *pushed_tree;
77 guint8 pushed_tree_index;
78 guint8 pushed_tree_max;
84 #define cVALS(x) (const value_string*)(x)
86 /** See inlined comments.
87 @param tree the tree to append this item to
88 @param hfindex field index
89 @param hfinfo header_field
90 @return the header field matching 'hfinfo' */
91 #define TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo) \
92 /* If this item is not referenced we dont have to do much work \
93 at all but we should still return a node so that field items \
94 below this node (think proto_item_add_subtree()) will still \
95 have somewhere to attach to or else filtering will not work \
96 (they would be ignored since tree would be NULL). \
97 DONT try to fake a node where PTREE_FINFO(tree) is NULL \
98 since dissectors that want to do proto_item_set_len() or \
99 other operations that dereference this would crash. \
100 We fake FT_PROTOCOL unless some clients have requested us \
105 PTREE_DATA(tree)->count++; \
106 if (PTREE_DATA(tree)->count > MAX_TREE_ITEMS) { \
107 if (getenv("WIRESHARK_ABORT_ON_TOO_MANY_ITEMS") != NULL) \
108 g_error("More than %d items in the tree -- possible infinite loop", MAX_TREE_ITEMS); \
109 /* Let the exception handler add items to the tree */ \
110 PTREE_DATA(tree)->count = 0; \
111 THROW_MESSAGE(DissectorError, \
112 ep_strdup_printf("More than %d items in the tree -- possible infinite loop", MAX_TREE_ITEMS)); \
114 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo); \
115 if (!(PTREE_DATA(tree)->visible)) { \
116 if (PTREE_FINFO(tree)) { \
117 if ((hfinfo->ref_type != HF_REF_TYPE_DIRECT) \
118 && (hfinfo->type != FT_PROTOCOL || \
119 PTREE_DATA(tree)->fake_protocols)) { \
120 /* just return tree back to the caller */\
126 /** See inlined comments.
127 @param pi the created protocol item we're about to return */
128 #define TRY_TO_FAKE_THIS_REPR(pi) \
130 if (!(PTREE_DATA(pi)->visible)) { \
131 /* If the tree (GUI) isn't visible it's pointless for us to generate the protocol \
132 * items string representation */ \
136 static const char *hf_try_val_to_str(guint32 value, const header_field_info *hfinfo);
138 static void fill_label_boolean(field_info *fi, gchar *label_str);
139 static void fill_label_bitfield(field_info *fi, gchar *label_str, gboolean is_signed);
140 static void fill_label_number(field_info *fi, gchar *label_str, gboolean is_signed);
141 static void fill_label_number64(field_info *fi, gchar *label_str, gboolean is_signed);
143 static const char *hfinfo_number_value_format_display(const header_field_info *hfinfo, int display, char buf[32], guint32 value);
144 static const char *hfinfo_number_vals_format(const header_field_info *hfinfo, char buf[32], guint32 value);
145 static const char *hfinfo_number_value_format(const header_field_info *hfinfo, char buf[32], guint32 value);
146 static const char *hfinfo_numeric_value_format(const header_field_info *hfinfo, char buf[32], guint32 value);
148 static const char* hfinfo_uint64_format(const header_field_info *hfinfo);
149 static const char* hfinfo_int64_format(const header_field_info *hfinfo);
152 proto_tree_add_node(proto_tree *tree, field_info *fi);
155 get_hfi_length(header_field_info *hfinfo, tvbuff_t *tvb, const gint start, gint *length,
159 new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
160 const gint start, const gint item_length);
163 alloc_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
164 const gint start, gint *length);
167 proto_tree_add_pi(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
168 gint start, gint *length);
171 proto_tree_set_representation_value(proto_item *pi, const char *format, va_list ap);
173 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap);
176 proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb);
178 proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length);
180 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length);
182 proto_tree_set_time(field_info *fi, nstime_t *value_ptr);
184 proto_tree_set_string(field_info *fi, const char* value);
186 proto_tree_set_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length, gint encoding);
188 proto_tree_set_ax25(field_info *fi, const guint8* value);
190 proto_tree_set_ax25_tvb(field_info *fi, tvbuff_t *tvb, gint start);
192 proto_tree_set_vines(field_info *fi, const guint8* value);
194 proto_tree_set_vines_tvb(field_info *fi, tvbuff_t *tvb, gint start);
196 proto_tree_set_ether(field_info *fi, const guint8* value);
198 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start);
200 proto_tree_set_ipxnet(field_info *fi, guint32 value);
202 proto_tree_set_ipv4(field_info *fi, guint32 value);
204 proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr);
206 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
208 proto_tree_set_guid(field_info *fi, const e_guid_t *value_ptr);
210 proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, gint start, const guint encoding);
212 proto_tree_set_oid(field_info *fi, const guint8* value_ptr, gint length);
214 proto_tree_set_oid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
216 proto_tree_set_boolean(field_info *fi, guint32 value);
218 proto_tree_set_float(field_info *fi, float value);
220 proto_tree_set_double(field_info *fi, double value);
222 proto_tree_set_uint(field_info *fi, guint32 value);
224 proto_tree_set_int(field_info *fi, gint32 value);
226 proto_tree_set_int64_tvb(field_info *fi, tvbuff_t *tvb, gint start, guint length, const guint encoding);
228 proto_tree_set_uint64(field_info *fi, guint64 value);
230 proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start, guint length, const guint encoding);
232 proto_tree_set_eui64(field_info *fi, const guint64 value);
234 proto_tree_set_eui64_tvb(field_info *fi, tvbuff_t *tvb, gint start, const guint encoding);
236 /* Handle type length mismatch (now filterable) expert info */
237 static int proto_type_length_mismatch = -1;
238 static expert_field ei_type_length_mismatch_error = EI_INIT;
239 static expert_field ei_type_length_mismatch_warn = EI_INIT;
240 static void register_type_length_mismatch(void);
242 static int proto_register_field_init(header_field_info *hfinfo, const int parent);
244 /* special-case header field used within proto.c */
245 static header_field_info hfi_text_only =
246 { "Text item", "text", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL };
247 int hf_text_only = -1;
249 /* Structure for information about a protocol */
251 const char *name; /* long description */
252 const char *short_name; /* short description */
253 const char *filter_name; /* name of this protocol in filters */
254 GSList *fields; /* fields for this protocol */
255 GSList *last_field; /* pointer to end of list of fields */
256 int proto_id; /* field ID for this protocol */
257 gboolean is_enabled; /* TRUE if protocol is enabled */
258 gboolean can_toggle; /* TRUE if is_enabled can be changed */
259 gboolean is_private; /* TRUE is protocol is private */
262 /* List of all protocols */
263 static GList *protocols = NULL;
265 /* Contains information about a field when a dissector calls
266 * proto_tree_add_item. */
267 #define FIELD_INFO_NEW(pool, fi) fi = wmem_new(pool, field_info)
268 #define FIELD_INFO_FREE(pool, fi) wmem_free(pool, fi)
270 /* Contains the space for proto_nodes. */
271 #define PROTO_NODE_INIT(node) \
272 node->first_child = NULL; \
273 node->last_child = NULL; \
276 #define PROTO_NODE_FREE(pool, node) \
277 wmem_free(pool, node)
279 /* String space for protocol and field items for the GUI */
280 #define ITEM_LABEL_NEW(pool, il) \
281 il = wmem_new(pool, item_label_t);
282 #define ITEM_LABEL_FREE(pool, il) \
285 #define PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo) \
286 if((guint)hfindex >= gpa_hfinfo.len && getenv("WIRESHARK_ABORT_ON_DISSECTOR_BUG")) \
287 g_error("Unregistered hf! index=%d", hfindex); \
288 DISSECTOR_ASSERT_HINT((guint)hfindex < gpa_hfinfo.len, "Unregistered hf!"); \
289 hfinfo = gpa_hfinfo.hfi[hfindex];
291 /* List which stores protocols and fields that have been registered */
292 typedef struct _gpa_hfinfo_t {
294 guint32 allocated_len;
295 header_field_info **hfi;
298 static gpa_hfinfo_t gpa_hfinfo;
300 /* Balanced tree of abbreviations and IDs */
301 static GTree *gpa_name_tree = NULL;
302 static header_field_info *same_name_hfinfo;
304 static void save_same_name_hfinfo(gpointer data)
306 same_name_hfinfo = (header_field_info*)data;
309 /* Points to the first element of an array of bits, indexed by
310 a subtree item type; that array element is TRUE if subtrees of
311 an item of that type are to be expanded. */
312 static guint32 *tree_is_expanded;
314 /* Number of elements in that array. */
317 /* Name hashtables for fast detection of duplicate names */
318 static GHashTable* proto_names = NULL;
319 static GHashTable* proto_short_names = NULL;
320 static GHashTable* proto_filter_names = NULL;
323 proto_compare_name(gconstpointer p1_arg, gconstpointer p2_arg)
325 const protocol_t *p1 = (const protocol_t *)p1_arg;
326 const protocol_t *p2 = (const protocol_t *)p2_arg;
328 return g_ascii_strcasecmp(p1->short_name, p2->short_name);
333 * List of dissector plugins.
336 void (*register_protoinfo)(void); /* routine to call to register protocol information */
337 void (*reg_handoff)(void); /* routine to call to register dissector handoff */
340 static GSList *dissector_plugins = NULL;
343 * Callback for each plugin found.
346 check_for_dissector_plugin(GModule *handle)
349 void (*register_protoinfo)(void);
350 void (*reg_handoff)(void);
351 dissector_plugin *plugin;
354 * Do we have a register routine?
356 if (g_module_symbol(handle, "plugin_register", &gp))
357 register_protoinfo = (void (*)(void))gp;
359 register_protoinfo = NULL;
362 * Do we have a reg_handoff routine?
364 if (g_module_symbol(handle, "plugin_reg_handoff", &gp))
365 reg_handoff = (void (*)(void))gp;
370 * If we have neither, we're not a dissector plugin.
372 if (register_protoinfo == NULL && reg_handoff == NULL)
376 * Add this one to the list of dissector plugins.
378 plugin = (dissector_plugin *)g_malloc(sizeof (dissector_plugin));
379 plugin->register_protoinfo = register_protoinfo;
380 plugin->reg_handoff = reg_handoff;
381 dissector_plugins = g_slist_append(dissector_plugins, plugin);
386 register_dissector_plugin(gpointer data, gpointer user_data _U_)
388 dissector_plugin *plugin = (dissector_plugin *)data;
390 if (plugin->register_protoinfo)
391 (plugin->register_protoinfo)();
395 reg_handoff_dissector_plugin(gpointer data, gpointer user_data _U_)
397 dissector_plugin *plugin = (dissector_plugin *)data;
399 if (plugin->reg_handoff)
400 (plugin->reg_handoff)();
404 * Register dissector plugin type.
407 register_dissector_plugin_type(void)
409 add_plugin_type("dissector", check_for_dissector_plugin);
411 #endif /* HAVE_PLUGINS */
413 /* initialize data structures and register protocols and fields */
415 proto_init(void (register_all_protocols_func)(register_cb cb, gpointer client_data),
416 void (register_all_handoffs_func)(register_cb cb, gpointer client_data),
418 gpointer client_data)
422 proto_names = g_hash_table_new_full(g_int_hash, g_int_equal, g_free, NULL);
423 proto_short_names = g_hash_table_new(wrs_str_hash, g_str_equal);
424 proto_filter_names = g_hash_table_new(wrs_str_hash, g_str_equal);
427 gpa_hfinfo.allocated_len = 0;
428 gpa_hfinfo.hfi = NULL;
429 gpa_name_tree = g_tree_new_full(wrs_strcmp_with_data, NULL, NULL, save_same_name_hfinfo);
431 /* Initialize the ftype subsystem */
434 /* Register one special-case FT_TEXT_ONLY field for use when
435 converting wireshark to new-style proto_tree. These fields
436 are merely strings on the GUI tree; they are not filterable */
437 hf_text_only = proto_register_field_init(&hfi_text_only, -1);
439 /* Register the pseudo-protocols used for exceptions. */
440 register_show_exception();
441 register_type_length_mismatch();
443 /* Have each built-in dissector register its protocols, fields,
444 dissector tables, and dissectors to be called through a
445 handle, and do whatever one-time initialization it needs to
447 register_all_protocols_func(cb, client_data);
449 /* Now scan for python protocols */
451 (*cb)(RA_PYTHON_REGISTER, NULL, client_data);
452 register_all_py_protocols_func();
456 /* Now call the registration routines for all disssector
459 (*cb)(RA_PLUGIN_REGISTER, NULL, client_data);
460 g_slist_foreach(dissector_plugins, register_dissector_plugin, NULL);
463 /* Now call the "handoff registration" routines of all built-in
464 dissectors; those routines register the dissector in other
465 dissectors' handoff tables, and fetch any dissector handles
467 register_all_handoffs_func(cb, client_data);
470 /* Now do the same with python dissectors */
472 (*cb)(RA_PYTHON_HANDOFF, NULL, client_data);
473 register_all_py_handoffs_func();
477 /* Now do the same with plugins. */
479 (*cb)(RA_PLUGIN_HANDOFF, NULL, client_data);
480 g_slist_foreach(dissector_plugins, reg_handoff_dissector_plugin, NULL);
483 /* sort the protocols by protocol name */
484 protocols = g_list_sort(protocols, proto_compare_name);
486 /* We've assigned all the subtree type values; allocate the array
487 for them, and zero it out. */
488 tree_is_expanded = g_new0(guint32, (num_tree_types/32)+1);
494 /* Free the abbrev/ID GTree */
496 g_tree_destroy(gpa_name_tree);
497 gpa_name_tree = NULL;
501 protocol_t *protocol = (protocol_t *)protocols->data;
502 header_field_info *hfinfo;
503 PROTO_REGISTRAR_GET_NTH(protocol->proto_id, hfinfo);
504 DISSECTOR_ASSERT(protocol->proto_id == hfinfo->id);
506 g_slice_free(header_field_info, hfinfo);
507 g_slist_free(protocol->fields);
508 protocols = g_list_remove(protocols, protocol);
513 g_hash_table_destroy(proto_names);
517 if (proto_short_names) {
518 g_hash_table_destroy(proto_short_names);
519 proto_short_names = NULL;
522 if (proto_filter_names) {
523 g_hash_table_destroy(proto_filter_names);
524 proto_filter_names = NULL;
527 if (gpa_hfinfo.allocated_len) {
529 gpa_hfinfo.allocated_len = 0;
530 g_free(gpa_hfinfo.hfi);
531 gpa_hfinfo.hfi = NULL;
533 g_free(tree_is_expanded);
534 tree_is_expanded = NULL;
538 proto_tree_traverse_pre_order(proto_tree *tree, proto_tree_traverse_func func,
541 proto_node *pnode = tree;
545 if (func(pnode, data))
548 child = pnode->first_child;
549 while (child != NULL) {
551 * The routine we call might modify the child, e.g. by
552 * freeing it, so we get the child's successor before
553 * calling that routine.
556 child = current->next;
557 if (proto_tree_traverse_pre_order((proto_tree *)current, func, data))
565 proto_tree_traverse_post_order(proto_tree *tree, proto_tree_traverse_func func,
568 proto_node *pnode = tree;
572 child = pnode->first_child;
573 while (child != NULL) {
575 * The routine we call might modify the child, e.g. by
576 * freeing it, so we get the child's successor before
577 * calling that routine.
580 child = current->next;
581 if (proto_tree_traverse_post_order((proto_tree *)current, func, data))
584 if (func(pnode, data))
591 proto_tree_children_foreach(proto_tree *tree, proto_tree_foreach_func func,
594 proto_node *node = tree;
600 node = node->first_child;
601 while (node != NULL) {
603 node = current->next;
604 func((proto_tree *)current, data);
609 free_GPtrArray_value(gpointer key, gpointer value, gpointer user_data _U_)
611 GPtrArray *ptrs = (GPtrArray *)value;
612 gint hfid = (gint)(long)key;
613 header_field_info *hfinfo;
615 PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
616 if (hfinfo->ref_type != HF_REF_TYPE_NONE) {
617 /* when a field is referenced by a filter this also
618 affects the refcount for the parent protocol so we need
619 to adjust the refcount for the parent as well
621 if (hfinfo->parent != -1) {
622 header_field_info *parent_hfinfo;
623 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
624 parent_hfinfo->ref_type = HF_REF_TYPE_NONE;
626 hfinfo->ref_type = HF_REF_TYPE_NONE;
629 g_ptr_array_free(ptrs, TRUE);
633 proto_tree_free_node(proto_node *node, gpointer data _U_)
635 field_info *finfo = PNODE_FINFO(node);
637 proto_tree_children_foreach(node, proto_tree_free_node, NULL);
639 FVALUE_CLEANUP(&finfo->value);
643 proto_tree_reset(proto_tree *tree)
645 tree_data_t *tree_data = PTREE_DATA(tree);
647 proto_tree_children_foreach(tree, proto_tree_free_node, NULL);
650 if (tree_data->interesting_hfids) {
651 /* Free all the GPtrArray's in the interesting_hfids hash. */
652 g_hash_table_foreach(tree_data->interesting_hfids,
653 free_GPtrArray_value, NULL);
655 /* And then destroy the hash. */
656 g_hash_table_destroy(tree_data->interesting_hfids);
658 tree_data->interesting_hfids = NULL;
661 /* Reset track of the number of children */
662 tree_data->count = 0;
664 PROTO_NODE_INIT(tree);
667 /* frees the resources that the dissection a proto_tree uses */
669 proto_tree_free(proto_tree *tree)
671 tree_data_t *tree_data = PTREE_DATA(tree);
673 proto_tree_children_foreach(tree, proto_tree_free_node, NULL);
676 if (tree_data->interesting_hfids) {
677 /* Free all the GPtrArray's in the interesting_hfids hash. */
678 g_hash_table_foreach(tree_data->interesting_hfids,
679 free_GPtrArray_value, NULL);
681 /* And then destroy the hash. */
682 g_hash_table_destroy(tree_data->interesting_hfids);
685 g_slice_free(tree_data_t, tree_data);
687 g_slice_free(proto_tree, tree);
690 /* Is the parsing being done for a visible proto_tree or an invisible one?
691 * By setting this correctly, the proto_tree creation is sped up by not
692 * having to call g_vsnprintf and copy strings around.
695 proto_tree_set_visible(proto_tree *tree, gboolean visible)
697 gboolean old_visible = PTREE_DATA(tree)->visible;
699 PTREE_DATA(tree)->visible = visible;
705 proto_tree_set_fake_protocols(proto_tree *tree, gboolean fake_protocols)
707 PTREE_DATA(tree)->fake_protocols = fake_protocols;
710 /* Assume dissector set only its protocol fields.
711 This function is called by dissectors and allows the speeding up of filtering
712 in wireshark; if this function returns FALSE it is safe to reset tree to NULL
713 and thus skip calling most of the expensive proto_tree_add_...()
715 If the tree is visible we implicitly assume the field is referenced.
718 proto_field_is_referenced(proto_tree *tree, int proto_id)
720 register header_field_info *hfinfo;
726 if (PTREE_DATA(tree)->visible)
729 PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
730 if (hfinfo->ref_type != HF_REF_TYPE_NONE)
733 if (hfinfo->type == FT_PROTOCOL && !PTREE_DATA(tree)->fake_protocols)
740 /* Finds a record in the hfinfo array by id. */
742 proto_registrar_get_nth(guint hfindex)
744 register header_field_info *hfinfo;
746 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
751 /* Prefix initialization
752 * this allows for a dissector to register a display filter name prefix
753 * so that it can delay the initialization of the hf array as long as
757 /* compute a hash for the part before the dot of a display filter */
759 prefix_hash (gconstpointer key) {
760 /* end the string at the dot and compute its hash */
761 gchar* copy = ep_strdup((const gchar *)key);
771 return g_str_hash(copy);
774 /* are both strings equal up to the end or the dot? */
776 prefix_equal (gconstpointer ap, gconstpointer bp) {
777 const gchar* a = (const gchar *)ap;
778 const gchar* b = (const gchar *)bp;
784 if ( (ac == '.' || ac == '\0') && (bc == '.' || bc == '\0') ) return TRUE;
786 if ( (ac == '.' || ac == '\0') && ! (bc == '.' || bc == '\0') ) return FALSE;
787 if ( (bc == '.' || bc == '\0') && ! (ac == '.' || ac == '\0') ) return FALSE;
789 if (ac != bc) return FALSE;
796 /* indexed by prefix, contains initializers */
797 static GHashTable* prefixes = NULL;
800 /* Register a new prefix for "delayed" initialization of field arrays */
802 proto_register_prefix(const char *prefix, prefix_initializer_t pi ) {
804 prefixes = g_hash_table_new(prefix_hash, prefix_equal);
807 g_hash_table_insert(prefixes, (gpointer)prefix, pi);
810 /* helper to call all prefix initializers */
812 initialize_prefix(gpointer k, gpointer v, gpointer u _U_) {
813 ((prefix_initializer_t)v)((const char *)k);
817 /** Initialize every remaining uninitialized prefix. */
819 proto_initialize_all_prefixes(void) {
820 g_hash_table_foreach_remove(prefixes, initialize_prefix, NULL);
823 /* Finds a record in the hfinfo array by name.
824 * If it fails to find it in the already registered fields,
825 * it tries to find and call an initializer in the prefixes
826 * table and if so it looks again.
829 proto_registrar_get_byname(const char *field_name)
831 header_field_info *hfinfo;
832 prefix_initializer_t pi;
837 hfinfo = (header_field_info *)g_tree_lookup(gpa_name_tree, field_name);
845 if ((pi = (prefix_initializer_t)g_hash_table_lookup(prefixes, field_name) ) != NULL) {
847 g_hash_table_remove(prefixes, field_name);
852 return (header_field_info *)g_tree_lookup(gpa_name_tree, field_name);
856 proto_registrar_get_id_byname(const char *field_name)
858 header_field_info *hfinfo;
860 hfinfo = proto_registrar_get_byname(field_name);
870 ptvcursor_new_subtree_levels(ptvcursor_t *ptvc)
872 subtree_lvl *pushed_tree;
874 DISSECTOR_ASSERT(ptvc->pushed_tree_max <= SUBTREE_MAX_LEVELS-SUBTREE_ONCE_ALLOCATION_NUMBER);
875 ptvc->pushed_tree_max += SUBTREE_ONCE_ALLOCATION_NUMBER;
877 pushed_tree = (subtree_lvl *)ep_alloc(sizeof(subtree_lvl) * ptvc->pushed_tree_max);
878 DISSECTOR_ASSERT(pushed_tree != NULL);
879 if (ptvc->pushed_tree)
880 memcpy(pushed_tree, ptvc->pushed_tree, ptvc->pushed_tree_max - SUBTREE_ONCE_ALLOCATION_NUMBER);
881 ptvc->pushed_tree = pushed_tree;
885 ptvcursor_free_subtree_levels(ptvcursor_t *ptvc)
887 ptvc->pushed_tree = NULL;
888 ptvc->pushed_tree_max = 0;
889 DISSECTOR_ASSERT(ptvc->pushed_tree_index == 0);
890 ptvc->pushed_tree_index = 0;
893 /* Allocates an initializes a ptvcursor_t with 3 variables:
894 * proto_tree, tvbuff, and offset. */
896 ptvcursor_new(proto_tree *tree, tvbuff_t *tvb, gint offset)
900 ptvc = (ptvcursor_t *)ep_alloc(sizeof(ptvcursor_t));
903 ptvc->offset = offset;
904 ptvc->pushed_tree = NULL;
905 ptvc->pushed_tree_max = 0;
906 ptvc->pushed_tree_index = 0;
911 /* Frees memory for ptvcursor_t, but nothing deeper than that. */
913 ptvcursor_free(ptvcursor_t *ptvc)
915 ptvcursor_free_subtree_levels(ptvc);
919 /* Returns tvbuff. */
921 ptvcursor_tvbuff(ptvcursor_t *ptvc)
926 /* Returns current offset. */
928 ptvcursor_current_offset(ptvcursor_t *ptvc)
934 ptvcursor_tree(ptvcursor_t *ptvc)
943 ptvcursor_set_tree(ptvcursor_t *ptvc, proto_tree *tree)
948 /* creates a subtree, sets it as the working tree and pushes the old working tree */
950 ptvcursor_push_subtree(ptvcursor_t *ptvc, proto_item *it, gint ett_subtree)
952 subtree_lvl *subtree;
953 if (ptvc->pushed_tree_index >= ptvc->pushed_tree_max)
954 ptvcursor_new_subtree_levels(ptvc);
956 subtree = ptvc->pushed_tree + ptvc->pushed_tree_index;
957 subtree->tree = ptvc->tree;
959 ptvc->pushed_tree_index++;
960 return ptvcursor_set_subtree(ptvc, it, ett_subtree);
965 ptvcursor_pop_subtree(ptvcursor_t *ptvc)
967 subtree_lvl *subtree;
969 if (ptvc->pushed_tree_index <= 0)
972 ptvc->pushed_tree_index--;
973 subtree = ptvc->pushed_tree + ptvc->pushed_tree_index;
974 if (subtree->it != NULL)
975 proto_item_set_len(subtree->it, ptvcursor_current_offset(ptvc) - subtree->cursor_offset);
977 ptvc->tree = subtree->tree;
980 /* saves the current tvb offset and the item in the current subtree level */
982 ptvcursor_subtree_set_item(ptvcursor_t *ptvc, proto_item *it)
984 subtree_lvl *subtree;
986 DISSECTOR_ASSERT(ptvc->pushed_tree_index > 0);
988 subtree = ptvc->pushed_tree + ptvc->pushed_tree_index - 1;
990 subtree->cursor_offset = ptvcursor_current_offset(ptvc);
993 /* Creates a subtree and adds it to the cursor as the working tree but does not
994 * save the old working tree */
996 ptvcursor_set_subtree(ptvcursor_t *ptvc, proto_item *it, gint ett_subtree)
998 ptvc->tree = proto_item_add_subtree(it, ett_subtree);
1003 ptvcursor_add_subtree_item(ptvcursor_t *ptvc, proto_item *it, gint ett_subtree, gint length)
1005 ptvcursor_push_subtree(ptvc, it, ett_subtree);
1006 if (length == SUBTREE_UNDEFINED_LENGTH)
1007 ptvcursor_subtree_set_item(ptvc, it);
1008 return ptvcursor_tree(ptvc);
1011 /* Add an item to the tree and create a subtree
1012 * If the length is unknown, length may be defined as SUBTREE_UNDEFINED_LENGTH.
1013 * In this case, when the subtree will be closed, the parent item length will
1014 * be equal to the advancement of the cursor since the creation of the subtree.
1017 ptvcursor_add_with_subtree(ptvcursor_t *ptvc, int hfindex, gint length,
1018 const guint encoding, gint ett_subtree)
1022 it = ptvcursor_add_no_advance(ptvc, hfindex, length, encoding);
1023 return ptvcursor_add_subtree_item(ptvc, it, ett_subtree, length);
1027 proto_tree_add_text_node(proto_tree *tree, tvbuff_t *tvb, gint start, gint length);
1029 /* Add a text node to the tree and create a subtree
1030 * If the length is unknown, length may be defined as SUBTREE_UNDEFINED_LENGTH.
1031 * In this case, when the subtree will be closed, the item length will be equal
1032 * to the advancement of the cursor since the creation of the subtree.
1035 ptvcursor_add_text_with_subtree(ptvcursor_t *ptvc, gint length,
1036 gint ett_subtree, const char *format, ...)
1040 header_field_info *hfinfo;
1043 tree = ptvcursor_tree(ptvc);
1045 TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
1047 pi = proto_tree_add_text_node(tree, ptvcursor_tvbuff(ptvc),
1048 ptvcursor_current_offset(ptvc), length);
1050 TRY_TO_FAKE_THIS_REPR(pi);
1052 va_start(ap, format);
1053 proto_tree_set_representation(pi, format, ap);
1056 return ptvcursor_add_subtree_item(ptvc, pi, ett_subtree, length);
1059 /* Add a text-only node, leaving it to our caller to fill the text in */
1061 proto_tree_add_text_node(proto_tree *tree, tvbuff_t *tvb, gint start, gint length)
1068 pi = proto_tree_add_pi(tree, &hfi_text_only, tvb, start, &length);
1073 /* Add a text-only node to the proto_tree */
1075 proto_tree_add_text(proto_tree *tree, tvbuff_t *tvb, gint start, gint length,
1076 const char *format, ...)
1080 header_field_info *hfinfo;
1082 TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
1084 pi = proto_tree_add_text_node(tree, tvb, start, length);
1086 TRY_TO_FAKE_THIS_REPR(pi);
1088 va_start(ap, format);
1089 proto_tree_set_representation(pi, format, ap);
1095 /* Add a text-only node to the proto_tree (va_list version) */
1097 proto_tree_add_text_valist(proto_tree *tree, tvbuff_t *tvb, gint start,
1098 gint length, const char *format, va_list ap)
1101 header_field_info *hfinfo;
1103 TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
1105 pi = proto_tree_add_text_node(tree, tvb, start, length);
1107 TRY_TO_FAKE_THIS_REPR(pi);
1109 proto_tree_set_representation(pi, format, ap);
1114 /* Add a text-only node for debugging purposes. The caller doesn't need
1115 * to worry about tvbuff, start, or length. Debug message gets sent to
1118 proto_tree_add_debug_text(proto_tree *tree, const char *format, ...)
1123 pi = proto_tree_add_text_node(tree, NULL, 0, 0);
1126 va_start(ap, format);
1127 proto_tree_set_representation(pi, format, ap);
1130 va_start(ap, format);
1131 vprintf(format, ap);
1138 void proto_report_dissector_bug(const char *message)
1140 if (getenv("WIRESHARK_ABORT_ON_DISSECTOR_BUG") != NULL)
1143 THROW_MESSAGE(DissectorError, message);
1146 /* We could probably get away with changing is_error to a minimum length value. */
1148 report_type_length_mismatch(proto_tree *tree, const gchar *descr, int length, gboolean is_error) {
1151 expert_add_info_format(NULL, tree, &ei_type_length_mismatch_error, "Trying to fetch %s with length %d", descr, length);
1153 expert_add_info_format(NULL, tree, &ei_type_length_mismatch_warn, "Trying to fetch %s with length %d", descr, length);
1157 THROW(ReportedBoundsError);
1162 get_uint_value(proto_tree *tree, tvbuff_t *tvb, gint offset, gint length, const guint encoding)
1165 gboolean length_error;
1170 value = tvb_get_guint8(tvb, offset);
1174 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letohs(tvb, offset)
1175 : tvb_get_ntohs(tvb, offset);
1179 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letoh24(tvb, offset)
1180 : tvb_get_ntoh24(tvb, offset);
1184 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letohl(tvb, offset)
1185 : tvb_get_ntohl(tvb, offset);
1190 length_error = TRUE;
1193 length_error = FALSE;
1194 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letohl(tvb, offset)
1195 : tvb_get_ntohl(tvb, offset);
1197 report_type_length_mismatch(tree, "an unsigned integer", length, length_error);
1204 * NOTE: to support code written when proto_tree_add_item() took a
1205 * gboolean as its last argument, with FALSE meaning "big-endian"
1206 * and TRUE meaning "little-endian", we treat any non-zero value of
1207 * "encoding" as meaning "little-endian".
1210 get_int_value(proto_tree *tree, tvbuff_t *tvb, gint offset, gint length, const guint encoding)
1213 gboolean length_error;
1218 value = (gint8)tvb_get_guint8(tvb, offset);
1222 value = (gint16) (encoding ? tvb_get_letohs(tvb, offset)
1223 : tvb_get_ntohs(tvb, offset));
1227 value = encoding ? tvb_get_letoh24(tvb, offset)
1228 : tvb_get_ntoh24(tvb, offset);
1229 if (value & 0x00800000) {
1230 /* Sign bit is set; sign-extend it. */
1231 value |= 0xFF000000;
1236 value = encoding ? tvb_get_letohl(tvb, offset)
1237 : tvb_get_ntohl(tvb, offset);
1242 length_error = TRUE;
1245 length_error = FALSE;
1246 value = encoding ? tvb_get_letohl(tvb, offset)
1247 : tvb_get_ntohl(tvb, offset);
1249 report_type_length_mismatch(tree, "a signed integer", length, length_error);
1256 tree_data_add_maybe_interesting_field(tree_data_t *tree_data, field_info *fi)
1258 const header_field_info *hfinfo = fi->hfinfo;
1260 if (hfinfo->ref_type == HF_REF_TYPE_DIRECT) {
1261 GPtrArray *ptrs = NULL;
1263 if (tree_data->interesting_hfids == NULL) {
1264 /* Initialize the hash because we now know that it is needed */
1265 tree_data->interesting_hfids =
1266 g_hash_table_new(g_direct_hash, NULL /* g_direct_equal */);
1268 ptrs = (GPtrArray *)g_hash_table_lookup(tree_data->interesting_hfids,
1269 GINT_TO_POINTER(hfinfo->id));
1271 /* First element triggers the creation of pointer array */
1272 ptrs = g_ptr_array_new();
1273 g_hash_table_insert(tree_data->interesting_hfids,
1274 GINT_TO_POINTER(hfinfo->id), ptrs);
1277 g_ptr_array_add(ptrs, fi);
1281 /* Add an item to a proto_tree, using the text label registered to that item;
1282 the item is extracted from the tvbuff handed to it. */
1284 proto_tree_new_item(field_info *new_fi, proto_tree *tree,
1285 tvbuff_t *tvb, gint start, gint length,
1293 nstime_t time_stamp;
1296 gboolean length_error;
1298 switch (new_fi->hfinfo->type) {
1300 /* no value to set for FT_NONE */
1304 proto_tree_set_protocol_tvb(new_fi, tvb);
1308 proto_tree_set_bytes_tvb(new_fi, tvb, start, length);
1313 * Map all non-zero values to little-endian for
1314 * backwards compatibility.
1317 encoding = ENC_LITTLE_ENDIAN;
1318 n = get_uint_value(tree, tvb, start, length, encoding);
1319 proto_tree_set_bytes_tvb(new_fi, tvb, start + length, n);
1321 /* Instead of calling proto_item_set_len(), since we don't yet
1322 * have a proto_item, we set the field_info's length ourselves. */
1323 new_fi->length = n + length;
1328 * Map all non-zero values to little-endian for
1329 * backwards compatibility.
1332 encoding = ENC_LITTLE_ENDIAN;
1333 proto_tree_set_boolean(new_fi,
1334 get_uint_value(tree, tvb, start, length, encoding));
1337 /* XXX - make these just FT_UINT? */
1343 * Map all non-zero values to little-endian for
1344 * backwards compatibility.
1347 encoding = ENC_LITTLE_ENDIAN;
1348 proto_tree_set_uint(new_fi,
1349 get_uint_value(tree, tvb, start, length, encoding));
1355 * Map all non-zero values to little-endian for
1356 * backwards compatibility.
1359 encoding = ENC_LITTLE_ENDIAN;
1360 if (length < 1 || length > 8) {
1361 length_error = length < 1 ? TRUE : FALSE;
1362 report_type_length_mismatch(tree, "a 64-bit integer", length, length_error);
1364 if (new_fi->hfinfo->type == FT_INT64)
1366 proto_tree_set_int64_tvb(new_fi, tvb, start, length, encoding);
1370 proto_tree_set_uint64_tvb(new_fi, tvb, start, length, encoding);
1374 /* XXX - make these just FT_INT? */
1380 * Map all non-zero values to little-endian for
1381 * backwards compatibility.
1384 encoding = ENC_LITTLE_ENDIAN;
1385 proto_tree_set_int(new_fi,
1386 get_int_value(tree, tvb, start, length, encoding));
1391 * Map all non-zero values to little-endian for
1392 * backwards compatibility.
1395 encoding = ENC_LITTLE_ENDIAN;
1396 if (length != FT_IPv4_LEN) {
1397 length_error = length < FT_IPv4_LEN ? TRUE : FALSE;
1398 report_type_length_mismatch(tree, "an IPv4 address", length, length_error);
1400 value = tvb_get_ipv4(tvb, start);
1402 * NOTE: to support code written when
1403 * proto_tree_add_item() took a gboolean as its
1404 * last argument, with FALSE meaning "big-endian"
1405 * and TRUE meaning "little-endian", we treat any
1406 * non-zero value of "encoding" as meaning
1409 proto_tree_set_ipv4(new_fi, encoding ? GUINT32_SWAP_LE_BE(value) : value);
1413 if (length != FT_IPXNET_LEN) {
1414 length_error = length < FT_IPXNET_LEN ? TRUE : FALSE;
1415 report_type_length_mismatch(tree, "an IPXNET address", length, length_error);
1417 proto_tree_set_ipxnet(new_fi,
1418 get_uint_value(tree, tvb, start, FT_IPXNET_LEN, ENC_BIG_ENDIAN));
1422 if (length != FT_IPv6_LEN) {
1423 length_error = length < FT_IPv6_LEN ? TRUE : FALSE;
1424 report_type_length_mismatch(tree, "an IPv6 address", length, length_error);
1426 proto_tree_set_ipv6_tvb(new_fi, tvb, start, length);
1431 length_error = length < 7 ? TRUE : FALSE;
1432 report_type_length_mismatch(tree, "an AX.25 address", length, length_error);
1434 proto_tree_set_ax25_tvb(new_fi, tvb, start);
1438 if (length != VINES_ADDR_LEN) {
1439 length_error = length < VINES_ADDR_LEN ? TRUE : FALSE;
1440 report_type_length_mismatch(tree, "a Vines address", length, length_error);
1442 proto_tree_set_vines_tvb(new_fi, tvb, start);
1446 if (length != FT_ETHER_LEN) {
1447 length_error = length < FT_ETHER_LEN ? TRUE : FALSE;
1448 report_type_length_mismatch(tree, "an Ethernet", length, length_error);
1450 proto_tree_set_ether_tvb(new_fi, tvb, start);
1455 * Map all non-zero values to little-endian for
1456 * backwards compatibility.
1459 encoding = ENC_LITTLE_ENDIAN;
1460 if (length != FT_EUI64_LEN) {
1461 length_error = length < FT_EUI64_LEN ? TRUE : FALSE;
1462 report_type_length_mismatch(tree, "an EUI-64 address", length, length_error);
1464 proto_tree_set_eui64_tvb(new_fi, tvb, start, encoding);
1468 * Map all non-zero values to little-endian for
1469 * backwards compatibility.
1472 encoding = ENC_LITTLE_ENDIAN;
1473 if (length != FT_GUID_LEN) {
1474 length_error = length < FT_GUID_LEN ? TRUE : FALSE;
1475 report_type_length_mismatch(tree, "a GUID", length, length_error);
1477 proto_tree_set_guid_tvb(new_fi, tvb, start, encoding);
1482 proto_tree_set_oid_tvb(new_fi, tvb, start, length);
1487 * NOTE: to support code written when
1488 * proto_tree_add_item() took a gboolean as its
1489 * last argument, with FALSE meaning "big-endian"
1490 * and TRUE meaning "little-endian", we treat any
1491 * non-zero value of "encoding" as meaning
1494 * At some point in the future, we might
1495 * support non-IEEE-binary floating-point
1496 * formats in the encoding as well
1497 * (IEEE decimal, System/3x0, VAX).
1500 encoding = ENC_LITTLE_ENDIAN;
1502 length_error = length < 4 ? TRUE : FALSE;
1503 report_type_length_mismatch(tree, "a single-precision floating point number", length, length_error);
1506 floatval = tvb_get_letohieee_float(tvb, start);
1508 floatval = tvb_get_ntohieee_float(tvb, start);
1509 proto_tree_set_float(new_fi, floatval);
1514 * NOTE: to support code written when
1515 * proto_tree_add_item() took a gboolean as its
1516 * last argument, with FALSE meaning "big-endian"
1517 * and TRUE meaning "little-endian", we treat any
1518 * non-zero value of "encoding" as meaning
1521 * At some point in the future, we might
1522 * support non-IEEE-binary floating-point
1523 * formats in the encoding as well
1524 * (IEEE decimal, System/3x0, VAX).
1526 if (encoding == TRUE)
1527 encoding = ENC_LITTLE_ENDIAN;
1529 length_error = length < 8 ? TRUE : FALSE;
1530 report_type_length_mismatch(tree, "a double-precision floating point number", length, length_error);
1533 doubleval = tvb_get_letohieee_double(tvb, start);
1535 doubleval = tvb_get_ntohieee_double(tvb, start);
1536 proto_tree_set_double(new_fi, doubleval);
1540 proto_tree_set_string_tvb(new_fi, tvb, start, length,
1546 report_type_length_mismatch(tree, "a string", length, TRUE);
1548 /* Instead of calling proto_item_set_len(),
1549 * since we don't yet have a proto_item, we
1550 * set the field_info's length ourselves.
1552 * XXX - our caller can't use that length to
1553 * advance an offset unless they arrange that
1554 * there always be a protocol tree into which
1555 * we're putting this item.
1558 /* This can throw an exception */
1559 string = tvb_get_stringz_enc(wmem_packet_scope(), tvb, start, &length, encoding);
1560 } else if (length == 0) {
1563 /* In this case, length signifies
1564 * the length of the string.
1566 * This could either be a null-padded
1567 * string, which doesn't necessarily
1568 * have a '\0' at the end, or a
1569 * null-terminated string, with a
1570 * trailing '\0'. (Yes, there are
1571 * cases where you have a string
1572 * that's both counted and null-
1575 * In the first case, we must
1576 * allocate a buffer of length
1577 * "length+1", to make room for
1580 * In the second case, we don't
1581 * assume that there is a trailing
1582 * '\0' there, as the packet might
1583 * be malformed. (XXX - should we
1584 * throw an exception if there's no
1585 * trailing '\0'?) Therefore, we
1586 * allocate a buffer of length
1587 * "length+1", and put in a trailing
1588 * '\0', just to be safe.
1590 * (XXX - this would change if
1591 * we made string values counted
1592 * rather than null-terminated.)
1594 string = tvb_get_string_enc(wmem_packet_scope(), tvb, start, length, encoding);
1596 new_fi->length = length;
1597 proto_tree_set_string(new_fi, string);
1600 case FT_UINT_STRING:
1602 * NOTE: to support code written when
1603 * proto_tree_add_item() took a gboolean as its
1604 * last argument, with FALSE meaning "big-endian"
1605 * and TRUE meaning "little-endian", if the
1606 * encoding value is TRUE, treat that as
1607 * ASCII with a little-endian length.
1609 * This won't work for code that passes
1610 * arbitrary non-zero values; that code
1611 * will need to be fixed.
1613 if (encoding == TRUE)
1614 encoding = ENC_ASCII|ENC_LITTLE_ENDIAN;
1615 n = get_uint_value(tree, tvb, start, length, encoding & ~ENC_CHARENCODING_MASK);
1616 proto_tree_set_string_tvb(new_fi, tvb, start + length, n,
1619 /* Instead of calling proto_item_set_len(), since we
1620 * don't yet have a proto_item, we set the
1621 * field_info's length ourselves.
1623 * XXX - our caller can't use that length to
1624 * advance an offset unless they arrange that
1625 * there always be a protocol tree into which
1626 * we're putting this item.
1628 new_fi->length = n + length;
1631 case FT_ABSOLUTE_TIME:
1633 * Absolute times can be in any of a number of
1634 * formats, and they can be big-endian or
1637 * Historically FT_TIMEs were only timespecs;
1638 * the only question was whether they were stored
1639 * in big- or little-endian format.
1641 * For backwards compatibility, we interpret an
1642 * encoding of 1 as meaning "little-endian timespec",
1643 * so that passing TRUE is interpreted as that.
1645 if (encoding == TRUE)
1646 encoding = ENC_TIME_TIMESPEC|ENC_LITTLE_ENDIAN;
1648 if (length != 8 && length != 4) {
1649 length_error = length < 4 ? TRUE : FALSE;
1650 report_type_length_mismatch(tree, "an absolute time value", length, length_error);
1655 case ENC_TIME_TIMESPEC|ENC_BIG_ENDIAN:
1657 * 4-byte UNIX epoch, possibly followed by
1658 * 4-byte fractional time in nanoseconds,
1661 time_stamp.secs = tvb_get_ntohl(tvb, start);
1663 time_stamp.nsecs = tvb_get_ntohl(tvb, start+4);
1665 time_stamp.nsecs = 0;
1668 case ENC_TIME_TIMESPEC|ENC_LITTLE_ENDIAN:
1670 * 4-byte UNIX epoch, possibly followed by
1671 * 4-byte fractional time in nanoseconds,
1672 * both little-endian.
1674 time_stamp.secs = tvb_get_letohl(tvb, start);
1676 time_stamp.nsecs = tvb_get_letohl(tvb, start+4);
1678 time_stamp.nsecs = 0;
1681 case ENC_TIME_TOD|ENC_BIG_ENDIAN:
1683 * TOD time stamp, big-endian.
1685 /* XXX - where should this go? */
1686 #define TOD_BASETIME 2208988800ul
1688 todsecs = tvb_get_ntoh64(tvb, start) >> 12;
1689 time_stamp.secs = (time_t)((todsecs / 1000000) - TOD_BASETIME);
1690 time_stamp.nsecs = (int)((todsecs % 1000000) * 1000);
1693 case ENC_TIME_TOD|ENC_LITTLE_ENDIAN:
1695 * TOD time stamp, big-endian.
1697 todsecs = tvb_get_letoh64(tvb, start) >> 12 ;
1698 time_stamp.secs = (time_t)((todsecs / 1000000) - TOD_BASETIME);
1699 time_stamp.nsecs = (int)((todsecs % 1000000) * 1000);
1702 case ENC_TIME_NTP|ENC_BIG_ENDIAN:
1704 * NTP time stamp, big-endian.
1707 /* XXX - where should this go? */
1708 #define NTP_BASETIME 2208988800ul
1710 /* We need a temporary variable here so the unsigned math
1711 * works correctly (for years > 2036 according to RFC 2030
1714 tmpsecs = tvb_get_ntohl(tvb, start);
1716 time_stamp.secs = tmpsecs - (guint32)NTP_BASETIME;
1718 time_stamp.secs = tmpsecs; /* 0 */
1722 * We're using nanoseconds here (and we will
1723 * display nanoseconds), but NTP's timestamps
1724 * have a precision in microseconds or greater.
1725 * Round to 1 microsecond.
1727 time_stamp.nsecs = (int)(1000000*(tvb_get_ntohl(tvb, start+4)/4294967296.0));
1728 time_stamp.nsecs *= 1000;
1730 time_stamp.nsecs = 0;
1734 case ENC_TIME_NTP|ENC_LITTLE_ENDIAN:
1736 * NTP time stamp, big-endian.
1738 tmpsecs = tvb_get_letohl(tvb, start);
1740 time_stamp.secs = tmpsecs - (guint32)NTP_BASETIME;
1742 time_stamp.secs = tmpsecs; /* 0 */
1746 * We're using nanoseconds here (and we will
1747 * display nanoseconds), but NTP's timestamps
1748 * have a precision in microseconds or greater.
1749 * Round to 1 microsecond.
1751 time_stamp.nsecs = (int)(1000000*(tvb_get_letohl(tvb, start+4)/4294967296.0));
1752 time_stamp.nsecs *= 1000;
1754 time_stamp.nsecs = 0;
1759 DISSECTOR_ASSERT_NOT_REACHED();
1760 time_stamp.secs = 0;
1761 time_stamp.nsecs = 0;
1764 proto_tree_set_time(new_fi, &time_stamp);
1767 case FT_RELATIVE_TIME:
1769 * Relative times can be in any of a number of
1770 * formats, and they can be big-endian or
1773 * Historically FT_TIMEs were only timespecs;
1774 * the only question was whether they were stored
1775 * in big- or little-endian format.
1777 * For backwards compatibility, we interpret an
1778 * encoding of 1 as meaning "little-endian timespec",
1779 * so that passing TRUE is interpreted as that.
1781 if (encoding == TRUE)
1782 encoding = ENC_TIME_TIMESPEC|ENC_LITTLE_ENDIAN;
1785 if (length != 8 && length != 4) {
1786 length_error = length < 4 ? TRUE : FALSE;
1787 report_type_length_mismatch(tree, "a relative time value", length, length_error);
1790 case ENC_TIME_TIMESPEC|ENC_BIG_ENDIAN:
1792 * 4-byte UNIX epoch, possibly followed by
1793 * 4-byte fractional time in nanoseconds,
1796 time_stamp.secs = tvb_get_ntohl(tvb, start);
1798 time_stamp.nsecs = tvb_get_ntohl(tvb, start+4);
1800 time_stamp.nsecs = 0;
1803 case ENC_TIME_TIMESPEC|ENC_LITTLE_ENDIAN:
1805 * 4-byte UNIX epoch, possibly followed by
1806 * 4-byte fractional time in nanoseconds,
1807 * both little-endian.
1809 time_stamp.secs = tvb_get_letohl(tvb, start);
1811 time_stamp.nsecs = tvb_get_letohl(tvb, start+4);
1813 time_stamp.nsecs = 0;
1816 proto_tree_set_time(new_fi, &time_stamp);
1820 g_error("new_fi->hfinfo->type %d (%s) not handled\n",
1821 new_fi->hfinfo->type,
1822 ftype_name(new_fi->hfinfo->type));
1823 DISSECTOR_ASSERT_NOT_REACHED();
1826 FI_SET_FLAG(new_fi, (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN);
1828 /* Don't add new node to proto_tree until now so that any exceptions
1829 * raised by a tvbuff access method doesn't leave junk in the proto_tree. */
1830 /* XXX. wouldn't be better to add this item to tree, with some special flag (FI_EXCEPTION?)
1831 * to know which item caused exception? */
1832 pi = proto_tree_add_node(tree, new_fi);
1837 /* Gets data from tvbuff, adds it to proto_tree, increments offset,
1838 and returns proto_item* */
1840 ptvcursor_add(ptvcursor_t *ptvc, int hfindex, gint length,
1841 const guint encoding)
1844 header_field_info *hfinfo;
1849 /* We can't fake it just yet. We have to advance the cursor
1850 TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfindex, hfinfo); */
1852 offset = ptvc->offset;
1853 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1854 get_hfi_length(hfinfo, ptvc->tvb, offset, &length, &item_length);
1855 ptvc->offset += length;
1856 if (hfinfo->type == FT_UINT_BYTES || hfinfo->type == FT_UINT_STRING) {
1858 * The length of the rest of the item is in the first N
1859 * bytes of the item.
1861 n = get_uint_value(ptvc->tree, ptvc->tvb, offset, length, encoding);
1865 /* Coast clear. Try and fake it */
1866 TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfindex, hfinfo);
1868 new_fi = new_field_info(ptvc->tree, hfinfo, ptvc->tvb, offset, item_length);
1870 return proto_tree_new_item(new_fi, ptvc->tree, ptvc->tvb,
1871 offset, length, encoding);
1875 * Validates that field length bytes are available starting from
1876 * start (pos/neg). Throws an exception if they aren't.
1879 test_length(header_field_info *hfinfo, tvbuff_t *tvb,
1880 gint start, gint length)
1887 if (hfinfo->type == FT_STRINGZ) {
1888 /* If we're fetching until the end of the TVB, only validate
1889 * that the offset is within range.
1895 tvb_ensure_bytes_exist(tvb, start, size);
1898 /* Add an item to a proto_tree, using the text label registered to that item;
1899 the item is extracted from the tvbuff handed to it. */
1901 proto_tree_add_item_new(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
1902 const gint start, gint length, const guint encoding)
1907 DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");
1909 get_hfi_length(hfinfo, tvb, start, &length, &item_length);
1910 test_length(hfinfo, tvb, start, item_length);
1912 TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
1914 new_fi = new_field_info(tree, hfinfo, tvb, start, item_length);
1919 return proto_tree_new_item(new_fi, tree, tvb, start, length, encoding);
1923 proto_tree_add_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1924 const gint start, gint length, const guint encoding)
1926 return proto_tree_add_item_new(tree, proto_registrar_get_nth(hfindex), tvb, start, length, encoding);
1929 /* Add a FT_NONE to a proto_tree */
1931 proto_tree_add_none_format(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
1932 const gint start, gint length, const char *format,
1937 header_field_info *hfinfo;
1939 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1941 DISSECTOR_ASSERT(hfinfo->type == FT_NONE);
1943 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
1945 TRY_TO_FAKE_THIS_REPR(pi);
1947 va_start(ap, format);
1948 proto_tree_set_representation(pi, format, ap);
1951 /* no value to set for FT_NONE */
1955 /* Gets data from tvbuff, adds it to proto_tree, *DOES NOT* increment
1956 * offset, and returns proto_item* */
1958 ptvcursor_add_no_advance(ptvcursor_t* ptvc, int hf, gint length,
1959 const guint encoding)
1963 item = proto_tree_add_item(ptvc->tree, hf, ptvc->tvb, ptvc->offset,
1969 /* Advance the ptvcursor's offset within its tvbuff without
1970 * adding anything to the proto_tree. */
1972 ptvcursor_advance(ptvcursor_t* ptvc, gint length)
1974 ptvc->offset += length;
1979 proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb)
1981 fvalue_set(&fi->value, tvb, TRUE);
1984 /* Add a FT_PROTOCOL to a proto_tree */
1986 proto_tree_add_protocol_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1987 gint start, gint length, const char *format, ...)
1991 header_field_info *hfinfo;
1993 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1995 DISSECTOR_ASSERT(hfinfo->type == FT_PROTOCOL);
1997 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
1999 proto_tree_set_protocol_tvb(PNODE_FINFO(pi), (start == 0 ? tvb : tvb_new_subset(tvb, start, length, length)));
2001 TRY_TO_FAKE_THIS_REPR(pi);
2003 va_start(ap, format);
2004 proto_tree_set_representation(pi, format, ap);
2011 /* Add a FT_BYTES to a proto_tree */
2013 proto_tree_add_bytes(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2014 gint length, const guint8 *start_ptr)
2017 header_field_info *hfinfo;
2019 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2021 DISSECTOR_ASSERT(hfinfo->type == FT_BYTES);
2023 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
2024 proto_tree_set_bytes(PNODE_FINFO(pi), start_ptr, length);
2030 proto_tree_add_bytes_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2031 gint start, gint length,
2032 const guint8 *start_ptr,
2033 const char *format, ...)
2037 header_field_info *hfinfo;
2039 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2042 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length,
2045 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length,
2046 tvb_get_ptr(tvb, start, length));
2048 va_start(ap, format);
2049 proto_tree_set_representation_value(pi, format, ap);
2056 proto_tree_add_bytes_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2057 gint start, gint length, const guint8 *start_ptr,
2058 const char *format, ...)
2062 header_field_info *hfinfo;
2064 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2067 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length,
2070 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length,
2071 tvb_get_ptr(tvb, start, length));
2073 TRY_TO_FAKE_THIS_REPR(pi);
2075 va_start(ap, format);
2076 proto_tree_set_representation(pi, format, ap);
2083 proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length)
2087 DISSECTOR_ASSERT(start_ptr != NULL || length == 0);
2089 bytes = g_byte_array_new();
2091 g_byte_array_append(bytes, start_ptr, length);
2093 fvalue_set(&fi->value, bytes, TRUE);
2098 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length)
2100 proto_tree_set_bytes(fi, tvb_get_ptr(tvb, offset, length), length);
2103 /* Add a FT_*TIME to a proto_tree */
2105 proto_tree_add_time(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2106 gint length, nstime_t *value_ptr)
2109 header_field_info *hfinfo;
2111 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2113 DISSECTOR_ASSERT(hfinfo->type == FT_ABSOLUTE_TIME ||
2114 hfinfo->type == FT_RELATIVE_TIME);
2116 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
2117 proto_tree_set_time(PNODE_FINFO(pi), value_ptr);
2123 proto_tree_add_time_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2124 gint start, gint length, nstime_t *value_ptr,
2125 const char *format, ...)
2130 pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
2132 va_start(ap, format);
2133 proto_tree_set_representation_value(pi, format, ap);
2141 proto_tree_add_time_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2142 gint start, gint length, nstime_t *value_ptr,
2143 const char *format, ...)
2148 pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
2150 TRY_TO_FAKE_THIS_REPR(pi);
2152 va_start(ap, format);
2153 proto_tree_set_representation(pi, format, ap);
2160 /* Set the FT_*TIME value */
2162 proto_tree_set_time(field_info *fi, nstime_t *value_ptr)
2164 DISSECTOR_ASSERT(value_ptr != NULL);
2166 fvalue_set(&fi->value, value_ptr, FALSE);
2169 /* Add a FT_IPXNET to a proto_tree */
2171 proto_tree_add_ipxnet(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2172 gint length, guint32 value)
2175 header_field_info *hfinfo;
2177 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2179 DISSECTOR_ASSERT(hfinfo->type == FT_IPXNET);
2181 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
2182 proto_tree_set_ipxnet(PNODE_FINFO(pi), value);
2188 proto_tree_add_ipxnet_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2189 gint start, gint length, guint32 value,
2190 const char *format, ...)
2195 pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
2197 va_start(ap, format);
2198 proto_tree_set_representation_value(pi, format, ap);
2206 proto_tree_add_ipxnet_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2207 gint start, gint length, guint32 value,
2208 const char *format, ...)
2213 pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
2215 TRY_TO_FAKE_THIS_REPR(pi);
2217 va_start(ap, format);
2218 proto_tree_set_representation(pi, format, ap);
2225 /* Set the FT_IPXNET value */
2227 proto_tree_set_ipxnet(field_info *fi, guint32 value)
2229 fvalue_set_uinteger(&fi->value, value);
2232 /* Add a FT_IPv4 to a proto_tree */
2234 proto_tree_add_ipv4(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2235 gint length, guint32 value)
2238 header_field_info *hfinfo;
2240 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2242 DISSECTOR_ASSERT(hfinfo->type == FT_IPv4);
2244 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
2245 proto_tree_set_ipv4(PNODE_FINFO(pi), value);
2251 proto_tree_add_ipv4_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2252 gint start, gint length, guint32 value,
2253 const char *format, ...)
2258 pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
2260 va_start(ap, format);
2261 proto_tree_set_representation_value(pi, format, ap);
2269 proto_tree_add_ipv4_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2270 gint start, gint length, guint32 value,
2271 const char *format, ...)
2276 pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
2278 TRY_TO_FAKE_THIS_REPR(pi);
2280 va_start(ap, format);
2281 proto_tree_set_representation(pi, format, ap);
2288 /* Set the FT_IPv4 value */
2290 proto_tree_set_ipv4(field_info *fi, guint32 value)
2292 fvalue_set_uinteger(&fi->value, value);
2295 /* Add a FT_IPv6 to a proto_tree */
2297 proto_tree_add_ipv6(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2298 gint length, const guint8* value_ptr)
2301 header_field_info *hfinfo;
2303 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2305 DISSECTOR_ASSERT(hfinfo->type == FT_IPv6);
2307 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
2308 proto_tree_set_ipv6(PNODE_FINFO(pi), value_ptr);
2314 proto_tree_add_ipv6_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2315 gint start, gint length,
2316 const guint8* value_ptr,
2317 const char *format, ...)
2322 pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
2324 va_start(ap, format);
2325 proto_tree_set_representation_value(pi, format, ap);
2333 proto_tree_add_ipv6_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2334 gint start, gint length, const guint8* value_ptr,
2335 const char *format, ...)
2340 pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
2342 TRY_TO_FAKE_THIS_REPR(pi);
2344 va_start(ap, format);
2345 proto_tree_set_representation(pi, format, ap);
2352 /* Set the FT_IPv6 value */
2354 proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr)
2356 DISSECTOR_ASSERT(value_ptr != NULL);
2357 fvalue_set(&fi->value, (gpointer) value_ptr, FALSE);
2361 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
2363 proto_tree_set_ipv6(fi, tvb_get_ptr(tvb, start, length));
2366 /* Add a FT_GUID to a proto_tree */
2368 proto_tree_add_guid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2369 gint length, const e_guid_t *value_ptr)
2372 header_field_info *hfinfo;
2374 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2376 DISSECTOR_ASSERT(hfinfo->type == FT_GUID);
2378 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
2379 proto_tree_set_guid(PNODE_FINFO(pi), value_ptr);
2385 proto_tree_add_guid_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2386 gint start, gint length,
2387 const e_guid_t *value_ptr,
2388 const char *format, ...)
2393 pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
2395 va_start(ap, format);
2396 proto_tree_set_representation_value(pi, format, ap);
2404 proto_tree_add_guid_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2405 gint start, gint length, const e_guid_t *value_ptr,
2406 const char *format, ...)
2411 pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
2413 TRY_TO_FAKE_THIS_REPR(pi);
2415 va_start(ap, format);
2416 proto_tree_set_representation(pi, format, ap);
2423 /* Set the FT_GUID value */
2425 proto_tree_set_guid(field_info *fi, const e_guid_t *value_ptr)
2427 DISSECTOR_ASSERT(value_ptr != NULL);
2428 fvalue_set(&fi->value, (gpointer) value_ptr, FALSE);
2432 proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, gint start,
2433 const guint encoding)
2437 tvb_get_guid(tvb, start, &guid, encoding);
2438 proto_tree_set_guid(fi, &guid);
2441 /* Add a FT_OID to a proto_tree */
2443 proto_tree_add_oid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2444 gint length, const guint8* value_ptr)
2447 header_field_info *hfinfo;
2449 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2451 DISSECTOR_ASSERT(hfinfo->type == FT_OID);
2453 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
2454 proto_tree_set_oid(PNODE_FINFO(pi), value_ptr, length);
2460 proto_tree_add_oid_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2461 gint start, gint length,
2462 const guint8* value_ptr,
2463 const char *format, ...)
2468 pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
2470 va_start(ap, format);
2471 proto_tree_set_representation_value(pi, format, ap);
2479 proto_tree_add_oid_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2480 gint start, gint length, const guint8* value_ptr,
2481 const char *format, ...)
2486 pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
2488 TRY_TO_FAKE_THIS_REPR(pi);
2490 va_start(ap, format);
2491 proto_tree_set_representation(pi, format, ap);
2498 /* Set the FT_OID value */
2500 proto_tree_set_oid(field_info *fi, const guint8* value_ptr, gint length)
2504 DISSECTOR_ASSERT(value_ptr != NULL || length == 0);
2506 bytes = g_byte_array_new();
2508 g_byte_array_append(bytes, value_ptr, length);
2510 fvalue_set(&fi->value, bytes, TRUE);
2514 proto_tree_set_oid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
2516 proto_tree_set_oid(fi, tvb_get_ptr(tvb, start, length), length);
2520 proto_tree_set_uint64(field_info *fi, guint64 value)
2522 fvalue_set_integer64(&fi->value, value);
2526 * NOTE: to support code written when proto_tree_add_item() took a
2527 * gboolean as its last argument, with FALSE meaning "big-endian"
2528 * and TRUE meaning "little-endian", we treat any non-zero value of
2529 * "encoding" as meaning "little-endian".
2532 proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start,
2533 guint length, const guint encoding)
2536 guint8* b = (guint8 *)tvb_memdup(wmem_packet_scope(), tvb, start, length);
2541 default: DISSECTOR_ASSERT_NOT_REACHED();
2542 case 8: value <<= 8; value += *--b;
2543 case 7: value <<= 8; value += *--b;
2544 case 6: value <<= 8; value += *--b;
2545 case 5: value <<= 8; value += *--b;
2546 case 4: value <<= 8; value += *--b;
2547 case 3: value <<= 8; value += *--b;
2548 case 2: value <<= 8; value += *--b;
2549 case 1: value <<= 8; value += *--b;
2554 default: DISSECTOR_ASSERT_NOT_REACHED();
2555 case 8: value <<= 8; value += *b++;
2556 case 7: value <<= 8; value += *b++;
2557 case 6: value <<= 8; value += *b++;
2558 case 5: value <<= 8; value += *b++;
2559 case 4: value <<= 8; value += *b++;
2560 case 3: value <<= 8; value += *b++;
2561 case 2: value <<= 8; value += *b++;
2562 case 1: value <<= 8; value += *b++;
2567 proto_tree_set_uint64(fi, value);
2571 proto_tree_set_int64_tvb(field_info *fi, tvbuff_t *tvb, gint start,
2572 guint length, const guint encoding)
2575 guint8* b = (guint8 *)tvb_memdup(wmem_packet_scope(), tvb, start, length);
2580 default: DISSECTOR_ASSERT_NOT_REACHED();
2581 case 8: value <<= 8; value += *--b;
2582 case 7: value <<= 8; value += *--b;
2583 case 6: value <<= 8; value += *--b;
2584 case 5: value <<= 8; value += *--b;
2585 case 4: value <<= 8; value += *--b;
2586 case 3: value <<= 8; value += *--b;
2587 case 2: value <<= 8; value += *--b;
2588 case 1: value <<= 8; value += *--b;
2593 default: DISSECTOR_ASSERT_NOT_REACHED();
2594 case 8: value <<= 8; value += *b++;
2595 case 7: value <<= 8; value += *b++;
2596 case 6: value <<= 8; value += *b++;
2597 case 5: value <<= 8; value += *b++;
2598 case 4: value <<= 8; value += *b++;
2599 case 3: value <<= 8; value += *b++;
2600 case 2: value <<= 8; value += *b++;
2601 case 1: value <<= 8; value += *b++;
2609 value = ws_sign_ext64(value, 56);
2612 value = ws_sign_ext64(value, 48);
2615 value = ws_sign_ext64(value, 40);
2618 value = ws_sign_ext64(value, 32);
2621 value = ws_sign_ext64(value, 24);
2624 value = ws_sign_ext64(value, 16);
2627 value = ws_sign_ext64(value, 8);
2631 proto_tree_set_uint64(fi, value);
2634 /* Add a FT_STRING or FT_STRINGZ to a proto_tree. Creates own copy of string,
2635 * and frees it when the proto_tree is destroyed. */
2637 proto_tree_add_string(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2638 gint length, const char* value)
2641 header_field_info *hfinfo;
2643 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2645 DISSECTOR_ASSERT(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ);
2647 if (hfinfo->display == STR_UNICODE) {
2648 DISSECTOR_ASSERT(g_utf8_validate(value, -1, NULL));
2651 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
2652 DISSECTOR_ASSERT(length >= 0);
2653 proto_tree_set_string(PNODE_FINFO(pi), value);
2659 proto_tree_add_string_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2660 gint start, gint length, const char* value,
2667 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
2669 va_start(ap, format);
2670 proto_tree_set_representation_value(pi, format, ap);
2678 proto_tree_add_string_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2679 gint start, gint length, const char* value,
2680 const char *format, ...)
2685 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
2687 TRY_TO_FAKE_THIS_REPR(pi);
2689 va_start(ap, format);
2690 proto_tree_set_representation(pi, format, ap);
2697 /* Appends string data to a FT_STRING or FT_STRINGZ, allowing progressive
2698 * field info update instead of only updating the representation as does
2699 * proto_item_append_text()
2701 /* NOTE: this function will break with the TRY_TO_FAKE_THIS_ITEM()
2702 * speed optimization.
2703 * Currently only WSP use this function so it is not that bad but try to
2704 * avoid using this one if possible.
2705 * IF you must use this function you MUST also disable the
2706 * TRY_TO_FAKE_THIS_ITEM() optimization for your dissector/function
2707 * using proto_item_append_string().
2708 * Do that by faking that the tree is visible by calling
2709 * proto_tree_set_visible(tree, TRUE) (see packet-wsp.c)
2710 * BEFORE you create the item you are later going to use
2711 * proto_item_append_string() on.
2714 proto_item_append_string(proto_item *pi, const char *str)
2717 header_field_info *hfinfo;
2718 const gchar *old_str, *new_str;
2725 fi = PITEM_FINFO(pi);
2726 DISSECTOR_ASSERT_HINT(fi, "proto_tree_set_visible(tree, TRUE) should have been called previously");
2728 hfinfo = fi->hfinfo;
2729 if (hfinfo->type == FT_PROTOCOL) {
2730 /* TRY_TO_FAKE_THIS_ITEM() speed optimization: silently skip */
2733 DISSECTOR_ASSERT(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ);
2734 old_str = (guint8 *)fvalue_get(&fi->value);
2735 if (old_str && old_str[0])
2736 new_str = ep_strconcat(old_str, str, NULL);
2739 fvalue_set(&fi->value, (gpointer) new_str, FALSE);
2742 /* Set the FT_STRING value */
2744 proto_tree_set_string(field_info *fi, const char* value)
2747 fvalue_set(&fi->value, (gpointer) value, FALSE);
2749 fvalue_set(&fi->value, (gpointer) "[ Null ]", FALSE);
2754 proto_tree_set_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length, gint encoding)
2759 length = tvb_ensure_length_remaining(tvb, start);
2762 string = tvb_get_string_enc(wmem_packet_scope(), tvb, start, length, encoding);
2763 proto_tree_set_string(fi, string);
2767 /* Add a FT_AX25 to a proto_tree */
2769 proto_tree_add_ax25(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2770 const guint8* value)
2773 header_field_info *hfinfo;
2775 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2777 DISSECTOR_ASSERT(hfinfo->type == FT_AX25);
2779 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
2780 proto_tree_set_ax25(PNODE_FINFO(pi), value);
2785 /* Set the FT_AX25 value */
2787 proto_tree_set_ax25(field_info *fi, const guint8* value)
2789 fvalue_set(&fi->value, (gpointer) value, FALSE);
2793 proto_tree_set_ax25_tvb(field_info *fi, tvbuff_t *tvb, gint start)
2795 proto_tree_set_ax25(fi, tvb_get_ptr(tvb, start, 7));
2798 /* Set the FT_VINES value */
2800 proto_tree_set_vines(field_info *fi, const guint8* value)
2802 fvalue_set(&fi->value, (gpointer) value, FALSE);
2806 proto_tree_set_vines_tvb(field_info *fi, tvbuff_t *tvb, gint start)
2808 proto_tree_set_vines(fi, tvb_get_ptr(tvb, start, FT_VINES_ADDR_LEN));
2811 /* Add a FT_ETHER to a proto_tree */
2813 proto_tree_add_ether(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2814 gint length, const guint8* value)
2817 header_field_info *hfinfo;
2819 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2821 DISSECTOR_ASSERT(hfinfo->type == FT_ETHER);
2823 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
2824 proto_tree_set_ether(PNODE_FINFO(pi), value);
2830 proto_tree_add_ether_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2831 gint start, gint length, const guint8* value,
2832 const char *format, ...)
2837 pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
2839 va_start(ap, format);
2840 proto_tree_set_representation_value(pi, format, ap);
2848 proto_tree_add_ether_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2849 gint start, gint length, const guint8* value,
2850 const char *format, ...)
2855 pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
2857 TRY_TO_FAKE_THIS_REPR(pi);
2859 va_start(ap, format);
2860 proto_tree_set_representation(pi, format, ap);
2867 /* Set the FT_ETHER value */
2869 proto_tree_set_ether(field_info *fi, const guint8* value)
2871 fvalue_set(&fi->value, (gpointer) value, FALSE);
2875 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start)
2877 proto_tree_set_ether(fi, tvb_get_ptr(tvb, start, FT_ETHER_LEN));
2880 /* Add a FT_BOOLEAN to a proto_tree */
2882 proto_tree_add_boolean(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2883 gint length, guint32 value)
2886 header_field_info *hfinfo;
2888 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2890 DISSECTOR_ASSERT(hfinfo->type == FT_BOOLEAN);
2892 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
2893 proto_tree_set_boolean(PNODE_FINFO(pi), value);
2899 proto_tree_add_boolean_format_value(proto_tree *tree, int hfindex,
2900 tvbuff_t *tvb, gint start, gint length,
2901 guint32 value, const char *format, ...)
2906 pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
2908 va_start(ap, format);
2909 proto_tree_set_representation_value(pi, format, ap);
2917 proto_tree_add_boolean_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2918 gint start, gint length, guint32 value,
2919 const char *format, ...)
2924 pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
2926 TRY_TO_FAKE_THIS_REPR(pi);
2928 va_start(ap, format);
2929 proto_tree_set_representation(pi, format, ap);
2936 /* Set the FT_BOOLEAN value */
2938 proto_tree_set_boolean(field_info *fi, guint32 value)
2940 proto_tree_set_uint(fi, value);
2943 /* Add a FT_FLOAT to a proto_tree */
2945 proto_tree_add_float(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2946 gint length, float value)
2949 header_field_info *hfinfo;
2951 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2953 DISSECTOR_ASSERT(hfinfo->type == FT_FLOAT);
2955 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
2956 proto_tree_set_float(PNODE_FINFO(pi), value);
2962 proto_tree_add_float_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2963 gint start, gint length, float value,
2964 const char *format, ...)
2969 pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
2971 va_start(ap, format);
2972 proto_tree_set_representation_value(pi, format, ap);
2980 proto_tree_add_float_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2981 gint start, gint length, float value,
2982 const char *format, ...)
2987 pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
2989 TRY_TO_FAKE_THIS_REPR(pi);
2991 va_start(ap, format);
2992 proto_tree_set_representation(pi, format, ap);
2999 /* Set the FT_FLOAT value */
3001 proto_tree_set_float(field_info *fi, float value)
3003 fvalue_set_floating(&fi->value, value);
3006 /* Add a FT_DOUBLE to a proto_tree */
3008 proto_tree_add_double(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3009 gint length, double value)
3012 header_field_info *hfinfo;
3014 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3016 DISSECTOR_ASSERT(hfinfo->type == FT_DOUBLE);
3018 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
3019 proto_tree_set_double(PNODE_FINFO(pi), value);
3025 proto_tree_add_double_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3026 gint start, gint length, double value,
3027 const char *format, ...)
3032 pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
3034 va_start(ap, format);
3035 proto_tree_set_representation_value(pi, format, ap);
3043 proto_tree_add_double_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3044 gint start, gint length, double value,
3045 const char *format, ...)
3050 pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
3052 TRY_TO_FAKE_THIS_REPR(pi);
3054 va_start(ap, format);
3055 proto_tree_set_representation(pi, format, ap);
3062 /* Set the FT_DOUBLE value */
3064 proto_tree_set_double(field_info *fi, double value)
3066 fvalue_set_floating(&fi->value, value);
3069 /* Add FT_UINT{8,16,24,32} to a proto_tree */
3071 proto_tree_add_uint(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3072 gint length, guint32 value)
3074 proto_item *pi = NULL;
3075 header_field_info *hfinfo;
3077 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3079 switch (hfinfo->type) {
3085 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
3086 proto_tree_set_uint(PNODE_FINFO(pi), value);
3090 DISSECTOR_ASSERT_NOT_REACHED();
3097 proto_tree_add_uint_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3098 gint start, gint length, guint32 value,
3099 const char *format, ...)
3104 pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
3106 va_start(ap, format);
3107 proto_tree_set_representation_value(pi, format, ap);
3115 proto_tree_add_uint_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3116 gint start, gint length, guint32 value,
3117 const char *format, ...)
3122 pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
3124 TRY_TO_FAKE_THIS_REPR(pi);
3126 va_start(ap, format);
3127 proto_tree_set_representation(pi, format, ap);
3134 /* Set the FT_UINT{8,16,24,32} value */
3136 proto_tree_set_uint(field_info *fi, guint32 value)
3138 header_field_info *hfinfo;
3141 hfinfo = fi->hfinfo;
3144 if (hfinfo->bitmask) {
3145 /* Mask out irrelevant portions */
3146 integer &= hfinfo->bitmask;
3149 integer >>= hfinfo_bitshift(hfinfo);
3152 fvalue_set_uinteger(&fi->value, integer);
3155 /* Add FT_UINT64 to a proto_tree */
3157 proto_tree_add_uint64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3158 gint length, guint64 value)
3161 header_field_info *hfinfo;
3163 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3165 DISSECTOR_ASSERT(hfinfo->type == FT_UINT64);
3167 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
3168 proto_tree_set_uint64(PNODE_FINFO(pi), value);
3174 proto_tree_add_uint64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3175 gint start, gint length, guint64 value,
3176 const char *format, ...)
3181 pi = proto_tree_add_uint64(tree, hfindex, tvb, start, length, value);
3183 va_start(ap, format);
3184 proto_tree_set_representation_value(pi, format, ap);
3192 proto_tree_add_uint64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3193 gint start, gint length, guint64 value,
3194 const char *format, ...)
3199 pi = proto_tree_add_uint64(tree, hfindex, tvb, start, length, value);
3201 TRY_TO_FAKE_THIS_REPR(pi);
3203 va_start(ap, format);
3204 proto_tree_set_representation(pi, format, ap);
3211 /* Add FT_INT{8,16,24,32} to a proto_tree */
3213 proto_tree_add_int(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3214 gint length, gint32 value)
3216 proto_item *pi = NULL;
3217 header_field_info *hfinfo;
3219 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3221 switch (hfinfo->type) {
3226 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
3227 proto_tree_set_int(PNODE_FINFO(pi), value);
3231 DISSECTOR_ASSERT_NOT_REACHED();
3238 proto_tree_add_int_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3239 gint start, gint length, gint32 value,
3240 const char *format, ...)
3245 pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
3247 va_start(ap, format);
3248 proto_tree_set_representation_value(pi, format, ap);
3256 proto_tree_add_int_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3257 gint start, gint length, gint32 value,
3258 const char *format, ...)
3263 pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
3265 TRY_TO_FAKE_THIS_REPR(pi);
3267 va_start(ap, format);
3268 proto_tree_set_representation(pi, format, ap);
3275 /* Set the FT_INT{8,16,24,32} value */
3277 proto_tree_set_int(field_info *fi, gint32 value)
3279 header_field_info *hfinfo;
3283 hfinfo = fi->hfinfo;
3284 integer = (guint32) value;
3286 if (hfinfo->bitmask) {
3287 /* Mask out irrelevant portions */
3288 integer &= hfinfo->bitmask;
3291 integer >>= hfinfo_bitshift(hfinfo);
3293 no_of_bits = ws_count_ones(hfinfo->bitmask);
3294 integer = ws_sign_ext32(integer, no_of_bits);
3297 fvalue_set_sinteger(&fi->value, integer);
3300 /* Add FT_INT64 to a proto_tree */
3302 proto_tree_add_int64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3303 gint length, gint64 value)
3306 header_field_info *hfinfo;
3308 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3310 DISSECTOR_ASSERT(hfinfo->type == FT_INT64);
3312 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
3313 proto_tree_set_uint64(PNODE_FINFO(pi), (guint64)value);
3319 proto_tree_add_int64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3320 gint start, gint length, gint64 value,
3321 const char *format, ...)
3326 pi = proto_tree_add_int64(tree, hfindex, tvb, start, length, value);
3328 va_start(ap, format);
3329 proto_tree_set_representation_value(pi, format, ap);
3337 proto_tree_add_int64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3338 gint start, gint length, gint64 value,
3339 const char *format, ...)
3344 pi = proto_tree_add_int64(tree, hfindex, tvb, start, length, value);
3346 TRY_TO_FAKE_THIS_REPR(pi);
3348 va_start(ap, format);
3349 proto_tree_set_representation(pi, format, ap);
3355 /* Add a FT_EUI64 to a proto_tree */
3357 proto_tree_add_eui64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3358 gint length, const guint64 value)
3361 header_field_info *hfinfo;
3363 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3365 DISSECTOR_ASSERT(hfinfo->type == FT_EUI64);
3367 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
3368 proto_tree_set_eui64(PNODE_FINFO(pi), value);
3374 proto_tree_add_eui64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3375 gint start, gint length, const guint64 value,
3376 const char *format, ...)
3381 pi = proto_tree_add_eui64(tree, hfindex, tvb, start, length, value);
3383 va_start(ap, format);
3384 proto_tree_set_representation_value(pi, format, ap);
3392 proto_tree_add_eui64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3393 gint start, gint length, const guint64 value,
3394 const char *format, ...)
3399 pi = proto_tree_add_eui64(tree, hfindex, tvb, start, length, value);
3401 TRY_TO_FAKE_THIS_REPR(pi);
3403 va_start(ap, format);
3404 proto_tree_set_representation(pi, format, ap);
3411 /* Set the FT_EUI64 value */
3413 proto_tree_set_eui64(field_info *fi, const guint64 value)
3415 fvalue_set_integer64(&fi->value, value);
3418 proto_tree_set_eui64_tvb(field_info *fi, tvbuff_t *tvb, gint start, const guint encoding)
3422 proto_tree_set_eui64(fi, tvb_get_letoh64(tvb, start));
3424 proto_tree_set_eui64(fi, tvb_get_ntoh64(tvb, start));
3428 /* Add a field_info struct to the proto_tree, encapsulating it in a proto_node */
3430 proto_tree_add_node(proto_tree *tree, field_info *fi)
3432 proto_node *pnode, *tnode, *sibling;
3436 * Make sure "tree" is ready to have subtrees under it, by
3437 * checking whether it's been given an ett_ value.
3439 * "PNODE_FINFO(tnode)" may be null; that's the case for the root
3440 * node of the protocol tree. That node is not displayed,
3441 * so it doesn't need an ett_ value to remember whether it
3445 tfi = PNODE_FINFO(tnode);
3446 if (tfi != NULL && (tfi->tree_type < 0 || tfi->tree_type >= num_tree_types)) {
3447 REPORT_DISSECTOR_BUG(ep_strdup_printf("\"%s\" - \"%s\" tfi->tree_type: %u invalid (%s:%u)",
3448 fi->hfinfo->name, fi->hfinfo->abbrev, tfi->tree_type, __FILE__, __LINE__));
3449 /* XXX - is it safe to continue here? */
3452 pnode = wmem_new(PNODE_POOL(tree), proto_node);
3453 PROTO_NODE_INIT(pnode);
3454 pnode->parent = tnode;
3455 PNODE_FINFO(pnode) = fi;
3456 pnode->tree_data = PTREE_DATA(tree);
3458 if (tnode->last_child != NULL) {
3459 sibling = tnode->last_child;
3460 DISSECTOR_ASSERT(sibling->next == NULL);
3461 sibling->next = pnode;
3463 tnode->first_child = pnode;
3464 tnode->last_child = pnode;
3466 tree_data_add_maybe_interesting_field(pnode->tree_data, fi);
3468 return (proto_item *)pnode;
3472 /* Generic way to allocate field_info and add to proto_tree.
3473 * Sets *pfi to address of newly-allocated field_info struct */
3475 proto_tree_add_pi(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb, gint start,
3481 fi = alloc_field_info(tree, hfinfo, tvb, start, length);
3482 pi = proto_tree_add_node(tree, fi);
3489 get_hfi_length(header_field_info *hfinfo, tvbuff_t *tvb, const gint start, gint *length,
3492 gint length_remaining;
3495 * We only allow a null tvbuff if the item has a zero length,
3496 * i.e. if there's no data backing it.
3498 DISSECTOR_ASSERT(tvb != NULL || *length == 0);
3501 * XXX - in some protocols, there are 32-bit unsigned length
3502 * fields, so lengths in protocol tree and tvbuff routines
3503 * should really be unsigned. We should have, for those
3504 * field types for which "to the end of the tvbuff" makes sense,
3505 * additional routines that take no length argument and
3506 * add fields that run to the end of the tvbuff.
3508 if (*length == -1) {
3510 * For FT_NONE, FT_PROTOCOL, FT_BYTES, and FT_STRING fields,
3511 * a length of -1 means "set the length to what remains in
3514 * The assumption is either that
3516 * 1) the length of the item can only be determined
3517 * by dissection (typically true of items with
3518 * subitems, which are probably FT_NONE or
3523 * 2) if the tvbuff is "short" (either due to a short
3524 * snapshot length or due to lack of reassembly of
3525 * fragments/segments/whatever), we want to display
3526 * what's available in the field (probably FT_BYTES
3527 * or FT_STRING) and then throw an exception later
3531 * 3) the field is defined to be "what's left in the
3534 * so we set the length to what remains in the tvbuff so
3535 * that, if we throw an exception while dissecting, it
3536 * has what is probably the right value.
3538 * For FT_STRINGZ, it means "the string is null-terminated,
3539 * not null-padded; set the length to the actual length
3540 * of the string", and if the tvbuff if short, we just
3541 * throw an exception.
3543 * It's not valid for any other type of field.
3545 switch (hfinfo->type) {
3549 * We allow this to be zero-length - for
3550 * example, an ONC RPC NULL procedure has
3551 * neither arguments nor reply, so the
3552 * payload for that protocol is empty.
3554 * However, if the length is negative, the
3555 * start offset is *past* the byte past the
3556 * end of the tvbuff, so we throw an
3559 *length = tvb_length_remaining(tvb, start);
3562 * Use "tvb_ensure_bytes_exist()"
3563 * to force the appropriate exception
3566 tvb_ensure_bytes_exist(tvb, start, 0);
3568 DISSECTOR_ASSERT(*length >= 0);
3574 *length = tvb_ensure_length_remaining(tvb, start);
3575 DISSECTOR_ASSERT(*length >= 0);
3580 * Leave the length as -1, so our caller knows
3586 DISSECTOR_ASSERT_NOT_REACHED();
3588 *item_length = *length;
3590 *item_length = *length;
3591 if (hfinfo->type == FT_PROTOCOL || hfinfo->type == FT_NONE) {
3593 * These types are for interior nodes of the
3594 * tree, and don't have data associated with
3595 * them; if the length is negative (XXX - see
3596 * above) or goes past the end of the tvbuff,
3597 * cut it short at the end of the tvbuff.
3598 * That way, if this field is selected in
3599 * Wireshark, we don't highlight stuff past
3600 * the end of the data.
3602 /* XXX - what to do, if we don't have a tvb? */
3604 length_remaining = tvb_length_remaining(tvb, start);
3605 if (*item_length < 0 ||
3606 (*item_length > 0 &&
3607 (length_remaining < *item_length)))
3608 *item_length = length_remaining;
3611 if (*item_length < 0) {
3612 THROW(ReportedBoundsError);
3618 new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
3619 const gint start, const gint item_length)
3623 FIELD_INFO_NEW(PNODE_POOL(tree), fi);
3625 fi->hfinfo = hfinfo;
3627 fi->start += (tvb)?tvb_raw_offset(tvb):0;
3628 fi->length = item_length;
3631 if (!PTREE_DATA(tree)->visible)
3632 FI_SET_FLAG(fi, FI_HIDDEN);
3633 fvalue_init(&fi->value, fi->hfinfo->type);
3636 /* add the data source tvbuff */
3637 fi->ds_tvb = tvb ? tvb_get_ds_tvb(tvb) : NULL;
3639 fi->appendix_start = 0;
3640 fi->appendix_length = 0;
3646 alloc_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb, const gint start,
3651 get_hfi_length(hfinfo, tvb, start, length, &item_length);
3652 return new_field_info(tree, hfinfo, tvb, start, item_length);
3656 label_mark_truncated_start(char *label_str)
3658 static const char trunc_str[] = "[truncated] ";
3659 const size_t trunc_len = sizeof(trunc_str)-1;
3661 memmove(label_str + trunc_len, label_str, ITEM_LABEL_LENGTH - trunc_len);
3662 memcpy(label_str, trunc_str, trunc_len);
3663 label_str[ITEM_LABEL_LENGTH-1] = '\0';
3666 /* If the protocol tree is to be visible, set the representation of a
3667 proto_tree entry with the name of the field for the item and with
3668 the value formatted with the supplied printf-style format and
3671 proto_tree_set_representation_value(proto_item *pi, const char *format, va_list ap)
3675 /* If the tree (GUI) or item isn't visible it's pointless for us to generate the protocol
3676 * items string representation */
3677 if (PTREE_DATA(pi)->visible && !PROTO_ITEM_IS_HIDDEN(pi)) {
3679 field_info *fi = PITEM_FINFO(pi);
3680 header_field_info *hf;
3682 DISSECTOR_ASSERT(fi);
3686 ITEM_LABEL_NEW(PNODE_POOL(pi), fi->rep);
3687 if (hf->bitmask && (hf->type == FT_BOOLEAN || IS_FT_UINT(hf->type))) {
3691 val = fvalue_get_uinteger(&fi->value);
3692 val <<= hfinfo_bitshift(hf);
3694 p = decode_bitfield_value(fi->rep->representation, val, hf->bitmask, hfinfo_bitwidth(hf));
3695 ret = (int) (p - fi->rep->representation);
3698 /* put in the hf name */
3699 ret += g_snprintf(fi->rep->representation + ret, ITEM_LABEL_LENGTH - ret, "%s: ", hf->name);
3701 /* If possible, Put in the value of the string */
3702 if (ret < ITEM_LABEL_LENGTH) {
3703 ret += g_vsnprintf(fi->rep->representation + ret,
3704 ITEM_LABEL_LENGTH - ret, format, ap);
3706 if (ret >= ITEM_LABEL_LENGTH) {
3707 /* Uh oh, we don't have enough room. Tell the user
3708 * that the field is truncated.
3710 /* XXX, label_mark_truncated() ? */
3711 label_mark_truncated_start(fi->rep->representation);
3716 /* If the protocol tree is to be visible, set the representation of a
3717 proto_tree entry with the representation formatted with the supplied
3718 printf-style format and argument list. */
3720 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap)
3722 int ret; /*tmp return value */
3723 field_info *fi = PITEM_FINFO(pi);
3725 DISSECTOR_ASSERT(fi);
3727 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
3728 ITEM_LABEL_NEW(PNODE_POOL(pi), fi->rep);
3729 ret = g_vsnprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
3731 if (ret >= ITEM_LABEL_LENGTH) {
3732 /* Uh oh, we don't have enough room. Tell the user
3733 * that the field is truncated.
3735 label_mark_truncated_start(fi->rep->representation);
3741 hfinfo_format_text(const header_field_info *hfinfo, const guchar *string)
3743 switch (hfinfo->display) {
3745 return format_text(string, strlen(string));
3748 return format_text_wsp(string, strlen(string));
3751 /* XXX, format_unicode_text() */
3755 return format_text(string, strlen(string));
3759 protoo_strlcpy(gchar *dest, const gchar *src, gsize dest_size)
3761 gsize res = g_strlcpy(dest, src, dest_size);
3763 if (res > dest_size)
3768 static header_field_info *
3769 hfinfo_same_name_get_prev(const header_field_info *hfinfo)
3771 if (hfinfo->same_name_prev_id == -1)
3773 return proto_registrar_get_nth(hfinfo->same_name_prev_id);
3776 /* -------------------------- */
3778 proto_custom_set(proto_tree* tree, const int field_id, gint occurrence,
3779 gchar *result, gchar *expr, const int size)
3784 struct e_in6_addr *ipv6;
3786 guint32 n_addr; /* network-order IPv4 address */
3788 const true_false_string *tfstring;
3790 int len, prev_len = 0, last, i, offset_r = 0, offset_e = 0;
3792 field_info *finfo = NULL;
3793 header_field_info* hfinfo;
3794 const gchar *abbrev = NULL;
3796 const char *hf_str_val;
3797 char number_buf[32];
3798 const char *number_out;
3800 g_assert(field_id >= 0);
3802 hfinfo = proto_registrar_get_nth((guint)field_id);
3804 /* do we need to rewind ? */
3808 if (occurrence < 0) {
3809 /* Search other direction */
3810 while (hfinfo->same_name_prev_id != -1) {
3811 hfinfo = proto_registrar_get_nth(hfinfo->same_name_prev_id);
3816 finfos = proto_get_finfo_ptr_array(tree, hfinfo->id);
3818 if (!finfos || !(len = g_ptr_array_len(finfos))) {
3819 if (occurrence < 0) {
3820 hfinfo = hfinfo->same_name_next;
3822 hfinfo = hfinfo_same_name_get_prev(hfinfo);
3827 /* Are there enough occurrences of the field? */
3828 if (((occurrence - prev_len) > len) || ((occurrence + prev_len) < -len)) {
3829 if (occurrence < 0) {
3830 hfinfo = hfinfo->same_name_next;
3832 hfinfo = hfinfo_same_name_get_prev(hfinfo);
3838 /* Calculate single index or set outer bounderies */
3839 if (occurrence < 0) {
3840 i = occurrence + len + prev_len;
3842 } else if (occurrence > 0) {
3843 i = occurrence - 1 - prev_len;
3850 prev_len += len; /* Count handled occurrences */
3853 finfo = (field_info *)g_ptr_array_index(finfos, i);
3855 if (offset_r && (offset_r < (size - 2)))
3856 result[offset_r++] = ',';
3858 if (offset_e && (offset_e < (size - 2)))
3859 expr[offset_e++] = ',';
3861 switch (hfinfo->type) {
3863 case FT_NONE: /* Nothing to add */
3864 if (offset_r == 0) {
3866 } else if (result[offset_r-1] == ',') {
3867 result[offset_r-1] = '\0';
3872 /* prevent multiple "yes" entries by setting result directly */
3873 g_strlcpy(result, "Yes", size);
3878 bytes = (guint8 *)fvalue_get(&finfo->value);
3879 offset_r += protoo_strlcpy(result+offset_r,
3881 fvalue_length(&finfo->value)),
3885 case FT_ABSOLUTE_TIME:
3886 offset_r += protoo_strlcpy(result+offset_r,
3887 abs_time_to_str((const nstime_t *)fvalue_get(&finfo->value),
3888 (absolute_time_display_e)hfinfo->display, TRUE),
3892 case FT_RELATIVE_TIME:
3893 offset_r += protoo_strlcpy(result+offset_r,
3894 rel_time_to_secs_str((const nstime_t *)fvalue_get(&finfo->value)),
3899 number = fvalue_get_uinteger(&finfo->value);
3900 tfstring = (const true_false_string *)&tfs_true_false;
3901 if (hfinfo->strings) {
3902 tfstring = (const struct true_false_string*) hfinfo->strings;
3904 offset_r += protoo_strlcpy(result+offset_r,
3906 tfstring->true_string :
3907 tfstring->false_string, size-offset_r);
3909 offset_e += protoo_strlcpy(expr+offset_e,
3910 number ? "1" : "0", size-offset_e);
3913 /* XXX - make these just FT_NUMBER? */
3924 number = IS_FT_INT(hfinfo->type) ?
3925 (guint32) fvalue_get_sinteger(&finfo->value) :
3926 fvalue_get_uinteger(&finfo->value);
3928 if ((hfinfo->display & FIELD_DISPLAY_E_MASK) == BASE_CUSTOM) {
3929 gchar tmp[ITEM_LABEL_LENGTH];
3930 custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hfinfo->strings;
3932 DISSECTOR_ASSERT(fmtfunc);
3933 fmtfunc(tmp, number);
3935 offset_r += protoo_strlcpy(result+offset_r, tmp, size-offset_r);
3937 } else if (hfinfo->strings) {
3938 number_out = hf_str_val = hf_try_val_to_str(number, hfinfo);
3941 number_out = hfinfo_number_value_format_display(hfinfo, BASE_DEC, number_buf, number);
3943 offset_r += protoo_strlcpy(result+offset_r, number_out, size-offset_r);
3946 number_out = hfinfo_number_value_format(hfinfo, number_buf, number);
3948 offset_r += protoo_strlcpy(result+offset_r, number_out, size-offset_r);
3951 if (hf_str_val && (hfinfo->display & FIELD_DISPLAY_E_MASK) == BASE_NONE) {
3952 g_snprintf(expr+offset_e, size-offset_e, "\"%s\"", hf_str_val);
3954 number_out = hfinfo_numeric_value_format(hfinfo, number_buf, number);
3956 g_strlcpy(expr+offset_e, number_out, size-offset_e);
3959 offset_e = (int)strlen(expr);
3963 /* XXX: Should handle BASE_CUSTOM ? */
3964 g_snprintf(result+offset_r, size-offset_r,
3965 "%" G_GINT64_MODIFIER "d",
3966 fvalue_get_integer64(&finfo->value));
3967 offset_r = (int)strlen(result);
3970 g_snprintf(result+offset_r, size-offset_r,
3971 /* XXX: Should handle BASE_CUSTOM ? */
3972 "%" G_GINT64_MODIFIER "u",
3973 fvalue_get_integer64(&finfo->value));
3974 offset_r = (int)strlen(result);
3977 offset_r += protoo_strlcpy(result+offset_r,
3978 eui64_to_str(fvalue_get_integer64(&finfo->value)),
3983 ipv4 = (ipv4_addr *)fvalue_get(&finfo->value);
3984 n_addr = ipv4_get_net_order_addr(ipv4);
3985 offset_r += protoo_strlcpy(result+offset_r,
3986 ip_to_str((guint8 *)&n_addr),
3991 ipv6 = (struct e_in6_addr *)fvalue_get(&finfo->value);
3992 SET_ADDRESS (&addr, AT_IPv6, sizeof(struct e_in6_addr), ipv6);
3993 address_to_str_buf(&addr, result+offset_r, size-offset_r);
3994 offset_r = (int)strlen(result);
3998 offset_r += protoo_strlcpy(result+offset_r,
3999 bytes_to_str_punct((const guint8 *)fvalue_get(&finfo->value),
4005 offset_r += protoo_strlcpy(result+offset_r,
4006 guid_to_str((e_guid_t *)fvalue_get(&finfo->value)),
4011 bytes = (guint8 *)fvalue_get(&finfo->value);
4012 offset_r += protoo_strlcpy(result+offset_r,
4013 rel_oid_resolved_from_encoded(bytes,
4014 fvalue_length(&finfo->value)),
4016 offset_e += protoo_strlcpy(expr+offset_e,
4017 rel_oid_encoded2string(bytes, fvalue_length(&finfo->value)),
4022 bytes = (guint8 *)fvalue_get(&finfo->value);
4023 offset_r += protoo_strlcpy(result+offset_r,
4024 oid_resolved_from_encoded(bytes,
4025 fvalue_length(&finfo->value)),
4027 offset_e += protoo_strlcpy(expr+offset_e,
4028 oid_encoded2string(bytes, fvalue_length(&finfo->value)),
4033 g_snprintf(result+offset_r, size-offset_r,
4034 "%." G_STRINGIFY(FLT_DIG) "g", fvalue_get_floating(&finfo->value));
4035 offset_r = (int)strlen(result);
4039 g_snprintf(result+offset_r, size-offset_r,
4040 "%." G_STRINGIFY(DBL_DIG) "g", fvalue_get_floating(&finfo->value));
4041 offset_r = (int)strlen(result);
4046 case FT_UINT_STRING:
4047 bytes = (guint8 *)fvalue_get(&finfo->value);
4048 offset_r += protoo_strlcpy(result+offset_r,
4049 hfinfo_format_text(hfinfo, bytes),
4053 case FT_IPXNET: /*XXX really No column custom ?*/
4056 g_error("hfinfo->type %d (%s) not handled\n",
4058 ftype_name(hfinfo->type));
4059 DISSECTOR_ASSERT_NOT_REACHED();
4065 switch (hfinfo->type) {
4079 /* for these types, "expr" is filled in the loop above */
4083 /* for all others, just copy "result" to "expr" */
4084 g_strlcpy(expr, result, size);
4089 /* Store abbrev for return value */
4090 abbrev = hfinfo->abbrev;
4093 if (occurrence == 0) {
4094 /* Fetch next hfinfo with same name (abbrev) */
4095 hfinfo = hfinfo_same_name_get_prev(hfinfo);
4101 return abbrev ? abbrev : "";
4105 /* Set text of proto_item after having already been created. */
4107 proto_item_set_text(proto_item *pi, const char *format, ...)
4109 field_info *fi = NULL;
4116 fi = PITEM_FINFO(pi);
4121 ITEM_LABEL_FREE(PNODE_POOL(pi), fi->rep);
4125 va_start(ap, format);
4126 proto_tree_set_representation(pi, format, ap);
4130 /* Append to text of proto_item after having already been created. */
4132 proto_item_append_text(proto_item *pi, const char *format, ...)
4134 field_info *fi = NULL;
4142 fi = PITEM_FINFO(pi);
4147 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
4149 * If we don't already have a representation,
4150 * generate the default representation.
4152 if (fi->rep == NULL) {
4153 ITEM_LABEL_NEW(PNODE_POOL(pi), fi->rep);
4154 proto_item_fill_label(fi, fi->rep->representation);
4157 curlen = strlen(fi->rep->representation);
4158 if (ITEM_LABEL_LENGTH > curlen) {
4159 va_start(ap, format);
4160 g_vsnprintf(fi->rep->representation + curlen,
4161 ITEM_LABEL_LENGTH - (gulong) curlen, format, ap);
4167 /* Prepend to text of proto_item after having already been created. */
4169 proto_item_prepend_text(proto_item *pi, const char *format, ...)
4171 field_info *fi = NULL;
4172 char representation[ITEM_LABEL_LENGTH];
4179 fi = PITEM_FINFO(pi);
4184 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
4186 * If we don't already have a representation,
4187 * generate the default representation.
4189 if (fi->rep == NULL) {
4190 ITEM_LABEL_NEW(PNODE_POOL(pi), fi->rep);
4191 proto_item_fill_label(fi, representation);
4193 g_strlcpy(representation, fi->rep->representation, ITEM_LABEL_LENGTH);
4195 va_start(ap, format);
4196 g_vsnprintf(fi->rep->representation,
4197 ITEM_LABEL_LENGTH, format, ap);
4199 g_strlcat(fi->rep->representation, representation, ITEM_LABEL_LENGTH);
4204 proto_item_set_len(proto_item *pi, const gint length)
4211 fi = PITEM_FINFO(pi);
4215 DISSECTOR_ASSERT(length >= 0);
4216 fi->length = length;
4219 * You cannot just make the "len" field of a GByteArray
4220 * larger, if there's no data to back that length;
4221 * you can only make it smaller.
4223 if (fi->value.ftype->ftype == FT_BYTES && length <= (gint)fi->value.value.bytes->len)
4224 fi->value.value.bytes->len = length;
4228 * Sets the length of the item based on its start and on the specified
4229 * offset, which is the offset past the end of the item; as the start
4230 * in the item is relative to the beginning of the data source tvbuff,
4231 * we need to pass in a tvbuff - the end offset is relative to the beginning
4235 proto_item_set_end(proto_item *pi, tvbuff_t *tvb, gint end)
4242 fi = PITEM_FINFO(pi);
4246 end += tvb_raw_offset(tvb);
4247 DISSECTOR_ASSERT(end >= fi->start);
4248 fi->length = end - fi->start;
4252 proto_item_get_len(const proto_item *pi)
4254 field_info *fi = PITEM_FINFO(pi);
4255 return fi ? fi->length : -1;
4259 proto_tree_create_root(packet_info *pinfo)
4263 /* Initialize the proto_node */
4264 pnode = g_slice_new(proto_tree);
4265 PROTO_NODE_INIT(pnode);
4266 pnode->parent = NULL;
4267 PNODE_FINFO(pnode) = NULL;
4268 pnode->tree_data = g_slice_new(tree_data_t);
4270 /* Make sure we can access pinfo everywhere */
4271 pnode->tree_data->pinfo = pinfo;
4273 /* Don't initialize the tree_data_t. Wait until we know we need it */
4274 pnode->tree_data->interesting_hfids = NULL;
4276 /* Set the default to FALSE so it's easier to
4277 * find errors; if we expect to see the protocol tree
4278 * but for some reason the default 'visible' is not
4279 * changed, then we'll find out very quickly. */
4280 pnode->tree_data->visible = FALSE;
4282 /* Make sure that we fake protocols (if possible) */
4283 pnode->tree_data->fake_protocols = TRUE;
4285 /* Keep track of the number of children */
4286 pnode->tree_data->count = 0;
4288 return (proto_tree *)pnode;
4292 /* "prime" a proto_tree with a single hfid that a dfilter
4293 * is interested in. */
4295 proto_tree_prime_hfid(proto_tree *tree _U_, const gint hfid)
4297 header_field_info *hfinfo;
4299 PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
4300 /* this field is referenced by a filter so increase the refcount.
4301 also increase the refcount for the parent, i.e the protocol.
4303 hfinfo->ref_type = HF_REF_TYPE_DIRECT;
4304 /* only increase the refcount if there is a parent.
4305 if this is a protocol and not a field then parent will be -1
4306 and there is no parent to add any refcounting for.
4308 if (hfinfo->parent != -1) {
4309 header_field_info *parent_hfinfo;
4310 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
4312 /* Mark parent as indirectly referenced unless it is already directly
4313 * referenced, i.e. the user has specified the parent in a filter.
4315 if (parent_hfinfo->ref_type != HF_REF_TYPE_DIRECT)
4316 parent_hfinfo->ref_type = HF_REF_TYPE_INDIRECT;
4321 proto_item_add_subtree(proto_item *pi, const gint idx) {
4327 DISSECTOR_ASSERT(idx >= 0 && idx < num_tree_types);
4329 fi = PITEM_FINFO(pi);
4331 return (proto_tree *)pi;
4333 fi->tree_type = idx;
4335 return (proto_tree *)pi;
4339 proto_item_get_subtree(const proto_item *pi) {
4344 fi = PITEM_FINFO(pi);
4345 if ( (!fi) || (fi->tree_type == -1) )
4347 return (proto_tree *)pi;
4351 proto_item_get_parent(const proto_item *ti) {
4358 proto_item_get_parent_nth(proto_item *ti, int gen) {
4371 proto_tree_get_parent(const proto_tree *tree) {
4374 return (proto_item *)tree;
4378 proto_tree_get_root(proto_tree *tree) {
4381 while (tree->parent) {
4382 tree = tree->parent;
4388 proto_tree_move_item(proto_tree *tree, proto_item *fixed_item,
4389 proto_item *item_to_move)
4392 /* Revert part of: http://anonsvn.wireshark.org/viewvc?view=rev&revision=32443
4393 * See https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=5500
4395 /* This function doesn't generate any values. It only reorganizes the prococol tree
4396 * so we can bail out immediately if it isn't visible. */
4397 if (!tree || !PTREE_DATA(tree)->visible)
4400 DISSECTOR_ASSERT(item_to_move->parent == tree);
4401 DISSECTOR_ASSERT(fixed_item->parent == tree);
4403 /*** cut item_to_move out ***/
4405 /* is item_to_move the first? */
4406 if (tree->first_child == item_to_move) {
4407 /* simply change first child to next */
4408 tree->first_child = item_to_move->next;
4410 DISSECTOR_ASSERT(tree->last_child != item_to_move);
4412 proto_item *curr_item;
4413 /* find previous and change it's next */
4414 for(curr_item = tree->first_child; curr_item != NULL; curr_item = curr_item->next) {
4415 if (curr_item->next == item_to_move) {
4420 DISSECTOR_ASSERT(curr_item);
4422 curr_item->next = item_to_move->next;
4424 /* fix last_child if required */
4425 if (tree->last_child == item_to_move) {
4426 tree->last_child = curr_item;
4430 /*** insert to_move after fixed ***/
4431 item_to_move->next = fixed_item->next;
4432 fixed_item->next = item_to_move;
4433 if (tree->last_child == fixed_item) {
4434 tree->last_child = item_to_move;
4439 proto_tree_set_appendix(proto_tree *tree, tvbuff_t *tvb, gint start,
4447 fi = PTREE_FINFO(tree);
4451 start += tvb_raw_offset(tvb);
4452 DISSECTOR_ASSERT(start >= 0);
4453 DISSECTOR_ASSERT(length >= 0);
4455 fi->appendix_start = start;
4456 fi->appendix_length = length;
4460 proto_register_protocol(const char *name, const char *short_name,
4461 const char *filter_name)
4463 protocol_t *protocol, *existing_protocol = NULL;
4464 header_field_info *hfinfo;
4466 char *existing_name;
4470 gboolean found_invalid;
4473 * Make sure there's not already a protocol with any of those
4474 * names. Crash if there is, as that's an error in the code
4475 * or an inappropriate plugin.
4476 * This situation has to be fixed to not register more than one
4477 * protocol with the same name.
4479 * This is done by reducing the number of strcmp (and alike) calls
4480 * as much as possible, as this significally slows down startup time.
4482 * Drawback: As a hash value is used to reduce insert time,
4483 * this might lead to a hash collision.
4484 * However, although we have somewhat over 1000 protocols, we're using
4485 * a 32 bit int so this is very, very unlikely.
4488 key = (gint *)g_malloc (sizeof(gint));
4489 *key = wrs_str_hash(name);
4491 existing_name = (char *)g_hash_table_lookup(proto_names, key);
4492 if (existing_name != NULL) {
4493 /* g_error will terminate the program */
4494 g_error("Duplicate protocol name \"%s\"!"
4495 " This might be caused by an inappropriate plugin or a development error.", name);
4497 g_hash_table_insert(proto_names, key, (gpointer)name);
4499 existing_name = (char *)g_hash_table_lookup(proto_short_names, (gpointer)short_name);
4500 if (existing_name != NULL) {
4501 g_error("Duplicate protocol short_name \"%s\"!"
4502 " This might be caused by an inappropriate plugin or a development error.", short_name);
4504 g_hash_table_insert(proto_short_names, (gpointer)short_name, (gpointer)short_name);
4506 found_invalid = FALSE;
4507 for (i = 0; filter_name[i]; i++) {
4509 if (!(islower(c) || isdigit(c) || c == '-' || c == '_' || c == '.')) {
4510 found_invalid = TRUE;
4513 if (found_invalid) {
4514 g_error("Protocol filter name \"%s\" has one or more invalid characters."
4515 " Allowed are lower characters, digits, '-', '_' and '.'."
4516 " This might be caused by an inappropriate plugin or a development error.", filter_name);
4518 existing_protocol = (protocol_t *)g_hash_table_lookup(proto_filter_names, (gpointer)filter_name);
4519 if (existing_protocol != NULL) {
4520 g_error("Duplicate protocol filter_name \"%s\"!"
4521 " This might be caused by an inappropriate plugin or a development error.", filter_name);
4524 /* Add this protocol to the list of known protocols; the list
4525 is sorted by protocol short name. */
4526 protocol = g_new(protocol_t, 1);
4527 protocol->name = name;
4528 protocol->short_name = short_name;
4529 protocol->filter_name = filter_name;
4530 protocol->fields = NULL;
4531 protocol->is_enabled = TRUE; /* protocol is enabled by default */
4532 protocol->can_toggle = TRUE;
4533 protocol->is_private = FALSE;
4534 /* list will be sorted later by name, when all protocols completed registering */
4535 protocols = g_list_prepend(protocols, protocol);
4536 g_hash_table_insert(proto_filter_names, (gpointer)filter_name, protocol);
4538 /* Here we allocate a new header_field_info struct */
4539 hfinfo = g_slice_new(header_field_info);
4540 hfinfo->name = name;
4541 hfinfo->abbrev = filter_name;
4542 hfinfo->type = FT_PROTOCOL;
4543 hfinfo->display = BASE_NONE;
4544 hfinfo->strings = protocol;
4545 hfinfo->bitmask = 0;
4546 hfinfo->ref_type = HF_REF_TYPE_NONE;
4547 hfinfo->blurb = NULL;
4548 hfinfo->parent = -1; /* this field differentiates protos and fields */
4550 proto_id = proto_register_field_init(hfinfo, hfinfo->parent);
4551 protocol->proto_id = proto_id;
4556 proto_mark_private(const int proto_id)
4558 protocol_t *protocol = find_protocol_by_id(proto_id);
4560 protocol->is_private = TRUE;
4564 proto_is_private(const int proto_id)
4566 protocol_t *protocol = find_protocol_by_id(proto_id);
4568 return protocol->is_private;
4574 * Routines to use to iterate over the protocols.
4575 * The argument passed to the iterator routines is an opaque cookie to
4576 * their callers; it's the GList pointer for the current element in
4578 * The ID of the protocol is returned, or -1 if there is no protocol.
4581 proto_get_first_protocol(void **cookie)
4583 protocol_t *protocol;
4585 if (protocols == NULL)
4587 *cookie = protocols;
4588 protocol = (protocol_t *)protocols->data;
4589 return protocol->proto_id;
4593 proto_get_data_protocol(void *cookie)
4595 GList *list_item = (GList *)cookie;
4597 protocol_t *protocol = (protocol_t *)list_item->data;
4598 return protocol->proto_id;
4602 proto_get_next_protocol(void **cookie)
4604 GList *list_item = (GList *)*cookie;
4605 protocol_t *protocol;
4607 list_item = g_list_next(list_item);
4608 if (list_item == NULL)
4610 *cookie = list_item;
4611 protocol = (protocol_t *)list_item->data;
4612 return protocol->proto_id;
4616 proto_get_first_protocol_field(const int proto_id, void **cookie)
4618 protocol_t *protocol = find_protocol_by_id(proto_id);
4620 if ((protocol == NULL) || (protocol->fields == NULL))
4623 *cookie = protocol->fields;
4624 return (header_field_info *)protocol->fields->data;
4628 proto_get_next_protocol_field(void **cookie)
4630 GSList *list_item = (GSList *)*cookie;
4632 list_item = g_slist_next(list_item);
4633 if (list_item == NULL)
4636 *cookie = list_item;
4637 return (header_field_info *)list_item->data;
4641 find_protocol_by_id(const int proto_id)
4643 header_field_info *hfinfo;
4648 PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
4649 DISSECTOR_ASSERT(hfinfo->type == FT_PROTOCOL);
4650 return (protocol_t *)hfinfo->strings;
4654 proto_get_id(const protocol_t *protocol)
4656 return protocol->proto_id;
4659 int proto_get_id_by_filter_name(const gchar* filter_name)
4661 protocol_t *protocol = NULL;
4664 fprintf(stderr, "No filter name present");
4665 DISSECTOR_ASSERT(filter_name);
4668 protocol = (protocol_t *)g_hash_table_lookup(proto_filter_names, (gpointer)filter_name);
4670 if (protocol == NULL)
4672 return protocol->proto_id;
4676 proto_get_protocol_name(const int proto_id)
4678 protocol_t *protocol;
4680 protocol = find_protocol_by_id(proto_id);
4682 if (protocol == NULL)
4684 return protocol->name;
4688 proto_get_protocol_short_name(const protocol_t *protocol)
4690 if (protocol == NULL)
4692 return protocol->short_name;
4696 proto_get_protocol_long_name(const protocol_t *protocol)
4698 if (protocol == NULL)
4700 return protocol->name;
4704 proto_get_protocol_filter_name(const int proto_id)
4706 protocol_t *protocol;
4708 protocol = find_protocol_by_id(proto_id);
4709 if (protocol == NULL)
4711 return protocol->filter_name;
4715 proto_get_frame_protocols(const wmem_list_t *layers, gboolean *is_ip, gboolean *is_tcp, gboolean *is_udp, gboolean *is_sctp) {
4716 wmem_list_frame_t* protos = wmem_list_head(layers);
4718 const char* proto_name;
4720 /* Walk the list of a available protocols in the packet and
4721 find "major" ones. */
4722 /* It might make more sense to assemble and return a bitfield. */
4723 while (protos != NULL)
4725 proto_id = GPOINTER_TO_INT(wmem_list_frame_data(protos));
4726 proto_name = proto_get_protocol_filter_name(proto_id);
4728 if (is_ip && ((!strcmp(proto_name, "ip")) ||
4729 (!strcmp(proto_name, "ipv6")))) {
4731 } else if (is_tcp && !strcmp(proto_name, "tcp")) {
4733 } else if (is_udp && !strcmp(proto_name, "udp")) {
4735 } else if (is_sctp && !strcmp(proto_name, "sctp")) {
4739 protos = wmem_list_frame_next(protos);
4744 proto_is_protocol_enabled(const protocol_t *protocol)
4746 return protocol->is_enabled;
4750 proto_can_toggle_protocol(const int proto_id)
4752 protocol_t *protocol;
4754 protocol = find_protocol_by_id(proto_id);
4755 return protocol->can_toggle;
4759 proto_set_decoding(const int proto_id, const gboolean enabled)
4761 protocol_t *protocol;
4763 protocol = find_protocol_by_id(proto_id);
4764 DISSECTOR_ASSERT(protocol->can_toggle);
4765 protocol->is_enabled = enabled;
4769 proto_enable_all(void)
4771 protocol_t *protocol;
4772 GList *list_item = protocols;
4774 if (protocols == NULL)
4778 protocol = (protocol_t *)list_item->data;
4779 if (protocol->can_toggle)
4780 protocol->is_enabled = TRUE;
4781 list_item = g_list_next(list_item);
4786 proto_set_cant_toggle(const int proto_id)
4788 protocol_t *protocol;
4790 protocol = find_protocol_by_id(proto_id);
4791 protocol->can_toggle = FALSE;
4795 proto_register_field_common(protocol_t *proto, header_field_info *hfi, const int parent)
4797 if (proto != NULL) {
4798 if (proto->fields == NULL) {
4799 proto->fields = g_slist_append(NULL, hfi);
4800 proto->last_field = proto->fields;
4803 g_slist_append(proto->last_field, hfi)->next;
4807 return proto_register_field_init(hfi, parent);
4810 /* for use with static arrays only, since we don't allocate our own copies
4811 of the header_field_info struct contained within the hf_register_info struct */
4813 proto_register_field_array(const int parent, hf_register_info *hf, const int num_records)
4815 hf_register_info *ptr = hf;
4819 proto = find_protocol_by_id(parent);
4820 for (i = 0; i < num_records; i++, ptr++) {
4822 * Make sure we haven't registered this yet.
4823 * Most fields have variables associated with them
4824 * that are initialized to -1; some have array elements,
4825 * or possibly uninitialized variables, so we also allow
4826 * 0 (which is unlikely to be the field ID we get back
4827 * from "proto_register_field_init()").
4829 if (*ptr->p_id != -1 && *ptr->p_id != 0) {
4831 "Duplicate field detected in call to proto_register_field_array: %s is already registered\n",
4832 ptr->hfinfo.abbrev);
4836 *ptr->p_id = proto_register_field_common(proto, &ptr->hfinfo, parent);
4841 proto_register_fields_section(const int parent, header_field_info *hfi, const int num_records)
4846 proto = find_protocol_by_id(parent);
4847 for (i = 0; i < num_records; i++) {
4849 * Make sure we haven't registered this yet.
4851 if (hfi[i].id != -1) {
4853 "Duplicate field detected in call to proto_register_fields: %s is already registered\n",
4858 proto_register_field_common(proto, &hfi[i], parent);
4863 proto_register_fields_manual(const int parent, header_field_info **hfi, const int num_records)
4868 proto = find_protocol_by_id(parent);
4869 for (i = 0; i < num_records; i++) {
4871 * Make sure we haven't registered this yet.
4873 if (hfi[i]->id != -1) {
4875 "Duplicate field detected in call to proto_register_fields: %s is already registered\n",
4880 proto_register_field_common(proto, hfi[i], parent);
4884 /* unregister already registered fields */
4886 proto_unregister_field (const int parent, gint hf_id)
4888 hf_register_info *hf;
4892 if (hf_id == -1 || hf_id == 0)
4895 proto = find_protocol_by_id (parent);
4896 if (!proto || !proto->fields) {
4900 for (field = proto->fields; field; field = field->next) {
4901 hf = (hf_register_info *)field->data;
4902 if (*hf->p_id == hf_id) {
4903 /* Found the hf_id in this protocol */
4904 g_tree_steal (gpa_name_tree, hf->hfinfo.abbrev);
4905 /* XXX, memleak? g_slist_delete_link() */
4906 proto->fields = g_slist_remove_link (proto->fields, field);
4907 proto->last_field = g_slist_last (proto->fields);
4913 /* chars allowed in field abbrev */
4915 const guchar fld_abbrev_chars[256] = {
4916 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00-0x0F */
4917 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10-0x1F */
4918 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, /* 0x20-0x2F '-', '.' */
4919 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 0x30-0x3F '0'-'9' */
4920 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x40-0x4F 'A'-'O' */
4921 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 0x50-0x5F 'P'-'Z', '_' */
4922 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x60-0x6F 'a'-'o' */
4923 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 0x70-0x7F 'p'-'z' */
4924 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80-0x8F */
4925 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90-0x9F */
4926 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xA0-0xAF */
4927 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xB0-0xBF */
4928 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xC0-0xCF */
4929 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xD0-0xDF */
4930 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xE0-0xEF */
4931 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xF0-0xFF */
4934 static const value_string hf_types[] = {
4935 { FT_NONE, "FT_NONE" },
4936 { FT_PROTOCOL, "FT_PROTOCOL" },
4937 { FT_BOOLEAN, "FT_BOOLEAN" },
4938 { FT_UINT8, "FT_UINT8" },
4939 { FT_UINT16, "FT_UINT16" },
4940 { FT_UINT24, "FT_UINT24" },
4941 { FT_UINT32, "FT_UINT32" },
4942 { FT_UINT64, "FT_UINT64" },
4943 { FT_INT8, "FT_INT8" },
4944 { FT_INT16, "FT_INT16" },
4945 { FT_INT24, "FT_INT24" },
4946 { FT_INT32, "FT_INT32" },
4947 { FT_INT64, "FT_INT64" },
4948 { FT_EUI64, "FT_EUI64" },
4949 { FT_FLOAT, "FT_FLOAT" },
4950 { FT_DOUBLE, "FT_DOUBLE" },
4951 { FT_ABSOLUTE_TIME, "FT_ABSOLUTE_TIME" },
4952 { FT_RELATIVE_TIME, "FT_RELATIVE_TIME" },
4953 { FT_STRING, "FT_STRING" },
4954 { FT_STRINGZ, "FT_STRINGZ" },
4955 { FT_UINT_STRING, "FT_UINT_STRING" },
4956 { FT_ETHER, "FT_ETHER" },
4957 { FT_BYTES, "FT_BYTES" },
4958 { FT_UINT_BYTES, "FT_UINT_BYTES" },
4959 { FT_IPv4, "FT_IPv4" },
4960 { FT_IPv6, "FT_IPv6" },
4961 { FT_IPXNET, "FT_IPXNET" },
4962 { FT_FRAMENUM, "FT_FRAMENUM" },
4963 { FT_PCRE, "FT_PCR" },
4964 { FT_GUID, "FT_GUID" },
4965 { FT_OID, "FT_OID" },
4966 { FT_REL_OID, "FT_REL_OID" },
4969 static const value_string hf_display[] = {
4970 { BASE_NONE, "BASE_NONE" },
4971 { BASE_DEC, "BASE_DEC" },
4972 { BASE_HEX, "BASE_HEX" },
4973 { BASE_OCT, "BASE_OCT" },
4974 { BASE_DEC_HEX, "BASE_DEC_HEX" },
4975 { BASE_HEX_DEC, "BASE_HEX_DEC" },
4976 { BASE_CUSTOM, "BASE_CUSTOM" },
4977 { BASE_NONE|BASE_RANGE_STRING, "BASE_NONE|BASE_RANGE_STRING" },
4978 { BASE_DEC|BASE_RANGE_STRING, "BASE_DEC|BASE_RANGE_STRING" },
4979 { BASE_HEX|BASE_RANGE_STRING, "BASE_HEX|BASE_RANGE_STRING" },
4980 { BASE_OCT|BASE_RANGE_STRING, "BASE_OCT|BASE_RANGE_STRING" },
4981 { BASE_DEC_HEX|BASE_RANGE_STRING, "BASE_DEC_HEX|BASE_RANGE_STRING" },
4982 { BASE_HEX_DEC|BASE_RANGE_STRING, "BASE_HEX_DEC|BASE_RANGE_STRING" },
4983 { BASE_CUSTOM|BASE_RANGE_STRING, "BASE_CUSTOM|BASE_RANGE_STRING" },
4984 { BASE_NONE|BASE_VAL64_STRING, "BASE_NONE|BASE_VAL64_STRING" },
4985 { BASE_DEC|BASE_VAL64_STRING, "BASE_DEC|BASE_VAL64_STRING" },
4986 { BASE_HEX|BASE_VAL64_STRING, "BASE_HEX|BASE_VAL64_STRING" },
4987 { BASE_OCT|BASE_VAL64_STRING, "BASE_OCT|BASE_VAL64_STRING" },
4988 { BASE_DEC_HEX|BASE_VAL64_STRING, "BASE_DEC_HEX|BASE_VAL64_STRING" },
4989 { BASE_HEX_DEC|BASE_VAL64_STRING, "BASE_HEX_DEC|BASE_VAL64_STRING" },
4990 { BASE_CUSTOM|BASE_VAL64_STRING, "BASE_CUSTOM|BASE_VAL64_STRING" },
4991 /* { STR_ASCII, "STR_ASCII" }, */
4992 { STR_UNICODE, "STR_UNICODE" },
4993 { ABSOLUTE_TIME_LOCAL, "ABSOLUTE_TIME_LOCAL" },
4994 { ABSOLUTE_TIME_UTC, "ABSOLUTE_TIME_UTC" },
4995 { ABSOLUTE_TIME_DOY_UTC, "ABSOLUTE_TIME_DOY_UTC" },
4998 /* temporary function containing assert part for easier profiling */
5000 tmp_fld_check_assert(header_field_info *hfinfo)
5003 /* The field must have a name (with length > 0) */
5004 if (!hfinfo->name || !hfinfo->name[0]) {
5006 /* Try to identify the field */
5007 g_error("Field (abbrev='%s') does not have a name\n",
5011 g_error("Field does not have a name (nor an abbreviation)\n");
5014 /* fields with an empty string for an abbreviation aren't filterable */
5015 if (!hfinfo->abbrev || !hfinfo->abbrev[0])
5016 g_error("Field '%s' does not have an abbreviation\n", hfinfo->name);
5018 /* These types of fields are allowed to have value_strings,
5019 * true_false_strings or a protocol_t struct
5021 if (hfinfo->strings != NULL && !(
5022 (hfinfo->type == FT_UINT8) ||
5023 (hfinfo->type == FT_UINT16) ||
5024 (hfinfo->type == FT_UINT24) ||
5025 (hfinfo->type == FT_UINT32) ||
5026 (hfinfo->type == FT_UINT64) ||
5027 (hfinfo->type == FT_INT8) ||
5028 (hfinfo->type == FT_INT16) ||
5029 (hfinfo->type == FT_INT24) ||
5030 (hfinfo->type == FT_INT32) ||
5031 (hfinfo->type == FT_INT64) ||
5032 (hfinfo->type == FT_BOOLEAN) ||
5033 (hfinfo->type == FT_PROTOCOL) ))
5034 g_error("Field '%s' (%s) has a 'strings' value but is of type %s"
5035 " (which is not allowed to have strings)\n",
5036 hfinfo->name, hfinfo->abbrev,
5037 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"));
5039 /* TODO: This check may slow down startup, and output quite a few warnings.
5040 It would be good to be able to enable this (and possibly other checks?)
5041 in non-release builds. */
5043 /* Check for duplicate value_string values.
5044 There are lots that have the same value *and* string, so for now only
5045 report those that have same value but different string. */
5046 if ((hfinfo->strings != NULL) &&
5047 !(hfinfo->display & BASE_RANGE_STRING) &&
5048 !((hfinfo->display & FIELD_DISPLAY_E_MASK) == BASE_CUSTOM) &&
5050 (hfinfo->type == FT_UINT8) ||
5051 (hfinfo->type == FT_UINT16) ||
5052 (hfinfo->type == FT_UINT24) ||
5053 (hfinfo->type == FT_UINT32) ||
5054 (hfinfo->type == FT_INT8) ||
5055 (hfinfo->type == FT_INT16) ||
5056 (hfinfo->type == FT_INT24) ||
5057 (hfinfo->type == FT_INT32) ||
5058 (hfinfo->type == FT_FRAMENUM) )) {
5061 const value_string *start_values;
5062 const value_string *current;
5064 if (hfinfo->display & BASE_EXT_STRING)
5065 start_values = VALUE_STRING_EXT_VS_P(((const value_string_ext*)hfinfo->strings));
5067 start_values = (const value_string*)hfinfo->strings;
5068 current = start_values;
5070 for (n=0; current; n++, current++) {
5071 /* Drop out if we reached the end. */
5072 if ((current->value == 0) && (current->strptr == NULL)) {
5076 /* Check value against all previous */
5077 for (m=0; m < n; m++) {
5078 /* There are lots of duplicates with the same string,
5079 so only report if different... */
5080 if ((start_values[m].value == current->value) &&
5081 (strcmp(start_values[m].strptr, current->strptr) != 0)) {
5082 g_warning("Field '%s' (%s) has a conflicting entry in its"
5083 " value_string: %u is at indices %u (%s) and %u (%s))\n",
5084 hfinfo->name, hfinfo->abbrev,
5085 current->value, m, start_values[m].strptr, n, current->strptr);
5093 switch (hfinfo->type) {
5100 /* Hexadecimal and octal are, in printf() and everywhere
5101 * else, unsigned so don't allow dissectors to register a
5102 * signed field to be displayed unsigned. (Else how would
5103 * we display negative values?)
5105 switch (hfinfo->display & FIELD_DISPLAY_E_MASK) {
5110 g_error("Field '%s' (%s) is signed (%s) but is being displayed unsigned (%s)\n",
5111 hfinfo->name, hfinfo->abbrev,
5112 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"),
5113 val_to_str(hfinfo->display, hf_display, "(Bit count: %d)"));
5121 /* Require integral types (other than frame number,
5122 * which is always displayed in decimal) to have a
5124 * If there is a strings value then this base is not
5125 * normally used except when constructing a display
5126 * filter for a value not found in the strings lookup.
5128 switch (hfinfo->display & FIELD_DISPLAY_E_MASK) {
5134 case BASE_CUSTOM: /* hfinfo_numeric_value_format() treats this as decimal */
5137 g_error("Field '%s' (%s) is an integral value (%s)"
5138 " but is being displayed as %s\n",
5139 hfinfo->name, hfinfo->abbrev,
5140 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"),
5141 val_to_str(hfinfo->display, hf_display, "(Unknown: 0x%x)"));
5147 if (hfinfo->display != BASE_NONE)
5148 g_error("Field '%s' (%s) is an %s but is being displayed as %s instead of BASE_NONE\n",
5149 hfinfo->name, hfinfo->abbrev,
5150 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"),
5151 val_to_str(hfinfo->display, hf_display, "(Bit count: %d)"));
5152 if (hfinfo->bitmask != 0)
5153 g_error("Field '%s' (%s) is an %s but has a bitmask\n",
5154 hfinfo->name, hfinfo->abbrev,
5155 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"));
5161 case FT_ABSOLUTE_TIME:
5162 if (!(hfinfo->display == ABSOLUTE_TIME_LOCAL ||
5163 hfinfo->display == ABSOLUTE_TIME_UTC ||
5164 hfinfo->display == ABSOLUTE_TIME_DOY_UTC))
5165 g_error("Field '%s' (%s) is a %s but is being displayed as %s instead of as a time\n",
5166 hfinfo->name, hfinfo->abbrev,
5167 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"),
5168 val_to_str(hfinfo->display, hf_display, "(Bit count: %d)"));
5169 if (hfinfo->bitmask != 0)
5170 g_error("Field '%s' (%s) is an %s but has a bitmask\n",
5171 hfinfo->name, hfinfo->abbrev,
5172 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"));
5177 case FT_UINT_STRING:
5178 switch (hfinfo->display) {
5184 g_error("Field '%s' (%s) is an string value (%s)"
5185 " but is being displayed as %s\n",
5186 hfinfo->name, hfinfo->abbrev,
5187 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"),
5188 val_to_str(hfinfo->display, hf_display, "(Unknown: 0x%x)"));
5191 if (hfinfo->bitmask != 0)
5192 g_error("Field '%s' (%s) is an %s but has a bitmask\n",
5193 hfinfo->name, hfinfo->abbrev,
5194 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"));
5195 if (hfinfo->strings != NULL)
5196 g_error("Field '%s' (%s) is an %s but has a strings value\n",
5197 hfinfo->name, hfinfo->abbrev,
5198 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"));
5202 if (hfinfo->display != BASE_NONE)
5203 g_error("Field '%s' (%s) is an %s but is being displayed as %s instead of BASE_NONE\n",
5204 hfinfo->name, hfinfo->abbrev,
5205 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"),
5206 val_to_str(hfinfo->display, hf_display, "(Bit count: %d)"));
5207 if (hfinfo->bitmask != 0)
5208 g_error("Field '%s' (%s) is an %s but has a bitmask\n",
5209 hfinfo->name, hfinfo->abbrev,
5210 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"));
5211 if (hfinfo->strings != NULL)
5212 g_error("Field '%s' (%s) is an %s but has a strings value\n",
5213 hfinfo->name, hfinfo->abbrev,
5214 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"));
5220 register_type_length_mismatch(void)
5222 static ei_register_info ei[] = {
5223 { &ei_type_length_mismatch_error, { "_ws.type_length.mismatch", PI_MALFORMED, PI_ERROR, "Trying to fetch X with length Y", EXPFILL }},
5224 { &ei_type_length_mismatch_warn, { "_ws.type_length.mismatch", PI_MALFORMED, PI_WARN, "Trying to fetch X with length Y", EXPFILL }},
5227 expert_module_t* expert_type_length_mismatch;
5229 proto_type_length_mismatch = proto_register_protocol("Type Length Mismatch", "Type length mismatch", "_ws.type_length");
5231 expert_type_length_mismatch = expert_register_protocol(proto_type_length_mismatch);
5232 expert_register_field_array(expert_type_length_mismatch, ei, array_length(ei));
5234 /* "Type Length Mismatch" isn't really a protocol, it's an error indication;
5235 disabling them makes no sense. */
5236 proto_set_cant_toggle(proto_type_length_mismatch);
5239 #define PROTO_PRE_ALLOC_HF_FIELDS_MEM (144000+PRE_ALLOC_EXPERT_FIELDS_MEM)
5241 proto_register_field_init(header_field_info *hfinfo, const int parent)
5244 tmp_fld_check_assert(hfinfo);
5246 hfinfo->parent = parent;
5247 hfinfo->same_name_next = NULL;
5248 hfinfo->same_name_prev_id = -1;
5250 /* if we always add and never delete, then id == len - 1 is correct */
5251 if (gpa_hfinfo.len >= gpa_hfinfo.allocated_len) {
5252 if (!gpa_hfinfo.hfi) {
5253 gpa_hfinfo.allocated_len = PROTO_PRE_ALLOC_HF_FIELDS_MEM;
5254 gpa_hfinfo.hfi = (header_field_info **)g_malloc(sizeof(header_field_info *)*PROTO_PRE_ALLOC_HF_FIELDS_MEM);
5256 gpa_hfinfo.allocated_len += 1000;
5257 gpa_hfinfo.hfi = (header_field_info **)g_realloc(gpa_hfinfo.hfi,
5258 sizeof(header_field_info *)*gpa_hfinfo.allocated_len);
5259 /*g_warning("gpa_hfinfo.allocated_len %u", gpa_hfinfo.allocated_len);*/
5262 gpa_hfinfo.hfi[gpa_hfinfo.len] = hfinfo;
5264 hfinfo->id = gpa_hfinfo.len - 1;
5266 /* if we have real names, enter this field in the name tree */
5267 if ((hfinfo->name[0] != 0) && (hfinfo->abbrev[0] != 0 )) {
5269 header_field_info *same_name_next_hfinfo;
5272 /* Check that the filter name (abbreviation) is legal;
5273 * it must contain only alphanumerics, '-', "_", and ".". */
5274 c = wrs_check_charset(fld_abbrev_chars, hfinfo->abbrev);
5276 fprintf(stderr, "Invalid character '%c' in filter name '%s'\n", c, hfinfo->abbrev);
5277 DISSECTOR_ASSERT(!c);
5280 /* We allow multiple hfinfo's to be registered under the same
5281 * abbreviation. This was done for X.25, as, depending
5282 * on whether it's modulo-8 or modulo-128 operation,
5283 * some bitfield fields may be in different bits of
5284 * a byte, and we want to be able to refer to that field
5285 * with one name regardless of whether the packets
5286 * are modulo-8 or modulo-128 packets. */
5288 same_name_hfinfo = NULL;
5290 g_tree_insert(gpa_name_tree, (gpointer) (hfinfo->abbrev), hfinfo);
5291 /* GLIB 2.x - if it is already present
5292 * the previous hfinfo with the same name is saved
5293 * to same_name_hfinfo by value destroy callback */
5294 if (same_name_hfinfo) {
5295 /* There's already a field with this name.
5296 * Put it after that field in the list of
5297 * fields with this name, then allow the code
5298 * after this if{} block to replace the old
5299 * hfinfo with the new hfinfo in the GTree. Thus,
5300 * we end up with a linked-list of same-named hfinfo's,
5301 * with the root of the list being the hfinfo in the GTree */
5302 same_name_next_hfinfo =
5303 same_name_hfinfo->same_name_next;
5305 hfinfo->same_name_next = same_name_next_hfinfo;
5306 if (same_name_next_hfinfo)
5307 same_name_next_hfinfo->same_name_prev_id = hfinfo->id;
5309 same_name_hfinfo->same_name_next = hfinfo;
5310 hfinfo->same_name_prev_id = same_name_hfinfo->id;
5318 proto_register_subtree_array(gint *const *indices, const int num_indices)
5321 gint *const *ptr = indices;
5324 * If we've already allocated the array of tree types, expand
5325 * it; this lets plugins such as mate add tree types after
5326 * the initial startup. (If we haven't already allocated it,
5327 * we don't allocate it; on the first pass, we just assign
5328 * ett values and keep track of how many we've assigned, and
5329 * when we're finished registering all dissectors we allocate
5330 * the array, so that we do only one allocation rather than
5331 * wasting CPU time and memory by growing the array for each
5332 * dissector that registers ett values.)
5334 if (tree_is_expanded != NULL) {
5335 tree_is_expanded = (guint32 *)g_realloc(tree_is_expanded, (1+((num_tree_types + num_indices)/32)) * sizeof(guint32));
5337 /* set new items to 0 */
5338 /* XXX, slow!!! optimize when needed (align 'i' to 32, and set rest of guint32 to 0) */
5339 for (i = num_tree_types; i < num_tree_types + num_indices; i++)
5340 tree_is_expanded[i >> 5] &= ~(1 << (i & 31));
5344 * Assign "num_indices" subtree numbers starting at "num_tree_types",
5345 * returning the indices through the pointers in the array whose
5346 * first element is pointed to by "indices", and update
5347 * "num_tree_types" appropriately.
5349 for (i = 0; i < num_indices; i++, ptr++, num_tree_types++) {
5351 /* g_error will terminate the program */
5352 g_error("register_subtree_array: subtree item type (ett_...) not -1 !"
5353 " This is a development error:"
5354 " Either the subtree item type has already been assigned or"
5355 " was not initialized to -1.");
5357 **ptr = num_tree_types;
5362 label_concat(char *label_str, gsize pos, const char *str)
5364 if (pos < ITEM_LABEL_LENGTH)
5365 pos += g_strlcpy(label_str + pos, str, ITEM_LABEL_LENGTH - pos);
5371 label_mark_truncated(char *label_str, gsize name_pos)
5373 static const char trunc_str[] = " [truncated]";
5374 const size_t trunc_len = sizeof(trunc_str)-1;
5376 /* ..... field_name: dataaaaaaaaaaaaa
5380 * ..... field_name [truncated]: dataaaaaaaaaaaaa */
5382 if (name_pos < ITEM_LABEL_LENGTH - trunc_len) {
5383 memmove(label_str + name_pos + trunc_len, label_str + name_pos, ITEM_LABEL_LENGTH - name_pos - trunc_len);
5384 memcpy(label_str + name_pos, trunc_str, trunc_len);
5385 label_str[ITEM_LABEL_LENGTH-1] = '\0';
5387 } else if (name_pos < ITEM_LABEL_LENGTH)
5388 g_strlcpy(label_str + name_pos, trunc_str, ITEM_LABEL_LENGTH - name_pos);
5392 label_fill(char *label_str, gsize pos, const header_field_info *hfinfo, const char *text)
5396 /* "%s: %s", hfinfo->name, text */
5397 name_pos = pos = label_concat(label_str, pos, hfinfo->name);
5398 pos = label_concat(label_str, pos, ": ");
5399 pos = label_concat(label_str, pos, text ? text : "(null)");
5401 if (pos >= ITEM_LABEL_LENGTH) {
5402 /* Uh oh, we don't have enough room. Tell the user that the field is truncated. */
5403 label_mark_truncated(label_str, name_pos);
5410 label_fill_descr(char *label_str, gsize pos, const header_field_info *hfinfo, const char *text, const char *descr)
5414 /* "%s: %s (%s)", hfinfo->name, text, descr */
5415 name_pos = pos = label_concat(label_str, pos, hfinfo->name);
5416 pos = label_concat(label_str, pos, ": ");
5417 pos = label_concat(label_str, pos, text ? text : "(null)");
5418 pos = label_concat(label_str, pos, " (");
5419 pos = label_concat(label_str, pos, descr ? descr : "(null)");
5420 pos = label_concat(label_str, pos, ")");
5422 if (pos >= ITEM_LABEL_LENGTH) {
5423 /* Uh oh, we don't have enough room. Tell the user that the field is truncated. */
5424 label_mark_truncated(label_str, name_pos);
5431 proto_item_fill_label(field_info *fi, gchar *label_str)
5433 header_field_info *hfinfo;
5439 guint32 n_addr; /* network-order IPv4 address */
5446 /* XXX: Check validity of hfinfo->type */
5450 hfinfo = fi->hfinfo;
5452 switch (hfinfo->type) {
5455 g_strlcpy(label_str, hfinfo->name, ITEM_LABEL_LENGTH);
5459 fill_label_boolean(fi, label_str);
5464 bytes = (guint8 *)fvalue_get(&fi->value);
5465 label_fill(label_str, 0, hfinfo,
5466 (bytes) ? bytes_to_str(bytes, fvalue_length(&fi->value)) : "<MISSING>");
5469 /* Four types of integers to take care of:
5470 * Bitfield, with val_string
5471 * Bitfield, w/o val_string
5472 * Non-bitfield, with val_string
5473 * Non-bitfield, w/o val_string
5479 if (hfinfo->bitmask) {
5480 fill_label_bitfield(fi, label_str, FALSE);
5482 fill_label_number(fi, label_str, FALSE);
5487 fill_label_number(fi, label_str, FALSE);
5491 fill_label_number64(fi, label_str, FALSE);
5498 if (hfinfo->bitmask) {
5499 fill_label_bitfield(fi, label_str, TRUE);
5501 fill_label_number(fi, label_str, TRUE);
5506 fill_label_number64(fi, label_str, TRUE);
5510 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5511 "%s: %." G_STRINGIFY(FLT_DIG) "g",
5512 hfinfo->name, fvalue_get_floating(&fi->value));
5516 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5517 "%s: %." G_STRINGIFY(DBL_DIG) "g",
5518 hfinfo->name, fvalue_get_floating(&fi->value));
5521 case FT_ABSOLUTE_TIME:
5522 label_fill(label_str, 0, hfinfo,
5523 abs_time_to_str((const nstime_t *)fvalue_get(&fi->value),
5524 (absolute_time_display_e)hfinfo->display, TRUE));
5527 case FT_RELATIVE_TIME:
5528 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5529 "%s: %s seconds", hfinfo->name,
5530 rel_time_to_secs_str((const nstime_t *)fvalue_get(&fi->value)));
5534 integer = fvalue_get_uinteger(&fi->value);
5535 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5536 "%s: %s (0x%08X)", hfinfo->name,
5537 get_ipxnet_name(integer), integer);
5541 bytes = (guint8 *)fvalue_get(&fi->value);
5542 label_fill_descr(label_str, 0, hfinfo,
5543 get_ax25_name(bytes),
5544 ax25_to_str(bytes));
5548 addr.type = AT_VINES;
5549 addr.len = VINES_ADDR_LEN;
5550 addr.data = (guint8 *)fvalue_get(&fi->value);
5552 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5553 "%s: %s", hfinfo->name,
5554 ep_address_to_str( &addr ));
5558 bytes = (guint8 *)fvalue_get(&fi->value);
5559 label_fill_descr(label_str, 0, hfinfo,
5560 get_ether_name(bytes),
5561 ether_to_str(bytes));
5565 ipv4 = (ipv4_addr *)fvalue_get(&fi->value);
5566 n_addr = ipv4_get_net_order_addr(ipv4);
5567 label_fill_descr(label_str, 0, hfinfo,
5568 get_hostname(n_addr),
5569 ip_to_str((guint8*)&n_addr));
5573 bytes = (guint8 *)fvalue_get(&fi->value);
5574 label_fill_descr(label_str, 0, hfinfo,
5575 get_hostname6((struct e_in6_addr *)bytes),
5576 ip6_to_str((struct e_in6_addr*)bytes));
5580 guid = (e_guid_t *)fvalue_get(&fi->value);
5581 label_fill(label_str, 0, hfinfo, guid_to_str(guid));
5585 bytes = (guint8 *)fvalue_get(&fi->value);
5586 name = oid_resolved_from_encoded(bytes, fvalue_length(&fi->value));
5588 label_fill_descr(label_str, 0, hfinfo,
5589 oid_encoded2string(bytes, fvalue_length(&fi->value)), name);
5591 label_fill(label_str, 0, hfinfo,
5592 oid_encoded2string(bytes, fvalue_length(&fi->value)));
5597 bytes = (guint8 *)fvalue_get(&fi->value);
5598 name = rel_oid_resolved_from_encoded(bytes, fvalue_length(&fi->value));
5600 label_fill_descr(label_str, 0, hfinfo,
5601 rel_oid_encoded2string(bytes, fvalue_length(&fi->value)), name);
5603 label_fill(label_str, 0, hfinfo,
5604 rel_oid_encoded2string(bytes, fvalue_length(&fi->value)));
5609 integer64 = fvalue_get_integer64(&fi->value);
5610 label_fill_descr(label_str, 0, hfinfo,
5611 get_eui64_name(integer64),
5612 eui64_to_str(integer64));
5616 case FT_UINT_STRING:
5617 bytes = (guint8 *)fvalue_get(&fi->value);
5618 label_fill(label_str, 0, hfinfo, hfinfo_format_text(hfinfo, bytes));
5622 g_error("hfinfo->type %d (%s) not handled\n",
5623 hfinfo->type, ftype_name(hfinfo->type));
5624 DISSECTOR_ASSERT_NOT_REACHED();
5630 fill_label_boolean(field_info *fi, gchar *label_str)
5632 char *p = label_str;
5633 int bitfield_byte_length = 0, bitwidth;
5634 guint32 unshifted_value;
5637 header_field_info *hfinfo = fi->hfinfo;
5638 const true_false_string *tfstring = (const true_false_string *)&tfs_true_false;
5640 if (hfinfo->strings) {
5641 tfstring = (const struct true_false_string*) hfinfo->strings;
5644 value = fvalue_get_uinteger(&fi->value);
5645 if (hfinfo->bitmask) {
5646 /* Figure out the bit width */
5647 bitwidth = hfinfo_bitwidth(hfinfo);
5650 unshifted_value = value;
5651 unshifted_value <<= hfinfo_bitshift(hfinfo);
5653 /* Create the bitfield first */
5654 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
5655 bitfield_byte_length = (int) (p - label_str);
5658 /* Fill in the textual info */
5659 label_fill(label_str, bitfield_byte_length, hfinfo, value ? tfstring->true_string : tfstring->false_string);
5663 hf_try_val_to_str(guint32 value, const header_field_info *hfinfo)
5665 if (hfinfo->display & BASE_RANGE_STRING)
5666 return try_rval_to_str(value, (const range_string *) hfinfo->strings);
5668 if (hfinfo->display & BASE_EXT_STRING)
5669 return try_val_to_str_ext(value, (const value_string_ext *) hfinfo->strings);
5671 if (hfinfo->display & BASE_VAL64_STRING)
5672 return try_val64_to_str(value, (const val64_string *) hfinfo->strings);
5674 return try_val_to_str(value, (const value_string *) hfinfo->strings);
5678 hf_try_val64_to_str(guint64 value, const header_field_info *hfinfo)
5680 if (hfinfo->display & BASE_VAL64_STRING)
5681 return try_val64_to_str(value, (const val64_string *) hfinfo->strings);
5683 /* If this is reached somebody registered a 64-bit field with a 32-bit
5684 * value-string, which isn't right. */
5685 DISSECTOR_ASSERT_NOT_REACHED();
5687 /* This is necessary to squelch MSVC errors; is there
5688 any way to tell it that DISSECTOR_ASSERT_NOT_REACHED()
5694 hf_try_val_to_str_const(guint32 value, const header_field_info *hfinfo, const char *unknown_str)
5696 const char *str = hf_try_val_to_str(value, hfinfo);
5698 return (str) ? str : unknown_str;
5702 hf_try_val64_to_str_const(guint64 value, const header_field_info *hfinfo, const char *unknown_str)
5704 const char *str = hf_try_val64_to_str(value, hfinfo);
5706 return (str) ? str : unknown_str;
5709 /* Fills data for bitfield ints with val_strings */
5711 fill_label_bitfield(field_info *fi, gchar *label_str, gboolean is_signed)
5714 int bitfield_byte_length, bitwidth;
5715 guint32 unshifted_value;
5721 header_field_info *hfinfo = fi->hfinfo;
5723 /* Figure out the bit width */
5724 bitwidth = hfinfo_bitwidth(hfinfo);
5728 unshifted_value = fvalue_get_sinteger(&fi->value);
5730 unshifted_value = fvalue_get_uinteger(&fi->value);
5732 value = unshifted_value;
5733 if (hfinfo->bitmask) {
5734 unshifted_value <<= hfinfo_bitshift(hfinfo);
5737 /* Create the bitfield first */
5738 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
5739 bitfield_byte_length = (int) (p - label_str);
5741 /* Fill in the textual info using stored (shifted) value */
5742 if (hfinfo->display == BASE_CUSTOM) {
5743 gchar tmp[ITEM_LABEL_LENGTH];
5744 const custom_fmt_func_t fmtfunc = (const custom_fmt_func_t)hfinfo->strings;
5746 DISSECTOR_ASSERT(fmtfunc);
5747 fmtfunc(tmp, value);
5748 label_fill(label_str, bitfield_byte_length, hfinfo, tmp);
5750 else if (hfinfo->strings) {
5751 const char *val_str = hf_try_val_to_str_const(value, hfinfo, "Unknown");
5753 out = hfinfo_number_vals_format(hfinfo, buf, value);
5754 if (out == NULL) /* BASE_NONE so don't put integer in descr */
5755 label_fill(label_str, bitfield_byte_length, hfinfo, val_str);
5757 label_fill_descr(label_str, bitfield_byte_length, hfinfo, val_str, out);
5760 out = hfinfo_number_value_format(hfinfo, buf, value);
5762 label_fill(label_str, bitfield_byte_length, hfinfo, out);
5767 fill_label_number(field_info *fi, gchar *label_str, gboolean is_signed)
5769 header_field_info *hfinfo = fi->hfinfo;
5776 value = fvalue_get_sinteger(&fi->value);
5778 value = fvalue_get_uinteger(&fi->value);
5780 /* Fill in the textual info */
5781 if (hfinfo->display == BASE_CUSTOM) {
5782 gchar tmp[ITEM_LABEL_LENGTH];
5783 const custom_fmt_func_t fmtfunc = (const custom_fmt_func_t)hfinfo->strings;
5785 DISSECTOR_ASSERT(fmtfunc);
5786 fmtfunc(tmp, value);
5787 label_fill(label_str, 0, hfinfo, tmp);
5789 else if (hfinfo->strings) {
5790 const char *val_str = hf_try_val_to_str_const(value, hfinfo, "Unknown");
5792 out = hfinfo_number_vals_format(hfinfo, buf, value);
5793 if (out == NULL) /* BASE_NONE so don't put integer in descr */
5794 label_fill(label_str, 0, hfinfo, val_str);
5796 label_fill_descr(label_str, 0, hfinfo, val_str, out);
5799 out = hfinfo_number_value_format(hfinfo, buf, value);
5801 label_fill(label_str, 0, hfinfo, out);
5806 fill_label_number64(field_info *fi, gchar *label_str, gboolean is_signed)
5808 const char *format = NULL;
5809 header_field_info *hfinfo = fi->hfinfo;
5811 char tmp[ITEM_LABEL_LENGTH+1];
5813 /* Pick the proper format string */
5815 format = hfinfo_int64_format(hfinfo);
5817 format = hfinfo_uint64_format(hfinfo);
5819 value = fvalue_get_integer64(&fi->value);
5821 /* Format the temporary string */
5822 if (IS_BASE_DUAL(hfinfo->display))
5823 g_snprintf(tmp, ITEM_LABEL_LENGTH, format, value, value);
5825 g_snprintf(tmp, ITEM_LABEL_LENGTH, format, value);
5827 if (hfinfo->strings) {
5828 const char *val_str = hf_try_val64_to_str_const(value, hfinfo, "Unknown");
5830 if ((hfinfo->display & FIELD_DISPLAY_E_MASK) == BASE_NONE) {
5831 label_fill(label_str, 0, hfinfo, val_str);
5834 label_fill_descr(label_str, 0, hfinfo, val_str, tmp);
5838 label_fill(label_str, 0, hfinfo, tmp);
5843 hfinfo_bitshift(const header_field_info *hfinfo)
5845 return ws_ctz(hfinfo->bitmask);
5849 hfinfo_bitwidth(const header_field_info *hfinfo)
5853 if (!hfinfo->bitmask) {
5857 switch (hfinfo->type) {
5875 bitwidth = hfinfo->display; /* hacky? :) */
5878 DISSECTOR_ASSERT_NOT_REACHED();
5885 _hfinfo_type_hex_octet(int type)
5905 DISSECTOR_ASSERT_NOT_REACHED();
5912 hfinfo_number_value_format_display(const header_field_info *hfinfo, int display, char buf[32], guint32 value)
5914 char *ptr = &buf[31];
5915 gboolean isint = IS_FT_INT(hfinfo->type);
5918 /* Properly format value */
5921 return isint ? int_to_str_back(ptr, (gint32) value) : uint_to_str_back(ptr, value);
5925 ptr = hex_to_str_back(ptr, _hfinfo_type_hex_octet(hfinfo->type), value);
5928 ptr = isint ? int_to_str_back(ptr, (gint32) value) : uint_to_str_back(ptr, value);
5932 return oct_to_str_back(ptr, value);
5935 return hex_to_str_back(ptr, _hfinfo_type_hex_octet(hfinfo->type), value);
5939 ptr = isint ? int_to_str_back(ptr, (gint32) value) : uint_to_str_back(ptr, value);
5942 ptr = hex_to_str_back(ptr, _hfinfo_type_hex_octet(hfinfo->type), value);
5946 DISSECTOR_ASSERT_NOT_REACHED();
5953 hfinfo_number_value_format(const header_field_info *hfinfo, char buf[32], guint32 value)
5955 int display = hfinfo->display;
5957 if (hfinfo->type == FT_FRAMENUM) {
5959 * Frame numbers are always displayed in decimal.
5964 return hfinfo_number_value_format_display(hfinfo, display, buf, value);
5968 hfinfo_numeric_value_format(const header_field_info *hfinfo, char buf[32], guint32 value)
5970 /* Get the underlying BASE_ value */
5971 int display = hfinfo->display & FIELD_DISPLAY_E_MASK;
5973 if (hfinfo->type == FT_FRAMENUM) {
5975 * Frame numbers are always displayed in decimal.
5982 /* case BASE_DEC: */
5984 case BASE_OCT: /* XXX, why we're changing BASE_OCT to BASE_DEC? */
5989 /* case BASE_HEX: */
5995 return hfinfo_number_value_format_display(hfinfo, display, buf, value);
5999 hfinfo_number_vals_format(const header_field_info *hfinfo, char buf[32], guint32 value)
6001 /* Get the underlying BASE_ value */
6002 int display = hfinfo->display & FIELD_DISPLAY_E_MASK;
6004 if (display == BASE_NONE)
6007 if (display == BASE_DEC_HEX)
6009 if (display == BASE_HEX_DEC)
6012 return hfinfo_number_value_format_display(hfinfo, display, buf, value);
6016 hfinfo_uint64_format(const header_field_info *hfinfo)
6018 const char *format = NULL;
6020 /* Pick the proper format string */
6021 switch (hfinfo->display & FIELD_DISPLAY_E_MASK) {
6023 format = "%" G_GINT64_MODIFIER "u";
6026 format = "%" G_GINT64_MODIFIER "u (0x%016" G_GINT64_MODIFIER "x)";
6028 case BASE_OCT: /* I'm lazy */
6029 format = "%#" G_GINT64_MODIFIER "o";
6032 format = "0x%016" G_GINT64_MODIFIER "x";
6035 format = "0x%016" G_GINT64_MODIFIER "x (%" G_GINT64_MODIFIER "u)";
6038 DISSECTOR_ASSERT_NOT_REACHED();
6045 hfinfo_int64_format(const header_field_info *hfinfo)
6047 const char *format = NULL;
6049 /* Pick the proper format string */
6050 switch (hfinfo->display & FIELD_DISPLAY_E_MASK) {
6052 format = "%" G_GINT64_MODIFIER "d";
6055 format = "%" G_GINT64_MODIFIER "d (0x%016" G_GINT64_MODIFIER "x)";
6057 case BASE_OCT: /* I'm lazy */
6058 format = "%#" G_GINT64_MODIFIER "o";
6061 format = "0x%016" G_GINT64_MODIFIER "x";
6064 format = "0x%016" G_GINT64_MODIFIER "x (%" G_GINT64_MODIFIER "d)";
6067 DISSECTOR_ASSERT_NOT_REACHED();
6074 proto_registrar_n(void)
6076 return gpa_hfinfo.len;
6080 proto_registrar_get_name(const int n)
6082 header_field_info *hfinfo;
6084 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
6085 return hfinfo->name;
6089 proto_registrar_get_abbrev(const int n)
6091 header_field_info *hfinfo;
6093 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
6094 return hfinfo->abbrev;
6098 proto_registrar_get_ftype(const int n)
6100 header_field_info *hfinfo;
6102 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
6103 return hfinfo->type;
6107 proto_registrar_get_parent(const int n)
6109 header_field_info *hfinfo;
6111 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
6112 return hfinfo->parent;
6116 proto_registrar_is_protocol(const int n)
6118 header_field_info *hfinfo;
6120 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
6121 return (hfinfo->parent == -1 ? TRUE : FALSE);
6124 /* Returns length of field in packet (not necessarily the length
6125 * in our internal representation, as in the case of IPv4).
6126 * 0 means undeterminable at time of registration
6127 * -1 means the field is not registered. */
6129 proto_registrar_get_length(const int n)
6131 header_field_info *hfinfo;
6133 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
6134 return ftype_length(hfinfo->type);
6137 /* Looks for a protocol or a field in a proto_tree. Returns TRUE if
6138 * it exists anywhere, or FALSE if it exists nowhere. */
6140 proto_check_for_protocol_or_field(const proto_tree* tree, const int id)
6142 GPtrArray *ptrs = proto_get_finfo_ptr_array(tree, id);
6147 else if (g_ptr_array_len(ptrs) > 0) {
6155 /* Return GPtrArray* of field_info pointers for all hfindex that appear in tree.
6156 * This only works if the hfindex was "primed" before the dissection
6157 * took place, as we just pass back the already-created GPtrArray*.
6158 * The caller should *not* free the GPtrArray*; proto_tree_free_node()
6161 proto_get_finfo_ptr_array(const proto_tree *tree, const int id)
6166 if (PTREE_DATA(tree)->interesting_hfids != NULL)
6167 return (GPtrArray *)g_hash_table_lookup(PTREE_DATA(tree)->interesting_hfids,
6168 GINT_TO_POINTER(id));
6174 proto_tracking_interesting_fields(const proto_tree *tree)
6179 return (PTREE_DATA(tree)->interesting_hfids != NULL);
6182 /* Helper struct for proto_find_info() and proto_all_finfos() */
6188 /* Helper function for proto_find_info() */
6190 find_finfo(proto_node *node, gpointer data)
6192 field_info *fi = PNODE_FINFO(node);
6193 if (fi && fi->hfinfo) {
6194 if (fi->hfinfo->id == ((ffdata_t*)data)->id) {
6195 g_ptr_array_add(((ffdata_t*)data)->array, fi);
6199 /* Don't stop traversing. */
6203 /* Return GPtrArray* of field_info pointers for all hfindex that appear in a tree.
6204 * This works on any proto_tree, primed or unprimed, but actually searches
6205 * the tree, so it is slower than using proto_get_finfo_ptr_array on a primed tree.
6206 * The caller does need to free the returned GPtrArray with
6207 * g_ptr_array_free(<array>, TRUE).
6210 proto_find_finfo(proto_tree *tree, const int id)
6214 ffdata.array = g_ptr_array_new();
6217 proto_tree_traverse_pre_order(tree, find_finfo, &ffdata);
6219 return ffdata.array;
6222 /* Helper function for proto_all_finfos() */
6224 every_finfo(proto_node *node, gpointer data)
6226 field_info *fi = PNODE_FINFO(node);
6227 if (fi && fi->hfinfo) {
6228 g_ptr_array_add(((ffdata_t*)data)->array, fi);
6231 /* Don't stop traversing. */
6235 /* Return GPtrArray* of field_info pointers containing all hfindexes that appear in a tree. */
6237 proto_all_finfos(proto_tree *tree)
6241 ffdata.array = g_ptr_array_new();
6244 proto_tree_traverse_pre_order(tree, every_finfo, &ffdata);
6246 return ffdata.array;
6257 check_for_offset(proto_node *node, const gpointer data)
6259 field_info *fi = PNODE_FINFO(node);
6260 offset_search_t *offsearch = (offset_search_t *)data;
6262 /* !fi == the top most container node which holds nothing */
6263 if (fi && !PROTO_ITEM_IS_HIDDEN(node) && fi->ds_tvb && offsearch->tvb == fi->ds_tvb) {
6264 if (offsearch->offset >= (guint) fi->start &&
6265 offsearch->offset < (guint) (fi->start + fi->length)) {
6267 offsearch->finfo = fi;
6268 return FALSE; /* keep traversing */
6271 return FALSE; /* keep traversing */
6274 /* Search a proto_tree backwards (from leaves to root) looking for the field
6275 * whose start/length occupies 'offset' */
6276 /* XXX - I couldn't find an easy way to search backwards, so I search
6277 * forwards, w/o stopping. Therefore, the last finfo I find will the be
6278 * the one I want to return to the user. This algorithm is inefficient
6279 * and could be re-done, but I'd have to handle all the children and
6280 * siblings of each node myself. When I have more time I'll do that.
6283 proto_find_field_from_offset(proto_tree *tree, guint offset, tvbuff_t *tvb)
6285 offset_search_t offsearch;
6287 offsearch.offset = offset;
6288 offsearch.finfo = NULL;
6289 offsearch.tvb = tvb;
6291 proto_tree_traverse_pre_order(tree, check_for_offset, &offsearch);
6293 return offsearch.finfo;
6296 /* Dumps the protocols in the registration database to stdout. An independent
6297 * program can take this output and format it into nice tables or HTML or
6300 * There is one record per line. The fields are tab-delimited.
6302 * Field 1 = protocol name
6303 * Field 2 = protocol short name
6304 * Field 3 = protocol filter name
6307 proto_registrar_dump_protocols(void)
6309 protocol_t *protocol;
6311 void *cookie = NULL;
6314 i = proto_get_first_protocol(&cookie);
6316 protocol = find_protocol_by_id(i);
6317 printf("%s\t%s\t%s\n", protocol->name, protocol->short_name,
6318 protocol->filter_name);
6319 i = proto_get_next_protocol(&cookie);
6323 /* Dumps the value_strings, extended value string headers, range_strings
6324 * or true/false strings for fields that have them.
6325 * There is one record per line. Fields are tab-delimited.
6326 * There are four types of records: Value String, Extended Value String Header,
6327 * Range String and True/False String. The first field, 'V', 'E', 'R' or 'T', indicates
6328 * the type of record.
6330 * Note that a record will be generated only if the value_string,... is referenced
6331 * in a registered hfinfo entry.
6337 * Field 2 = Field abbreviation to which this value string corresponds
6338 * Field 3 = Integer value
6341 * Extended Value String Headers
6342 * -----------------------------
6344 * Field 2 = Field abbreviation to which this extended value string header corresponds
6345 * Field 3 = Extended Value String "Name"
6346 * Field 4 = Number of entries in the associated value_string array
6347 * Field 5 = Access Type: "Linear Search", "Binary Search", "Direct (indexed) Access"
6352 * Field 2 = Field abbreviation to which this range string corresponds
6353 * Field 3 = Integer value: lower bound
6354 * Field 4 = Integer value: upper bound
6357 * True/False Strings
6358 * ------------------
6360 * Field 2 = Field abbreviation to which this true/false string corresponds
6361 * Field 3 = True String
6362 * Field 4 = False String
6365 proto_registrar_dump_values(void)
6367 header_field_info *hfinfo;
6369 const value_string *vals;
6370 const val64_string *vals64;
6371 const range_string *range;
6372 const true_false_string *tfs;
6374 len = gpa_hfinfo.len;
6375 for (i = 0; i < len ; i++) {
6376 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
6378 if (hfinfo->id == hf_text_only) {
6382 /* ignore protocols */
6383 if (proto_registrar_is_protocol(i)) {
6386 /* process header fields */
6389 * If this field isn't at the head of the list of
6390 * fields with this name, skip this field - all
6391 * fields with the same name are really just versions
6392 * of the same field stored in different bits, and
6393 * should have the same type/radix/value list, and
6394 * just differ in their bit masks. (If a field isn't
6395 * a bitfield, but can be, say, 1 or 2 bytes long,
6396 * it can just be made FT_UINT16, meaning the
6397 * *maximum* length is 2 bytes, and be used
6400 if (hfinfo->same_name_prev_id != -1)
6408 if (hfinfo->strings != NULL) {
6409 if ((hfinfo->display & FIELD_DISPLAY_E_MASK) != BASE_CUSTOM &&
6410 (hfinfo->type == FT_UINT8 ||
6411 hfinfo->type == FT_UINT16 ||
6412 hfinfo->type == FT_UINT24 ||
6413 hfinfo->type == FT_UINT32 ||
6414 hfinfo->type == FT_UINT64 ||
6415 hfinfo->type == FT_INT8 ||
6416 hfinfo->type == FT_INT16 ||
6417 hfinfo->type == FT_INT24 ||
6418 hfinfo->type == FT_INT32 ||
6419 hfinfo->type == FT_INT64)) {
6421 if (hfinfo->display & BASE_RANGE_STRING) {
6422 range = (const range_string *)hfinfo->strings;
6423 } else if (hfinfo->display & BASE_EXT_STRING) {
6424 vals = VALUE_STRING_EXT_VS_P((const value_string_ext *)hfinfo->strings);
6425 } else if (hfinfo->display & BASE_VAL64_STRING) {
6426 vals64 = (const val64_string *)hfinfo->strings;
6428 vals = (const value_string *)hfinfo->strings;
6431 else if (hfinfo->type == FT_BOOLEAN) {
6432 tfs = (const struct true_false_string *)hfinfo->strings;
6436 /* Print value strings? */
6438 if (hfinfo->display & BASE_EXT_STRING) {
6439 const value_string_ext *vse_p = (const value_string_ext *)hfinfo->strings;
6440 if (!value_string_ext_validate(vse_p)) {
6441 g_warning("Invalid value_string_ext ptr for: %s", hfinfo->abbrev);
6444 try_val_to_str_ext(0, vse_p); /* "prime" the extended value_string */
6445 printf("E\t%s\t%d\t%s\t%s\n",
6447 VALUE_STRING_EXT_VS_NUM_ENTRIES(vse_p),
6448 VALUE_STRING_EXT_VS_NAME(vse_p),
6449 value_string_ext_match_type_str(vse_p));
6452 while (vals[vi].strptr) {
6453 /* Print in the proper base */
6454 if (hfinfo->display == BASE_HEX) {
6455 printf("V\t%s\t0x%x\t%s\n",
6461 printf("V\t%s\t%u\t%s\n",
6471 while (vals64[vi].strptr) {
6472 printf("V64\t%s\t%" G_GINT64_MODIFIER "u\t%s\n",
6480 /* print range strings? */
6483 while (range[vi].strptr) {
6484 /* Print in the proper base */
6485 if ((hfinfo->display & FIELD_DISPLAY_E_MASK) == BASE_HEX) {
6486 printf("R\t%s\t0x%x\t0x%x\t%s\n",
6488 range[vi].value_min,
6489 range[vi].value_max,
6493 printf("R\t%s\t%u\t%u\t%s\n",
6495 range[vi].value_min,
6496 range[vi].value_max,
6503 /* Print true/false strings? */
6505 printf("T\t%s\t%s\t%s\n", hfinfo->abbrev,
6506 tfs->true_string, tfs->false_string);
6512 /* Dumps the contents of the registration database to stdout. An independent
6513 * program can take this output and format it into nice tables or HTML or
6516 * There is one record per line. Each record is either a protocol or a header
6517 * field, differentiated by the first field. The fields are tab-delimited.
6522 * Field 2 = descriptive protocol name
6523 * Field 3 = protocol abbreviation
6528 * Field 2 = descriptive field name
6529 * Field 3 = field abbreviation
6530 * Field 4 = type ( textual representation of the the ftenum type )
6531 * Field 5 = parent protocol abbreviation
6532 * Field 6 = base for display (for integer types); "parent bitfield width" for FT_BOOLEAN
6533 * Field 7 = bitmask: format: hex: 0x....
6534 * Field 8 = blurb describing field
6537 proto_registrar_dump_fields(void)
6539 header_field_info *hfinfo, *parent_hfinfo;
6541 const char *enum_name;
6542 const char *base_name;
6546 len = gpa_hfinfo.len;
6547 for (i = 0; i < len ; i++) {
6548 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
6551 * Skip the pseudo-field for "proto_tree_add_text()" since
6552 * we don't want it in the list of filterable fields.
6554 if (hfinfo->id == hf_text_only)
6557 /* format for protocols */
6558 if (proto_registrar_is_protocol(i)) {
6559 printf("P\t%s\t%s\n", hfinfo->name, hfinfo->abbrev);
6561 /* format for header fields */
6564 * If this field isn't at the head of the list of
6565 * fields with this name, skip this field - all
6566 * fields with the same name are really just versions
6567 * of the same field stored in different bits, and
6568 * should have the same type/radix/value list, and
6569 * just differ in their bit masks. (If a field isn't
6570 * a bitfield, but can be, say, 1 or 2 bytes long,
6571 * it can just be made FT_UINT16, meaning the
6572 * *maximum* length is 2 bytes, and be used
6575 if (hfinfo->same_name_prev_id != -1)
6578 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
6580 enum_name = ftype_name(hfinfo->type);
6583 if (hfinfo->type == FT_UINT8 ||
6584 hfinfo->type == FT_UINT16 ||
6585 hfinfo->type == FT_UINT24 ||
6586 hfinfo->type == FT_UINT32 ||
6587 hfinfo->type == FT_UINT64 ||
6588 hfinfo->type == FT_INT8 ||
6589 hfinfo->type == FT_INT16 ||
6590 hfinfo->type == FT_INT24 ||
6591 hfinfo->type == FT_INT32 ||
6592 hfinfo->type == FT_INT64) {
6594 switch (hfinfo->display & FIELD_DISPLAY_E_MASK) {
6596 base_name = "BASE_NONE";
6599 base_name = "BASE_DEC";
6602 base_name = "BASE_HEX";
6605 base_name = "BASE_OCT";
6608 base_name = "BASE_DEC_HEX";
6611 base_name = "BASE_HEX_DEC";
6614 base_name = "BASE_CUSTOM";
6620 } else if (hfinfo->type == FT_BOOLEAN) {
6621 /* For FT_BOOLEAN: 'display' can be "parent bitfield width" */
6622 g_snprintf(width, sizeof(width), "%d", hfinfo->display);
6626 blurb = hfinfo->blurb;
6629 else if (strlen(blurb) == 0)
6632 printf("F\t%s\t%s\t%s\t%s\t%s\t0x%x\t%s\n",
6633 hfinfo->name, hfinfo->abbrev, enum_name,
6634 parent_hfinfo->abbrev, base_name, hfinfo->bitmask, blurb);
6639 /* Dumps field types and descriptive names to stdout. An independent
6640 * program can take this output and format it into nice tables or HTML or
6643 * There is one record per line. The fields are tab-delimited.
6645 * Field 1 = field type name, e.g. FT_UINT8
6646 * Field 2 = descriptive name, e.g. "Unsigned, 1 byte"
6649 proto_registrar_dump_ftypes(void)
6653 for (fte = 0; fte < FT_NUM_TYPES; fte++) {
6654 printf("%s\t%s\n", ftype_name((ftenum_t)fte), ftype_pretty_name((ftenum_t)fte));
6659 hfinfo_numeric_format(const header_field_info *hfinfo)
6661 const char *format = NULL;
6663 /* Get the underlying BASE_ value */
6664 switch (hfinfo->display & FIELD_DISPLAY_E_MASK) {
6667 case BASE_OCT: /* I'm lazy */
6669 switch (hfinfo->type) {
6671 format = "%s == %" G_GINT64_MODIFIER "u";
6674 format = "%s == %" G_GINT64_MODIFIER "d";
6677 DISSECTOR_ASSERT_NOT_REACHED();
6683 switch (hfinfo->type) {
6686 format = "%s == 0x%016" G_GINT64_MODIFIER "x";
6689 DISSECTOR_ASSERT_NOT_REACHED();
6694 DISSECTOR_ASSERT_NOT_REACHED();
6700 /* This function indicates whether it's possible to construct a
6701 * "match selected" display filter string for the specified field,
6702 * returns an indication of whether it's possible, and, if it's
6703 * possible and "filter" is non-null, constructs the filter and
6704 * sets "*filter" to point to it.
6705 * You do not need to [g_]free() this string since it will be automatically
6706 * freed once the next packet is dissected.
6709 construct_match_selected_string(field_info *finfo, epan_dissect_t *edt,
6712 header_field_info *hfinfo;
6717 gint start, length, length_remaining;
6719 gchar is_signed_num = FALSE;
6724 hfinfo = finfo->hfinfo;
6725 DISSECTOR_ASSERT(hfinfo);
6726 abbrev_len = (int) strlen(hfinfo->abbrev);
6728 if (hfinfo->strings && (hfinfo->display & FIELD_DISPLAY_E_MASK) == BASE_NONE) {
6729 const gchar *str = NULL;
6731 switch (hfinfo->type) {
6737 str = hf_try_val_to_str(fvalue_get_sinteger(&finfo->value), hfinfo);
6744 str = hf_try_val_to_str(fvalue_get_uinteger(&finfo->value), hfinfo);
6751 if (str != NULL && filter != NULL) {
6752 *filter = ep_strdup_printf("%s == \"%s\"", hfinfo->abbrev, str);
6758 * XXX - we can't use the "val_to_string_repr" and "string_repr_len"
6759 * functions for FT_UINT and FT_INT types, as we choose the base in
6760 * the string expression based on the display base of the field.
6762 * Note that the base does matter, as this is also used for
6763 * the protocolinfo tap.
6765 * It might be nice to use them in "proto_item_fill_label()"
6766 * as well, although, there, you'd have to deal with the base
6767 * *and* with resolved values for addresses.
6769 * Perhaps we need two different val_to_string routines, one
6770 * to generate items for display filters and one to generate
6771 * strings for display, and pass to both of them the
6772 * "display" and "strings" values in the header_field_info
6773 * structure for the field, so they can get the base and,
6774 * if the field is Boolean or an enumerated integer type,
6775 * the tables used to generate human-readable values.
6777 switch (hfinfo->type) {
6783 is_signed_num = TRUE;
6790 if (filter != NULL) {
6797 number = fvalue_get_sinteger(&finfo->value);
6799 number = fvalue_get_uinteger(&finfo->value);
6801 out = hfinfo_numeric_value_format(hfinfo, buf, number);
6803 *filter = ep_strdup_printf("%s == %s", hfinfo->abbrev, out);
6809 if (filter != NULL) {
6810 const char *format = hfinfo_numeric_format(hfinfo);
6812 *filter = ep_strdup_printf(format,
6814 fvalue_get_integer64(&finfo->value));
6820 *filter = ep_strdup(finfo->hfinfo->abbrev);
6825 * If the length is 0, just match the name of the
6828 * (Also check for negative values, just in case,
6829 * as we'll cast it to an unsigned value later.)
6831 length = finfo->length;
6834 *filter = ep_strdup(finfo->hfinfo->abbrev);
6841 * This doesn't have a value, so we'd match
6842 * on the raw bytes at this address.
6844 * Should we be allowed to access to the raw bytes?
6845 * If "edt" is NULL, the answer is "no".
6851 * Is this field part of the raw frame tvbuff?
6852 * If not, we can't use "frame[N:M]" to match
6855 * XXX - should this be frame-relative, or
6856 * protocol-relative?
6858 * XXX - does this fallback for non-registered
6859 * fields even make sense?
6861 if (finfo->ds_tvb != edt->tvb)
6862 return FALSE; /* you lose */
6865 * Don't go past the end of that tvbuff.
6867 length_remaining = tvb_length_remaining(finfo->ds_tvb, finfo->start);
6868 if (length > length_remaining)
6869 length = length_remaining;
6873 if (filter != NULL) {
6874 start = finfo->start;
6875 buf_len = 32 + length * 3;
6876 *filter = (char *)ep_alloc0(buf_len);
6879 ptr += g_snprintf(ptr, (gulong) (buf_len-(ptr-*filter)),
6880 "frame[%d:%d] == ", finfo->start, length);
6881 for (i=0; i<length; i++) {
6882 c = tvb_get_guint8(finfo->ds_tvb, start);
6885 ptr += g_snprintf(ptr, (gulong) (buf_len-(ptr-*filter)), "%02x", c);
6888 ptr += g_snprintf(ptr, (gulong) (buf_len-(ptr-*filter)), ":%02x", c);
6895 /* FT_PCRE never appears as a type for a registered field. It is
6896 * only used internally. */
6897 DISSECTOR_ASSERT_NOT_REACHED();
6900 /* By default, use the fvalue's "to_string_repr" method. */
6902 /* Figure out the string length needed.
6903 * The ft_repr length.
6904 * 4 bytes for " == ".
6905 * 1 byte for trailing NUL.
6907 if (filter != NULL) {
6908 dfilter_len = fvalue_string_repr_len(&finfo->value,
6910 dfilter_len += abbrev_len + 4 + 1;
6911 *filter = (char *)ep_alloc0(dfilter_len);
6913 /* Create the string */
6914 g_snprintf(*filter, dfilter_len, "%s == ",
6916 fvalue_to_string_repr(&finfo->value,
6918 &(*filter)[abbrev_len + 4]);
6927 * Returns TRUE if we can do a "match selected" on the field, FALSE
6931 proto_can_match_selected(field_info *finfo, epan_dissect_t *edt)
6933 return construct_match_selected_string(finfo, edt, NULL);
6936 /* This function attempts to construct a "match selected" display filter
6937 * string for the specified field; if it can do so, it returns a pointer
6938 * to the string, otherwise it returns NULL.
6940 * The string is allocated with packet lifetime scope.
6941 * You do not need to [g_]free() this string since it will be automatically
6942 * freed once the next packet is dissected.
6945 proto_construct_match_selected_string(field_info *finfo, epan_dissect_t *edt)
6949 if (!construct_match_selected_string(finfo, edt, &filter))
6954 /* This function is common code for both proto_tree_add_bitmask() and
6955 * proto_tree_add_bitmask_text() functions.
6958 /* NOTE: to support code written when proto_tree_add_bitmask() and
6959 * proto_tree_add_bitmask_text took a
6960 * gboolean as its last argument, with FALSE meaning "big-endian"
6961 * and TRUE meaning "little-endian", we treat any non-zero value of
6962 * "encoding" as meaning "little-endian".
6965 proto_item_add_bitmask_tree(proto_item *item, tvbuff_t *tvb, const int offset,
6966 const int len, const gint ett, const int **fields,
6967 const guint encoding, const int flags,
6971 guint32 available_bits = 0;
6973 proto_tree *tree = NULL;
6974 header_field_info *hf;
6978 value = tvb_get_guint8(tvb, offset);
6979 available_bits = 0xFF;
6982 value = encoding ? tvb_get_letohs(tvb, offset) :
6983 tvb_get_ntohs(tvb, offset);
6984 available_bits = 0xFFFF;
6987 value = encoding ? tvb_get_letoh24(tvb, offset) :
6988 tvb_get_ntoh24(tvb, offset);
6989 available_bits = 0xFFFFFF;
6992 value = encoding ? tvb_get_letohl(tvb, offset) :
6993 tvb_get_ntohl(tvb, offset);
6994 available_bits = 0xFFFFFFFF;
6997 g_assert_not_reached();
7000 tree = proto_item_add_subtree(item, ett);
7002 guint32 present_bits;
7003 hf = proto_registrar_get_nth(**fields);
7004 DISSECTOR_ASSERT(hf->bitmask != 0);
7006 /* Skip fields that aren't fully present */
7007 present_bits = available_bits & hf->bitmask;
7008 if (present_bits != hf->bitmask) {
7013 proto_tree_add_item(tree, **fields, tvb, offset, len, encoding);
7014 if (flags & BMT_NO_APPEND) {
7018 tmpval = (value & hf->bitmask) >> hfinfo_bitshift(hf);
7029 if (hf->display == BASE_CUSTOM) {
7030 gchar lbl[ITEM_LABEL_LENGTH];
7031 const custom_fmt_func_t fmtfunc = (const custom_fmt_func_t)hf->strings;
7033 DISSECTOR_ASSERT(fmtfunc);
7034 fmtfunc(lbl, tmpval);
7035 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
7039 else if (hf->strings) {
7040 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
7041 hf->name, hf_try_val_to_str_const(tmpval, hf, "Unknown"));
7044 else if (!(flags & BMT_NO_INT)) {
7049 proto_item_append_text(item, ", ");
7052 out = hfinfo_number_value_format(hf, buf, tmpval);
7053 proto_item_append_text(item, "%s: %s", hf->name, out);
7059 if (hf->strings && !(flags & BMT_NO_TFS)) {
7060 /* If we have true/false strings, emit full - otherwise messages
7062 const struct true_false_string *tfs =
7063 (const struct true_false_string *)hf->strings;
7066 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
7067 hf->name, tfs->true_string);
7069 } else if (!(flags & BMT_NO_FALSE)) {
7070 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
7071 hf->name, tfs->false_string);
7074 } else if (hf->bitmask & value) {
7075 /* If the flag is set, show the name */
7076 proto_item_append_text(item, "%s%s", first ? "" : ", ", hf->name);
7081 g_assert_not_reached();
7090 /* This function will dissect a sequence of bytes that describe a
7092 * hf_hdr is a 8/16/24/32 bit integer that describes the bitmask to be dissected.
7093 * This field will form an expansion under which the individual fields of the
7094 * bitmask is dissected and displayed.
7095 * This field must be of the type FT_[U]INT{8|16|24|32}.
7097 * fields is an array of pointers to int that lists all the fields of the
7098 * bitmask. These fields can be either of the type FT_BOOLEAN for flags
7099 * or another integer of the same type/size as hf_hdr with a mask specified.
7100 * This array is terminated by a NULL entry.
7102 * FT_BOOLEAN bits that are set to 1 will have the name added to the expansion.
7103 * FT_integer fields that have a value_string attached will have the
7104 * matched string displayed on the expansion line.
7107 proto_tree_add_bitmask(proto_tree *parent_tree, tvbuff_t *tvb,
7108 const guint offset, const int hf_hdr,
7109 const gint ett, const int **fields,
7110 const guint encoding)
7112 proto_item *item = NULL;
7113 header_field_info *hf;
7116 hf = proto_registrar_get_nth(hf_hdr);
7117 DISSECTOR_ASSERT(IS_FT_INT(hf->type) || IS_FT_UINT(hf->type));
7118 len = ftype_length(hf->type);
7121 item = proto_tree_add_item(parent_tree, hf_hdr, tvb, offset, len, encoding);
7122 proto_item_add_bitmask_tree(item, tvb, offset, len, ett, fields, encoding,
7123 BMT_NO_INT|BMT_NO_TFS, FALSE);
7129 /* The same as proto_tree_add_bitmask(), but using a caller-supplied length.
7130 * This is intended to support bitmask fields whose lengths can vary, perhaps
7131 * as the underlying standard evolves over time.
7132 * With this API there is the possibility of being called to display more or
7133 * less data than the dissector was coded to support.
7134 * In such cases, it is assumed that bitmasks are extended on the MSb end.
7135 * Thus when presented with "too much" or "too little" data, MSbits will be
7136 * ignored or MSfields sacrificed.
7138 * Only fields for which all defined bits are available are displayed.
7141 proto_tree_add_bitmask_len(proto_tree *parent_tree, tvbuff_t *tvb,
7142 const guint offset, const guint len, const int hf_hdr,
7143 const gint ett, const int **fields, struct expert_field* exp,
7144 const guint encoding)
7146 proto_item *item = NULL;
7147 header_field_info *hf;
7148 guint decodable_len;
7149 guint decodable_offset;
7150 guint32 decodable_value;
7152 hf = proto_registrar_get_nth(hf_hdr);
7153 DISSECTOR_ASSERT(IS_FT_INT(hf->type) || IS_FT_UINT(hf->type));
7155 decodable_offset = offset;
7156 decodable_len = MIN(len, (guint) ftype_length(hf->type));
7158 /* If we are ftype_length-limited,
7159 * make sure we decode as many LSBs as possible.
7161 if (encoding == ENC_BIG_ENDIAN) {
7162 decodable_offset += (len - decodable_len);
7166 decodable_value = get_uint_value(parent_tree, tvb, decodable_offset,
7167 decodable_len, encoding);
7169 /* The root item covers all the bytes even if we can't decode them all */
7170 item = proto_tree_add_uint(parent_tree, hf_hdr, tvb, offset, len,
7174 if (decodable_len < len) {
7175 /* Dissector likely requires updating for new protocol revision */
7176 expert_add_info_format(NULL, item, exp,
7177 "Only least-significant %d of %d bytes decoded",
7178 decodable_len, len);
7182 proto_item_add_bitmask_tree(item, tvb, decodable_offset, decodable_len,
7183 ett, fields, encoding, BMT_NO_INT|BMT_NO_TFS, FALSE);
7189 /* The same as proto_tree_add_bitmask(), but using an arbitrary text as a top-level item */
7191 proto_tree_add_bitmask_text(proto_tree *parent_tree, tvbuff_t *tvb,
7192 const guint offset, const guint len,
7193 const char *name, const char *fallback,
7194 const gint ett, const int **fields,
7195 const guint encoding, const int flags)
7197 proto_item *item = NULL;
7200 item = proto_tree_add_text(parent_tree, tvb, offset, len, "%s", name ? name : "");
7201 if (proto_item_add_bitmask_tree(item, tvb, offset, len, ett, fields, encoding,
7202 flags, TRUE) && fallback) {
7203 /* Still at first item - append 'fallback' text if any */
7204 proto_item_append_text(item, "%s", fallback);
7212 proto_tree_add_bits_item(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
7213 const guint bit_offset, const gint no_of_bits,
7214 const guint encoding)
7216 header_field_info *hfinfo;
7220 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
7222 octet_length = (no_of_bits + 7) >> 3;
7223 octet_offset = bit_offset >> 3;
7224 test_length(hfinfo, tvb, octet_offset, octet_length);
7226 /* Yes, we try to fake this item again in proto_tree_add_bits_ret_val()
7227 * but only after doing a bunch more work (which we can, in the common
7228 * case, shortcut here).
7230 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
7232 return proto_tree_add_bits_ret_val(tree, hfindex, tvb, bit_offset, no_of_bits, NULL, encoding);
7236 * This function will dissect a sequence of bits that does not need to be byte aligned; the bits
7237 * set will be shown in the tree as ..10 10.. and the integer value returned if return_value is set.
7238 * Offset should be given in bits from the start of the tvb.
7242 _proto_tree_add_bits_ret_val(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
7243 const guint bit_offset, const gint no_of_bits,
7244 guint64 *return_value, const guint encoding)
7250 char lbl_str[ITEM_LABEL_LENGTH];
7254 header_field_info *hf_field;
7256 const true_false_string *tfstring;
7258 /* We can't fake it just yet. We have to fill in the 'return_value' parameter */
7259 PROTO_REGISTRAR_GET_NTH(hfindex, hf_field);
7261 if (hf_field->bitmask != 0) {
7262 REPORT_DISSECTOR_BUG(ep_strdup_printf("Incompatible use of proto_tree_add_bits_ret_val"
7263 " with field '%s' (%s) with bitmask != 0",
7264 hf_field->abbrev, hf_field->name));
7267 DISSECTOR_ASSERT(no_of_bits > 0);
7269 /* Byte align offset */
7270 offset = bit_offset>>3;
7273 * Calculate the number of octets used to hold the bits
7275 tot_no_bits = ((bit_offset&0x7) + no_of_bits);
7276 length = (tot_no_bits + 7) >> 3;
7278 if (no_of_bits < 65) {
7279 value = tvb_get_bits64(tvb, bit_offset, no_of_bits, encoding);
7281 DISSECTOR_ASSERT_NOT_REACHED();
7285 /* Sign extend for signed types */
7286 switch (hf_field->type) {
7292 if (value & (G_GINT64_CONSTANT(1) << (no_of_bits-1)))
7293 value |= (G_GINT64_CONSTANT(-1) << no_of_bits);
7301 *return_value = value;
7304 /* Coast clear. Try and fake it */
7305 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
7307 bf_str = decode_bits_in_field(bit_offset, no_of_bits, value);
7309 switch (hf_field->type) {
7312 tfstring = (const true_false_string *) &tfs_true_false;
7313 if (hf_field->strings)
7314 tfstring = (const true_false_string *)hf_field->strings;
7315 return proto_tree_add_boolean_format(tree, hfindex, tvb, offset, length, (guint32)value,
7317 bf_str, hf_field->name,
7318 (guint32)value ? tfstring->true_string : tfstring->false_string);
7325 pi = proto_tree_add_uint(tree, hfindex, tvb, offset, length, (guint32)value);
7326 fill_label_number(PITEM_FINFO(pi), lbl_str, FALSE);
7333 pi = proto_tree_add_int(tree, hfindex, tvb, offset, length, (gint32)value);
7334 fill_label_number(PITEM_FINFO(pi), lbl_str, TRUE);
7338 pi = proto_tree_add_uint64(tree, hfindex, tvb, offset, length, value);
7339 fill_label_number64(PITEM_FINFO(pi), lbl_str, FALSE);
7343 pi = proto_tree_add_int64(tree, hfindex, tvb, offset, length, (gint64)value);
7344 fill_label_number64(PITEM_FINFO(pi), lbl_str, TRUE);
7348 DISSECTOR_ASSERT_NOT_REACHED();
7353 proto_item_set_text(pi, "%s = %s", bf_str, lbl_str);
7358 proto_tree_add_split_bits_item_ret_val(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
7359 const guint bit_offset, const crumb_spec_t *crumb_spec,
7360 guint64 *return_value)
7365 guint mask_initial_bit_offset;
7366 guint mask_greatest_bit_offset;
7370 char lbl_str[ITEM_LABEL_LENGTH];
7372 guint64 composite_bitmask;
7373 guint64 composite_bitmap;
7375 header_field_info *hf_field;
7376 const true_false_string *tfstring;
7378 /* We can't fake it just yet. We have to fill in the 'return_value' parameter */
7379 PROTO_REGISTRAR_GET_NTH(hfindex, hf_field);
7381 if (hf_field->bitmask != 0) {
7382 REPORT_DISSECTOR_BUG(ep_strdup_printf(
7383 "Incompatible use of proto_tree_add_split_bits_item_ret_val"
7384 " with field '%s' (%s) with bitmask != 0",
7385 hf_field->abbrev, hf_field->name));
7388 mask_initial_bit_offset = bit_offset % 8;
7393 mask_greatest_bit_offset = 0;
7394 composite_bitmask = 0;
7395 composite_bitmap = 0;
7397 while (crumb_spec[i].crumb_bit_length != 0) {
7398 guint64 crumb_mask, crumb_value;
7399 guint8 crumb_end_bit_offset;
7401 DISSECTOR_ASSERT(i < 64);
7402 crumb_value = tvb_get_bits64(tvb,
7403 bit_offset + crumb_spec[i].crumb_bit_offset,
7404 crumb_spec[i].crumb_bit_length,
7406 value += crumb_value;
7407 no_of_bits += crumb_spec[i].crumb_bit_length;
7409 /* The bitmask is 64 bit, left-aligned, starting at the first bit of the
7410 octet containing the initial offset.
7411 If the mask is beyond 32 bits, then give up on bit map display.
7412 This could be improved in future, probably showing a table
7413 of 32 or 64 bits per row */
7414 if (mask_greatest_bit_offset < 32) {
7415 crumb_end_bit_offset = mask_initial_bit_offset
7416 + crumb_spec[i].crumb_bit_offset
7417 + crumb_spec[i].crumb_bit_length;
7418 crumb_mask = (G_GUINT64_CONSTANT(1) << crumb_spec[i].crumb_bit_length) - 1;
7420 if (crumb_end_bit_offset > mask_greatest_bit_offset) {
7421 mask_greatest_bit_offset = crumb_end_bit_offset;
7423 composite_bitmask |= (crumb_mask << (64 - crumb_end_bit_offset));
7424 composite_bitmap |= (crumb_value << (64 - crumb_end_bit_offset));
7426 /* Shift left for the next segment */
7427 value <<= crumb_spec[++i].crumb_bit_length;
7430 /* Sign extend for signed types */
7431 switch (hf_field->type) {
7437 if (no_of_bits && (value & (G_GINT64_CONSTANT(1) << (no_of_bits-1))))
7438 value |= (G_GINT64_CONSTANT(-1) << no_of_bits);
7445 *return_value = value;
7448 /* Coast clear. Try and fake it */
7449 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
7451 /* initialise the format string */
7452 bf_str = (char *)ep_alloc(256);
7455 octet_offset = bit_offset >> 3;
7457 /* Round up mask length to nearest octet */
7458 octet_length = ((mask_greatest_bit_offset + 7) >> 3);
7459 mask_greatest_bit_offset = octet_length << 3;
7461 /* As noted above, we currently only produce a bitmap if the crumbs span less than 4 octets of the tvb.
7462 It would be a useful enhancement to eliminate this restriction. */
7463 if (mask_greatest_bit_offset <= 32) {
7464 other_decode_bitfield_value(bf_str,
7465 (guint32)(composite_bitmap >> (64 - mask_greatest_bit_offset)),
7466 (guint32)(composite_bitmask >> (64 - mask_greatest_bit_offset)),
7467 mask_greatest_bit_offset);
7470 switch (hf_field->type) {
7471 case FT_BOOLEAN: /* it is a bit odd to have a boolean encoded as split-bits, but possible, I suppose? */
7473 tfstring = (const true_false_string *) &tfs_true_false;
7474 if (hf_field->strings)
7475 tfstring = (const true_false_string *) hf_field->strings;
7476 return proto_tree_add_boolean_format(tree, hfindex,
7477 tvb, octet_offset, octet_length, (guint32)value,
7479 bf_str, hf_field->name,
7480 (guint32)value ? tfstring->true_string : tfstring->false_string);
7487 pi = proto_tree_add_uint(tree, hfindex, tvb, octet_offset, octet_length, (guint32)value);
7488 fill_label_number(PITEM_FINFO(pi), lbl_str, FALSE);
7495 pi = proto_tree_add_int(tree, hfindex, tvb, octet_offset, octet_length, (gint32)value);
7496 fill_label_number(PITEM_FINFO(pi), lbl_str, TRUE);
7500 pi = proto_tree_add_uint64(tree, hfindex, tvb, octet_offset, octet_length, value);
7501 fill_label_number64(PITEM_FINFO(pi), lbl_str, FALSE);
7505 pi = proto_tree_add_int64(tree, hfindex, tvb, octet_offset, octet_length, (gint64)value);
7506 fill_label_number64(PITEM_FINFO(pi), lbl_str, TRUE);
7510 DISSECTOR_ASSERT_NOT_REACHED();
7514 proto_item_set_text(pi, "%s = %s", bf_str, lbl_str);
7519 proto_tree_add_split_bits_crumb(proto_tree *tree, const int hfindex, tvbuff_t *tvb, const guint bit_offset,
7520 const crumb_spec_t *crumb_spec, guint16 crumb_index)
7522 header_field_info *hfinfo;
7524 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
7525 proto_tree_add_text(tree, tvb,
7527 ((bit_offset + crumb_spec[crumb_index].crumb_bit_length - 1) >> 3) - (bit_offset >> 3) + 1,
7528 "%s crumb %d of %s (decoded above)",
7529 decode_bits_in_field(bit_offset, crumb_spec[crumb_index].crumb_bit_length,
7532 crumb_spec[crumb_index].crumb_bit_length,
7539 proto_tree_add_bits_ret_val(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
7540 const guint bit_offset, const gint no_of_bits,
7541 guint64 *return_value, const guint encoding)
7545 if ((item = _proto_tree_add_bits_ret_val(tree, hfindex, tvb,
7546 bit_offset, no_of_bits,
7547 return_value, encoding))) {
7548 FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_OFFSET(bit_offset));
7549 FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_SIZE(no_of_bits));
7555 _proto_tree_add_bits_format_value(proto_tree *tree, const int hfindex,
7556 tvbuff_t *tvb, const guint bit_offset,
7557 const gint no_of_bits, void *value_ptr,
7565 header_field_info *hf_field;
7567 /* We do not have to return a value, try to fake it as soon as possible */
7568 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
7570 if (hf_field->bitmask != 0) {
7571 REPORT_DISSECTOR_BUG(ep_strdup_printf(
7572 "Incompatible use of proto_tree_add_bits_format_value"
7573 " with field '%s' (%s) with bitmask != 0",
7574 hf_field->abbrev, hf_field->name));
7577 DISSECTOR_ASSERT(no_of_bits > 0);
7579 /* Byte align offset */
7580 offset = bit_offset>>3;
7583 * Calculate the number of octets used to hold the bits
7585 tot_no_bits = ((bit_offset&0x7) + no_of_bits);
7586 length = tot_no_bits>>3;
7587 /* If we are using part of the next octet, increase length by 1 */
7588 if (tot_no_bits & 0x07)
7591 if (no_of_bits < 65) {
7592 value = tvb_get_bits64(tvb, bit_offset, no_of_bits, ENC_BIG_ENDIAN);
7594 DISSECTOR_ASSERT_NOT_REACHED();
7598 str = decode_bits_in_field(bit_offset, no_of_bits, value);
7601 strcat(str, hf_field->name);
7604 * This function does not receive an actual value but a dimensionless pointer to that value.
7605 * For this reason, the type of the header field is examined in order to determine
7606 * what kind of value we should read from this address.
7607 * The caller of this function must make sure that for the specific header field type the address of
7608 * a compatible value is provided.
7610 switch (hf_field->type) {
7612 return proto_tree_add_boolean_format(tree, hfindex, tvb, offset, length, *(guint32 *)value_ptr,
7613 "%s: %s", str, value_str);
7620 return proto_tree_add_uint_format(tree, hfindex, tvb, offset, length, *(guint32 *)value_ptr,
7621 "%s: %s", str, value_str);
7625 return proto_tree_add_uint64_format(tree, hfindex, tvb, offset, length, *(guint64 *)value_ptr,
7626 "%s: %s", str, value_str);
7633 return proto_tree_add_int_format(tree, hfindex, tvb, offset, length, *(gint32 *)value_ptr,
7634 "%s: %s", str, value_str);
7638 return proto_tree_add_int64_format(tree, hfindex, tvb, offset, length, *(gint64 *)value_ptr,
7639 "%s: %s", str, value_str);
7643 return proto_tree_add_float_format(tree, hfindex, tvb, offset, length, *(float *)value_ptr,
7644 "%s: %s", str, value_str);
7648 DISSECTOR_ASSERT_NOT_REACHED();
7655 proto_tree_add_bits_format_value(proto_tree *tree, const int hfindex,
7656 tvbuff_t *tvb, const guint bit_offset,
7657 const gint no_of_bits, void *value_ptr,
7662 if ((item = _proto_tree_add_bits_format_value(tree, hfindex,
7663 tvb, bit_offset, no_of_bits,
7664 value_ptr, value_str))) {
7665 FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_OFFSET(bit_offset));
7666 FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_SIZE(no_of_bits));
7671 #define CREATE_VALUE_STRING(dst,format,ap) \
7672 va_start(ap, format); \
7673 dst = ep_strdup_vprintf(format, ap); \
7677 proto_tree_add_uint_bits_format_value(proto_tree *tree, const int hfindex,
7678 tvbuff_t *tvb, const guint bit_offset,
7679 const gint no_of_bits, guint32 value,
7680 const char *format, ...)
7684 header_field_info *hf_field;
7686 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
7688 switch (hf_field->type) {
7696 DISSECTOR_ASSERT_NOT_REACHED();
7701 CREATE_VALUE_STRING(dst, format, ap);
7703 return proto_tree_add_bits_format_value(tree, hfindex, tvb, bit_offset, no_of_bits, &value, dst);
7707 proto_tree_add_float_bits_format_value(proto_tree *tree, const int hfindex,
7708 tvbuff_t *tvb, const guint bit_offset,
7709 const gint no_of_bits, float value,
7710 const char *format, ...)
7714 header_field_info *hf_field;
7716 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
7718 DISSECTOR_ASSERT(hf_field->type == FT_FLOAT);
7720 CREATE_VALUE_STRING(dst, format, ap);
7722 return proto_tree_add_bits_format_value(tree, hfindex, tvb, bit_offset, no_of_bits, &value, dst);
7726 proto_tree_add_int_bits_format_value(proto_tree *tree, const int hfindex,
7727 tvbuff_t *tvb, const guint bit_offset,
7728 const gint no_of_bits, gint32 value,
7729 const char *format, ...)
7733 header_field_info *hf_field;
7735 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
7737 switch (hf_field->type) {
7745 DISSECTOR_ASSERT_NOT_REACHED();
7750 CREATE_VALUE_STRING(dst, format, ap);
7752 return proto_tree_add_bits_format_value(tree, hfindex, tvb, bit_offset, no_of_bits, &value, dst);
7756 proto_tree_add_boolean_bits_format_value(proto_tree *tree, const int hfindex,
7757 tvbuff_t *tvb, const guint bit_offset,
7758 const gint no_of_bits, guint32 value,
7759 const char *format, ...)
7763 header_field_info *hf_field;
7765 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
7767 DISSECTOR_ASSERT(hf_field->type == FT_BOOLEAN);
7769 CREATE_VALUE_STRING(dst, format, ap);
7771 return proto_tree_add_bits_format_value(tree, hfindex, tvb, bit_offset, no_of_bits, &value, dst);
7775 proto_check_field_name(const gchar *field_name)
7777 return wrs_check_charset(fld_abbrev_chars, field_name);
7781 tree_expanded(int tree_type)
7783 g_assert(tree_type >= 0 && tree_type < num_tree_types);
7784 return tree_is_expanded[tree_type >> 5] & (1 << (tree_type & 31));
7788 tree_expanded_set(int tree_type, gboolean value)
7790 g_assert(tree_type >= 0 && tree_type < num_tree_types);
7793 tree_is_expanded[tree_type >> 5] |= (1 << (tree_type & 31));
7795 tree_is_expanded[tree_type >> 5] &= ~(1 << (tree_type & 31));
7799 * Editor modelines - http://www.wireshark.org/tools/modelines.html
7804 * indent-tabs-mode: t
7807 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
7808 * :indentSize=8:tabSize=8:noTabs=false: