2 * Routines for protocol tree
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
36 #include "ptvcursor.h"
38 #include "addr_resolv.h"
42 #include "epan_dissect.h"
47 #include "asm_utils.h"
48 #include "column-utils.h"
51 #include "wspython/wspy_register.h"
53 #define SUBTREE_ONCE_ALLOCATION_NUMBER 8
54 #define SUBTREE_MAX_LEVELS 256
55 /* Throw an exception if we exceed this many tree items. */
56 /* XXX - This should probably be a preference */
57 #define MAX_TREE_ITEMS (1 * 1000 * 1000)
60 typedef struct __subtree_lvl {
67 subtree_lvl *pushed_tree;
68 guint8 pushed_tree_index;
69 guint8 pushed_tree_max;
75 /* Candidates for assembler */
77 wrs_count_bitshift(const guint32 bitmask)
81 while ((bitmask & (1 << bitshift)) == 0)
86 #define cVALS(x) (const value_string*)(x)
88 /** See inlined comments.
89 @param tree the tree to append this item to
90 @param hfindex field index
91 @param hfinfo header_field
92 @return the header field matching 'hfinfo' */
93 #define TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo) \
94 /* If this item is not referenced we dont have to do much work \
95 at all but we should still return a node so that \
96 field items below this node ( think proto_item_add_subtree() )\
97 will still have somewhere to attach to \
98 or else filtering will not work (they would be ignored since tree\
100 DONT try to fake a node where PTREE_FINFO(tree) is NULL \
101 since dissectors that want to do proto_item_set_len() or \
102 other operations that dereference this would crash. \
103 We fake FT_PROTOCOL unless some clients have requested us \
108 PTREE_DATA(tree)->count++; \
109 if (PTREE_DATA(tree)->count > MAX_TREE_ITEMS) { \
110 /* Let the exception handler add items to the tree */ \
111 PTREE_DATA(tree)->count = 0; \
112 THROW_MESSAGE(DissectorError, \
113 ep_strdup_printf("More than %d items in the tree -- possible infinite loop", MAX_TREE_ITEMS)); \
115 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo); \
116 if(!(PTREE_DATA(tree)->visible)){ \
117 if(PTREE_FINFO(tree)){ \
118 if((hfinfo->ref_type != HF_REF_TYPE_DIRECT) \
119 && (hfinfo->type!=FT_PROTOCOL || \
120 PTREE_DATA(tree)->fake_protocols)){ \
121 /* just return tree back to the caller */\
127 /** See inlined comments.
128 @param tree the tree to append this item to
129 @param pi the created protocol item we're about to return */
131 #define TRY_TO_FAKE_THIS_REPR(tree, pi) \
132 DISSECTOR_ASSERT(tree); \
133 if(!(PTREE_DATA(tree)->visible)) { \
134 /* If the tree (GUI) isn't visible it's pointless for us to generate the protocol \
135 * items string representation */ \
139 #define TRY_TO_FAKE_THIS_REPR(tree, pi)
143 proto_tree_free_node(proto_node *node, gpointer data);
145 static void fill_label_boolean(field_info *fi, gchar *label_str);
146 static void fill_label_uint(field_info *fi, gchar *label_str);
147 static void fill_label_uint64(field_info *fi, gchar *label_str);
148 static void fill_label_bitfield(field_info *fi, gchar *label_str);
149 static void fill_label_int(field_info *fi, gchar *label_str);
150 static void fill_label_int64(field_info *fi, gchar *label_str);
152 static const char* hfinfo_uint_vals_format(const header_field_info *hfinfo);
153 static const char* hfinfo_uint_format(const header_field_info *hfinfo);
154 static const char* hfinfo_uint_value_format(const header_field_info *hfinfo);
155 static const char* hfinfo_uint64_format(const header_field_info *hfinfo);
156 static const char* hfinfo_int_vals_format(const header_field_info *hfinfo);
157 static const char* hfinfo_int_format(const header_field_info *hfinfo);
158 static const char* hfinfo_int_value_format(const header_field_info *hfinfo);
159 static const char* hfinfo_int64_format(const header_field_info *hfinfo);
162 proto_tree_add_node(proto_tree *tree, field_info *fi);
164 static header_field_info *
165 get_hfi_and_length(int hfindex, tvbuff_t *tvb, const gint start, gint *length,
169 new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
170 const gint start, const gint item_length);
173 alloc_field_info(proto_tree *tree, int hfindex, tvbuff_t *tvb,
174 const gint start, gint *length);
177 proto_tree_add_pi(proto_tree *tree, int hfindex, tvbuff_t *tvb,
178 gint start, gint *length, field_info **pfi);
181 proto_tree_set_representation_value(proto_item *pi, const char *format, va_list ap);
183 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap);
186 proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb);
188 proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length);
190 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length);
192 proto_tree_set_time(field_info *fi, nstime_t *value_ptr);
194 proto_tree_set_string(field_info *fi, const char* value);
196 proto_tree_set_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
198 proto_tree_set_ebcdic_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
200 proto_tree_set_ether(field_info *fi, const guint8* value);
202 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start);
204 proto_tree_set_ipxnet(field_info *fi, guint32 value);
206 proto_tree_set_ipv4(field_info *fi, guint32 value);
208 proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr);
210 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
212 proto_tree_set_guid(field_info *fi, const e_guid_t *value_ptr);
214 proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, gint start, const guint encoding);
216 proto_tree_set_oid(field_info *fi, const guint8* value_ptr, gint length);
218 proto_tree_set_oid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
220 proto_tree_set_boolean(field_info *fi, guint32 value);
222 proto_tree_set_float(field_info *fi, float value);
224 proto_tree_set_double(field_info *fi, double value);
226 proto_tree_set_uint(field_info *fi, guint32 value);
228 proto_tree_set_int(field_info *fi, gint32 value);
230 proto_tree_set_uint64(field_info *fi, guint64 value);
232 proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start, guint length, const guint encoding);
234 proto_item_add_bitmask_tree(proto_item *item, tvbuff_t *tvb, const int offset,
235 const int len, const gint ett, const gint **fields,
236 const gboolean little_endian, const int flags,
239 static int proto_register_field_init(header_field_info *hfinfo, const int parent);
241 /* special-case header field used within proto.c */
242 int hf_text_only = -1;
244 /* Structure for information about a protocol */
246 const char *name; /* long description */
247 const char *short_name; /* short description */
248 const char *filter_name; /* name of this protocol in filters */
249 int proto_id; /* field ID for this protocol */
250 GList *fields; /* fields for this protocol */
251 GList *last_field; /* pointer to end of list of fields */
252 gboolean is_enabled; /* TRUE if protocol is enabled */
253 gboolean can_toggle; /* TRUE if is_enabled can be changed */
254 gboolean is_private; /* TRUE is protocol is private */
257 /* List of all protocols */
258 static GList *protocols = NULL;
260 #define INITIAL_NUM_PROTOCOL_HFINFO 1500
262 /* Contains information about protocols and header fields. Used when
263 * dissectors register their data */
264 #if GLIB_CHECK_VERSION(2,10,0)
266 static GMemChunk *gmc_hfinfo = NULL;
269 /* Contains information about a field when a dissector calls
270 * proto_tree_add_item. */
271 SLAB_ITEM_TYPE_DEFINE(field_info)
272 static SLAB_FREE_LIST_DEFINE(field_info)
273 static field_info *field_info_tmp=NULL;
274 #define FIELD_INFO_NEW(fi) \
275 SLAB_ALLOC(fi, field_info)
276 #define FIELD_INFO_FREE(fi) \
277 SLAB_FREE(fi, field_info)
279 /* Contains the space for proto_nodes. */
280 SLAB_ITEM_TYPE_DEFINE(proto_node)
281 static SLAB_FREE_LIST_DEFINE(proto_node)
282 #define PROTO_NODE_NEW(node) \
283 SLAB_ALLOC(node, proto_node) \
284 node->first_child = NULL; \
285 node->last_child = NULL; \
288 #define PROTO_NODE_FREE(node) \
289 SLAB_FREE(node, proto_node)
291 /* String space for protocol and field items for the GUI */
292 SLAB_ITEM_TYPE_DEFINE(item_label_t)
293 static SLAB_FREE_LIST_DEFINE(item_label_t)
294 #define ITEM_LABEL_NEW(il) \
295 SLAB_ALLOC(il, item_label_t)
296 #define ITEM_LABEL_FREE(il) \
297 SLAB_FREE(il, item_label_t)
299 #define PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo) \
300 DISSECTOR_ASSERT((guint)hfindex < gpa_hfinfo.len); \
301 hfinfo=gpa_hfinfo.hfi[hfindex];
303 /* List which stores protocols and fields that have been registered */
304 typedef struct _gpa_hfinfo_t {
306 guint32 allocated_len;
307 header_field_info **hfi;
309 gpa_hfinfo_t gpa_hfinfo;
311 /* Balanced tree of abbreviations and IDs */
312 static GTree *gpa_name_tree = NULL;
313 static header_field_info *same_name_hfinfo;
315 static void save_same_name_hfinfo(gpointer data)
317 same_name_hfinfo = (header_field_info*)data;
320 /* Points to the first element of an array of Booleans, indexed by
321 a subtree item type; that array element is TRUE if subtrees of
322 an item of that type are to be expanded. */
323 gboolean *tree_is_expanded;
325 /* Number of elements in that array. */
328 /* Name hashtables for fast detection of duplicate names */
329 static GHashTable* proto_names = NULL;
330 static GHashTable* proto_short_names = NULL;
331 static GHashTable* proto_filter_names = NULL;
334 proto_compare_name(gconstpointer p1_arg, gconstpointer p2_arg)
336 const protocol_t *p1 = p1_arg;
337 const protocol_t *p2 = p2_arg;
339 return g_ascii_strcasecmp(p1->short_name, p2->short_name);
343 /* initialize data structures and register protocols and fields */
345 proto_init(void (register_all_protocols_func)(register_cb cb, gpointer client_data),
346 void (register_all_handoffs_func)(register_cb cb, gpointer client_data),
348 gpointer client_data)
350 static hf_register_info hf[] = {
352 { "Text item", "text", FT_NONE, BASE_NONE, NULL, 0x0,
358 proto_names = g_hash_table_new_full(g_int_hash, g_int_equal, g_free, NULL);
359 proto_short_names = g_hash_table_new(wrs_str_hash, g_str_equal);
360 proto_filter_names = g_hash_table_new(wrs_str_hash, g_str_equal);
362 #if GLIB_CHECK_VERSION(2,10,0)
364 gmc_hfinfo = g_mem_chunk_new("gmc_hfinfo",
365 sizeof(header_field_info),
366 INITIAL_NUM_PROTOCOL_HFINFO * sizeof(header_field_info),
371 gpa_hfinfo.allocated_len=0;
373 gpa_name_tree = g_tree_new_full(wrs_strcmp_with_data, NULL, NULL, save_same_name_hfinfo);
375 /* Initialize the ftype subsystem */
378 /* Register one special-case FT_TEXT_ONLY field for use when
379 converting wireshark to new-style proto_tree. These fields
380 are merely strings on the GUI tree; they are not filterable */
381 proto_register_field_array(-1, hf, array_length(hf));
383 /* Have each built-in dissector register its protocols, fields,
384 dissector tables, and dissectors to be called through a
385 handle, and do whatever one-time initialization it needs to
387 register_all_protocols_func(cb, client_data);
389 /* Now scan for python protocols */
390 register_all_py_protocols_func(cb, client_data);
394 /* Now scan for plugins and load all the ones we find, calling
395 their register routines to do the stuff described above. */
397 (*cb)(RA_PLUGIN_REGISTER, NULL, client_data);
399 register_all_plugin_registrations();
402 /* Now call the "handoff registration" routines of all built-in
403 dissectors; those routines register the dissector in other
404 dissectors' handoff tables, and fetch any dissector handles
406 register_all_handoffs_func(cb, client_data);
409 /* Now do the same with python dissectors */
410 register_all_py_handoffs_func(cb, client_data);
414 /* Now do the same with plugins. */
416 (*cb)(RA_PLUGIN_HANDOFF, NULL, client_data);
417 register_all_plugin_handoffs();
420 /* sort the protocols by protocol name */
421 protocols = g_list_sort(protocols, proto_compare_name);
423 /* We've assigned all the subtree type values; allocate the array
424 for them, and zero it out. */
425 tree_is_expanded = g_new0(gboolean, num_tree_types);
431 /* Free the abbrev/ID GTree */
433 g_tree_destroy(gpa_name_tree);
434 gpa_name_tree = NULL;
438 protocol_t *protocol = protocols->data;
439 header_field_info *hfinfo;
440 PROTO_REGISTRAR_GET_NTH(protocol->proto_id, hfinfo);
441 DISSECTOR_ASSERT(protocol->proto_id == hfinfo->id);
443 #if GLIB_CHECK_VERSION(2,10,0)
444 g_slice_free(header_field_info, hfinfo);
446 g_mem_chunk_free(gmc_hfinfo, hfinfo);
449 g_list_free(protocol->fields);
450 protocols = g_list_remove(protocols, protocol);
455 g_hash_table_destroy(proto_names);
459 if (proto_short_names) {
460 g_hash_table_destroy(proto_short_names);
461 proto_short_names = NULL;
464 if (proto_filter_names) {
465 g_hash_table_destroy(proto_filter_names);
466 proto_filter_names = NULL;
469 #if GLIB_CHECK_VERSION(2,10,0)
472 g_mem_chunk_destroy(gmc_hfinfo);
477 if(gpa_hfinfo.allocated_len){
479 gpa_hfinfo.allocated_len=0;
480 g_free(gpa_hfinfo.hfi);
483 g_free(tree_is_expanded);
484 tree_is_expanded = NULL;
488 proto_tree_traverse_pre_order(proto_tree *tree, proto_tree_traverse_func func,
491 proto_node *pnode = tree;
495 if (func(pnode, data))
498 child = pnode->first_child;
499 while (child != NULL) {
501 * The routine we call might modify the child, e.g. by
502 * freeing it, so we get the child's successor before
503 * calling that routine.
506 child = current->next;
507 if (proto_tree_traverse_pre_order((proto_tree *)current, func,
516 proto_tree_traverse_post_order(proto_tree *tree, proto_tree_traverse_func func,
519 proto_node *pnode = tree;
523 child = pnode->first_child;
524 while (child != NULL) {
526 * The routine we call might modify the child, e.g. by
527 * freeing it, so we get the child's successor before
528 * calling that routine.
531 child = current->next;
532 if (proto_tree_traverse_post_order((proto_tree *)current, func,
536 if (func(pnode, data))
543 proto_tree_children_foreach(proto_tree *tree, proto_tree_foreach_func func,
546 proto_node *node = tree;
549 node = node->first_child;
550 while (node != NULL) {
552 node = current->next;
553 func((proto_tree *)current, data);
557 /* frees the resources that the dissection a proto_tree uses */
559 proto_tree_free(proto_tree *tree)
561 proto_tree_traverse_post_order(tree, proto_tree_free_node, NULL);
565 free_GPtrArray_value(gpointer key, gpointer value, gpointer user_data _U_)
567 GPtrArray *ptrs = value;
568 gint hfid = (gint)(long)key;
569 header_field_info *hfinfo;
571 PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
572 if(hfinfo->ref_type != HF_REF_TYPE_NONE) {
573 /* when a field is referenced by a filter this also
574 affects the refcount for the parent protocol so we need
575 to adjust the refcount for the parent as well
577 if( hfinfo->parent != -1 ) {
578 header_field_info *parent_hfinfo;
579 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
580 parent_hfinfo->ref_type = HF_REF_TYPE_NONE;
582 hfinfo->ref_type = HF_REF_TYPE_NONE;
585 g_ptr_array_free(ptrs, TRUE);
589 free_node_tree_data(tree_data_t *tree_data)
591 if (tree_data->interesting_hfids) {
592 /* Free all the GPtrArray's in the interesting_hfids hash. */
593 g_hash_table_foreach(tree_data->interesting_hfids,
594 free_GPtrArray_value, NULL);
596 /* And then destroy the hash. */
597 g_hash_table_destroy(tree_data->interesting_hfids);
600 /* And finally the tree_data_t itself. */
604 #define FREE_NODE_FIELD_INFO(finfo) \
606 ITEM_LABEL_FREE(finfo->rep); \
608 FVALUE_CLEANUP(&finfo->value); \
609 FIELD_INFO_FREE(finfo);
612 proto_tree_free_node(proto_node *node, gpointer data _U_)
614 field_info *finfo = PNODE_FINFO(node);
616 proto_node *parent = node->parent;
620 /* This is the root node. Destroy the per-tree data.
621 * There is no field_info to destroy. */
622 if (PTREE_DATA(node)) free_node_tree_data(PTREE_DATA(node));
625 /* This is a child node. Don't free the per-tree data, but
626 * do free the field_info data. */
627 FREE_NODE_FIELD_INFO(finfo);
631 /* NOTE: This code is required when this function is used to free individual
632 * nodes only. Current use is for the destruction of complete trees, so the
633 * inconsistancies have no ill effect.
635 /* Remove node from parent */
637 proto_item *prev_item = NULL;
638 if (parent->first_child == node) {
639 parent->first_child = node->next;
641 /* find previous and change its next */
642 for (prev_item = parent->first_child; prev_item; prev_item = prev_item->next) {
643 if (prev_item->next == node) {
647 DISSECTOR_ASSERT(prev_item);
648 prev_item->next = node->next;
650 /* fix last_child if required */
651 if (parent->last_child == node) {
652 parent->last_child = prev_item;
655 DISSECTOR_ASSERT(node->first_child == NULL && node->last_child == NULL);
657 /* Free the proto_node. */
658 PROTO_NODE_FREE(node);
660 return FALSE; /* FALSE = do not end traversal of protocol tree */
663 /* Is the parsing being done for a visible proto_tree or an invisible one?
664 * By setting this correctly, the proto_tree creation is sped up by not
665 * having to call g_vsnprintf and copy strings around.
668 proto_tree_set_visible(proto_tree *tree, gboolean visible)
670 gboolean old_visible = PTREE_DATA(tree)->visible;
672 PTREE_DATA(tree)->visible = visible;
678 proto_tree_set_fake_protocols(proto_tree *tree, gboolean fake_protocols)
680 PTREE_DATA(tree)->fake_protocols = fake_protocols;
683 /* Assume dissector set only its protocol fields.
684 This function is called by dissectors and allows the speeding up of filtering
685 in wireshark; if this function returns FALSE it is safe to reset tree to NULL
686 and thus skip calling most of the expensive proto_tree_add_...()
688 If the tree is visible we implicitly assume the field is referenced.
691 proto_field_is_referenced(proto_tree *tree, int proto_id)
693 register header_field_info *hfinfo;
699 if (PTREE_DATA(tree)->visible)
702 PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
703 if (hfinfo->ref_type != HF_REF_TYPE_NONE)
706 if (hfinfo->type == FT_PROTOCOL && !PTREE_DATA(tree)->fake_protocols)
713 /* Finds a record in the hf_info_records array by id. */
715 proto_registrar_get_nth(guint hfindex)
717 register header_field_info *hfinfo;
719 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
724 /* Prefix initialization
725 * this allows for a dissector to register a display filter name prefix
726 * so that it can delay the initialization of the hf array as long as
730 /* compute a hash for the part before the dot of a display filter */
732 prefix_hash (gconstpointer key) {
733 /* end the string at the dot and compute its hash */
734 gchar* copy = ep_strdup(key);
744 return g_str_hash(copy);
747 /* are both strings equal up to the end or the dot? */
749 prefix_equal (gconstpointer ap,gconstpointer bp) {
757 if ((ac == '.' || ac == '\0') && (bc == '.' || bc == '\0')) return TRUE;
759 if ( (ac == '.' || ac == '\0') && ! (bc == '.' || bc == '\0') ) return FALSE;
760 if ( (bc == '.' || bc == '\0') && ! (ac == '.' || ac == '\0') ) return FALSE;
762 if (ac != bc) return FALSE;
769 /* indexed by prefix, contains initializers */
770 static GHashTable* prefixes = NULL;
773 /* Register a new prefix for "delayed" initialization of field arrays */
775 proto_register_prefix(const char *prefix, prefix_initializer_t pi ) {
777 prefixes = g_hash_table_new(prefix_hash,prefix_equal);
780 g_hash_table_insert(prefixes,(gpointer)prefix,pi);
783 /* helper to call all prefix initializers */
785 initialize_prefix(gpointer k, gpointer v, gpointer u _U_) {
786 ((prefix_initializer_t)v)(k);
790 /** Initialize every remaining uninitialized prefix. */
792 proto_initialize_all_prefixes(void) {
793 g_hash_table_foreach_remove(prefixes, initialize_prefix, NULL);
796 /* Finds a record in the hf_info_records array by name.
797 * If it fails to find it in the already registered fields,
798 * it tries to find and call an initializer in the prefixes
799 * table and if so it looks again.
802 proto_registrar_get_byname(const char *field_name)
804 header_field_info* hfinfo;
805 prefix_initializer_t pi;
810 hfinfo = g_tree_lookup(gpa_name_tree, field_name);
812 if (hfinfo) return hfinfo;
814 if (!prefixes) return NULL;
816 if(( pi = g_hash_table_lookup(prefixes,field_name) )) {
818 g_hash_table_remove(prefixes,field_name);
823 return g_tree_lookup(gpa_name_tree, field_name);
828 ptvcursor_new_subtree_levels(ptvcursor_t * ptvc)
830 subtree_lvl * pushed_tree;
832 DISSECTOR_ASSERT(ptvc->pushed_tree_max <= SUBTREE_MAX_LEVELS-SUBTREE_ONCE_ALLOCATION_NUMBER);
833 ptvc->pushed_tree_max += SUBTREE_ONCE_ALLOCATION_NUMBER;
835 pushed_tree = ep_alloc(sizeof(subtree_lvl) * ptvc->pushed_tree_max);
836 DISSECTOR_ASSERT(pushed_tree != NULL);
837 if (ptvc->pushed_tree)
838 memcpy(pushed_tree, ptvc->pushed_tree, ptvc->pushed_tree_max - SUBTREE_ONCE_ALLOCATION_NUMBER);
839 ptvc->pushed_tree = pushed_tree;
843 ptvcursor_free_subtree_levels(ptvcursor_t * ptvc)
845 ptvc->pushed_tree = NULL;
846 ptvc->pushed_tree_max = 0;
847 DISSECTOR_ASSERT(ptvc->pushed_tree_index ==0);
848 ptvc->pushed_tree_index = 0;
851 /* Allocates an initializes a ptvcursor_t with 3 variables:
852 * proto_tree, tvbuff, and offset. */
854 ptvcursor_new(proto_tree *tree, tvbuff_t *tvb, gint offset)
858 ptvc = ep_alloc(sizeof(ptvcursor_t));
861 ptvc->offset = offset;
862 ptvc->pushed_tree= NULL;
863 ptvc->pushed_tree_max= 0;
864 ptvc->pushed_tree_index= 0;
869 /* Frees memory for ptvcursor_t, but nothing deeper than that. */
871 ptvcursor_free(ptvcursor_t *ptvc)
873 ptvcursor_free_subtree_levels(ptvc);
877 /* Returns tvbuff. */
879 ptvcursor_tvbuff(ptvcursor_t* ptvc)
884 /* Returns current offset. */
886 ptvcursor_current_offset(ptvcursor_t* ptvc)
892 ptvcursor_tree(ptvcursor_t* ptvc)
901 ptvcursor_set_tree(ptvcursor_t* ptvc, proto_tree *tree)
906 /* creates a subtree, sets it as the working tree and pushes the old working tree */
908 ptvcursor_push_subtree(ptvcursor_t *ptvc, proto_item *it, gint ett_subtree)
910 subtree_lvl * subtree;
911 if (ptvc->pushed_tree_index >= ptvc->pushed_tree_max)
912 ptvcursor_new_subtree_levels(ptvc);
914 subtree = ptvc->pushed_tree+ptvc->pushed_tree_index;
915 subtree->tree = ptvc->tree;
917 ptvc->pushed_tree_index++;
918 return ptvcursor_set_subtree(ptvc, it, ett_subtree);
923 ptvcursor_pop_subtree(ptvcursor_t *ptvc)
925 subtree_lvl * subtree;
926 if (ptvc->pushed_tree_index <= 0)
929 ptvc->pushed_tree_index--;
930 subtree = ptvc->pushed_tree+ptvc->pushed_tree_index;
931 if (subtree->it != NULL)
932 proto_item_set_len(subtree->it, ptvcursor_current_offset(ptvc) - subtree->cursor_offset);
934 ptvc->tree = subtree->tree;
937 /* saves the current tvb offset and the item in the current subtree level */
939 ptvcursor_subtree_set_item(ptvcursor_t * ptvc, proto_item * it)
941 subtree_lvl * subtree;
943 DISSECTOR_ASSERT(ptvc->pushed_tree_index > 0);
945 subtree = ptvc->pushed_tree+ptvc->pushed_tree_index-1;
947 subtree->cursor_offset = ptvcursor_current_offset(ptvc);
950 /* Creates a subtree and adds it to the cursor as the working tree but does not
951 * save the old working tree */
953 ptvcursor_set_subtree(ptvcursor_t *ptvc, proto_item *it, gint ett_subtree)
955 ptvc->tree = proto_item_add_subtree(it, ett_subtree);
960 ptvcursor_add_subtree_item(ptvcursor_t * ptvc, proto_item * it, gint ett_subtree, gint length)
962 ptvcursor_push_subtree(ptvc, it, ett_subtree);
963 if (length == SUBTREE_UNDEFINED_LENGTH)
964 ptvcursor_subtree_set_item(ptvc, it);
965 return ptvcursor_tree(ptvc);
968 /* Add an item to the tree and create a subtree
969 * If the length is unknown, length may be defined as SUBTREE_UNDEFINED_LENGTH.
970 * In this case, when the subtree will be closed, the parent item length will
971 * be equal to the advancement of the cursor since the creation of the subtree.
974 ptvcursor_add_with_subtree(ptvcursor_t * ptvc, int hfindex, gint length,
975 const guint encoding, gint ett_subtree)
979 it = ptvcursor_add_no_advance(ptvc, hfindex, length, encoding);
980 return ptvcursor_add_subtree_item(ptvc, it, ett_subtree, length);
984 proto_tree_add_text_node(proto_tree *tree, tvbuff_t *tvb, gint start, gint length);
986 /* Add a text node to the tree and create a subtree
987 * If the length is unknown, length may be defined as SUBTREE_UNDEFINED_LENGTH.
988 * In this case, when the subtree will be closed, the item length will be equal
989 * to the advancement of the cursor since the creation of the subtree.
992 ptvcursor_add_text_with_subtree(ptvcursor_t * ptvc, gint length,
993 gint ett_subtree, const char *format, ...)
997 header_field_info *hfinfo;
999 TRY_TO_FAKE_THIS_ITEM(ptvcursor_tree(ptvc), hf_text_only, hfinfo);
1001 it = proto_tree_add_text_node(ptvcursor_tree(ptvc), ptvcursor_tvbuff(ptvc),
1002 ptvcursor_current_offset(ptvc), length);
1007 va_start(ap, format);
1008 proto_tree_set_representation(it, format, ap);
1011 return ptvcursor_add_subtree_item(ptvc, it, ett_subtree, length);
1014 /* Add a text-only node, leaving it to our caller to fill the text in */
1016 proto_tree_add_text_node(proto_tree *tree, tvbuff_t *tvb, gint start, gint length)
1020 pi = proto_tree_add_pi(tree, hf_text_only, tvb, start, &length, NULL);
1027 /* Add a text-only node to the proto_tree */
1029 proto_tree_add_text(proto_tree *tree, tvbuff_t *tvb, gint start, gint length,
1030 const char *format, ...)
1034 header_field_info *hfinfo;
1036 TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
1038 pi = proto_tree_add_text_node(tree, tvb, start, length);
1042 TRY_TO_FAKE_THIS_REPR(tree, pi);
1044 va_start(ap, format);
1045 proto_tree_set_representation(pi, format, ap);
1051 /* Add a text-only node to the proto_tree (va_list version) */
1053 proto_tree_add_text_valist(proto_tree *tree, tvbuff_t *tvb, gint start,
1054 gint length, const char *format, va_list ap)
1057 header_field_info *hfinfo;
1059 TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
1061 pi = proto_tree_add_text_node(tree, tvb, start, length);
1065 TRY_TO_FAKE_THIS_REPR(tree, pi);
1067 proto_tree_set_representation(pi, format, ap);
1072 /* Add a text-only node for debugging purposes. The caller doesn't need
1073 * to worry about tvbuff, start, or length. Debug message gets sent to
1076 proto_tree_add_debug_text(proto_tree *tree, const char *format, ...)
1081 pi = proto_tree_add_text_node(tree, NULL, 0, 0);
1084 va_start(ap, format);
1085 proto_tree_set_representation(pi, format, ap);
1088 va_start(ap, format);
1089 vprintf(format, ap);
1097 * NOTE: to support code written when proto_tree_add_item() took a
1098 * gboolean as its last argument, with FALSE meaning "big-endian"
1099 * and TRUE meaning "little-endian", we treat any non-zero value of
1100 * "encoding" as meaning "little-endian".
1103 get_uint_value(tvbuff_t *tvb, gint offset, gint length, const guint encoding)
1110 value = tvb_get_guint8(tvb, offset);
1114 value = encoding ? tvb_get_letohs(tvb, offset)
1115 : tvb_get_ntohs(tvb, offset);
1119 value = encoding ? tvb_get_letoh24(tvb, offset)
1120 : tvb_get_ntoh24(tvb, offset);
1124 value = encoding ? tvb_get_letohl(tvb, offset)
1125 : tvb_get_ntohl(tvb, offset);
1129 DISSECTOR_ASSERT_NOT_REACHED();
1137 * NOTE: to support code written when proto_tree_add_item() took a
1138 * gboolean as its last argument, with FALSE meaning "big-endian"
1139 * and TRUE meaning "little-endian", we treat any non-zero value of
1140 * "encoding" as meaning "little-endian".
1143 get_int_value(tvbuff_t *tvb, gint offset, gint length, const guint encoding)
1150 value = (gint8)tvb_get_guint8(tvb, offset);
1154 value = (gint16) (encoding ? tvb_get_letohs(tvb, offset)
1155 : tvb_get_ntohs(tvb, offset));
1159 value = encoding ? tvb_get_letoh24(tvb, offset)
1160 : tvb_get_ntoh24(tvb, offset);
1161 if (value & 0x00800000) {
1162 /* Sign bit is set; sign-extend it. */
1163 value |= 0xFF000000;
1168 value = encoding ? tvb_get_letohl(tvb, offset)
1169 : tvb_get_ntohl(tvb, offset);
1173 DISSECTOR_ASSERT_NOT_REACHED();
1181 proto_lookup_or_create_interesting_hfids(proto_tree *tree,
1182 header_field_info *hfinfo)
1184 GPtrArray *ptrs = NULL;
1186 DISSECTOR_ASSERT(tree);
1187 DISSECTOR_ASSERT(hfinfo);
1189 if (hfinfo->ref_type == HF_REF_TYPE_DIRECT) {
1190 if (PTREE_DATA(tree)->interesting_hfids == NULL) {
1191 /* Initialize the hash because we now know that it is needed */
1192 PTREE_DATA(tree)->interesting_hfids =
1193 g_hash_table_new(g_direct_hash, NULL /* g_direct_equal */);
1196 ptrs = g_hash_table_lookup(PTREE_DATA(tree)->interesting_hfids,
1197 GINT_TO_POINTER(hfinfo->id));
1199 /* First element triggers the creation of pointer array */
1200 ptrs = g_ptr_array_new();
1201 g_hash_table_insert(PTREE_DATA(tree)->interesting_hfids,
1202 GINT_TO_POINTER(hfinfo->id), ptrs);
1209 /* Add an item to a proto_tree, using the text label registered to that item;
1210 the item is extracted from the tvbuff handed to it. */
1212 proto_tree_new_item(field_info *new_fi, proto_tree *tree,
1213 tvbuff_t *tvb, gint start, gint length,
1214 const guint encoding)
1221 nstime_t time_stamp;
1224 /* there is a possibility here that we might raise an exception
1225 * and thus would lose track of the field_info.
1226 * store it in a temp so that if we come here again we can reclaim
1227 * the field_info without leaking memory.
1229 /* XXX this only keeps track of one field_info struct,
1230 if we ever go multithreaded for calls to this function
1231 we have to change this code to use per thread variable.
1234 /* oops, last one we got must have been lost due
1236 * good thing we saved it, now we can reverse the
1237 * memory leak and reclaim it.
1239 SLAB_FREE(field_info_tmp, field_info);
1241 /* we might throw an exception, keep track of this one
1242 * across the "dangerous" section below.
1244 field_info_tmp=new_fi;
1246 switch(new_fi->hfinfo->type) {
1248 /* no value to set for FT_NONE */
1252 proto_tree_set_protocol_tvb(new_fi, tvb);
1256 proto_tree_set_bytes_tvb(new_fi, tvb, start, length);
1260 n = get_uint_value(tvb, start, length, encoding);
1261 proto_tree_set_bytes_tvb(new_fi, tvb, start + length, n);
1263 /* Instead of calling proto_item_set_len(), since we don't yet
1264 * have a proto_item, we set the field_info's length ourselves. */
1265 new_fi->length = n + length;
1269 proto_tree_set_boolean(new_fi,
1270 get_uint_value(tvb, start, length, encoding));
1273 /* XXX - make these just FT_UINT? */
1278 proto_tree_set_uint(new_fi,
1279 get_uint_value(tvb, start, length, encoding));
1284 DISSECTOR_ASSERT( length <= 8 && length >= 1);
1285 proto_tree_set_uint64_tvb(new_fi, tvb, start, length, encoding);
1288 /* XXX - make these just FT_INT? */
1293 proto_tree_set_int(new_fi,
1294 get_int_value(tvb, start, length, encoding));
1298 DISSECTOR_ASSERT(length == FT_IPv4_LEN);
1299 value = tvb_get_ipv4(tvb, start);
1301 * NOTE: to support code written when
1302 * proto_tree_add_item() took a gboolean as its
1303 * last argument, with FALSE meaning "big-endian"
1304 * and TRUE meaning "little-endian", we treat any
1305 * non-zero value of "encoding" as meaning
1308 proto_tree_set_ipv4(new_fi, encoding ? GUINT32_SWAP_LE_BE(value) : value);
1312 DISSECTOR_ASSERT(length == FT_IPXNET_LEN);
1313 proto_tree_set_ipxnet(new_fi,
1314 get_uint_value(tvb, start, 4, FALSE));
1318 DISSECTOR_ASSERT(length >=0 && length <= FT_IPv6_LEN);
1319 proto_tree_set_ipv6_tvb(new_fi, tvb, start, length);
1323 DISSECTOR_ASSERT(length == FT_ETHER_LEN);
1324 proto_tree_set_ether_tvb(new_fi, tvb, start);
1328 DISSECTOR_ASSERT(length == FT_GUID_LEN);
1329 proto_tree_set_guid_tvb(new_fi, tvb, start, encoding);
1333 proto_tree_set_oid_tvb(new_fi, tvb, start, length);
1337 DISSECTOR_ASSERT(length == 4);
1339 * NOTE: to support code written when
1340 * proto_tree_add_item() took a gboolean as its
1341 * last argument, with FALSE meaning "big-endian"
1342 * and TRUE meaning "little-endian", we treat any
1343 * non-zero value of "encoding" as meaning
1346 * At some point in the future, we might
1347 * support non-IEEE-binary floating-point
1348 * formats in the encoding as well
1349 * (IEEE decimal, System/3x0, VAX).
1352 floatval = tvb_get_letohieee_float(tvb, start);
1354 floatval = tvb_get_ntohieee_float(tvb, start);
1355 proto_tree_set_float(new_fi, floatval);
1360 * NOTE: to support code written when
1361 * proto_tree_add_item() took a gboolean as its
1362 * last argument, with FALSE meaning "big-endian"
1363 * and TRUE meaning "little-endian", we treat any
1364 * non-zero value of "encoding" as meaning
1367 * At some point in the future, we might
1368 * support non-IEEE-binary floating-point
1369 * formats in the encoding as well
1370 * (IEEE decimal, System/3x0, VAX).
1372 DISSECTOR_ASSERT(length == 8);
1374 doubleval = tvb_get_letohieee_double(tvb, start);
1376 doubleval = tvb_get_ntohieee_double(tvb, start);
1377 proto_tree_set_double(new_fi, doubleval);
1381 proto_tree_set_string_tvb(new_fi, tvb, start, length);
1385 DISSECTOR_ASSERT(length >= -1);
1386 /* Instead of calling proto_item_set_len(),
1387 * since we don't yet have a proto_item, we
1388 * set the field_info's length ourselves.
1390 * XXX - our caller can't use that length to
1391 * advance an offset unless they arrange that
1392 * there always be a protocol tree into which
1393 * we're putting this item.
1396 /* This can throw an exception */
1397 length = tvb_strsize(tvb, start);
1399 string = ep_alloc(length);
1401 tvb_memcpy(tvb, string, start, length);
1402 } else if (length == 0) {
1405 /* In this case, length signifies
1406 * the length of the string.
1408 * This could either be a null-padded
1409 * string, which doesn't necessarily
1410 * have a '\0' at the end, or a
1411 * null-terminated string, with a
1412 * trailing '\0'. (Yes, there are
1413 * cases where you have a string
1414 * that's both counted and null-
1417 * In the first case, we must
1418 * allocate a buffer of length
1419 * "length+1", to make room for
1422 * In the second case, we don't
1423 * assume that there is a trailing
1424 * '\0' there, as the packet might
1425 * be malformed. (XXX - should we
1426 * throw an exception if there's no
1427 * trailing '\0'?) Therefore, we
1428 * allocate a buffer of length
1429 * "length+1", and put in a trailing
1430 * '\0', just to be safe.
1432 * (XXX - this would change if
1433 * we made string values counted
1434 * rather than null-terminated.)
1436 string = tvb_get_ephemeral_string(tvb,
1440 new_fi->length = length;
1441 proto_tree_set_string(new_fi, string);
1445 proto_tree_set_ebcdic_string_tvb(new_fi, tvb, start, length);
1448 case FT_UINT_STRING:
1449 n = get_uint_value(tvb, start, length, encoding);
1450 proto_tree_set_string_tvb(new_fi, tvb, start + length, n);
1452 /* Instead of calling proto_item_set_len(), since we
1453 * don't yet have a proto_item, we set the
1454 * field_info's length ourselves.
1456 * XXX - our caller can't use that length to
1457 * advance an offset unless they arrange that
1458 * there always be a protocol tree into which
1459 * we're putting this item.
1461 new_fi->length = n + length;
1464 case FT_ABSOLUTE_TIME:
1465 case FT_RELATIVE_TIME:
1466 DISSECTOR_ASSERT(length == 8);
1468 * NOTE: to support code written when
1469 * proto_tree_add_item() took a gboolean as its
1470 * last argument, with FALSE meaning "big-endian"
1471 * and TRUE meaning "little-endian", we treat any
1472 * non-zero value of "encoding" as meaning
1475 * At some point in the future, we might
1476 * support non-struct timespec formats in
1477 * the encoding as well (struct timeval,
1478 * NTP time, Windows NT FILETIME, time_t, etc.).
1481 time_stamp.secs = tvb_get_letohl(tvb, start);
1482 time_stamp.nsecs = tvb_get_letohl(tvb, start+4);
1484 time_stamp.secs = tvb_get_ntohl(tvb, start);
1485 time_stamp.nsecs = tvb_get_ntohl(tvb, start+4);
1487 proto_tree_set_time(new_fi, &time_stamp);
1491 g_error("new_fi->hfinfo->type %d (%s) not handled\n",
1492 new_fi->hfinfo->type,
1493 ftype_name(new_fi->hfinfo->type));
1494 DISSECTOR_ASSERT_NOT_REACHED();
1498 * XXX - this should just check the ENC_*_ENDIAN bit, with
1499 * those fields for which we treat any non-zero value of
1500 * "encoding" checking the rest of the bits.
1502 FI_SET_FLAG(new_fi, (encoding) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN);
1504 /* Don't add new node to proto_tree until now so that any exceptions
1505 * raised by a tvbuff access method doesn't leave junk in the proto_tree. */
1506 pi = proto_tree_add_node(tree, new_fi);
1508 /* we did not raise an exception so we dont have to remember this
1509 * field_info struct any more.
1511 field_info_tmp=NULL;
1513 /* If the proto_tree wants to keep a record of this finfo
1514 * for quick lookup, then record it. */
1515 ptrs = proto_lookup_or_create_interesting_hfids(tree, new_fi->hfinfo);
1517 g_ptr_array_add(ptrs, new_fi);
1522 /* Gets data from tvbuff, adds it to proto_tree, increments offset,
1523 and returns proto_item* */
1525 ptvcursor_add(ptvcursor_t *ptvc, int hfindex, gint length,
1526 const guint encoding)
1529 header_field_info *hfinfo;
1534 /* We can't fake it just yet. We have to advance the cursor
1535 TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfindex, hfinfo); */
1537 offset = ptvc->offset;
1538 hfinfo = get_hfi_and_length(hfindex, ptvc->tvb, offset, &length,
1540 ptvc->offset += length;
1541 if (hfinfo->type == FT_UINT_BYTES || hfinfo->type == FT_UINT_STRING) {
1543 * The length of the rest of the item is in the first N
1544 * bytes of the item.
1546 n = get_uint_value(ptvc->tvb, offset, length, encoding);
1550 /* Coast clear. Try and fake it */
1551 TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfindex, hfinfo);
1553 new_fi = new_field_info(ptvc->tree, hfinfo, ptvc->tvb, offset, item_length);
1557 return proto_tree_new_item(new_fi, ptvc->tree, ptvc->tvb,
1558 offset, length, encoding);
1561 /* Add an item to a proto_tree, using the text label registered to that item;
1562 the item is extracted from the tvbuff handed to it. */
1564 proto_tree_add_item(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
1565 const gint start, gint length, const guint encoding)
1568 header_field_info *hfinfo;
1570 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1572 new_fi = alloc_field_info(tree, hfindex, tvb, start, &length);
1577 return proto_tree_new_item(new_fi, tree, tvb, start,
1581 /* Add a FT_NONE to a proto_tree */
1583 proto_tree_add_none_format(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
1584 const gint start, gint length, const char *format,
1589 header_field_info *hfinfo;
1591 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1593 DISSECTOR_ASSERT(hfinfo->type == FT_NONE);
1595 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, NULL);
1597 TRY_TO_FAKE_THIS_REPR(tree, pi);
1599 va_start(ap, format);
1600 proto_tree_set_representation(pi, format, ap);
1603 /* no value to set for FT_NONE */
1607 /* Gets data from tvbuff, adds it to proto_tree, *DOES NOT* increment
1608 * offset, and returns proto_item* */
1610 ptvcursor_add_no_advance(ptvcursor_t* ptvc, int hf, gint length,
1611 const guint encoding)
1615 item = proto_tree_add_item(ptvc->tree, hf, ptvc->tvb, ptvc->offset,
1621 /* Advance the ptvcursor's offset within its tvbuff without
1622 * adding anything to the proto_tree. */
1624 ptvcursor_advance(ptvcursor_t* ptvc, gint length)
1626 ptvc->offset += length;
1631 proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb)
1633 fvalue_set(&fi->value, tvb, TRUE);
1636 /* Add a FT_PROTOCOL to a proto_tree */
1638 proto_tree_add_protocol_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1639 gint start, gint length, const char *format, ...)
1644 header_field_info *hfinfo;
1646 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1648 DISSECTOR_ASSERT(hfinfo->type == FT_PROTOCOL);
1650 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1652 proto_tree_set_protocol_tvb(new_fi, (start == 0 ? tvb : tvb_new_subset(tvb, start, length, length)));
1654 TRY_TO_FAKE_THIS_REPR(tree, pi);
1656 va_start(ap, format);
1657 proto_tree_set_representation(pi, format, ap);
1664 /* Add a FT_BYTES to a proto_tree */
1666 proto_tree_add_bytes(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1667 gint length, const guint8 *start_ptr)
1671 header_field_info *hfinfo;
1673 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1675 DISSECTOR_ASSERT(hfinfo->type == FT_BYTES);
1677 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1678 proto_tree_set_bytes(new_fi, start_ptr, length);
1684 proto_tree_add_bytes_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1685 gint start, gint length,
1686 const guint8 *start_ptr,
1687 const char *format, ...)
1691 header_field_info *hfinfo;
1693 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1695 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length, start_ptr);
1699 TRY_TO_FAKE_THIS_REPR(tree, pi);
1701 va_start(ap, format);
1702 proto_tree_set_representation_value(pi, format, ap);
1709 proto_tree_add_bytes_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1710 gint start, gint length, const guint8 *start_ptr,
1711 const char *format, ...)
1715 header_field_info *hfinfo;
1717 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1719 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length, start_ptr);
1723 TRY_TO_FAKE_THIS_REPR(tree, pi);
1725 va_start(ap, format);
1726 proto_tree_set_representation(pi, format, ap);
1733 proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length)
1737 bytes = g_byte_array_new();
1739 g_byte_array_append(bytes, start_ptr, length);
1741 fvalue_set(&fi->value, bytes, TRUE);
1746 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length)
1748 proto_tree_set_bytes(fi, tvb_get_ptr(tvb, offset, length), length);
1751 /* Add a FT_*TIME to a proto_tree */
1753 proto_tree_add_time(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1754 gint length, nstime_t *value_ptr)
1758 header_field_info *hfinfo;
1760 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1762 DISSECTOR_ASSERT(hfinfo->type == FT_ABSOLUTE_TIME ||
1763 hfinfo->type == FT_RELATIVE_TIME);
1765 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1766 proto_tree_set_time(new_fi, value_ptr);
1772 proto_tree_add_time_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1773 gint start, gint length, nstime_t *value_ptr,
1774 const char *format, ...)
1778 header_field_info *hfinfo;
1780 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1782 pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
1786 TRY_TO_FAKE_THIS_REPR(tree, pi);
1788 va_start(ap, format);
1789 proto_tree_set_representation_value(pi, format, ap);
1796 proto_tree_add_time_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1797 gint start, gint length, nstime_t *value_ptr,
1798 const char *format, ...)
1802 header_field_info *hfinfo;
1804 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1806 pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
1810 TRY_TO_FAKE_THIS_REPR(tree, pi);
1812 va_start(ap, format);
1813 proto_tree_set_representation(pi, format, ap);
1819 /* Set the FT_*TIME value */
1821 proto_tree_set_time(field_info *fi, nstime_t *value_ptr)
1823 DISSECTOR_ASSERT(value_ptr != NULL);
1825 fvalue_set(&fi->value, value_ptr, FALSE);
1828 /* Add a FT_IPXNET to a proto_tree */
1830 proto_tree_add_ipxnet(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1831 gint length, guint32 value)
1835 header_field_info *hfinfo;
1837 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1839 DISSECTOR_ASSERT(hfinfo->type == FT_IPXNET);
1841 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1842 proto_tree_set_ipxnet(new_fi, value);
1848 proto_tree_add_ipxnet_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1849 gint start, gint length, guint32 value,
1850 const char *format, ...)
1854 header_field_info *hfinfo;
1856 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1858 pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
1862 TRY_TO_FAKE_THIS_REPR(tree, pi);
1864 va_start(ap, format);
1865 proto_tree_set_representation_value(pi, format, ap);
1872 proto_tree_add_ipxnet_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1873 gint start, gint length, guint32 value,
1874 const char *format, ...)
1878 header_field_info *hfinfo;
1880 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1882 pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
1886 TRY_TO_FAKE_THIS_REPR(tree, pi);
1888 va_start(ap, format);
1889 proto_tree_set_representation(pi, format, ap);
1895 /* Set the FT_IPXNET value */
1897 proto_tree_set_ipxnet(field_info *fi, guint32 value)
1899 fvalue_set_uinteger(&fi->value, value);
1902 /* Add a FT_IPv4 to a proto_tree */
1904 proto_tree_add_ipv4(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1905 gint length, guint32 value)
1909 header_field_info *hfinfo;
1911 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1913 DISSECTOR_ASSERT(hfinfo->type == FT_IPv4);
1915 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1916 proto_tree_set_ipv4(new_fi, value);
1922 proto_tree_add_ipv4_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1923 gint start, gint length, guint32 value,
1924 const char *format, ...)
1928 header_field_info *hfinfo;
1930 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1932 pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
1936 TRY_TO_FAKE_THIS_REPR(tree, pi);
1938 va_start(ap, format);
1939 proto_tree_set_representation_value(pi, format, ap);
1946 proto_tree_add_ipv4_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1947 gint start, gint length, guint32 value,
1948 const char *format, ...)
1952 header_field_info *hfinfo;
1954 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1956 pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
1960 TRY_TO_FAKE_THIS_REPR(tree, pi);
1962 va_start(ap, format);
1963 proto_tree_set_representation(pi, format, ap);
1969 /* Set the FT_IPv4 value */
1971 proto_tree_set_ipv4(field_info *fi, guint32 value)
1973 fvalue_set_uinteger(&fi->value, value);
1976 /* Add a FT_IPv6 to a proto_tree */
1978 proto_tree_add_ipv6(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1979 gint length, const guint8* value_ptr)
1983 header_field_info *hfinfo;
1985 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1987 DISSECTOR_ASSERT(hfinfo->type == FT_IPv6);
1989 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1990 proto_tree_set_ipv6(new_fi, value_ptr);
1996 proto_tree_add_ipv6_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1997 gint start, gint length,
1998 const guint8* value_ptr,
1999 const char *format, ...)
2003 header_field_info *hfinfo;
2005 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2007 pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
2011 TRY_TO_FAKE_THIS_REPR(tree, pi);
2013 va_start(ap, format);
2014 proto_tree_set_representation_value(pi, format, ap);
2021 proto_tree_add_ipv6_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2022 gint start, gint length, const guint8* value_ptr,
2023 const char *format, ...)
2027 header_field_info *hfinfo;
2029 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2031 pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
2035 TRY_TO_FAKE_THIS_REPR(tree, pi);
2037 va_start(ap, format);
2038 proto_tree_set_representation(pi, format, ap);
2044 /* Set the FT_IPv6 value */
2046 proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr)
2048 DISSECTOR_ASSERT(value_ptr != NULL);
2049 fvalue_set(&fi->value, (gpointer) value_ptr, FALSE);
2053 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
2055 proto_tree_set_ipv6(fi, tvb_get_ptr(tvb, start, length));
2058 /* Add a FT_GUID to a proto_tree */
2060 proto_tree_add_guid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2061 gint length, const e_guid_t *value_ptr)
2065 header_field_info *hfinfo;
2067 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2069 DISSECTOR_ASSERT(hfinfo->type == FT_GUID);
2071 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2072 proto_tree_set_guid(new_fi, value_ptr);
2078 proto_tree_add_guid_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2079 gint start, gint length,
2080 const e_guid_t *value_ptr,
2081 const char *format, ...)
2085 header_field_info *hfinfo;
2087 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2089 pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
2093 TRY_TO_FAKE_THIS_REPR(tree, pi);
2095 va_start(ap, format);
2096 proto_tree_set_representation_value(pi, format, ap);
2103 proto_tree_add_guid_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2104 gint start, gint length, const e_guid_t *value_ptr,
2105 const char *format, ...)
2109 header_field_info *hfinfo;
2111 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2113 pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
2117 TRY_TO_FAKE_THIS_REPR(tree, pi);
2119 va_start(ap, format);
2120 proto_tree_set_representation(pi, format, ap);
2126 /* Set the FT_GUID value */
2128 proto_tree_set_guid(field_info *fi, const e_guid_t *value_ptr)
2130 DISSECTOR_ASSERT(value_ptr != NULL);
2131 fvalue_set(&fi->value, (gpointer) value_ptr, FALSE);
2135 proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, gint start,
2136 const guint encoding)
2140 tvb_get_guid(tvb, start, &guid, encoding);
2141 proto_tree_set_guid(fi, &guid);
2144 /* Add a FT_OID to a proto_tree */
2146 proto_tree_add_oid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2147 gint length, const guint8* value_ptr)
2151 header_field_info *hfinfo;
2153 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2155 DISSECTOR_ASSERT(hfinfo->type == FT_OID);
2157 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2158 proto_tree_set_oid(new_fi, value_ptr, length);
2164 proto_tree_add_oid_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2165 gint start, gint length,
2166 const guint8* value_ptr,
2167 const char *format, ...)
2171 header_field_info *hfinfo;
2173 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2175 pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
2179 TRY_TO_FAKE_THIS_REPR(tree, pi);
2181 va_start(ap, format);
2182 proto_tree_set_representation_value(pi, format, ap);
2189 proto_tree_add_oid_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2190 gint start, gint length, const guint8* value_ptr,
2191 const char *format, ...)
2195 header_field_info *hfinfo;
2197 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2199 pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
2203 TRY_TO_FAKE_THIS_REPR(tree, pi);
2205 va_start(ap, format);
2206 proto_tree_set_representation(pi, format, ap);
2212 /* Set the FT_OID value */
2214 proto_tree_set_oid(field_info *fi, const guint8* value_ptr, gint length)
2218 DISSECTOR_ASSERT(value_ptr != NULL);
2220 bytes = g_byte_array_new();
2222 g_byte_array_append(bytes, value_ptr, length);
2224 fvalue_set(&fi->value, bytes, TRUE);
2228 proto_tree_set_oid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
2230 proto_tree_set_oid(fi, tvb_get_ptr(tvb, start, length), length);
2234 proto_tree_set_uint64(field_info *fi, guint64 value)
2236 fvalue_set_integer64(&fi->value, value);
2240 * NOTE: to support code written when proto_tree_add_item() took a
2241 * gboolean as its last argument, with FALSE meaning "big-endian"
2242 * and TRUE meaning "little-endian", we treat any non-zero value of
2243 * "encoding" as meaning "little-endian".
2246 proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start,
2247 guint length, const guint encoding)
2250 guint8* b = ep_tvb_memdup(tvb,start,length);
2255 default: DISSECTOR_ASSERT_NOT_REACHED();
2256 case 8: value <<= 8; value += *--b;
2257 case 7: value <<= 8; value += *--b;
2258 case 6: value <<= 8; value += *--b;
2259 case 5: value <<= 8; value += *--b;
2260 case 4: value <<= 8; value += *--b;
2261 case 3: value <<= 8; value += *--b;
2262 case 2: value <<= 8; value += *--b;
2263 case 1: value <<= 8; value += *--b;
2268 default: DISSECTOR_ASSERT_NOT_REACHED();
2269 case 8: value <<= 8; value += *b++;
2270 case 7: value <<= 8; value += *b++;
2271 case 6: value <<= 8; value += *b++;
2272 case 5: value <<= 8; value += *b++;
2273 case 4: value <<= 8; value += *b++;
2274 case 3: value <<= 8; value += *b++;
2275 case 2: value <<= 8; value += *b++;
2276 case 1: value <<= 8; value += *b++;
2281 proto_tree_set_uint64(fi, value);
2284 /* Add a FT_STRING or FT_STRINGZ to a proto_tree. Creates own copy of string,
2285 * and frees it when the proto_tree is destroyed. */
2287 proto_tree_add_string(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2288 gint length, const char* value)
2292 header_field_info *hfinfo;
2294 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2296 DISSECTOR_ASSERT(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ);
2298 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2299 DISSECTOR_ASSERT(length >= 0);
2300 proto_tree_set_string(new_fi, value);
2306 proto_tree_add_string_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2307 gint start, gint length, const char* value,
2313 header_field_info *hfinfo;
2315 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2317 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
2321 TRY_TO_FAKE_THIS_REPR(tree, pi);
2323 va_start(ap, format);
2324 proto_tree_set_representation_value(pi, format, ap);
2331 proto_tree_add_string_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2332 gint start, gint length, const char* value,
2333 const char *format, ...)
2337 header_field_info *hfinfo;
2339 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2341 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
2345 TRY_TO_FAKE_THIS_REPR(tree, pi);
2347 va_start(ap, format);
2348 proto_tree_set_representation(pi, format, ap);
2354 /* Appends string data to a FT_STRING or FT_STRINGZ, allowing progressive
2355 * field info update instead of only updating the representation as does
2356 * proto_item_append_text()
2358 /* NOTE: this function will break with the TRY_TO_FAKE_THIS_ITEM()
2359 * speed optimization.
2360 * Currently only WSP use this function so it is not that bad but try to
2361 * avoid using this one if possible.
2362 * IF you must use this function you MUST also disable the
2363 * TRY_TO_FAKE_THIS_ITEM() optimization for your dissector/function
2364 * using proto_item_append_string().
2365 * Do that by faking that the tree is visible by calling
2366 * proto_tree_set_visible(tree, TRUE) (see packet-wsp.c)
2367 * BEFORE you create the item you are later going to use
2368 * proto_item_append_string() on.
2371 proto_item_append_string(proto_item *pi, const char *str)
2374 header_field_info *hfinfo;
2375 gchar *old_str, *new_str;
2382 fi = PITEM_FINFO(pi);
2383 DISSECTOR_ASSERT(fi && "proto_tree_set_visible(tree, TRUE) should have been called previously");
2385 hfinfo = fi->hfinfo;
2386 if (hfinfo->type == FT_PROTOCOL) {
2387 /* TRY_TO_FAKE_THIS_ITEM() speed optimization: silently skip */
2390 DISSECTOR_ASSERT(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ);
2391 old_str = fvalue_get(&fi->value);
2392 new_str = ep_strdup_printf("%s%s", old_str, str);
2393 fvalue_set(&fi->value, new_str, FALSE);
2396 /* Set the FT_STRING value */
2398 proto_tree_set_string(field_info *fi, const char* value)
2401 fvalue_set(&fi->value, (gpointer) value, FALSE);
2403 fvalue_set(&fi->value, (gpointer) "[ Null ]", FALSE);
2408 proto_tree_set_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
2413 length = tvb_ensure_length_remaining(tvb, start);
2416 string = tvb_get_ephemeral_string(tvb, start, length);
2417 proto_tree_set_string(fi, string);
2421 proto_tree_set_ebcdic_string_tvb(field_info *fi, tvbuff_t *tvb, gint start,
2427 length = tvb_ensure_length_remaining(tvb, start);
2430 string = tvb_get_ephemeral_string(tvb, start, length);
2431 EBCDIC_to_ASCII(string, length);
2432 proto_tree_set_string(fi, string);
2435 /* Add a FT_ETHER to a proto_tree */
2437 proto_tree_add_ether(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2438 gint length, const guint8* value)
2442 header_field_info *hfinfo;
2444 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2446 DISSECTOR_ASSERT(hfinfo->type == FT_ETHER);
2448 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2449 proto_tree_set_ether(new_fi, value);
2455 proto_tree_add_ether_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2456 gint start, gint length, const guint8* value,
2457 const char *format, ...)
2461 header_field_info *hfinfo;
2463 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2465 pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
2469 TRY_TO_FAKE_THIS_REPR(tree, pi);
2471 va_start(ap, format);
2472 proto_tree_set_representation_value(pi, format, ap);
2479 proto_tree_add_ether_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2480 gint start, gint length, const guint8* value,
2481 const char *format, ...)
2485 header_field_info *hfinfo;
2487 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2489 pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
2493 TRY_TO_FAKE_THIS_REPR(tree, pi);
2495 va_start(ap, format);
2496 proto_tree_set_representation(pi, format, ap);
2502 /* Set the FT_ETHER value */
2504 proto_tree_set_ether(field_info *fi, const guint8* value)
2506 fvalue_set(&fi->value, (gpointer) value, FALSE);
2510 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start)
2512 proto_tree_set_ether(fi, tvb_get_ptr(tvb, start, FT_ETHER_LEN));
2515 /* Add a FT_BOOLEAN to a proto_tree */
2517 proto_tree_add_boolean(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2518 gint length, guint32 value)
2522 header_field_info *hfinfo;
2524 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2526 DISSECTOR_ASSERT(hfinfo->type == FT_BOOLEAN);
2528 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2529 proto_tree_set_boolean(new_fi, value);
2535 proto_tree_add_boolean_format_value(proto_tree *tree, int hfindex,
2536 tvbuff_t *tvb, gint start, gint length,
2537 guint32 value, const char *format, ...)
2541 header_field_info *hfinfo;
2543 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2545 pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
2549 TRY_TO_FAKE_THIS_REPR(tree, pi);
2551 va_start(ap, format);
2552 proto_tree_set_representation_value(pi, format, ap);
2559 proto_tree_add_boolean_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2560 gint start, gint length, guint32 value,
2561 const char *format, ...)
2565 header_field_info *hfinfo;
2567 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2569 pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
2573 TRY_TO_FAKE_THIS_REPR(tree, pi);
2575 va_start(ap, format);
2576 proto_tree_set_representation(pi, format, ap);
2582 /* Set the FT_BOOLEAN value */
2584 proto_tree_set_boolean(field_info *fi, guint32 value)
2586 proto_tree_set_uint(fi, value);
2589 /* Add a FT_FLOAT to a proto_tree */
2591 proto_tree_add_float(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2592 gint length, float value)
2596 header_field_info *hfinfo;
2598 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2600 DISSECTOR_ASSERT(hfinfo->type == FT_FLOAT);
2602 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2603 proto_tree_set_float(new_fi, value);
2609 proto_tree_add_float_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2610 gint start, gint length, float value,
2611 const char *format, ...)
2615 header_field_info *hfinfo;
2617 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2619 pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
2623 TRY_TO_FAKE_THIS_REPR(tree, pi);
2625 va_start(ap, format);
2626 proto_tree_set_representation_value(pi, format, ap);
2633 proto_tree_add_float_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2634 gint start, gint length, float value,
2635 const char *format, ...)
2639 header_field_info *hfinfo;
2641 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2643 pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
2647 TRY_TO_FAKE_THIS_REPR(tree, pi);
2649 va_start(ap, format);
2650 proto_tree_set_representation(pi, format, ap);
2656 /* Set the FT_FLOAT value */
2658 proto_tree_set_float(field_info *fi, float value)
2660 fvalue_set_floating(&fi->value, value);
2663 /* Add a FT_DOUBLE to a proto_tree */
2665 proto_tree_add_double(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2666 gint length, double value)
2670 header_field_info *hfinfo;
2672 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2674 DISSECTOR_ASSERT(hfinfo->type == FT_DOUBLE);
2676 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2677 proto_tree_set_double(new_fi, value);
2683 proto_tree_add_double_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2684 gint start, gint length, double value,
2685 const char *format, ...)
2689 header_field_info *hfinfo;
2691 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2693 pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
2697 TRY_TO_FAKE_THIS_REPR(tree, pi);
2699 va_start(ap, format);
2700 proto_tree_set_representation_value(pi, format, ap);
2707 proto_tree_add_double_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2708 gint start, gint length, double value,
2709 const char *format, ...)
2713 header_field_info *hfinfo;
2715 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2717 pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
2721 TRY_TO_FAKE_THIS_REPR(tree, pi);
2723 va_start(ap, format);
2724 proto_tree_set_representation(pi, format, ap);
2730 /* Set the FT_DOUBLE value */
2732 proto_tree_set_double(field_info *fi, double value)
2734 fvalue_set_floating(&fi->value, value);
2737 /* Add FT_UINT{8,16,24,32} to a proto_tree */
2739 proto_tree_add_uint(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2740 gint length, guint32 value)
2742 proto_item *pi = NULL;
2744 header_field_info *hfinfo;
2746 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2748 switch(hfinfo->type) {
2754 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length,
2756 proto_tree_set_uint(new_fi, value);
2760 DISSECTOR_ASSERT_NOT_REACHED();
2767 proto_tree_add_uint_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2768 gint start, gint length, guint32 value,
2769 const char *format, ...)
2773 header_field_info *hfinfo;
2775 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2777 pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
2781 TRY_TO_FAKE_THIS_REPR(tree, pi);
2783 va_start(ap, format);
2784 proto_tree_set_representation_value(pi, format, ap);
2791 proto_tree_add_uint_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2792 gint start, gint length, guint32 value,
2793 const char *format, ...)
2797 header_field_info *hfinfo;
2799 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2801 pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
2805 TRY_TO_FAKE_THIS_REPR(tree, pi);
2807 va_start(ap, format);
2808 proto_tree_set_representation(pi, format, ap);
2814 /* Set the FT_UINT{8,16,24,32} value */
2816 proto_tree_set_uint(field_info *fi, guint32 value)
2818 header_field_info *hfinfo;
2821 hfinfo = fi->hfinfo;
2824 if (hfinfo->bitmask) {
2825 /* Mask out irrelevant portions */
2826 integer &= hfinfo->bitmask;
2829 if (hfinfo->bitshift > 0) {
2830 integer >>= hfinfo->bitshift;
2834 fvalue_set_uinteger(&fi->value, integer);
2837 /* Add FT_UINT64 to a proto_tree */
2839 proto_tree_add_uint64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2840 gint length, guint64 value)
2842 proto_item *pi = NULL;
2844 header_field_info *hfinfo;
2846 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2848 DISSECTOR_ASSERT(hfinfo->type == FT_UINT64);
2850 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2851 proto_tree_set_uint64(new_fi, value);
2857 proto_tree_add_uint64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2858 gint start, gint length, guint64 value,
2859 const char *format, ...)
2863 header_field_info *hfinfo;
2865 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2867 pi = proto_tree_add_uint64(tree, hfindex, tvb, start, length, value);
2871 TRY_TO_FAKE_THIS_REPR(tree, pi);
2873 va_start(ap, format);
2874 proto_tree_set_representation_value(pi, format, ap);
2881 proto_tree_add_uint64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2882 gint start, gint length, guint64 value,
2883 const char *format, ...)
2887 header_field_info *hfinfo;
2889 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2891 pi = proto_tree_add_uint64(tree, hfindex, tvb, start, length, value);
2895 TRY_TO_FAKE_THIS_REPR(tree, pi);
2897 va_start(ap, format);
2898 proto_tree_set_representation(pi, format, ap);
2904 /* Add FT_INT{8,16,24,32} to a proto_tree */
2906 proto_tree_add_int(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2907 gint length, gint32 value)
2909 proto_item *pi = NULL;
2911 header_field_info *hfinfo;
2913 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2915 switch(hfinfo->type) {
2920 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length,
2922 proto_tree_set_int(new_fi, value);
2926 DISSECTOR_ASSERT_NOT_REACHED();
2933 proto_tree_add_int_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2934 gint start, gint length, gint32 value,
2935 const char *format, ...)
2937 proto_item *pi = NULL;
2939 header_field_info *hfinfo;
2941 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2943 pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
2947 TRY_TO_FAKE_THIS_REPR(tree, pi);
2949 va_start(ap, format);
2950 proto_tree_set_representation_value(pi, format, ap);
2957 proto_tree_add_int_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2958 gint start, gint length, gint32 value,
2959 const char *format, ...)
2961 proto_item *pi = NULL;
2963 header_field_info *hfinfo;
2965 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2967 pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
2971 TRY_TO_FAKE_THIS_REPR(tree, pi);
2973 va_start(ap, format);
2974 proto_tree_set_representation(pi, format, ap);
2980 /* Set the FT_INT{8,16,24,32} value */
2982 proto_tree_set_int(field_info *fi, gint32 value)
2984 header_field_info *hfinfo;
2987 hfinfo = fi->hfinfo;
2988 integer = (guint32) value;
2990 if (hfinfo->bitmask) {
2991 /* Mask out irrelevant portions */
2992 integer &= hfinfo->bitmask;
2995 if (hfinfo->bitshift > 0) {
2996 integer >>= hfinfo->bitshift;
3000 fvalue_set_sinteger(&fi->value, integer);
3003 /* Add FT_INT64 to a proto_tree */
3005 proto_tree_add_int64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3006 gint length, gint64 value)
3008 proto_item *pi = NULL;
3010 header_field_info *hfinfo;
3012 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3014 DISSECTOR_ASSERT(hfinfo->type == FT_INT64);
3016 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
3017 proto_tree_set_uint64(new_fi, (guint64)value);
3023 proto_tree_add_int64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3024 gint start, gint length, gint64 value,
3025 const char *format, ...)
3029 header_field_info *hfinfo;
3031 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3033 pi = proto_tree_add_int64(tree, hfindex, tvb, start, length, value);
3037 TRY_TO_FAKE_THIS_REPR(tree, pi);
3039 va_start(ap, format);
3040 proto_tree_set_representation_value(pi, format, ap);
3047 proto_tree_add_int64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3048 gint start, gint length, gint64 value,
3049 const char *format, ...)
3053 header_field_info *hfinfo;
3055 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3057 pi = proto_tree_add_int64(tree, hfindex, tvb, start, length, value);
3061 TRY_TO_FAKE_THIS_REPR(tree, pi);
3063 va_start(ap, format);
3064 proto_tree_set_representation(pi, format, ap);
3070 /* Add a field_info struct to the proto_tree, encapsulating it in a proto_node */
3072 proto_tree_add_node(proto_tree *tree, field_info *fi)
3074 proto_node *pnode, *tnode, *sibling;
3078 * Make sure "tree" is ready to have subtrees under it, by
3079 * checking whether it's been given an ett_ value.
3081 * "PNODE_FINFO(tnode)" may be null; that's the case for the root
3082 * node of the protocol tree. That node is not displayed,
3083 * so it doesn't need an ett_ value to remember whether it
3087 tfi = PNODE_FINFO(tnode);
3088 if (tfi != NULL && (tfi->tree_type < 0 || tfi->tree_type >= num_tree_types)) {
3089 REPORT_DISSECTOR_BUG(ep_strdup_printf("\"%s\" - \"%s\" tfi->tree_type: %u invalid (%s:%u)",
3090 fi->hfinfo->name, fi->hfinfo->abbrev, tfi->tree_type, __FILE__, __LINE__));
3091 /* XXX - is it safe to continue here? */
3094 DISSECTOR_ASSERT(tfi == NULL ||
3095 (tfi->tree_type >= 0 && tfi->tree_type < num_tree_types));
3097 PROTO_NODE_NEW(pnode);
3098 pnode->parent = tnode;
3099 PNODE_FINFO(pnode) = fi;
3100 pnode->tree_data = PTREE_DATA(tree);
3102 if (tnode->last_child != NULL) {
3103 sibling = tnode->last_child;
3104 DISSECTOR_ASSERT(sibling->next == NULL);
3105 sibling->next = pnode;
3107 tnode->first_child = pnode;
3108 tnode->last_child = pnode;
3110 return (proto_item*)pnode;
3114 /* Generic way to allocate field_info and add to proto_tree.
3115 * Sets *pfi to address of newly-allocated field_info struct, if pfi is
3118 proto_tree_add_pi(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3119 gint *length, field_info **pfi)
3128 fi = alloc_field_info(tree, hfindex, tvb, start, length);
3129 pi = proto_tree_add_node(tree, fi);
3131 /* If the proto_tree wants to keep a record of this finfo
3132 * for quick lookup, then record it. */
3133 ptrs = proto_lookup_or_create_interesting_hfids(tree, fi->hfinfo);
3135 g_ptr_array_add(ptrs, fi);
3137 /* Does the caller want to know the fi pointer? */
3146 static header_field_info *
3147 get_hfi_and_length(int hfindex, tvbuff_t *tvb, const gint start, gint *length,
3150 header_field_info *hfinfo;
3151 gint length_remaining;
3154 * We only allow a null tvbuff if the item has a zero length,
3155 * i.e. if there's no data backing it.
3157 DISSECTOR_ASSERT(tvb != NULL || *length == 0);
3159 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
3162 * XXX - in some protocols, there are 32-bit unsigned length
3163 * fields, so lengths in protocol tree and tvbuff routines
3164 * should really be unsigned. We should have, for those
3165 * field types for which "to the end of the tvbuff" makes sense,
3166 * additional routines that take no length argument and
3167 * add fields that run to the end of the tvbuff.
3169 if (*length == -1) {
3171 * For FT_NONE, FT_PROTOCOL, FT_BYTES, and FT_STRING fields,
3172 * a length of -1 means "set the length to what remains in
3175 * The assumption is either that
3177 * 1) the length of the item can only be determined
3178 * by dissection (typically true of items with
3179 * subitems, which are probably FT_NONE or
3184 * 2) if the tvbuff is "short" (either due to a short
3185 * snapshot length or due to lack of reassembly of
3186 * fragments/segments/whatever), we want to display
3187 * what's available in the field (probably FT_BYTES
3188 * or FT_STRING) and then throw an exception later
3192 * 3) the field is defined to be "what's left in the
3195 * so we set the length to what remains in the tvbuff so
3196 * that, if we throw an exception while dissecting, it
3197 * has what is probably the right value.
3199 * For FT_STRINGZ, it means "the string is null-terminated,
3200 * not null-padded; set the length to the actual length
3201 * of the string", and if the tvbuff if short, we just
3202 * throw an exception.
3204 * It's not valid for any other type of field.
3206 switch (hfinfo->type) {
3210 * We allow this to be zero-length - for
3211 * example, an ONC RPC NULL procedure has
3212 * neither arguments nor reply, so the
3213 * payload for that protocol is empty.
3215 * However, if the length is negative, the
3216 * start offset is *past* the byte past the
3217 * end of the tvbuff, so we throw an
3220 *length = tvb_length_remaining(tvb, start);
3223 * Use "tvb_ensure_bytes_exist()"
3224 * to force the appropriate exception
3227 tvb_ensure_bytes_exist(tvb, start, 0);
3229 DISSECTOR_ASSERT(*length >= 0);
3235 *length = tvb_ensure_length_remaining(tvb, start);
3236 DISSECTOR_ASSERT(*length >= 0);
3241 * Leave the length as -1, so our caller knows
3247 DISSECTOR_ASSERT_NOT_REACHED();
3249 *item_length = *length;
3251 *item_length = *length;
3252 if (hfinfo->type == FT_PROTOCOL || hfinfo->type == FT_NONE) {
3254 * These types are for interior nodes of the
3255 * tree, and don't have data associated with
3256 * them; if the length is negative (XXX - see
3257 * above) or goes past the end of the tvbuff,
3258 * cut it short at the end of the tvbuff.
3259 * That way, if this field is selected in
3260 * Wireshark, we don't highlight stuff past
3261 * the end of the data.
3263 /* XXX - what to do, if we don't have a tvb? */
3265 length_remaining = tvb_length_remaining(tvb, start);
3266 if (*item_length < 0 ||
3267 (*item_length > 0 &&
3268 (length_remaining < *item_length)))
3269 *item_length = length_remaining;
3272 if (*item_length < 0) {
3273 THROW(ReportedBoundsError);
3281 new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
3282 const gint start, const gint item_length)
3288 fi->hfinfo = hfinfo;
3290 fi->start+=(tvb)?TVB_RAW_OFFSET(tvb):0;
3291 fi->length = item_length;
3294 if (!PTREE_DATA(tree)->visible)
3295 FI_SET_FLAG(fi, FI_HIDDEN);
3296 fvalue_init(&fi->value, fi->hfinfo->type);
3299 /* add the data source tvbuff */
3300 fi->ds_tvb=tvb?TVB_GET_DS_TVB(tvb):NULL;
3302 fi->appendix_start = 0;
3303 fi->appendix_length = 0;
3309 alloc_field_info(proto_tree *tree, int hfindex, tvbuff_t *tvb, const gint start,
3312 header_field_info *hfinfo;
3315 hfinfo = get_hfi_and_length(hfindex, tvb, start, length, &item_length);
3316 return new_field_info(tree, hfinfo, tvb, start, item_length);
3319 /* If the protocol tree is to be visible, set the representation of a
3320 proto_tree entry with the name of the field for the item and with
3321 the value formatted with the supplied printf-style format and
3324 proto_tree_set_representation_value(proto_item *pi, const char *format, va_list ap)
3326 int ret; /*tmp return value */
3327 field_info *fi = PITEM_FINFO(pi);
3328 header_field_info *hf;
3330 DISSECTOR_ASSERT(fi);
3334 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
3335 ITEM_LABEL_NEW(fi->rep);
3336 if (hf->bitmask && (hf->type == FT_BOOLEAN || IS_FT_UINT(hf->type))) {
3340 val = fvalue_get_uinteger(&fi->value);
3341 if (hf->bitshift > 0) {
3342 val <<= hf->bitshift;
3344 decode_bitfield_value(tmpbuf, val, hf->bitmask, hfinfo_bitwidth(hf));
3345 /* put in the hf name */
3346 ret = g_snprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
3347 "%s%s: ", tmpbuf, fi->hfinfo->name);
3349 /* put in the hf name */
3350 ret = g_snprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
3351 "%s: ", fi->hfinfo->name);
3354 /* If possible, Put in the value of the string */
3355 if (ret < ITEM_LABEL_LENGTH) {
3356 ret += g_vsnprintf(fi->rep->representation + ret,
3357 ITEM_LABEL_LENGTH - ret, format, ap);
3359 if (ret >= ITEM_LABEL_LENGTH) {
3360 /* Uh oh, we don't have enough room. Tell the user
3361 * that the field is truncated.
3365 /* Argh, we cannot reuse 'ap' here. So make a copy
3366 * of what we formatted for (re)use below.
3368 oldrep = g_strdup(fi->rep->representation);
3370 g_snprintf(fi->rep->representation,
3379 /* If the protocol tree is to be visible, set the representation of a
3380 proto_tree entry with the representation formatted with the supplied
3381 printf-style format and argument list. */
3383 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap)
3385 int ret; /*tmp return value */
3386 field_info *fi = PITEM_FINFO(pi);
3388 DISSECTOR_ASSERT(fi);
3390 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
3391 ITEM_LABEL_NEW(fi->rep);
3392 ret = g_vsnprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
3394 if (ret >= ITEM_LABEL_LENGTH) {
3395 /* Uh oh, we don't have enough room. Tell the user
3396 * that the field is truncated.
3400 /* Argh, we cannot reuse 'ap' here. So make a copy
3401 * of what we formatted for (re)use below.
3403 oldrep = g_strdup(fi->rep->representation);
3405 g_snprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
3406 "[truncated] %s", oldrep);
3412 /* -------------------------- */
3414 proto_custom_set(proto_tree* tree, const int field_id, gchar *result,
3415 gchar *expr, const int size)
3421 struct e_in6_addr *ipv6;
3423 guint32 n_addr; /* network-order IPv4 address */
3425 const true_false_string *tfstring;
3429 header_field_info* hfinfo;
3431 g_assert(field_id >= 0);
3433 hfinfo = proto_registrar_get_nth((guint)field_id);
3435 /* do we need to rewind ? */
3440 finfos = proto_get_finfo_ptr_array(tree, hfinfo->id);
3442 if (!finfos || !(len = g_ptr_array_len(finfos))) {
3443 hfinfo = hfinfo->same_name_next;
3446 /* get the last one */
3447 finfo = g_ptr_array_index(finfos, len -1);
3449 switch(hfinfo->type) {
3451 case FT_NONE: /* Nothing to add */
3456 g_strlcpy(result, "Yes", size);
3461 bytes = fvalue_get(&finfo->value);
3462 g_strlcpy(result, bytes_to_str(bytes, fvalue_length(&finfo->value)), size);
3465 case FT_ABSOLUTE_TIME:
3467 abs_time_to_str(fvalue_get(&finfo->value), hfinfo->display, TRUE),
3471 case FT_RELATIVE_TIME:
3472 g_strlcpy(result, rel_time_to_secs_str(fvalue_get(&finfo->value)), size);
3476 u_integer = fvalue_get_uinteger(&finfo->value);
3477 tfstring = (const true_false_string *)&tfs_true_false;
3478 if (hfinfo->strings) {
3479 tfstring = (const struct true_false_string*) hfinfo->strings;
3481 g_strlcpy(result, u_integer ? tfstring->true_string : tfstring->false_string, size);
3489 u_integer = fvalue_get_uinteger(&finfo->value);
3490 if (hfinfo->strings) {
3491 if (hfinfo->display & BASE_RANGE_STRING) {
3492 g_strlcpy(result, rval_to_str(u_integer, hfinfo->strings, "%u"), size);
3493 } else if (hfinfo->display & BASE_EXT_STRING) {
3494 g_strlcpy(result, val_to_str_ext(u_integer, (value_string_ext *) (hfinfo->strings), "%u"), size);
3496 g_strlcpy(result, val_to_str(u_integer, cVALS(hfinfo->strings), "%u"), size);
3498 } else if (IS_BASE_DUAL(hfinfo->display)) {
3499 g_snprintf(result, size, hfinfo_uint_value_format(hfinfo), u_integer, u_integer);
3501 g_snprintf(result, size, hfinfo_uint_value_format(hfinfo), u_integer);
3507 g_snprintf(result, size, "%" G_GINT64_MODIFIER "u", fvalue_get_integer64(&finfo->value));
3510 /* XXX - make these just FT_INT? */
3515 integer = fvalue_get_sinteger(&finfo->value);
3516 if (hfinfo->strings) {
3517 if (hfinfo->display & BASE_RANGE_STRING) {
3518 g_strlcpy(result, rval_to_str(integer, hfinfo->strings, "%d"), size);
3519 } else if (hfinfo->display & BASE_EXT_STRING) {
3520 g_strlcpy(result, val_to_str_ext(integer, (value_string_ext *) (hfinfo->strings), "%d"), size);
3522 g_strlcpy(result, val_to_str(integer, cVALS(hfinfo->strings), "%d"), size);
3524 } else if (IS_BASE_DUAL(hfinfo->display)) {
3525 g_snprintf(result, size, hfinfo_int_value_format(hfinfo), integer, integer);
3527 g_snprintf(result, size, hfinfo_int_value_format(hfinfo), integer);
3532 ipv4 = fvalue_get(&finfo->value);
3533 n_addr = ipv4_get_net_order_addr(ipv4);
3534 g_strlcpy(result, ip_to_str((guint8 *)&n_addr), size);
3538 ipv6 = fvalue_get(&finfo->value);
3539 SET_ADDRESS (&addr, AT_IPv6, sizeof(struct e_in6_addr), ipv6);
3540 address_to_str_buf(&addr, result, size);
3544 g_strlcpy(result, bytes_to_str_punct(fvalue_get(&finfo->value), 6, ':'), size);
3548 g_strlcpy(result, guid_to_str((e_guid_t *)fvalue_get(&finfo->value)), size);
3552 bytes = fvalue_get(&finfo->value);
3553 g_strlcpy(result, oid_resolved_from_encoded(bytes, fvalue_length(&finfo->value)), size);
3557 g_snprintf(result, size, "%." STRINGIFY(FLT_DIG) "f", fvalue_get_floating(&finfo->value));
3561 g_snprintf(result, size, "%." STRINGIFY(DBL_DIG) "g", fvalue_get_floating(&finfo->value));
3567 case FT_UINT_STRING:
3568 bytes = fvalue_get(&finfo->value);
3569 g_strlcpy(result, format_text(bytes, strlen(bytes)), size);
3572 case FT_IPXNET: /*XXX really No column custom ?*/
3575 g_error("hfinfo->type %d (%s) not handled\n",
3577 ftype_name(hfinfo->type));
3578 DISSECTOR_ASSERT_NOT_REACHED();
3582 switch(hfinfo->type) {
3586 case FT_UINT_STRING:
3587 g_snprintf(expr, size, "\"%s\"",result);
3589 g_strlcpy(expr, result, size);
3592 return hfinfo->abbrev;
3598 /* Set text of proto_item after having already been created. */
3600 proto_item_set_text(proto_item *pi, const char *format, ...)
3602 field_info *fi = NULL;
3609 fi = PITEM_FINFO(pi);
3614 ITEM_LABEL_FREE(fi->rep);
3617 va_start(ap, format);
3618 proto_tree_set_representation(pi, format, ap);
3622 /* Append to text of proto_item after having already been created. */
3624 proto_item_append_text(proto_item *pi, const char *format, ...)
3626 field_info *fi = NULL;
3634 fi = PITEM_FINFO(pi);
3639 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
3641 * If we don't already have a representation,
3642 * generate the default representation.
3644 if (fi->rep == NULL) {
3645 ITEM_LABEL_NEW(fi->rep);
3646 proto_item_fill_label(fi, fi->rep->representation);
3649 curlen = strlen(fi->rep->representation);
3650 if (ITEM_LABEL_LENGTH > curlen) {
3651 va_start(ap, format);
3652 g_vsnprintf(fi->rep->representation + curlen,
3653 ITEM_LABEL_LENGTH - (gulong) curlen, format, ap);
3660 proto_item_set_len(proto_item *pi, const gint length)
3667 fi = PITEM_FINFO(pi);
3671 DISSECTOR_ASSERT(length >= 0);
3672 fi->length = length;
3674 if (fi->value.ftype->ftype == FT_BYTES)
3675 fi->value.value.bytes->len = length;
3679 * Sets the length of the item based on its start and on the specified
3680 * offset, which is the offset past the end of the item; as the start
3681 * in the item is relative to the beginning of the data source tvbuff,
3682 * we need to pass in a tvbuff - the end offset is relative to the beginning
3686 proto_item_set_end(proto_item *pi, tvbuff_t *tvb, gint end)
3693 fi = PITEM_FINFO(pi);
3697 end += TVB_RAW_OFFSET(tvb);
3698 DISSECTOR_ASSERT(end >= fi->start);
3699 fi->length = end - fi->start;
3703 proto_item_get_len(const proto_item *pi)
3705 field_info *fi = PITEM_FINFO(pi);
3706 return fi ? fi->length : -1;
3710 /** clear flags according to the mask and set new flag values */
3711 #define FI_REPLACE_FLAGS(fi, mask, flags_in) { \
3712 (fi->flags = (fi)->flags & ~(mask)); \
3713 (fi->flags = (fi)->flags | (flags_in)); \
3717 proto_item_set_expert_flags(proto_item *pi, const int group, const guint severity)
3719 if(pi == NULL || PITEM_FINFO(pi) == NULL)
3722 /* only change things if severity is worse or at least equal than before */
3723 if(severity >= FI_GET_FLAG(PITEM_FINFO(pi), PI_SEVERITY_MASK)) {
3724 FI_REPLACE_FLAGS(PITEM_FINFO(pi), PI_GROUP_MASK, group);
3725 FI_REPLACE_FLAGS(PITEM_FINFO(pi), PI_SEVERITY_MASK, severity);
3734 proto_tree_create_root(void)
3738 /* Initialize the proto_node */
3739 PROTO_NODE_NEW(pnode);
3740 pnode->parent = NULL;
3741 PNODE_FINFO(pnode) = NULL;
3742 pnode->tree_data = g_new(tree_data_t, 1);
3744 /* Don't initialize the tree_data_t. Wait until we know we need it */
3745 pnode->tree_data->interesting_hfids = NULL;
3747 /* Set the default to FALSE so it's easier to
3748 * find errors; if we expect to see the protocol tree
3749 * but for some reason the default 'visible' is not
3750 * changed, then we'll find out very quickly. */
3751 pnode->tree_data->visible = FALSE;
3753 /* Make sure that we fake protocols (if possible) */
3754 pnode->tree_data->fake_protocols = TRUE;
3756 /* Keep track of the number of children */
3757 pnode->tree_data->count = 0;
3759 return (proto_tree*) pnode;
3763 /* "prime" a proto_tree with a single hfid that a dfilter
3764 * is interested in. */
3766 proto_tree_prime_hfid(proto_tree *tree _U_, const gint hfid)
3768 header_field_info *hfinfo;
3770 PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
3771 /* this field is referenced by a filter so increase the refcount.
3772 also increase the refcount for the parent, i.e the protocol.
3774 hfinfo->ref_type = HF_REF_TYPE_DIRECT;
3775 /* only increase the refcount if there is a parent.
3776 if this is a protocol and not a field then parent will be -1
3777 and there is no parent to add any refcounting for.
3779 if (hfinfo->parent != -1) {
3780 header_field_info *parent_hfinfo;
3781 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
3783 /* Mark parent as indirectly referenced unless it is already directly
3784 * referenced, i.e. the user has specified the parent in a filter.
3786 if (parent_hfinfo->ref_type != HF_REF_TYPE_DIRECT)
3787 parent_hfinfo->ref_type = HF_REF_TYPE_INDIRECT;
3792 proto_item_add_subtree(proto_item *pi, const gint idx) {
3798 DISSECTOR_ASSERT(idx >= 0 && idx < num_tree_types);
3800 fi = PITEM_FINFO(pi);
3802 return (proto_tree*) pi;
3804 fi->tree_type = idx;
3806 return (proto_tree*) pi;
3810 proto_item_get_subtree(const proto_item *pi) {
3815 fi = PITEM_FINFO(pi);
3816 if ( (!fi) || (fi->tree_type == -1) )
3818 return (proto_tree*) pi;
3822 proto_item_get_parent(const proto_item *ti) {
3829 proto_item_get_parent_nth(proto_item *ti, int gen) {
3842 proto_tree_get_parent(const proto_tree *tree) {
3845 return (proto_item*) tree;
3849 proto_tree_get_root(proto_tree *tree) {
3852 while (tree->parent) {
3853 tree = tree->parent;
3859 proto_tree_move_item(proto_tree *tree, proto_item *fixed_item,
3860 proto_item *item_to_move)
3862 DISSECTOR_ASSERT(item_to_move->parent == tree);
3863 DISSECTOR_ASSERT(fixed_item->parent == tree);
3865 /*** cut item_to_move out ***/
3867 /* is item_to_move the first? */
3868 if(tree->first_child == item_to_move) {
3869 /* simply change first child to next */
3870 tree->first_child = item_to_move->next;
3872 DISSECTOR_ASSERT(tree->last_child != item_to_move);
3874 proto_item *curr_item;
3875 /* find previous and change it's next */
3876 for(curr_item = tree->first_child; curr_item != NULL; curr_item = curr_item->next) {
3877 if(curr_item->next == item_to_move) {
3882 DISSECTOR_ASSERT(curr_item);
3884 curr_item->next = item_to_move->next;
3886 /* fix last_child if required */
3887 if(tree->last_child == item_to_move) {
3888 tree->last_child = curr_item;
3892 /*** insert to_move after fixed ***/
3893 item_to_move->next = fixed_item->next;
3894 fixed_item->next = item_to_move;
3895 if(tree->last_child == fixed_item) {
3896 tree->last_child = item_to_move;
3901 proto_tree_set_appendix(proto_tree *tree, tvbuff_t *tvb, gint start,
3909 fi = PTREE_FINFO(tree);
3913 start += TVB_RAW_OFFSET(tvb);
3914 DISSECTOR_ASSERT(start >= 0);
3915 DISSECTOR_ASSERT(length >= 0);
3917 fi->appendix_start = start;
3918 fi->appendix_length = length;
3922 proto_register_protocol(const char *name, const char *short_name,
3923 const char *filter_name)
3925 protocol_t *protocol;
3926 header_field_info *hfinfo;
3928 char *existing_name;
3932 gboolean found_invalid;
3935 * Make sure there's not already a protocol with any of those
3936 * names. Crash if there is, as that's an error in the code
3937 * or an inappropriate plugin.
3938 * This situation has to be fixed to not register more than one
3939 * protocol with the same name.
3941 * This is done by reducing the number of strcmp (and alike) calls as much as possible,
3942 * as this significally slows down startup time.
3944 * Drawback: As a hash value is used to reduce insert time,
3945 * this might lead to a hash collision.
3946 * However, as we have around 500+ protocols and we're using a 32 bit int this is very,
3950 key = g_malloc (sizeof(gint));
3951 *key = wrs_str_hash(name);
3952 existing_name = g_hash_table_lookup(proto_names, key);
3953 if (existing_name != NULL) {
3954 /* g_error will terminate the program */
3955 g_error("Duplicate protocol name \"%s\"!"
3956 " This might be caused by an inappropriate plugin or a development error.", name);
3958 g_hash_table_insert(proto_names, key, (gpointer)name);
3960 existing_name = g_hash_table_lookup(proto_short_names, (gpointer)short_name);
3961 if (existing_name != NULL) {
3962 g_error("Duplicate protocol short_name \"%s\"!"
3963 " This might be caused by an inappropriate plugin or a development error.", short_name);
3965 g_hash_table_insert(proto_short_names, (gpointer)short_name, (gpointer)short_name);
3967 found_invalid = FALSE;
3968 for (i = 0; i < strlen(filter_name); i++) {
3970 if (!(islower(c) || isdigit(c) || c == '-' || c == '_' || c == '.')) {
3971 found_invalid = TRUE;
3974 if (found_invalid) {
3975 g_error("Protocol filter name \"%s\" has one or more invalid characters."
3976 " Allowed are lower characters, digits, '-', '_' and '.'."
3977 " This might be caused by an inappropriate plugin or a development error.", filter_name);
3979 existing_name = g_hash_table_lookup(proto_filter_names, (gpointer)filter_name);
3980 if (existing_name != NULL) {
3981 g_error("Duplicate protocol filter_name \"%s\"!"
3982 " This might be caused by an inappropriate plugin or a development error.", filter_name);
3984 g_hash_table_insert(proto_filter_names, (gpointer)filter_name, (gpointer)filter_name);
3986 /* Add this protocol to the list of known protocols; the list
3987 is sorted by protocol short name. */
3988 protocol = g_new(protocol_t, 1);
3989 protocol->name = name;
3990 protocol->short_name = short_name;
3991 protocol->filter_name = filter_name;
3992 protocol->fields = NULL;
3993 protocol->is_enabled = TRUE; /* protocol is enabled by default */
3994 protocol->can_toggle = TRUE;
3995 protocol->is_private = FALSE;
3996 /* list will be sorted later by name, when all protocols completed registering */
3997 protocols = g_list_prepend(protocols, protocol);
3999 /* Here we do allocate a new header_field_info struct */
4000 #if GLIB_CHECK_VERSION(2,10,0)
4001 hfinfo = g_slice_new(header_field_info);
4003 hfinfo = g_mem_chunk_alloc(gmc_hfinfo);
4005 hfinfo->name = name;
4006 hfinfo->abbrev = filter_name;
4007 hfinfo->type = FT_PROTOCOL;
4008 hfinfo->display = BASE_NONE;
4009 hfinfo->strings = protocol;
4010 hfinfo->bitmask = 0;
4011 hfinfo->bitshift = 0;
4012 hfinfo->ref_type = HF_REF_TYPE_NONE;
4013 hfinfo->blurb = NULL;
4014 hfinfo->parent = -1; /* this field differentiates protos and fields */
4016 proto_id = proto_register_field_init(hfinfo, hfinfo->parent);
4017 protocol->proto_id = proto_id;
4022 proto_mark_private(const int proto_id)
4024 protocol_t *protocol = find_protocol_by_id(proto_id);
4026 protocol->is_private = TRUE;
4030 proto_is_private(const int proto_id)
4032 protocol_t *protocol = find_protocol_by_id(proto_id);
4034 return protocol->is_private;
4040 * Routines to use to iterate over the protocols.
4041 * The argument passed to the iterator routines is an opaque cookie to
4042 * their callers; it's the GList pointer for the current element in
4044 * The ID of the protocol is returned, or -1 if there is no protocol.
4047 proto_get_first_protocol(void **cookie)
4049 protocol_t *protocol;
4051 if (protocols == NULL)
4053 *cookie = protocols;
4054 protocol = protocols->data;
4055 return protocol->proto_id;
4059 proto_get_next_protocol(void **cookie)
4061 GList *list_item = *cookie;
4062 protocol_t *protocol;
4064 list_item = g_list_next(list_item);
4065 if (list_item == NULL)
4067 *cookie = list_item;
4068 protocol = list_item->data;
4069 return protocol->proto_id;
4073 proto_get_first_protocol_field(const int proto_id, void **cookie)
4075 protocol_t *protocol = find_protocol_by_id(proto_id);
4076 hf_register_info *ptr;
4078 if ((protocol == NULL) || (protocol->fields == NULL))
4081 *cookie = protocol->fields;
4082 ptr = protocol->fields->data;
4083 return &ptr->hfinfo;
4087 proto_get_next_protocol_field(void **cookie)
4089 GList *list_item = *cookie;
4090 hf_register_info *ptr;
4092 list_item = g_list_next(list_item);
4093 if (list_item == NULL)
4096 *cookie = list_item;
4097 ptr = list_item->data;
4098 return &ptr->hfinfo;
4102 find_protocol_by_id(const int proto_id)
4104 header_field_info *hfinfo;
4109 PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
4110 DISSECTOR_ASSERT(hfinfo->type==FT_PROTOCOL);
4111 return (protocol_t *)hfinfo->strings;
4114 static gint compare_filter_name(gconstpointer proto_arg,
4115 gconstpointer filter_name)
4117 const protocol_t *protocol = proto_arg;
4118 const gchar* f_name = filter_name;
4120 return (strcmp(protocol->filter_name, f_name));
4124 proto_get_id(const protocol_t *protocol)
4126 return protocol->proto_id;
4129 int proto_get_id_by_filter_name(const gchar* filter_name)
4132 protocol_t *protocol;
4134 list_entry = g_list_find_custom(protocols, filter_name,
4135 compare_filter_name);
4137 if (list_entry == NULL)
4139 protocol = list_entry->data;
4140 return protocol->proto_id;
4144 proto_get_protocol_name(const int proto_id)
4146 protocol_t *protocol;
4148 protocol = find_protocol_by_id(proto_id);
4149 return protocol->name;
4153 proto_get_protocol_short_name(const protocol_t *protocol)
4155 if (protocol == NULL)
4157 return protocol->short_name;
4161 proto_get_protocol_long_name(const protocol_t *protocol)
4163 if (protocol == NULL)
4165 return protocol->name;
4169 proto_get_protocol_filter_name(const int proto_id)
4171 protocol_t *protocol;
4173 protocol = find_protocol_by_id(proto_id);
4174 if (protocol == NULL)
4176 return protocol->filter_name;
4180 proto_is_protocol_enabled(const protocol_t *protocol)
4182 return protocol->is_enabled;
4186 proto_can_toggle_protocol(const int proto_id)
4188 protocol_t *protocol;
4190 protocol = find_protocol_by_id(proto_id);
4191 return protocol->can_toggle;
4195 proto_set_decoding(const int proto_id, const gboolean enabled)
4197 protocol_t *protocol;
4199 protocol = find_protocol_by_id(proto_id);
4200 DISSECTOR_ASSERT(protocol->can_toggle);
4201 protocol->is_enabled = enabled;
4205 proto_enable_all(void)
4207 protocol_t *protocol;
4208 GList *list_item = protocols;
4210 if (protocols == NULL)
4214 protocol = list_item->data;
4215 if (protocol->can_toggle)
4216 protocol->is_enabled = TRUE;
4217 list_item = g_list_next(list_item);
4222 proto_set_cant_toggle(const int proto_id)
4224 protocol_t *protocol;
4226 protocol = find_protocol_by_id(proto_id);
4227 protocol->can_toggle = FALSE;
4230 /* for use with static arrays only, since we don't allocate our own copies
4231 of the header_field_info struct contained within the hf_register_info struct */
4233 proto_register_field_array(const int parent, hf_register_info *hf, const int num_records)
4236 hf_register_info *ptr = hf;
4239 proto = find_protocol_by_id(parent);
4240 for (i = 0; i < num_records; i++, ptr++) {
4242 * Make sure we haven't registered this yet.
4243 * Most fields have variables associated with them
4244 * that are initialized to -1; some have array elements,
4245 * or possibly uninitialized variables, so we also allow
4246 * 0 (which is unlikely to be the field ID we get back
4247 * from "proto_register_field_init()").
4249 if (*ptr->p_id != -1 && *ptr->p_id != 0) {
4251 "Duplicate field detected in call to proto_register_field_array: %s is already registered\n",
4252 ptr->hfinfo.abbrev);
4256 if (proto != NULL) {
4257 if (proto->fields == NULL) {
4258 proto->fields = g_list_append(NULL, ptr);
4259 proto->last_field = proto->fields;
4262 g_list_append(proto->last_field, ptr)->next;
4265 field_id = proto_register_field_init(&ptr->hfinfo, parent);
4266 *ptr->p_id = field_id;
4270 /* chars allowed in field abbrev */
4272 const guchar fld_abbrev_chars[256] = {
4273 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00-0x0F */
4274 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10-0x1F */
4275 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, /* 0x20-0x2F '-', '.' */
4276 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 0x30-0x3F '0'-'9' */
4277 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x40-0x4F 'A'-'O' */
4278 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 0x50-0x5F 'P'-'Z', '_' */
4279 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x60-0x6F 'a'-'o' */
4280 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 0x70-0x7F 'p'-'z' */
4281 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80-0x8F */
4282 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90-0x9F */
4283 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xA0-0xAF */
4284 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xB0-0xBF */
4285 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xC0-0xCF */
4286 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xD0-0xDF */
4287 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xE0-0xEF */
4288 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xF0-0xFF */
4291 /* temporary function containing assert part for easier profiling */
4292 static void tmp_fld_check_assert(header_field_info *hfinfo) {
4293 static const value_string hf_types[] = {
4294 { FT_NONE, "FT_NONE" },
4295 { FT_PROTOCOL, "FT_PROTOCOL" },
4296 { FT_BOOLEAN, "FT_BOOLEAN" },
4297 { FT_UINT8, "FT_UINT8" },
4298 { FT_UINT16, "FT_UINT16" },
4299 { FT_UINT24, "FT_UINT24" },
4300 { FT_UINT32, "FT_UINT32" },
4301 { FT_UINT64, "FT_UINT64" },
4302 { FT_INT8, "FT_INT8" },
4303 { FT_INT16, "FT_INT16" },
4304 { FT_INT24, "FT_INT24" },
4305 { FT_INT32, "FT_INT32" },
4306 { FT_INT64, "FT_INT64" },
4307 { FT_FLOAT, "FT_FLOAT" },
4308 { FT_DOUBLE, "FT_DOUBLE" },
4309 { FT_ABSOLUTE_TIME, "FT_ABSOLUTE_TIME" },
4310 { FT_RELATIVE_TIME, "FT_RELATIVE_TIME" },
4311 { FT_STRING, "FT_STRING" },
4312 { FT_STRINGZ, "FT_STRINGZ" },
4313 { FT_EBCDIC, "FT_EBCDIC" },
4314 { FT_UINT_STRING, "FT_UINT_STRING" },
4315 { FT_ETHER, "FT_ETHER" },
4316 { FT_BYTES, "FT_BYTES" },
4317 { FT_UINT_BYTES, "FT_UINT_BYTES" },
4318 { FT_IPv4, "FT_IPv4" },
4319 { FT_IPv6, "FT_IPv6" },
4320 { FT_IPXNET, "FT_IPXNET" },
4321 { FT_FRAMENUM, "FT_FRAMENUM" },
4322 { FT_PCRE, "FT_PCR" },
4323 { FT_GUID, "FT_GUID" },
4324 { FT_OID, "FT_OID" },
4327 static const value_string hf_display[] = {
4328 { BASE_NONE, "BASE_NONE" },
4329 { BASE_DEC, "BASE_DEC" },
4330 { BASE_HEX, "BASE_HEX" },
4331 { BASE_OCT, "BASE_OCT" },
4332 { BASE_DEC_HEX, "BASE_DEC_HEX" },
4333 { BASE_HEX_DEC, "BASE_HEX_DEC" },
4334 { BASE_CUSTOM, "BASE_CUSTOM" },
4335 { BASE_NONE|BASE_RANGE_STRING, "BASE_NONE|BASE_RANGE_STRING" },
4336 { BASE_DEC|BASE_RANGE_STRING, "BASE_DEC|BASE_RANGE_STRING" },
4337 { BASE_HEX|BASE_RANGE_STRING, "BASE_HEX|BASE_RANGE_STRING" },
4338 { BASE_OCT|BASE_RANGE_STRING, "BASE_OCT|BASE_RANGE_STRING" },
4339 { BASE_DEC_HEX|BASE_RANGE_STRING, "BASE_DEC_HEX|BASE_RANGE_STRING" },
4340 { BASE_HEX_DEC|BASE_RANGE_STRING, "BASE_HEX_DEC|BASE_RANGE_STRING" },
4341 { BASE_CUSTOM|BASE_RANGE_STRING, "BASE_CUSTOM|BASE_RANGE_STRING" },
4342 { ABSOLUTE_TIME_LOCAL, "ABSOLUTE_TIME_LOCAL" },
4343 { ABSOLUTE_TIME_UTC, "ABSOLUTE_TIME_LOCAL" },
4344 { ABSOLUTE_TIME_DOY_UTC, "ABSOLUTE_TIME_LOCAL" },
4347 /* The field must have a name (with length > 0) */
4348 if (!hfinfo->name || !hfinfo->name[0]) {
4350 /* Try to identify the field */
4351 g_error("Field (abbrev='%s') does not have a name\n",
4355 g_error("Field does not have a name (nor an abbreviation)\n");
4358 /* fields with an empty string for an abbreviation aren't filterable */
4359 /* XXX - so why aren't we checking for an empty string here?? */
4360 if (!hfinfo->abbrev)
4361 g_error("Field '%s' does not have an abbreviation\n", hfinfo->name);
4362 /* Okay, let's at least put out a warning and see if anyone complains */
4363 if (!hfinfo->abbrev[0])
4364 g_warning("Field '%s' does not have an abbreviation", hfinfo->name);
4366 /* These types of fields are allowed to have value_strings,
4367 * true_false_strings or a protocol_t struct
4369 if (hfinfo->strings != NULL && !(
4370 (hfinfo->type == FT_UINT8) ||
4371 (hfinfo->type == FT_UINT16) ||
4372 (hfinfo->type == FT_UINT24) ||
4373 (hfinfo->type == FT_UINT32) ||
4374 (hfinfo->type == FT_INT8) ||
4375 (hfinfo->type == FT_INT16) ||
4376 (hfinfo->type == FT_INT24) ||
4377 (hfinfo->type == FT_INT32) ||
4378 (hfinfo->type == FT_BOOLEAN) ||
4379 (hfinfo->type == FT_PROTOCOL) ||
4380 (hfinfo->type == FT_FRAMENUM) ))
4381 g_error("Field '%s' (%s) has a 'strings' value but is of type %s (which is not allowed to have strings)\n",
4382 hfinfo->name, hfinfo->abbrev,
4383 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"));
4385 switch (hfinfo->type) {
4392 /* Hexadecimal and octal are, in printf() and everywhere
4393 * else, unsigned so don't allow dissectors to register a
4394 * signed field to be displayed unsigned. (Else how would
4395 * we display negative values?)
4397 * If you want to take out this check, be sure to fix
4398 * hfinfo_numeric_format() so that it does not assert out
4399 * when trying to construct a hexadecimal representation of
4402 if (hfinfo->display == BASE_HEX ||
4403 hfinfo->display == BASE_HEX_DEC ||
4404 hfinfo->display == BASE_DEC_HEX ||
4405 hfinfo->display == BASE_OCT)
4406 g_error("Field '%s' (%s) is signed (%s) but is being displayed unsigned (%s)\n",
4407 hfinfo->name, hfinfo->abbrev,
4408 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"),
4409 val_to_str(hfinfo->display, hf_display, "(Bit count: %d)"));
4415 if (hfinfo->strings == NULL) {
4416 /* Require integral types (other than frame number,
4417 * which is always displayed in decimal) to have a
4419 if (hfinfo->display == BASE_NONE)
4420 g_error("Field '%s' (%s) is an integral value (%s) without strings but is being displayed as BASE_NONE\n",
4421 hfinfo->name, hfinfo->abbrev,
4422 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"));
4427 if (hfinfo->display == BASE_NONE)
4428 g_error("Field '%s' (%s) is an integral value (%s) but is being displayed as BASE_NONE\n",
4429 hfinfo->name, hfinfo->abbrev,
4430 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"));
4435 if (hfinfo->display != BASE_NONE)
4436 g_error("Field '%s' (%s) is an %s but is being displayed as %s instead of BASE_NONE\n",
4437 hfinfo->name, hfinfo->abbrev,
4438 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"),
4439 val_to_str(hfinfo->display, hf_display, "(Bit count: %d)"));
4440 if (hfinfo->bitmask != 0)
4441 g_error("Field '%s' (%s) is an %s but has a bitmask\n",
4442 hfinfo->name, hfinfo->abbrev,
4443 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"));
4449 case FT_ABSOLUTE_TIME:
4450 if (!(hfinfo->display == ABSOLUTE_TIME_LOCAL ||
4451 hfinfo->display == ABSOLUTE_TIME_UTC ||
4452 hfinfo->display == ABSOLUTE_TIME_DOY_UTC))
4453 g_error("Field '%s' (%s) is a %s but is being displayed as %s instead of as a time\n",
4454 hfinfo->name, hfinfo->abbrev,
4455 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"),
4456 val_to_str(hfinfo->display, hf_display, "(Bit count: %d)"));
4457 if (hfinfo->bitmask != 0)
4458 g_error("Field '%s' (%s) is an %s but has a bitmask\n",
4459 hfinfo->name, hfinfo->abbrev,
4460 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"));
4464 if (hfinfo->display != BASE_NONE)
4465 g_error("Field '%s' (%s) is an %s but is being displayed as %s instead of BASE_NONE\n",
4466 hfinfo->name, hfinfo->abbrev,
4467 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"),
4468 val_to_str(hfinfo->display, hf_display, "(Bit count: %d)"));
4469 if (hfinfo->bitmask != 0)
4470 g_error("Field '%s' (%s) is an %s but has a bitmask\n",
4471 hfinfo->name, hfinfo->abbrev,
4472 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"));
4473 if (hfinfo->strings != NULL)
4474 g_error("Field '%s' (%s) is an %s but has a strings value\n",
4475 hfinfo->name, hfinfo->abbrev,
4476 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"));
4482 proto_register_field_init(header_field_info *hfinfo, const int parent)
4485 tmp_fld_check_assert(hfinfo);
4487 /* if this is a bitfield, compute bitshift */
4488 if (hfinfo->bitmask) {
4489 hfinfo->bitshift = wrs_count_bitshift(hfinfo->bitmask);
4492 hfinfo->parent = parent;
4493 hfinfo->same_name_next = NULL;
4494 hfinfo->same_name_prev = NULL;
4496 /* if we always add and never delete, then id == len - 1 is correct */
4497 if(gpa_hfinfo.len>=gpa_hfinfo.allocated_len){
4498 if(!gpa_hfinfo.hfi){
4499 gpa_hfinfo.allocated_len=100000;
4500 gpa_hfinfo.hfi=g_malloc(sizeof(header_field_info *)*100000);
4502 gpa_hfinfo.allocated_len+=1000;
4503 gpa_hfinfo.hfi=g_realloc(gpa_hfinfo.hfi, sizeof(header_field_info *)*gpa_hfinfo.allocated_len);
4506 gpa_hfinfo.hfi[gpa_hfinfo.len]=hfinfo;
4508 hfinfo->id = gpa_hfinfo.len - 1;
4510 /* if we have real names, enter this field in the name tree */
4511 if ((hfinfo->name[0] != 0) && (hfinfo->abbrev[0] != 0 )) {
4513 header_field_info *same_name_next_hfinfo;
4516 /* Check that the filter name (abbreviation) is legal;
4517 * it must contain only alphanumerics, '-', "_", and ".". */
4518 c = wrs_check_charset(fld_abbrev_chars, hfinfo->abbrev);
4520 fprintf(stderr, "OOPS: '%c' in '%s'\n", c, hfinfo->abbrev);
4521 DISSECTOR_ASSERT(!c);
4524 /* We allow multiple hfinfo's to be registered under the same
4525 * abbreviation. This was done for X.25, as, depending
4526 * on whether it's modulo-8 or modulo-128 operation,
4527 * some bitfield fields may be in different bits of
4528 * a byte, and we want to be able to refer to that field
4529 * with one name regardless of whether the packets
4530 * are modulo-8 or modulo-128 packets. */
4532 same_name_hfinfo = NULL;
4534 g_tree_insert(gpa_name_tree, (gpointer) (hfinfo->abbrev), hfinfo);
4535 /* GLIB 2.x - if it is already present
4536 * the previous hfinfo with the same name is saved
4537 * to same_name_hfinfo by value destroy callback */
4538 if (same_name_hfinfo) {
4539 /* There's already a field with this name.
4540 * Put it after that field in the list of
4541 * fields with this name, then allow the code
4542 * after this if{} block to replace the old
4543 * hfinfo with the new hfinfo in the GTree. Thus,
4544 * we end up with a linked-list of same-named hfinfo's,
4545 * with the root of the list being the hfinfo in the GTree */
4546 same_name_next_hfinfo =
4547 same_name_hfinfo->same_name_next;
4549 hfinfo->same_name_next = same_name_next_hfinfo;
4550 if (same_name_next_hfinfo)
4551 same_name_next_hfinfo->same_name_prev = hfinfo;
4553 same_name_hfinfo->same_name_next = hfinfo;
4554 hfinfo->same_name_prev = same_name_hfinfo;
4562 proto_register_subtree_array(gint *const *indices, const int num_indices)
4565 gint *const *ptr = indices;
4568 * If we've already allocated the array of tree types, expand
4569 * it; this lets plugins such as mate add tree types after
4570 * the initial startup. (If we haven't already allocated it,
4571 * we don't allocate it; on the first pass, we just assign
4572 * ett values and keep track of how many we've assigned, and
4573 * when we're finished registering all dissectors we allocate
4574 * the array, so that we do only one allocation rather than
4575 * wasting CPU time and memory by growing the array for each
4576 * dissector that registers ett values.)
4578 if (tree_is_expanded != NULL) {
4580 g_realloc(tree_is_expanded,
4581 (num_tree_types+num_indices)*sizeof (gboolean));
4582 memset(tree_is_expanded + num_tree_types, 0,
4583 num_indices*sizeof (gboolean));
4587 * Assign "num_indices" subtree numbers starting at "num_tree_types",
4588 * returning the indices through the pointers in the array whose
4589 * first element is pointed to by "indices", and update
4590 * "num_tree_types" appropriately.
4592 for (i = 0; i < num_indices; i++, ptr++, num_tree_types++) {
4594 /* g_error will terminate the program */
4595 g_error("register_subtree_array: subtree item type (ett_...) not -1 !"
4596 " This is a development error:"
4597 " Either the subtree item type has already been assigned or"
4598 " was not initialized to -1.");
4600 **ptr = num_tree_types;
4605 proto_item_fill_label(field_info *fi, gchar *label_str)
4607 header_field_info *hfinfo;
4613 guint32 n_addr; /* network-order IPv4 address */
4615 int ret; /*tmp return value */
4620 /* XXX: Check validity of hfinfo->type */
4624 hfinfo = fi->hfinfo;
4626 switch(hfinfo->type) {
4629 g_strlcpy(label_str, hfinfo->name, ITEM_LABEL_LENGTH);
4633 fill_label_boolean(fi, label_str);
4638 bytes = fvalue_get(&fi->value);
4640 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4641 "%s: %s", hfinfo->name,
4642 bytes_to_str(bytes, fvalue_length(&fi->value)));
4643 if (ret >= ITEM_LABEL_LENGTH) {
4644 /* Uh oh, we don't have enough room. Tell the
4645 * user that the field is truncated.
4647 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4648 "%s [truncated]: %s",
4650 bytes_to_str(bytes, fvalue_length(&fi->value)));
4654 g_snprintf(label_str, ITEM_LABEL_LENGTH, "%s: <MISSING>", hfinfo->name);
4658 /* Four types of integers to take care of:
4659 * Bitfield, with val_string
4660 * Bitfield, w/o val_string
4661 * Non-bitfield, with val_string
4662 * Non-bitfield, w/o val_string
4668 if (hfinfo->bitmask) {
4669 fill_label_bitfield(fi, label_str);
4671 fill_label_uint(fi, label_str);
4676 fill_label_uint(fi, label_str);
4680 fill_label_uint64(fi, label_str);
4687 DISSECTOR_ASSERT(!hfinfo->bitmask);
4688 fill_label_int(fi, label_str);
4692 fill_label_int64(fi, label_str);
4696 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4697 "%s: %." STRINGIFY(FLT_DIG) "f",
4698 hfinfo->name, fvalue_get_floating(&fi->value));
4702 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4703 "%s: %." STRINGIFY(DBL_DIG) "g",
4704 hfinfo->name, fvalue_get_floating(&fi->value));
4707 case FT_ABSOLUTE_TIME:
4708 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4709 "%s: %s", hfinfo->name,
4710 abs_time_to_str(fvalue_get(&fi->value), hfinfo->display, TRUE));
4713 case FT_RELATIVE_TIME:
4714 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4715 "%s: %s seconds", hfinfo->name,
4716 rel_time_to_secs_str(fvalue_get(&fi->value)));
4720 integer = fvalue_get_uinteger(&fi->value);
4721 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4722 "%s: %s (0x%08X)", hfinfo->name,
4723 get_ipxnet_name(integer), integer);
4727 bytes = fvalue_get(&fi->value);
4728 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4729 "%s: %s (%s)", hfinfo->name,
4730 get_ether_name(bytes),
4731 ether_to_str(bytes));
4735 ipv4 = fvalue_get(&fi->value);
4736 n_addr = ipv4_get_net_order_addr(ipv4);
4737 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4738 "%s: %s (%s)", hfinfo->name,
4739 get_hostname(n_addr),
4740 ip_to_str((guint8*)&n_addr));
4744 bytes = fvalue_get(&fi->value);
4745 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4746 "%s: %s (%s)", hfinfo->name,
4747 get_hostname6((struct e_in6_addr *)bytes),
4748 ip6_to_str((struct e_in6_addr*)bytes));
4752 guid = fvalue_get(&fi->value);
4753 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4754 "%s: %s", hfinfo->name,
4759 bytes = fvalue_get(&fi->value);
4760 name = oid_resolved_from_encoded(bytes, fvalue_length(&fi->value));
4762 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4763 "%s: %s (%s)", hfinfo->name,
4764 oid_encoded2string(bytes, fvalue_length(&fi->value)), name);
4766 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4767 "%s: %s", hfinfo->name,
4768 oid_encoded2string(bytes, fvalue_length(&fi->value)));
4775 case FT_UINT_STRING:
4776 bytes = fvalue_get(&fi->value);
4777 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4778 "%s: %s", hfinfo->name,
4779 format_text(bytes, strlen(bytes)));
4780 if (ret >= ITEM_LABEL_LENGTH) {
4781 /* Uh oh, we don't have enough room. Tell the
4782 * user that the field is truncated.
4784 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4785 "%s [truncated]: %s", hfinfo->name,
4786 format_text(bytes, strlen(bytes)));
4791 g_error("hfinfo->type %d (%s) not handled\n",
4792 hfinfo->type, ftype_name(hfinfo->type));
4793 DISSECTOR_ASSERT_NOT_REACHED();
4799 fill_label_boolean(field_info *fi, gchar *label_str)
4801 char *p = label_str;
4802 int bitfield_byte_length = 0, bitwidth;
4803 guint32 unshifted_value;
4806 header_field_info *hfinfo = fi->hfinfo;
4807 const true_false_string *tfstring = (const true_false_string *)&tfs_true_false;
4809 if (hfinfo->strings) {
4810 tfstring = (const struct true_false_string*) hfinfo->strings;
4813 value = fvalue_get_uinteger(&fi->value);
4814 if (hfinfo->bitmask) {
4815 /* Figure out the bit width */
4816 bitwidth = hfinfo_bitwidth(hfinfo);
4819 unshifted_value = value;
4820 if (hfinfo->bitshift > 0) {
4821 unshifted_value <<= hfinfo->bitshift;
4824 /* Create the bitfield first */
4825 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
4826 bitfield_byte_length = (int) (p - label_str);
4829 /* Fill in the textual info */
4830 g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
4831 "%s: %s", hfinfo->name,
4832 value ? tfstring->true_string : tfstring->false_string);
4835 /* Fills data for bitfield ints with val_strings */
4837 fill_label_bitfield(field_info *fi, gchar *label_str)
4839 const char *format = NULL;
4841 int bitfield_byte_length, bitwidth;
4842 guint32 unshifted_value;
4845 header_field_info *hfinfo = fi->hfinfo;
4847 /* Figure out the bit width */
4848 bitwidth = hfinfo_bitwidth(hfinfo);
4851 unshifted_value = fvalue_get_uinteger(&fi->value);
4852 value = unshifted_value;
4853 if (hfinfo->bitshift > 0) {
4854 unshifted_value <<= hfinfo->bitshift;
4857 /* Create the bitfield first */
4858 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
4859 bitfield_byte_length = (int) (p - label_str);
4861 /* Fill in the textual info using stored (shifted) value */
4862 if (hfinfo->display == BASE_CUSTOM) {
4863 gchar tmp[ITEM_LABEL_LENGTH];
4864 custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hfinfo->strings;
4866 DISSECTOR_ASSERT(fmtfunc);
4867 fmtfunc(tmp, value);
4868 g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
4869 "%s: %s", hfinfo->name, tmp);
4871 else if (hfinfo->strings) {
4872 format = hfinfo_uint_vals_format(hfinfo);
4873 if (hfinfo->display & BASE_RANGE_STRING) {
4874 g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
4875 format, hfinfo->name,
4876 rval_to_str(value, hfinfo->strings, "Unknown"), value);
4877 } else if (hfinfo->display & BASE_EXT_STRING) {
4878 g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
4879 format, hfinfo->name,
4880 val_to_str_ext(value, (value_string_ext *) hfinfo->strings, "Unknown"), value);
4882 g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
4883 format, hfinfo->name,
4884 val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
4888 format = hfinfo_uint_format(hfinfo);
4889 if (IS_BASE_DUAL(hfinfo->display)) {
4890 g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
4891 format, hfinfo->name, value, value);
4893 g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
4894 format, hfinfo->name, value);
4900 fill_label_uint(field_info *fi, gchar *label_str)
4902 const char *format = NULL;
4903 header_field_info *hfinfo = fi->hfinfo;
4906 value = fvalue_get_uinteger(&fi->value);
4908 /* Fill in the textual info */
4909 if (hfinfo->display == BASE_CUSTOM) {
4910 gchar tmp[ITEM_LABEL_LENGTH];
4911 custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hfinfo->strings;
4913 DISSECTOR_ASSERT(fmtfunc);
4914 fmtfunc(tmp, value);
4915 g_snprintf(label_str, ITEM_LABEL_LENGTH, "%s: %s", hfinfo->name, tmp);
4917 else if (hfinfo->strings) {
4918 format = hfinfo_uint_vals_format(hfinfo);
4919 if (hfinfo->display & BASE_RANGE_STRING) {
4920 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4921 format, hfinfo->name,
4922 rval_to_str(value, hfinfo->strings, "Unknown"), value);
4923 } else if (hfinfo->display & BASE_EXT_STRING) {
4924 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4925 format, hfinfo->name,
4926 val_to_str_ext(value, (value_string_ext *) hfinfo->strings, "Unknown"), value);
4928 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4929 format, hfinfo->name,
4930 val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
4934 format = hfinfo_uint_format(hfinfo);
4935 if (IS_BASE_DUAL(hfinfo->display)) {
4936 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4937 format, hfinfo->name, value, value);
4939 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4940 format, hfinfo->name, value);
4946 fill_label_uint64(field_info *fi, gchar *label_str)
4948 const char *format = NULL;
4949 header_field_info *hfinfo = fi->hfinfo;
4952 /* Pick the proper format string */
4953 format = hfinfo_uint64_format(hfinfo);
4954 value = fvalue_get_integer64(&fi->value);
4956 /* Fill in the textual info */
4957 if (IS_BASE_DUAL(hfinfo->display)) {
4958 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4959 format, hfinfo->name, value, value);
4961 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4962 format, hfinfo->name, value);
4967 fill_label_int(field_info *fi, gchar *label_str)
4969 const char *format = NULL;
4970 header_field_info *hfinfo = fi->hfinfo;
4973 value = fvalue_get_sinteger(&fi->value);
4975 /* Fill in the textual info */
4976 if (hfinfo->display == BASE_CUSTOM) {
4977 gchar tmp[ITEM_LABEL_LENGTH];
4978 custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hfinfo->strings;
4980 DISSECTOR_ASSERT(fmtfunc);
4981 fmtfunc(tmp, value);
4982 g_snprintf(label_str, ITEM_LABEL_LENGTH, "%s: %s", hfinfo->name, tmp);
4984 else if (hfinfo->strings) {
4985 format = hfinfo_int_vals_format(hfinfo);
4986 if (hfinfo->display & BASE_RANGE_STRING) {
4987 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4988 format, hfinfo->name,
4989 rval_to_str(value, hfinfo->strings, "Unknown"), value);
4990 } else if (hfinfo->display & BASE_EXT_STRING) {
4991 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4992 format, hfinfo->name,
4993 val_to_str_ext(value, (value_string_ext *) hfinfo->strings, "Unknown"), value);
4995 g_snprintf(label_str, ITEM_LABEL_LENGTH,
4996 format, hfinfo->name,
4997 val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
5001 format = hfinfo_int_format(hfinfo);
5002 if (IS_BASE_DUAL(hfinfo->display)) {
5003 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5004 format, hfinfo->name, value, value);
5006 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5007 format, hfinfo->name, value);
5013 fill_label_int64(field_info *fi, gchar *label_str)
5015 const char *format = NULL;
5016 header_field_info *hfinfo = fi->hfinfo;
5019 /* Pick the proper format string */
5020 format = hfinfo_int64_format(hfinfo);
5021 value = fvalue_get_integer64(&fi->value);
5023 /* Fill in the textual info */
5024 if (IS_BASE_DUAL(hfinfo->display)) {
5025 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5026 format, hfinfo->name, value, value);
5028 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5029 format, hfinfo->name, value);
5034 hfinfo_bitwidth(const header_field_info *hfinfo)
5038 if (!hfinfo->bitmask) {
5042 switch(hfinfo->type) {
5060 bitwidth = hfinfo->display; /* hacky? :) */
5063 DISSECTOR_ASSERT_NOT_REACHED();
5070 hfinfo_uint_vals_format(const header_field_info *hfinfo)
5072 const char *format = NULL;
5074 /* Get the underlying BASE_ value */
5075 switch(hfinfo->display & BASE_DISPLAY_E_MASK) {
5081 format = "%s: %s (%u)";
5083 case BASE_OCT: /* I'm lazy */
5084 format = "%s: %s (%#o)";
5088 switch(hfinfo->type) {
5090 format = "%s: %s (0x%02x)";
5093 format = "%s: %s (0x%04x)";
5096 format = "%s: %s (0x%06x)";
5099 format = "%s: %s (0x%08x)";
5102 DISSECTOR_ASSERT_NOT_REACHED();
5107 DISSECTOR_ASSERT_NOT_REACHED();
5114 hfinfo_uint_format(const header_field_info *hfinfo)
5116 const char *format = NULL;
5118 /* Pick the proper format string */
5119 if (hfinfo->type == FT_FRAMENUM) {
5121 * Frame numbers are always displayed in decimal.
5125 switch(hfinfo->display) {
5130 switch(hfinfo->type) {
5132 format = "%s: %u (0x%02x)";
5135 format = "%s: %u (0x%04x)";
5138 format = "%s: %u (0x%06x)";
5141 format = "%s: %u (0x%08x)";
5144 DISSECTOR_ASSERT_NOT_REACHED();
5148 case BASE_OCT: /* I'm lazy */
5152 switch(hfinfo->type) {
5154 format = "%s: 0x%02x";
5157 format = "%s: 0x%04x";
5160 format = "%s: 0x%06x";
5163 format = "%s: 0x%08x";
5166 DISSECTOR_ASSERT_NOT_REACHED();
5171 switch(hfinfo->type) {
5173 format = "%s: 0x%02x (%u)";
5176 format = "%s: 0x%04x (%u)";
5179 format = "%s: 0x%06x (%u)";
5182 format = "%s: 0x%08x (%u)";
5185 DISSECTOR_ASSERT_NOT_REACHED();
5190 DISSECTOR_ASSERT_NOT_REACHED();
5198 hfinfo_uint_value_format(const header_field_info *hfinfo)
5200 const char *format = NULL;
5202 /* Pick the proper format string */
5203 if (hfinfo->type == FT_FRAMENUM) {
5205 * Frame numbers are always displayed in decimal.
5209 switch(hfinfo->display) {
5214 switch(hfinfo->type) {
5216 format = "%u (0x%02x)";
5219 format = "%u (0x%04x)";
5222 format = "%u (0x%06x)";
5225 format = "%u (0x%08x)";
5228 DISSECTOR_ASSERT_NOT_REACHED();
5236 switch(hfinfo->type) {
5250 DISSECTOR_ASSERT_NOT_REACHED();
5255 switch(hfinfo->type) {
5257 format = "0x%02x (%u)";
5260 format = "0x%04x (%u)";
5263 format = "0x%06x (%u)";
5266 format = "0x%08x (%u)";
5269 DISSECTOR_ASSERT_NOT_REACHED();
5274 DISSECTOR_ASSERT_NOT_REACHED();
5282 hfinfo_int_vals_format(const header_field_info *hfinfo)
5284 const char *format = NULL;
5286 /* Get the underlying BASE_ value */
5287 switch(hfinfo->display & BASE_DISPLAY_E_MASK) {
5293 format = "%s: %s (%d)";
5295 case BASE_OCT: /* I'm lazy */
5296 format = "%s: %s (%#o)";
5300 switch(hfinfo->type) {
5302 format = "%s: %s (0x%02x)";
5305 format = "%s: %s (0x%04x)";
5308 format = "%s: %s (0x%06x)";
5311 format = "%s: %s (0x%08x)";
5314 DISSECTOR_ASSERT_NOT_REACHED();
5319 DISSECTOR_ASSERT_NOT_REACHED();
5326 hfinfo_uint64_format(const header_field_info *hfinfo)
5328 const char *format = NULL;
5330 /* Pick the proper format string */
5331 switch(hfinfo->display) {
5333 format = "%s: %" G_GINT64_MODIFIER "u";
5336 format = "%s: %" G_GINT64_MODIFIER "u (%" G_GINT64_MODIFIER "x)";
5338 case BASE_OCT: /* I'm lazy */
5339 format = "%s: %#" G_GINT64_MODIFIER "o";
5342 format = "%s: 0x%016" G_GINT64_MODIFIER "x";
5345 format = "%s: 0x%016" G_GINT64_MODIFIER "x (%" G_GINT64_MODIFIER "u)";
5348 DISSECTOR_ASSERT_NOT_REACHED();
5355 hfinfo_int_format(const header_field_info *hfinfo)
5357 const char *format = NULL;
5359 /* Pick the proper format string */
5360 switch(hfinfo->display) {
5365 switch(hfinfo->type) {
5367 format = "%s: %d (0x%02x)";
5370 format = "%s: %d (0x%04x)";
5373 format = "%s: %d (0x%06x)";
5376 format = "%s: %d (0x%08x)";
5379 DISSECTOR_ASSERT_NOT_REACHED();
5383 case BASE_OCT: /* I'm lazy */
5387 switch(hfinfo->type) {
5389 format = "%s: 0x%02x";
5392 format = "%s: 0x%04x";
5395 format = "%s: 0x%06x";
5398 format = "%s: 0x%08x";
5401 DISSECTOR_ASSERT_NOT_REACHED();
5406 switch(hfinfo->type) {
5408 format = "%s: 0x%02x (%d)";
5411 format = "%s: 0x%04x (%d)";
5414 format = "%s: 0x%06x (%d)";
5417 format = "%s: 0x%08x (%d)";
5420 DISSECTOR_ASSERT_NOT_REACHED();
5425 DISSECTOR_ASSERT_NOT_REACHED();
5432 hfinfo_int_value_format(const header_field_info *hfinfo)
5434 const char *format = NULL;
5436 /* Pick the proper format string */
5437 switch(hfinfo->display) {
5442 switch(hfinfo->type) {
5444 format = "%d (0x%02x)";
5447 format = "%d (0x%04x)";
5450 format = "%d (0x%06x)";
5453 format = "%d (0x%08x)";
5456 DISSECTOR_ASSERT_NOT_REACHED();
5464 switch(hfinfo->type) {
5478 DISSECTOR_ASSERT_NOT_REACHED();
5483 switch(hfinfo->type) {
5485 format = "0x%02x (%d)";
5488 format = "0x%04x (%d)";
5491 format = "0x%06x (%d)";
5494 format = "0x%08x (%d)";
5497 DISSECTOR_ASSERT_NOT_REACHED();
5502 DISSECTOR_ASSERT_NOT_REACHED();
5509 hfinfo_int64_format(const header_field_info *hfinfo)
5511 const char *format = NULL;
5513 /* Pick the proper format string */
5514 switch(hfinfo->display) {
5516 format = "%s: %" G_GINT64_MODIFIER "d";
5519 format = "%s: %" G_GINT64_MODIFIER "d (%" G_GINT64_MODIFIER "x)";
5521 case BASE_OCT: /* I'm lazy */
5522 format = "%s: %#" G_GINT64_MODIFIER "o";
5525 format = "%s: 0x%016" G_GINT64_MODIFIER "x";
5528 format = "%s: 0x%016" G_GINT64_MODIFIER "x (%" G_GINT64_MODIFIER "d)";
5531 DISSECTOR_ASSERT_NOT_REACHED();
5538 proto_registrar_n(void)
5540 return gpa_hfinfo.len;
5544 proto_registrar_get_name(const int n)
5546 header_field_info *hfinfo;
5548 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
5549 return hfinfo->name;
5553 proto_registrar_get_abbrev(const int n)
5555 header_field_info *hfinfo;
5557 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
5558 return hfinfo->abbrev;
5562 proto_registrar_get_ftype(const int n)
5564 header_field_info *hfinfo;
5566 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
5567 return hfinfo->type;
5571 proto_registrar_get_parent(const int n)
5573 header_field_info *hfinfo;
5575 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
5576 return hfinfo->parent;
5580 proto_registrar_is_protocol(const int n)
5582 header_field_info *hfinfo;
5584 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
5585 return (hfinfo->parent == -1 ? TRUE : FALSE);
5588 /* Returns length of field in packet (not necessarily the length
5589 * in our internal representation, as in the case of IPv4).
5590 * 0 means undeterminable at time of registration
5591 * -1 means the field is not registered. */
5593 proto_registrar_get_length(const int n)
5595 header_field_info *hfinfo;
5597 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
5598 return ftype_length(hfinfo->type);
5601 /* Looks for a protocol or a field in a proto_tree. Returns TRUE if
5602 * it exists anywhere, or FALSE if it exists nowhere. */
5604 proto_check_for_protocol_or_field(const proto_tree* tree, const int id)
5606 GPtrArray *ptrs = proto_get_finfo_ptr_array(tree, id);
5611 else if (g_ptr_array_len(ptrs) > 0) {
5619 /* Return GPtrArray* of field_info pointers for all hfindex that appear in tree.
5620 * This only works if the hfindex was "primed" before the dissection
5621 * took place, as we just pass back the already-created GPtrArray*.
5622 * The caller should *not* free the GPtrArray*; proto_tree_free_node()
5625 proto_get_finfo_ptr_array(const proto_tree *tree, const int id)
5630 if (PTREE_DATA(tree)->interesting_hfids != NULL)
5631 return g_hash_table_lookup(PTREE_DATA(tree)->interesting_hfids,
5632 GINT_TO_POINTER(id));
5638 proto_tracking_interesting_fields(const proto_tree *tree)
5643 return (PTREE_DATA(tree)->interesting_hfids != NULL);
5646 /* Helper struct for proto_find_info() and proto_all_finfos() */
5652 /* Helper function for proto_find_info() */
5654 find_finfo(proto_node *node, gpointer data)
5656 field_info *fi = PNODE_FINFO(node);
5657 if (fi && fi->hfinfo) {
5658 if (fi->hfinfo->id == ((ffdata_t*)data)->id) {
5659 g_ptr_array_add(((ffdata_t*)data)->array, fi);
5663 /* Don't stop traversing. */
5667 /* Return GPtrArray* of field_info pointers for all hfindex that appear in a tree.
5668 * This works on any proto_tree, primed or unprimed, but actually searches
5669 * the tree, so it is slower than using proto_get_finfo_ptr_array on a primed tree.
5670 * The caller does need to free the returned GPtrArray with
5671 * g_ptr_array_free(<array>, TRUE).
5674 proto_find_finfo(proto_tree *tree, const int id)
5678 ffdata.array = g_ptr_array_new();
5681 proto_tree_traverse_pre_order(tree, find_finfo, &ffdata);
5683 return ffdata.array;
5686 /* Helper function for proto_all_finfos() */
5688 every_finfo(proto_node *node, gpointer data)
5690 field_info *fi = PNODE_FINFO(node);
5691 if (fi && fi->hfinfo) {
5692 g_ptr_array_add(((ffdata_t*)data)->array, fi);
5695 /* Don't stop traversing. */
5699 /* Return GPtrArray* of field_info pointers containing all hfindexes that appear in a tree. */
5701 proto_all_finfos(proto_tree *tree)
5705 ffdata.array = g_ptr_array_new();
5708 proto_tree_traverse_pre_order(tree, every_finfo, &ffdata);
5710 return ffdata.array;
5721 check_for_offset(proto_node *node, const gpointer data)
5723 field_info *fi = PNODE_FINFO(node);
5724 offset_search_t *offsearch = data;
5726 /* !fi == the top most container node which holds nothing */
5727 if (fi && !PROTO_ITEM_IS_HIDDEN(node) && fi->ds_tvb && offsearch->tvb == fi->ds_tvb) {
5728 if (offsearch->offset >= (guint) fi->start &&
5729 offsearch->offset < (guint) (fi->start + fi->length)) {
5731 offsearch->finfo = fi;
5732 return FALSE; /* keep traversing */
5735 return FALSE; /* keep traversing */
5738 /* Search a proto_tree backwards (from leaves to root) looking for the field
5739 * whose start/length occupies 'offset' */
5740 /* XXX - I couldn't find an easy way to search backwards, so I search
5741 * forwards, w/o stopping. Therefore, the last finfo I find will the be
5742 * the one I want to return to the user. This algorithm is inefficient
5743 * and could be re-done, but I'd have to handle all the children and
5744 * siblings of each node myself. When I have more time I'll do that.
5747 proto_find_field_from_offset(proto_tree *tree, guint offset, tvbuff_t *tvb)
5749 offset_search_t offsearch;
5751 offsearch.offset = offset;
5752 offsearch.finfo = NULL;
5753 offsearch.tvb = tvb;
5755 proto_tree_traverse_pre_order(tree, check_for_offset, &offsearch);
5757 return offsearch.finfo;
5760 /* Dumps the protocols in the registration database to stdout. An independent
5761 * program can take this output and format it into nice tables or HTML or
5764 * There is one record per line. The fields are tab-delimited.
5766 * Field 1 = protocol name
5767 * Field 2 = protocol short name
5768 * Field 3 = protocol filter name
5771 proto_registrar_dump_protocols(void)
5773 protocol_t *protocol;
5775 void *cookie = NULL;
5777 for (i = proto_get_first_protocol(&cookie); i != -1;
5778 i = proto_get_next_protocol(&cookie)) {
5779 protocol = find_protocol_by_id(i);
5780 printf("%s\t%s\t%s\n", protocol->name, protocol->short_name,
5781 protocol->filter_name);
5785 /* Dumps the value_strings, range_strings or true/false strings for fields
5786 * that have them. There is one record per line. Fields are tab-delimited.
5787 * There are three types of records: Value String, Range String
5788 * and True/False String. The first field, 'V', 'R' or 'T', indicates
5789 * the type of record.
5794 * Field 2 = field abbreviation to which this value string corresponds
5795 * Field 3 = Integer value
5801 * Field 2 = field abbreviation to which this range string corresponds
5802 * Field 3 = Integer value: lower bound
5803 * Field 4 = Integer value: upper bound
5806 * True/False Strings
5807 * ------------------
5809 * Field 2 = field abbreviation to which this true/false string corresponds
5810 * Field 3 = True String
5811 * Field 4 = False String
5814 proto_registrar_dump_values(void)
5816 header_field_info *hfinfo, *parent_hfinfo;
5818 const value_string *vals;
5819 const range_string *range;
5820 const true_false_string *tfs;
5822 len = gpa_hfinfo.len;
5823 for (i = 0; i < len ; i++) {
5824 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
5826 if (hfinfo->id == hf_text_only) {
5830 /* ignore protocols */
5831 if (proto_registrar_is_protocol(i)) {
5834 /* process header fields */
5837 * If this field isn't at the head of the list of
5838 * fields with this name, skip this field - all
5839 * fields with the same name are really just versions
5840 * of the same field stored in different bits, and
5841 * should have the same type/radix/value list, and
5842 * just differ in their bit masks. (If a field isn't
5843 * a bitfield, but can be, say, 1 or 2 bytes long,
5844 * it can just be made FT_UINT16, meaning the
5845 * *maximum* length is 2 bytes, and be used
5848 if (hfinfo->same_name_prev != NULL)
5851 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
5857 if ((hfinfo->display & BASE_DISPLAY_E_MASK) != BASE_CUSTOM &&
5858 (hfinfo->type == FT_UINT8 ||
5859 hfinfo->type == FT_UINT16 ||
5860 hfinfo->type == FT_UINT24 ||
5861 hfinfo->type == FT_UINT32 ||
5862 hfinfo->type == FT_UINT64 ||
5863 hfinfo->type == FT_INT8 ||
5864 hfinfo->type == FT_INT16 ||
5865 hfinfo->type == FT_INT24 ||
5866 hfinfo->type == FT_INT32 ||
5867 hfinfo->type == FT_INT64)) {
5869 if ((hfinfo->display & BASE_EXT_STRING)) {
5870 vals = ((value_string_ext *) hfinfo->strings)->vals;
5871 } if ((hfinfo->display & BASE_RANGE_STRING) == 0) {
5872 vals = hfinfo->strings;
5874 range = hfinfo->strings;
5877 else if (hfinfo->type == FT_BOOLEAN) {
5878 tfs = hfinfo->strings;
5881 /* Print value strings? */
5884 while (vals[vi].strptr) {
5885 /* Print in the proper base */
5886 if (hfinfo->display == BASE_HEX) {
5887 printf("V\t%s\t0x%x\t%s\n",
5893 printf("V\t%s\t%u\t%s\n",
5902 /* print range strings? */
5905 while (range[vi].strptr) {
5906 /* Print in the proper base */
5907 if ((hfinfo->display & BASE_DISPLAY_E_MASK) == BASE_HEX) {
5908 printf("R\t%s\t0x%x\t0x%x\t%s\n",
5910 range[vi].value_min,
5911 range[vi].value_max,
5915 printf("R\t%s\t%u\t%u\t%s\n",
5917 range[vi].value_min,
5918 range[vi].value_max,
5925 /* Print true/false strings? */
5927 printf("T\t%s\t%s\t%s\n", hfinfo->abbrev,
5928 tfs->true_string, tfs->false_string);
5934 /* Dumps the contents of the registration database to stdout. An independent
5935 * program can take this output and format it into nice tables or HTML or
5938 * There is one record per line. Each record is either a protocol or a header
5939 * field, differentiated by the first field. The fields are tab-delimited.
5944 * Field 2 = descriptive protocol name
5945 * Field 3 = protocol abbreviation
5951 * Field 2 = descriptive field name
5952 * Field 3 = field abbreviation
5953 * Field 4 = type ( textual representation of the the ftenum type )
5954 * Field 5 = parent protocol abbreviation
5955 * Field 6 = blurb describing field
5959 * Field 2 = descriptive field name
5960 * Field 3 = field abbreviation
5961 * Field 4 = type ( textual representation of the the ftenum type )
5962 * Field 5 = parent protocol abbreviation
5963 * Field 6 = blurb describing field
5964 * Field 7 = base for display (for integer types); "parent bitfield width" for FT_BOOLEAN
5965 * Field 8 = blurb describing field (yes, apparently we repeated this accidentally)
5969 * Field 2 = descriptive field name
5970 * Field 3 = field abbreviation
5971 * Field 4 = type ( textual representation of the the ftenum type )
5972 * Field 5 = parent protocol abbreviation
5973 * Field 6 = blurb describing field
5974 * Field 7 = base for display (for integer types); "parent bitfield width" for FT_BOOLEAN
5975 * Field 8 = bitmask: format: hex: 0x....
5978 proto_registrar_dump_fields(const int format)
5980 header_field_info *hfinfo, *parent_hfinfo;
5982 const char *enum_name;
5983 const char *base_name;
5987 len = gpa_hfinfo.len;
5988 for (i = 0; i < len ; i++) {
5989 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
5992 * Skip the pseudo-field for "proto_tree_add_text()" since
5993 * we don't want it in the list of filterable fields.
5995 if (hfinfo->id == hf_text_only)
5998 /* format for protocols */
5999 if (proto_registrar_is_protocol(i)) {
6000 printf("P\t%s\t%s\n", hfinfo->name, hfinfo->abbrev);
6002 /* format for header fields */
6005 * If this field isn't at the head of the list of
6006 * fields with this name, skip this field - all
6007 * fields with the same name are really just versions
6008 * of the same field stored in different bits, and
6009 * should have the same type/radix/value list, and
6010 * just differ in their bit masks. (If a field isn't
6011 * a bitfield, but can be, say, 1 or 2 bytes long,
6012 * it can just be made FT_UINT16, meaning the
6013 * *maximum* length is 2 bytes, and be used
6016 if (hfinfo->same_name_prev != NULL)
6019 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
6021 enum_name = ftype_name(hfinfo->type);
6025 if (hfinfo->type == FT_UINT8 ||
6026 hfinfo->type == FT_UINT16 ||
6027 hfinfo->type == FT_UINT24 ||
6028 hfinfo->type == FT_UINT32 ||
6029 hfinfo->type == FT_UINT64 ||
6030 hfinfo->type == FT_INT8 ||
6031 hfinfo->type == FT_INT16 ||
6032 hfinfo->type == FT_INT24 ||
6033 hfinfo->type == FT_INT32 ||
6034 hfinfo->type == FT_INT64) {
6037 switch(hfinfo->display & BASE_DISPLAY_E_MASK) {
6039 base_name = "BASE_NONE";
6042 base_name = "BASE_DEC";
6045 base_name = "BASE_HEX";
6048 base_name = "BASE_OCT";
6051 base_name = "BASE_DEC_HEX";
6054 base_name = "BASE_HEX_DEC";
6057 base_name = "BASE_CUSTOM";
6063 } else if (hfinfo->type == FT_BOOLEAN) {
6064 /* For FT_BOOLEAN: 'display' can be "parent bitfield width" */
6065 g_snprintf(width, sizeof(width), "%d", hfinfo->display);
6070 blurb = hfinfo->blurb;
6073 else if (strlen(blurb) == 0)
6076 printf("F\t%s\t%s\t%s\t%s\t%s\n",
6077 hfinfo->name, hfinfo->abbrev, enum_name,
6078 parent_hfinfo->abbrev, blurb);
6080 else if (format == 2) {
6081 printf("F\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n",
6082 hfinfo->name, hfinfo->abbrev, enum_name,
6083 parent_hfinfo->abbrev, blurb,
6086 else if (format == 3) {
6087 printf("F\t%s\t%s\t%s\t%s\t%s\t%s\t0x%x\n",
6088 hfinfo->name, hfinfo->abbrev, enum_name,
6089 parent_hfinfo->abbrev, blurb,
6090 base_name, hfinfo->bitmask);
6093 g_assert_not_reached();
6100 hfinfo_numeric_format(const header_field_info *hfinfo)
6102 const char *format = NULL;
6104 /* Pick the proper format string */
6105 if (hfinfo->type == FT_FRAMENUM) {
6107 * Frame numbers are always displayed in decimal.
6109 format = "%s == %u";
6111 /* Get the underlying BASE_ value */
6112 switch(hfinfo->display & BASE_DISPLAY_E_MASK) {
6115 case BASE_OCT: /* I'm lazy */
6117 switch(hfinfo->type) {
6122 format = "%s == %u";
6125 format = "%s == %" G_GINT64_MODIFIER "u";
6131 format = "%s == %d";
6134 format = "%s == %" G_GINT64_MODIFIER "d";
6137 DISSECTOR_ASSERT_NOT_REACHED();
6143 switch(hfinfo->type) {
6145 format = "%s == 0x%02x";
6148 format = "%s == 0x%04x";
6151 format = "%s == 0x%06x";
6154 format = "%s == 0x%08x";
6157 format = "%s == 0x%016" G_GINT64_MODIFIER "x";
6160 DISSECTOR_ASSERT_NOT_REACHED();
6165 DISSECTOR_ASSERT_NOT_REACHED();
6172 /* This function indicates whether it's possible to construct a
6173 * "match selected" display filter string for the specified field,
6174 * returns an indication of whether it's possible, and, if it's
6175 * possible and "filter" is non-null, constructs the filter and
6176 * sets "*filter" to point to it.
6177 * You do not need to [g_]free() this string since it will be automatically
6178 * freed once the next packet is dissected.
6181 construct_match_selected_string(field_info *finfo, epan_dissect_t *edt,
6184 header_field_info *hfinfo;
6190 gint start, length, length_remaining;
6192 gchar is_signed_num = FALSE;
6194 hfinfo = finfo->hfinfo;
6195 DISSECTOR_ASSERT(hfinfo);
6196 abbrev_len = (int) strlen(hfinfo->abbrev);
6198 if (hfinfo->strings && (hfinfo->display & BASE_DISPLAY_E_MASK) == BASE_NONE) {
6199 const gchar *str = NULL;
6201 switch(hfinfo->type) {
6207 if (hfinfo->display & BASE_RANGE_STRING) {
6208 str = match_strrval(fvalue_get_sinteger(&finfo->value), hfinfo->strings);
6209 } else if (hfinfo->display & BASE_EXT_STRING) {
6210 str = match_strval_ext(fvalue_get_sinteger(&finfo->value), hfinfo->strings);
6212 str = match_strval(fvalue_get_sinteger(&finfo->value), hfinfo->strings);
6220 if (hfinfo->display & BASE_RANGE_STRING) {
6221 str = match_strrval(fvalue_get_uinteger(&finfo->value), hfinfo->strings);
6222 } else if (hfinfo->display & BASE_EXT_STRING) {
6223 str = match_strval_ext(fvalue_get_uinteger(&finfo->value), hfinfo->strings);
6225 str = match_strval(fvalue_get_uinteger(&finfo->value), hfinfo->strings);
6233 if (str != NULL && filter != NULL) {
6234 *filter = ep_strdup_printf("%s == \"%s\"", hfinfo->abbrev, str);
6240 * XXX - we can't use the "val_to_string_repr" and "string_repr_len"
6241 * functions for FT_UINT and FT_INT types, as we choose the base in
6242 * the string expression based on the display base of the field.
6244 * Note that the base does matter, as this is also used for
6245 * the protocolinfo tap.
6247 * It might be nice to use them in "proto_item_fill_label()"
6248 * as well, although, there, you'd have to deal with the base
6249 * *and* with resolved values for addresses.
6251 * Perhaps we need two different val_to_string routines, one
6252 * to generate items for display filters and one to generate
6253 * strings for display, and pass to both of them the
6254 * "display" and "strings" values in the header_field_info
6255 * structure for the field, so they can get the base and,
6256 * if the field is Boolean or an enumerated integer type,
6257 * the tables used to generate human-readable values.
6259 switch(hfinfo->type) {
6265 is_signed_num = TRUE;
6270 if (filter != NULL) {
6271 format = hfinfo_numeric_format(hfinfo);
6273 *filter = ep_strdup_printf(format,
6275 fvalue_get_sinteger(&finfo->value));
6277 *filter = ep_strdup_printf(format,
6279 fvalue_get_uinteger(&finfo->value));
6285 DISSECTOR_ASSERT(!is_signed_num);
6286 if (filter != NULL) {
6287 format = hfinfo_numeric_format(hfinfo);
6288 *filter = ep_strdup_printf(format,
6290 fvalue_get_uinteger(&finfo->value));
6296 if (filter != NULL) {
6297 format = hfinfo_numeric_format(hfinfo);
6298 *filter = ep_strdup_printf(format,
6300 fvalue_get_integer64(&finfo->value));
6306 *filter = ep_strdup(finfo->hfinfo->abbrev);
6311 * If the length is 0, just match the name of the
6314 * (Also check for negative values, just in case,
6315 * as we'll cast it to an unsigned value later.)
6317 length = finfo->length;
6320 *filter = ep_strdup(finfo->hfinfo->abbrev);
6327 * This doesn't have a value, so we'd match
6328 * on the raw bytes at this address.
6330 * Should we be allowed to access to the raw bytes?
6331 * If "edt" is NULL, the answer is "no".
6337 * Is this field part of the raw frame tvbuff?
6338 * If not, we can't use "frame[N:M]" to match
6341 * XXX - should this be frame-relative, or
6342 * protocol-relative?
6344 * XXX - does this fallback for non-registered
6345 * fields even make sense?
6347 if (finfo->ds_tvb != edt->tvb)
6348 return FALSE; /* you lose */
6351 * Don't go past the end of that tvbuff.
6353 length_remaining = tvb_length_remaining(finfo->ds_tvb, finfo->start);
6354 if (length > length_remaining)
6355 length = length_remaining;
6359 if (filter != NULL) {
6360 start = finfo->start;
6361 buf_len = 32 + length * 3;
6362 *filter = ep_alloc0(buf_len);
6365 ptr += g_snprintf(ptr, (gulong) (buf_len-(ptr-*filter)),
6366 "frame[%d:%d] == ", finfo->start, length);
6367 for (i=0;i<length; i++) {
6368 c = tvb_get_guint8(finfo->ds_tvb, start);
6371 ptr += g_snprintf(ptr, (gulong) (buf_len-(ptr-*filter)), "%02x", c);
6374 ptr += g_snprintf(ptr, (gulong) (buf_len-(ptr-*filter)), ":%02x", c);
6381 /* FT_PCRE never appears as a type for a registered field. It is
6382 * only used internally. */
6383 DISSECTOR_ASSERT_NOT_REACHED();
6386 /* By default, use the fvalue's "to_string_repr" method. */
6388 /* Figure out the string length needed.
6389 * The ft_repr length.
6390 * 4 bytes for " == ".
6391 * 1 byte for trailing NUL.
6393 if (filter != NULL) {
6394 dfilter_len = fvalue_string_repr_len(&finfo->value,
6396 dfilter_len += abbrev_len + 4 + 1;
6397 *filter = ep_alloc0(dfilter_len);
6399 /* Create the string */
6400 g_snprintf(*filter, dfilter_len, "%s == ",
6402 fvalue_to_string_repr(&finfo->value,
6404 &(*filter)[abbrev_len + 4]);
6413 * Returns TRUE if we can do a "match selected" on the field, FALSE
6417 proto_can_match_selected(field_info *finfo, epan_dissect_t *edt)
6419 return construct_match_selected_string(finfo, edt, NULL);
6422 /* This function attempts to construct a "match selected" display filter
6423 * string for the specified field; if it can do so, it returns a pointer
6424 * to the string, otherwise it returns NULL.
6426 * The string is allocated with packet lifetime scope.
6427 * You do not need to [g_]free() this string since it will be automatically
6428 * freed once the next packet is dissected.
6431 proto_construct_match_selected_string(field_info *finfo, epan_dissect_t *edt)
6435 if (!construct_match_selected_string(finfo, edt, &filter))
6440 /* This function is common code for both proto_tree_add_bitmask() and
6441 * proto_tree_add_bitmask_text() functions.
6444 proto_item_add_bitmask_tree(proto_item *item, tvbuff_t *tvb, const int offset,
6445 const int len, const gint ett, const int **fields,
6446 const gboolean little_endian, const int flags,
6449 guint32 value = 0, tmpval;
6450 proto_tree *tree = NULL;
6451 header_field_info *hf;
6456 value = tvb_get_guint8(tvb, offset);
6459 value = little_endian ? tvb_get_letohs(tvb, offset) :
6460 tvb_get_ntohs(tvb, offset);
6463 value = little_endian ? tvb_get_letoh24(tvb, offset) :
6464 tvb_get_ntoh24(tvb, offset);
6467 value = little_endian ? tvb_get_letohl(tvb, offset) :
6468 tvb_get_ntohl(tvb, offset);
6471 g_assert_not_reached();
6474 tree = proto_item_add_subtree(item, ett);
6476 proto_tree_add_item(tree, **fields, tvb, offset, len, little_endian);
6477 if (flags & BMT_NO_APPEND) {
6481 hf = proto_registrar_get_nth(**fields);
6482 DISSECTOR_ASSERT(hf->bitmask != 0);
6483 tmpval = (value & hf->bitmask) >> hf->bitshift;
6494 DISSECTOR_ASSERT(len == ftype_length(hf->type));
6496 if (hf->display == BASE_CUSTOM) {
6497 gchar lbl[ITEM_LABEL_LENGTH];
6498 custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hf->strings;
6500 DISSECTOR_ASSERT(fmtfunc);
6501 fmtfunc(lbl, tmpval);
6502 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
6506 else if (hf->strings) {
6507 if (hf->display & BASE_RANGE_STRING) {
6508 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
6509 hf->name, rval_to_str(tmpval, hf->strings, "Unknown"));
6510 } else if (hf->display & BASE_EXT_STRING) {
6511 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
6512 hf->name, val_to_str_ext(tmpval, (value_string_ext *) (hf->strings), "Unknown"));
6514 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
6515 hf->name, val_to_str(tmpval, cVALS(hf->strings), "Unknown"));
6519 else if (!(flags & BMT_NO_INT)) {
6521 proto_item_append_text(item, ", ");
6524 fmt = IS_FT_INT(hf->type) ? hfinfo_int_format(hf) : hfinfo_uint_format(hf);
6525 if (IS_BASE_DUAL(hf->display)) {
6526 proto_item_append_text(item, fmt, hf->name, tmpval, tmpval);
6528 proto_item_append_text(item, fmt, hf->name, tmpval);
6535 DISSECTOR_ASSERT(len * 8 == hf->display);
6537 if (hf->strings && !(flags & BMT_NO_TFS)) {
6538 /* If we have true/false strings, emit full - otherwise messages
6540 const struct true_false_string *tfs =
6541 (const struct true_false_string *)hf->strings;
6544 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
6545 hf->name, tfs->true_string);
6547 } else if (!(flags & BMT_NO_FALSE)) {
6548 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
6549 hf->name, tfs->false_string);
6552 } else if (hf->bitmask & value) {
6553 /* If the flag is set, show the name */
6554 proto_item_append_text(item, "%s%s", first ? "" : ", ", hf->name);
6559 g_assert_not_reached();
6568 /* This function will dissect a sequence of bytes that describe a
6570 * hf_hdr is a 8/16/24/32 bit integer that describes the bitmask to be dissected.
6571 * This field will form an expansion under which the individual fields of the
6572 * bitmask is dissected and displayed.
6573 * This field must be of the type FT_[U]INT{8|16|24|32}.
6575 * fields is an array of pointers to int that lists all the fields of the
6576 * bitmask. These fields can be either of the type FT_BOOLEAN for flags
6577 * or another integer of the same type/size as hf_hdr with a mask specified.
6578 * This array is terminated by a NULL entry.
6580 * FT_BOOLEAN bits that are set to 1 will have the name added to the expansion.
6581 * FT_integer fields that have a value_string attached will have the
6582 * matched string displayed on the expansion line.
6585 proto_tree_add_bitmask(proto_tree *parent_tree, tvbuff_t *tvb,
6586 const guint offset, const int hf_hdr,
6587 const gint ett, const int **fields,
6588 const gboolean little_endian)
6590 proto_item *item = NULL;
6591 header_field_info *hf;
6594 hf = proto_registrar_get_nth(hf_hdr);
6595 DISSECTOR_ASSERT(IS_FT_INT(hf->type) || IS_FT_UINT(hf->type));
6596 len = ftype_length(hf->type);
6599 item = proto_tree_add_item(parent_tree, hf_hdr, tvb, offset, len, little_endian);
6600 proto_item_add_bitmask_tree(item, tvb, offset, len, ett, fields, little_endian,
6601 BMT_NO_INT|BMT_NO_TFS, FALSE);
6607 /* The same as proto_tree_add_bitmask(), but using an arbitrary text as a top-level item */
6609 proto_tree_add_bitmask_text(proto_tree *parent_tree, tvbuff_t *tvb,
6610 const guint offset, const guint len,
6611 const char *name, const char *fallback,
6612 const gint ett, const int **fields,
6613 const gboolean little_endian, const int flags)
6615 proto_item *item = NULL;
6618 item = proto_tree_add_text(parent_tree, tvb, offset, len, "%s", name ? name : "");
6619 if (proto_item_add_bitmask_tree(item, tvb, offset, len, ett, fields, little_endian,
6620 flags, TRUE) && fallback) {
6621 /* Still at first item - append 'fallback' text if any */
6622 proto_item_append_text(item, "%s", fallback);
6630 proto_tree_add_bits_item(proto_tree *tree, const int hf_index, tvbuff_t *tvb,
6631 const gint bit_offset, const gint no_of_bits,
6632 const gboolean little_endian)
6634 header_field_info *hfinfo;
6636 TRY_TO_FAKE_THIS_ITEM(tree, hf_index, hfinfo);
6638 return proto_tree_add_bits_ret_val(tree, hf_index, tvb, bit_offset, no_of_bits, NULL, little_endian);
6642 * This function will dissect a sequence of bits that does not need to be byte aligned; the bits
6643 * set will be shown in the tree as ..10 10.. and the integer value returned if return_value is set.
6644 * Offset should be given in bits from the start of the tvb.
6648 _proto_tree_add_bits_ret_val(proto_tree *tree, const int hf_index, tvbuff_t *tvb,
6649 const gint bit_offset, const gint no_of_bits,
6650 guint64 *return_value, const gboolean little_endian)
6652 const char *format = NULL;
6657 header_field_info *hf_field;
6659 const true_false_string *tfstring;
6661 /* We can't fake it just yet. We have to fill in the 'return_value' parameter */
6662 PROTO_REGISTRAR_GET_NTH(hf_index, hf_field);
6664 if(hf_field -> bitmask != 0) {
6665 REPORT_DISSECTOR_BUG(ep_strdup_printf("Incompatible use of proto_tree_add_bits_ret_val with field '%s' (%s) with bitmask != 0",
6666 hf_field->abbrev, hf_field->name));
6669 DISSECTOR_ASSERT(bit_offset >= 0);
6670 DISSECTOR_ASSERT(no_of_bits > 0);
6672 /* Byte align offset */
6673 offset = bit_offset>>3;
6676 * Calculate the number of octets used to hold the bits
6678 tot_no_bits = ((bit_offset&0x7)+no_of_bits);
6679 length = tot_no_bits>>3;
6680 /* If we are using part of the next octet, increase length by 1 */
6681 if (tot_no_bits & 0x07)
6684 if (no_of_bits < 9){
6685 value = tvb_get_bits8(tvb, bit_offset, no_of_bits);
6686 }else if(no_of_bits < 17){
6687 value = tvb_get_bits16(tvb, bit_offset, no_of_bits, little_endian);
6688 }else if(no_of_bits < 33){
6689 value = tvb_get_bits32(tvb, bit_offset, no_of_bits, little_endian);
6690 }else if(no_of_bits < 65){
6691 value = tvb_get_bits64(tvb, bit_offset, no_of_bits, little_endian);
6693 DISSECTOR_ASSERT_NOT_REACHED();
6698 *return_value=value;
6701 /* Coast clear. Try and fake it */
6702 TRY_TO_FAKE_THIS_ITEM(tree, hf_index, hf_field);
6704 str = decode_bits_in_field(bit_offset, no_of_bits, value);
6707 strcat(str,hf_field->name);
6709 switch(hf_field->type){
6712 tfstring = (const true_false_string *) &tfs_true_false;
6713 if (hf_field->strings)
6714 tfstring = (const true_false_string *) hf_field->strings;
6715 return proto_tree_add_boolean_format(tree, hf_index, tvb, offset, length, (guint32)value,
6718 (guint32)value ? tfstring->true_string : tfstring->false_string);
6725 /* 1 - 32 bits field */
6726 if (hf_field->strings) {
6727 return proto_tree_add_uint_format(tree, hf_index, tvb, offset, length, (guint32)value,
6729 str, (hf_field->display & BASE_RANGE_STRING) ?
6730 rval_to_str((guint32)value, hf_field->strings, "Unknown ") :
6731 (hf_field->display & BASE_EXT_STRING) ?
6732 val_to_str_ext((guint32)value, (value_string_ext *) (hf_field->strings), "Unknown ") :
6733 val_to_str((guint32)value, cVALS(hf_field->strings), "Unknown "),
6737 /* Pick the proper format string */
6738 format = hfinfo_uint_format(hf_field);
6739 if (IS_BASE_DUAL(hf_field->display)) {
6740 return proto_tree_add_uint_format(tree, hf_index, tvb, offset, length, (guint32)value,
6741 format, str, (guint32)value, (guint32)value);
6743 return proto_tree_add_uint_format(tree, hf_index, tvb, offset, length, (guint32)value,
6744 format, str, (guint32)value);
6749 /* Pick the proper format string */
6750 format = hfinfo_uint64_format(hf_field);
6751 if (IS_BASE_DUAL(hf_field->display)) {
6752 return proto_tree_add_uint64_format(tree, hf_index, tvb, offset, length, value,
6753 format, str, value, value);
6755 return proto_tree_add_uint64_format(tree, hf_index, tvb, offset, length, value,
6756 format, str, value);
6761 DISSECTOR_ASSERT_NOT_REACHED();
6768 proto_tree_add_bits_ret_val(proto_tree *tree, const int hf_index, tvbuff_t *tvb,
6769 const gint bit_offset, const gint no_of_bits,
6770 guint64 *return_value, const gboolean little_endian)
6774 if ((item = _proto_tree_add_bits_ret_val(tree, hf_index, tvb, bit_offset, no_of_bits, return_value, little_endian))) {
6775 FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_OFFSET(bit_offset));
6776 FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_SIZE(no_of_bits));
6782 _proto_tree_add_bits_format_value(proto_tree *tree, const int hf_index,
6783 tvbuff_t *tvb, const gint bit_offset,
6784 const gint no_of_bits, void *value_ptr,
6791 header_field_info *hf_field;
6794 /* We do not have to return a value, try to fake it as soon as possible */
6795 TRY_TO_FAKE_THIS_ITEM(tree, hf_index, hf_field);
6797 if(hf_field -> bitmask != 0) {
6798 REPORT_DISSECTOR_BUG(ep_strdup_printf("Incompatible use of proto_tree_add_bits_ret_val with field '%s' (%s) with bitmask != 0",
6799 hf_field->abbrev, hf_field->name));
6802 DISSECTOR_ASSERT(bit_offset >= 0);
6803 DISSECTOR_ASSERT(no_of_bits > 0);
6805 /* Byte align offset */
6806 offset = bit_offset>>3;
6809 * Calculate the number of octets used to hold the bits
6811 tot_no_bits = ((bit_offset&0x7)+no_of_bits);
6812 length = tot_no_bits>>3;
6813 /* If we are using part of the next octet, increase length by 1 */
6814 if (tot_no_bits & 0x07)
6817 if (no_of_bits < 9){
6818 value = tvb_get_bits8(tvb, bit_offset, no_of_bits);
6819 }else if(no_of_bits < 17){
6820 value = tvb_get_bits16(tvb, bit_offset, no_of_bits, FALSE);
6821 }else if(no_of_bits < 33){
6822 value = tvb_get_bits32(tvb, bit_offset, no_of_bits, FALSE);
6823 }else if(no_of_bits < 65){
6824 value = tvb_get_bits64(tvb, bit_offset, no_of_bits, FALSE);
6826 DISSECTOR_ASSERT_NOT_REACHED();
6830 str = decode_bits_in_field(bit_offset, no_of_bits, value);
6833 strcat(str,hf_field->name);
6836 * This function does not receive an actual value but a dimensionless pointer to that value.
6837 * For this reason, the type of the header field is examined in order to determine
6838 * what kind of value we should read from this address.
6839 * The caller of this function must make sure that for the specific header field type the address of
6840 * a compatible value is provided.
6842 switch(hf_field->type){
6844 return proto_tree_add_boolean_format(tree, hf_index, tvb, offset, length, *(guint32 *)value_ptr,
6845 "%s: %s", str, value_str);
6852 return proto_tree_add_uint_format(tree, hf_index, tvb, offset, length, *(guint32 *)value_ptr,
6853 "%s: %s", str, value_str);
6857 return proto_tree_add_uint64_format(tree, hf_index, tvb, offset, length, *(guint64 *)value_ptr,
6858 "%s: %s", str, value_str);
6865 return proto_tree_add_int_format(tree, hf_index, tvb, offset, length, *(gint32 *)value_ptr,
6866 "%s: %s", str, value_str);
6870 return proto_tree_add_float_format(tree, hf_index, tvb, offset, length, *(float *)value_ptr,
6871 "%s: %s", str, value_str);
6875 DISSECTOR_ASSERT_NOT_REACHED();
6882 proto_tree_add_bits_format_value(proto_tree *tree, const int hf_index,
6883 tvbuff_t *tvb, const gint bit_offset,
6884 const gint no_of_bits, void *value_ptr,
6889 if ((item = _proto_tree_add_bits_format_value(tree, hf_index, tvb, bit_offset, no_of_bits, value_ptr, value_str))) {
6890 FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_OFFSET(bit_offset));
6891 FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_SIZE(no_of_bits));
6896 #define CREATE_VALUE_STRING(dst,format,ap) \
6897 va_start(ap,format); \
6898 dst = ep_strdup_vprintf(format, ap); \
6902 proto_tree_add_uint_bits_format_value(proto_tree *tree, const int hf_index,
6903 tvbuff_t *tvb, const gint bit_offset,
6904 const gint no_of_bits, guint32 value,
6905 const char *format, ...)
6909 header_field_info *hf_field;
6911 TRY_TO_FAKE_THIS_ITEM(tree, hf_index, hf_field);
6913 switch(hf_field->type){
6921 DISSECTOR_ASSERT_NOT_REACHED();
6926 CREATE_VALUE_STRING(dst,format,ap);
6928 return proto_tree_add_bits_format_value(tree, hf_index, tvb, bit_offset, no_of_bits, &value, dst);
6932 proto_tree_add_float_bits_format_value(proto_tree *tree, const int hf_index,
6933 tvbuff_t *tvb, const gint bit_offset,
6934 const gint no_of_bits, float value,
6935 const char *format, ...)
6939 header_field_info *hf_field;
6941 TRY_TO_FAKE_THIS_ITEM(tree, hf_index, hf_field);
6943 DISSECTOR_ASSERT(hf_field->type == FT_FLOAT);
6945 CREATE_VALUE_STRING(dst,format,ap);
6947 return proto_tree_add_bits_format_value(tree, hf_index, tvb, bit_offset, no_of_bits, &value, dst);
6951 proto_tree_add_int_bits_format_value(proto_tree *tree, const int hf_index,
6952 tvbuff_t *tvb, const gint bit_offset,
6953 const gint no_of_bits, gint32 value,
6954 const char *format, ...)
6958 header_field_info *hf_field;
6960 TRY_TO_FAKE_THIS_ITEM(tree, hf_index, hf_field);
6962 switch(hf_field->type){
6970 DISSECTOR_ASSERT_NOT_REACHED();
6975 CREATE_VALUE_STRING(dst,format,ap);
6977 return proto_tree_add_bits_format_value(tree, hf_index, tvb, bit_offset, no_of_bits, &value, dst);
6981 proto_tree_add_boolean_bits_format_value(proto_tree *tree, const int hf_index,
6982 tvbuff_t *tvb, const gint bit_offset,
6983 const gint no_of_bits, guint32 value,
6984 const char *format, ...)
6988 header_field_info *hf_field;
6990 TRY_TO_FAKE_THIS_ITEM(tree, hf_index, hf_field);
6992 DISSECTOR_ASSERT(hf_field->type == FT_BOOLEAN);
6994 CREATE_VALUE_STRING(dst,format,ap);
6996 return proto_tree_add_bits_format_value(tree, hf_index, tvb, bit_offset, no_of_bits, &value, dst);
7000 proto_check_field_name(const gchar *field_name)
7002 return wrs_check_charset(fld_abbrev_chars, field_name);