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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
36 #include "ptvcursor.h"
38 #include "addr_resolv.h"
39 #include "oid_resolv.h"
42 #include "epan_dissect.h"
53 #define cVALS(x) (const value_string*)(x)
56 #define TRY_TO_FAKE_THIS_ITEM(tree, hfindex) \
57 /* If this item is not referenced we dont have to do much work \
58 at all but we should still return a node so that \
59 field items below this node ( think proto_item_add_subtree() )\
60 will still have somewhere to attach to \
61 or else filtering will not work (they would be ignored since tree\
63 DONT try to fake a node where PITEM_FINFO(pi) is NULL \
64 since dissectors that want to do proto_item_set_len() ot \
65 other operations that dereference this would crash. \
66 We dont fake FT_PROTOCOL either since these are cheap and \
67 some stuff (proto hier stat) assumes they always exist. \
69 if(!(PTREE_DATA(tree)->visible)){ \
70 if(PITEM_FINFO(tree)){ \
71 register header_field_info *hfinfo; \
72 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo); \
73 if((hfinfo->ref_count == 0) \
74 && (hfinfo->type!=FT_PROTOCOL)){ \
75 /* just return tree back to the caller */\
81 #define TRY_TO_FAKE_THIS_ITEM(tree, hfindex) ;
85 proto_tree_free_node(proto_node *node, gpointer data);
87 static void fill_label_boolean(field_info *fi, gchar *label_str);
88 static void fill_label_uint(field_info *fi, gchar *label_str);
89 static void fill_label_uint64(field_info *fi, gchar *label_str);
90 static void fill_label_enumerated_uint(field_info *fi, gchar *label_str);
91 static void fill_label_enumerated_bitfield(field_info *fi, gchar *label_str);
92 static void fill_label_numeric_bitfield(field_info *fi, gchar *label_str);
93 static void fill_label_int(field_info *fi, gchar *label_str);
94 static void fill_label_int64(field_info *fi, gchar *label_str);
95 static void fill_label_enumerated_int(field_info *fi, gchar *label_str);
97 int hfinfo_bitwidth(header_field_info *hfinfo);
98 static const char* hfinfo_uint_vals_format(header_field_info *hfinfo);
99 static const char* hfinfo_uint_format(header_field_info *hfinfo);
100 static const char* hfinfo_uint64_format(header_field_info *hfinfo);
101 static const char* hfinfo_int_vals_format(header_field_info *hfinfo);
102 static const char* hfinfo_int_format(header_field_info *hfinfo);
103 static const char* hfinfo_int64_format(header_field_info *hfinfo);
106 proto_tree_add_node(proto_tree *tree, field_info *fi);
108 static header_field_info *
109 get_hfi_and_length(int hfindex, tvbuff_t *tvb, gint start, gint *length,
113 new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
114 gint start, gint item_length);
117 alloc_field_info(proto_tree *tree, int hfindex, tvbuff_t *tvb,
118 gint start, gint *length);
121 proto_tree_add_pi(proto_tree *tree, int hfindex, tvbuff_t *tvb,
122 gint start, gint *length, field_info **pfi);
125 proto_tree_set_representation_value(proto_item *pi, const char *format, va_list ap);
127 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap);
130 proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb);
132 proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length);
134 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length);
136 proto_tree_set_time(field_info *fi, nstime_t *value_ptr);
138 proto_tree_set_string(field_info *fi, const char* value, gboolean);
140 proto_tree_set_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
142 proto_tree_set_ether(field_info *fi, const guint8* value);
144 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start);
146 proto_tree_set_ipxnet(field_info *fi, guint32 value);
148 proto_tree_set_ipv4(field_info *fi, guint32 value);
150 proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr);
152 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start);
154 proto_tree_set_guid(field_info *fi, const e_guid_t *value_ptr);
156 proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gboolean little_endian);
158 proto_tree_set_oid(field_info *fi, const guint8* value_ptr, gint length);
160 proto_tree_set_oid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
162 proto_tree_set_boolean(field_info *fi, guint32 value);
164 proto_tree_set_float(field_info *fi, float value);
166 proto_tree_set_double(field_info *fi, double value);
168 proto_tree_set_uint(field_info *fi, guint32 value);
170 proto_tree_set_int(field_info *fi, gint32 value);
172 proto_tree_set_uint64(field_info *fi, guint64 value);
174 proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start, gboolean little_endian);
176 static int proto_register_field_init(header_field_info *hfinfo, int parent);
178 /* Comparision function for tree insertion. A wrapper around strcmp() */
179 static int g_strcmp(gconstpointer a, gconstpointer b);
181 /* special-case header field used within proto.c */
182 int hf_text_only = -1;
184 /* Structure for information about a protocol */
186 const char *name; /* long description */
187 const char *short_name; /* short description */
188 const char *filter_name; /* name of this protocol in filters */
189 int proto_id; /* field ID for this protocol */
190 GList *fields; /* fields for this protocol */
191 GList *last_field; /* pointer to end of list of fields */
192 gboolean is_enabled; /* TRUE if protocol is enabled */
193 gboolean can_toggle; /* TRUE if is_enabled can be changed */
196 /* List of all protocols */
197 static GList *protocols = NULL;
199 #define INITIAL_NUM_PROTOCOL_HFINFO 200
202 /* Contains information about protocols and header fields. Used when
203 * dissectors register their data */
204 static GMemChunk *gmc_hfinfo = NULL;
206 /* Contains information about a field when a dissector calls
207 * proto_tree_add_item. */
208 SLAB_ITEM_TYPE_DEFINE(field_info)
209 static SLAB_FREE_LIST_DEFINE(field_info)
210 static field_info *field_info_tmp=NULL;
211 #define FIELD_INFO_NEW(fi) \
212 SLAB_ALLOC(fi, field_info)
213 #define FIELD_INFO_FREE(fi) \
214 SLAB_FREE(fi, field_info)
218 /* Contains the space for proto_nodes. */
219 SLAB_ITEM_TYPE_DEFINE(proto_node)
220 static SLAB_FREE_LIST_DEFINE(proto_node)
221 #define PROTO_NODE_NEW(node) \
222 SLAB_ALLOC(node, proto_node) \
223 node->first_child = NULL; \
224 node->last_child = NULL; \
227 #define PROTO_NODE_FREE(node) \
228 SLAB_FREE(node, proto_node)
232 /* String space for protocol and field items for the GUI */
233 SLAB_ITEM_TYPE_DEFINE(item_label_t)
234 static SLAB_FREE_LIST_DEFINE(item_label_t)
235 #define ITEM_LABEL_NEW(il) \
236 SLAB_ALLOC(il, item_label_t)
237 #define ITEM_LABEL_FREE(il) \
238 SLAB_FREE(il, item_label_t)
241 #define PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo) \
242 DISSECTOR_ASSERT((guint)hfindex < gpa_hfinfo.len); \
243 hfinfo=gpa_hfinfo.hfi[hfindex];
246 /* List which stores protocols and fields that have been registered */
247 typedef struct _gpa_hfinfo_t {
249 guint32 allocated_len;
250 header_field_info **hfi;
252 gpa_hfinfo_t gpa_hfinfo;
254 /* Balanced tree of abbreviations and IDs */
255 static GTree *gpa_name_tree = NULL;
257 /* Points to the first element of an array of Booleans, indexed by
258 a subtree item type; that array element is TRUE if subtrees of
259 an item of that type are to be expanded. */
260 gboolean *tree_is_expanded;
262 /* Number of elements in that array. */
265 /* Name hashtables for fast detection of duplicate names */
266 static GHashTable* proto_names = NULL;
267 static GHashTable* proto_short_names = NULL;
268 static GHashTable* proto_filter_names = NULL;
271 proto_compare_name(gconstpointer p1_arg, gconstpointer p2_arg)
273 const protocol_t *p1 = p1_arg;
274 const protocol_t *p2 = p2_arg;
276 return g_strcasecmp(p1->short_name, p2->short_name);
280 /* initialize data structures and register protocols and fields */
282 proto_init(const char *plugin_dir
287 void (register_all_protocols)(void),
288 void (register_all_protocol_handoffs)(void))
290 static hf_register_info hf[] = {
292 { "", "", FT_NONE, BASE_NONE, NULL, 0x0,
297 proto_names = g_hash_table_new(g_int_hash, g_int_equal);
298 proto_short_names = g_hash_table_new(g_int_hash, g_int_equal);
299 proto_filter_names = g_hash_table_new(g_int_hash, g_int_equal);
303 gmc_hfinfo = g_mem_chunk_new("gmc_hfinfo",
304 sizeof(header_field_info),
305 INITIAL_NUM_PROTOCOL_HFINFO * sizeof(header_field_info),
309 gpa_hfinfo.allocated_len=0;
311 gpa_name_tree = g_tree_new(g_strcmp);
313 /* Initialize the ftype subsystem */
316 /* Register one special-case FT_TEXT_ONLY field for use when
317 converting wireshark to new-style proto_tree. These fields
318 are merely strings on the GUI tree; they are not filterable */
319 proto_register_field_array(-1, hf, array_length(hf));
321 /* Have each built-in dissector register its protocols, fields,
322 dissector tables, and dissectors to be called through a
323 handle, and do whatever one-time initialization it needs to
325 register_all_protocols();
328 /* Now scan for plugins and load all the ones we find, calling
329 their register routines to do the stuff described above. */
330 init_plugins(plugin_dir);
333 /* Now call the "handoff registration" routines of all built-in
334 dissectors; those routines register the dissector in other
335 dissectors' handoff tables, and fetch any dissector handles
337 register_all_protocol_handoffs();
340 /* Now do the same with plugins. */
341 register_all_plugin_handoffs();
344 /* sort the protocols by protocol name */
345 protocols = g_list_sort(protocols, proto_compare_name);
347 /* We've assigned all the subtree type values; allocate the array
348 for them, and zero it out. */
349 tree_is_expanded = g_malloc(num_tree_types*sizeof (gboolean));
350 memset(tree_is_expanded, 0, num_tree_types*sizeof (gboolean));
353 /* String comparison func for dfilter_token GTree */
355 g_strcmp(gconstpointer a, gconstpointer b)
357 return strcmp((const char*)a, (const char*)b);
363 /* Free the abbrev/ID GTree */
365 g_tree_destroy(gpa_name_tree);
366 gpa_name_tree = NULL;
370 g_mem_chunk_destroy(gmc_hfinfo);
372 if(gpa_hfinfo.allocated_len){
374 gpa_hfinfo.allocated_len=0;
375 g_free(gpa_hfinfo.hfi);
378 if (tree_is_expanded != NULL)
379 g_free(tree_is_expanded);
383 typedef gboolean (*proto_tree_traverse_func)(proto_node *, gpointer);
386 proto_tree_traverse_pre_order(proto_tree *tree, proto_tree_traverse_func func,
389 proto_node *pnode = tree;
393 if (func(pnode, data))
396 child = pnode->first_child;
397 while (child != NULL) {
399 * The routine we call might modify the child, e.g. by
400 * freeing it, so we get the child's successor before
401 * calling that routine.
404 child = current->next;
405 if (proto_tree_traverse_pre_order((proto_tree *)current, func,
414 proto_tree_traverse_in_order(proto_tree *tree, proto_tree_traverse_func func,
417 proto_node *pnode = tree;
421 child = pnode->first_child;
424 * The routine we call might modify the child, e.g. by
425 * freeing it, so we get the child's successor before
426 * calling that routine.
429 child = current->next;
431 if (proto_tree_traverse_in_order((proto_tree *)current, func,
435 if (func(pnode, data))
438 while (child != NULL) {
440 * The routine we call might modify the child, e.g. by
441 * freeing it, so we get the child's successor before
442 * calling that routine.
445 child = current->next;
446 if (proto_tree_traverse_in_order((proto_tree *)current,
451 if (func(pnode, data))
459 proto_tree_children_foreach(proto_tree *tree, proto_tree_foreach_func func,
462 proto_node *node = tree;
465 node = node->first_child;
466 while (node != NULL) {
468 node = current->next;
469 func((proto_tree *)current, data);
473 /* frees the resources that the dissection a proto_tree uses */
475 proto_tree_free(proto_tree *tree)
477 proto_tree_traverse_in_order(tree, proto_tree_free_node, NULL);
481 free_GPtrArray_value(gpointer key _U_, gpointer value, gpointer user_data _U_)
483 GPtrArray *ptrs = value;
484 gint hfid = (gint)key;
485 header_field_info *hfinfo;
488 PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
489 if(hfinfo->ref_count){
490 /* when a field is referenced by a filter this also
491 affects the refcount for the parent protocol so we need
492 to adjust the refcount for the parent as well
494 if( (hfinfo->parent != -1) && (hfinfo->ref_count) ){
495 header_field_info *parent_hfinfo;
496 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
497 parent_hfinfo->ref_count -= hfinfo->ref_count;
499 hfinfo->ref_count = 0;
502 g_ptr_array_free(ptrs, TRUE);
506 free_node_tree_data(tree_data_t *tree_data)
508 /* Free all the GPtrArray's in the interesting_hfids hash. */
509 g_hash_table_foreach(tree_data->interesting_hfids,
510 free_GPtrArray_value, NULL);
512 /* And then destroy the hash. */
513 g_hash_table_destroy(tree_data->interesting_hfids);
515 /* And finally the tree_data_t itself. */
519 #define FREE_NODE_FIELD_INFO(finfo) \
521 ITEM_LABEL_FREE(finfo->rep); \
523 FVALUE_CLEANUP(&finfo->value); \
524 FIELD_INFO_FREE(finfo);
527 proto_tree_free_node(proto_node *node, gpointer data _U_)
529 field_info *finfo = PITEM_FINFO(node);
532 /* This is the root node. Destroy the per-tree data.
533 * There is no field_info to destroy. */
534 free_node_tree_data(PTREE_DATA(node));
537 /* This is a child node. Don't free the per-tree data, but
538 * do free the field_info data. */
539 FREE_NODE_FIELD_INFO(finfo);
542 /* Free the proto_node. */
543 PROTO_NODE_FREE(node);
545 return FALSE; /* FALSE = do not end traversal of protocol tree */
548 /* Is the parsing being done for a visible proto_tree or an invisible one?
549 * By setting this correctly, the proto_tree creation is sped up by not
550 * having to call g_vsnprintf and copy strings around.
553 proto_tree_set_visible(proto_tree *tree, gboolean visible)
555 PTREE_DATA(tree)->visible = visible;
558 /* Assume dissector set only its protocol fields.
559 This function is called by dissectors and allowes to speed up filtering
560 in wireshark, if this function returns FALSE it is safe to reset tree to NULL
561 and thus skip calling most of the expensive proto_tree_add_...()
563 If the tree is visible we implicitely assume the field is referenced.
566 proto_field_is_referenced(proto_tree *tree, int proto_id)
568 register header_field_info *hfinfo;
574 if (PTREE_DATA(tree)->visible)
577 PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
578 if (hfinfo->ref_count != 0)
585 /* Finds a record in the hf_info_records array by id. */
587 proto_registrar_get_nth(guint hfindex)
589 register header_field_info *hfinfo;
591 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
595 /* Finds a record in the hf_info_records array by name.
598 proto_registrar_get_byname(const char *field_name)
600 DISSECTOR_ASSERT(field_name != NULL);
601 return g_tree_lookup(gpa_name_tree, field_name);
604 /* Allocates an initializes a ptvcursor_t with 3 variables:
605 * proto_tree, tvbuff, and offset. */
607 ptvcursor_new(proto_tree *tree, tvbuff_t *tvb, gint offset)
611 ptvc = g_new(ptvcursor_t, 1);
614 ptvc->offset = offset;
618 /* Frees memory for ptvcursor_t, but nothing deeper than that. */
620 ptvcursor_free(ptvcursor_t *ptvc)
625 /* Returns tvbuff. */
627 ptvcursor_tvbuff(ptvcursor_t* ptvc)
632 /* Returns current offset. */
634 ptvcursor_current_offset(ptvcursor_t* ptvc)
640 ptvcursor_tree(ptvcursor_t* ptvc)
646 ptvcursor_set_tree(ptvcursor_t* ptvc, proto_tree *tree)
651 /* Add a text-only node, leaving it to our caller to fill the text in */
653 proto_tree_add_text_node(proto_tree *tree, tvbuff_t *tvb, gint start, gint length)
657 pi = proto_tree_add_pi(tree, hf_text_only, tvb, start, &length, NULL);
664 /* Add a text-only node to the proto_tree */
666 proto_tree_add_text(proto_tree *tree, tvbuff_t *tvb, gint start, gint length,
667 const char *format, ...)
672 pi = proto_tree_add_text_node(tree, tvb, start, length);
676 va_start(ap, format);
677 proto_tree_set_representation(pi, format, ap);
683 /* Add a text-only node to the proto_tree (va_list version) */
685 proto_tree_add_text_valist(proto_tree *tree, tvbuff_t *tvb, gint start,
686 gint length, const char *format, va_list ap)
690 pi = proto_tree_add_text_node(tree, tvb, start, length);
694 proto_tree_set_representation(pi, format, ap);
699 /* Add a text-only node for debugging purposes. The caller doesn't need
700 * to worry about tvbuff, start, or length. Debug message gets sent to
703 proto_tree_add_debug_text(proto_tree *tree, const char *format, ...)
708 pi = proto_tree_add_text_node(tree, NULL, 0, 0);
712 va_start(ap, format);
713 proto_tree_set_representation(pi, format, ap);
723 get_uint_value(tvbuff_t *tvb, gint offset, gint length, gboolean little_endian)
730 value = tvb_get_guint8(tvb, offset);
734 value = little_endian ? tvb_get_letohs(tvb, offset)
735 : tvb_get_ntohs(tvb, offset);
739 value = little_endian ? tvb_get_letoh24(tvb, offset)
740 : tvb_get_ntoh24(tvb, offset);
744 value = little_endian ? tvb_get_letohl(tvb, offset)
745 : tvb_get_ntohl(tvb, offset);
749 THROW(ReportedBoundsError);
757 get_int_value(tvbuff_t *tvb, gint offset, gint length, gboolean little_endian)
764 value = (gint8)tvb_get_guint8(tvb, offset);
768 value = (gint16) (little_endian ? tvb_get_letohs(tvb, offset)
769 : tvb_get_ntohs(tvb, offset));
773 value = little_endian ? tvb_get_letoh24(tvb, offset)
774 : tvb_get_ntoh24(tvb, offset);
775 if (value & 0x00800000) {
776 /* Sign bit is set; sign-extend it. */
782 value = little_endian ? tvb_get_letohl(tvb, offset)
783 : tvb_get_ntohl(tvb, offset);
787 THROW(ReportedBoundsError);
794 /* Add an item to a proto_tree, using the text label registered to that item;
795 the item is extracted from the tvbuff handed to it. */
797 proto_tree_new_item(field_info *new_fi, proto_tree *tree, int hfindex,
798 tvbuff_t *tvb, gint start, gint length, gboolean little_endian)
808 /* there is a possibility here that we might raise an exception
809 * and thus would lose track of the field_info.
810 * store it in a temp so that if we come here again we can reclaim
811 * the field_info without leaking memory.
813 /* XXX this only keeps track of one field_info struct,
814 if we ever go multithreaded for calls to this function
815 we have to change this code to use per thread variable.
818 /* oops, last one we got must have been lost due
820 * good thing we saved it, now we can reverse the
821 * memory leak and reclaim it.
823 SLAB_FREE(field_info_tmp, field_info);
825 /* we might throw an exception, keep track of this one
826 * across the "dangerous" section below.
828 field_info_tmp=new_fi;
830 switch(new_fi->hfinfo->type) {
832 /* no value to set for FT_NONE */
836 proto_tree_set_protocol_tvb(new_fi, tvb);
840 proto_tree_set_bytes_tvb(new_fi, tvb, start, length);
844 n = get_uint_value(tvb, start, length, little_endian);
845 proto_tree_set_bytes_tvb(new_fi, tvb, start + length, n);
847 /* Instead of calling proto_item_set_len(), since we don't yet
848 * have a proto_item, we set the field_info's length ourselves. */
849 new_fi->length = n + length;
853 proto_tree_set_boolean(new_fi,
854 get_uint_value(tvb, start, length, little_endian));
857 /* XXX - make these just FT_UINT? */
862 proto_tree_set_uint(new_fi,
863 get_uint_value(tvb, start, length, little_endian));
868 DISSECTOR_ASSERT(length == 8);
869 proto_tree_set_uint64_tvb(new_fi, tvb, start, little_endian);
872 /* XXX - make these just FT_INT? */
877 proto_tree_set_int(new_fi,
878 get_int_value(tvb, start, length, little_endian));
882 DISSECTOR_ASSERT(length == 4);
883 value = tvb_get_ipv4(tvb, start);
884 proto_tree_set_ipv4(new_fi, little_endian ? GUINT32_SWAP_LE_BE(value) : value);
888 DISSECTOR_ASSERT(length == 4);
889 proto_tree_set_ipxnet(new_fi,
890 get_uint_value(tvb, start, 4, FALSE));
894 DISSECTOR_ASSERT(length == 16);
895 proto_tree_set_ipv6_tvb(new_fi, tvb, start);
899 DISSECTOR_ASSERT(length == 6);
900 proto_tree_set_ether_tvb(new_fi, tvb, start);
904 DISSECTOR_ASSERT(length == 16);
905 proto_tree_set_guid_tvb(new_fi, tvb, start, little_endian);
909 proto_tree_set_oid_tvb(new_fi, tvb, start, length);
913 DISSECTOR_ASSERT(length == 4);
915 floatval = tvb_get_letohieee_float(tvb, start);
917 floatval = tvb_get_ntohieee_float(tvb, start);
918 proto_tree_set_float(new_fi, floatval);
922 DISSECTOR_ASSERT(length == 8);
924 doubleval = tvb_get_letohieee_double(tvb, start);
926 doubleval = tvb_get_ntohieee_double(tvb, start);
927 proto_tree_set_double(new_fi, doubleval);
931 /* This g_strdup'ed memory is freed in proto_tree_free_node() */
932 proto_tree_set_string_tvb(new_fi, tvb, start, length);
936 DISSECTOR_ASSERT(length >= -1);
937 /* Instead of calling proto_item_set_len(),
938 * since we don't yet have a proto_item, we
939 * set the field_info's length ourselves.
941 * XXX - our caller can't use that length to
942 * advance an offset unless they arrange that
943 * there always be a protocol tree into which
944 * we're putting this item.
947 /* This can throw an exception */
948 length = tvb_strsize(tvb, start);
950 /* This g_malloc'ed memory is freed
951 in proto_tree_free_node() */
952 string = g_malloc(length);
954 tvb_memcpy(tvb, string, start, length);
955 } else if (length == 0) {
956 string = g_strdup("[Empty]");
958 /* In this case, length signifies
959 * the length of the string.
961 * This could either be a null-padded
962 * string, which doesn't necessarily
963 * have a '\0' at the end, or a
964 * null-terminated string, with a
965 * trailing '\0'. (Yes, there are
966 * cases where you have a string
967 * that's both counted and null-
970 * In the first case, we must
971 * allocate a buffer of length
972 * "length+1", to make room for
975 * In the second case, we don't
976 * assume that there is a trailing
977 * '\0' there, as the packet might
978 * be malformed. (XXX - should we
979 * throw an exception if there's no
980 * trailing '\0'?) Therefore, we
981 * allocate a buffer of length
982 * "length+1", and put in a trailing
983 * '\0', just to be safe.
985 * (XXX - this would change if
986 * we made string values counted
987 * rather than null-terminated.)
990 /* This g_malloc'ed memory is freed
991 * in proto_tree_free_node() */
992 string = tvb_get_string(tvb, start,
995 new_fi->length = length;
996 proto_tree_set_string(new_fi, string, TRUE);
1000 /* This g_strdup'ed memory is freed in proto_tree_free_node() */
1001 n = get_uint_value(tvb, start, length, little_endian);
1002 proto_tree_set_string_tvb(new_fi, tvb, start + length, n);
1004 /* Instead of calling proto_item_set_len(), since we
1005 * don't yet have a proto_item, we set the
1006 * field_info's length ourselves.
1008 * XXX - our caller can't use that length to
1009 * advance an offset unless they arrange that
1010 * there always be a protocol tree into which
1011 * we're putting this item.
1013 new_fi->length = n + length;
1017 g_error("new_fi->hfinfo->type %d (%s) not handled\n",
1018 new_fi->hfinfo->type,
1019 ftype_name(new_fi->hfinfo->type));
1020 DISSECTOR_ASSERT_NOT_REACHED();
1024 /* Don't add new node to proto_tree until now so that any exceptions
1025 * raised by a tvbuff access method doesn't leave junk in the proto_tree. */
1026 pi = proto_tree_add_node(tree, new_fi);
1028 /* we did not raise an exception so we dont have to remember this
1029 * field_info struct any more.
1031 field_info_tmp=NULL;
1033 /* If the proto_tree wants to keep a record of this finfo
1034 * for quick lookup, then record it. */
1035 if (new_fi->hfinfo->ref_count) {
1037 hash = PTREE_DATA(tree)->interesting_hfids;
1038 ptrs = g_hash_table_lookup(hash, GINT_TO_POINTER(hfindex));
1040 g_ptr_array_add(ptrs, new_fi);
1047 /* Gets data from tvbuff, adds it to proto_tree, increments offset,
1048 and returns proto_item* */
1050 ptvcursor_add(ptvcursor_t *ptvc, int hfindex, gint length,
1051 gboolean little_endian)
1054 header_field_info *hfinfo;
1059 offset = ptvc->offset;
1060 hfinfo = get_hfi_and_length(hfindex, ptvc->tvb, offset, &length,
1062 ptvc->offset += length;
1063 if (hfinfo->type == FT_UINT_BYTES || hfinfo->type == FT_UINT_STRING) {
1065 * The length of the rest of the item is in the first N
1066 * bytes of the item.
1068 n = get_uint_value(ptvc->tvb, offset, length, little_endian);
1071 if (ptvc->tree == NULL)
1074 TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfindex);
1076 new_fi = new_field_info(ptvc->tree, hfinfo, ptvc->tvb, offset,
1081 return proto_tree_new_item(new_fi, ptvc->tree, hfindex, ptvc->tvb,
1082 offset, length, little_endian);
1085 /* Add an item to a proto_tree, using the text label registered to that item;
1086 the item is extracted from the tvbuff handed to it. */
1088 proto_tree_add_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1089 gint start, gint length, gboolean little_endian)
1096 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1098 new_fi = alloc_field_info(tree, hfindex, tvb, start, &length);
1103 return proto_tree_new_item(new_fi, tree, hfindex, tvb, start,
1104 length, little_endian);
1108 proto_tree_add_item_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1109 gint start, gint length, gboolean little_endian)
1113 pi = proto_tree_add_item(tree, hfindex, tvb, start, length, little_endian);
1117 PROTO_ITEM_SET_HIDDEN(pi);
1123 /* Add a FT_NONE to a proto_tree */
1125 proto_tree_add_none_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1126 gint length, const char *format, ...)
1130 header_field_info *hfinfo;
1135 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1136 DISSECTOR_ASSERT(hfinfo->type == FT_NONE);
1138 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, NULL);
1140 va_start(ap, format);
1141 proto_tree_set_representation(pi, format, ap);
1144 /* no value to set for FT_NONE */
1148 /* Gets data from tvbuff, adds it to proto_tree, *DOES NOT* increment
1149 * offset, and returns proto_item* */
1151 ptvcursor_add_no_advance(ptvcursor_t* ptvc, int hf, gint length,
1152 gboolean endianness)
1156 item = proto_tree_add_item(ptvc->tree, hf, ptvc->tvb, ptvc->offset,
1157 length, endianness);
1162 /* Advance the ptvcursor's offset within its tvbuff without
1163 * adding anything to the proto_tree. */
1165 ptvcursor_advance(ptvcursor_t* ptvc, gint length)
1167 ptvc->offset += length;
1172 proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb)
1174 fvalue_set(&fi->value, tvb, TRUE);
1177 /* Add a FT_PROTOCOL to a proto_tree */
1179 proto_tree_add_protocol_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1180 gint length, const char *format, ...)
1184 header_field_info *hfinfo;
1190 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1191 DISSECTOR_ASSERT(hfinfo->type == FT_PROTOCOL);
1193 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1195 va_start(ap, format);
1196 proto_tree_set_representation(pi, format, ap);
1200 proto_tree_set_protocol_tvb(new_fi, tvb);
1203 proto_tree_set_protocol_tvb(new_fi, NULL);
1209 /* Add a FT_BYTES to a proto_tree */
1211 proto_tree_add_bytes(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1212 gint length, const guint8 *start_ptr)
1216 header_field_info *hfinfo;
1221 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1223 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1224 DISSECTOR_ASSERT(hfinfo->type == FT_BYTES);
1226 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1227 proto_tree_set_bytes(new_fi, start_ptr, length);
1233 proto_tree_add_bytes_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1234 gint length, const guint8 *start_ptr)
1238 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length, start_ptr);
1242 PROTO_ITEM_SET_HIDDEN(pi);
1248 proto_tree_add_bytes_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1249 gint start, gint length, const guint8 *start_ptr,
1250 const char *format, ...)
1255 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length, start_ptr);
1259 va_start(ap, format);
1260 proto_tree_set_representation_value(pi, format, ap);
1267 proto_tree_add_bytes_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1268 gint length, const guint8 *start_ptr, const char *format, ...)
1273 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length, start_ptr);
1277 va_start(ap, format);
1278 proto_tree_set_representation(pi, format, ap);
1285 proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length)
1289 bytes = g_byte_array_new();
1291 g_byte_array_append(bytes, start_ptr, length);
1293 fvalue_set(&fi->value, bytes, TRUE);
1298 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length)
1300 proto_tree_set_bytes(fi, tvb_get_ptr(tvb, offset, length), length);
1303 /* Add a FT_*TIME to a proto_tree */
1305 proto_tree_add_time(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1306 nstime_t *value_ptr)
1310 header_field_info *hfinfo;
1315 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1317 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1318 DISSECTOR_ASSERT(hfinfo->type == FT_ABSOLUTE_TIME ||
1319 hfinfo->type == FT_RELATIVE_TIME);
1321 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1322 proto_tree_set_time(new_fi, value_ptr);
1328 proto_tree_add_time_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1329 nstime_t *value_ptr)
1333 pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
1337 PROTO_ITEM_SET_HIDDEN(pi);
1343 proto_tree_add_time_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1344 gint start, gint length, nstime_t *value_ptr,
1345 const char *format, ...)
1350 pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
1354 va_start(ap, format);
1355 proto_tree_set_representation_value(pi, format, ap);
1362 proto_tree_add_time_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1363 nstime_t *value_ptr, const char *format, ...)
1368 pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
1372 va_start(ap, format);
1373 proto_tree_set_representation(pi, format, ap);
1379 /* Set the FT_*TIME value */
1381 proto_tree_set_time(field_info *fi, nstime_t *value_ptr)
1383 DISSECTOR_ASSERT(value_ptr != NULL);
1384 fvalue_set(&fi->value, value_ptr, FALSE);
1387 /* Add a FT_IPXNET to a proto_tree */
1389 proto_tree_add_ipxnet(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1394 header_field_info *hfinfo;
1399 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1401 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1402 DISSECTOR_ASSERT(hfinfo->type == FT_IPXNET);
1404 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1405 proto_tree_set_ipxnet(new_fi, value);
1411 proto_tree_add_ipxnet_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1416 pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
1420 PROTO_ITEM_SET_HIDDEN(pi);
1426 proto_tree_add_ipxnet_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1427 gint start, gint length, guint32 value, const char *format, ...)
1432 pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
1436 va_start(ap, format);
1437 proto_tree_set_representation_value(pi, format, ap);
1444 proto_tree_add_ipxnet_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1445 guint32 value, const char *format, ...)
1450 pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
1454 va_start(ap, format);
1455 proto_tree_set_representation(pi, format, ap);
1461 /* Set the FT_IPXNET value */
1463 proto_tree_set_ipxnet(field_info *fi, guint32 value)
1465 fvalue_set_integer(&fi->value, value);
1468 /* Add a FT_IPv4 to a proto_tree */
1470 proto_tree_add_ipv4(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1475 header_field_info *hfinfo;
1480 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1482 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1483 DISSECTOR_ASSERT(hfinfo->type == FT_IPv4);
1485 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1486 proto_tree_set_ipv4(new_fi, value);
1492 proto_tree_add_ipv4_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1497 pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
1501 PROTO_ITEM_SET_HIDDEN(pi);
1507 proto_tree_add_ipv4_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1508 gint start, gint length, guint32 value, const char *format, ...)
1513 pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
1517 va_start(ap, format);
1518 proto_tree_set_representation_value(pi, format, ap);
1525 proto_tree_add_ipv4_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1526 guint32 value, const char *format, ...)
1531 pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
1535 va_start(ap, format);
1536 proto_tree_set_representation(pi, format, ap);
1542 /* Set the FT_IPv4 value */
1544 proto_tree_set_ipv4(field_info *fi, guint32 value)
1546 fvalue_set_integer(&fi->value, value);
1549 /* Add a FT_IPv6 to a proto_tree */
1551 proto_tree_add_ipv6(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1552 const guint8* value_ptr)
1556 header_field_info *hfinfo;
1561 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1563 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1564 DISSECTOR_ASSERT(hfinfo->type == FT_IPv6);
1566 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1567 proto_tree_set_ipv6(new_fi, value_ptr);
1573 proto_tree_add_ipv6_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1574 const guint8* value_ptr)
1578 pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
1582 PROTO_ITEM_SET_HIDDEN(pi);
1588 proto_tree_add_ipv6_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1589 gint start, gint length, const guint8* value_ptr,
1590 const char *format, ...)
1595 pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
1599 va_start(ap, format);
1600 proto_tree_set_representation_value(pi, format, ap);
1607 proto_tree_add_ipv6_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1608 const guint8* value_ptr, const char *format, ...)
1613 pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
1617 va_start(ap, format);
1618 proto_tree_set_representation(pi, format, ap);
1624 /* Set the FT_IPv6 value */
1626 proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr)
1628 DISSECTOR_ASSERT(value_ptr != NULL);
1629 fvalue_set(&fi->value, (gpointer) value_ptr, FALSE);
1633 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start)
1635 proto_tree_set_ipv6(fi, tvb_get_ptr(tvb, start, 16));
1638 /* Add a FT_GUID to a proto_tree */
1640 proto_tree_add_guid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1641 const e_guid_t *value_ptr)
1645 header_field_info *hfinfo;
1650 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1652 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1653 DISSECTOR_ASSERT(hfinfo->type == FT_GUID);
1655 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1656 proto_tree_set_guid(new_fi, value_ptr);
1662 proto_tree_add_guid_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1663 const e_guid_t *value_ptr)
1667 pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
1671 PROTO_ITEM_SET_HIDDEN(pi);
1677 proto_tree_add_guid_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1678 gint start, gint length, const e_guid_t *value_ptr,
1679 const char *format, ...)
1684 pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
1688 va_start(ap, format);
1689 proto_tree_set_representation_value(pi, format, ap);
1696 proto_tree_add_guid_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1697 const e_guid_t *value_ptr, const char *format, ...)
1702 pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
1706 va_start(ap, format);
1707 proto_tree_set_representation(pi, format, ap);
1713 /* Set the FT_GUID value */
1715 proto_tree_set_guid(field_info *fi, const e_guid_t *value_ptr)
1717 DISSECTOR_ASSERT(value_ptr != NULL);
1718 fvalue_set(&fi->value, (gpointer) value_ptr, FALSE);
1722 proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gboolean little_endian)
1726 tvb_get_guid(tvb, start, &guid, little_endian);
1727 proto_tree_set_guid(fi, &guid);
1730 /* Add a FT_OID to a proto_tree */
1732 proto_tree_add_oid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1733 const guint8* value_ptr)
1737 header_field_info *hfinfo;
1742 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1744 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1745 DISSECTOR_ASSERT(hfinfo->type == FT_OID);
1747 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1748 proto_tree_set_oid(new_fi, value_ptr, length);
1754 proto_tree_add_oid_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1755 const guint8* value_ptr)
1759 pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
1763 PROTO_ITEM_SET_HIDDEN(pi);
1769 proto_tree_add_oid_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1770 gint start, gint length, const guint8* value_ptr,
1771 const char *format, ...)
1776 pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
1780 va_start(ap, format);
1781 proto_tree_set_representation_value(pi, format, ap);
1788 proto_tree_add_oid_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1789 const guint8* value_ptr, const char *format, ...)
1794 pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
1798 va_start(ap, format);
1799 proto_tree_set_representation(pi, format, ap);
1805 /* Set the FT_OID value */
1807 proto_tree_set_oid(field_info *fi, const guint8* value_ptr, gint length)
1811 DISSECTOR_ASSERT(value_ptr != NULL);
1813 bytes = g_byte_array_new();
1815 g_byte_array_append(bytes, value_ptr, length);
1817 fvalue_set(&fi->value, bytes, TRUE);
1821 proto_tree_set_oid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
1823 proto_tree_set_oid(fi, tvb_get_ptr(tvb, start, length), length);
1827 proto_tree_set_uint64(field_info *fi, guint64 value)
1829 fvalue_set_integer64(&fi->value, value);
1833 proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start, gboolean little_endian)
1837 value = little_endian ? tvb_get_letoh64(tvb, start)
1838 : tvb_get_ntoh64(tvb, start);
1840 proto_tree_set_uint64(fi, value);
1843 /* Add a FT_STRING or FT_STRINGZ to a proto_tree. Creates own copy of string,
1844 * and frees it when the proto_tree is destroyed. */
1846 proto_tree_add_string(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1847 gint length, const char* value)
1851 header_field_info *hfinfo;
1856 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1858 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1859 DISSECTOR_ASSERT(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ);
1861 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1862 DISSECTOR_ASSERT(length >= 0);
1863 proto_tree_set_string(new_fi, value, FALSE);
1869 proto_tree_add_string_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1870 gint length, const char* value)
1874 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
1878 PROTO_ITEM_SET_HIDDEN(pi);
1884 proto_tree_add_string_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1885 gint start, gint length, const char* value, const char *format,
1891 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
1895 va_start(ap, format);
1896 proto_tree_set_representation_value(pi, format, ap);
1903 proto_tree_add_string_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1904 gint length, const char* value, const char *format, ...)
1909 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
1913 va_start(ap, format);
1914 proto_tree_set_representation(pi, format, ap);
1920 /* Appends string data to a FT_STRING or FT_STRINGZ, allowing progressive
1921 * field info update instead of only updating the representation as does
1922 * proto_item_append_text()
1924 /* NOTE: this function will break with the TRY_TO_FAKE_THIS_ITEM()
1925 * speed optimization.
1926 * Currently only WSP use this function so it is not that bad but try to
1927 * avoid using this one if possible.
1928 * IF you must use this function you MUST also disable the
1929 * TRY_TO_FAKE_THIS_ITEM() optimization for your dissector/function
1930 * using proto_item_append_string().
1931 * Do that by faking that the tree is visible by setting :
1932 * PTREE_DATA(tree)->visible=1; (see packet-wsp.c)
1933 * BEFORE you create the item you are later going to use
1934 * proto_item_append_string() on.
1937 proto_item_append_string(proto_item *pi, const char *str)
1940 header_field_info *hfinfo;
1941 gchar *old_str, *new_str;
1948 fi = PITEM_FINFO(pi);
1949 hfinfo = fi->hfinfo;
1950 if (hfinfo->type == FT_PROTOCOL) {
1951 /* TRY_TO_FAKE_THIS_ITEM() speed optimization: silently skip */
1954 DISSECTOR_ASSERT(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ);
1955 old_str = fvalue_get(&fi->value);
1956 new_str = g_strdup_printf("%s%s", old_str, str);
1957 fvalue_set(&fi->value, new_str, TRUE);
1960 /* Set the FT_STRING value */
1962 proto_tree_set_string(field_info *fi, const char* value,
1963 gboolean already_allocated)
1966 fvalue_set(&fi->value, (gpointer) value, already_allocated);
1968 fvalue_set(&fi->value, (gpointer) "[ Null ]", already_allocated);
1972 proto_tree_set_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
1977 length = tvb_ensure_length_remaining(tvb, start);
1980 /* This memory is freed in proto_tree_free_node() */
1981 string = tvb_get_string(tvb, start, length);
1982 proto_tree_set_string(fi, string, TRUE);
1985 /* Add a FT_ETHER to a proto_tree */
1987 proto_tree_add_ether(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1988 const guint8* value)
1992 header_field_info *hfinfo;
1997 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1999 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2000 DISSECTOR_ASSERT(hfinfo->type == FT_ETHER);
2002 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2003 proto_tree_set_ether(new_fi, value);
2009 proto_tree_add_ether_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2010 const guint8* value)
2014 pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
2018 PROTO_ITEM_SET_HIDDEN(pi);
2024 proto_tree_add_ether_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2025 gint start, gint length, const guint8* value,
2026 const char *format, ...)
2031 pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
2035 va_start(ap, format);
2036 proto_tree_set_representation_value(pi, format, ap);
2043 proto_tree_add_ether_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2044 const guint8* value, const char *format, ...)
2049 pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
2053 va_start(ap, format);
2054 proto_tree_set_representation(pi, format, ap);
2060 /* Set the FT_ETHER value */
2062 proto_tree_set_ether(field_info *fi, const guint8* value)
2064 fvalue_set(&fi->value, (gpointer) value, FALSE);
2068 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start)
2070 proto_tree_set_ether(fi, tvb_get_ptr(tvb, start, 6));
2073 /* Add a FT_BOOLEAN to a proto_tree */
2075 proto_tree_add_boolean(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2080 header_field_info *hfinfo;
2085 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
2087 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2088 DISSECTOR_ASSERT(hfinfo->type == FT_BOOLEAN);
2090 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2091 proto_tree_set_boolean(new_fi, value);
2097 proto_tree_add_boolean_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2102 pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
2106 PROTO_ITEM_SET_HIDDEN(pi);
2112 proto_tree_add_boolean_format_value(proto_tree *tree, int hfindex,
2113 tvbuff_t *tvb, gint start, gint length, guint32 value,
2114 const char *format, ...)
2119 pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
2123 va_start(ap, format);
2124 proto_tree_set_representation_value(pi, format, ap);
2131 proto_tree_add_boolean_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2132 guint32 value, const char *format, ...)
2137 pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
2141 va_start(ap, format);
2142 proto_tree_set_representation(pi, format, ap);
2148 /* Set the FT_BOOLEAN value */
2150 proto_tree_set_boolean(field_info *fi, guint32 value)
2152 proto_tree_set_uint(fi, value);
2155 /* Add a FT_FLOAT to a proto_tree */
2157 proto_tree_add_float(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2162 header_field_info *hfinfo;
2167 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
2169 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2170 DISSECTOR_ASSERT(hfinfo->type == FT_FLOAT);
2172 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2173 proto_tree_set_float(new_fi, value);
2179 proto_tree_add_float_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2184 pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
2188 PROTO_ITEM_SET_HIDDEN(pi);
2194 proto_tree_add_float_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2195 gint start, gint length, float value, const char *format, ...)
2200 pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
2204 va_start(ap, format);
2205 proto_tree_set_representation_value(pi, format, ap);
2212 proto_tree_add_float_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2213 float value, const char *format, ...)
2218 pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
2222 va_start(ap, format);
2223 proto_tree_set_representation(pi, format, ap);
2229 /* Set the FT_FLOAT value */
2231 proto_tree_set_float(field_info *fi, float value)
2233 fvalue_set_floating(&fi->value, value);
2236 /* Add a FT_DOUBLE to a proto_tree */
2238 proto_tree_add_double(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2243 header_field_info *hfinfo;
2248 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
2250 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2251 DISSECTOR_ASSERT(hfinfo->type == FT_DOUBLE);
2253 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2254 proto_tree_set_double(new_fi, value);
2260 proto_tree_add_double_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2265 pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
2269 PROTO_ITEM_SET_HIDDEN(pi);
2275 proto_tree_add_double_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2276 gint start, gint length, double value, const char *format, ...)
2281 pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
2285 va_start(ap, format);
2286 proto_tree_set_representation_value(pi, format, ap);
2293 proto_tree_add_double_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2294 double value, const char *format, ...)
2299 pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
2303 va_start(ap, format);
2304 proto_tree_set_representation(pi, format, ap);
2310 /* Set the FT_DOUBLE value */
2312 proto_tree_set_double(field_info *fi, double value)
2314 fvalue_set_floating(&fi->value, value);
2317 /* Add FT_UINT{8,16,24,32} to a proto_tree */
2319 proto_tree_add_uint(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2322 proto_item *pi = NULL;
2324 header_field_info *hfinfo;
2329 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
2331 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2332 switch(hfinfo->type) {
2338 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length,
2340 proto_tree_set_uint(new_fi, value);
2344 DISSECTOR_ASSERT_NOT_REACHED();
2351 proto_tree_add_uint_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2356 pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
2360 PROTO_ITEM_SET_HIDDEN(pi);
2366 proto_tree_add_uint_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2367 gint start, gint length, guint32 value, const char *format, ...)
2372 pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
2376 va_start(ap, format);
2377 proto_tree_set_representation_value(pi, format, ap);
2384 proto_tree_add_uint_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2385 guint32 value, const char *format, ...)
2390 pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
2394 va_start(ap, format);
2395 proto_tree_set_representation(pi, format, ap);
2401 /* Set the FT_UINT{8,16,24,32} value */
2403 proto_tree_set_uint(field_info *fi, guint32 value)
2405 header_field_info *hfinfo;
2408 hfinfo = fi->hfinfo;
2411 if (hfinfo->bitmask) {
2412 /* Mask out irrelevant portions */
2413 integer &= hfinfo->bitmask;
2416 if (hfinfo->bitshift > 0) {
2417 integer >>= hfinfo->bitshift;
2420 fvalue_set_integer(&fi->value, integer);
2423 /* Add FT_UINT64 to a proto_tree */
2425 proto_tree_add_uint64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2428 proto_item *pi = NULL;
2430 header_field_info *hfinfo;
2435 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
2437 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2438 DISSECTOR_ASSERT(hfinfo->type == FT_UINT64);
2440 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2441 proto_tree_set_uint64(new_fi, value);
2447 proto_tree_add_uint64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2448 gint start, gint length, guint64 value, const char *format, ...)
2453 pi = proto_tree_add_uint64(tree, hfindex, tvb, start, length, value);
2457 va_start(ap, format);
2458 proto_tree_set_representation_value(pi, format, ap);
2465 proto_tree_add_uint64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2466 guint64 value, const char *format, ...)
2471 pi = proto_tree_add_uint64(tree, hfindex, tvb, start, length, value);
2475 va_start(ap, format);
2476 proto_tree_set_representation(pi, format, ap);
2482 /* Add FT_INT{8,16,24,32} to a proto_tree */
2484 proto_tree_add_int(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2487 proto_item *pi = NULL;
2489 header_field_info *hfinfo;
2494 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
2496 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2497 switch(hfinfo->type) {
2502 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length,
2504 proto_tree_set_int(new_fi, value);
2508 DISSECTOR_ASSERT_NOT_REACHED();
2515 proto_tree_add_int_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2520 pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
2524 PROTO_ITEM_SET_HIDDEN(pi);
2530 proto_tree_add_int_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2531 gint start, gint length, gint32 value, const char *format, ...)
2533 proto_item *pi = NULL;
2536 pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
2540 va_start(ap, format);
2541 proto_tree_set_representation_value(pi, format, ap);
2548 proto_tree_add_int_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2549 gint32 value, const char *format, ...)
2551 proto_item *pi = NULL;
2554 pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
2558 va_start(ap, format);
2559 proto_tree_set_representation(pi, format, ap);
2565 /* Set the FT_INT{8,16,24,32} value */
2567 proto_tree_set_int(field_info *fi, gint32 value)
2569 header_field_info *hfinfo;
2572 hfinfo = fi->hfinfo;
2573 integer = (guint32) value;
2575 if (hfinfo->bitmask) {
2576 /* Mask out irrelevant portions */
2577 integer &= hfinfo->bitmask;
2580 if (hfinfo->bitshift > 0) {
2581 integer >>= hfinfo->bitshift;
2584 fvalue_set_integer(&fi->value, integer);
2587 /* Add FT_INT64 to a proto_tree */
2589 proto_tree_add_int64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2592 proto_item *pi = NULL;
2594 header_field_info *hfinfo;
2599 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
2601 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2602 DISSECTOR_ASSERT(hfinfo->type == FT_INT64);
2604 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2605 proto_tree_set_uint64(new_fi, (guint64)value);
2611 proto_tree_add_int64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2612 gint start, gint length, gint64 value, const char *format, ...)
2617 pi = proto_tree_add_int64(tree, hfindex, tvb, start, length, value);
2621 va_start(ap, format);
2622 proto_tree_set_representation_value(pi, format, ap);
2629 proto_tree_add_int64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2630 gint64 value, const char *format, ...)
2635 pi = proto_tree_add_int64(tree, hfindex, tvb, start, length, value);
2639 va_start(ap, format);
2640 proto_tree_set_representation(pi, format, ap);
2646 /* Throw an exception if we exceed this many tree items. */
2647 /* XXX - This should probably be a preference */
2648 #define MAX_TREE_ITEMS (1 * 1000 * 1000)
2649 /* Add a field_info struct to the proto_tree, encapsulating it in a proto_node */
2651 proto_tree_add_node(proto_tree *tree, field_info *fi)
2653 proto_node *pnode, *tnode, *sibling;
2657 * Make sure "tree" is ready to have subtrees under it, by
2658 * checking whether it's been given an ett_ value.
2660 * "tnode->finfo" may be null; that's the case for the root
2661 * node of the protocol tree. That node is not displayed,
2662 * so it doesn't need an ett_ value to remember whether it
2667 if (tfi != NULL && (tfi->tree_type < 0 || tfi->tree_type >= num_tree_types)) {
2668 REPORT_DISSECTOR_BUG(ep_strdup_printf("\"%s\" - \"%s\" tfi->tree_type: %u invalid (%s:%u)",
2669 fi->hfinfo->name, fi->hfinfo->abbrev, tfi->tree_type, __FILE__, __LINE__));
2670 /* XXX - is it safe to continue here? */
2673 DISSECTOR_ASSERT(tfi == NULL ||
2674 (tfi->tree_type >= 0 && tfi->tree_type < num_tree_types));
2676 PTREE_DATA(tree)->count++;
2677 if (PTREE_DATA(tree)->count > MAX_TREE_ITEMS) {
2678 /* Let the exception handler add items to the tree */
2679 PTREE_DATA(tree)->count = 0;
2680 THROW_MESSAGE(DissectorError,
2681 ep_strdup_printf("More than %d items in the tree -- possible infinite loop", MAX_TREE_ITEMS));
2684 PROTO_NODE_NEW(pnode);
2685 pnode->parent = tnode;
2687 pnode->tree_data = PTREE_DATA(tree);
2689 if (tnode->last_child != NULL) {
2690 sibling = tnode->last_child;
2691 DISSECTOR_ASSERT(sibling->next == NULL);
2692 sibling->next = pnode;
2694 tnode->first_child = pnode;
2695 tnode->last_child = pnode;
2697 return (proto_item*)pnode;
2701 /* Generic way to allocate field_info and add to proto_tree.
2702 * Sets *pfi to address of newly-allocated field_info struct, if pfi is
2705 proto_tree_add_pi(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2706 gint *length, field_info **pfi)
2716 fi = alloc_field_info(tree, hfindex, tvb, start, length);
2717 pi = proto_tree_add_node(tree, fi);
2719 /* If the proto_tree wants to keep a record of this finfo
2720 * for quick lookup, then record it. */
2721 if (fi->hfinfo->ref_count) {
2723 hash = PTREE_DATA(tree)->interesting_hfids;
2724 ptrs = g_hash_table_lookup(hash, GINT_TO_POINTER(hfindex));
2726 g_ptr_array_add(ptrs, fi);
2730 /* Does the caller want to know the fi pointer? */
2739 static header_field_info *
2740 get_hfi_and_length(int hfindex, tvbuff_t *tvb, gint start, gint *length,
2743 header_field_info *hfinfo;
2744 gint length_remaining;
2747 * We only allow a null tvbuff if the item has a zero length,
2748 * i.e. if there's no data backing it.
2750 DISSECTOR_ASSERT(tvb != NULL || *length == 0);
2752 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2755 * XXX - in some protocols, there are 32-bit unsigned length
2756 * fields, so lengths in protocol tree and tvbuff routines
2757 * should really be unsigned. We should have, for those
2758 * field types for which "to the end of the tvbuff" makes sense,
2759 * additional routines that take no length argument and
2760 * add fields that run to the end of the tvbuff.
2762 if (*length == -1) {
2764 * For FT_NONE, FT_PROTOCOL, FT_BYTES, and FT_STRING fields,
2765 * a length of -1 means "set the length to what remains in
2768 * The assumption is either that
2770 * 1) the length of the item can only be determined
2771 * by dissection (typically true of items with
2772 * subitems, which are probably FT_NONE or
2777 * 2) if the tvbuff is "short" (either due to a short
2778 * snapshot length or due to lack of reassembly of
2779 * fragments/segments/whatever), we want to display
2780 * what's available in the field (probably FT_BYTES
2781 * or FT_STRING) and then throw an exception later
2785 * 3) the field is defined to be "what's left in the
2788 * so we set the length to what remains in the tvbuff so
2789 * that, if we throw an exception while dissecting, it
2790 * has what is probably the right value.
2792 * For FT_STRINGZ, it means "the string is null-terminated,
2793 * not null-padded; set the length to the actual length
2794 * of the string", and if the tvbuff if short, we just
2795 * throw an exception.
2797 * It's not valid for any other type of field.
2799 switch (hfinfo->type) {
2803 * We allow this to be zero-length - for
2804 * example, an ONC RPC NULL procedure has
2805 * neither arguments nor reply, so the
2806 * payload for that protocol is empty.
2808 * However, if the length is negative, the
2809 * start offset is *past* the byte past the
2810 * end of the tvbuff, so we throw an
2813 *length = tvb_length_remaining(tvb, start);
2816 * Use "tvb_ensure_bytes_exist()"
2817 * to force the appropriate exception
2820 tvb_ensure_bytes_exist(tvb, start, 0);
2822 DISSECTOR_ASSERT(*length >= 0);
2828 *length = tvb_ensure_length_remaining(tvb, start);
2829 DISSECTOR_ASSERT(*length >= 0);
2834 * Leave the length as -1, so our caller knows
2840 DISSECTOR_ASSERT_NOT_REACHED();
2842 *item_length = *length;
2844 *item_length = *length;
2845 if (hfinfo->type == FT_PROTOCOL || hfinfo->type == FT_NONE) {
2847 * These types are for interior nodes of the
2848 * tree, and don't have data associated with
2849 * them; if the length is negative (XXX - see
2850 * above) or goes past the end of the tvbuff,
2851 * cut it short at the end of the tvbuff.
2852 * That way, if this field is selected in
2853 * Wireshark, we don't highlight stuff past
2854 * the end of the data.
2856 /* XXX - what to do, if we don't have a tvb? */
2858 length_remaining = tvb_length_remaining(tvb, start);
2859 if (*item_length < 0 ||
2860 (*item_length > 0 &&
2861 (length_remaining < *item_length)))
2862 *item_length = length_remaining;
2865 if (*item_length < 0) {
2866 THROW(ReportedBoundsError);
2874 new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
2875 gint start, gint item_length)
2881 fi->hfinfo = hfinfo;
2883 fi->start+=(tvb)?TVB_RAW_OFFSET(tvb):0;
2884 fi->length = item_length;
2887 if (!PTREE_DATA(tree)->visible)
2888 FI_SET_FLAG(fi, FI_HIDDEN);
2889 fvalue_init(&fi->value, fi->hfinfo->type);
2892 /* add the data source tvbuff */
2893 fi->ds_tvb=tvb?TVB_GET_DS_TVB(tvb):NULL;
2899 alloc_field_info(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2902 header_field_info *hfinfo;
2905 hfinfo = get_hfi_and_length(hfindex, tvb, start, length, &item_length);
2906 return new_field_info(tree, hfinfo, tvb, start, item_length);
2909 /* If the protocol tree is to be visible, set the representation of a
2910 proto_tree entry with the name of the field for the item and with
2911 the value formatted with the supplied printf-style format and
2914 proto_tree_set_representation_value(proto_item *pi, const char *format, va_list ap)
2916 int ret; /*tmp return value */
2918 field_info *fi = PITEM_FINFO(pi);
2920 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
2921 ITEM_LABEL_NEW(fi->rep);
2923 ret = g_snprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
2924 "%s: ", fi->hfinfo->name);
2925 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH)) {
2926 /* That's all we can put in the representation. */
2927 fi->rep->representation[ITEM_LABEL_LENGTH - 1] = '\0';
2931 ret = g_vsnprintf(fi->rep->representation + replen,
2932 ITEM_LABEL_LENGTH - replen, format, ap);
2933 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH - replen))
2934 fi->rep->representation[ITEM_LABEL_LENGTH - 1] = '\0';
2938 /* If the protocol tree is to be visible, set the representation of a
2939 proto_tree entry with the representation formatted with the supplied
2940 printf-style format and argument list. */
2942 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap)
2944 int ret; /*tmp return value */
2945 field_info *fi = PITEM_FINFO(pi);
2947 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
2948 ITEM_LABEL_NEW(fi->rep);
2949 ret = g_vsnprintf(fi->rep->representation, ITEM_LABEL_LENGTH, format, ap);
2950 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
2951 fi->rep->representation[ITEM_LABEL_LENGTH - 1] = '\0';
2955 /* Set text of proto_item after having already been created. */
2957 proto_item_set_text(proto_item *pi, const char *format, ...)
2959 field_info *fi = NULL;
2966 fi = PITEM_FINFO(pi);
2969 ITEM_LABEL_FREE(fi->rep);
2972 va_start(ap, format);
2973 proto_tree_set_representation(pi, format, ap);
2977 /* Append to text of proto_item after having already been created. */
2979 proto_item_append_text(proto_item *pi, const char *format, ...)
2981 field_info *fi = NULL;
2984 int ret; /*tmp return value */
2990 fi = PITEM_FINFO(pi);
2992 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
2993 va_start(ap, format);
2996 * If we don't already have a representation,
2997 * generate the default representation.
2999 if (fi->rep == NULL) {
3000 ITEM_LABEL_NEW(fi->rep);
3001 proto_item_fill_label(fi, fi->rep->representation);
3004 curlen = strlen(fi->rep->representation);
3005 if (ITEM_LABEL_LENGTH > curlen) {
3006 ret = g_vsnprintf(fi->rep->representation + curlen,
3007 ITEM_LABEL_LENGTH - curlen, format, ap);
3008 if ((ret == -1) || (ret >= (int)(ITEM_LABEL_LENGTH - curlen)))
3009 fi->rep->representation[ITEM_LABEL_LENGTH - 1] = '\0';
3016 proto_item_set_len(proto_item *pi, gint length)
3022 fi = PITEM_FINFO(pi);
3023 DISSECTOR_ASSERT(length >= 0);
3024 fi->length = length;
3028 * Sets the length of the item based on its start and on the specified
3029 * offset, which is the offset past the end of the item; as the start
3030 * in the item is relative to the beginning of the data source tvbuff,
3031 * we need to pass in a tvbuff - the end offset is relative to the beginning
3035 proto_item_set_end(proto_item *pi, tvbuff_t *tvb, gint end)
3041 fi = PITEM_FINFO(pi);
3042 end += TVB_RAW_OFFSET(tvb);
3043 DISSECTOR_ASSERT(end >= fi->start);
3044 fi->length = end - fi->start;
3048 proto_item_get_len(proto_item *pi)
3050 field_info *fi = PITEM_FINFO(pi);
3055 /** clear flags according to the mask and set new flag values */
3056 #define FI_REPLACE_FLAGS(fi, mask, flags_in) { \
3057 (fi->flags = (fi)->flags & ~(mask)); \
3058 (fi->flags = (fi)->flags | (flags_in)); \
3062 proto_item_set_expert_flags(proto_item *pi, int group, int severity)
3064 if(pi == NULL || pi->finfo == NULL)
3067 /* only change things if severity is worse or at least equal than before */
3068 if(severity >= FI_GET_FLAG(pi->finfo, PI_SEVERITY_MASK)) {
3069 FI_REPLACE_FLAGS(pi->finfo, PI_GROUP_MASK, group);
3070 FI_REPLACE_FLAGS(pi->finfo, PI_SEVERITY_MASK, severity);
3081 proto_tree_create_root(void)
3085 /* Initialize the proto_node */
3086 PROTO_NODE_NEW(pnode);
3087 pnode->parent = NULL;
3088 pnode->finfo = NULL;
3089 pnode->tree_data = g_new(tree_data_t, 1);
3091 /* Initialize the tree_data_t */
3092 pnode->tree_data->interesting_hfids =
3093 g_hash_table_new(g_direct_hash, g_direct_equal);
3095 /* Set the default to FALSE so it's easier to
3096 * find errors; if we expect to see the protocol tree
3097 * but for some reason the default 'visible' is not
3098 * changed, then we'll find out very quickly. */
3099 pnode->tree_data->visible = FALSE;
3101 /* Keep track of the number of children */
3102 pnode->tree_data->count = 0;
3104 return (proto_tree*) pnode;
3108 /* "prime" a proto_tree with a single hfid that a dfilter
3109 * is interested in. */
3111 proto_tree_prime_hfid(proto_tree *tree, gint hfid)
3113 header_field_info *hfinfo;
3115 g_hash_table_insert(PTREE_DATA(tree)->interesting_hfids,
3116 GINT_TO_POINTER(hfid), g_ptr_array_new());
3118 PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
3119 /* this field is referenced by a filter so increase the refcount.
3120 also increase the refcount for the parent, i.e the protocol.
3122 hfinfo->ref_count++;
3123 /* only increase the refcount if there is a parent.
3124 if this is a protocol and not a field then parent will be -1
3125 and there is no parent to add any refcounting for.
3127 if (hfinfo->parent != -1) {
3128 header_field_info *parent_hfinfo;
3129 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
3130 parent_hfinfo->ref_count++;
3135 proto_item_add_subtree(proto_item *pi, gint idx) {
3141 fi = PITEM_FINFO(pi);
3142 DISSECTOR_ASSERT(idx >= 0 && idx < num_tree_types);
3143 fi->tree_type = idx;
3145 return (proto_tree*) pi;
3149 proto_item_get_subtree(proto_item *pi) {
3154 fi = PITEM_FINFO(pi);
3155 if ( (!fi) || (fi->tree_type == -1) )
3157 return (proto_tree*) pi;
3161 proto_item_get_parent(proto_item *ti) {
3162 /* dont bother if tree is not visible */
3163 if( (!ti) || (!(PTREE_DATA(ti)->visible)) )
3169 proto_item_get_parent_nth(proto_item *ti, int gen) {
3170 /* dont bother if tree is not visible */
3171 if( (!ti) || (!(PTREE_DATA(ti)->visible)) )
3183 proto_tree_get_parent(proto_tree *tree) {
3184 /* dont bother if tree is not visible */
3185 if( (!tree) || (!(PTREE_DATA(tree)->visible)) )
3187 return (proto_item*) tree;
3191 proto_tree_get_root(proto_tree *tree) {
3192 /* dont bother if tree is not visible */
3193 if( (!tree) || (!(PTREE_DATA(tree)->visible)) )
3195 while (tree->parent) {
3196 tree = tree->parent;
3202 proto_tree_move_item(proto_tree *tree, proto_item *fixed_item, proto_item *item_to_move)
3204 proto_item *curr_item;
3207 /*** cut item_to_move out ***/
3209 /* is item_to_move the first? */
3210 if(tree->first_child == item_to_move) {
3211 /* simply change first child to next */
3212 tree->first_child = item_to_move->next;
3214 /* find previous and change it's next */
3215 for(curr_item = tree->first_child; curr_item != NULL; curr_item = curr_item->next) {
3216 if(curr_item->next == item_to_move) {
3221 DISSECTOR_ASSERT(curr_item);
3223 curr_item->next = item_to_move->next;
3225 /* fix last_child if required */
3226 if(tree->last_child == item_to_move) {
3227 tree->last_child = curr_item;
3231 /*** insert to_move after fixed ***/
3232 item_to_move->next = fixed_item->next;
3233 fixed_item->next = item_to_move;
3234 if(tree->last_child == fixed_item) {
3235 tree->last_child = item_to_move;
3241 proto_register_protocol(const char *name, const char *short_name, const char *filter_name)
3243 protocol_t *protocol;
3244 header_field_info *hfinfo;
3246 char *existing_name;
3250 gboolean found_invalid;
3253 * Make sure there's not already a protocol with any of those
3254 * names. Crash if there is, as that's an error in the code
3255 * or an inappropriate plugin.
3256 * This situation has to be fixed to not register more than one
3257 * protocol with the same name.
3259 * This is done by reducing the number of strcmp (and alike) calls as much as possible,
3260 * as this significally slows down startup time.
3262 * Drawback: As a hash value is used to reduce insert time,
3263 * this might lead to a hash collision.
3264 * However, as we have around 500+ protocols and we're using a 32 bit int this is very,
3268 key = g_malloc (sizeof(gint));
3269 *key = g_str_hash(name);
3270 existing_name = g_hash_table_lookup(proto_names, key);
3271 if (existing_name != NULL) {
3272 /* g_error will terminate the program */
3273 g_error("Duplicate protocol name \"%s\"!"
3274 " This might be caused by an inappropriate plugin or a development error.", name);
3276 g_hash_table_insert(proto_names, key, (gpointer)name);
3278 key = g_malloc (sizeof(gint));
3279 *key = g_str_hash(short_name);
3280 existing_name = g_hash_table_lookup(proto_short_names, key);
3281 if (existing_name != NULL) {
3282 g_error("Duplicate protocol short_name \"%s\"!"
3283 " This might be caused by an inappropriate plugin or a development error.", short_name);
3285 g_hash_table_insert(proto_short_names, key, (gpointer)short_name);
3287 found_invalid = FALSE;
3288 for (i = 0; i < strlen(filter_name); i++) {
3290 if (!(islower(c) || isdigit(c) || c == '-' || c == '_' || c == '.')) {
3291 found_invalid = TRUE;
3294 if (found_invalid) {
3295 g_error("Protocol filter name \"%s\" has one or more invalid characters."
3296 " Allowed are lower characters, digits, '-', '_' and '.'."
3297 " This might be caused by an inappropriate plugin or a development error.", filter_name);
3299 key = g_malloc (sizeof(gint));
3300 *key = g_str_hash(filter_name);
3301 existing_name = g_hash_table_lookup(proto_filter_names, key);
3302 if (existing_name != NULL) {
3303 g_error("Duplicate protocol filter_name \"%s\"!"
3304 " This might be caused by an inappropriate plugin or a development error.", filter_name);
3306 g_hash_table_insert(proto_filter_names, key, (gpointer)filter_name);
3308 /* Add this protocol to the list of known protocols; the list
3309 is sorted by protocol short name. */
3310 protocol = g_malloc(sizeof (protocol_t));
3311 protocol->name = name;
3312 protocol->short_name = short_name;
3313 protocol->filter_name = filter_name;
3314 protocol->fields = NULL;
3315 protocol->is_enabled = TRUE; /* protocol is enabled by default */
3316 protocol->can_toggle = TRUE;
3317 /* list will be sorted later by name, when all protocols completed registering */
3318 protocols = g_list_append(protocols, protocol);
3320 /* Here we do allocate a new header_field_info struct */
3321 hfinfo = g_mem_chunk_alloc(gmc_hfinfo);
3322 hfinfo->name = name;
3323 hfinfo->abbrev = filter_name;
3324 hfinfo->type = FT_PROTOCOL;
3325 hfinfo->strings = protocol;
3326 hfinfo->bitmask = 0;
3327 hfinfo->bitshift = 0;
3328 hfinfo->ref_count = 0;
3329 hfinfo->blurb = NULL;
3330 hfinfo->parent = -1; /* this field differentiates protos and fields */
3332 proto_id = proto_register_field_init(hfinfo, hfinfo->parent);
3333 protocol->proto_id = proto_id;
3338 * Routines to use to iterate over the protocols.
3339 * The argument passed to the iterator routines is an opaque cookie to
3340 * their callers; it's the GList pointer for the current element in
3342 * The ID of the protocol is returned, or -1 if there is no protocol.
3345 proto_get_first_protocol(void **cookie)
3347 protocol_t *protocol;
3349 if (protocols == NULL)
3351 *cookie = protocols;
3352 protocol = protocols->data;
3353 return protocol->proto_id;
3357 proto_get_next_protocol(void **cookie)
3359 GList *list_item = *cookie;
3360 protocol_t *protocol;
3362 list_item = g_list_next(list_item);
3363 if (list_item == NULL)
3365 *cookie = list_item;
3366 protocol = list_item->data;
3367 return protocol->proto_id;
3371 proto_get_first_protocol_field(int proto_id, void **cookie)
3373 protocol_t *protocol = find_protocol_by_id(proto_id);
3374 hf_register_info *ptr;
3376 if ((protocol == NULL) || (protocol->fields == NULL))
3379 *cookie = protocol->fields;
3380 ptr = protocol->fields->data;
3381 return &ptr->hfinfo;
3385 proto_get_next_protocol_field(void **cookie)
3387 GList *list_item = *cookie;
3388 hf_register_info *ptr;
3390 list_item = g_list_next(list_item);
3391 if (list_item == NULL)
3394 *cookie = list_item;
3395 ptr = list_item->data;
3396 return &ptr->hfinfo;
3400 find_protocol_by_id(int proto_id)
3402 header_field_info *hfinfo;
3407 PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
3408 DISSECTOR_ASSERT(hfinfo->type==FT_PROTOCOL);
3409 return (protocol_t *)hfinfo->strings;
3412 static gint compare_filter_name(gconstpointer proto_arg,
3413 gconstpointer filter_name)
3415 const protocol_t *protocol = proto_arg;
3416 const gchar* f_name = filter_name;
3418 return (strcmp(protocol->filter_name, f_name));
3422 proto_get_id(protocol_t *protocol)
3424 return protocol->proto_id;
3427 int proto_get_id_by_filter_name(const gchar* filter_name)
3430 protocol_t *protocol;
3432 list_entry = g_list_find_custom(protocols, filter_name,
3433 compare_filter_name);
3434 if (list_entry == NULL)
3436 protocol = list_entry->data;
3437 return protocol->proto_id;
3441 proto_get_protocol_name(int proto_id)
3443 protocol_t *protocol;
3445 protocol = find_protocol_by_id(proto_id);
3446 return protocol->name;
3450 proto_get_protocol_short_name(protocol_t *protocol)
3452 if (protocol == NULL)
3454 return protocol->short_name;
3458 proto_get_protocol_filter_name(int proto_id)
3460 protocol_t *protocol;
3462 protocol = find_protocol_by_id(proto_id);
3463 return protocol->filter_name;
3467 proto_is_protocol_enabled(protocol_t *protocol)
3469 return protocol->is_enabled;
3473 proto_can_toggle_protocol(int proto_id)
3475 protocol_t *protocol;
3477 protocol = find_protocol_by_id(proto_id);
3478 return protocol->can_toggle;
3482 proto_set_decoding(int proto_id, gboolean enabled)
3484 protocol_t *protocol;
3486 protocol = find_protocol_by_id(proto_id);
3487 DISSECTOR_ASSERT(protocol->can_toggle);
3488 protocol->is_enabled = enabled;
3492 proto_set_cant_toggle(int proto_id)
3494 protocol_t *protocol;
3496 protocol = find_protocol_by_id(proto_id);
3497 protocol->can_toggle = FALSE;
3500 /* for use with static arrays only, since we don't allocate our own copies
3501 of the header_field_info struct contained within the hf_register_info struct */
3503 proto_register_field_array(int parent, hf_register_info *hf, int num_records)
3506 hf_register_info *ptr = hf;
3509 proto = find_protocol_by_id(parent);
3510 for (i = 0; i < num_records; i++, ptr++) {
3512 * Make sure we haven't registered this yet.
3513 * Most fields have variables associated with them
3514 * that are initialized to -1; some have array elements,
3515 * or possibly uninitialized variables, so we also allow
3516 * 0 (which is unlikely to be the field ID we get back
3517 * from "proto_register_field_init()").
3519 if (*ptr->p_id != -1 && *ptr->p_id != 0) {
3521 "Duplicate field detected in call to proto_register_field_array: %s is already registered\n",
3522 ptr->hfinfo.abbrev);
3526 if (proto != NULL) {
3527 if (proto->fields == NULL) {
3528 proto->fields = g_list_append(NULL, ptr);
3529 proto->last_field = proto->fields;
3532 g_list_append(proto->last_field, ptr)->next;
3535 field_id = proto_register_field_init(&ptr->hfinfo, parent);
3536 *ptr->p_id = field_id;
3541 proto_register_field_init(header_field_info *hfinfo, int parent)
3543 /* The field must have names */
3544 DISSECTOR_ASSERT(hfinfo->name);
3545 DISSECTOR_ASSERT(hfinfo->abbrev);
3547 /* These types of fields are allowed to have value_strings, true_false_strings or a protocol_t struct*/
3548 DISSECTOR_ASSERT((hfinfo->strings == NULL) || (
3549 (hfinfo->type == FT_UINT8) ||
3550 (hfinfo->type == FT_UINT16) ||
3551 (hfinfo->type == FT_UINT24) ||
3552 (hfinfo->type == FT_UINT32) ||
3553 (hfinfo->type == FT_INT8) ||
3554 (hfinfo->type == FT_INT16) ||
3555 (hfinfo->type == FT_INT24) ||
3556 (hfinfo->type == FT_INT32) ||
3557 (hfinfo->type == FT_BOOLEAN) ||
3558 (hfinfo->type == FT_PROTOCOL) ||
3559 (hfinfo->type == FT_FRAMENUM) ));
3561 switch (hfinfo->type) {
3571 /* Require integral types (other than frame number, which is
3572 always displayed in decimal) to have a number base */
3573 DISSECTOR_ASSERT(hfinfo->display != BASE_NONE);
3577 /* Don't allow bitfields or value strings for frame numbers */
3578 DISSECTOR_ASSERT(hfinfo->bitmask == 0);
3579 DISSECTOR_ASSERT(hfinfo->strings == NULL);
3585 /* if this is a bitfield, compute bitshift */
3586 if (hfinfo->bitmask) {
3587 while ((hfinfo->bitmask & (1 << hfinfo->bitshift)) == 0)
3591 hfinfo->parent = parent;
3592 hfinfo->same_name_next = NULL;
3593 hfinfo->same_name_prev = NULL;
3595 /* if we always add and never delete, then id == len - 1 is correct */
3596 if(gpa_hfinfo.len>=gpa_hfinfo.allocated_len){
3597 if(!gpa_hfinfo.hfi){
3598 gpa_hfinfo.allocated_len=1000;
3599 gpa_hfinfo.hfi=g_malloc(sizeof(header_field_info *)*1000);
3601 gpa_hfinfo.allocated_len+=1000;
3602 gpa_hfinfo.hfi=g_realloc(gpa_hfinfo.hfi, sizeof(header_field_info *)*gpa_hfinfo.allocated_len);
3605 gpa_hfinfo.hfi[gpa_hfinfo.len]=hfinfo;
3607 hfinfo->id = gpa_hfinfo.len - 1;
3609 /* if we have real names, enter this field in the name tree */
3610 if ((hfinfo->name[0] != 0) && (hfinfo->abbrev[0] != 0 )) {
3612 header_field_info *same_name_hfinfo, *same_name_next_hfinfo;
3616 /* Check that the filter name (abbreviation) is legal;
3617 * it must contain only alphanumerics, '-', "_", and ".". */
3618 for (p = hfinfo->abbrev; (c = *p) != '\0'; p++) {
3619 if (!(isalnum(c) || c == '-' || c == '_' || c == '.')) {
3620 fprintf(stderr, "OOPS: '%c' in '%s'\n", c, hfinfo->abbrev);
3621 DISSECTOR_ASSERT(isalnum(c) || c == '-' || c == '_' ||
3625 /* We allow multiple hfinfo's to be registered under the same
3626 * abbreviation. This was done for X.25, as, depending
3627 * on whether it's modulo-8 or modulo-128 operation,
3628 * some bitfield fields may be in different bits of
3629 * a byte, and we want to be able to refer to that field
3630 * with one name regardless of whether the packets
3631 * are modulo-8 or modulo-128 packets. */
3632 same_name_hfinfo = g_tree_lookup(gpa_name_tree, hfinfo->abbrev);
3633 if (same_name_hfinfo) {
3634 /* There's already a field with this name.
3635 * Put it after that field in the list of
3636 * fields with this name, then allow the code
3637 * after this if{} block to replace the old
3638 * hfinfo with the new hfinfo in the GTree. Thus,
3639 * we end up with a linked-list of same-named hfinfo's,
3640 * with the root of the list being the hfinfo in the GTree */
3641 same_name_next_hfinfo =
3642 same_name_hfinfo->same_name_next;
3644 hfinfo->same_name_next = same_name_next_hfinfo;
3645 if (same_name_next_hfinfo)
3646 same_name_next_hfinfo->same_name_prev = hfinfo;
3648 same_name_hfinfo->same_name_next = hfinfo;
3649 hfinfo->same_name_prev = same_name_hfinfo;
3651 g_tree_insert(gpa_name_tree, (gpointer) (hfinfo->abbrev), hfinfo);
3658 proto_register_subtree_array(gint *const *indices, int num_indices)
3661 gint *const *ptr = indices;
3664 * If we've already allocated the array of tree types, expand
3665 * it; this lets plugins such as mate add tree types after
3666 * the initial startup. (If we haven't already allocated it,
3667 * we don't allocate it; on the first pass, we just assign
3668 * ett values and keep track of how many we've assigned, and
3669 * when we're finished registering all dissectors we allocate
3670 * the array, so that we do only one allocation rather than
3671 * wasting CPU time and memory by growing the array for each
3672 * dissector that registers ett values.)
3674 if (tree_is_expanded != NULL) {
3676 g_realloc(tree_is_expanded,
3677 (num_tree_types+num_indices)*sizeof (gboolean));
3678 memset(tree_is_expanded + num_tree_types, 0,
3679 num_indices*sizeof (gboolean));
3683 * Assign "num_indices" subtree numbers starting at "num_tree_types",
3684 * returning the indices through the pointers in the array whose
3685 * first element is pointed to by "indices", and update
3686 * "num_tree_types" appropriately.
3688 for (i = 0; i < num_indices; i++, ptr++, num_tree_types++)
3689 **ptr = num_tree_types;
3693 proto_item_fill_label(field_info *fi, gchar *label_str)
3695 header_field_info *hfinfo = fi->hfinfo;
3701 guint32 n_addr; /* network-order IPv4 address */
3703 int ret; /*tmp return value */
3705 switch(hfinfo->type) {
3708 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3709 "%s", hfinfo->name);
3710 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3711 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3715 fill_label_boolean(fi, label_str);
3720 bytes = fvalue_get(&fi->value);
3722 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3723 "%s: %s", hfinfo->name,
3724 bytes_to_str(bytes, fvalue_length(&fi->value)));
3725 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3726 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3729 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3730 "%s: <MISSING>", hfinfo->name);
3731 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3732 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3736 /* Four types of integers to take care of:
3737 * Bitfield, with val_string
3738 * Bitfield, w/o val_string
3739 * Non-bitfield, with val_string
3740 * Non-bitfield, w/o val_string
3747 if (hfinfo->bitmask) {
3748 if (hfinfo->strings) {
3749 fill_label_enumerated_bitfield(fi, label_str);
3752 fill_label_numeric_bitfield(fi, label_str);
3756 if (hfinfo->strings) {
3757 fill_label_enumerated_uint(fi, label_str);
3760 fill_label_uint(fi, label_str);
3766 fill_label_uint64(fi, label_str);
3773 DISSECTOR_ASSERT(!hfinfo->bitmask);
3774 if (hfinfo->strings) {
3775 fill_label_enumerated_int(fi, label_str);
3778 fill_label_int(fi, label_str);
3783 fill_label_int64(fi, label_str);
3787 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3788 "%s: %." STRINGIFY(FLT_DIG) "f",
3789 hfinfo->name, fvalue_get_floating(&fi->value));
3790 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3791 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3795 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3796 "%s: %." STRINGIFY(DBL_DIG) "g",
3797 hfinfo->name, fvalue_get_floating(&fi->value));
3798 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3799 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3802 case FT_ABSOLUTE_TIME:
3803 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3804 "%s: %s", hfinfo->name,
3805 abs_time_to_str(fvalue_get(&fi->value)));
3806 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3807 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3810 case FT_RELATIVE_TIME:
3811 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3812 "%s: %s seconds", hfinfo->name,
3813 rel_time_to_secs_str(fvalue_get(&fi->value)));
3814 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3815 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3819 integer = fvalue_get_integer(&fi->value);
3820 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3821 "%s: %s (0x%08X)", hfinfo->name,
3822 get_ipxnet_name(integer), integer);
3823 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3824 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3828 bytes = fvalue_get(&fi->value);
3829 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3830 "%s: %s (%s)", hfinfo->name,
3831 get_ether_name(bytes),
3832 ether_to_str(bytes));
3833 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3834 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3838 ipv4 = fvalue_get(&fi->value);
3839 n_addr = ipv4_get_net_order_addr(ipv4);
3840 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3841 "%s: %s (%s)", hfinfo->name,
3842 get_hostname(n_addr),
3843 ip_to_str((guint8*)&n_addr));
3844 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3845 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3849 bytes = fvalue_get(&fi->value);
3850 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3851 "%s: %s (%s)", hfinfo->name,
3852 get_hostname6((struct e_in6_addr *)bytes),
3853 ip6_to_str((struct e_in6_addr*)bytes));
3854 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3855 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3859 guid = fvalue_get(&fi->value);
3860 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3861 "%s: %s", hfinfo->name,
3863 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3864 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3868 bytes = fvalue_get(&fi->value);
3869 name = (oid_resolv_enabled()) ? get_oid_name(bytes, fvalue_length(&fi->value)) : NULL;
3871 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3872 "%s: %s (%s)", hfinfo->name,
3873 oid_to_str(bytes, fvalue_length(&fi->value)), name);
3875 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3876 "%s: %s", hfinfo->name,
3877 oid_to_str(bytes, fvalue_length(&fi->value)));
3879 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3880 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3885 case FT_UINT_STRING:
3886 bytes = fvalue_get(&fi->value);
3887 if(strlen(bytes) > ITEM_LABEL_LENGTH) {
3888 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3889 "%s [truncated]: %s", hfinfo->name,
3890 format_text(bytes, strlen(bytes)));
3892 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3893 "%s: %s", hfinfo->name,
3894 format_text(bytes, strlen(bytes)));
3896 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3897 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3901 g_error("hfinfo->type %d (%s) not handled\n",
3903 ftype_name(hfinfo->type));
3904 DISSECTOR_ASSERT_NOT_REACHED();
3910 fill_label_boolean(field_info *fi, gchar *label_str)
3912 char *p = label_str;
3913 int bitfield_byte_length = 0, bitwidth;
3914 guint32 unshifted_value;
3916 int ret; /*tmp return value */
3918 header_field_info *hfinfo = fi->hfinfo;
3919 static const true_false_string default_tf = { "True", "False" };
3920 const true_false_string *tfstring = &default_tf;
3922 if (hfinfo->strings) {
3923 tfstring = (const struct true_false_string*) hfinfo->strings;
3926 value = fvalue_get_integer(&fi->value);
3927 if (hfinfo->bitmask) {
3928 /* Figure out the bit width */
3929 bitwidth = hfinfo_bitwidth(hfinfo);
3932 unshifted_value = value;
3933 if (hfinfo->bitshift > 0) {
3934 unshifted_value <<= hfinfo->bitshift;
3937 /* Create the bitfield first */
3938 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
3939 bitfield_byte_length = p - label_str;
3942 /* Fill in the textual info */
3943 ret = g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
3944 "%s: %s", hfinfo->name,
3945 value ? tfstring->true_string : tfstring->false_string);
3946 if ((ret == -1) || (ret >= (ITEM_LABEL_LENGTH - bitfield_byte_length)))
3947 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3951 /* Fills data for bitfield ints with val_strings */
3953 fill_label_enumerated_bitfield(field_info *fi, gchar *label_str)
3955 const char *format = NULL;
3957 int bitfield_byte_length, bitwidth;
3958 guint32 unshifted_value;
3960 int ret; /*tmp return value */
3962 header_field_info *hfinfo = fi->hfinfo;
3964 /* Figure out the bit width */
3965 bitwidth = hfinfo_bitwidth(hfinfo);
3967 /* Pick the proper format string */
3968 format = hfinfo_uint_vals_format(hfinfo);
3971 unshifted_value = fvalue_get_integer(&fi->value);
3972 value = unshifted_value;
3973 if (hfinfo->bitshift > 0) {
3974 unshifted_value <<= hfinfo->bitshift;
3977 /* Create the bitfield first */
3978 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
3979 bitfield_byte_length = p - label_str;
3981 /* Fill in the textual info using stored (shifted) value */
3982 ret = g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
3983 format, hfinfo->name,
3984 val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
3985 if ((ret == -1) || (ret >= (ITEM_LABEL_LENGTH - bitfield_byte_length)))
3986 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3990 fill_label_numeric_bitfield(field_info *fi, gchar *label_str)
3992 const char *format = NULL;
3994 int bitfield_byte_length, bitwidth;
3995 guint32 unshifted_value;
3997 int ret; /*tmp return value */
3999 header_field_info *hfinfo = fi->hfinfo;
4001 /* Figure out the bit width */
4002 bitwidth = hfinfo_bitwidth(hfinfo);
4004 /* Pick the proper format string */
4005 format = hfinfo_uint_format(hfinfo);
4008 unshifted_value = fvalue_get_integer(&fi->value);
4009 value = unshifted_value;
4010 if (hfinfo->bitshift > 0) {
4011 unshifted_value <<= hfinfo->bitshift;
4014 /* Create the bitfield using */
4015 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
4016 bitfield_byte_length = p - label_str;
4018 /* Fill in the textual info using stored (shifted) value */
4019 if (IS_BASE_DUAL(hfinfo->display)) {
4020 ret = g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
4021 format, hfinfo->name, value, value);
4023 ret = g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
4024 format, hfinfo->name, value);
4026 if ((ret == -1) || (ret >= (ITEM_LABEL_LENGTH - bitfield_byte_length)))
4027 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4032 fill_label_enumerated_uint(field_info *fi, gchar *label_str)
4034 const char *format = NULL;
4035 header_field_info *hfinfo = fi->hfinfo;
4037 int ret; /*tmp return value */
4039 /* Pick the proper format string */
4040 format = hfinfo_uint_vals_format(hfinfo);
4042 value = fvalue_get_integer(&fi->value);
4044 /* Fill in the textual info */
4045 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4046 format, hfinfo->name,
4047 val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
4048 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4049 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4053 fill_label_uint(field_info *fi, gchar *label_str)
4055 const char *format = NULL;
4056 header_field_info *hfinfo = fi->hfinfo;
4058 int ret; /*tmp return value */
4060 /* Pick the proper format string */
4061 format = hfinfo_uint_format(hfinfo);
4062 value = fvalue_get_integer(&fi->value);
4064 /* Fill in the textual info */
4065 if (IS_BASE_DUAL(hfinfo->display)) {
4066 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4067 format, hfinfo->name, value, value);
4069 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4070 format, hfinfo->name, value);
4072 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4073 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4077 fill_label_uint64(field_info *fi, gchar *label_str)
4079 const char *format = NULL;
4080 header_field_info *hfinfo = fi->hfinfo;
4082 int ret; /*tmp return value */
4084 /* Pick the proper format string */
4085 format = hfinfo_uint64_format(hfinfo);
4086 value = fvalue_get_integer64(&fi->value);
4088 /* Fill in the textual info */
4089 if (IS_BASE_DUAL(hfinfo->display)) {
4090 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4091 format, hfinfo->name, value, value);
4093 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4094 format, hfinfo->name, value);
4096 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4097 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4101 fill_label_enumerated_int(field_info *fi, gchar *label_str)
4103 const char *format = NULL;
4104 header_field_info *hfinfo = fi->hfinfo;
4106 int ret; /*tmp return value */
4108 /* Pick the proper format string */
4109 format = hfinfo_int_vals_format(hfinfo);
4110 value = fvalue_get_integer(&fi->value);
4112 /* Fill in the textual info */
4113 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4114 format, hfinfo->name,
4115 val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
4116 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4117 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4121 fill_label_int(field_info *fi, gchar *label_str)
4123 const char *format = NULL;
4124 header_field_info *hfinfo = fi->hfinfo;
4126 int ret; /*tmp return value */
4128 /* Pick the proper format string */
4129 format = hfinfo_int_format(hfinfo);
4130 value = fvalue_get_integer(&fi->value);
4132 /* Fill in the textual info */
4133 if (IS_BASE_DUAL(hfinfo->display)) {
4134 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4135 format, hfinfo->name, value, value);
4137 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4138 format, hfinfo->name, value);
4140 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4141 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4145 fill_label_int64(field_info *fi, gchar *label_str)
4147 const char *format = NULL;
4148 header_field_info *hfinfo = fi->hfinfo;
4150 int ret; /*tmp return value */
4152 /* Pick the proper format string */
4153 format = hfinfo_int64_format(hfinfo);
4154 value = fvalue_get_integer64(&fi->value);
4156 /* Fill in the textual info */
4157 if (IS_BASE_DUAL(hfinfo->display)) {
4158 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4159 format, hfinfo->name, value, value);
4161 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4162 format, hfinfo->name, value);
4164 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4165 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4169 hfinfo_bitwidth(header_field_info *hfinfo)
4173 if (!hfinfo->bitmask) {
4177 switch(hfinfo->type) {
4195 bitwidth = hfinfo->display; /* hacky? :) */
4198 DISSECTOR_ASSERT_NOT_REACHED();
4205 hfinfo_uint_vals_format(header_field_info *hfinfo)
4207 const char *format = NULL;
4209 switch(hfinfo->display) {
4212 format = "%s: %s (%u)";
4214 case BASE_OCT: /* I'm lazy */
4215 format = "%s: %s (%o)";
4219 switch(hfinfo->type) {
4221 format = "%s: %s (0x%02x)";
4224 format = "%s: %s (0x%04x)";
4227 format = "%s: %s (0x%06x)";
4230 format = "%s: %s (0x%08x)";
4233 DISSECTOR_ASSERT_NOT_REACHED();
4238 DISSECTOR_ASSERT_NOT_REACHED();
4245 hfinfo_uint_format(header_field_info *hfinfo)
4247 const char *format = NULL;
4249 /* Pick the proper format string */
4250 if (hfinfo->type == FT_FRAMENUM) {
4252 * Frame numbers are always displayed in decimal.
4256 switch(hfinfo->display) {
4261 switch(hfinfo->type) {
4263 format = "%s: %u (0x%02x)";
4266 format = "%s: %u (0x%04x)";
4269 format = "%s: %u (0x%06x)";
4272 format = "%s: %u (0x%08x)";
4275 DISSECTOR_ASSERT_NOT_REACHED();
4279 case BASE_OCT: /* I'm lazy */
4283 switch(hfinfo->type) {
4285 format = "%s: 0x%02x";
4288 format = "%s: 0x%04x";
4291 format = "%s: 0x%06x";
4294 format = "%s: 0x%08x";
4297 DISSECTOR_ASSERT_NOT_REACHED();
4302 switch(hfinfo->type) {
4304 format = "%s: 0x%02x (%u)";
4307 format = "%s: 0x%04x (%u)";
4310 format = "%s: 0x%06x (%u)";
4313 format = "%s: 0x%08x (%u)";
4316 DISSECTOR_ASSERT_NOT_REACHED();
4321 DISSECTOR_ASSERT_NOT_REACHED();
4329 hfinfo_int_vals_format(header_field_info *hfinfo)
4331 const char *format = NULL;
4333 switch(hfinfo->display) {
4336 format = "%s: %s (%d)";
4338 case BASE_OCT: /* I'm lazy */
4339 format = "%s: %s (%o)";
4343 switch(hfinfo->type) {
4345 format = "%s: %s (0x%02x)";
4348 format = "%s: %s (0x%04x)";
4351 format = "%s: %s (0x%06x)";
4354 format = "%s: %s (0x%08x)";
4357 DISSECTOR_ASSERT_NOT_REACHED();
4362 DISSECTOR_ASSERT_NOT_REACHED();
4369 hfinfo_uint64_format(header_field_info *hfinfo)
4371 const char *format = NULL;
4373 /* Pick the proper format string */
4374 switch(hfinfo->display) {
4376 format = "%s: %" PRIu64;
4379 format = "%s: %" PRIu64 " (%" PRIx64 ")";
4381 case BASE_OCT: /* I'm lazy */
4382 format = "%s: %" PRIo64;
4385 format = "%s: 0x%016" PRIx64;
4388 format = "%s: 0x%016" PRIx64 " (%" PRIu64 ")";
4391 DISSECTOR_ASSERT_NOT_REACHED();
4398 hfinfo_int_format(header_field_info *hfinfo)
4400 const char *format = NULL;
4402 /* Pick the proper format string */
4403 switch(hfinfo->display) {
4408 switch(hfinfo->type) {
4410 format = "%s: %d (0x%02x)";
4413 format = "%s: %d (0x%04x)";
4416 format = "%s: %d (0x%06x)";
4419 format = "%s: %d (0x%08x)";
4422 DISSECTOR_ASSERT_NOT_REACHED();
4425 case BASE_OCT: /* I'm lazy */
4429 switch(hfinfo->type) {
4431 format = "%s: 0x%02x";
4434 format = "%s: 0x%04x";
4437 format = "%s: 0x%06x";
4440 format = "%s: 0x%08x";
4443 DISSECTOR_ASSERT_NOT_REACHED();
4448 switch(hfinfo->type) {
4450 format = "%s: 0x%02x (%d)";
4453 format = "%s: 0x%04x (%d)";
4456 format = "%s: 0x%06x (%d)";
4459 format = "%s: 0x%08x (%d)";
4462 DISSECTOR_ASSERT_NOT_REACHED();
4467 DISSECTOR_ASSERT_NOT_REACHED();
4474 hfinfo_int64_format(header_field_info *hfinfo)
4476 const char *format = NULL;
4478 /* Pick the proper format string */
4479 switch(hfinfo->display) {
4481 format = "%s: %" PRId64;
4484 format = "%s: %" PRId64 " (%" PRIx64 ")";
4486 case BASE_OCT: /* I'm lazy */
4487 format = "%s: %" PRIo64;
4490 format = "%s: 0x%016" PRIx64;
4493 format = "%s: 0x%016" PRIx64 " (%" PRId64 ")";
4496 DISSECTOR_ASSERT_NOT_REACHED();
4505 proto_registrar_n(void)
4507 return gpa_hfinfo.len;
4511 proto_registrar_get_name(int n)
4513 header_field_info *hfinfo;
4515 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
4516 return hfinfo->name;
4520 proto_registrar_get_abbrev(int n)
4522 header_field_info *hfinfo;
4524 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
4525 return hfinfo->abbrev;
4529 proto_registrar_get_ftype(int n)
4531 header_field_info *hfinfo;
4533 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
4534 return hfinfo->type;
4538 proto_registrar_get_parent(int n)
4540 header_field_info *hfinfo;
4542 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
4543 return hfinfo->parent;
4547 proto_registrar_is_protocol(int n)
4549 header_field_info *hfinfo;
4551 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
4552 return (hfinfo->parent == -1 ? TRUE : FALSE);
4555 /* Returns length of field in packet (not necessarily the length
4556 * in our internal representation, as in the case of IPv4).
4557 * 0 means undeterminable at time of registration
4558 * -1 means the field is not registered. */
4560 proto_registrar_get_length(int n)
4562 header_field_info *hfinfo;
4564 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
4565 return ftype_length(hfinfo->type);
4570 /* Looks for a protocol or a field in a proto_tree. Returns TRUE if
4571 * it exists anywhere, or FALSE if it exists nowhere. */
4573 proto_check_for_protocol_or_field(proto_tree* tree, int id)
4575 GPtrArray *ptrs = proto_get_finfo_ptr_array(tree, id);
4580 else if (g_ptr_array_len(ptrs) > 0) {
4588 /* Return GPtrArray* of field_info pointers for all hfindex that appear in tree.
4589 * This only works if the hfindex was "primed" before the dissection
4590 * took place, as we just pass back the already-created GPtrArray*.
4591 * The caller should *not* free the GPtrArray*; proto_tree_free_node()
4594 proto_get_finfo_ptr_array(proto_tree *tree, int id)
4596 return g_hash_table_lookup(PTREE_DATA(tree)->interesting_hfids,
4597 GINT_TO_POINTER(id));
4601 /* Helper struct for proto_find_info() and proto_all_finfos() */
4607 /* Helper function for proto_find_info() */
4609 find_finfo(proto_node *node, gpointer data)
4611 field_info *fi = PITEM_FINFO(node);
4612 if (fi && fi->hfinfo) {
4613 if (fi->hfinfo->id == ((ffdata_t*)data)->id) {
4614 g_ptr_array_add(((ffdata_t*)data)->array, fi);
4618 /* Don't stop traversing. */
4622 /* Return GPtrArray* of field_info pointers for all hfindex that appear in a tree.
4623 * This works on any proto_tree, primed or unprimed, but actually searches
4624 * the tree, so it is slower than using proto_get_finfo_ptr_array on a primed tree.
4625 * The caller does need to free the returned GPtrArray with
4626 * g_ptr_array_free(<array>, FALSE).
4629 proto_find_finfo(proto_tree *tree, int id)
4633 ffdata.array = g_ptr_array_new();
4636 proto_tree_traverse_pre_order(tree, find_finfo, &ffdata);
4638 return ffdata.array;
4641 /* Helper function for proto_all_finfos() */
4643 every_finfo(proto_node *node, gpointer data)
4645 field_info *fi = PITEM_FINFO(node);
4646 if (fi && fi->hfinfo) {
4647 g_ptr_array_add(((ffdata_t*)data)->array, fi);
4650 /* Don't stop traversing. */
4654 /* Return GPtrArray* of field_info pointers containing all hfindexes that appear in a tree. */
4656 proto_all_finfos(proto_tree *tree)
4660 ffdata.array = g_ptr_array_new();
4663 proto_tree_traverse_pre_order(tree, every_finfo, &ffdata);
4665 return ffdata.array;
4676 check_for_offset(proto_node *node, gpointer data)
4678 field_info *fi = PITEM_FINFO(node);
4679 offset_search_t *offsearch = data;
4681 /* !fi == the top most container node which holds nothing */
4682 if (fi && !PROTO_ITEM_IS_HIDDEN(node) && fi->ds_tvb && offsearch->tvb == fi->ds_tvb) {
4683 if (offsearch->offset >= (guint) fi->start &&
4684 offsearch->offset < (guint) (fi->start + fi->length)) {
4686 offsearch->finfo = fi;
4687 return FALSE; /* keep traversing */
4690 return FALSE; /* keep traversing */
4693 /* Search a proto_tree backwards (from leaves to root) looking for the field
4694 * whose start/length occupies 'offset' */
4695 /* XXX - I couldn't find an easy way to search backwards, so I search
4696 * forwards, w/o stopping. Therefore, the last finfo I find will the be
4697 * the one I want to return to the user. This algorithm is inefficient
4698 * and could be re-done, but I'd have to handle all the children and
4699 * siblings of each node myself. When I have more time I'll do that.
4702 proto_find_field_from_offset(proto_tree *tree, guint offset, tvbuff_t *tvb)
4704 offset_search_t offsearch;
4706 offsearch.offset = offset;
4707 offsearch.finfo = NULL;
4708 offsearch.tvb = tvb;
4710 proto_tree_traverse_pre_order(tree, check_for_offset, &offsearch);
4712 return offsearch.finfo;
4715 /* Dumps the protocols in the registration database to stdout. An independent
4716 * program can take this output and format it into nice tables or HTML or
4719 * There is one record per line. The fields are tab-delimited.
4721 * Field 1 = protocol name
4722 * Field 2 = protocol short name
4723 * Field 3 = protocol filter name
4726 proto_registrar_dump_protocols(void)
4728 protocol_t *protocol;
4730 void *cookie = NULL;
4732 for (i = proto_get_first_protocol(&cookie); i != -1;
4733 i = proto_get_next_protocol(&cookie)) {
4734 protocol = find_protocol_by_id(i);
4735 printf("%s\t%s\t%s\n", protocol->name, protocol->short_name,
4736 protocol->filter_name);
4740 /* Dumps the value_string and true/false strings for fields that have
4741 * them. There is one record per line. Fields are tab-delimited.
4742 * There are two types of records, Value String records and True/False
4743 * String records. The first field, 'V' or 'T', indicates the type
4749 * Field 2 = field abbreviation to which this value string corresponds
4750 * Field 3 = Integer value
4753 * True/False Strings
4754 * ------------------
4756 * Field 2 = field abbreviation to which this true/false string corresponds
4757 * Field 3 = True String
4758 * Field 4 = False String
4761 proto_registrar_dump_values(void)
4763 header_field_info *hfinfo, *parent_hfinfo;
4765 const value_string *vals;
4766 const true_false_string *tfs;
4768 len = gpa_hfinfo.len;
4769 for (i = 0; i < len ; i++) {
4770 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
4772 if (hfinfo->id == hf_text_only) {
4776 /* ignore protocols */
4777 if (proto_registrar_is_protocol(i)) {
4780 /* process header fields */
4783 * If this field isn't at the head of the list of
4784 * fields with this name, skip this field - all
4785 * fields with the same name are really just versions
4786 * of the same field stored in different bits, and
4787 * should have the same type/radix/value list, and
4788 * just differ in their bit masks. (If a field isn't
4789 * a bitfield, but can be, say, 1 or 2 bytes long,
4790 * it can just be made FT_UINT16, meaning the
4791 * *maximum* length is 2 bytes, and be used
4794 if (hfinfo->same_name_prev != NULL)
4797 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
4802 if (hfinfo->type == FT_UINT8 ||
4803 hfinfo->type == FT_UINT16 ||
4804 hfinfo->type == FT_UINT24 ||
4805 hfinfo->type == FT_UINT32 ||
4806 hfinfo->type == FT_UINT64 ||
4807 hfinfo->type == FT_INT8 ||
4808 hfinfo->type == FT_INT16 ||
4809 hfinfo->type == FT_INT24 ||
4810 hfinfo->type == FT_INT32 ||
4811 hfinfo->type == FT_INT64) {
4813 vals = hfinfo->strings;
4815 else if (hfinfo->type == FT_BOOLEAN) {
4816 tfs = hfinfo->strings;
4819 /* Print value strings? */
4822 while (vals[vi].strptr) {
4823 /* Print in the proper base */
4824 if (hfinfo->display == BASE_HEX) {
4825 printf("V\t%s\t0x%x\t%s\n",
4831 printf("V\t%s\t%u\t%s\n",
4840 /* Print true/false strings? */
4842 printf("T\t%s\t%s\t%s\n", hfinfo->abbrev,
4843 tfs->true_string, tfs->false_string);
4849 /* Dumps the contents of the registration database to stdout. An indepedent
4850 * program can take this output and format it into nice tables or HTML or
4853 * There is one record per line. Each record is either a protocol or a header
4854 * field, differentiated by the first field. The fields are tab-delimited.
4859 * Field 2 = descriptive protocol name
4860 * Field 3 = protocol abbreviation
4866 * Field 2 = descriptive field name
4867 * Field 3 = field abbreviation
4868 * Field 4 = type ( textual representation of the the ftenum type )
4869 * Field 5 = parent protocol abbreviation
4870 * Field 6 = blurb describing field
4874 * Field 2 = descriptive field name
4875 * Field 3 = field abbreviation
4876 * Field 4 = type ( textual representation of the the ftenum type )
4877 * Field 5 = parent protocol abbreviation
4878 * Field 6 = blurb describing field
4879 * Field 7 = base for display (for integer types)
4880 * Field 8 = blurb describing field (yes, apparently we repeated this accidentally)
4884 * Field 2 = descriptive field name
4885 * Field 3 = field abbreviation
4886 * Field 4 = type ( textual representation of the the ftenum type )
4887 * Field 5 = parent protocol abbreviation
4888 * Field 6 = blurb describing field
4889 * Field 7 = base for display (for integer types)
4893 proto_registrar_dump_fields(int format)
4895 header_field_info *hfinfo, *parent_hfinfo;
4897 const char *enum_name;
4898 const char *base_name;
4901 len = gpa_hfinfo.len;
4902 for (i = 0; i < len ; i++) {
4903 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
4906 * Skip the pseudo-field for "proto_tree_add_text()" since
4907 * we don't want it in the list of filterable fields.
4909 if (hfinfo->id == hf_text_only)
4912 /* format for protocols */
4913 if (proto_registrar_is_protocol(i)) {
4914 printf("P\t%s\t%s\n", hfinfo->name, hfinfo->abbrev);
4916 /* format for header fields */
4919 * If this field isn't at the head of the list of
4920 * fields with this name, skip this field - all
4921 * fields with the same name are really just versions
4922 * of the same field stored in different bits, and
4923 * should have the same type/radix/value list, and
4924 * just differ in their bit masks. (If a field isn't
4925 * a bitfield, but can be, say, 1 or 2 bytes long,
4926 * it can just be made FT_UINT16, meaning the
4927 * *maximum* length is 2 bytes, and be used
4930 if (hfinfo->same_name_prev != NULL)
4933 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
4935 enum_name = ftype_name(hfinfo->type);
4939 if (hfinfo->type == FT_UINT8 ||
4940 hfinfo->type == FT_UINT16 ||
4941 hfinfo->type == FT_UINT24 ||
4942 hfinfo->type == FT_UINT32 ||
4943 hfinfo->type == FT_UINT64 ||
4944 hfinfo->type == FT_INT8 ||
4945 hfinfo->type == FT_INT16 ||
4946 hfinfo->type == FT_INT24 ||
4947 hfinfo->type == FT_INT32 ||
4948 hfinfo->type == FT_INT64) {
4951 switch(hfinfo->display) {
4953 base_name = "BASE_NONE";
4956 base_name = "BASE_DEC";
4959 base_name = "BASE_HEX";
4962 base_name = "BASE_OCT";
4965 base_name = "BASE_DEC_HEX";
4968 base_name = "BASE_HEX_DEC";
4974 blurb = hfinfo->blurb;
4978 printf("F\t%s\t%s\t%s\t%s\t%s\n",
4979 hfinfo->name, hfinfo->abbrev, enum_name,
4980 parent_hfinfo->abbrev, blurb);
4982 else if (format == 2) {
4983 printf("F\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n",
4984 hfinfo->name, hfinfo->abbrev, enum_name,
4985 parent_hfinfo->abbrev, blurb,
4988 else if (format == 3) {
4989 printf("F\t%s\t%s\t%s\t%s\t%s\t%s\t%u\n",
4990 hfinfo->name, hfinfo->abbrev, enum_name,
4991 parent_hfinfo->abbrev, blurb,
4992 base_name, hfinfo->bitmask);
4995 g_assert_not_reached();
5002 hfinfo_numeric_format(header_field_info *hfinfo)
5004 const char *format = NULL;
5006 /* Pick the proper format string */
5007 if (hfinfo->type == FT_FRAMENUM) {
5009 * Frame numbers are always displayed in decimal.
5011 format = "%s == %u";
5013 /* Pick the proper format string */
5014 switch(hfinfo->display) {
5017 case BASE_OCT: /* I'm lazy */
5018 switch(hfinfo->type) {
5023 format = "%s == %u";
5026 format = "%s == %" PRIu64;
5032 format = "%s == %d";
5035 format = "%s == %" PRId64;
5038 DISSECTOR_ASSERT_NOT_REACHED();
5044 switch(hfinfo->type) {
5046 format = "%s == 0x%02x";
5049 format = "%s == 0x%04x";
5052 format = "%s == 0x%06x";
5055 format = "%s == 0x%08x";
5058 format = "%s == 0x%016" PRIx64;
5061 DISSECTOR_ASSERT_NOT_REACHED();
5066 DISSECTOR_ASSERT_NOT_REACHED();
5074 * Returns TRUE if we can do a "match selected" on the field, FALSE
5078 proto_can_match_selected(field_info *finfo, epan_dissect_t *edt)
5080 header_field_info *hfinfo;
5083 hfinfo = finfo->hfinfo;
5084 DISSECTOR_ASSERT(hfinfo);
5086 switch(hfinfo->type) {
5090 * Doesn't have a value, but may still want to test
5091 * for its presence in a trace
5097 * This doesn't have a value, so we'd match
5098 * on the raw bytes at this address.
5100 * Should we be allowed to access to the raw bytes?
5101 * If "edt" is NULL, the answer is "no".
5107 * Is this field part of the raw frame tvbuff?
5108 * If not, we can't use "frame[N:M]" to match
5111 * XXX - should this be frame-relative, or
5112 * protocol-relative?
5114 * XXX - does this fallback for non-registered
5115 * fields even make sense?
5117 if (finfo->ds_tvb != edt->tvb)
5121 * If the length is 0, there's nothing to match, so
5122 * we can't match. (Also check for negative values,
5123 * just in case, as we'll cast it to an unsigned
5126 length = finfo->length;
5131 * Don't go past the end of that tvbuff.
5133 if ((guint)length > tvb_length(finfo->ds_tvb))
5134 length = tvb_length(finfo->ds_tvb);
5141 * By default, assume the type has a value, so
5148 /* This function returns a string allocated with packet lifetime scope.
5149 * You do not need to [g_]free() this string since it will be automatically
5150 * freed once the next packet is dissected.
5153 proto_construct_dfilter_string(field_info *finfo, epan_dissect_t *edt)
5155 header_field_info *hfinfo;
5161 gint start, length, length_remaining;
5164 hfinfo = finfo->hfinfo;
5165 DISSECTOR_ASSERT(hfinfo);
5166 abbrev_len = strlen(hfinfo->abbrev);
5169 * XXX - we can't use the "val_to_string_repr" and "string_repr_len"
5170 * functions for FT_UINT and FT_INT types, as we choose the base in
5171 * the string expression based on the display base of the field.
5173 * Note that the base does matter, as this is also used for
5174 * the protocolinfo tap.
5176 * It might be nice to use them in "proto_item_fill_label()"
5177 * as well, although, there, you'd have to deal with the base
5178 * *and* with resolved values for addresses.
5180 * Perhaps we need two different val_to_string routines, one
5181 * to generate items for display filters and one to generate
5182 * strings for display, and pass to both of them the
5183 * "display" and "strings" values in the header_field_info
5184 * structure for the field, so they can get the base and,
5185 * if the field is Boolean or an enumerated integer type,
5186 * the tables used to generate human-readable values.
5188 switch(hfinfo->type) {
5200 * 4 bytes for " == ".
5203 * a sign + up to 10 digits of 32-bit integer,
5206 * "0x" + 8 digits of 32-bit integer, in hex;
5208 * 11 digits of 32-bit integer, in octal.
5209 * (No, we don't do octal, but this way,
5210 * we know that if we do, this will still
5213 * 1 byte for the trailing '\0'.
5215 dfilter_len = abbrev_len + 4 + 11 + 1;
5216 buf = ep_alloc0(dfilter_len);
5217 format = hfinfo_numeric_format(hfinfo);
5218 g_snprintf(buf, dfilter_len, format, hfinfo->abbrev, fvalue_get_integer(&finfo->value));
5224 * 4 bytes for " == ".
5227 * a sign + up to 20 digits of 32-bit integer,
5230 * "0x" + 16 digits of 32-bit integer, in hex;
5232 * 22 digits of 32-bit integer, in octal.
5233 * (No, we don't do octal, but this way,
5234 * we know that if we do, this will still
5237 * 1 byte for the trailing '\0'.
5239 dfilter_len = abbrev_len + 4 + 22 + 1;
5240 buf = ep_alloc0(dfilter_len);
5241 format = hfinfo_numeric_format(hfinfo);
5242 g_snprintf(buf, dfilter_len, format, hfinfo->abbrev, fvalue_get_integer64(&finfo->value));
5246 buf = ep_strdup(finfo->hfinfo->abbrev);
5252 * This doesn't have a value, so we'd match
5253 * on the raw bytes at this address.
5255 * Should we be allowed to access to the raw bytes?
5256 * If "edt" is NULL, the answer is "no".
5262 * Is this field part of the raw frame tvbuff?
5263 * If not, we can't use "frame[N:M]" to match
5266 * XXX - should this be frame-relative, or
5267 * protocol-relative?
5269 * XXX - does this fallback for non-registered
5270 * fields even make sense?
5272 if (finfo->ds_tvb != edt->tvb)
5273 return NULL; /* you lose */
5276 * If the length is 0, just match the name of the field
5277 * (Also check for negative values,
5278 * just in case, as we'll cast it to an unsigned
5281 length = finfo->length;
5284 buf = ep_strdup(finfo->hfinfo->abbrev);
5291 * Don't go past the end of that tvbuff.
5293 length_remaining = tvb_length_remaining(finfo->ds_tvb, finfo->start);
5294 if (length > length_remaining)
5295 length = length_remaining;
5299 start = finfo->start;
5300 buf_len = 32 + length * 3;
5301 buf = ep_alloc0(buf_len);
5304 ptr += g_snprintf(ptr, buf_len-(ptr-buf), "frame[%d:%d] == ", finfo->start, length);
5305 for (i=0;i<length; i++) {
5306 c = tvb_get_guint8(finfo->ds_tvb, start);
5309 ptr += g_snprintf(ptr, buf_len-(ptr-buf), "%02x", c);
5312 ptr += g_snprintf(ptr, buf_len-(ptr-buf), ":%02x", c);
5317 /* By default, use the fvalue's "to_string_repr" method. */
5319 /* Figure out the string length needed.
5320 * The ft_repr length.
5321 * 4 bytes for " == ".
5322 * 1 byte for trailing NUL.
5324 dfilter_len = fvalue_string_repr_len(&finfo->value,
5326 dfilter_len += abbrev_len + 4 + 1;
5327 buf = ep_alloc0(dfilter_len);
5329 /* Create the string */
5330 g_snprintf(buf, dfilter_len, "%s == ", hfinfo->abbrev);
5331 fvalue_to_string_repr(&finfo->value,
5333 &buf[abbrev_len + 4]);