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);
2647 /* Add a field_info struct to the proto_tree, encapsulating it in a proto_node */
2649 proto_tree_add_node(proto_tree *tree, field_info *fi)
2651 proto_node *pnode, *tnode, *sibling;
2655 * Make sure "tree" is ready to have subtrees under it, by
2656 * checking whether it's been given an ett_ value.
2658 * "tnode->finfo" may be null; that's the case for the root
2659 * node of the protocol tree. That node is not displayed,
2660 * so it doesn't need an ett_ value to remember whether it
2665 if (tfi != NULL && (tfi->tree_type < 0 || tfi->tree_type >= num_tree_types)) {
2666 REPORT_DISSECTOR_BUG(ep_strdup_printf("\"%s\" - \"%s\" tfi->tree_type: %u invalid (%s:%u)",
2667 fi->hfinfo->name, fi->hfinfo->abbrev, tfi->tree_type, __FILE__, __LINE__));
2668 /* XXX - is it safe to continue here? */
2671 DISSECTOR_ASSERT(tfi == NULL ||
2672 (tfi->tree_type >= 0 && tfi->tree_type < num_tree_types));
2674 PROTO_NODE_NEW(pnode);
2675 pnode->parent = tnode;
2677 pnode->tree_data = PTREE_DATA(tree);
2679 if (tnode->last_child != NULL) {
2680 sibling = tnode->last_child;
2681 DISSECTOR_ASSERT(sibling->next == NULL);
2682 sibling->next = pnode;
2684 tnode->first_child = pnode;
2685 tnode->last_child = pnode;
2687 return (proto_item*)pnode;
2691 /* Generic way to allocate field_info and add to proto_tree.
2692 * Sets *pfi to address of newly-allocated field_info struct, if pfi is
2695 proto_tree_add_pi(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2696 gint *length, field_info **pfi)
2706 fi = alloc_field_info(tree, hfindex, tvb, start, length);
2707 pi = proto_tree_add_node(tree, fi);
2709 /* If the proto_tree wants to keep a record of this finfo
2710 * for quick lookup, then record it. */
2711 if (fi->hfinfo->ref_count) {
2713 hash = PTREE_DATA(tree)->interesting_hfids;
2714 ptrs = g_hash_table_lookup(hash, GINT_TO_POINTER(hfindex));
2716 g_ptr_array_add(ptrs, fi);
2720 /* Does the caller want to know the fi pointer? */
2729 static header_field_info *
2730 get_hfi_and_length(int hfindex, tvbuff_t *tvb, gint start, gint *length,
2733 header_field_info *hfinfo;
2734 gint length_remaining;
2737 * We only allow a null tvbuff if the item has a zero length,
2738 * i.e. if there's no data backing it.
2740 DISSECTOR_ASSERT(tvb != NULL || *length == 0);
2742 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2745 * XXX - in some protocols, there are 32-bit unsigned length
2746 * fields, so lengths in protocol tree and tvbuff routines
2747 * should really be unsigned. We should have, for those
2748 * field types for which "to the end of the tvbuff" makes sense,
2749 * additional routines that take no length argument and
2750 * add fields that run to the end of the tvbuff.
2752 if (*length == -1) {
2754 * For FT_NONE, FT_PROTOCOL, FT_BYTES, and FT_STRING fields,
2755 * a length of -1 means "set the length to what remains in
2758 * The assumption is either that
2760 * 1) the length of the item can only be determined
2761 * by dissection (typically true of items with
2762 * subitems, which are probably FT_NONE or
2767 * 2) if the tvbuff is "short" (either due to a short
2768 * snapshot length or due to lack of reassembly of
2769 * fragments/segments/whatever), we want to display
2770 * what's available in the field (probably FT_BYTES
2771 * or FT_STRING) and then throw an exception later
2775 * 3) the field is defined to be "what's left in the
2778 * so we set the length to what remains in the tvbuff so
2779 * that, if we throw an exception while dissecting, it
2780 * has what is probably the right value.
2782 * For FT_STRINGZ, it means "the string is null-terminated,
2783 * not null-padded; set the length to the actual length
2784 * of the string", and if the tvbuff if short, we just
2785 * throw an exception.
2787 * It's not valid for any other type of field.
2789 switch (hfinfo->type) {
2793 * We allow this to be zero-length - for
2794 * example, an ONC RPC NULL procedure has
2795 * neither arguments nor reply, so the
2796 * payload for that protocol is empty.
2798 * However, if the length is negative, the
2799 * start offset is *past* the byte past the
2800 * end of the tvbuff, so we throw an
2803 *length = tvb_length_remaining(tvb, start);
2806 * Use "tvb_ensure_bytes_exist()"
2807 * to force the appropriate exception
2810 tvb_ensure_bytes_exist(tvb, start, 0);
2812 DISSECTOR_ASSERT(*length >= 0);
2818 *length = tvb_ensure_length_remaining(tvb, start);
2819 DISSECTOR_ASSERT(*length >= 0);
2824 * Leave the length as -1, so our caller knows
2830 DISSECTOR_ASSERT_NOT_REACHED();
2832 *item_length = *length;
2834 *item_length = *length;
2835 if (hfinfo->type == FT_PROTOCOL || hfinfo->type == FT_NONE) {
2837 * These types are for interior nodes of the
2838 * tree, and don't have data associated with
2839 * them; if the length is negative (XXX - see
2840 * above) or goes past the end of the tvbuff,
2841 * cut it short at the end of the tvbuff.
2842 * That way, if this field is selected in
2843 * Wireshark, we don't highlight stuff past
2844 * the end of the data.
2846 /* XXX - what to do, if we don't have a tvb? */
2848 length_remaining = tvb_length_remaining(tvb, start);
2849 if (*item_length < 0 ||
2850 (*item_length > 0 &&
2851 (length_remaining < *item_length)))
2852 *item_length = length_remaining;
2855 if (*item_length < 0) {
2856 THROW(ReportedBoundsError);
2864 new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
2865 gint start, gint item_length)
2871 fi->hfinfo = hfinfo;
2873 fi->start+=(tvb)?TVB_RAW_OFFSET(tvb):0;
2874 fi->length = item_length;
2877 if (!PTREE_DATA(tree)->visible)
2878 FI_SET_FLAG(fi, FI_HIDDEN);
2879 fvalue_init(&fi->value, fi->hfinfo->type);
2882 /* add the data source tvbuff */
2883 fi->ds_tvb=tvb?TVB_GET_DS_TVB(tvb):NULL;
2889 alloc_field_info(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2892 header_field_info *hfinfo;
2895 hfinfo = get_hfi_and_length(hfindex, tvb, start, length, &item_length);
2896 return new_field_info(tree, hfinfo, tvb, start, item_length);
2899 /* If the protocol tree is to be visible, set the representation of a
2900 proto_tree entry with the name of the field for the item and with
2901 the value formatted with the supplied printf-style format and
2904 proto_tree_set_representation_value(proto_item *pi, const char *format, va_list ap)
2906 int ret; /*tmp return value */
2908 field_info *fi = PITEM_FINFO(pi);
2910 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
2911 ITEM_LABEL_NEW(fi->rep);
2913 ret = g_snprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
2914 "%s: ", fi->hfinfo->name);
2915 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH)) {
2916 /* That's all we can put in the representation. */
2917 fi->rep->representation[ITEM_LABEL_LENGTH - 1] = '\0';
2921 ret = g_vsnprintf(fi->rep->representation + replen,
2922 ITEM_LABEL_LENGTH - replen, format, ap);
2923 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH - replen))
2924 fi->rep->representation[ITEM_LABEL_LENGTH - 1] = '\0';
2928 /* If the protocol tree is to be visible, set the representation of a
2929 proto_tree entry with the representation formatted with the supplied
2930 printf-style format and argument list. */
2932 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap)
2934 int ret; /*tmp return value */
2935 field_info *fi = PITEM_FINFO(pi);
2937 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
2938 ITEM_LABEL_NEW(fi->rep);
2939 ret = g_vsnprintf(fi->rep->representation, ITEM_LABEL_LENGTH, format, ap);
2940 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
2941 fi->rep->representation[ITEM_LABEL_LENGTH - 1] = '\0';
2945 /* Set text of proto_item after having already been created. */
2947 proto_item_set_text(proto_item *pi, const char *format, ...)
2949 field_info *fi = NULL;
2956 fi = PITEM_FINFO(pi);
2959 ITEM_LABEL_FREE(fi->rep);
2962 va_start(ap, format);
2963 proto_tree_set_representation(pi, format, ap);
2967 /* Append to text of proto_item after having already been created. */
2969 proto_item_append_text(proto_item *pi, const char *format, ...)
2971 field_info *fi = NULL;
2974 int ret; /*tmp return value */
2980 fi = PITEM_FINFO(pi);
2982 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
2983 va_start(ap, format);
2986 * If we don't already have a representation,
2987 * generate the default representation.
2989 if (fi->rep == NULL) {
2990 ITEM_LABEL_NEW(fi->rep);
2991 proto_item_fill_label(fi, fi->rep->representation);
2994 curlen = strlen(fi->rep->representation);
2995 if (ITEM_LABEL_LENGTH > curlen) {
2996 ret = g_vsnprintf(fi->rep->representation + curlen,
2997 ITEM_LABEL_LENGTH - curlen, format, ap);
2998 if ((ret == -1) || (ret >= (int)(ITEM_LABEL_LENGTH - curlen)))
2999 fi->rep->representation[ITEM_LABEL_LENGTH - 1] = '\0';
3006 proto_item_set_len(proto_item *pi, gint length)
3012 fi = PITEM_FINFO(pi);
3013 DISSECTOR_ASSERT(length >= 0);
3014 fi->length = length;
3018 * Sets the length of the item based on its start and on the specified
3019 * offset, which is the offset past the end of the item; as the start
3020 * in the item is relative to the beginning of the data source tvbuff,
3021 * we need to pass in a tvbuff - the end offset is relative to the beginning
3025 proto_item_set_end(proto_item *pi, tvbuff_t *tvb, gint end)
3031 fi = PITEM_FINFO(pi);
3032 end += TVB_RAW_OFFSET(tvb);
3033 DISSECTOR_ASSERT(end >= fi->start);
3034 fi->length = end - fi->start;
3038 proto_item_get_len(proto_item *pi)
3040 field_info *fi = PITEM_FINFO(pi);
3045 /** clear flags according to the mask and set new flag values */
3046 #define FI_REPLACE_FLAGS(fi, mask, flags_in) { \
3047 (fi->flags = (fi)->flags & ~(mask)); \
3048 (fi->flags = (fi)->flags | (flags_in)); \
3052 proto_item_set_expert_flags(proto_item *pi, int group, int severity)
3054 if(pi == NULL || pi->finfo == NULL)
3057 /* only change things if severity is worse or at least equal than before */
3058 if(severity >= FI_GET_FLAG(pi->finfo, PI_SEVERITY_MASK)) {
3059 FI_REPLACE_FLAGS(pi->finfo, PI_GROUP_MASK, group);
3060 FI_REPLACE_FLAGS(pi->finfo, PI_SEVERITY_MASK, severity);
3071 proto_tree_create_root(void)
3075 /* Initialize the proto_node */
3076 PROTO_NODE_NEW(pnode);
3077 pnode->parent = NULL;
3078 pnode->finfo = NULL;
3079 pnode->tree_data = g_new(tree_data_t, 1);
3081 /* Initialize the tree_data_t */
3082 pnode->tree_data->interesting_hfids =
3083 g_hash_table_new(g_direct_hash, g_direct_equal);
3085 /* Set the default to FALSE so it's easier to
3086 * find errors; if we expect to see the protocol tree
3087 * but for some reason the default 'visible' is not
3088 * changed, then we'll find out very quickly. */
3089 pnode->tree_data->visible = FALSE;
3091 return (proto_tree*) pnode;
3095 /* "prime" a proto_tree with a single hfid that a dfilter
3096 * is interested in. */
3098 proto_tree_prime_hfid(proto_tree *tree, gint hfid)
3100 header_field_info *hfinfo;
3102 g_hash_table_insert(PTREE_DATA(tree)->interesting_hfids,
3103 GINT_TO_POINTER(hfid), g_ptr_array_new());
3105 PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
3106 /* this field is referenced by a filter so increase the refcount.
3107 also increase the refcount for the parent, i.e the protocol.
3109 hfinfo->ref_count++;
3110 /* only increase the refcount if there is a parent.
3111 if this is a protocol and not a field then parent will be -1
3112 and there is no parent to add any refcounting for.
3114 if (hfinfo->parent != -1) {
3115 header_field_info *parent_hfinfo;
3116 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
3117 parent_hfinfo->ref_count++;
3122 proto_item_add_subtree(proto_item *pi, gint idx) {
3128 fi = PITEM_FINFO(pi);
3129 DISSECTOR_ASSERT(idx >= 0 && idx < num_tree_types);
3130 fi->tree_type = idx;
3132 return (proto_tree*) pi;
3136 proto_item_get_subtree(proto_item *pi) {
3141 fi = PITEM_FINFO(pi);
3142 if ( (!fi) || (fi->tree_type == -1) )
3144 return (proto_tree*) pi;
3148 proto_item_get_parent(proto_item *ti) {
3149 /* dont bother if tree is not visible */
3150 if( (!ti) || (!(PTREE_DATA(ti)->visible)) )
3156 proto_item_get_parent_nth(proto_item *ti, int gen) {
3157 /* dont bother if tree is not visible */
3158 if( (!ti) || (!(PTREE_DATA(ti)->visible)) )
3170 proto_tree_get_parent(proto_tree *tree) {
3171 /* dont bother if tree is not visible */
3172 if( (!tree) || (!(PTREE_DATA(tree)->visible)) )
3174 return (proto_item*) tree;
3179 proto_tree_move_item(proto_tree *tree, proto_item *fixed_item, proto_item *item_to_move)
3181 proto_item *curr_item;
3184 /*** cut item_to_move out ***/
3186 /* is item_to_move the first? */
3187 if(tree->first_child == item_to_move) {
3188 /* simply change first child to next */
3189 tree->first_child = item_to_move->next;
3191 /* find previous and change it's next */
3192 for(curr_item = tree->first_child; curr_item != NULL; curr_item = curr_item->next) {
3193 if(curr_item->next == item_to_move) {
3198 DISSECTOR_ASSERT(curr_item);
3200 curr_item->next = item_to_move->next;
3202 /* fix last_child if required */
3203 if(tree->last_child == item_to_move) {
3204 tree->last_child = curr_item;
3208 /*** insert to_move after fixed ***/
3209 item_to_move->next = fixed_item->next;
3210 fixed_item->next = item_to_move;
3211 if(tree->last_child == fixed_item) {
3212 tree->last_child = item_to_move;
3218 proto_register_protocol(const char *name, const char *short_name, const char *filter_name)
3220 protocol_t *protocol;
3221 header_field_info *hfinfo;
3223 char *existing_name;
3227 gboolean found_invalid;
3230 * Make sure there's not already a protocol with any of those
3231 * names. Crash if there is, as that's an error in the code
3232 * or an inappropriate plugin.
3233 * This situation has to be fixed to not register more than one
3234 * protocol with the same name.
3236 * This is done by reducing the number of strcmp (and alike) calls as much as possible,
3237 * as this significally slows down startup time.
3239 * Drawback: As a hash value is used to reduce insert time,
3240 * this might lead to a hash collision.
3241 * However, as we have around 500+ protocols and we're using a 32 bit int this is very,
3245 key = g_malloc (sizeof(gint));
3246 *key = g_str_hash(name);
3247 existing_name = g_hash_table_lookup(proto_names, key);
3248 if (existing_name != NULL) {
3249 /* g_error will terminate the program */
3250 g_error("Duplicate protocol name \"%s\"!"
3251 " This might be caused by an inappropriate plugin or a development error.", name);
3253 g_hash_table_insert(proto_names, key, (gpointer)name);
3255 key = g_malloc (sizeof(gint));
3256 *key = g_str_hash(short_name);
3257 existing_name = g_hash_table_lookup(proto_short_names, key);
3258 if (existing_name != NULL) {
3259 g_error("Duplicate protocol short_name \"%s\"!"
3260 " This might be caused by an inappropriate plugin or a development error.", short_name);
3262 g_hash_table_insert(proto_short_names, key, (gpointer)short_name);
3264 found_invalid = FALSE;
3265 for (i = 0; i < strlen(filter_name); i++) {
3267 if (!(islower(c) || isdigit(c) || c == '-' || c == '_' || c == '.')) {
3268 found_invalid = TRUE;
3271 if (found_invalid) {
3272 g_error("Protocol filter name \"%s\" has one or more invalid characters."
3273 " Allowed are lower characters, digits, '-', '_' and '.'."
3274 " This might be caused by an inappropriate plugin or a development error.", filter_name);
3276 key = g_malloc (sizeof(gint));
3277 *key = g_str_hash(filter_name);
3278 existing_name = g_hash_table_lookup(proto_filter_names, key);
3279 if (existing_name != NULL) {
3280 g_error("Duplicate protocol filter_name \"%s\"!"
3281 " This might be caused by an inappropriate plugin or a development error.", filter_name);
3283 g_hash_table_insert(proto_filter_names, key, (gpointer)filter_name);
3285 /* Add this protocol to the list of known protocols; the list
3286 is sorted by protocol short name. */
3287 protocol = g_malloc(sizeof (protocol_t));
3288 protocol->name = name;
3289 protocol->short_name = short_name;
3290 protocol->filter_name = filter_name;
3291 protocol->fields = NULL;
3292 protocol->is_enabled = TRUE; /* protocol is enabled by default */
3293 protocol->can_toggle = TRUE;
3294 /* list will be sorted later by name, when all protocols completed registering */
3295 protocols = g_list_append(protocols, protocol);
3297 /* Here we do allocate a new header_field_info struct */
3298 hfinfo = g_mem_chunk_alloc(gmc_hfinfo);
3299 hfinfo->name = name;
3300 hfinfo->abbrev = filter_name;
3301 hfinfo->type = FT_PROTOCOL;
3302 hfinfo->strings = protocol;
3303 hfinfo->bitmask = 0;
3304 hfinfo->bitshift = 0;
3305 hfinfo->ref_count = 0;
3306 hfinfo->blurb = NULL;
3307 hfinfo->parent = -1; /* this field differentiates protos and fields */
3309 proto_id = proto_register_field_init(hfinfo, hfinfo->parent);
3310 protocol->proto_id = proto_id;
3315 * Routines to use to iterate over the protocols.
3316 * The argument passed to the iterator routines is an opaque cookie to
3317 * their callers; it's the GList pointer for the current element in
3319 * The ID of the protocol is returned, or -1 if there is no protocol.
3322 proto_get_first_protocol(void **cookie)
3324 protocol_t *protocol;
3326 if (protocols == NULL)
3328 *cookie = protocols;
3329 protocol = protocols->data;
3330 return protocol->proto_id;
3334 proto_get_next_protocol(void **cookie)
3336 GList *list_item = *cookie;
3337 protocol_t *protocol;
3339 list_item = g_list_next(list_item);
3340 if (list_item == NULL)
3342 *cookie = list_item;
3343 protocol = list_item->data;
3344 return protocol->proto_id;
3348 proto_get_first_protocol_field(int proto_id, void **cookie)
3350 protocol_t *protocol = find_protocol_by_id(proto_id);
3351 hf_register_info *ptr;
3353 if ((protocol == NULL) || (protocol->fields == NULL))
3356 *cookie = protocol->fields;
3357 ptr = protocol->fields->data;
3358 return &ptr->hfinfo;
3362 proto_get_next_protocol_field(void **cookie)
3364 GList *list_item = *cookie;
3365 hf_register_info *ptr;
3367 list_item = g_list_next(list_item);
3368 if (list_item == NULL)
3371 *cookie = list_item;
3372 ptr = list_item->data;
3373 return &ptr->hfinfo;
3377 find_protocol_by_id(int proto_id)
3379 header_field_info *hfinfo;
3384 PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
3385 DISSECTOR_ASSERT(hfinfo->type==FT_PROTOCOL);
3386 return (protocol_t *)hfinfo->strings;
3389 static gint compare_filter_name(gconstpointer proto_arg,
3390 gconstpointer filter_name)
3392 const protocol_t *protocol = proto_arg;
3393 const gchar* f_name = filter_name;
3395 return (strcmp(protocol->filter_name, f_name));
3399 proto_get_id(protocol_t *protocol)
3401 return protocol->proto_id;
3404 int proto_get_id_by_filter_name(const gchar* filter_name)
3407 protocol_t *protocol;
3409 list_entry = g_list_find_custom(protocols, filter_name,
3410 compare_filter_name);
3411 if (list_entry == NULL)
3413 protocol = list_entry->data;
3414 return protocol->proto_id;
3418 proto_get_protocol_name(int proto_id)
3420 protocol_t *protocol;
3422 protocol = find_protocol_by_id(proto_id);
3423 return protocol->name;
3427 proto_get_protocol_short_name(protocol_t *protocol)
3429 if (protocol == NULL)
3431 return protocol->short_name;
3435 proto_get_protocol_filter_name(int proto_id)
3437 protocol_t *protocol;
3439 protocol = find_protocol_by_id(proto_id);
3440 return protocol->filter_name;
3444 proto_is_protocol_enabled(protocol_t *protocol)
3446 return protocol->is_enabled;
3450 proto_can_toggle_protocol(int proto_id)
3452 protocol_t *protocol;
3454 protocol = find_protocol_by_id(proto_id);
3455 return protocol->can_toggle;
3459 proto_set_decoding(int proto_id, gboolean enabled)
3461 protocol_t *protocol;
3463 protocol = find_protocol_by_id(proto_id);
3464 DISSECTOR_ASSERT(protocol->can_toggle);
3465 protocol->is_enabled = enabled;
3469 proto_set_cant_toggle(int proto_id)
3471 protocol_t *protocol;
3473 protocol = find_protocol_by_id(proto_id);
3474 protocol->can_toggle = FALSE;
3477 /* for use with static arrays only, since we don't allocate our own copies
3478 of the header_field_info struct contained within the hf_register_info struct */
3480 proto_register_field_array(int parent, hf_register_info *hf, int num_records)
3483 hf_register_info *ptr = hf;
3486 proto = find_protocol_by_id(parent);
3487 for (i = 0; i < num_records; i++, ptr++) {
3489 * Make sure we haven't registered this yet.
3490 * Most fields have variables associated with them
3491 * that are initialized to -1; some have array elements,
3492 * or possibly uninitialized variables, so we also allow
3493 * 0 (which is unlikely to be the field ID we get back
3494 * from "proto_register_field_init()").
3496 if (*ptr->p_id != -1 && *ptr->p_id != 0) {
3498 "Duplicate field detected in call to proto_register_field_array: %s is already registered\n",
3499 ptr->hfinfo.abbrev);
3503 if (proto != NULL) {
3504 if (proto->fields == NULL) {
3505 proto->fields = g_list_append(NULL, ptr);
3506 proto->last_field = proto->fields;
3509 g_list_append(proto->last_field, ptr)->next;
3512 field_id = proto_register_field_init(&ptr->hfinfo, parent);
3513 *ptr->p_id = field_id;
3518 proto_register_field_init(header_field_info *hfinfo, int parent)
3520 /* The field must have names */
3521 DISSECTOR_ASSERT(hfinfo->name);
3522 DISSECTOR_ASSERT(hfinfo->abbrev);
3524 /* These types of fields are allowed to have value_strings, true_false_strings or a protocol_t struct*/
3525 DISSECTOR_ASSERT((hfinfo->strings == NULL) || (
3526 (hfinfo->type == FT_UINT8) ||
3527 (hfinfo->type == FT_UINT16) ||
3528 (hfinfo->type == FT_UINT24) ||
3529 (hfinfo->type == FT_UINT32) ||
3530 (hfinfo->type == FT_INT8) ||
3531 (hfinfo->type == FT_INT16) ||
3532 (hfinfo->type == FT_INT24) ||
3533 (hfinfo->type == FT_INT32) ||
3534 (hfinfo->type == FT_BOOLEAN) ||
3535 (hfinfo->type == FT_PROTOCOL) ||
3536 (hfinfo->type == FT_FRAMENUM) ));
3538 switch (hfinfo->type) {
3548 /* Require integral types (other than frame number, which is
3549 always displayed in decimal) to have a number base */
3550 DISSECTOR_ASSERT(hfinfo->display != BASE_NONE);
3554 /* Don't allow bitfields or value strings for frame numbers */
3555 DISSECTOR_ASSERT(hfinfo->bitmask == 0);
3556 DISSECTOR_ASSERT(hfinfo->strings == NULL);
3562 /* if this is a bitfield, compute bitshift */
3563 if (hfinfo->bitmask) {
3564 while ((hfinfo->bitmask & (1 << hfinfo->bitshift)) == 0)
3568 hfinfo->parent = parent;
3569 hfinfo->same_name_next = NULL;
3570 hfinfo->same_name_prev = NULL;
3572 /* if we always add and never delete, then id == len - 1 is correct */
3573 if(gpa_hfinfo.len>=gpa_hfinfo.allocated_len){
3574 if(!gpa_hfinfo.hfi){
3575 gpa_hfinfo.allocated_len=1000;
3576 gpa_hfinfo.hfi=g_malloc(sizeof(header_field_info *)*1000);
3578 gpa_hfinfo.allocated_len+=1000;
3579 gpa_hfinfo.hfi=g_realloc(gpa_hfinfo.hfi, sizeof(header_field_info *)*gpa_hfinfo.allocated_len);
3582 gpa_hfinfo.hfi[gpa_hfinfo.len]=hfinfo;
3584 hfinfo->id = gpa_hfinfo.len - 1;
3586 /* if we have real names, enter this field in the name tree */
3587 if ((hfinfo->name[0] != 0) && (hfinfo->abbrev[0] != 0 )) {
3589 header_field_info *same_name_hfinfo, *same_name_next_hfinfo;
3593 /* Check that the filter name (abbreviation) is legal;
3594 * it must contain only alphanumerics, '-', "_", and ".". */
3595 for (p = hfinfo->abbrev; (c = *p) != '\0'; p++) {
3596 if (!(isalnum(c) || c == '-' || c == '_' || c == '.')) {
3597 fprintf(stderr, "OOPS: '%c' in '%s'\n", c, hfinfo->abbrev);
3598 DISSECTOR_ASSERT(isalnum(c) || c == '-' || c == '_' ||
3602 /* We allow multiple hfinfo's to be registered under the same
3603 * abbreviation. This was done for X.25, as, depending
3604 * on whether it's modulo-8 or modulo-128 operation,
3605 * some bitfield fields may be in different bits of
3606 * a byte, and we want to be able to refer to that field
3607 * with one name regardless of whether the packets
3608 * are modulo-8 or modulo-128 packets. */
3609 same_name_hfinfo = g_tree_lookup(gpa_name_tree, hfinfo->abbrev);
3610 if (same_name_hfinfo) {
3611 /* There's already a field with this name.
3612 * Put it after that field in the list of
3613 * fields with this name, then allow the code
3614 * after this if{} block to replace the old
3615 * hfinfo with the new hfinfo in the GTree. Thus,
3616 * we end up with a linked-list of same-named hfinfo's,
3617 * with the root of the list being the hfinfo in the GTree */
3618 same_name_next_hfinfo =
3619 same_name_hfinfo->same_name_next;
3621 hfinfo->same_name_next = same_name_next_hfinfo;
3622 if (same_name_next_hfinfo)
3623 same_name_next_hfinfo->same_name_prev = hfinfo;
3625 same_name_hfinfo->same_name_next = hfinfo;
3626 hfinfo->same_name_prev = same_name_hfinfo;
3628 g_tree_insert(gpa_name_tree, (gpointer) (hfinfo->abbrev), hfinfo);
3635 proto_register_subtree_array(gint *const *indices, int num_indices)
3638 gint *const *ptr = indices;
3641 * If we've already allocated the array of tree types, expand
3642 * it; this lets plugins such as mate add tree types after
3643 * the initial startup. (If we haven't already allocated it,
3644 * we don't allocate it; on the first pass, we just assign
3645 * ett values and keep track of how many we've assigned, and
3646 * when we're finished registering all dissectors we allocate
3647 * the array, so that we do only one allocation rather than
3648 * wasting CPU time and memory by growing the array for each
3649 * dissector that registers ett values.)
3651 if (tree_is_expanded != NULL) {
3653 g_realloc(tree_is_expanded,
3654 (num_tree_types+num_indices)*sizeof (gboolean));
3655 memset(tree_is_expanded + num_tree_types, 0,
3656 num_indices*sizeof (gboolean));
3660 * Assign "num_indices" subtree numbers starting at "num_tree_types",
3661 * returning the indices through the pointers in the array whose
3662 * first element is pointed to by "indices", and update
3663 * "num_tree_types" appropriately.
3665 for (i = 0; i < num_indices; i++, ptr++, num_tree_types++)
3666 **ptr = num_tree_types;
3670 proto_item_fill_label(field_info *fi, gchar *label_str)
3672 header_field_info *hfinfo = fi->hfinfo;
3678 guint32 n_addr; /* network-order IPv4 address */
3680 int ret; /*tmp return value */
3682 switch(hfinfo->type) {
3685 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3686 "%s", hfinfo->name);
3687 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3688 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3692 fill_label_boolean(fi, label_str);
3697 bytes = fvalue_get(&fi->value);
3699 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3700 "%s: %s", hfinfo->name,
3701 bytes_to_str(bytes, fvalue_length(&fi->value)));
3702 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3703 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3706 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3707 "%s: <MISSING>", hfinfo->name);
3708 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3709 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3713 /* Four types of integers to take care of:
3714 * Bitfield, with val_string
3715 * Bitfield, w/o val_string
3716 * Non-bitfield, with val_string
3717 * Non-bitfield, w/o val_string
3724 if (hfinfo->bitmask) {
3725 if (hfinfo->strings) {
3726 fill_label_enumerated_bitfield(fi, label_str);
3729 fill_label_numeric_bitfield(fi, label_str);
3733 if (hfinfo->strings) {
3734 fill_label_enumerated_uint(fi, label_str);
3737 fill_label_uint(fi, label_str);
3743 fill_label_uint64(fi, label_str);
3750 DISSECTOR_ASSERT(!hfinfo->bitmask);
3751 if (hfinfo->strings) {
3752 fill_label_enumerated_int(fi, label_str);
3755 fill_label_int(fi, label_str);
3760 fill_label_int64(fi, label_str);
3764 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3765 "%s: %." STRINGIFY(FLT_DIG) "f",
3766 hfinfo->name, fvalue_get_floating(&fi->value));
3767 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3768 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3772 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3773 "%s: %." STRINGIFY(DBL_DIG) "g",
3774 hfinfo->name, fvalue_get_floating(&fi->value));
3775 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3776 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3779 case FT_ABSOLUTE_TIME:
3780 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3781 "%s: %s", hfinfo->name,
3782 abs_time_to_str(fvalue_get(&fi->value)));
3783 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3784 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3787 case FT_RELATIVE_TIME:
3788 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3789 "%s: %s seconds", hfinfo->name,
3790 rel_time_to_secs_str(fvalue_get(&fi->value)));
3791 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3792 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3796 integer = fvalue_get_integer(&fi->value);
3797 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3798 "%s: %s (0x%08X)", hfinfo->name,
3799 get_ipxnet_name(integer), integer);
3800 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3801 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3805 bytes = fvalue_get(&fi->value);
3806 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3807 "%s: %s (%s)", hfinfo->name,
3808 get_ether_name(bytes),
3809 ether_to_str(bytes));
3810 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3811 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3815 ipv4 = fvalue_get(&fi->value);
3816 n_addr = ipv4_get_net_order_addr(ipv4);
3817 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3818 "%s: %s (%s)", hfinfo->name,
3819 get_hostname(n_addr),
3820 ip_to_str((guint8*)&n_addr));
3821 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3822 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3826 bytes = fvalue_get(&fi->value);
3827 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3828 "%s: %s (%s)", hfinfo->name,
3829 get_hostname6((struct e_in6_addr *)bytes),
3830 ip6_to_str((struct e_in6_addr*)bytes));
3831 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3832 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3836 guid = fvalue_get(&fi->value);
3837 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3838 "%s: %s", hfinfo->name,
3840 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3841 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3845 bytes = fvalue_get(&fi->value);
3846 name = (oid_resolv_enabled()) ? get_oid_name(bytes, fvalue_length(&fi->value)) : NULL;
3848 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3849 "%s: %s (%s)", hfinfo->name,
3850 oid_to_str(bytes, fvalue_length(&fi->value)), name);
3852 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3853 "%s: %s", hfinfo->name,
3854 oid_to_str(bytes, fvalue_length(&fi->value)));
3856 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3857 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3862 case FT_UINT_STRING:
3863 bytes = fvalue_get(&fi->value);
3864 if(strlen(bytes) > ITEM_LABEL_LENGTH) {
3865 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3866 "%s [truncated]: %s", hfinfo->name,
3867 format_text(bytes, strlen(bytes)));
3869 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3870 "%s: %s", hfinfo->name,
3871 format_text(bytes, strlen(bytes)));
3873 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3874 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3878 g_error("hfinfo->type %d (%s) not handled\n",
3880 ftype_name(hfinfo->type));
3881 DISSECTOR_ASSERT_NOT_REACHED();
3887 fill_label_boolean(field_info *fi, gchar *label_str)
3889 char *p = label_str;
3890 int bitfield_byte_length = 0, bitwidth;
3891 guint32 unshifted_value;
3893 int ret; /*tmp return value */
3895 header_field_info *hfinfo = fi->hfinfo;
3896 static const true_false_string default_tf = { "True", "False" };
3897 const true_false_string *tfstring = &default_tf;
3899 if (hfinfo->strings) {
3900 tfstring = (const struct true_false_string*) hfinfo->strings;
3903 value = fvalue_get_integer(&fi->value);
3904 if (hfinfo->bitmask) {
3905 /* Figure out the bit width */
3906 bitwidth = hfinfo_bitwidth(hfinfo);
3909 unshifted_value = value;
3910 if (hfinfo->bitshift > 0) {
3911 unshifted_value <<= hfinfo->bitshift;
3914 /* Create the bitfield first */
3915 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
3916 bitfield_byte_length = p - label_str;
3919 /* Fill in the textual info */
3920 ret = g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
3921 "%s: %s", hfinfo->name,
3922 value ? tfstring->true_string : tfstring->false_string);
3923 if ((ret == -1) || (ret >= (ITEM_LABEL_LENGTH - bitfield_byte_length)))
3924 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3928 /* Fills data for bitfield ints with val_strings */
3930 fill_label_enumerated_bitfield(field_info *fi, gchar *label_str)
3932 const char *format = NULL;
3934 int bitfield_byte_length, bitwidth;
3935 guint32 unshifted_value;
3937 int ret; /*tmp return value */
3939 header_field_info *hfinfo = fi->hfinfo;
3941 /* Figure out the bit width */
3942 bitwidth = hfinfo_bitwidth(hfinfo);
3944 /* Pick the proper format string */
3945 format = hfinfo_uint_vals_format(hfinfo);
3948 unshifted_value = fvalue_get_integer(&fi->value);
3949 value = unshifted_value;
3950 if (hfinfo->bitshift > 0) {
3951 unshifted_value <<= hfinfo->bitshift;
3954 /* Create the bitfield first */
3955 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
3956 bitfield_byte_length = p - label_str;
3958 /* Fill in the textual info using stored (shifted) value */
3959 ret = g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
3960 format, hfinfo->name,
3961 val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
3962 if ((ret == -1) || (ret >= (ITEM_LABEL_LENGTH - bitfield_byte_length)))
3963 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3967 fill_label_numeric_bitfield(field_info *fi, gchar *label_str)
3969 const char *format = NULL;
3971 int bitfield_byte_length, bitwidth;
3972 guint32 unshifted_value;
3974 int ret; /*tmp return value */
3976 header_field_info *hfinfo = fi->hfinfo;
3978 /* Figure out the bit width */
3979 bitwidth = hfinfo_bitwidth(hfinfo);
3981 /* Pick the proper format string */
3982 format = hfinfo_uint_format(hfinfo);
3985 unshifted_value = fvalue_get_integer(&fi->value);
3986 value = unshifted_value;
3987 if (hfinfo->bitshift > 0) {
3988 unshifted_value <<= hfinfo->bitshift;
3991 /* Create the bitfield using */
3992 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
3993 bitfield_byte_length = p - label_str;
3995 /* Fill in the textual info using stored (shifted) value */
3996 if (IS_BASE_DUAL(hfinfo->display)) {
3997 ret = g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
3998 format, hfinfo->name, value, value);
4000 ret = g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
4001 format, hfinfo->name, value);
4003 if ((ret == -1) || (ret >= (ITEM_LABEL_LENGTH - bitfield_byte_length)))
4004 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4009 fill_label_enumerated_uint(field_info *fi, gchar *label_str)
4011 const char *format = NULL;
4012 header_field_info *hfinfo = fi->hfinfo;
4014 int ret; /*tmp return value */
4016 /* Pick the proper format string */
4017 format = hfinfo_uint_vals_format(hfinfo);
4019 value = fvalue_get_integer(&fi->value);
4021 /* Fill in the textual info */
4022 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4023 format, hfinfo->name,
4024 val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
4025 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4026 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4030 fill_label_uint(field_info *fi, gchar *label_str)
4032 const char *format = NULL;
4033 header_field_info *hfinfo = fi->hfinfo;
4035 int ret; /*tmp return value */
4037 /* Pick the proper format string */
4038 format = hfinfo_uint_format(hfinfo);
4039 value = fvalue_get_integer(&fi->value);
4041 /* Fill in the textual info */
4042 if (IS_BASE_DUAL(hfinfo->display)) {
4043 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4044 format, hfinfo->name, value, value);
4046 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4047 format, hfinfo->name, value);
4049 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4050 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4054 fill_label_uint64(field_info *fi, gchar *label_str)
4056 const char *format = NULL;
4057 header_field_info *hfinfo = fi->hfinfo;
4059 int ret; /*tmp return value */
4061 /* Pick the proper format string */
4062 format = hfinfo_uint64_format(hfinfo);
4063 value = fvalue_get_integer64(&fi->value);
4065 /* Fill in the textual info */
4066 if (IS_BASE_DUAL(hfinfo->display)) {
4067 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4068 format, hfinfo->name, value, value);
4070 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4071 format, hfinfo->name, value);
4073 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4074 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4078 fill_label_enumerated_int(field_info *fi, gchar *label_str)
4080 const char *format = NULL;
4081 header_field_info *hfinfo = fi->hfinfo;
4083 int ret; /*tmp return value */
4085 /* Pick the proper format string */
4086 format = hfinfo_int_vals_format(hfinfo);
4087 value = fvalue_get_integer(&fi->value);
4089 /* Fill in the textual info */
4090 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4091 format, hfinfo->name,
4092 val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
4093 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4094 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4098 fill_label_int(field_info *fi, gchar *label_str)
4100 const char *format = NULL;
4101 header_field_info *hfinfo = fi->hfinfo;
4103 int ret; /*tmp return value */
4105 /* Pick the proper format string */
4106 format = hfinfo_int_format(hfinfo);
4107 value = fvalue_get_integer(&fi->value);
4109 /* Fill in the textual info */
4110 if (IS_BASE_DUAL(hfinfo->display)) {
4111 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4112 format, hfinfo->name, value, value);
4114 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4115 format, hfinfo->name, value);
4117 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4118 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4122 fill_label_int64(field_info *fi, gchar *label_str)
4124 const char *format = NULL;
4125 header_field_info *hfinfo = fi->hfinfo;
4127 int ret; /*tmp return value */
4129 /* Pick the proper format string */
4130 format = hfinfo_int64_format(hfinfo);
4131 value = fvalue_get_integer64(&fi->value);
4133 /* Fill in the textual info */
4134 if (IS_BASE_DUAL(hfinfo->display)) {
4135 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4136 format, hfinfo->name, value, value);
4138 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4139 format, hfinfo->name, value);
4141 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4142 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4146 hfinfo_bitwidth(header_field_info *hfinfo)
4150 if (!hfinfo->bitmask) {
4154 switch(hfinfo->type) {
4172 bitwidth = hfinfo->display; /* hacky? :) */
4175 DISSECTOR_ASSERT_NOT_REACHED();
4182 hfinfo_uint_vals_format(header_field_info *hfinfo)
4184 const char *format = NULL;
4186 switch(hfinfo->display) {
4189 format = "%s: %s (%u)";
4191 case BASE_OCT: /* I'm lazy */
4192 format = "%s: %s (%o)";
4196 switch(hfinfo->type) {
4198 format = "%s: %s (0x%02x)";
4201 format = "%s: %s (0x%04x)";
4204 format = "%s: %s (0x%06x)";
4207 format = "%s: %s (0x%08x)";
4210 DISSECTOR_ASSERT_NOT_REACHED();
4215 DISSECTOR_ASSERT_NOT_REACHED();
4222 hfinfo_uint_format(header_field_info *hfinfo)
4224 const char *format = NULL;
4226 /* Pick the proper format string */
4227 if (hfinfo->type == FT_FRAMENUM) {
4229 * Frame numbers are always displayed in decimal.
4233 switch(hfinfo->display) {
4238 switch(hfinfo->type) {
4240 format = "%s: %u (0x%02x)";
4243 format = "%s: %u (0x%04x)";
4246 format = "%s: %u (0x%06x)";
4249 format = "%s: %u (0x%08x)";
4252 DISSECTOR_ASSERT_NOT_REACHED();
4256 case BASE_OCT: /* I'm lazy */
4260 switch(hfinfo->type) {
4262 format = "%s: 0x%02x";
4265 format = "%s: 0x%04x";
4268 format = "%s: 0x%06x";
4271 format = "%s: 0x%08x";
4274 DISSECTOR_ASSERT_NOT_REACHED();
4279 switch(hfinfo->type) {
4281 format = "%s: 0x%02x (%u)";
4284 format = "%s: 0x%04x (%u)";
4287 format = "%s: 0x%06x (%u)";
4290 format = "%s: 0x%08x (%u)";
4293 DISSECTOR_ASSERT_NOT_REACHED();
4298 DISSECTOR_ASSERT_NOT_REACHED();
4306 hfinfo_int_vals_format(header_field_info *hfinfo)
4308 const char *format = NULL;
4310 switch(hfinfo->display) {
4313 format = "%s: %s (%d)";
4315 case BASE_OCT: /* I'm lazy */
4316 format = "%s: %s (%o)";
4320 switch(hfinfo->type) {
4322 format = "%s: %s (0x%02x)";
4325 format = "%s: %s (0x%04x)";
4328 format = "%s: %s (0x%06x)";
4331 format = "%s: %s (0x%08x)";
4334 DISSECTOR_ASSERT_NOT_REACHED();
4339 DISSECTOR_ASSERT_NOT_REACHED();
4346 hfinfo_uint64_format(header_field_info *hfinfo)
4348 const char *format = NULL;
4350 /* Pick the proper format string */
4351 switch(hfinfo->display) {
4353 format = "%s: %" PRIu64;
4356 format = "%s: %" PRIu64 " (%" PRIx64 ")";
4358 case BASE_OCT: /* I'm lazy */
4359 format = "%s: %" PRIo64;
4362 format = "%s: 0x%016" PRIx64;
4365 format = "%s: 0x%016" PRIx64 " (%" PRIu64 ")";
4368 DISSECTOR_ASSERT_NOT_REACHED();
4375 hfinfo_int_format(header_field_info *hfinfo)
4377 const char *format = NULL;
4379 /* Pick the proper format string */
4380 switch(hfinfo->display) {
4385 switch(hfinfo->type) {
4387 format = "%s: %d (0x%02x)";
4390 format = "%s: %d (0x%04x)";
4393 format = "%s: %d (0x%06x)";
4396 format = "%s: %d (0x%08x)";
4399 DISSECTOR_ASSERT_NOT_REACHED();
4402 case BASE_OCT: /* I'm lazy */
4406 switch(hfinfo->type) {
4408 format = "%s: 0x%02x";
4411 format = "%s: 0x%04x";
4414 format = "%s: 0x%06x";
4417 format = "%s: 0x%08x";
4420 DISSECTOR_ASSERT_NOT_REACHED();
4425 switch(hfinfo->type) {
4427 format = "%s: 0x%02x (%d)";
4430 format = "%s: 0x%04x (%d)";
4433 format = "%s: 0x%06x (%d)";
4436 format = "%s: 0x%08x (%d)";
4439 DISSECTOR_ASSERT_NOT_REACHED();
4444 DISSECTOR_ASSERT_NOT_REACHED();
4451 hfinfo_int64_format(header_field_info *hfinfo)
4453 const char *format = NULL;
4455 /* Pick the proper format string */
4456 switch(hfinfo->display) {
4458 format = "%s: %" PRId64;
4461 format = "%s: %" PRId64 " (%" PRIx64 ")";
4463 case BASE_OCT: /* I'm lazy */
4464 format = "%s: %" PRIo64;
4467 format = "%s: 0x%016" PRIx64;
4470 format = "%s: 0x%016" PRIx64 " (%" PRId64 ")";
4473 DISSECTOR_ASSERT_NOT_REACHED();
4482 proto_registrar_n(void)
4484 return gpa_hfinfo.len;
4488 proto_registrar_get_name(int n)
4490 header_field_info *hfinfo;
4492 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
4493 return hfinfo->name;
4497 proto_registrar_get_abbrev(int n)
4499 header_field_info *hfinfo;
4501 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
4502 return hfinfo->abbrev;
4506 proto_registrar_get_ftype(int n)
4508 header_field_info *hfinfo;
4510 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
4511 return hfinfo->type;
4515 proto_registrar_get_parent(int n)
4517 header_field_info *hfinfo;
4519 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
4520 return hfinfo->parent;
4524 proto_registrar_is_protocol(int n)
4526 header_field_info *hfinfo;
4528 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
4529 return (hfinfo->parent == -1 ? TRUE : FALSE);
4532 /* Returns length of field in packet (not necessarily the length
4533 * in our internal representation, as in the case of IPv4).
4534 * 0 means undeterminable at time of registration
4535 * -1 means the field is not registered. */
4537 proto_registrar_get_length(int n)
4539 header_field_info *hfinfo;
4541 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
4542 return ftype_length(hfinfo->type);
4547 /* Looks for a protocol or a field in a proto_tree. Returns TRUE if
4548 * it exists anywhere, or FALSE if it exists nowhere. */
4550 proto_check_for_protocol_or_field(proto_tree* tree, int id)
4552 GPtrArray *ptrs = proto_get_finfo_ptr_array(tree, id);
4557 else if (g_ptr_array_len(ptrs) > 0) {
4565 /* Return GPtrArray* of field_info pointers for all hfindex that appear in tree.
4566 * This only works if the hfindex was "primed" before the dissection
4567 * took place, as we just pass back the already-created GPtrArray*.
4568 * The caller should *not* free the GPtrArray*; proto_tree_free_node()
4571 proto_get_finfo_ptr_array(proto_tree *tree, int id)
4573 return g_hash_table_lookup(PTREE_DATA(tree)->interesting_hfids,
4574 GINT_TO_POINTER(id));
4578 /* Helper struct for proto_find_info() and proto_all_finfos() */
4584 /* Helper function for proto_find_info() */
4586 find_finfo(proto_node *node, gpointer data)
4588 field_info *fi = PITEM_FINFO(node);
4589 if (fi && fi->hfinfo) {
4590 if (fi->hfinfo->id == ((ffdata_t*)data)->id) {
4591 g_ptr_array_add(((ffdata_t*)data)->array, fi);
4595 /* Don't stop traversing. */
4599 /* Return GPtrArray* of field_info pointers for all hfindex that appear in a tree.
4600 * This works on any proto_tree, primed or unprimed, but actually searches
4601 * the tree, so it is slower than using proto_get_finfo_ptr_array on a primed tree.
4602 * The caller does need to free the returned GPtrArray with
4603 * g_ptr_array_free(<array>, FALSE).
4606 proto_find_finfo(proto_tree *tree, int id)
4610 ffdata.array = g_ptr_array_new();
4613 proto_tree_traverse_pre_order(tree, find_finfo, &ffdata);
4615 return ffdata.array;
4618 /* Helper function for proto_all_finfos() */
4620 every_finfo(proto_node *node, gpointer data)
4622 field_info *fi = PITEM_FINFO(node);
4623 if (fi && fi->hfinfo) {
4624 g_ptr_array_add(((ffdata_t*)data)->array, fi);
4627 /* Don't stop traversing. */
4631 /* Return GPtrArray* of field_info pointers containing all hfindexes that appear in a tree. */
4633 proto_all_finfos(proto_tree *tree)
4637 ffdata.array = g_ptr_array_new();
4640 proto_tree_traverse_pre_order(tree, every_finfo, &ffdata);
4642 return ffdata.array;
4653 check_for_offset(proto_node *node, gpointer data)
4655 field_info *fi = PITEM_FINFO(node);
4656 offset_search_t *offsearch = data;
4658 /* !fi == the top most container node which holds nothing */
4659 if (fi && !PROTO_ITEM_IS_HIDDEN(node) && fi->ds_tvb && offsearch->tvb == fi->ds_tvb) {
4660 if (offsearch->offset >= (guint) fi->start &&
4661 offsearch->offset < (guint) (fi->start + fi->length)) {
4663 offsearch->finfo = fi;
4664 return FALSE; /* keep traversing */
4667 return FALSE; /* keep traversing */
4670 /* Search a proto_tree backwards (from leaves to root) looking for the field
4671 * whose start/length occupies 'offset' */
4672 /* XXX - I couldn't find an easy way to search backwards, so I search
4673 * forwards, w/o stopping. Therefore, the last finfo I find will the be
4674 * the one I want to return to the user. This algorithm is inefficient
4675 * and could be re-done, but I'd have to handle all the children and
4676 * siblings of each node myself. When I have more time I'll do that.
4679 proto_find_field_from_offset(proto_tree *tree, guint offset, tvbuff_t *tvb)
4681 offset_search_t offsearch;
4683 offsearch.offset = offset;
4684 offsearch.finfo = NULL;
4685 offsearch.tvb = tvb;
4687 proto_tree_traverse_pre_order(tree, check_for_offset, &offsearch);
4689 return offsearch.finfo;
4692 /* Dumps the protocols in the registration database to stdout. An independent
4693 * program can take this output and format it into nice tables or HTML or
4696 * There is one record per line. The fields are tab-delimited.
4698 * Field 1 = protocol name
4699 * Field 2 = protocol short name
4700 * Field 3 = protocol filter name
4703 proto_registrar_dump_protocols(void)
4705 protocol_t *protocol;
4707 void *cookie = NULL;
4709 for (i = proto_get_first_protocol(&cookie); i != -1;
4710 i = proto_get_next_protocol(&cookie)) {
4711 protocol = find_protocol_by_id(i);
4712 printf("%s\t%s\t%s\n", protocol->name, protocol->short_name,
4713 protocol->filter_name);
4717 /* Dumps the value_string and true/false strings for fields that have
4718 * them. There is one record per line. Fields are tab-delimited.
4719 * There are two types of records, Value String records and True/False
4720 * String records. The first field, 'V' or 'T', indicates the type
4726 * Field 2 = field abbreviation to which this value string corresponds
4727 * Field 3 = Integer value
4730 * True/False Strings
4731 * ------------------
4733 * Field 2 = field abbreviation to which this true/false string corresponds
4734 * Field 3 = True String
4735 * Field 4 = False String
4738 proto_registrar_dump_values(void)
4740 header_field_info *hfinfo, *parent_hfinfo;
4742 const value_string *vals;
4743 const true_false_string *tfs;
4745 len = gpa_hfinfo.len;
4746 for (i = 0; i < len ; i++) {
4747 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
4749 if (hfinfo->id == hf_text_only) {
4753 /* ignore protocols */
4754 if (proto_registrar_is_protocol(i)) {
4757 /* process header fields */
4760 * If this field isn't at the head of the list of
4761 * fields with this name, skip this field - all
4762 * fields with the same name are really just versions
4763 * of the same field stored in different bits, and
4764 * should have the same type/radix/value list, and
4765 * just differ in their bit masks. (If a field isn't
4766 * a bitfield, but can be, say, 1 or 2 bytes long,
4767 * it can just be made FT_UINT16, meaning the
4768 * *maximum* length is 2 bytes, and be used
4771 if (hfinfo->same_name_prev != NULL)
4774 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
4779 if (hfinfo->type == FT_UINT8 ||
4780 hfinfo->type == FT_UINT16 ||
4781 hfinfo->type == FT_UINT24 ||
4782 hfinfo->type == FT_UINT32 ||
4783 hfinfo->type == FT_UINT64 ||
4784 hfinfo->type == FT_INT8 ||
4785 hfinfo->type == FT_INT16 ||
4786 hfinfo->type == FT_INT24 ||
4787 hfinfo->type == FT_INT32 ||
4788 hfinfo->type == FT_INT64) {
4790 vals = hfinfo->strings;
4792 else if (hfinfo->type == FT_BOOLEAN) {
4793 tfs = hfinfo->strings;
4796 /* Print value strings? */
4799 while (vals[vi].strptr) {
4800 /* Print in the proper base */
4801 if (hfinfo->display == BASE_HEX) {
4802 printf("V\t%s\t0x%x\t%s\n",
4808 printf("V\t%s\t%u\t%s\n",
4817 /* Print true/false strings? */
4819 printf("T\t%s\t%s\t%s\n", hfinfo->abbrev,
4820 tfs->true_string, tfs->false_string);
4826 /* Dumps the contents of the registration database to stdout. An indepedent
4827 * program can take this output and format it into nice tables or HTML or
4830 * There is one record per line. Each record is either a protocol or a header
4831 * field, differentiated by the first field. The fields are tab-delimited.
4836 * Field 2 = descriptive protocol name
4837 * Field 3 = protocol abbreviation
4843 * Field 2 = descriptive field name
4844 * Field 3 = field abbreviation
4845 * Field 4 = type ( textual representation of the the ftenum type )
4846 * Field 5 = parent protocol abbreviation
4847 * Field 6 = blurb describing field
4851 * Field 2 = descriptive field name
4852 * Field 3 = field abbreviation
4853 * Field 4 = type ( textual representation of the the ftenum type )
4854 * Field 5 = parent protocol abbreviation
4855 * Field 6 = blurb describing field
4856 * Field 7 = base for display (for integer types)
4857 * Field 8 = blurb describing field (yes, apparently we repeated this accidentally)
4861 * Field 2 = descriptive field name
4862 * Field 3 = field abbreviation
4863 * Field 4 = type ( textual representation of the the ftenum type )
4864 * Field 5 = parent protocol abbreviation
4865 * Field 6 = blurb describing field
4866 * Field 7 = base for display (for integer types)
4870 proto_registrar_dump_fields(int format)
4872 header_field_info *hfinfo, *parent_hfinfo;
4874 const char *enum_name;
4875 const char *base_name;
4878 len = gpa_hfinfo.len;
4879 for (i = 0; i < len ; i++) {
4880 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
4883 * Skip fields with zero-length names or abbreviations;
4884 * the pseudo-field for "proto_tree_add_text()" is such
4885 * a field, and we don't want it in the list of filterable
4888 * XXX - perhaps the name and abbrev field should be null
4889 * pointers rather than null strings for that pseudo-field,
4890 * but we'd have to add checks for null pointers in some
4891 * places if we did that.
4893 * Or perhaps protocol tree items added with
4894 * "proto_tree_add_text()" should have -1 as the field index,
4895 * with no pseudo-field being used, but that might also
4896 * require special checks for -1 to be added.
4898 /* XXX - we could just skip the special text
4899 * pseudo-field by testing: if (hfinfo->id == hf_text_only)
4901 if (hfinfo->name[0] == 0 || hfinfo->abbrev[0] == 0)
4904 /* format for protocols */
4905 if (proto_registrar_is_protocol(i)) {
4906 printf("P\t%s\t%s\n", hfinfo->name, hfinfo->abbrev);
4908 /* format for header fields */
4911 * If this field isn't at the head of the list of
4912 * fields with this name, skip this field - all
4913 * fields with the same name are really just versions
4914 * of the same field stored in different bits, and
4915 * should have the same type/radix/value list, and
4916 * just differ in their bit masks. (If a field isn't
4917 * a bitfield, but can be, say, 1 or 2 bytes long,
4918 * it can just be made FT_UINT16, meaning the
4919 * *maximum* length is 2 bytes, and be used
4922 if (hfinfo->same_name_prev != NULL)
4925 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
4927 enum_name = ftype_name(hfinfo->type);
4931 if (hfinfo->type == FT_UINT8 ||
4932 hfinfo->type == FT_UINT16 ||
4933 hfinfo->type == FT_UINT24 ||
4934 hfinfo->type == FT_UINT32 ||
4935 hfinfo->type == FT_UINT64 ||
4936 hfinfo->type == FT_INT8 ||
4937 hfinfo->type == FT_INT16 ||
4938 hfinfo->type == FT_INT24 ||
4939 hfinfo->type == FT_INT32 ||
4940 hfinfo->type == FT_INT64) {
4943 switch(hfinfo->display) {
4945 base_name = "BASE_NONE";
4948 base_name = "BASE_DEC";
4951 base_name = "BASE_HEX";
4954 base_name = "BASE_OCT";
4957 base_name = "BASE_DEC_HEX";
4960 base_name = "BASE_HEX_DEC";
4966 blurb = hfinfo->blurb;
4970 printf("F\t%s\t%s\t%s\t%s\t%s\n",
4971 hfinfo->name, hfinfo->abbrev, enum_name,
4972 parent_hfinfo->abbrev, blurb);
4974 else if (format == 2) {
4975 printf("F\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n",
4976 hfinfo->name, hfinfo->abbrev, enum_name,
4977 parent_hfinfo->abbrev, blurb,
4980 else if (format == 3) {
4981 printf("F\t%s\t%s\t%s\t%s\t%s\t%s\t%u\n",
4982 hfinfo->name, hfinfo->abbrev, enum_name,
4983 parent_hfinfo->abbrev, blurb,
4984 base_name, hfinfo->bitmask);
4987 g_assert_not_reached();
4994 hfinfo_numeric_format(header_field_info *hfinfo)
4996 const char *format = NULL;
4998 /* Pick the proper format string */
4999 if (hfinfo->type == FT_FRAMENUM) {
5001 * Frame numbers are always displayed in decimal.
5003 format = "%s == %u";
5005 /* Pick the proper format string */
5006 switch(hfinfo->display) {
5009 case BASE_OCT: /* I'm lazy */
5010 switch(hfinfo->type) {
5015 format = "%s == %u";
5018 format = "%s == %" PRIu64;
5024 format = "%s == %d";
5027 format = "%s == %" PRId64;
5030 DISSECTOR_ASSERT_NOT_REACHED();
5036 switch(hfinfo->type) {
5038 format = "%s == 0x%02x";
5041 format = "%s == 0x%04x";
5044 format = "%s == 0x%06x";
5047 format = "%s == 0x%08x";
5050 format = "%s == 0x%016" PRIx64;
5053 DISSECTOR_ASSERT_NOT_REACHED();
5058 DISSECTOR_ASSERT_NOT_REACHED();
5066 * Returns TRUE if we can do a "match selected" on the field, FALSE
5070 proto_can_match_selected(field_info *finfo, epan_dissect_t *edt)
5072 header_field_info *hfinfo;
5075 hfinfo = finfo->hfinfo;
5076 DISSECTOR_ASSERT(hfinfo);
5078 switch(hfinfo->type) {
5097 case FT_ABSOLUTE_TIME:
5098 case FT_RELATIVE_TIME:
5101 case FT_UINT_STRING:
5109 * These all have values, so we can match.
5114 * Doesn't have a value, but may still want to test
5115 * for its presence in a trace
5120 * This doesn't have a value, so we'd match
5121 * on the raw bytes at this address.
5123 * Should we be allowed to access to the raw bytes?
5124 * If "edt" is NULL, the answer is "no".
5130 * Is this field part of the raw frame tvbuff?
5131 * If not, we can't use "frame[N:M]" to match
5134 * XXX - should this be frame-relative, or
5135 * protocol-relative?
5137 * XXX - does this fallback for non-registered
5138 * fields even make sense?
5140 if (finfo->ds_tvb != edt->tvb)
5144 * If the length is 0, there's nothing to match, so
5145 * we can't match. (Also check for negative values,
5146 * just in case, as we'll cast it to an unsigned
5149 length = finfo->length;
5154 * Don't go past the end of that tvbuff.
5156 if ((guint)length > tvb_length(finfo->ds_tvb))
5157 length = tvb_length(finfo->ds_tvb);
5164 /* This function returns a string allocated with packet lifetime scope.
5165 * You do not need to [g_]free() this string since it will be automatically
5166 * freed once the next packet is dissected.
5169 proto_construct_dfilter_string(field_info *finfo, epan_dissect_t *edt)
5171 header_field_info *hfinfo;
5177 gint start, length, length_remaining;
5180 hfinfo = finfo->hfinfo;
5181 DISSECTOR_ASSERT(hfinfo);
5182 abbrev_len = strlen(hfinfo->abbrev);
5185 * XXX - we can't use the "val_to_string_repr" and "string_repr_len"
5186 * functions for FT_UINT and FT_INT types, as we choose the base in
5187 * the string expression based on the display base of the field.
5189 * Note that the base does matter, as this is also used for
5190 * the protocolinfo tap.
5192 * It might be nice to use them in "proto_item_fill_label()"
5193 * as well, although, there, you'd have to deal with the base
5194 * *and* with resolved values for addresses.
5196 * Perhaps we need two different val_to_string routines, one
5197 * to generate items for display filters and one to generate
5198 * strings for display, and pass to both of them the
5199 * "display" and "strings" values in the header_field_info
5200 * structure for the field, so they can get the base and,
5201 * if the field is Boolean or an enumerated integer type,
5202 * the tables used to generate human-readable values.
5204 switch(hfinfo->type) {
5216 * 4 bytes for " == ".
5219 * a sign + up to 10 digits of 32-bit integer,
5222 * "0x" + 8 digits of 32-bit integer, in hex;
5224 * 11 digits of 32-bit integer, in octal.
5225 * (No, we don't do octal, but this way,
5226 * we know that if we do, this will still
5229 * 1 byte for the trailing '\0'.
5231 dfilter_len = abbrev_len + 4 + 11 + 1;
5232 buf = ep_alloc0(dfilter_len);
5233 format = hfinfo_numeric_format(hfinfo);
5234 g_snprintf(buf, dfilter_len, format, hfinfo->abbrev, fvalue_get_integer(&finfo->value));
5240 * 4 bytes for " == ".
5243 * a sign + up to 20 digits of 32-bit integer,
5246 * "0x" + 16 digits of 32-bit integer, in hex;
5248 * 22 digits of 32-bit integer, in octal.
5249 * (No, we don't do octal, but this way,
5250 * we know that if we do, this will still
5253 * 1 byte for the trailing '\0'.
5255 dfilter_len = abbrev_len + 4 + 22 + 1;
5256 buf = ep_alloc0(dfilter_len);
5257 format = hfinfo_numeric_format(hfinfo);
5258 g_snprintf(buf, dfilter_len, format, hfinfo->abbrev, fvalue_get_integer64(&finfo->value));
5261 /* These use the fvalue's "to_string_repr" method. */
5270 case FT_ABSOLUTE_TIME:
5271 case FT_RELATIVE_TIME:
5276 /* Figure out the string length needed.
5277 * The ft_repr length.
5278 * 4 bytes for " == ".
5279 * 1 byte for trailing NUL.
5281 dfilter_len = fvalue_string_repr_len(&finfo->value,
5283 dfilter_len += abbrev_len + 4 + 1;
5284 buf = ep_alloc0(dfilter_len);
5286 /* Create the string */
5287 g_snprintf(buf, dfilter_len, "%s == ", hfinfo->abbrev);
5288 fvalue_to_string_repr(&finfo->value,
5290 &buf[abbrev_len + 4]);
5294 buf = ep_strdup(finfo->hfinfo->abbrev);
5299 * This doesn't have a value, so we'd match
5300 * on the raw bytes at this address.
5302 * Should we be allowed to access to the raw bytes?
5303 * If "edt" is NULL, the answer is "no".
5309 * Is this field part of the raw frame tvbuff?
5310 * If not, we can't use "frame[N:M]" to match
5313 * XXX - should this be frame-relative, or
5314 * protocol-relative?
5316 * XXX - does this fallback for non-registered
5317 * fields even make sense?
5319 if (finfo->ds_tvb != edt->tvb)
5320 return NULL; /* you lose */
5323 * If the length is 0, just match the name of the field
5324 * (Also check for negative values,
5325 * just in case, as we'll cast it to an unsigned
5328 length = finfo->length;
5331 buf = ep_strdup(finfo->hfinfo->abbrev);
5338 * Don't go past the end of that tvbuff.
5340 length_remaining = tvb_length_remaining(finfo->ds_tvb, finfo->start);
5341 if (length > length_remaining)
5342 length = length_remaining;
5346 start = finfo->start;
5347 buf_len = 32 + length * 3;
5348 buf = ep_alloc0(buf_len);
5351 ptr += g_snprintf(ptr, buf_len-(ptr-buf), "frame[%d:%d] == ", finfo->start, length);
5352 for (i=0;i<length; i++) {
5353 c = tvb_get_guint8(finfo->ds_tvb, start);
5356 ptr += g_snprintf(ptr, buf_len-(ptr-buf), "%02x", c);
5359 ptr += g_snprintf(ptr, buf_len-(ptr-buf), ":%02x", c);