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"
49 #ifdef NEED_G_ASCII_STRCASECMP_H
50 #include "g_ascii_strcasecmp.h"
53 #define SUBTREE_ONCE_ALLOCATION_NUMBER 8
54 #define SUBTREE_MAX_LEVELS 256
57 typedef struct __subtree_lvl {
64 subtree_lvl *pushed_tree;
65 guint8 pushed_tree_index;
66 guint8 pushed_tree_max;
72 /* Candidates for assembler */
74 wrs_count_bitshift(guint32 bitmask)
78 while ((bitmask & (1 << bitshift)) == 0)
85 #if GLIB_MAJOR_VERSION < 2
86 static void *discard_const(const void *const_ptr)
89 const void *const_ptr;
93 stupid_const.const_ptr = const_ptr;
95 return stupid_const.ptr;
99 #define cVALS(x) (const value_string*)(x)
102 #define TRY_TO_FAKE_THIS_ITEM(tree, hfindex) \
103 /* If this item is not referenced we dont have to do much work \
104 at all but we should still return a node so that \
105 field items below this node ( think proto_item_add_subtree() )\
106 will still have somewhere to attach to \
107 or else filtering will not work (they would be ignored since tree\
109 DONT try to fake a node where PITEM_FINFO(pi) is NULL \
110 since dissectors that want to do proto_item_set_len() or \
111 other operations that dereference this would crash. \
112 We dont fake FT_PROTOCOL either since these are cheap and \
113 some stuff (proto hier stat) assumes they always exist. \
115 if(!(PTREE_DATA(tree)->visible)){ \
116 if(PITEM_FINFO(tree)){ \
117 register header_field_info *hfinfo; \
118 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo); \
119 if((hfinfo->ref_count == 0) \
120 && (hfinfo->type!=FT_PROTOCOL)){ \
121 /* just return tree back to the caller */\
127 #define TRY_TO_FAKE_THIS_ITEM(tree, hfindex) ;
131 proto_tree_free_node(proto_node *node, gpointer data);
133 static void fill_label_boolean(field_info *fi, gchar *label_str);
134 static void fill_label_uint(field_info *fi, gchar *label_str);
135 static void fill_label_uint64(field_info *fi, gchar *label_str);
136 static void fill_label_enumerated_uint(field_info *fi, gchar *label_str);
137 static void fill_label_enumerated_bitfield(field_info *fi, gchar *label_str);
138 static void fill_label_numeric_bitfield(field_info *fi, gchar *label_str);
139 static void fill_label_int(field_info *fi, gchar *label_str);
140 static void fill_label_int64(field_info *fi, gchar *label_str);
141 static void fill_label_enumerated_int(field_info *fi, gchar *label_str);
143 int hfinfo_bitwidth(header_field_info *hfinfo);
144 static const char* hfinfo_uint_vals_format(header_field_info *hfinfo);
145 static const char* hfinfo_uint_format(header_field_info *hfinfo);
146 static const char* hfinfo_uint64_format(header_field_info *hfinfo);
147 static const char* hfinfo_int_vals_format(header_field_info *hfinfo);
148 static const char* hfinfo_int_format(header_field_info *hfinfo);
149 static const char* hfinfo_int64_format(header_field_info *hfinfo);
152 proto_tree_add_node(proto_tree *tree, field_info *fi);
154 static header_field_info *
155 get_hfi_and_length(int hfindex, tvbuff_t *tvb, gint start, gint *length,
159 new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
160 gint start, gint item_length);
163 alloc_field_info(proto_tree *tree, int hfindex, tvbuff_t *tvb,
164 gint start, gint *length);
167 proto_tree_add_pi(proto_tree *tree, int hfindex, tvbuff_t *tvb,
168 gint start, gint *length, field_info **pfi);
171 proto_tree_set_representation_value(proto_item *pi, const char *format, va_list ap);
173 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap);
176 proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb);
178 proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length);
180 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length);
182 proto_tree_set_time(field_info *fi, nstime_t *value_ptr);
184 proto_tree_set_string(field_info *fi, const char* value);
186 proto_tree_set_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
188 proto_tree_set_ebcdic_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
190 proto_tree_set_ether(field_info *fi, const guint8* value);
192 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start);
194 proto_tree_set_ipxnet(field_info *fi, guint32 value);
196 proto_tree_set_ipv4(field_info *fi, guint32 value);
198 proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr);
200 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start);
202 proto_tree_set_guid(field_info *fi, const e_guid_t *value_ptr);
204 proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gboolean little_endian);
206 proto_tree_set_oid(field_info *fi, const guint8* value_ptr, gint length);
208 proto_tree_set_oid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
210 proto_tree_set_boolean(field_info *fi, guint32 value);
212 proto_tree_set_float(field_info *fi, float value);
214 proto_tree_set_double(field_info *fi, double value);
216 proto_tree_set_uint(field_info *fi, guint32 value);
218 proto_tree_set_int(field_info *fi, gint32 value);
220 proto_tree_set_uint64(field_info *fi, guint64 value);
222 proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start, guint length, gboolean little_endian);
224 static int proto_register_field_init(header_field_info *hfinfo, int parent);
226 /* special-case header field used within proto.c */
227 int hf_text_only = -1;
229 /* Structure for information about a protocol */
231 const char *name; /* long description */
232 const char *short_name; /* short description */
233 const char *filter_name; /* name of this protocol in filters */
234 int proto_id; /* field ID for this protocol */
235 GList *fields; /* fields for this protocol */
236 GList *last_field; /* pointer to end of list of fields */
237 gboolean is_enabled; /* TRUE if protocol is enabled */
238 gboolean can_toggle; /* TRUE if is_enabled can be changed */
241 /* List of all protocols */
242 static GList *protocols = NULL;
244 #define INITIAL_NUM_PROTOCOL_HFINFO 200
247 /* Contains information about protocols and header fields. Used when
248 * dissectors register their data */
249 static GMemChunk *gmc_hfinfo = NULL;
251 /* Contains information about a field when a dissector calls
252 * proto_tree_add_item. */
253 SLAB_ITEM_TYPE_DEFINE(field_info)
254 static SLAB_FREE_LIST_DEFINE(field_info)
255 static field_info *field_info_tmp=NULL;
256 #define FIELD_INFO_NEW(fi) \
257 SLAB_ALLOC(fi, field_info)
258 #define FIELD_INFO_FREE(fi) \
259 SLAB_FREE(fi, field_info)
263 /* Contains the space for proto_nodes. */
264 SLAB_ITEM_TYPE_DEFINE(proto_node)
265 static SLAB_FREE_LIST_DEFINE(proto_node)
266 #define PROTO_NODE_NEW(node) \
267 SLAB_ALLOC(node, proto_node) \
268 node->first_child = NULL; \
269 node->last_child = NULL; \
272 #define PROTO_NODE_FREE(node) \
273 SLAB_FREE(node, proto_node)
277 /* String space for protocol and field items for the GUI */
278 SLAB_ITEM_TYPE_DEFINE(item_label_t)
279 static SLAB_FREE_LIST_DEFINE(item_label_t)
280 #define ITEM_LABEL_NEW(il) \
281 SLAB_ALLOC(il, item_label_t)
282 #define ITEM_LABEL_FREE(il) \
283 SLAB_FREE(il, item_label_t)
286 #define PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo) \
287 DISSECTOR_ASSERT((guint)hfindex < gpa_hfinfo.len); \
288 hfinfo=gpa_hfinfo.hfi[hfindex];
291 /* List which stores protocols and fields that have been registered */
292 typedef struct _gpa_hfinfo_t {
294 guint32 allocated_len;
295 header_field_info **hfi;
297 gpa_hfinfo_t gpa_hfinfo;
299 /* Balanced tree of abbreviations and IDs */
300 static GTree *gpa_name_tree = NULL;
301 static header_field_info *same_name_hfinfo;
303 #if GLIB_MAJOR_VERSION >= 2
304 static void save_same_name_hfinfo(gpointer data)
306 same_name_hfinfo = (header_field_info*)data;
310 /* Points to the first element of an array of Booleans, indexed by
311 a subtree item type; that array element is TRUE if subtrees of
312 an item of that type are to be expanded. */
313 gboolean *tree_is_expanded;
315 /* Number of elements in that array. */
318 /* Name hashtables for fast detection of duplicate names */
319 static GHashTable* proto_names = NULL;
320 static GHashTable* proto_short_names = NULL;
321 static GHashTable* proto_filter_names = NULL;
324 proto_compare_name(gconstpointer p1_arg, gconstpointer p2_arg)
326 const protocol_t *p1 = p1_arg;
327 const protocol_t *p2 = p2_arg;
329 return g_ascii_strcasecmp(p1->short_name, p2->short_name);
333 /* initialize data structures and register protocols and fields */
335 proto_init(void (register_all_protocols)(register_cb cb, gpointer client_data),
336 void (register_all_protocol_handoffs)(register_cb cb, gpointer client_data),
338 gpointer client_data)
340 static hf_register_info hf[] = {
342 { "Text item", "", FT_NONE, BASE_NONE, NULL, 0x0,
347 proto_names = g_hash_table_new(g_int_hash, g_int_equal);
348 proto_short_names = g_hash_table_new(wrs_str_hash, g_str_equal);
349 proto_filter_names = g_hash_table_new(wrs_str_hash, g_str_equal);
353 gmc_hfinfo = g_mem_chunk_new("gmc_hfinfo",
354 sizeof(header_field_info),
355 INITIAL_NUM_PROTOCOL_HFINFO * sizeof(header_field_info),
359 gpa_hfinfo.allocated_len=0;
361 #if GLIB_MAJOR_VERSION < 2
362 gpa_name_tree = g_tree_new(wrs_strcmp);
364 gpa_name_tree = g_tree_new_full(wrs_strcmp_with_data, NULL, NULL, save_same_name_hfinfo);
367 /* Initialize the ftype subsystem */
370 /* Register one special-case FT_TEXT_ONLY field for use when
371 converting wireshark to new-style proto_tree. These fields
372 are merely strings on the GUI tree; they are not filterable */
373 proto_register_field_array(-1, hf, array_length(hf));
375 /* Have each built-in dissector register its protocols, fields,
376 dissector tables, and dissectors to be called through a
377 handle, and do whatever one-time initialization it needs to
379 register_all_protocols(cb, client_data);
382 /* Now scan for plugins and load all the ones we find, calling
383 their register routines to do the stuff described above. */
385 (*cb)(RA_PLUGIN_REGISTER, NULL, client_data);
387 register_all_plugin_registrations();
390 /* Now call the "handoff registration" routines of all built-in
391 dissectors; those routines register the dissector in other
392 dissectors' handoff tables, and fetch any dissector handles
394 register_all_protocol_handoffs(cb, client_data);
397 /* Now do the same with plugins. */
399 (*cb)(RA_PLUGIN_HANDOFF, NULL, client_data);
400 register_all_plugin_handoffs();
403 /* sort the protocols by protocol name */
404 protocols = g_list_sort(protocols, proto_compare_name);
406 /* We've assigned all the subtree type values; allocate the array
407 for them, and zero it out. */
408 tree_is_expanded = g_malloc(num_tree_types*sizeof (gboolean));
409 memset(tree_is_expanded, 0, num_tree_types*sizeof (gboolean));
415 /* Free the abbrev/ID GTree */
417 g_tree_destroy(gpa_name_tree);
418 gpa_name_tree = NULL;
422 g_mem_chunk_destroy(gmc_hfinfo);
424 if(gpa_hfinfo.allocated_len){
426 gpa_hfinfo.allocated_len=0;
427 g_free(gpa_hfinfo.hfi);
430 if (tree_is_expanded != NULL)
431 g_free(tree_is_expanded);
436 proto_tree_traverse_pre_order(proto_tree *tree, proto_tree_traverse_func func,
439 proto_node *pnode = tree;
443 if (func(pnode, data))
446 child = pnode->first_child;
447 while (child != NULL) {
449 * The routine we call might modify the child, e.g. by
450 * freeing it, so we get the child's successor before
451 * calling that routine.
454 child = current->next;
455 if (proto_tree_traverse_pre_order((proto_tree *)current, func,
464 proto_tree_traverse_in_order(proto_tree *tree, proto_tree_traverse_func func,
467 proto_node *pnode = tree;
471 child = pnode->first_child;
474 * The routine we call might modify the child, e.g. by
475 * freeing it, so we get the child's successor before
476 * calling that routine.
479 child = current->next;
481 if (proto_tree_traverse_in_order((proto_tree *)current, func,
485 if (func(pnode, data))
488 while (child != NULL) {
490 * The routine we call might modify the child, e.g. by
491 * freeing it, so we get the child's successor before
492 * calling that routine.
495 child = current->next;
496 if (proto_tree_traverse_in_order((proto_tree *)current,
501 if (func(pnode, data))
509 proto_tree_children_foreach(proto_tree *tree, proto_tree_foreach_func func,
512 proto_node *node = tree;
515 node = node->first_child;
516 while (node != NULL) {
518 node = current->next;
519 func((proto_tree *)current, data);
523 /* frees the resources that the dissection a proto_tree uses */
525 proto_tree_free(proto_tree *tree)
527 proto_tree_traverse_in_order(tree, proto_tree_free_node, NULL);
531 free_GPtrArray_value(gpointer key, gpointer value, gpointer user_data _U_)
533 GPtrArray *ptrs = value;
534 gint hfid = (gint)(long)key;
535 header_field_info *hfinfo;
538 PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
539 if(hfinfo->ref_count){
540 /* when a field is referenced by a filter this also
541 affects the refcount for the parent protocol so we need
542 to adjust the refcount for the parent as well
544 if( (hfinfo->parent != -1) && (hfinfo->ref_count) ){
545 header_field_info *parent_hfinfo;
546 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
547 parent_hfinfo->ref_count -= hfinfo->ref_count;
549 hfinfo->ref_count = 0;
552 g_ptr_array_free(ptrs, TRUE);
556 free_node_tree_data(tree_data_t *tree_data)
558 /* Free all the GPtrArray's in the interesting_hfids hash. */
559 g_hash_table_foreach(tree_data->interesting_hfids,
560 free_GPtrArray_value, NULL);
562 /* And then destroy the hash. */
563 g_hash_table_destroy(tree_data->interesting_hfids);
565 /* And finally the tree_data_t itself. */
569 #define FREE_NODE_FIELD_INFO(finfo) \
571 ITEM_LABEL_FREE(finfo->rep); \
573 FVALUE_CLEANUP(&finfo->value); \
574 FIELD_INFO_FREE(finfo);
577 proto_tree_free_node(proto_node *node, gpointer data _U_)
579 field_info *finfo = PITEM_FINFO(node);
582 /* This is the root node. Destroy the per-tree data.
583 * There is no field_info to destroy. */
584 free_node_tree_data(PTREE_DATA(node));
587 /* This is a child node. Don't free the per-tree data, but
588 * do free the field_info data. */
589 FREE_NODE_FIELD_INFO(finfo);
592 /* Free the proto_node. */
593 PROTO_NODE_FREE(node);
595 return FALSE; /* FALSE = do not end traversal of protocol tree */
598 /* Is the parsing being done for a visible proto_tree or an invisible one?
599 * By setting this correctly, the proto_tree creation is sped up by not
600 * having to call g_vsnprintf and copy strings around.
603 proto_tree_set_visible(proto_tree *tree, gboolean visible)
605 PTREE_DATA(tree)->visible = visible;
608 /* Assume dissector set only its protocol fields.
609 This function is called by dissectors and allowes to speed up filtering
610 in wireshark, if this function returns FALSE it is safe to reset tree to NULL
611 and thus skip calling most of the expensive proto_tree_add_...()
613 If the tree is visible we implicitely assume the field is referenced.
616 proto_field_is_referenced(proto_tree *tree, int proto_id)
618 register header_field_info *hfinfo;
624 if (PTREE_DATA(tree)->visible)
627 PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
628 if (hfinfo->ref_count != 0)
635 /* Finds a record in the hf_info_records array by id. */
637 proto_registrar_get_nth(guint hfindex)
639 register header_field_info *hfinfo;
641 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
645 /* Finds a record in the hf_info_records array by name.
648 proto_registrar_get_byname(const char *field_name)
650 DISSECTOR_ASSERT(field_name != NULL);
651 #if GLIB_MAJOR_VERSION < 2
652 return g_tree_lookup(gpa_name_tree, discard_const(field_name));
654 return g_tree_lookup(gpa_name_tree, field_name);
659 void ptvcursor_new_subtree_levels(ptvcursor_t * ptvc)
661 subtree_lvl * pushed_tree;
663 DISSECTOR_ASSERT(ptvc->pushed_tree_max <= SUBTREE_MAX_LEVELS-SUBTREE_ONCE_ALLOCATION_NUMBER);
664 ptvc->pushed_tree_max += SUBTREE_ONCE_ALLOCATION_NUMBER;
666 pushed_tree = ep_alloc(sizeof(subtree_lvl) * ptvc->pushed_tree_max);
667 DISSECTOR_ASSERT(pushed_tree != NULL);
668 if (ptvc->pushed_tree)
669 memcpy(pushed_tree, ptvc->pushed_tree, ptvc->pushed_tree_max - SUBTREE_ONCE_ALLOCATION_NUMBER);
670 ptvc->pushed_tree = pushed_tree;
673 void ptvcursor_free_subtree_levels(ptvcursor_t * ptvc)
675 ptvc->pushed_tree = NULL;
676 ptvc->pushed_tree_max = 0;
677 DISSECTOR_ASSERT(ptvc->pushed_tree_index ==0);
678 ptvc->pushed_tree_index = 0;
681 /* Allocates an initializes a ptvcursor_t with 3 variables:
682 * proto_tree, tvbuff, and offset. */
684 ptvcursor_new(proto_tree *tree, tvbuff_t *tvb, gint offset)
688 ptvc = ep_alloc(sizeof(ptvcursor_t));
691 ptvc->offset = offset;
692 ptvc->pushed_tree= NULL;
693 ptvc->pushed_tree_max= 0;
694 ptvc->pushed_tree_index= 0;
699 /* Frees memory for ptvcursor_t, but nothing deeper than that. */
701 ptvcursor_free(ptvcursor_t *ptvc)
703 ptvcursor_free_subtree_levels(ptvc);
707 /* Returns tvbuff. */
709 ptvcursor_tvbuff(ptvcursor_t* ptvc)
714 /* Returns current offset. */
716 ptvcursor_current_offset(ptvcursor_t* ptvc)
722 ptvcursor_tree(ptvcursor_t* ptvc)
731 ptvcursor_set_tree(ptvcursor_t* ptvc, proto_tree *tree)
736 /* creates a subtree, sets it as the working tree and pushes the old working tree */
738 ptvcursor_push_subtree(ptvcursor_t *ptvc, proto_item *it, gint ett_subtree)
740 subtree_lvl * subtree;
741 if (ptvc->pushed_tree_index >= ptvc->pushed_tree_max)
742 ptvcursor_new_subtree_levels(ptvc);
744 subtree = ptvc->pushed_tree+ptvc->pushed_tree_index;
745 subtree->tree = ptvc->tree;
747 ptvc->pushed_tree_index++;
748 return ptvcursor_set_subtree(ptvc, it, ett_subtree);
753 ptvcursor_pop_subtree(ptvcursor_t *ptvc)
755 subtree_lvl * subtree;
756 if (ptvc->pushed_tree_index <= 0)
759 ptvc->pushed_tree_index--;
760 subtree = ptvc->pushed_tree+ptvc->pushed_tree_index;
761 if (subtree->it != NULL)
762 proto_item_set_len(subtree->it, ptvcursor_current_offset(ptvc) - subtree->cursor_offset);
763 ptvc->tree = subtree->tree;
766 /* saves the current tvb offset and the item in the current subtree level */
767 void ptvcursor_subtree_set_item(ptvcursor_t * ptvc, proto_item * it)
769 subtree_lvl * subtree;
771 DISSECTOR_ASSERT(ptvc->pushed_tree_index > 0);
773 subtree = ptvc->pushed_tree+ptvc->pushed_tree_index-1;
775 subtree->cursor_offset = ptvcursor_current_offset(ptvc);
778 /* Creates a subtree and adds it to the cursor as the working tree but does not
779 * save the old working tree */
781 ptvcursor_set_subtree(ptvcursor_t *ptvc, proto_item *it, gint ett_subtree)
783 ptvc->tree = proto_item_add_subtree(it, ett_subtree);
787 proto_tree* ptvcursor_add_subtree_item(ptvcursor_t * ptvc, proto_item * it, gint ett_subtree, gint length)
789 ptvcursor_push_subtree(ptvc, it, ett_subtree);
790 if (length == SUBTREE_UNDEFINED_LENGTH)
791 ptvcursor_subtree_set_item(ptvc, it);
792 return ptvcursor_tree(ptvc);
795 /* Add an item to the tree and create a subtree
796 * If the length is unknown, length may be defined as SUBTREE_UNDEFINED_LENGTH.
797 * In this case, when the subtree will be closed, the parent item length will
798 * be equal to the advancement of the cursor since the creation of the subtree.
800 proto_tree* ptvcursor_add_with_subtree(ptvcursor_t * ptvc, int hfindex, gint length,
801 gboolean little_endian, gint ett_subtree)
804 it = ptvcursor_add_no_advance(ptvc, hfindex, length, little_endian);
805 return ptvcursor_add_subtree_item(ptvc, it, ett_subtree, length);
809 proto_tree_add_text_node(proto_tree *tree, tvbuff_t *tvb, gint start, gint length);
811 /* Add a text node to the tree and create a subtree
812 * If the length is unknown, length may be defined as SUBTREE_UNDEFINED_LENGTH.
813 * In this case, when the subtree will be closed, the item length will be equal
814 * to the advancement of the cursor since the creation of the subtree.
816 proto_tree * ptvcursor_add_text_with_subtree(ptvcursor_t * ptvc, gint length,
817 gint ett_subtree, const char *format, ...)
822 it = proto_tree_add_text_node(ptvcursor_tree(ptvc), ptvcursor_tvbuff(ptvc),
823 ptvcursor_current_offset(ptvc), length);
825 va_start(ap, format);
826 proto_tree_set_representation(it, format, ap);
829 return ptvcursor_add_subtree_item(ptvc, it, ett_subtree, length);
832 /* Add a text-only node, leaving it to our caller to fill the text in */
834 proto_tree_add_text_node(proto_tree *tree, tvbuff_t *tvb, gint start, gint length)
838 pi = proto_tree_add_pi(tree, hf_text_only, tvb, start, &length, NULL);
845 /* Add a text-only node to the proto_tree */
847 proto_tree_add_text(proto_tree *tree, tvbuff_t *tvb, gint start, gint length,
848 const char *format, ...)
853 pi = proto_tree_add_text_node(tree, tvb, start, length);
857 va_start(ap, format);
858 proto_tree_set_representation(pi, format, ap);
864 /* Add a text-only node to the proto_tree (va_list version) */
866 proto_tree_add_text_valist(proto_tree *tree, tvbuff_t *tvb, gint start,
867 gint length, const char *format, va_list ap)
871 pi = proto_tree_add_text_node(tree, tvb, start, length);
875 proto_tree_set_representation(pi, format, ap);
880 /* Add a text-only node for debugging purposes. The caller doesn't need
881 * to worry about tvbuff, start, or length. Debug message gets sent to
884 proto_tree_add_debug_text(proto_tree *tree, const char *format, ...)
889 pi = proto_tree_add_text_node(tree, NULL, 0, 0);
893 va_start(ap, format);
894 proto_tree_set_representation(pi, format, ap);
904 get_uint_value(tvbuff_t *tvb, gint offset, gint length, gboolean little_endian)
911 value = tvb_get_guint8(tvb, offset);
915 value = little_endian ? tvb_get_letohs(tvb, offset)
916 : tvb_get_ntohs(tvb, offset);
920 value = little_endian ? tvb_get_letoh24(tvb, offset)
921 : tvb_get_ntoh24(tvb, offset);
925 value = little_endian ? tvb_get_letohl(tvb, offset)
926 : tvb_get_ntohl(tvb, offset);
930 DISSECTOR_ASSERT_NOT_REACHED();
938 get_int_value(tvbuff_t *tvb, gint offset, gint length, gboolean little_endian)
945 value = (gint8)tvb_get_guint8(tvb, offset);
949 value = (gint16) (little_endian ? tvb_get_letohs(tvb, offset)
950 : tvb_get_ntohs(tvb, offset));
954 value = little_endian ? tvb_get_letoh24(tvb, offset)
955 : tvb_get_ntoh24(tvb, offset);
956 if (value & 0x00800000) {
957 /* Sign bit is set; sign-extend it. */
963 value = little_endian ? tvb_get_letohl(tvb, offset)
964 : tvb_get_ntohl(tvb, offset);
968 DISSECTOR_ASSERT_NOT_REACHED();
975 /* Add an item to a proto_tree, using the text label registered to that item;
976 the item is extracted from the tvbuff handed to it. */
978 proto_tree_new_item(field_info *new_fi, proto_tree *tree, int hfindex,
979 tvbuff_t *tvb, gint start, gint length, gboolean little_endian)
989 /* there is a possibility here that we might raise an exception
990 * and thus would lose track of the field_info.
991 * store it in a temp so that if we come here again we can reclaim
992 * the field_info without leaking memory.
994 /* XXX this only keeps track of one field_info struct,
995 if we ever go multithreaded for calls to this function
996 we have to change this code to use per thread variable.
999 /* oops, last one we got must have been lost due
1001 * good thing we saved it, now we can reverse the
1002 * memory leak and reclaim it.
1004 SLAB_FREE(field_info_tmp, field_info);
1006 /* we might throw an exception, keep track of this one
1007 * across the "dangerous" section below.
1009 field_info_tmp=new_fi;
1011 switch(new_fi->hfinfo->type) {
1013 /* no value to set for FT_NONE */
1017 proto_tree_set_protocol_tvb(new_fi, tvb);
1021 proto_tree_set_bytes_tvb(new_fi, tvb, start, length);
1025 n = get_uint_value(tvb, start, length, little_endian);
1026 proto_tree_set_bytes_tvb(new_fi, tvb, start + length, n);
1028 /* Instead of calling proto_item_set_len(), since we don't yet
1029 * have a proto_item, we set the field_info's length ourselves. */
1030 new_fi->length = n + length;
1034 proto_tree_set_boolean(new_fi,
1035 get_uint_value(tvb, start, length, little_endian));
1038 /* XXX - make these just FT_UINT? */
1043 proto_tree_set_uint(new_fi,
1044 get_uint_value(tvb, start, length, little_endian));
1049 DISSECTOR_ASSERT( length <= 8 && length >= 1);
1050 proto_tree_set_uint64_tvb(new_fi, tvb, start, length, little_endian);
1053 /* XXX - make these just FT_INT? */
1058 proto_tree_set_int(new_fi,
1059 get_int_value(tvb, start, length, little_endian));
1063 DISSECTOR_ASSERT(length == 4);
1064 value = tvb_get_ipv4(tvb, start);
1065 proto_tree_set_ipv4(new_fi, little_endian ? GUINT32_SWAP_LE_BE(value) : value);
1069 DISSECTOR_ASSERT(length == 4);
1070 proto_tree_set_ipxnet(new_fi,
1071 get_uint_value(tvb, start, 4, FALSE));
1075 DISSECTOR_ASSERT(length == 16);
1076 proto_tree_set_ipv6_tvb(new_fi, tvb, start);
1080 DISSECTOR_ASSERT(length == 6);
1081 proto_tree_set_ether_tvb(new_fi, tvb, start);
1085 DISSECTOR_ASSERT(length == 16);
1086 proto_tree_set_guid_tvb(new_fi, tvb, start, little_endian);
1090 proto_tree_set_oid_tvb(new_fi, tvb, start, length);
1094 DISSECTOR_ASSERT(length == 4);
1096 floatval = tvb_get_letohieee_float(tvb, start);
1098 floatval = tvb_get_ntohieee_float(tvb, start);
1099 proto_tree_set_float(new_fi, floatval);
1103 DISSECTOR_ASSERT(length == 8);
1105 doubleval = tvb_get_letohieee_double(tvb, start);
1107 doubleval = tvb_get_ntohieee_double(tvb, start);
1108 proto_tree_set_double(new_fi, doubleval);
1112 proto_tree_set_string_tvb(new_fi, tvb, start, length);
1116 DISSECTOR_ASSERT(length >= -1);
1117 /* Instead of calling proto_item_set_len(),
1118 * since we don't yet have a proto_item, we
1119 * set the field_info's length ourselves.
1121 * XXX - our caller can't use that length to
1122 * advance an offset unless they arrange that
1123 * there always be a protocol tree into which
1124 * we're putting this item.
1127 /* This can throw an exception */
1128 length = tvb_strsize(tvb, start);
1130 string = ep_alloc(length);
1132 tvb_memcpy(tvb, string, start, length);
1133 } else if (length == 0) {
1136 /* In this case, length signifies
1137 * the length of the string.
1139 * This could either be a null-padded
1140 * string, which doesn't necessarily
1141 * have a '\0' at the end, or a
1142 * null-terminated string, with a
1143 * trailing '\0'. (Yes, there are
1144 * cases where you have a string
1145 * that's both counted and null-
1148 * In the first case, we must
1149 * allocate a buffer of length
1150 * "length+1", to make room for
1153 * In the second case, we don't
1154 * assume that there is a trailing
1155 * '\0' there, as the packet might
1156 * be malformed. (XXX - should we
1157 * throw an exception if there's no
1158 * trailing '\0'?) Therefore, we
1159 * allocate a buffer of length
1160 * "length+1", and put in a trailing
1161 * '\0', just to be safe.
1163 * (XXX - this would change if
1164 * we made string values counted
1165 * rather than null-terminated.)
1167 string = tvb_get_ephemeral_string(tvb,
1171 new_fi->length = length;
1172 proto_tree_set_string(new_fi, string);
1176 proto_tree_set_ebcdic_string_tvb(new_fi, tvb, start, length);
1179 case FT_UINT_STRING:
1180 n = get_uint_value(tvb, start, length, little_endian);
1181 proto_tree_set_string_tvb(new_fi, tvb, start + length, n);
1183 /* Instead of calling proto_item_set_len(), since we
1184 * don't yet have a proto_item, we set the
1185 * field_info's length ourselves.
1187 * XXX - our caller can't use that length to
1188 * advance an offset unless they arrange that
1189 * there always be a protocol tree into which
1190 * we're putting this item.
1192 new_fi->length = n + length;
1196 g_error("new_fi->hfinfo->type %d (%s) not handled\n",
1197 new_fi->hfinfo->type,
1198 ftype_name(new_fi->hfinfo->type));
1199 DISSECTOR_ASSERT_NOT_REACHED();
1203 /* Don't add new node to proto_tree until now so that any exceptions
1204 * raised by a tvbuff access method doesn't leave junk in the proto_tree. */
1205 pi = proto_tree_add_node(tree, new_fi);
1207 /* we did not raise an exception so we dont have to remember this
1208 * field_info struct any more.
1210 field_info_tmp=NULL;
1212 /* If the proto_tree wants to keep a record of this finfo
1213 * for quick lookup, then record it. */
1214 if (new_fi->hfinfo->ref_count) {
1216 hash = PTREE_DATA(tree)->interesting_hfids;
1217 ptrs = g_hash_table_lookup(hash, GINT_TO_POINTER(hfindex));
1219 g_ptr_array_add(ptrs, new_fi);
1226 /* Gets data from tvbuff, adds it to proto_tree, increments offset,
1227 and returns proto_item* */
1229 ptvcursor_add(ptvcursor_t *ptvc, int hfindex, gint length,
1230 gboolean little_endian)
1233 header_field_info *hfinfo;
1238 offset = ptvc->offset;
1239 hfinfo = get_hfi_and_length(hfindex, ptvc->tvb, offset, &length,
1241 ptvc->offset += length;
1242 if (hfinfo->type == FT_UINT_BYTES || hfinfo->type == FT_UINT_STRING) {
1244 * The length of the rest of the item is in the first N
1245 * bytes of the item.
1247 n = get_uint_value(ptvc->tvb, offset, length, little_endian);
1250 if (ptvc->tree == NULL)
1253 TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfindex);
1255 new_fi = new_field_info(ptvc->tree, hfinfo, ptvc->tvb, offset,
1260 return proto_tree_new_item(new_fi, ptvc->tree, hfindex, ptvc->tvb,
1261 offset, length, little_endian);
1264 /* Add an item to a proto_tree, using the text label registered to that item;
1265 the item is extracted from the tvbuff handed to it. */
1267 proto_tree_add_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1268 gint start, gint length, gboolean little_endian)
1275 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1277 new_fi = alloc_field_info(tree, hfindex, tvb, start, &length);
1282 return proto_tree_new_item(new_fi, tree, hfindex, tvb, start,
1283 length, little_endian);
1287 proto_tree_add_item_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1288 gint start, gint length, gboolean little_endian)
1292 pi = proto_tree_add_item(tree, hfindex, tvb, start, length, little_endian);
1296 PROTO_ITEM_SET_HIDDEN(pi);
1302 /* Add a FT_NONE to a proto_tree */
1304 proto_tree_add_none_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1305 gint length, const char *format, ...)
1309 header_field_info *hfinfo;
1314 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1315 DISSECTOR_ASSERT(hfinfo->type == FT_NONE);
1317 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, NULL);
1319 va_start(ap, format);
1320 proto_tree_set_representation(pi, format, ap);
1323 /* no value to set for FT_NONE */
1327 /* Gets data from tvbuff, adds it to proto_tree, *DOES NOT* increment
1328 * offset, and returns proto_item* */
1330 ptvcursor_add_no_advance(ptvcursor_t* ptvc, int hf, gint length,
1331 gboolean endianness)
1335 item = proto_tree_add_item(ptvc->tree, hf, ptvc->tvb, ptvc->offset,
1336 length, endianness);
1341 /* Advance the ptvcursor's offset within its tvbuff without
1342 * adding anything to the proto_tree. */
1344 ptvcursor_advance(ptvcursor_t* ptvc, gint length)
1346 ptvc->offset += length;
1351 proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb)
1353 fvalue_set(&fi->value, tvb, TRUE);
1356 /* Add a FT_PROTOCOL to a proto_tree */
1358 proto_tree_add_protocol_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1359 gint length, const char *format, ...)
1363 header_field_info *hfinfo;
1369 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1370 DISSECTOR_ASSERT(hfinfo->type == FT_PROTOCOL);
1372 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1374 va_start(ap, format);
1375 proto_tree_set_representation(pi, format, ap);
1379 proto_tree_set_protocol_tvb(new_fi, tvb);
1382 proto_tree_set_protocol_tvb(new_fi, NULL);
1388 /* Add a FT_BYTES to a proto_tree */
1390 proto_tree_add_bytes(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1391 gint length, const guint8 *start_ptr)
1395 header_field_info *hfinfo;
1400 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1402 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1403 DISSECTOR_ASSERT(hfinfo->type == FT_BYTES);
1405 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1406 proto_tree_set_bytes(new_fi, start_ptr, length);
1412 proto_tree_add_bytes_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1413 gint length, const guint8 *start_ptr)
1417 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length, start_ptr);
1421 PROTO_ITEM_SET_HIDDEN(pi);
1427 proto_tree_add_bytes_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1428 gint start, gint length, const guint8 *start_ptr,
1429 const char *format, ...)
1434 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length, start_ptr);
1438 va_start(ap, format);
1439 proto_tree_set_representation_value(pi, format, ap);
1446 proto_tree_add_bytes_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1447 gint length, const guint8 *start_ptr, const char *format, ...)
1452 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length, start_ptr);
1456 va_start(ap, format);
1457 proto_tree_set_representation(pi, format, ap);
1464 proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length)
1468 bytes = g_byte_array_new();
1470 g_byte_array_append(bytes, start_ptr, length);
1472 fvalue_set(&fi->value, bytes, TRUE);
1477 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length)
1479 proto_tree_set_bytes(fi, tvb_get_ptr(tvb, offset, length), length);
1482 /* Add a FT_*TIME to a proto_tree */
1484 proto_tree_add_time(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1485 nstime_t *value_ptr)
1489 header_field_info *hfinfo;
1494 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1496 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1497 DISSECTOR_ASSERT(hfinfo->type == FT_ABSOLUTE_TIME ||
1498 hfinfo->type == FT_RELATIVE_TIME);
1500 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1501 proto_tree_set_time(new_fi, value_ptr);
1507 proto_tree_add_time_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1508 nstime_t *value_ptr)
1512 pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
1516 PROTO_ITEM_SET_HIDDEN(pi);
1522 proto_tree_add_time_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1523 gint start, gint length, nstime_t *value_ptr,
1524 const char *format, ...)
1529 pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
1533 va_start(ap, format);
1534 proto_tree_set_representation_value(pi, format, ap);
1541 proto_tree_add_time_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1542 nstime_t *value_ptr, const char *format, ...)
1547 pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
1551 va_start(ap, format);
1552 proto_tree_set_representation(pi, format, ap);
1558 /* Set the FT_*TIME value */
1560 proto_tree_set_time(field_info *fi, nstime_t *value_ptr)
1562 DISSECTOR_ASSERT(value_ptr != NULL);
1563 fvalue_set(&fi->value, value_ptr, FALSE);
1566 /* Add a FT_IPXNET to a proto_tree */
1568 proto_tree_add_ipxnet(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1573 header_field_info *hfinfo;
1578 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1580 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1581 DISSECTOR_ASSERT(hfinfo->type == FT_IPXNET);
1583 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1584 proto_tree_set_ipxnet(new_fi, value);
1590 proto_tree_add_ipxnet_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1595 pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
1599 PROTO_ITEM_SET_HIDDEN(pi);
1605 proto_tree_add_ipxnet_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1606 gint start, gint length, guint32 value, const char *format, ...)
1611 pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
1615 va_start(ap, format);
1616 proto_tree_set_representation_value(pi, format, ap);
1623 proto_tree_add_ipxnet_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1624 guint32 value, const char *format, ...)
1629 pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
1633 va_start(ap, format);
1634 proto_tree_set_representation(pi, format, ap);
1640 /* Set the FT_IPXNET value */
1642 proto_tree_set_ipxnet(field_info *fi, guint32 value)
1644 fvalue_set_uinteger(&fi->value, value);
1647 /* Add a FT_IPv4 to a proto_tree */
1649 proto_tree_add_ipv4(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1654 header_field_info *hfinfo;
1659 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1661 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1662 DISSECTOR_ASSERT(hfinfo->type == FT_IPv4);
1664 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1665 proto_tree_set_ipv4(new_fi, value);
1671 proto_tree_add_ipv4_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1676 pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
1680 PROTO_ITEM_SET_HIDDEN(pi);
1686 proto_tree_add_ipv4_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1687 gint start, gint length, guint32 value, const char *format, ...)
1692 pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
1696 va_start(ap, format);
1697 proto_tree_set_representation_value(pi, format, ap);
1704 proto_tree_add_ipv4_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1705 guint32 value, const char *format, ...)
1710 pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
1714 va_start(ap, format);
1715 proto_tree_set_representation(pi, format, ap);
1721 /* Set the FT_IPv4 value */
1723 proto_tree_set_ipv4(field_info *fi, guint32 value)
1725 fvalue_set_uinteger(&fi->value, value);
1728 /* Add a FT_IPv6 to a proto_tree */
1730 proto_tree_add_ipv6(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1731 const guint8* value_ptr)
1735 header_field_info *hfinfo;
1740 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1742 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1743 DISSECTOR_ASSERT(hfinfo->type == FT_IPv6);
1745 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1746 proto_tree_set_ipv6(new_fi, value_ptr);
1752 proto_tree_add_ipv6_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1753 const guint8* value_ptr)
1757 pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
1761 PROTO_ITEM_SET_HIDDEN(pi);
1767 proto_tree_add_ipv6_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1768 gint start, gint length, const guint8* value_ptr,
1769 const char *format, ...)
1774 pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
1778 va_start(ap, format);
1779 proto_tree_set_representation_value(pi, format, ap);
1786 proto_tree_add_ipv6_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1787 const guint8* value_ptr, const char *format, ...)
1792 pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
1796 va_start(ap, format);
1797 proto_tree_set_representation(pi, format, ap);
1803 /* Set the FT_IPv6 value */
1805 proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr)
1807 DISSECTOR_ASSERT(value_ptr != NULL);
1808 fvalue_set(&fi->value, (gpointer) value_ptr, FALSE);
1812 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start)
1814 proto_tree_set_ipv6(fi, tvb_get_ptr(tvb, start, 16));
1817 /* Add a FT_GUID to a proto_tree */
1819 proto_tree_add_guid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1820 const e_guid_t *value_ptr)
1824 header_field_info *hfinfo;
1829 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1831 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1832 DISSECTOR_ASSERT(hfinfo->type == FT_GUID);
1834 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1835 proto_tree_set_guid(new_fi, value_ptr);
1841 proto_tree_add_guid_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1842 const e_guid_t *value_ptr)
1846 pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
1850 PROTO_ITEM_SET_HIDDEN(pi);
1856 proto_tree_add_guid_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1857 gint start, gint length, const e_guid_t *value_ptr,
1858 const char *format, ...)
1863 pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
1867 va_start(ap, format);
1868 proto_tree_set_representation_value(pi, format, ap);
1875 proto_tree_add_guid_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1876 const e_guid_t *value_ptr, const char *format, ...)
1881 pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
1885 va_start(ap, format);
1886 proto_tree_set_representation(pi, format, ap);
1892 /* Set the FT_GUID value */
1894 proto_tree_set_guid(field_info *fi, const e_guid_t *value_ptr)
1896 DISSECTOR_ASSERT(value_ptr != NULL);
1897 fvalue_set(&fi->value, (gpointer) value_ptr, FALSE);
1901 proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gboolean little_endian)
1905 tvb_get_guid(tvb, start, &guid, little_endian);
1906 proto_tree_set_guid(fi, &guid);
1909 /* Add a FT_OID to a proto_tree */
1911 proto_tree_add_oid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1912 const guint8* value_ptr)
1916 header_field_info *hfinfo;
1921 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1923 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1924 DISSECTOR_ASSERT(hfinfo->type == FT_OID);
1926 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1927 proto_tree_set_oid(new_fi, value_ptr, length);
1933 proto_tree_add_oid_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1934 const guint8* value_ptr)
1938 pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
1942 PROTO_ITEM_SET_HIDDEN(pi);
1948 proto_tree_add_oid_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1949 gint start, gint length, const guint8* value_ptr,
1950 const char *format, ...)
1955 pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
1959 va_start(ap, format);
1960 proto_tree_set_representation_value(pi, format, ap);
1967 proto_tree_add_oid_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1968 const guint8* value_ptr, const char *format, ...)
1973 pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
1977 va_start(ap, format);
1978 proto_tree_set_representation(pi, format, ap);
1984 /* Set the FT_OID value */
1986 proto_tree_set_oid(field_info *fi, const guint8* value_ptr, gint length)
1990 DISSECTOR_ASSERT(value_ptr != NULL);
1992 bytes = g_byte_array_new();
1994 g_byte_array_append(bytes, value_ptr, length);
1996 fvalue_set(&fi->value, bytes, TRUE);
2000 proto_tree_set_oid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
2002 proto_tree_set_oid(fi, tvb_get_ptr(tvb, start, length), length);
2006 proto_tree_set_uint64(field_info *fi, guint64 value)
2008 fvalue_set_integer64(&fi->value, value);
2012 proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start, guint length, gboolean little_endian)
2015 guint8* b = ep_tvb_memdup(tvb,start,length);
2020 default: DISSECTOR_ASSERT_NOT_REACHED();
2021 case 8: value <<= 8; value += *--b;
2022 case 7: value <<= 8; value += *--b;
2023 case 6: value <<= 8; value += *--b;
2024 case 5: value <<= 8; value += *--b;
2025 case 4: value <<= 8; value += *--b;
2026 case 3: value <<= 8; value += *--b;
2027 case 2: value <<= 8; value += *--b;
2028 case 1: value <<= 8; value += *--b;
2033 default: DISSECTOR_ASSERT_NOT_REACHED();
2034 case 8: value <<= 8; value += *b++;
2035 case 7: value <<= 8; value += *b++;
2036 case 6: value <<= 8; value += *b++;
2037 case 5: value <<= 8; value += *b++;
2038 case 4: value <<= 8; value += *b++;
2039 case 3: value <<= 8; value += *b++;
2040 case 2: value <<= 8; value += *b++;
2041 case 1: value <<= 8; value += *b++;
2046 proto_tree_set_uint64(fi, value);
2049 /* Add a FT_STRING or FT_STRINGZ to a proto_tree. Creates own copy of string,
2050 * and frees it when the proto_tree is destroyed. */
2052 proto_tree_add_string(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2053 gint length, const char* value)
2057 header_field_info *hfinfo;
2062 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
2064 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2065 DISSECTOR_ASSERT(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ);
2067 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2068 DISSECTOR_ASSERT(length >= 0);
2069 proto_tree_set_string(new_fi, value);
2075 proto_tree_add_string_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2076 gint length, const char* value)
2080 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
2084 PROTO_ITEM_SET_HIDDEN(pi);
2090 proto_tree_add_string_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2091 gint start, gint length, const char* value, const char *format,
2097 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
2101 va_start(ap, format);
2102 proto_tree_set_representation_value(pi, format, ap);
2109 proto_tree_add_string_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2110 gint length, const char* value, const char *format, ...)
2115 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
2119 va_start(ap, format);
2120 proto_tree_set_representation(pi, format, ap);
2126 /* Appends string data to a FT_STRING or FT_STRINGZ, allowing progressive
2127 * field info update instead of only updating the representation as does
2128 * proto_item_append_text()
2130 /* NOTE: this function will break with the TRY_TO_FAKE_THIS_ITEM()
2131 * speed optimization.
2132 * Currently only WSP use this function so it is not that bad but try to
2133 * avoid using this one if possible.
2134 * IF you must use this function you MUST also disable the
2135 * TRY_TO_FAKE_THIS_ITEM() optimization for your dissector/function
2136 * using proto_item_append_string().
2137 * Do that by faking that the tree is visible by calling
2138 * proto_tree_set_visible(tree, TRUE) (see packet-wsp.c)
2139 * BEFORE you create the item you are later going to use
2140 * proto_item_append_string() on.
2143 proto_item_append_string(proto_item *pi, const char *str)
2146 header_field_info *hfinfo;
2147 gchar *old_str, *new_str;
2154 fi = PITEM_FINFO(pi);
2155 hfinfo = fi->hfinfo;
2156 if (hfinfo->type == FT_PROTOCOL) {
2157 /* TRY_TO_FAKE_THIS_ITEM() speed optimization: silently skip */
2160 DISSECTOR_ASSERT(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ);
2161 old_str = fvalue_get(&fi->value);
2162 new_str = ep_strdup_printf("%s%s", old_str, str);
2163 fvalue_set(&fi->value, new_str, FALSE);
2166 /* Set the FT_STRING value */
2168 proto_tree_set_string(field_info *fi, const char* value)
2171 fvalue_set(&fi->value, (gpointer) value, FALSE);
2173 fvalue_set(&fi->value, (gpointer) "[ Null ]", FALSE);
2177 proto_tree_set_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
2182 length = tvb_ensure_length_remaining(tvb, start);
2185 string = tvb_get_ephemeral_string(tvb, start, length);
2186 proto_tree_set_string(fi, string);
2190 proto_tree_set_ebcdic_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
2195 length = tvb_ensure_length_remaining(tvb, start);
2198 string = tvb_get_ephemeral_string(tvb, start, length);
2199 EBCDIC_to_ASCII(string, length);
2200 proto_tree_set_string(fi, string);
2203 /* Add a FT_ETHER to a proto_tree */
2205 proto_tree_add_ether(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2206 const guint8* value)
2210 header_field_info *hfinfo;
2215 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
2217 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2218 DISSECTOR_ASSERT(hfinfo->type == FT_ETHER);
2220 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2221 proto_tree_set_ether(new_fi, value);
2227 proto_tree_add_ether_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2228 const guint8* value)
2232 pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
2236 PROTO_ITEM_SET_HIDDEN(pi);
2242 proto_tree_add_ether_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2243 gint start, gint length, const guint8* value,
2244 const char *format, ...)
2249 pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
2253 va_start(ap, format);
2254 proto_tree_set_representation_value(pi, format, ap);
2261 proto_tree_add_ether_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2262 const guint8* value, const char *format, ...)
2267 pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
2271 va_start(ap, format);
2272 proto_tree_set_representation(pi, format, ap);
2278 /* Set the FT_ETHER value */
2280 proto_tree_set_ether(field_info *fi, const guint8* value)
2282 fvalue_set(&fi->value, (gpointer) value, FALSE);
2286 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start)
2288 proto_tree_set_ether(fi, tvb_get_ptr(tvb, start, 6));
2291 /* Add a FT_BOOLEAN to a proto_tree */
2293 proto_tree_add_boolean(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2298 header_field_info *hfinfo;
2303 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
2305 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2306 DISSECTOR_ASSERT(hfinfo->type == FT_BOOLEAN);
2308 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2309 proto_tree_set_boolean(new_fi, value);
2315 proto_tree_add_boolean_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2320 pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
2324 PROTO_ITEM_SET_HIDDEN(pi);
2330 proto_tree_add_boolean_format_value(proto_tree *tree, int hfindex,
2331 tvbuff_t *tvb, gint start, gint length, guint32 value,
2332 const char *format, ...)
2337 pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
2341 va_start(ap, format);
2342 proto_tree_set_representation_value(pi, format, ap);
2349 proto_tree_add_boolean_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2350 guint32 value, const char *format, ...)
2355 pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
2359 va_start(ap, format);
2360 proto_tree_set_representation(pi, format, ap);
2366 /* Set the FT_BOOLEAN value */
2368 proto_tree_set_boolean(field_info *fi, guint32 value)
2370 proto_tree_set_uint(fi, value);
2373 /* Add a FT_FLOAT to a proto_tree */
2375 proto_tree_add_float(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2380 header_field_info *hfinfo;
2385 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
2387 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2388 DISSECTOR_ASSERT(hfinfo->type == FT_FLOAT);
2390 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2391 proto_tree_set_float(new_fi, value);
2397 proto_tree_add_float_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2402 pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
2406 PROTO_ITEM_SET_HIDDEN(pi);
2412 proto_tree_add_float_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2413 gint start, gint length, float value, const char *format, ...)
2418 pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
2422 va_start(ap, format);
2423 proto_tree_set_representation_value(pi, format, ap);
2430 proto_tree_add_float_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2431 float value, const char *format, ...)
2436 pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
2440 va_start(ap, format);
2441 proto_tree_set_representation(pi, format, ap);
2447 /* Set the FT_FLOAT value */
2449 proto_tree_set_float(field_info *fi, float value)
2451 fvalue_set_floating(&fi->value, value);
2454 /* Add a FT_DOUBLE to a proto_tree */
2456 proto_tree_add_double(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2461 header_field_info *hfinfo;
2466 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
2468 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2469 DISSECTOR_ASSERT(hfinfo->type == FT_DOUBLE);
2471 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2472 proto_tree_set_double(new_fi, value);
2478 proto_tree_add_double_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2483 pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
2487 PROTO_ITEM_SET_HIDDEN(pi);
2493 proto_tree_add_double_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2494 gint start, gint length, double value, const char *format, ...)
2499 pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
2503 va_start(ap, format);
2504 proto_tree_set_representation_value(pi, format, ap);
2511 proto_tree_add_double_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2512 double value, const char *format, ...)
2517 pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
2521 va_start(ap, format);
2522 proto_tree_set_representation(pi, format, ap);
2528 /* Set the FT_DOUBLE value */
2530 proto_tree_set_double(field_info *fi, double value)
2532 fvalue_set_floating(&fi->value, value);
2535 /* Add FT_UINT{8,16,24,32} to a proto_tree */
2537 proto_tree_add_uint(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2540 proto_item *pi = NULL;
2542 header_field_info *hfinfo;
2547 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
2549 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2550 switch(hfinfo->type) {
2556 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length,
2558 proto_tree_set_uint(new_fi, value);
2562 DISSECTOR_ASSERT_NOT_REACHED();
2569 proto_tree_add_uint_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2574 pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
2578 PROTO_ITEM_SET_HIDDEN(pi);
2584 proto_tree_add_uint_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2585 gint start, gint length, guint32 value, const char *format, ...)
2590 pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
2594 va_start(ap, format);
2595 proto_tree_set_representation_value(pi, format, ap);
2602 proto_tree_add_uint_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2603 guint32 value, const char *format, ...)
2608 pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
2612 va_start(ap, format);
2613 proto_tree_set_representation(pi, format, ap);
2619 /* Set the FT_UINT{8,16,24,32} value */
2621 proto_tree_set_uint(field_info *fi, guint32 value)
2623 header_field_info *hfinfo;
2626 hfinfo = fi->hfinfo;
2629 if (hfinfo->bitmask) {
2630 /* Mask out irrelevant portions */
2631 integer &= hfinfo->bitmask;
2634 if (hfinfo->bitshift > 0) {
2635 integer >>= hfinfo->bitshift;
2638 fvalue_set_uinteger(&fi->value, integer);
2641 /* Add FT_UINT64 to a proto_tree */
2643 proto_tree_add_uint64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2646 proto_item *pi = NULL;
2648 header_field_info *hfinfo;
2653 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
2655 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2656 DISSECTOR_ASSERT(hfinfo->type == FT_UINT64);
2658 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2659 proto_tree_set_uint64(new_fi, value);
2665 proto_tree_add_uint64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2666 gint start, gint length, guint64 value, const char *format, ...)
2671 pi = proto_tree_add_uint64(tree, hfindex, tvb, start, length, value);
2675 va_start(ap, format);
2676 proto_tree_set_representation_value(pi, format, ap);
2683 proto_tree_add_uint64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2684 guint64 value, const char *format, ...)
2689 pi = proto_tree_add_uint64(tree, hfindex, tvb, start, length, value);
2693 va_start(ap, format);
2694 proto_tree_set_representation(pi, format, ap);
2700 /* Add FT_INT{8,16,24,32} to a proto_tree */
2702 proto_tree_add_int(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2705 proto_item *pi = NULL;
2707 header_field_info *hfinfo;
2712 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
2714 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2715 switch(hfinfo->type) {
2720 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length,
2722 proto_tree_set_int(new_fi, value);
2726 DISSECTOR_ASSERT_NOT_REACHED();
2733 proto_tree_add_int_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2738 pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
2742 PROTO_ITEM_SET_HIDDEN(pi);
2748 proto_tree_add_int_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2749 gint start, gint length, gint32 value, const char *format, ...)
2751 proto_item *pi = NULL;
2754 pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
2758 va_start(ap, format);
2759 proto_tree_set_representation_value(pi, format, ap);
2766 proto_tree_add_int_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2767 gint32 value, const char *format, ...)
2769 proto_item *pi = NULL;
2772 pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
2776 va_start(ap, format);
2777 proto_tree_set_representation(pi, format, ap);
2783 /* Set the FT_INT{8,16,24,32} value */
2785 proto_tree_set_int(field_info *fi, gint32 value)
2787 header_field_info *hfinfo;
2790 hfinfo = fi->hfinfo;
2791 integer = (guint32) value;
2793 if (hfinfo->bitmask) {
2794 /* Mask out irrelevant portions */
2795 integer &= hfinfo->bitmask;
2798 if (hfinfo->bitshift > 0) {
2799 integer >>= hfinfo->bitshift;
2802 fvalue_set_sinteger(&fi->value, integer);
2805 /* Add FT_INT64 to a proto_tree */
2807 proto_tree_add_int64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2810 proto_item *pi = NULL;
2812 header_field_info *hfinfo;
2817 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
2819 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2820 DISSECTOR_ASSERT(hfinfo->type == FT_INT64);
2822 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2823 proto_tree_set_uint64(new_fi, (guint64)value);
2829 proto_tree_add_int64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2830 gint start, gint length, gint64 value, const char *format, ...)
2835 pi = proto_tree_add_int64(tree, hfindex, tvb, start, length, value);
2839 va_start(ap, format);
2840 proto_tree_set_representation_value(pi, format, ap);
2847 proto_tree_add_int64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2848 gint64 value, const char *format, ...)
2853 pi = proto_tree_add_int64(tree, hfindex, tvb, start, length, value);
2857 va_start(ap, format);
2858 proto_tree_set_representation(pi, format, ap);
2864 /* Throw an exception if we exceed this many tree items. */
2865 /* XXX - This should probably be a preference */
2866 #define MAX_TREE_ITEMS (1 * 1000 * 1000)
2867 /* Add a field_info struct to the proto_tree, encapsulating it in a proto_node */
2869 proto_tree_add_node(proto_tree *tree, field_info *fi)
2871 proto_node *pnode, *tnode, *sibling;
2875 * Make sure "tree" is ready to have subtrees under it, by
2876 * checking whether it's been given an ett_ value.
2878 * "tnode->finfo" may be null; that's the case for the root
2879 * node of the protocol tree. That node is not displayed,
2880 * so it doesn't need an ett_ value to remember whether it
2885 if (tfi != NULL && (tfi->tree_type < 0 || tfi->tree_type >= num_tree_types)) {
2886 REPORT_DISSECTOR_BUG(ep_strdup_printf("\"%s\" - \"%s\" tfi->tree_type: %u invalid (%s:%u)",
2887 fi->hfinfo->name, fi->hfinfo->abbrev, tfi->tree_type, __FILE__, __LINE__));
2888 /* XXX - is it safe to continue here? */
2891 DISSECTOR_ASSERT(tfi == NULL ||
2892 (tfi->tree_type >= 0 && tfi->tree_type < num_tree_types));
2894 PTREE_DATA(tree)->count++;
2895 if (PTREE_DATA(tree)->count > MAX_TREE_ITEMS) {
2896 /* Let the exception handler add items to the tree */
2897 PTREE_DATA(tree)->count = 0;
2898 THROW_MESSAGE(DissectorError,
2899 ep_strdup_printf("More than %d items in the tree -- possible infinite loop", MAX_TREE_ITEMS));
2902 PROTO_NODE_NEW(pnode);
2903 pnode->parent = tnode;
2905 pnode->tree_data = PTREE_DATA(tree);
2907 if (tnode->last_child != NULL) {
2908 sibling = tnode->last_child;
2909 DISSECTOR_ASSERT(sibling->next == NULL);
2910 sibling->next = pnode;
2912 tnode->first_child = pnode;
2913 tnode->last_child = pnode;
2915 return (proto_item*)pnode;
2919 /* Generic way to allocate field_info and add to proto_tree.
2920 * Sets *pfi to address of newly-allocated field_info struct, if pfi is
2923 proto_tree_add_pi(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2924 gint *length, field_info **pfi)
2934 fi = alloc_field_info(tree, hfindex, tvb, start, length);
2935 pi = proto_tree_add_node(tree, fi);
2937 /* If the proto_tree wants to keep a record of this finfo
2938 * for quick lookup, then record it. */
2939 if (fi->hfinfo->ref_count) {
2941 hash = PTREE_DATA(tree)->interesting_hfids;
2942 ptrs = g_hash_table_lookup(hash, GINT_TO_POINTER(hfindex));
2944 g_ptr_array_add(ptrs, fi);
2948 /* Does the caller want to know the fi pointer? */
2957 static header_field_info *
2958 get_hfi_and_length(int hfindex, tvbuff_t *tvb, gint start, gint *length,
2961 header_field_info *hfinfo;
2962 gint length_remaining;
2965 * We only allow a null tvbuff if the item has a zero length,
2966 * i.e. if there's no data backing it.
2968 DISSECTOR_ASSERT(tvb != NULL || *length == 0);
2970 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2973 * XXX - in some protocols, there are 32-bit unsigned length
2974 * fields, so lengths in protocol tree and tvbuff routines
2975 * should really be unsigned. We should have, for those
2976 * field types for which "to the end of the tvbuff" makes sense,
2977 * additional routines that take no length argument and
2978 * add fields that run to the end of the tvbuff.
2980 if (*length == -1) {
2982 * For FT_NONE, FT_PROTOCOL, FT_BYTES, and FT_STRING fields,
2983 * a length of -1 means "set the length to what remains in
2986 * The assumption is either that
2988 * 1) the length of the item can only be determined
2989 * by dissection (typically true of items with
2990 * subitems, which are probably FT_NONE or
2995 * 2) if the tvbuff is "short" (either due to a short
2996 * snapshot length or due to lack of reassembly of
2997 * fragments/segments/whatever), we want to display
2998 * what's available in the field (probably FT_BYTES
2999 * or FT_STRING) and then throw an exception later
3003 * 3) the field is defined to be "what's left in the
3006 * so we set the length to what remains in the tvbuff so
3007 * that, if we throw an exception while dissecting, it
3008 * has what is probably the right value.
3010 * For FT_STRINGZ, it means "the string is null-terminated,
3011 * not null-padded; set the length to the actual length
3012 * of the string", and if the tvbuff if short, we just
3013 * throw an exception.
3015 * It's not valid for any other type of field.
3017 switch (hfinfo->type) {
3021 * We allow this to be zero-length - for
3022 * example, an ONC RPC NULL procedure has
3023 * neither arguments nor reply, so the
3024 * payload for that protocol is empty.
3026 * However, if the length is negative, the
3027 * start offset is *past* the byte past the
3028 * end of the tvbuff, so we throw an
3031 *length = tvb_length_remaining(tvb, start);
3034 * Use "tvb_ensure_bytes_exist()"
3035 * to force the appropriate exception
3038 tvb_ensure_bytes_exist(tvb, start, 0);
3040 DISSECTOR_ASSERT(*length >= 0);
3046 *length = tvb_ensure_length_remaining(tvb, start);
3047 DISSECTOR_ASSERT(*length >= 0);
3052 * Leave the length as -1, so our caller knows
3058 DISSECTOR_ASSERT_NOT_REACHED();
3060 *item_length = *length;
3062 *item_length = *length;
3063 if (hfinfo->type == FT_PROTOCOL || hfinfo->type == FT_NONE) {
3065 * These types are for interior nodes of the
3066 * tree, and don't have data associated with
3067 * them; if the length is negative (XXX - see
3068 * above) or goes past the end of the tvbuff,
3069 * cut it short at the end of the tvbuff.
3070 * That way, if this field is selected in
3071 * Wireshark, we don't highlight stuff past
3072 * the end of the data.
3074 /* XXX - what to do, if we don't have a tvb? */
3076 length_remaining = tvb_length_remaining(tvb, start);
3077 if (*item_length < 0 ||
3078 (*item_length > 0 &&
3079 (length_remaining < *item_length)))
3080 *item_length = length_remaining;
3083 if (*item_length < 0) {
3084 THROW(ReportedBoundsError);
3092 new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
3093 gint start, gint item_length)
3099 fi->hfinfo = hfinfo;
3101 fi->start+=(tvb)?TVB_RAW_OFFSET(tvb):0;
3102 fi->length = item_length;
3105 if (!PTREE_DATA(tree)->visible)
3106 FI_SET_FLAG(fi, FI_HIDDEN);
3107 fvalue_init(&fi->value, fi->hfinfo->type);
3110 /* add the data source tvbuff */
3111 fi->ds_tvb=tvb?TVB_GET_DS_TVB(tvb):NULL;
3113 fi->appendix_start = 0;
3114 fi->appendix_length = 0;
3120 alloc_field_info(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3123 header_field_info *hfinfo;
3126 hfinfo = get_hfi_and_length(hfindex, tvb, start, length, &item_length);
3127 return new_field_info(tree, hfinfo, tvb, start, item_length);
3130 /* If the protocol tree is to be visible, set the representation of a
3131 proto_tree entry with the name of the field for the item and with
3132 the value formatted with the supplied printf-style format and
3135 proto_tree_set_representation_value(proto_item *pi, const char *format, va_list ap)
3137 int ret; /*tmp return value */
3139 field_info *fi = PITEM_FINFO(pi);
3141 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
3142 ITEM_LABEL_NEW(fi->rep);
3144 ret = g_snprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
3145 "%s: ", fi->hfinfo->name);
3146 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH)) {
3147 /* That's all we can put in the representation. */
3148 fi->rep->representation[ITEM_LABEL_LENGTH - 1] = '\0';
3152 ret = g_vsnprintf(fi->rep->representation + replen,
3153 ITEM_LABEL_LENGTH - replen, format, ap);
3154 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH - replen))
3155 fi->rep->representation[ITEM_LABEL_LENGTH - 1] = '\0';
3159 /* If the protocol tree is to be visible, set the representation of a
3160 proto_tree entry with the representation formatted with the supplied
3161 printf-style format and argument list. */
3163 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap)
3165 int ret; /*tmp return value */
3166 field_info *fi = PITEM_FINFO(pi);
3168 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
3169 ITEM_LABEL_NEW(fi->rep);
3170 ret = g_vsnprintf(fi->rep->representation, ITEM_LABEL_LENGTH, format, ap);
3171 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3172 fi->rep->representation[ITEM_LABEL_LENGTH - 1] = '\0';
3176 /* Set text of proto_item after having already been created. */
3178 proto_item_set_text(proto_item *pi, const char *format, ...)
3180 field_info *fi = NULL;
3187 fi = PITEM_FINFO(pi);
3190 ITEM_LABEL_FREE(fi->rep);
3193 va_start(ap, format);
3194 proto_tree_set_representation(pi, format, ap);
3198 /* Append to text of proto_item after having already been created. */
3200 proto_item_append_text(proto_item *pi, const char *format, ...)
3202 field_info *fi = NULL;
3205 int ret; /*tmp return value */
3211 fi = PITEM_FINFO(pi);
3216 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
3217 va_start(ap, format);
3220 * If we don't already have a representation,
3221 * generate the default representation.
3223 if (fi->rep == NULL) {
3224 ITEM_LABEL_NEW(fi->rep);
3225 proto_item_fill_label(fi, fi->rep->representation);
3228 curlen = strlen(fi->rep->representation);
3229 if (ITEM_LABEL_LENGTH > curlen) {
3230 ret = g_vsnprintf(fi->rep->representation + curlen,
3231 ITEM_LABEL_LENGTH - curlen, format, ap);
3232 if ((ret == -1) || (ret >= (int)(ITEM_LABEL_LENGTH - curlen)))
3233 fi->rep->representation[ITEM_LABEL_LENGTH - 1] = '\0';
3240 proto_item_set_len(proto_item *pi, gint length)
3246 fi = PITEM_FINFO(pi);
3247 DISSECTOR_ASSERT(length >= 0);
3248 fi->length = length;
3250 if (fi->value.ftype->ftype == FT_BYTES)
3251 fi->value.value.bytes->len = length;
3255 * Sets the length of the item based on its start and on the specified
3256 * offset, which is the offset past the end of the item; as the start
3257 * in the item is relative to the beginning of the data source tvbuff,
3258 * we need to pass in a tvbuff - the end offset is relative to the beginning
3262 proto_item_set_end(proto_item *pi, tvbuff_t *tvb, gint end)
3268 fi = PITEM_FINFO(pi);
3269 end += TVB_RAW_OFFSET(tvb);
3270 DISSECTOR_ASSERT(end >= fi->start);
3271 fi->length = end - fi->start;
3275 proto_item_get_len(proto_item *pi)
3277 field_info *fi = PITEM_FINFO(pi);
3282 /** clear flags according to the mask and set new flag values */
3283 #define FI_REPLACE_FLAGS(fi, mask, flags_in) { \
3284 (fi->flags = (fi)->flags & ~(mask)); \
3285 (fi->flags = (fi)->flags | (flags_in)); \
3289 proto_item_set_expert_flags(proto_item *pi, int group, guint severity)
3291 if(pi == NULL || pi->finfo == NULL)
3294 /* only change things if severity is worse or at least equal than before */
3295 if(severity >= FI_GET_FLAG(pi->finfo, PI_SEVERITY_MASK)) {
3296 FI_REPLACE_FLAGS(pi->finfo, PI_GROUP_MASK, group);
3297 FI_REPLACE_FLAGS(pi->finfo, PI_SEVERITY_MASK, severity);
3308 proto_tree_create_root(void)
3312 /* Initialize the proto_node */
3313 PROTO_NODE_NEW(pnode);
3314 pnode->parent = NULL;
3315 pnode->finfo = NULL;
3316 pnode->tree_data = g_new(tree_data_t, 1);
3318 /* Initialize the tree_data_t */
3319 pnode->tree_data->interesting_hfids =
3320 g_hash_table_new(g_direct_hash, g_direct_equal);
3322 /* Set the default to FALSE so it's easier to
3323 * find errors; if we expect to see the protocol tree
3324 * but for some reason the default 'visible' is not
3325 * changed, then we'll find out very quickly. */
3326 pnode->tree_data->visible = FALSE;
3328 /* Keep track of the number of children */
3329 pnode->tree_data->count = 0;
3331 return (proto_tree*) pnode;
3335 /* "prime" a proto_tree with a single hfid that a dfilter
3336 * is interested in. */
3338 proto_tree_prime_hfid(proto_tree *tree, gint hfid)
3340 header_field_info *hfinfo;
3342 g_hash_table_insert(PTREE_DATA(tree)->interesting_hfids,
3343 GINT_TO_POINTER(hfid), g_ptr_array_new());
3345 PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
3346 /* this field is referenced by a filter so increase the refcount.
3347 also increase the refcount for the parent, i.e the protocol.
3349 hfinfo->ref_count++;
3350 /* only increase the refcount if there is a parent.
3351 if this is a protocol and not a field then parent will be -1
3352 and there is no parent to add any refcounting for.
3354 if (hfinfo->parent != -1) {
3355 header_field_info *parent_hfinfo;
3356 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
3357 parent_hfinfo->ref_count++;
3362 proto_item_add_subtree(proto_item *pi, gint idx) {
3368 fi = PITEM_FINFO(pi);
3369 DISSECTOR_ASSERT(idx >= 0 && idx < num_tree_types);
3370 fi->tree_type = idx;
3372 return (proto_tree*) pi;
3376 proto_item_get_subtree(proto_item *pi) {
3381 fi = PITEM_FINFO(pi);
3382 if ( (!fi) || (fi->tree_type == -1) )
3384 return (proto_tree*) pi;
3388 proto_item_get_parent(proto_item *ti) {
3395 proto_item_get_parent_nth(proto_item *ti, int gen) {
3408 proto_tree_get_parent(proto_tree *tree) {
3411 return (proto_item*) tree;
3415 proto_tree_get_root(proto_tree *tree) {
3418 while (tree->parent) {
3419 tree = tree->parent;
3425 proto_tree_move_item(proto_tree *tree, proto_item *fixed_item, proto_item *item_to_move)
3427 proto_item *curr_item;
3430 /*** cut item_to_move out ***/
3432 /* is item_to_move the first? */
3433 if(tree->first_child == item_to_move) {
3434 /* simply change first child to next */
3435 tree->first_child = item_to_move->next;
3437 /* find previous and change it's next */
3438 for(curr_item = tree->first_child; curr_item != NULL; curr_item = curr_item->next) {
3439 if(curr_item->next == item_to_move) {
3444 DISSECTOR_ASSERT(curr_item);
3446 curr_item->next = item_to_move->next;
3448 /* fix last_child if required */
3449 if(tree->last_child == item_to_move) {
3450 tree->last_child = curr_item;
3454 /*** insert to_move after fixed ***/
3455 item_to_move->next = fixed_item->next;
3456 fixed_item->next = item_to_move;
3457 if(tree->last_child == fixed_item) {
3458 tree->last_child = item_to_move;
3463 proto_tree_set_appendix(proto_tree *tree, tvbuff_t *tvb, gint start, gint length)
3471 start += TVB_RAW_OFFSET(tvb);
3472 DISSECTOR_ASSERT(start >= 0);
3473 DISSECTOR_ASSERT(length >= 0);
3475 fi->appendix_start = start;
3476 fi->appendix_length = length;
3480 proto_register_protocol(const char *name, const char *short_name, const char *filter_name)
3482 protocol_t *protocol;
3483 header_field_info *hfinfo;
3485 char *existing_name;
3489 gboolean found_invalid;
3492 * Make sure there's not already a protocol with any of those
3493 * names. Crash if there is, as that's an error in the code
3494 * or an inappropriate plugin.
3495 * This situation has to be fixed to not register more than one
3496 * protocol with the same name.
3498 * This is done by reducing the number of strcmp (and alike) calls as much as possible,
3499 * as this significally slows down startup time.
3501 * Drawback: As a hash value is used to reduce insert time,
3502 * this might lead to a hash collision.
3503 * However, as we have around 500+ protocols and we're using a 32 bit int this is very,
3507 key = g_malloc (sizeof(gint));
3508 *key = wrs_str_hash(name);
3509 existing_name = g_hash_table_lookup(proto_names, key);
3510 if (existing_name != NULL) {
3511 /* g_error will terminate the program */
3512 g_error("Duplicate protocol name \"%s\"!"
3513 " This might be caused by an inappropriate plugin or a development error.", name);
3515 g_hash_table_insert(proto_names, key, (gpointer)name);
3517 existing_name = g_hash_table_lookup(proto_short_names, (gpointer)short_name);
3518 if (existing_name != NULL) {
3519 g_error("Duplicate protocol short_name \"%s\"!"
3520 " This might be caused by an inappropriate plugin or a development error.", short_name);
3522 g_hash_table_insert(proto_short_names, (gpointer)short_name, (gpointer)short_name);
3524 found_invalid = FALSE;
3525 for (i = 0; i < strlen(filter_name); i++) {
3527 if (!(islower(c) || isdigit(c) || c == '-' || c == '_' || c == '.')) {
3528 found_invalid = TRUE;
3531 if (found_invalid) {
3532 g_error("Protocol filter name \"%s\" has one or more invalid characters."
3533 " Allowed are lower characters, digits, '-', '_' and '.'."
3534 " This might be caused by an inappropriate plugin or a development error.", filter_name);
3536 existing_name = g_hash_table_lookup(proto_filter_names, (gpointer)filter_name);
3537 if (existing_name != NULL) {
3538 g_error("Duplicate protocol filter_name \"%s\"!"
3539 " This might be caused by an inappropriate plugin or a development error.", filter_name);
3541 g_hash_table_insert(proto_filter_names, (gpointer)filter_name, (gpointer)filter_name);
3543 /* Add this protocol to the list of known protocols; the list
3544 is sorted by protocol short name. */
3545 protocol = g_malloc(sizeof (protocol_t));
3546 protocol->name = name;
3547 protocol->short_name = short_name;
3548 protocol->filter_name = filter_name;
3549 protocol->fields = NULL;
3550 protocol->is_enabled = TRUE; /* protocol is enabled by default */
3551 protocol->can_toggle = TRUE;
3552 /* list will be sorted later by name, when all protocols completed registering */
3553 protocols = g_list_prepend(protocols, protocol);
3555 /* Here we do allocate a new header_field_info struct */
3556 hfinfo = g_mem_chunk_alloc(gmc_hfinfo);
3557 hfinfo->name = name;
3558 hfinfo->abbrev = filter_name;
3559 hfinfo->type = FT_PROTOCOL;
3560 hfinfo->strings = protocol;
3561 hfinfo->bitmask = 0;
3562 hfinfo->bitshift = 0;
3563 hfinfo->ref_count = 0;
3564 hfinfo->blurb = NULL;
3565 hfinfo->parent = -1; /* this field differentiates protos and fields */
3567 proto_id = proto_register_field_init(hfinfo, hfinfo->parent);
3568 protocol->proto_id = proto_id;
3573 * Routines to use to iterate over the protocols.
3574 * The argument passed to the iterator routines is an opaque cookie to
3575 * their callers; it's the GList pointer for the current element in
3577 * The ID of the protocol is returned, or -1 if there is no protocol.
3580 proto_get_first_protocol(void **cookie)
3582 protocol_t *protocol;
3584 if (protocols == NULL)
3586 *cookie = protocols;
3587 protocol = protocols->data;
3588 return protocol->proto_id;
3592 proto_get_next_protocol(void **cookie)
3594 GList *list_item = *cookie;
3595 protocol_t *protocol;
3597 list_item = g_list_next(list_item);
3598 if (list_item == NULL)
3600 *cookie = list_item;
3601 protocol = list_item->data;
3602 return protocol->proto_id;
3606 proto_get_first_protocol_field(int proto_id, void **cookie)
3608 protocol_t *protocol = find_protocol_by_id(proto_id);
3609 hf_register_info *ptr;
3611 if ((protocol == NULL) || (protocol->fields == NULL))
3614 *cookie = protocol->fields;
3615 ptr = protocol->fields->data;
3616 return &ptr->hfinfo;
3620 proto_get_next_protocol_field(void **cookie)
3622 GList *list_item = *cookie;
3623 hf_register_info *ptr;
3625 list_item = g_list_next(list_item);
3626 if (list_item == NULL)
3629 *cookie = list_item;
3630 ptr = list_item->data;
3631 return &ptr->hfinfo;
3635 find_protocol_by_id(int proto_id)
3637 header_field_info *hfinfo;
3642 PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
3643 DISSECTOR_ASSERT(hfinfo->type==FT_PROTOCOL);
3644 return (protocol_t *)hfinfo->strings;
3647 static gint compare_filter_name(gconstpointer proto_arg,
3648 gconstpointer filter_name)
3650 const protocol_t *protocol = proto_arg;
3651 const gchar* f_name = filter_name;
3653 return (strcmp(protocol->filter_name, f_name));
3657 proto_get_id(protocol_t *protocol)
3659 return protocol->proto_id;
3662 int proto_get_id_by_filter_name(const gchar* filter_name)
3665 protocol_t *protocol;
3667 #if GLIB_MAJOR_VERSION < 2
3668 list_entry = g_list_find_custom(protocols, discard_const(filter_name),
3669 compare_filter_name);
3671 list_entry = g_list_find_custom(protocols, filter_name,
3672 compare_filter_name);
3674 if (list_entry == NULL)
3676 protocol = list_entry->data;
3677 return protocol->proto_id;
3681 proto_get_protocol_name(int proto_id)
3683 protocol_t *protocol;
3685 protocol = find_protocol_by_id(proto_id);
3686 return protocol->name;
3690 proto_get_protocol_short_name(protocol_t *protocol)
3692 if (protocol == NULL)
3694 return protocol->short_name;
3698 proto_get_protocol_filter_name(int proto_id)
3700 protocol_t *protocol;
3702 protocol = find_protocol_by_id(proto_id);
3703 if (protocol == NULL)
3705 return protocol->filter_name;
3709 proto_is_protocol_enabled(protocol_t *protocol)
3711 return protocol->is_enabled;
3715 proto_can_toggle_protocol(int proto_id)
3717 protocol_t *protocol;
3719 protocol = find_protocol_by_id(proto_id);
3720 return protocol->can_toggle;
3724 proto_set_decoding(int proto_id, gboolean enabled)
3726 protocol_t *protocol;
3728 protocol = find_protocol_by_id(proto_id);
3729 DISSECTOR_ASSERT(protocol->can_toggle);
3730 protocol->is_enabled = enabled;
3734 proto_set_cant_toggle(int proto_id)
3736 protocol_t *protocol;
3738 protocol = find_protocol_by_id(proto_id);
3739 protocol->can_toggle = FALSE;
3742 /* for use with static arrays only, since we don't allocate our own copies
3743 of the header_field_info struct contained within the hf_register_info struct */
3745 proto_register_field_array(int parent, hf_register_info *hf, int num_records)
3748 hf_register_info *ptr = hf;
3751 proto = find_protocol_by_id(parent);
3752 for (i = 0; i < num_records; i++, ptr++) {
3754 * Make sure we haven't registered this yet.
3755 * Most fields have variables associated with them
3756 * that are initialized to -1; some have array elements,
3757 * or possibly uninitialized variables, so we also allow
3758 * 0 (which is unlikely to be the field ID we get back
3759 * from "proto_register_field_init()").
3761 if (*ptr->p_id != -1 && *ptr->p_id != 0) {
3763 "Duplicate field detected in call to proto_register_field_array: %s is already registered\n",
3764 ptr->hfinfo.abbrev);
3768 if (proto != NULL) {
3769 if (proto->fields == NULL) {
3770 proto->fields = g_list_append(NULL, ptr);
3771 proto->last_field = proto->fields;
3774 g_list_append(proto->last_field, ptr)->next;
3777 field_id = proto_register_field_init(&ptr->hfinfo, parent);
3778 *ptr->p_id = field_id;
3782 /* chars allowed in field abbrev */
3784 const guchar fld_abbrev_chars[256] = {
3785 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00-0x0F */
3786 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10-0x1F */
3787 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, /* 0x20-0x2F '-', '.' */
3788 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 0x30-0x3F '0'-'9' */
3789 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x40-0x4F 'A'-'O' */
3790 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 0x50-0x5F 'P'-'Z', '_' */
3791 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x60-0x6F 'a'-'o' */
3792 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 0x70-0x7F 'p'-'z' */
3793 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80-0x8F */
3794 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90-0x9F */
3795 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xA0-0xAF */
3796 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xB0-0xBF */
3797 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xC0-0xCF */
3798 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xD0-0xDF */
3799 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xE0-0xEF */
3800 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xF0-0xFF */
3803 /* temporary function containing assert part for easier profiling */
3804 static void tmp_fld_check_assert(header_field_info *hfinfo) {
3805 /* The field must have a name (with length > 0) */
3806 DISSECTOR_ASSERT(hfinfo->name && hfinfo->name[0]);
3808 /* fields with an empty string for an abbreviation aren't filterable */
3809 DISSECTOR_ASSERT(hfinfo->abbrev);
3811 /* These types of fields are allowed to have value_strings, true_false_strings or a protocol_t struct*/
3812 DISSECTOR_ASSERT((hfinfo->strings == NULL) || (
3813 (hfinfo->type == FT_UINT8) ||
3814 (hfinfo->type == FT_UINT16) ||
3815 (hfinfo->type == FT_UINT24) ||
3816 (hfinfo->type == FT_UINT32) ||
3817 (hfinfo->type == FT_INT8) ||
3818 (hfinfo->type == FT_INT16) ||
3819 (hfinfo->type == FT_INT24) ||
3820 (hfinfo->type == FT_INT32) ||
3821 (hfinfo->type == FT_BOOLEAN) ||
3822 (hfinfo->type == FT_PROTOCOL) ||
3823 (hfinfo->type == FT_FRAMENUM) ));
3825 switch (hfinfo->type) {
3835 /* Require integral types (other than frame number, which is
3836 always displayed in decimal) to have a number base */
3837 DISSECTOR_ASSERT(hfinfo->display != BASE_NONE);
3841 /* Don't allow bitfields or value strings for frame numbers */
3842 DISSECTOR_ASSERT(hfinfo->bitmask == 0);
3843 DISSECTOR_ASSERT(hfinfo->strings == NULL);
3852 proto_register_field_init(header_field_info *hfinfo, int parent)
3855 tmp_fld_check_assert(hfinfo);
3857 /* if this is a bitfield, compute bitshift */
3858 if (hfinfo->bitmask) {
3859 hfinfo->bitshift = wrs_count_bitshift(hfinfo->bitmask);
3862 hfinfo->parent = parent;
3863 hfinfo->same_name_next = NULL;
3864 hfinfo->same_name_prev = NULL;
3866 /* if we always add and never delete, then id == len - 1 is correct */
3867 if(gpa_hfinfo.len>=gpa_hfinfo.allocated_len){
3868 if(!gpa_hfinfo.hfi){
3869 gpa_hfinfo.allocated_len=1000;
3870 gpa_hfinfo.hfi=g_malloc(sizeof(header_field_info *)*1000);
3872 gpa_hfinfo.allocated_len+=1000;
3873 gpa_hfinfo.hfi=g_realloc(gpa_hfinfo.hfi, sizeof(header_field_info *)*gpa_hfinfo.allocated_len);
3876 gpa_hfinfo.hfi[gpa_hfinfo.len]=hfinfo;
3878 hfinfo->id = gpa_hfinfo.len - 1;
3880 /* if we have real names, enter this field in the name tree */
3881 if ((hfinfo->name[0] != 0) && (hfinfo->abbrev[0] != 0 )) {
3883 header_field_info *same_name_next_hfinfo;
3886 /* Check that the filter name (abbreviation) is legal;
3887 * it must contain only alphanumerics, '-', "_", and ".". */
3888 c = wrs_check_charset(fld_abbrev_chars, hfinfo->abbrev);
3890 fprintf(stderr, "OOPS: '%c' in '%s'\n", c, hfinfo->abbrev);
3891 DISSECTOR_ASSERT(!c);
3894 /* We allow multiple hfinfo's to be registered under the same
3895 * abbreviation. This was done for X.25, as, depending
3896 * on whether it's modulo-8 or modulo-128 operation,
3897 * some bitfield fields may be in different bits of
3898 * a byte, and we want to be able to refer to that field
3899 * with one name regardless of whether the packets
3900 * are modulo-8 or modulo-128 packets. */
3901 #if GLIB_MAJOR_VERSION < 2
3902 same_name_hfinfo = g_tree_lookup(gpa_name_tree, discard_const(hfinfo->abbrev));
3904 same_name_hfinfo = NULL;
3906 g_tree_insert(gpa_name_tree, (gpointer) (hfinfo->abbrev), hfinfo);
3907 /* GLIB 2.x - if it is already present
3908 * the previous hfinfo with the same name is saved
3909 * to same_name_hfinfo by value destroy callback */
3910 if (same_name_hfinfo) {
3911 /* There's already a field with this name.
3912 * Put it after that field in the list of
3913 * fields with this name, then allow the code
3914 * after this if{} block to replace the old
3915 * hfinfo with the new hfinfo in the GTree. Thus,
3916 * we end up with a linked-list of same-named hfinfo's,
3917 * with the root of the list being the hfinfo in the GTree */
3918 same_name_next_hfinfo =
3919 same_name_hfinfo->same_name_next;
3921 hfinfo->same_name_next = same_name_next_hfinfo;
3922 if (same_name_next_hfinfo)
3923 same_name_next_hfinfo->same_name_prev = hfinfo;
3925 same_name_hfinfo->same_name_next = hfinfo;
3926 hfinfo->same_name_prev = same_name_hfinfo;
3934 proto_register_subtree_array(gint *const *indices, int num_indices)
3937 gint *const *ptr = indices;
3940 * If we've already allocated the array of tree types, expand
3941 * it; this lets plugins such as mate add tree types after
3942 * the initial startup. (If we haven't already allocated it,
3943 * we don't allocate it; on the first pass, we just assign
3944 * ett values and keep track of how many we've assigned, and
3945 * when we're finished registering all dissectors we allocate
3946 * the array, so that we do only one allocation rather than
3947 * wasting CPU time and memory by growing the array for each
3948 * dissector that registers ett values.)
3950 if (tree_is_expanded != NULL) {
3952 g_realloc(tree_is_expanded,
3953 (num_tree_types+num_indices)*sizeof (gboolean));
3954 memset(tree_is_expanded + num_tree_types, 0,
3955 num_indices*sizeof (gboolean));
3959 * Assign "num_indices" subtree numbers starting at "num_tree_types",
3960 * returning the indices through the pointers in the array whose
3961 * first element is pointed to by "indices", and update
3962 * "num_tree_types" appropriately.
3964 for (i = 0; i < num_indices; i++, ptr++, num_tree_types++)
3965 **ptr = num_tree_types;
3969 proto_item_fill_label(field_info *fi, gchar *label_str)
3971 header_field_info *hfinfo = fi->hfinfo;
3977 guint32 n_addr; /* network-order IPv4 address */
3979 int ret; /*tmp return value */
3981 switch(hfinfo->type) {
3984 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3985 "%s", hfinfo->name);
3986 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3987 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3991 fill_label_boolean(fi, label_str);
3996 bytes = fvalue_get(&fi->value);
3998 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3999 "%s: %s", hfinfo->name,
4000 bytes_to_str(bytes, fvalue_length(&fi->value)));
4001 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4002 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4005 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4006 "%s: <MISSING>", hfinfo->name);
4007 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4008 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4012 /* Four types of integers to take care of:
4013 * Bitfield, with val_string
4014 * Bitfield, w/o val_string
4015 * Non-bitfield, with val_string
4016 * Non-bitfield, w/o val_string
4023 if (hfinfo->bitmask) {
4024 if (hfinfo->strings) {
4025 fill_label_enumerated_bitfield(fi, label_str);
4028 fill_label_numeric_bitfield(fi, label_str);
4032 if (hfinfo->strings) {
4033 fill_label_enumerated_uint(fi, label_str);
4036 fill_label_uint(fi, label_str);
4042 fill_label_uint64(fi, label_str);
4049 DISSECTOR_ASSERT(!hfinfo->bitmask);
4050 if (hfinfo->strings) {
4051 fill_label_enumerated_int(fi, label_str);
4054 fill_label_int(fi, label_str);
4059 fill_label_int64(fi, label_str);
4063 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4064 "%s: %." STRINGIFY(FLT_DIG) "f",
4065 hfinfo->name, fvalue_get_floating(&fi->value));
4066 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4067 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4071 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4072 "%s: %." STRINGIFY(DBL_DIG) "g",
4073 hfinfo->name, fvalue_get_floating(&fi->value));
4074 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4075 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4078 case FT_ABSOLUTE_TIME:
4079 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4080 "%s: %s", hfinfo->name,
4081 abs_time_to_str(fvalue_get(&fi->value)));
4082 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4083 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4086 case FT_RELATIVE_TIME:
4087 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4088 "%s: %s seconds", hfinfo->name,
4089 rel_time_to_secs_str(fvalue_get(&fi->value)));
4090 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4091 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4095 integer = fvalue_get_uinteger(&fi->value);
4096 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4097 "%s: %s (0x%08X)", hfinfo->name,
4098 get_ipxnet_name(integer), integer);
4099 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4100 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4104 bytes = fvalue_get(&fi->value);
4105 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4106 "%s: %s (%s)", hfinfo->name,
4107 get_ether_name(bytes),
4108 ether_to_str(bytes));
4109 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4110 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4114 ipv4 = fvalue_get(&fi->value);
4115 n_addr = ipv4_get_net_order_addr(ipv4);
4116 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4117 "%s: %s (%s)", hfinfo->name,
4118 get_hostname(n_addr),
4119 ip_to_str((guint8*)&n_addr));
4120 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4121 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4125 bytes = fvalue_get(&fi->value);
4126 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4127 "%s: %s (%s)", hfinfo->name,
4128 get_hostname6((struct e_in6_addr *)bytes),
4129 ip6_to_str((struct e_in6_addr*)bytes));
4130 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4131 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4135 guid = fvalue_get(&fi->value);
4136 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4137 "%s: %s", hfinfo->name,
4139 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4140 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4144 bytes = fvalue_get(&fi->value);
4145 name = oid_resolved_from_encoded(bytes, fvalue_length(&fi->value));
4147 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4148 "%s: %s (%s)", hfinfo->name,
4149 oid_encoded2string(bytes, fvalue_length(&fi->value)), name);
4151 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4152 "%s: %s", hfinfo->name,
4153 oid_encoded2string(bytes, fvalue_length(&fi->value)));
4155 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4156 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4162 case FT_UINT_STRING:
4163 bytes = fvalue_get(&fi->value);
4164 if(strlen(bytes) > ITEM_LABEL_LENGTH) {
4165 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4166 "%s [truncated]: %s", hfinfo->name,
4167 format_text(bytes, strlen(bytes)));
4169 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4170 "%s: %s", hfinfo->name,
4171 format_text(bytes, strlen(bytes)));
4173 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4174 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4178 g_error("hfinfo->type %d (%s) not handled\n",
4180 ftype_name(hfinfo->type));
4181 DISSECTOR_ASSERT_NOT_REACHED();
4187 fill_label_boolean(field_info *fi, gchar *label_str)
4189 char *p = label_str;
4190 int bitfield_byte_length = 0, bitwidth;
4191 guint32 unshifted_value;
4193 int ret; /*tmp return value */
4195 header_field_info *hfinfo = fi->hfinfo;
4196 const true_false_string *tfstring = &tfs_true_false;
4198 if (hfinfo->strings) {
4199 tfstring = (const struct true_false_string*) hfinfo->strings;
4202 value = fvalue_get_uinteger(&fi->value);
4203 if (hfinfo->bitmask) {
4204 /* Figure out the bit width */
4205 bitwidth = hfinfo_bitwidth(hfinfo);
4208 unshifted_value = value;
4209 if (hfinfo->bitshift > 0) {
4210 unshifted_value <<= hfinfo->bitshift;
4213 /* Create the bitfield first */
4214 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
4215 bitfield_byte_length = p - label_str;
4218 /* Fill in the textual info */
4219 ret = g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
4220 "%s: %s", hfinfo->name,
4221 value ? tfstring->true_string : tfstring->false_string);
4222 if ((ret == -1) || (ret >= (ITEM_LABEL_LENGTH - bitfield_byte_length)))
4223 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4227 /* Fills data for bitfield ints with val_strings */
4229 fill_label_enumerated_bitfield(field_info *fi, gchar *label_str)
4231 const char *format = NULL;
4233 int bitfield_byte_length, bitwidth;
4234 guint32 unshifted_value;
4236 int ret; /*tmp return value */
4238 header_field_info *hfinfo = fi->hfinfo;
4240 /* Figure out the bit width */
4241 bitwidth = hfinfo_bitwidth(hfinfo);
4243 /* Pick the proper format string */
4244 format = hfinfo_uint_vals_format(hfinfo);
4247 unshifted_value = fvalue_get_uinteger(&fi->value);
4248 value = unshifted_value;
4249 if (hfinfo->bitshift > 0) {
4250 unshifted_value <<= hfinfo->bitshift;
4253 /* Create the bitfield first */
4254 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
4255 bitfield_byte_length = p - label_str;
4257 /* Fill in the textual info using stored (shifted) value */
4258 ret = g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
4259 format, hfinfo->name,
4260 val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
4261 if ((ret == -1) || (ret >= (ITEM_LABEL_LENGTH - bitfield_byte_length)))
4262 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4266 fill_label_numeric_bitfield(field_info *fi, gchar *label_str)
4268 const char *format = NULL;
4270 int bitfield_byte_length, bitwidth;
4271 guint32 unshifted_value;
4273 int ret; /*tmp return value */
4275 header_field_info *hfinfo = fi->hfinfo;
4277 /* Figure out the bit width */
4278 bitwidth = hfinfo_bitwidth(hfinfo);
4280 /* Pick the proper format string */
4281 format = hfinfo_uint_format(hfinfo);
4284 unshifted_value = fvalue_get_uinteger(&fi->value);
4285 value = unshifted_value;
4286 if (hfinfo->bitshift > 0) {
4287 unshifted_value <<= hfinfo->bitshift;
4290 /* Create the bitfield using */
4291 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
4292 bitfield_byte_length = p - label_str;
4294 /* Fill in the textual info using stored (shifted) value */
4295 if (IS_BASE_DUAL(hfinfo->display)) {
4296 ret = g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
4297 format, hfinfo->name, value, value);
4299 ret = g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
4300 format, hfinfo->name, value);
4302 if ((ret == -1) || (ret >= (ITEM_LABEL_LENGTH - bitfield_byte_length)))
4303 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4308 fill_label_enumerated_uint(field_info *fi, gchar *label_str)
4310 const char *format = NULL;
4311 header_field_info *hfinfo = fi->hfinfo;
4313 int ret; /*tmp return value */
4315 /* Pick the proper format string */
4316 format = hfinfo_uint_vals_format(hfinfo);
4318 value = fvalue_get_uinteger(&fi->value);
4320 /* Fill in the textual info */
4321 if (hfinfo->display & BASE_RANGE_STRING) {
4322 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4323 format, hfinfo->name,
4324 rval_to_str(value, hfinfo->strings, "Unknown"), value);
4326 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4327 format, hfinfo->name,
4328 val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
4330 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4331 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4335 fill_label_uint(field_info *fi, gchar *label_str)
4337 const char *format = NULL;
4338 header_field_info *hfinfo = fi->hfinfo;
4340 int ret; /*tmp return value */
4342 /* Pick the proper format string */
4343 format = hfinfo_uint_format(hfinfo);
4344 value = fvalue_get_uinteger(&fi->value);
4346 /* Fill in the textual info */
4347 if (IS_BASE_DUAL(hfinfo->display)) {
4348 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4349 format, hfinfo->name, value, value);
4351 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4352 format, hfinfo->name, value);
4354 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4355 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4359 fill_label_uint64(field_info *fi, gchar *label_str)
4361 const char *format = NULL;
4362 header_field_info *hfinfo = fi->hfinfo;
4364 int ret; /*tmp return value */
4366 /* Pick the proper format string */
4367 format = hfinfo_uint64_format(hfinfo);
4368 value = fvalue_get_integer64(&fi->value);
4370 /* Fill in the textual info */
4371 if (IS_BASE_DUAL(hfinfo->display)) {
4372 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4373 format, hfinfo->name, value, value);
4375 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4376 format, hfinfo->name, value);
4378 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4379 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4383 fill_label_enumerated_int(field_info *fi, gchar *label_str)
4385 const char *format = NULL;
4386 header_field_info *hfinfo = fi->hfinfo;
4388 int ret; /*tmp return value */
4390 /* Pick the proper format string */
4391 format = hfinfo_int_vals_format(hfinfo);
4392 value = fvalue_get_sinteger(&fi->value);
4394 /* Fill in the textual info */
4395 if (hfinfo->display & BASE_RANGE_STRING) {
4396 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4397 format, hfinfo->name,
4398 rval_to_str(value, hfinfo->strings, "Unknown"), value);
4400 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4401 format, hfinfo->name,
4402 val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
4404 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4405 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4409 fill_label_int(field_info *fi, gchar *label_str)
4411 const char *format = NULL;
4412 header_field_info *hfinfo = fi->hfinfo;
4414 int ret; /*tmp return value */
4416 /* Pick the proper format string */
4417 format = hfinfo_int_format(hfinfo);
4418 value = fvalue_get_sinteger(&fi->value);
4420 /* Fill in the textual info */
4421 if (IS_BASE_DUAL(hfinfo->display)) {
4422 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4423 format, hfinfo->name, value, value);
4425 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4426 format, hfinfo->name, value);
4428 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4429 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4433 fill_label_int64(field_info *fi, gchar *label_str)
4435 const char *format = NULL;
4436 header_field_info *hfinfo = fi->hfinfo;
4438 int ret; /*tmp return value */
4440 /* Pick the proper format string */
4441 format = hfinfo_int64_format(hfinfo);
4442 value = fvalue_get_integer64(&fi->value);
4444 /* Fill in the textual info */
4445 if (IS_BASE_DUAL(hfinfo->display)) {
4446 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4447 format, hfinfo->name, value, value);
4449 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4450 format, hfinfo->name, value);
4452 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4453 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4457 hfinfo_bitwidth(header_field_info *hfinfo)
4461 if (!hfinfo->bitmask) {
4465 switch(hfinfo->type) {
4483 bitwidth = hfinfo->display; /* hacky? :) */
4486 DISSECTOR_ASSERT_NOT_REACHED();
4493 hfinfo_uint_vals_format(header_field_info *hfinfo)
4495 const char *format = NULL;
4497 /* bit operation to reset the potential BASE_RANGE_STRING (or others in
4499 switch(hfinfo->display & BASE_STRUCTURE_RESET) {
4502 format = "%s: %s (%u)";
4504 case BASE_OCT: /* I'm lazy */
4505 format = "%s: %s (%o)";
4509 switch(hfinfo->type) {
4511 format = "%s: %s (0x%02x)";
4514 format = "%s: %s (0x%04x)";
4517 format = "%s: %s (0x%06x)";
4520 format = "%s: %s (0x%08x)";
4523 DISSECTOR_ASSERT_NOT_REACHED();
4528 DISSECTOR_ASSERT_NOT_REACHED();
4535 hfinfo_uint_format(header_field_info *hfinfo)
4537 const char *format = NULL;
4539 /* Pick the proper format string */
4540 if (hfinfo->type == FT_FRAMENUM) {
4542 * Frame numbers are always displayed in decimal.
4546 switch(hfinfo->display) {
4551 switch(hfinfo->type) {
4553 format = "%s: %u (0x%02x)";
4556 format = "%s: %u (0x%04x)";
4559 format = "%s: %u (0x%06x)";
4562 format = "%s: %u (0x%08x)";
4565 DISSECTOR_ASSERT_NOT_REACHED();
4569 case BASE_OCT: /* I'm lazy */
4573 switch(hfinfo->type) {
4575 format = "%s: 0x%02x";
4578 format = "%s: 0x%04x";
4581 format = "%s: 0x%06x";
4584 format = "%s: 0x%08x";
4587 DISSECTOR_ASSERT_NOT_REACHED();
4592 switch(hfinfo->type) {
4594 format = "%s: 0x%02x (%u)";
4597 format = "%s: 0x%04x (%u)";
4600 format = "%s: 0x%06x (%u)";
4603 format = "%s: 0x%08x (%u)";
4606 DISSECTOR_ASSERT_NOT_REACHED();
4611 DISSECTOR_ASSERT_NOT_REACHED();
4619 hfinfo_int_vals_format(header_field_info *hfinfo)
4621 const char *format = NULL;
4623 /* bit operation to reset the potential BASE_RANGE_STRING (or others in
4625 switch(hfinfo->display & BASE_STRUCTURE_RESET) {
4628 format = "%s: %s (%d)";
4630 case BASE_OCT: /* I'm lazy */
4631 format = "%s: %s (%o)";
4635 switch(hfinfo->type) {
4637 format = "%s: %s (0x%02x)";
4640 format = "%s: %s (0x%04x)";
4643 format = "%s: %s (0x%06x)";
4646 format = "%s: %s (0x%08x)";
4649 DISSECTOR_ASSERT_NOT_REACHED();
4654 DISSECTOR_ASSERT_NOT_REACHED();
4661 hfinfo_uint64_format(header_field_info *hfinfo)
4663 const char *format = NULL;
4665 /* Pick the proper format string */
4666 switch(hfinfo->display) {
4668 format = "%s: %" G_GINT64_MODIFIER "u";
4671 format = "%s: %" G_GINT64_MODIFIER "u (%" G_GINT64_MODIFIER "x)";
4673 case BASE_OCT: /* I'm lazy */
4674 format = "%s: %" G_GINT64_MODIFIER "o";
4677 format = "%s: 0x%016" G_GINT64_MODIFIER "x";
4680 format = "%s: 0x%016" G_GINT64_MODIFIER "x (%" G_GINT64_MODIFIER "u)";
4683 DISSECTOR_ASSERT_NOT_REACHED();
4690 hfinfo_int_format(header_field_info *hfinfo)
4692 const char *format = NULL;
4694 /* Pick the proper format string */
4695 switch(hfinfo->display) {
4700 switch(hfinfo->type) {
4702 format = "%s: %d (0x%02x)";
4705 format = "%s: %d (0x%04x)";
4708 format = "%s: %d (0x%06x)";
4711 format = "%s: %d (0x%08x)";
4714 DISSECTOR_ASSERT_NOT_REACHED();
4718 case BASE_OCT: /* I'm lazy */
4722 switch(hfinfo->type) {
4724 format = "%s: 0x%02x";
4727 format = "%s: 0x%04x";
4730 format = "%s: 0x%06x";
4733 format = "%s: 0x%08x";
4736 DISSECTOR_ASSERT_NOT_REACHED();
4741 switch(hfinfo->type) {
4743 format = "%s: 0x%02x (%d)";
4746 format = "%s: 0x%04x (%d)";
4749 format = "%s: 0x%06x (%d)";
4752 format = "%s: 0x%08x (%d)";
4755 DISSECTOR_ASSERT_NOT_REACHED();
4760 DISSECTOR_ASSERT_NOT_REACHED();
4767 hfinfo_int64_format(header_field_info *hfinfo)
4769 const char *format = NULL;
4771 /* Pick the proper format string */
4772 switch(hfinfo->display) {
4774 format = "%s: %" G_GINT64_MODIFIER "d";
4777 format = "%s: %" G_GINT64_MODIFIER "d (%" G_GINT64_MODIFIER "x)";
4779 case BASE_OCT: /* I'm lazy */
4780 format = "%s: %" G_GINT64_MODIFIER "o";
4783 format = "%s: 0x%016" G_GINT64_MODIFIER "x";
4786 format = "%s: 0x%016" G_GINT64_MODIFIER "x (%" G_GINT64_MODIFIER "d)";
4789 DISSECTOR_ASSERT_NOT_REACHED();
4798 proto_registrar_n(void)
4800 return gpa_hfinfo.len;
4804 proto_registrar_get_name(int n)
4806 header_field_info *hfinfo;
4808 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
4809 return hfinfo->name;
4813 proto_registrar_get_abbrev(int n)
4815 header_field_info *hfinfo;
4817 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
4818 return hfinfo->abbrev;
4822 proto_registrar_get_ftype(int n)
4824 header_field_info *hfinfo;
4826 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
4827 return hfinfo->type;
4831 proto_registrar_get_parent(int n)
4833 header_field_info *hfinfo;
4835 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
4836 return hfinfo->parent;
4840 proto_registrar_is_protocol(int n)
4842 header_field_info *hfinfo;
4844 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
4845 return (hfinfo->parent == -1 ? TRUE : FALSE);
4848 /* Returns length of field in packet (not necessarily the length
4849 * in our internal representation, as in the case of IPv4).
4850 * 0 means undeterminable at time of registration
4851 * -1 means the field is not registered. */
4853 proto_registrar_get_length(int n)
4855 header_field_info *hfinfo;
4857 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
4858 return ftype_length(hfinfo->type);
4863 /* Looks for a protocol or a field in a proto_tree. Returns TRUE if
4864 * it exists anywhere, or FALSE if it exists nowhere. */
4866 proto_check_for_protocol_or_field(proto_tree* tree, int id)
4868 GPtrArray *ptrs = proto_get_finfo_ptr_array(tree, id);
4873 else if (g_ptr_array_len(ptrs) > 0) {
4881 /* Return GPtrArray* of field_info pointers for all hfindex that appear in tree.
4882 * This only works if the hfindex was "primed" before the dissection
4883 * took place, as we just pass back the already-created GPtrArray*.
4884 * The caller should *not* free the GPtrArray*; proto_tree_free_node()
4887 proto_get_finfo_ptr_array(proto_tree *tree, int id)
4889 return g_hash_table_lookup(PTREE_DATA(tree)->interesting_hfids,
4890 GINT_TO_POINTER(id));
4894 /* Helper struct for proto_find_info() and proto_all_finfos() */
4900 /* Helper function for proto_find_info() */
4902 find_finfo(proto_node *node, gpointer data)
4904 field_info *fi = PITEM_FINFO(node);
4905 if (fi && fi->hfinfo) {
4906 if (fi->hfinfo->id == ((ffdata_t*)data)->id) {
4907 g_ptr_array_add(((ffdata_t*)data)->array, fi);
4911 /* Don't stop traversing. */
4915 /* Return GPtrArray* of field_info pointers for all hfindex that appear in a tree.
4916 * This works on any proto_tree, primed or unprimed, but actually searches
4917 * the tree, so it is slower than using proto_get_finfo_ptr_array on a primed tree.
4918 * The caller does need to free the returned GPtrArray with
4919 * g_ptr_array_free(<array>, FALSE).
4922 proto_find_finfo(proto_tree *tree, int id)
4926 ffdata.array = g_ptr_array_new();
4929 proto_tree_traverse_pre_order(tree, find_finfo, &ffdata);
4931 return ffdata.array;
4934 /* Helper function for proto_all_finfos() */
4936 every_finfo(proto_node *node, gpointer data)
4938 field_info *fi = PITEM_FINFO(node);
4939 if (fi && fi->hfinfo) {
4940 g_ptr_array_add(((ffdata_t*)data)->array, fi);
4943 /* Don't stop traversing. */
4947 /* Return GPtrArray* of field_info pointers containing all hfindexes that appear in a tree. */
4949 proto_all_finfos(proto_tree *tree)
4953 ffdata.array = g_ptr_array_new();
4956 proto_tree_traverse_pre_order(tree, every_finfo, &ffdata);
4958 return ffdata.array;
4969 check_for_offset(proto_node *node, gpointer data)
4971 field_info *fi = PITEM_FINFO(node);
4972 offset_search_t *offsearch = data;
4974 /* !fi == the top most container node which holds nothing */
4975 if (fi && !PROTO_ITEM_IS_HIDDEN(node) && fi->ds_tvb && offsearch->tvb == fi->ds_tvb) {
4976 if (offsearch->offset >= (guint) fi->start &&
4977 offsearch->offset < (guint) (fi->start + fi->length)) {
4979 offsearch->finfo = fi;
4980 return FALSE; /* keep traversing */
4983 return FALSE; /* keep traversing */
4986 /* Search a proto_tree backwards (from leaves to root) looking for the field
4987 * whose start/length occupies 'offset' */
4988 /* XXX - I couldn't find an easy way to search backwards, so I search
4989 * forwards, w/o stopping. Therefore, the last finfo I find will the be
4990 * the one I want to return to the user. This algorithm is inefficient
4991 * and could be re-done, but I'd have to handle all the children and
4992 * siblings of each node myself. When I have more time I'll do that.
4995 proto_find_field_from_offset(proto_tree *tree, guint offset, tvbuff_t *tvb)
4997 offset_search_t offsearch;
4999 offsearch.offset = offset;
5000 offsearch.finfo = NULL;
5001 offsearch.tvb = tvb;
5003 proto_tree_traverse_pre_order(tree, check_for_offset, &offsearch);
5005 return offsearch.finfo;
5008 /* Dumps the protocols in the registration database to stdout. An independent
5009 * program can take this output and format it into nice tables or HTML or
5012 * There is one record per line. The fields are tab-delimited.
5014 * Field 1 = protocol name
5015 * Field 2 = protocol short name
5016 * Field 3 = protocol filter name
5019 proto_registrar_dump_protocols(void)
5021 protocol_t *protocol;
5023 void *cookie = NULL;
5025 for (i = proto_get_first_protocol(&cookie); i != -1;
5026 i = proto_get_next_protocol(&cookie)) {
5027 protocol = find_protocol_by_id(i);
5028 printf("%s\t%s\t%s\n", protocol->name, protocol->short_name,
5029 protocol->filter_name);
5033 /* Dumps the value_string and true/false strings for fields that have
5034 * them. There is one record per line. Fields are tab-delimited.
5035 * There are two types of records, Value String records and True/False
5036 * String records. The first field, 'V' or 'T', indicates the type
5042 * Field 2 = field abbreviation to which this value string corresponds
5043 * Field 3 = Integer value
5046 * True/False Strings
5047 * ------------------
5049 * Field 2 = field abbreviation to which this true/false string corresponds
5050 * Field 3 = True String
5051 * Field 4 = False String
5054 proto_registrar_dump_values(void)
5056 header_field_info *hfinfo, *parent_hfinfo;
5058 const value_string *vals;
5059 const true_false_string *tfs;
5061 len = gpa_hfinfo.len;
5062 for (i = 0; i < len ; i++) {
5063 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
5065 if (hfinfo->id == hf_text_only) {
5069 /* ignore protocols */
5070 if (proto_registrar_is_protocol(i)) {
5073 /* process header fields */
5076 * If this field isn't at the head of the list of
5077 * fields with this name, skip this field - all
5078 * fields with the same name are really just versions
5079 * of the same field stored in different bits, and
5080 * should have the same type/radix/value list, and
5081 * just differ in their bit masks. (If a field isn't
5082 * a bitfield, but can be, say, 1 or 2 bytes long,
5083 * it can just be made FT_UINT16, meaning the
5084 * *maximum* length is 2 bytes, and be used
5087 if (hfinfo->same_name_prev != NULL)
5090 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
5095 if (hfinfo->type == FT_UINT8 ||
5096 hfinfo->type == FT_UINT16 ||
5097 hfinfo->type == FT_UINT24 ||
5098 hfinfo->type == FT_UINT32 ||
5099 hfinfo->type == FT_UINT64 ||
5100 hfinfo->type == FT_INT8 ||
5101 hfinfo->type == FT_INT16 ||
5102 hfinfo->type == FT_INT24 ||
5103 hfinfo->type == FT_INT32 ||
5104 hfinfo->type == FT_INT64) {
5106 vals = hfinfo->strings;
5108 else if (hfinfo->type == FT_BOOLEAN) {
5109 tfs = hfinfo->strings;
5112 /* Print value strings? */
5115 while (vals[vi].strptr) {
5116 /* Print in the proper base */
5117 if (hfinfo->display == BASE_HEX) {
5118 printf("V\t%s\t0x%x\t%s\n",
5124 printf("V\t%s\t%u\t%s\n",
5133 /* Print true/false strings? */
5135 printf("T\t%s\t%s\t%s\n", hfinfo->abbrev,
5136 tfs->true_string, tfs->false_string);
5142 /* Dumps the contents of the registration database to stdout. An indepedent
5143 * program can take this output and format it into nice tables or HTML or
5146 * There is one record per line. Each record is either a protocol or a header
5147 * field, differentiated by the first field. The fields are tab-delimited.
5152 * Field 2 = descriptive protocol name
5153 * Field 3 = protocol abbreviation
5159 * Field 2 = descriptive field name
5160 * Field 3 = field abbreviation
5161 * Field 4 = type ( textual representation of the the ftenum type )
5162 * Field 5 = parent protocol abbreviation
5163 * Field 6 = blurb describing field
5167 * Field 2 = descriptive field name
5168 * Field 3 = field abbreviation
5169 * Field 4 = type ( textual representation of the the ftenum type )
5170 * Field 5 = parent protocol abbreviation
5171 * Field 6 = blurb describing field
5172 * Field 7 = base for display (for integer types)
5173 * Field 8 = blurb describing field (yes, apparently we repeated this accidentally)
5177 * Field 2 = descriptive field name
5178 * Field 3 = field abbreviation
5179 * Field 4 = type ( textual representation of the the ftenum type )
5180 * Field 5 = parent protocol abbreviation
5181 * Field 6 = blurb describing field
5182 * Field 7 = base for display (for integer types)
5186 proto_registrar_dump_fields(int format)
5188 header_field_info *hfinfo, *parent_hfinfo;
5190 const char *enum_name;
5191 const char *base_name;
5194 len = gpa_hfinfo.len;
5195 for (i = 0; i < len ; i++) {
5196 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
5199 * Skip the pseudo-field for "proto_tree_add_text()" since
5200 * we don't want it in the list of filterable fields.
5202 if (hfinfo->id == hf_text_only)
5205 /* format for protocols */
5206 if (proto_registrar_is_protocol(i)) {
5207 printf("P\t%s\t%s\n", hfinfo->name, hfinfo->abbrev);
5209 /* format for header fields */
5212 * If this field isn't at the head of the list of
5213 * fields with this name, skip this field - all
5214 * fields with the same name are really just versions
5215 * of the same field stored in different bits, and
5216 * should have the same type/radix/value list, and
5217 * just differ in their bit masks. (If a field isn't
5218 * a bitfield, but can be, say, 1 or 2 bytes long,
5219 * it can just be made FT_UINT16, meaning the
5220 * *maximum* length is 2 bytes, and be used
5223 if (hfinfo->same_name_prev != NULL)
5226 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
5228 enum_name = ftype_name(hfinfo->type);
5232 if (hfinfo->type == FT_UINT8 ||
5233 hfinfo->type == FT_UINT16 ||
5234 hfinfo->type == FT_UINT24 ||
5235 hfinfo->type == FT_UINT32 ||
5236 hfinfo->type == FT_UINT64 ||
5237 hfinfo->type == FT_INT8 ||
5238 hfinfo->type == FT_INT16 ||
5239 hfinfo->type == FT_INT24 ||
5240 hfinfo->type == FT_INT32 ||
5241 hfinfo->type == FT_INT64) {
5244 switch(hfinfo->display) {
5246 base_name = "BASE_NONE";
5249 base_name = "BASE_DEC";
5252 base_name = "BASE_HEX";
5255 base_name = "BASE_OCT";
5258 base_name = "BASE_DEC_HEX";
5261 base_name = "BASE_HEX_DEC";
5267 blurb = hfinfo->blurb;
5271 printf("F\t%s\t%s\t%s\t%s\t%s\n",
5272 hfinfo->name, hfinfo->abbrev, enum_name,
5273 parent_hfinfo->abbrev, blurb);
5275 else if (format == 2) {
5276 printf("F\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n",
5277 hfinfo->name, hfinfo->abbrev, enum_name,
5278 parent_hfinfo->abbrev, blurb,
5281 else if (format == 3) {
5282 printf("F\t%s\t%s\t%s\t%s\t%s\t%s\t%u\n",
5283 hfinfo->name, hfinfo->abbrev, enum_name,
5284 parent_hfinfo->abbrev, blurb,
5285 base_name, hfinfo->bitmask);
5288 g_assert_not_reached();
5295 hfinfo_numeric_format(header_field_info *hfinfo)
5297 const char *format = NULL;
5299 /* Pick the proper format string */
5300 if (hfinfo->type == FT_FRAMENUM) {
5302 * Frame numbers are always displayed in decimal.
5304 format = "%s == %u";
5306 /* Pick the proper format string */
5307 switch(hfinfo->display) {
5310 case BASE_OCT: /* I'm lazy */
5311 switch(hfinfo->type) {
5316 format = "%s == %u";
5319 format = "%s == %" G_GINT64_MODIFIER "u";
5325 format = "%s == %d";
5328 format = "%s == %" G_GINT64_MODIFIER "d";
5331 DISSECTOR_ASSERT_NOT_REACHED();
5337 switch(hfinfo->type) {
5339 format = "%s == 0x%02x";
5342 format = "%s == 0x%04x";
5345 format = "%s == 0x%06x";
5348 format = "%s == 0x%08x";
5351 format = "%s == 0x%016" G_GINT64_MODIFIER "x";
5354 DISSECTOR_ASSERT_NOT_REACHED();
5359 DISSECTOR_ASSERT_NOT_REACHED();
5366 /* This function indicates whether it's possible to construct a
5367 * "match selected" display filter string for the specified field,
5368 * returns an indication of whether it's possible, and, if it's
5369 * possible and "filter" is non-null, constructs the filter and
5370 * sets "*filter" to point to it.
5371 * You do not need to [g_]free() this string since it will be automatically
5372 * freed once the next packet is dissected.
5375 construct_match_selected_string(field_info *finfo, epan_dissect_t *edt,
5378 header_field_info *hfinfo;
5384 gint start, length, length_remaining;
5386 gchar is_signed_num = FALSE;
5388 hfinfo = finfo->hfinfo;
5389 DISSECTOR_ASSERT(hfinfo);
5390 abbrev_len = strlen(hfinfo->abbrev);
5393 * XXX - we can't use the "val_to_string_repr" and "string_repr_len"
5394 * functions for FT_UINT and FT_INT types, as we choose the base in
5395 * the string expression based on the display base of the field.
5397 * Note that the base does matter, as this is also used for
5398 * the protocolinfo tap.
5400 * It might be nice to use them in "proto_item_fill_label()"
5401 * as well, although, there, you'd have to deal with the base
5402 * *and* with resolved values for addresses.
5404 * Perhaps we need two different val_to_string routines, one
5405 * to generate items for display filters and one to generate
5406 * strings for display, and pass to both of them the
5407 * "display" and "strings" values in the header_field_info
5408 * structure for the field, so they can get the base and,
5409 * if the field is Boolean or an enumerated integer type,
5410 * the tables used to generate human-readable values.
5412 switch(hfinfo->type) {
5418 is_signed_num = TRUE;
5425 * 4 bytes for " == ".
5428 * a sign + up to 10 digits of 32-bit integer,
5431 * "0x" + 8 digits of 32-bit integer, in hex;
5433 * 11 digits of 32-bit integer, in octal.
5434 * (No, we don't do octal, but this way,
5435 * we know that if we do, this will still
5438 * 1 byte for the trailing '\0'.
5440 if (filter != NULL) {
5441 dfilter_len = abbrev_len + 4 + 11 + 1;
5442 *filter = ep_alloc0(dfilter_len);
5443 format = hfinfo_numeric_format(hfinfo);
5445 g_snprintf(*filter, dfilter_len, format,
5447 fvalue_get_sinteger(&finfo->value));
5449 g_snprintf(*filter, dfilter_len, format,
5451 fvalue_get_uinteger(&finfo->value));
5459 * 4 bytes for " == ".
5462 * a sign + up to 20 digits of 32-bit integer,
5465 * "0x" + 16 digits of 32-bit integer, in hex;
5467 * 22 digits of 32-bit integer, in octal.
5468 * (No, we don't do octal, but this way,
5469 * we know that if we do, this will still
5472 * 1 byte for the trailing '\0'.
5474 if (filter != NULL) {
5475 dfilter_len = abbrev_len + 4 + 22 + 1;
5476 *filter = ep_alloc0(dfilter_len);
5477 format = hfinfo_numeric_format(hfinfo);
5478 g_snprintf(*filter, dfilter_len, format,
5480 fvalue_get_integer64(&finfo->value));
5486 *filter = ep_strdup(finfo->hfinfo->abbrev);
5492 * If the length is 0, just match the name of the
5495 * (Also check for negative values, just in case,
5496 * as we'll cast it to an unsigned value later.)
5498 length = finfo->length;
5501 *filter = ep_strdup(finfo->hfinfo->abbrev);
5508 * This doesn't have a value, so we'd match
5509 * on the raw bytes at this address.
5511 * Should we be allowed to access to the raw bytes?
5512 * If "edt" is NULL, the answer is "no".
5518 * Is this field part of the raw frame tvbuff?
5519 * If not, we can't use "frame[N:M]" to match
5522 * XXX - should this be frame-relative, or
5523 * protocol-relative?
5525 * XXX - does this fallback for non-registered
5526 * fields even make sense?
5528 if (finfo->ds_tvb != edt->tvb)
5529 return FALSE; /* you lose */
5532 * Don't go past the end of that tvbuff.
5534 length_remaining = tvb_length_remaining(finfo->ds_tvb, finfo->start);
5535 if (length > length_remaining)
5536 length = length_remaining;
5540 if (filter != NULL) {
5541 start = finfo->start;
5542 buf_len = 32 + length * 3;
5543 *filter = ep_alloc0(buf_len);
5546 ptr += g_snprintf(ptr, buf_len-(ptr-*filter),
5547 "frame[%d:%d] == ", finfo->start, length);
5548 for (i=0;i<length; i++) {
5549 c = tvb_get_guint8(finfo->ds_tvb, start);
5552 ptr += g_snprintf(ptr, buf_len-(ptr-*filter), "%02x", c);
5555 ptr += g_snprintf(ptr, buf_len-(ptr-*filter), ":%02x", c);
5561 /* By default, use the fvalue's "to_string_repr" method. */
5563 /* Figure out the string length needed.
5564 * The ft_repr length.
5565 * 4 bytes for " == ".
5566 * 1 byte for trailing NUL.
5568 if (filter != NULL) {
5569 dfilter_len = fvalue_string_repr_len(&finfo->value,
5571 dfilter_len += abbrev_len + 4 + 1;
5572 *filter = ep_alloc0(dfilter_len);
5574 /* Create the string */
5575 g_snprintf(*filter, dfilter_len, "%s == ",
5577 fvalue_to_string_repr(&finfo->value,
5579 &(*filter)[abbrev_len + 4]);
5588 * Returns TRUE if we can do a "match selected" on the field, FALSE
5592 proto_can_match_selected(field_info *finfo, epan_dissect_t *edt)
5594 return construct_match_selected_string(finfo, edt, NULL);
5597 /* This function attempts to construct a "match selected" display filter
5598 * string for the specified field; if it can do so, it returns a pointer
5599 * to the string, otherwise it returns NULL.
5601 * The string is allocated with packet lifetime scope.
5602 * You do not need to [g_]free() this string since it will be automatically
5603 * freed once the next packet is dissected.
5606 proto_construct_match_selected_string(field_info *finfo, epan_dissect_t *edt)
5610 if (!construct_match_selected_string(finfo, edt, &filter))
5616 /* This function will dissect a sequence of bytes that describe a
5618 * hf_hdr is a 8/16/24/32 bit integer that describes the bitmask to be dissected.
5619 * This field will form an expansion under which the individual fields of the
5620 * bitmask is dissected and displayed.
5621 * This field must be of the type FT_[U]INT{8|16|24|32}.
5623 * fields is an array of pointers to int that lists all the fields of the
5624 * bitmask. These fields can be either of the type FT_BOOLEAN for flags
5625 * or another integer of the same type/size as hf_hdr with a mask specified.
5626 * This array is terminated by a NULL entry.
5628 * FT_BOOLEAN bits that are set to 1 will have the name added to the expansion.
5629 * FT_integer fields that have a value_string attached will have the
5630 * matched string displayed on the expansion line.
5633 proto_tree_add_bitmask(proto_tree *parent_tree, tvbuff_t *tvb, int offset, int hf_hdr, gint ett, const int **fields, gboolean little_endian)
5635 proto_tree *tree=NULL;
5636 proto_item *item=NULL;
5637 header_field_info *hf_info;
5641 hf_info=proto_registrar_get_nth(hf_hdr);
5642 switch(hf_info->type){
5646 value=tvb_get_guint8(tvb, offset);
5652 value=tvb_get_letohs(tvb, offset);
5654 value=tvb_get_ntohs(tvb, offset);
5661 value=tvb_get_letoh24(tvb, offset);
5663 value=tvb_get_ntoh24(tvb, offset);
5670 value=tvb_get_letohl(tvb, offset);
5672 value=tvb_get_ntohl(tvb, offset);
5676 g_assert_not_reached();
5680 item=proto_tree_add_item(parent_tree, hf_hdr, tvb, offset, len, little_endian);
5681 tree=proto_item_add_subtree(item, ett);
5685 header_field_info *hf_field;
5686 guint32 tmpval, tmpmask;
5688 hf_field=proto_registrar_get_nth(**fields);
5689 switch(hf_field->type){
5698 proto_tree_add_item(tree, **fields, tvb, offset, len, little_endian);
5700 /* Mask and shift out the value */
5701 tmpmask=hf_field->bitmask;
5705 while(!(tmpmask&0x00000001)){
5710 /* Show the value_string content (if there is one) */
5711 if(hf_field->strings){
5712 proto_item_append_text(item, ", %s", val_to_str(tmpval, hf_field->strings, "Unknown"));
5717 proto_tree_add_item(tree, **fields, tvb, offset, len, little_endian);
5718 /* if the flag is set, show the name */
5719 if(hf_field->bitmask&value){
5720 proto_item_append_text(item, ", %s", hf_field->name);
5724 g_assert_not_reached();
5734 proto_tree_add_bits_item(proto_tree *tree, int hf_index, tvbuff_t *tvb, gint bit_offset, gint no_of_bits, gboolean little_endian)
5736 return proto_tree_add_bits_ret_val(tree, hf_index, tvb, bit_offset, no_of_bits, NULL, little_endian);
5740 * This function will dissect a sequence of bits that does not need to be byte aligned the bits
5741 * set vill be shown in the tree as ..10 10.. and the integer value returned if return_value is set.
5742 * Offset should be given in bits from the start of the tvb.
5746 proto_tree_add_bits_ret_val(proto_tree *tree, int hf_index, tvbuff_t *tvb, gint bit_offset, gint no_of_bits, guint64 *return_value, gboolean little_endian)
5751 guint8 remaining_bits;
5752 guint64 mask = 0,tmp;
5754 header_field_info *hf_field;
5759 hf_field = proto_registrar_get_nth(hf_index);
5761 /* Byte align offset */
5762 offset = bit_offset>>3;
5766 * Calculate the number of octets used to hold the bits
5768 tot_no_bits = ((bit_offset&0x7)+no_of_bits);
5769 length = tot_no_bits>>3;
5770 remaining_bits = tot_no_bits % 8;
5771 if ((remaining_bits)!=0)
5774 if (no_of_bits < 9){
5775 value = tvb_get_bits8(tvb, bit_offset, no_of_bits);
5776 }else if(no_of_bits < 17){
5777 value = tvb_get_bits16(tvb, bit_offset, no_of_bits, little_endian);
5778 }else if(no_of_bits < 33){
5779 value = tvb_get_bits32(tvb, bit_offset, no_of_bits, little_endian);
5780 }else if(no_of_bits < 65){
5781 value = tvb_get_bits64(tvb, bit_offset, no_of_bits, little_endian);
5782 }else if(no_of_bits>64){
5783 DISSECTOR_ASSERT_NOT_REACHED();
5789 mask = mask << (no_of_bits-1);
5791 /* prepare the string */
5794 for(bit=0;bit<((int)(bit_offset&0x07));bit++){
5795 if(bit&&(!(bit%4))){
5800 /* read the bits for the int */
5801 for(i=0;i<no_of_bits;i++){
5802 if(bit&&(!(bit%4))){
5805 if(bit&&(!(bit%8))){
5818 if(bit&&(!(bit%4))){
5825 *return_value=value;
5831 strcat(str,hf_field->name);
5833 switch(hf_field->type){
5836 if (hf_field->strings) {
5837 const true_false_string *tfstring = &tfs_true_false;
5838 tfstring = (const struct true_false_string*) hf_field->strings;
5840 return proto_tree_add_boolean_format(tree, hf_index, tvb, offset, length, (guint32)value,
5843 (guint32)value ? tfstring->true_string : tfstring->false_string);
5845 return proto_tree_add_boolean_format(tree, hf_index, tvb, offset, length, (guint32)value,
5855 /* 1 - 32 bits field */
5856 if (hf_field->strings) {
5857 return proto_tree_add_uint_format(tree, hf_index, tvb, offset, length, (guint32)value,
5860 val_to_str((guint32)value, cVALS(hf_field->strings), "Unknown "),
5864 switch(hf_field->display){
5866 return proto_tree_add_uint_format(tree, hf_index, tvb, offset, length, (guint32)value,
5872 return proto_tree_add_uint_format(tree, hf_index, tvb, offset, length, (guint32)value,
5878 DISSECTOR_ASSERT_NOT_REACHED();
5884 switch(hf_field->display){
5886 return proto_tree_add_uint64_format(tree, hf_index, tvb, offset, length, value,
5887 "%s: %" G_GINT64_MODIFIER "u",
5891 return proto_tree_add_uint64_format(tree, hf_index, tvb, offset, length, value,
5892 "%s: 0x%" G_GINT64_MODIFIER "x",
5896 DISSECTOR_ASSERT_NOT_REACHED();
5902 DISSECTOR_ASSERT_NOT_REACHED();