2 * Routines for protocol tree
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
36 #include "ptvcursor.h"
38 #include "addr_resolv.h"
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);
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(void (register_all_protocols)(void),
283 void (register_all_protocol_handoffs)(void))
285 static hf_register_info hf[] = {
287 { "Proto Init", "", FT_NONE, BASE_NONE, NULL, 0x0,
292 proto_names = g_hash_table_new(g_int_hash, g_int_equal);
293 proto_short_names = g_hash_table_new(g_int_hash, g_int_equal);
294 proto_filter_names = g_hash_table_new(g_int_hash, g_int_equal);
298 gmc_hfinfo = g_mem_chunk_new("gmc_hfinfo",
299 sizeof(header_field_info),
300 INITIAL_NUM_PROTOCOL_HFINFO * sizeof(header_field_info),
304 gpa_hfinfo.allocated_len=0;
306 gpa_name_tree = g_tree_new(g_strcmp);
308 /* Initialize the ftype subsystem */
311 /* Register one special-case FT_TEXT_ONLY field for use when
312 converting wireshark to new-style proto_tree. These fields
313 are merely strings on the GUI tree; they are not filterable */
314 proto_register_field_array(-1, hf, array_length(hf));
316 /* Have each built-in dissector register its protocols, fields,
317 dissector tables, and dissectors to be called through a
318 handle, and do whatever one-time initialization it needs to
320 register_all_protocols();
323 /* Now scan for plugins and load all the ones we find, calling
324 their register routines to do the stuff described above. */
328 /* Now call the "handoff registration" routines of all built-in
329 dissectors; those routines register the dissector in other
330 dissectors' handoff tables, and fetch any dissector handles
332 register_all_protocol_handoffs();
335 /* Now do the same with plugins. */
336 register_all_plugin_handoffs();
339 /* sort the protocols by protocol name */
340 protocols = g_list_sort(protocols, proto_compare_name);
342 /* We've assigned all the subtree type values; allocate the array
343 for them, and zero it out. */
344 tree_is_expanded = g_malloc(num_tree_types*sizeof (gboolean));
345 memset(tree_is_expanded, 0, num_tree_types*sizeof (gboolean));
348 /* String comparison func for dfilter_token GTree */
350 g_strcmp(gconstpointer a, gconstpointer b)
352 return strcmp((const char*)a, (const char*)b);
358 /* Free the abbrev/ID GTree */
360 g_tree_destroy(gpa_name_tree);
361 gpa_name_tree = NULL;
365 g_mem_chunk_destroy(gmc_hfinfo);
367 if(gpa_hfinfo.allocated_len){
369 gpa_hfinfo.allocated_len=0;
370 g_free(gpa_hfinfo.hfi);
373 if (tree_is_expanded != NULL)
374 g_free(tree_is_expanded);
378 typedef gboolean (*proto_tree_traverse_func)(proto_node *, gpointer);
381 proto_tree_traverse_pre_order(proto_tree *tree, proto_tree_traverse_func func,
384 proto_node *pnode = tree;
388 if (func(pnode, data))
391 child = pnode->first_child;
392 while (child != NULL) {
394 * The routine we call might modify the child, e.g. by
395 * freeing it, so we get the child's successor before
396 * calling that routine.
399 child = current->next;
400 if (proto_tree_traverse_pre_order((proto_tree *)current, func,
409 proto_tree_traverse_in_order(proto_tree *tree, proto_tree_traverse_func func,
412 proto_node *pnode = tree;
416 child = pnode->first_child;
419 * The routine we call might modify the child, e.g. by
420 * freeing it, so we get the child's successor before
421 * calling that routine.
424 child = current->next;
426 if (proto_tree_traverse_in_order((proto_tree *)current, func,
430 if (func(pnode, data))
433 while (child != NULL) {
435 * The routine we call might modify the child, e.g. by
436 * freeing it, so we get the child's successor before
437 * calling that routine.
440 child = current->next;
441 if (proto_tree_traverse_in_order((proto_tree *)current,
446 if (func(pnode, data))
454 proto_tree_children_foreach(proto_tree *tree, proto_tree_foreach_func func,
457 proto_node *node = tree;
460 node = node->first_child;
461 while (node != NULL) {
463 node = current->next;
464 func((proto_tree *)current, data);
468 /* frees the resources that the dissection a proto_tree uses */
470 proto_tree_free(proto_tree *tree)
472 proto_tree_traverse_in_order(tree, proto_tree_free_node, NULL);
476 free_GPtrArray_value(gpointer key _U_, gpointer value, gpointer user_data _U_)
478 GPtrArray *ptrs = value;
479 gint hfid = (gint)key;
480 header_field_info *hfinfo;
483 PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
484 if(hfinfo->ref_count){
485 /* when a field is referenced by a filter this also
486 affects the refcount for the parent protocol so we need
487 to adjust the refcount for the parent as well
489 if( (hfinfo->parent != -1) && (hfinfo->ref_count) ){
490 header_field_info *parent_hfinfo;
491 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
492 parent_hfinfo->ref_count -= hfinfo->ref_count;
494 hfinfo->ref_count = 0;
497 g_ptr_array_free(ptrs, TRUE);
501 free_node_tree_data(tree_data_t *tree_data)
503 /* Free all the GPtrArray's in the interesting_hfids hash. */
504 g_hash_table_foreach(tree_data->interesting_hfids,
505 free_GPtrArray_value, NULL);
507 /* And then destroy the hash. */
508 g_hash_table_destroy(tree_data->interesting_hfids);
510 /* And finally the tree_data_t itself. */
514 #define FREE_NODE_FIELD_INFO(finfo) \
516 ITEM_LABEL_FREE(finfo->rep); \
518 FVALUE_CLEANUP(&finfo->value); \
519 FIELD_INFO_FREE(finfo);
522 proto_tree_free_node(proto_node *node, gpointer data _U_)
524 field_info *finfo = PITEM_FINFO(node);
527 /* This is the root node. Destroy the per-tree data.
528 * There is no field_info to destroy. */
529 free_node_tree_data(PTREE_DATA(node));
532 /* This is a child node. Don't free the per-tree data, but
533 * do free the field_info data. */
534 FREE_NODE_FIELD_INFO(finfo);
537 /* Free the proto_node. */
538 PROTO_NODE_FREE(node);
540 return FALSE; /* FALSE = do not end traversal of protocol tree */
543 /* Is the parsing being done for a visible proto_tree or an invisible one?
544 * By setting this correctly, the proto_tree creation is sped up by not
545 * having to call g_vsnprintf and copy strings around.
548 proto_tree_set_visible(proto_tree *tree, gboolean visible)
550 PTREE_DATA(tree)->visible = visible;
553 /* Assume dissector set only its protocol fields.
554 This function is called by dissectors and allowes to speed up filtering
555 in wireshark, if this function returns FALSE it is safe to reset tree to NULL
556 and thus skip calling most of the expensive proto_tree_add_...()
558 If the tree is visible we implicitely assume the field is referenced.
561 proto_field_is_referenced(proto_tree *tree, int proto_id)
563 register header_field_info *hfinfo;
569 if (PTREE_DATA(tree)->visible)
572 PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
573 if (hfinfo->ref_count != 0)
580 /* Finds a record in the hf_info_records array by id. */
582 proto_registrar_get_nth(guint hfindex)
584 register header_field_info *hfinfo;
586 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
590 /* Finds a record in the hf_info_records array by name.
593 proto_registrar_get_byname(const char *field_name)
595 DISSECTOR_ASSERT(field_name != NULL);
596 return g_tree_lookup(gpa_name_tree, field_name);
599 /* Allocates an initializes a ptvcursor_t with 3 variables:
600 * proto_tree, tvbuff, and offset. */
602 ptvcursor_new(proto_tree *tree, tvbuff_t *tvb, gint offset)
606 ptvc = g_new(ptvcursor_t, 1);
609 ptvc->offset = offset;
613 /* Frees memory for ptvcursor_t, but nothing deeper than that. */
615 ptvcursor_free(ptvcursor_t *ptvc)
620 /* Returns tvbuff. */
622 ptvcursor_tvbuff(ptvcursor_t* ptvc)
627 /* Returns current offset. */
629 ptvcursor_current_offset(ptvcursor_t* ptvc)
635 ptvcursor_tree(ptvcursor_t* ptvc)
641 ptvcursor_set_tree(ptvcursor_t* ptvc, proto_tree *tree)
646 /* Add a text-only node, leaving it to our caller to fill the text in */
648 proto_tree_add_text_node(proto_tree *tree, tvbuff_t *tvb, gint start, gint length)
652 pi = proto_tree_add_pi(tree, hf_text_only, tvb, start, &length, NULL);
659 /* Add a text-only node to the proto_tree */
661 proto_tree_add_text(proto_tree *tree, tvbuff_t *tvb, gint start, gint length,
662 const char *format, ...)
667 pi = proto_tree_add_text_node(tree, tvb, start, length);
671 va_start(ap, format);
672 proto_tree_set_representation(pi, format, ap);
678 /* Add a text-only node to the proto_tree (va_list version) */
680 proto_tree_add_text_valist(proto_tree *tree, tvbuff_t *tvb, gint start,
681 gint length, const char *format, va_list ap)
685 pi = proto_tree_add_text_node(tree, tvb, start, length);
689 proto_tree_set_representation(pi, format, ap);
694 /* Add a text-only node for debugging purposes. The caller doesn't need
695 * to worry about tvbuff, start, or length. Debug message gets sent to
698 proto_tree_add_debug_text(proto_tree *tree, const char *format, ...)
703 pi = proto_tree_add_text_node(tree, NULL, 0, 0);
707 va_start(ap, format);
708 proto_tree_set_representation(pi, format, ap);
718 get_uint_value(tvbuff_t *tvb, gint offset, gint length, gboolean little_endian)
725 value = tvb_get_guint8(tvb, offset);
729 value = little_endian ? tvb_get_letohs(tvb, offset)
730 : tvb_get_ntohs(tvb, offset);
734 value = little_endian ? tvb_get_letoh24(tvb, offset)
735 : tvb_get_ntoh24(tvb, offset);
739 value = little_endian ? tvb_get_letohl(tvb, offset)
740 : tvb_get_ntohl(tvb, offset);
744 DISSECTOR_ASSERT_NOT_REACHED();
752 get_int_value(tvbuff_t *tvb, gint offset, gint length, gboolean little_endian)
759 value = (gint8)tvb_get_guint8(tvb, offset);
763 value = (gint16) (little_endian ? tvb_get_letohs(tvb, offset)
764 : tvb_get_ntohs(tvb, offset));
768 value = little_endian ? tvb_get_letoh24(tvb, offset)
769 : tvb_get_ntoh24(tvb, offset);
770 if (value & 0x00800000) {
771 /* Sign bit is set; sign-extend it. */
777 value = little_endian ? tvb_get_letohl(tvb, offset)
778 : tvb_get_ntohl(tvb, offset);
782 DISSECTOR_ASSERT_NOT_REACHED();
789 /* Add an item to a proto_tree, using the text label registered to that item;
790 the item is extracted from the tvbuff handed to it. */
792 proto_tree_new_item(field_info *new_fi, proto_tree *tree, int hfindex,
793 tvbuff_t *tvb, gint start, gint length, gboolean little_endian)
803 /* there is a possibility here that we might raise an exception
804 * and thus would lose track of the field_info.
805 * store it in a temp so that if we come here again we can reclaim
806 * the field_info without leaking memory.
808 /* XXX this only keeps track of one field_info struct,
809 if we ever go multithreaded for calls to this function
810 we have to change this code to use per thread variable.
813 /* oops, last one we got must have been lost due
815 * good thing we saved it, now we can reverse the
816 * memory leak and reclaim it.
818 SLAB_FREE(field_info_tmp, field_info);
820 /* we might throw an exception, keep track of this one
821 * across the "dangerous" section below.
823 field_info_tmp=new_fi;
825 switch(new_fi->hfinfo->type) {
827 /* no value to set for FT_NONE */
831 proto_tree_set_protocol_tvb(new_fi, tvb);
835 proto_tree_set_bytes_tvb(new_fi, tvb, start, length);
839 n = get_uint_value(tvb, start, length, little_endian);
840 proto_tree_set_bytes_tvb(new_fi, tvb, start + length, n);
842 /* Instead of calling proto_item_set_len(), since we don't yet
843 * have a proto_item, we set the field_info's length ourselves. */
844 new_fi->length = n + length;
848 proto_tree_set_boolean(new_fi,
849 get_uint_value(tvb, start, length, little_endian));
852 /* XXX - make these just FT_UINT? */
857 proto_tree_set_uint(new_fi,
858 get_uint_value(tvb, start, length, little_endian));
863 DISSECTOR_ASSERT(length == 8);
864 proto_tree_set_uint64_tvb(new_fi, tvb, start, little_endian);
867 /* XXX - make these just FT_INT? */
872 proto_tree_set_int(new_fi,
873 get_int_value(tvb, start, length, little_endian));
877 DISSECTOR_ASSERT(length == 4);
878 value = tvb_get_ipv4(tvb, start);
879 proto_tree_set_ipv4(new_fi, little_endian ? GUINT32_SWAP_LE_BE(value) : value);
883 DISSECTOR_ASSERT(length == 4);
884 proto_tree_set_ipxnet(new_fi,
885 get_uint_value(tvb, start, 4, FALSE));
889 DISSECTOR_ASSERT(length == 16);
890 proto_tree_set_ipv6_tvb(new_fi, tvb, start);
894 DISSECTOR_ASSERT(length == 6);
895 proto_tree_set_ether_tvb(new_fi, tvb, start);
899 DISSECTOR_ASSERT(length == 16);
900 proto_tree_set_guid_tvb(new_fi, tvb, start, little_endian);
904 proto_tree_set_oid_tvb(new_fi, tvb, start, length);
908 DISSECTOR_ASSERT(length == 4);
910 floatval = tvb_get_letohieee_float(tvb, start);
912 floatval = tvb_get_ntohieee_float(tvb, start);
913 proto_tree_set_float(new_fi, floatval);
917 DISSECTOR_ASSERT(length == 8);
919 doubleval = tvb_get_letohieee_double(tvb, start);
921 doubleval = tvb_get_ntohieee_double(tvb, start);
922 proto_tree_set_double(new_fi, doubleval);
926 proto_tree_set_string_tvb(new_fi, tvb, start, length);
930 DISSECTOR_ASSERT(length >= -1);
931 /* Instead of calling proto_item_set_len(),
932 * since we don't yet have a proto_item, we
933 * set the field_info's length ourselves.
935 * XXX - our caller can't use that length to
936 * advance an offset unless they arrange that
937 * there always be a protocol tree into which
938 * we're putting this item.
941 /* This can throw an exception */
942 length = tvb_strsize(tvb, start);
944 string = ep_alloc(length);
946 tvb_memcpy(tvb, string, start, length);
947 } else if (length == 0) {
950 /* In this case, length signifies
951 * the length of the string.
953 * This could either be a null-padded
954 * string, which doesn't necessarily
955 * have a '\0' at the end, or a
956 * null-terminated string, with a
957 * trailing '\0'. (Yes, there are
958 * cases where you have a string
959 * that's both counted and null-
962 * In the first case, we must
963 * allocate a buffer of length
964 * "length+1", to make room for
967 * In the second case, we don't
968 * assume that there is a trailing
969 * '\0' there, as the packet might
970 * be malformed. (XXX - should we
971 * throw an exception if there's no
972 * trailing '\0'?) Therefore, we
973 * allocate a buffer of length
974 * "length+1", and put in a trailing
975 * '\0', just to be safe.
977 * (XXX - this would change if
978 * we made string values counted
979 * rather than null-terminated.)
981 string = tvb_get_ephemeral_string(tvb, start,
984 new_fi->length = length;
985 proto_tree_set_string(new_fi, string);
989 n = get_uint_value(tvb, start, length, little_endian);
990 proto_tree_set_string_tvb(new_fi, tvb, start + length, n);
992 /* Instead of calling proto_item_set_len(), since we
993 * don't yet have a proto_item, we set the
994 * field_info's length ourselves.
996 * XXX - our caller can't use that length to
997 * advance an offset unless they arrange that
998 * there always be a protocol tree into which
999 * we're putting this item.
1001 new_fi->length = n + length;
1005 g_error("new_fi->hfinfo->type %d (%s) not handled\n",
1006 new_fi->hfinfo->type,
1007 ftype_name(new_fi->hfinfo->type));
1008 DISSECTOR_ASSERT_NOT_REACHED();
1012 /* Don't add new node to proto_tree until now so that any exceptions
1013 * raised by a tvbuff access method doesn't leave junk in the proto_tree. */
1014 pi = proto_tree_add_node(tree, new_fi);
1016 /* we did not raise an exception so we dont have to remember this
1017 * field_info struct any more.
1019 field_info_tmp=NULL;
1021 /* If the proto_tree wants to keep a record of this finfo
1022 * for quick lookup, then record it. */
1023 if (new_fi->hfinfo->ref_count) {
1025 hash = PTREE_DATA(tree)->interesting_hfids;
1026 ptrs = g_hash_table_lookup(hash, GINT_TO_POINTER(hfindex));
1028 g_ptr_array_add(ptrs, new_fi);
1035 /* Gets data from tvbuff, adds it to proto_tree, increments offset,
1036 and returns proto_item* */
1038 ptvcursor_add(ptvcursor_t *ptvc, int hfindex, gint length,
1039 gboolean little_endian)
1042 header_field_info *hfinfo;
1047 offset = ptvc->offset;
1048 hfinfo = get_hfi_and_length(hfindex, ptvc->tvb, offset, &length,
1050 ptvc->offset += length;
1051 if (hfinfo->type == FT_UINT_BYTES || hfinfo->type == FT_UINT_STRING) {
1053 * The length of the rest of the item is in the first N
1054 * bytes of the item.
1056 n = get_uint_value(ptvc->tvb, offset, length, little_endian);
1059 if (ptvc->tree == NULL)
1062 TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfindex);
1064 new_fi = new_field_info(ptvc->tree, hfinfo, ptvc->tvb, offset,
1069 return proto_tree_new_item(new_fi, ptvc->tree, hfindex, ptvc->tvb,
1070 offset, length, little_endian);
1073 /* Add an item to a proto_tree, using the text label registered to that item;
1074 the item is extracted from the tvbuff handed to it. */
1076 proto_tree_add_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1077 gint start, gint length, gboolean little_endian)
1084 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1086 new_fi = alloc_field_info(tree, hfindex, tvb, start, &length);
1091 return proto_tree_new_item(new_fi, tree, hfindex, tvb, start,
1092 length, little_endian);
1096 proto_tree_add_item_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1097 gint start, gint length, gboolean little_endian)
1101 pi = proto_tree_add_item(tree, hfindex, tvb, start, length, little_endian);
1105 PROTO_ITEM_SET_HIDDEN(pi);
1111 /* Add a FT_NONE to a proto_tree */
1113 proto_tree_add_none_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1114 gint length, const char *format, ...)
1118 header_field_info *hfinfo;
1123 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1124 DISSECTOR_ASSERT(hfinfo->type == FT_NONE);
1126 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, NULL);
1128 va_start(ap, format);
1129 proto_tree_set_representation(pi, format, ap);
1132 /* no value to set for FT_NONE */
1136 /* Gets data from tvbuff, adds it to proto_tree, *DOES NOT* increment
1137 * offset, and returns proto_item* */
1139 ptvcursor_add_no_advance(ptvcursor_t* ptvc, int hf, gint length,
1140 gboolean endianness)
1144 item = proto_tree_add_item(ptvc->tree, hf, ptvc->tvb, ptvc->offset,
1145 length, endianness);
1150 /* Advance the ptvcursor's offset within its tvbuff without
1151 * adding anything to the proto_tree. */
1153 ptvcursor_advance(ptvcursor_t* ptvc, gint length)
1155 ptvc->offset += length;
1160 proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb)
1162 fvalue_set(&fi->value, tvb, TRUE);
1165 /* Add a FT_PROTOCOL to a proto_tree */
1167 proto_tree_add_protocol_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1168 gint length, const char *format, ...)
1172 header_field_info *hfinfo;
1178 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1179 DISSECTOR_ASSERT(hfinfo->type == FT_PROTOCOL);
1181 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1183 va_start(ap, format);
1184 proto_tree_set_representation(pi, format, ap);
1188 proto_tree_set_protocol_tvb(new_fi, tvb);
1191 proto_tree_set_protocol_tvb(new_fi, NULL);
1197 /* Add a FT_BYTES to a proto_tree */
1199 proto_tree_add_bytes(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1200 gint length, const guint8 *start_ptr)
1204 header_field_info *hfinfo;
1209 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1211 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1212 DISSECTOR_ASSERT(hfinfo->type == FT_BYTES);
1214 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1215 proto_tree_set_bytes(new_fi, start_ptr, length);
1221 proto_tree_add_bytes_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1222 gint length, const guint8 *start_ptr)
1226 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length, start_ptr);
1230 PROTO_ITEM_SET_HIDDEN(pi);
1236 proto_tree_add_bytes_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1237 gint start, gint length, const guint8 *start_ptr,
1238 const char *format, ...)
1243 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length, start_ptr);
1247 va_start(ap, format);
1248 proto_tree_set_representation_value(pi, format, ap);
1255 proto_tree_add_bytes_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1256 gint length, const guint8 *start_ptr, const char *format, ...)
1261 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length, start_ptr);
1265 va_start(ap, format);
1266 proto_tree_set_representation(pi, format, ap);
1273 proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length)
1277 bytes = g_byte_array_new();
1279 g_byte_array_append(bytes, start_ptr, length);
1281 fvalue_set(&fi->value, bytes, TRUE);
1286 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length)
1288 proto_tree_set_bytes(fi, tvb_get_ptr(tvb, offset, length), length);
1291 /* Add a FT_*TIME to a proto_tree */
1293 proto_tree_add_time(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1294 nstime_t *value_ptr)
1298 header_field_info *hfinfo;
1303 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1305 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1306 DISSECTOR_ASSERT(hfinfo->type == FT_ABSOLUTE_TIME ||
1307 hfinfo->type == FT_RELATIVE_TIME);
1309 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1310 proto_tree_set_time(new_fi, value_ptr);
1316 proto_tree_add_time_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1317 nstime_t *value_ptr)
1321 pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
1325 PROTO_ITEM_SET_HIDDEN(pi);
1331 proto_tree_add_time_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1332 gint start, gint length, nstime_t *value_ptr,
1333 const char *format, ...)
1338 pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
1342 va_start(ap, format);
1343 proto_tree_set_representation_value(pi, format, ap);
1350 proto_tree_add_time_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1351 nstime_t *value_ptr, const char *format, ...)
1356 pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
1360 va_start(ap, format);
1361 proto_tree_set_representation(pi, format, ap);
1367 /* Set the FT_*TIME value */
1369 proto_tree_set_time(field_info *fi, nstime_t *value_ptr)
1371 DISSECTOR_ASSERT(value_ptr != NULL);
1372 fvalue_set(&fi->value, value_ptr, FALSE);
1375 /* Add a FT_IPXNET to a proto_tree */
1377 proto_tree_add_ipxnet(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1382 header_field_info *hfinfo;
1387 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1389 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1390 DISSECTOR_ASSERT(hfinfo->type == FT_IPXNET);
1392 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1393 proto_tree_set_ipxnet(new_fi, value);
1399 proto_tree_add_ipxnet_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1404 pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
1408 PROTO_ITEM_SET_HIDDEN(pi);
1414 proto_tree_add_ipxnet_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1415 gint start, gint length, guint32 value, const char *format, ...)
1420 pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
1424 va_start(ap, format);
1425 proto_tree_set_representation_value(pi, format, ap);
1432 proto_tree_add_ipxnet_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1433 guint32 value, const char *format, ...)
1438 pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
1442 va_start(ap, format);
1443 proto_tree_set_representation(pi, format, ap);
1449 /* Set the FT_IPXNET value */
1451 proto_tree_set_ipxnet(field_info *fi, guint32 value)
1453 fvalue_set_uinteger(&fi->value, value);
1456 /* Add a FT_IPv4 to a proto_tree */
1458 proto_tree_add_ipv4(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1463 header_field_info *hfinfo;
1468 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1470 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1471 DISSECTOR_ASSERT(hfinfo->type == FT_IPv4);
1473 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1474 proto_tree_set_ipv4(new_fi, value);
1480 proto_tree_add_ipv4_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1485 pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
1489 PROTO_ITEM_SET_HIDDEN(pi);
1495 proto_tree_add_ipv4_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1496 gint start, gint length, guint32 value, const char *format, ...)
1501 pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
1505 va_start(ap, format);
1506 proto_tree_set_representation_value(pi, format, ap);
1513 proto_tree_add_ipv4_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1514 guint32 value, const char *format, ...)
1519 pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
1523 va_start(ap, format);
1524 proto_tree_set_representation(pi, format, ap);
1530 /* Set the FT_IPv4 value */
1532 proto_tree_set_ipv4(field_info *fi, guint32 value)
1534 fvalue_set_uinteger(&fi->value, value);
1537 /* Add a FT_IPv6 to a proto_tree */
1539 proto_tree_add_ipv6(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1540 const guint8* value_ptr)
1544 header_field_info *hfinfo;
1549 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1551 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1552 DISSECTOR_ASSERT(hfinfo->type == FT_IPv6);
1554 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1555 proto_tree_set_ipv6(new_fi, value_ptr);
1561 proto_tree_add_ipv6_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1562 const guint8* value_ptr)
1566 pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
1570 PROTO_ITEM_SET_HIDDEN(pi);
1576 proto_tree_add_ipv6_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1577 gint start, gint length, const guint8* value_ptr,
1578 const char *format, ...)
1583 pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
1587 va_start(ap, format);
1588 proto_tree_set_representation_value(pi, format, ap);
1595 proto_tree_add_ipv6_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1596 const guint8* value_ptr, const char *format, ...)
1601 pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
1605 va_start(ap, format);
1606 proto_tree_set_representation(pi, format, ap);
1612 /* Set the FT_IPv6 value */
1614 proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr)
1616 DISSECTOR_ASSERT(value_ptr != NULL);
1617 fvalue_set(&fi->value, (gpointer) value_ptr, FALSE);
1621 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start)
1623 proto_tree_set_ipv6(fi, tvb_get_ptr(tvb, start, 16));
1626 /* Add a FT_GUID to a proto_tree */
1628 proto_tree_add_guid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1629 const e_guid_t *value_ptr)
1633 header_field_info *hfinfo;
1638 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1640 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1641 DISSECTOR_ASSERT(hfinfo->type == FT_GUID);
1643 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1644 proto_tree_set_guid(new_fi, value_ptr);
1650 proto_tree_add_guid_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1651 const e_guid_t *value_ptr)
1655 pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
1659 PROTO_ITEM_SET_HIDDEN(pi);
1665 proto_tree_add_guid_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1666 gint start, gint length, const e_guid_t *value_ptr,
1667 const char *format, ...)
1672 pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
1676 va_start(ap, format);
1677 proto_tree_set_representation_value(pi, format, ap);
1684 proto_tree_add_guid_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1685 const e_guid_t *value_ptr, const char *format, ...)
1690 pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
1694 va_start(ap, format);
1695 proto_tree_set_representation(pi, format, ap);
1701 /* Set the FT_GUID value */
1703 proto_tree_set_guid(field_info *fi, const e_guid_t *value_ptr)
1705 DISSECTOR_ASSERT(value_ptr != NULL);
1706 fvalue_set(&fi->value, (gpointer) value_ptr, FALSE);
1710 proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gboolean little_endian)
1714 tvb_get_guid(tvb, start, &guid, little_endian);
1715 proto_tree_set_guid(fi, &guid);
1718 /* Add a FT_OID to a proto_tree */
1720 proto_tree_add_oid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1721 const guint8* value_ptr)
1725 header_field_info *hfinfo;
1730 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1732 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1733 DISSECTOR_ASSERT(hfinfo->type == FT_OID);
1735 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1736 proto_tree_set_oid(new_fi, value_ptr, length);
1742 proto_tree_add_oid_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1743 const guint8* value_ptr)
1747 pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
1751 PROTO_ITEM_SET_HIDDEN(pi);
1757 proto_tree_add_oid_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1758 gint start, gint length, const guint8* value_ptr,
1759 const char *format, ...)
1764 pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
1768 va_start(ap, format);
1769 proto_tree_set_representation_value(pi, format, ap);
1776 proto_tree_add_oid_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1777 const guint8* value_ptr, const char *format, ...)
1782 pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
1786 va_start(ap, format);
1787 proto_tree_set_representation(pi, format, ap);
1793 /* Set the FT_OID value */
1795 proto_tree_set_oid(field_info *fi, const guint8* value_ptr, gint length)
1799 DISSECTOR_ASSERT(value_ptr != NULL);
1801 bytes = g_byte_array_new();
1803 g_byte_array_append(bytes, value_ptr, length);
1805 fvalue_set(&fi->value, bytes, TRUE);
1809 proto_tree_set_oid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
1811 proto_tree_set_oid(fi, tvb_get_ptr(tvb, start, length), length);
1815 proto_tree_set_uint64(field_info *fi, guint64 value)
1817 fvalue_set_integer64(&fi->value, value);
1821 proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start, gboolean little_endian)
1825 value = little_endian ? tvb_get_letoh64(tvb, start)
1826 : tvb_get_ntoh64(tvb, start);
1828 proto_tree_set_uint64(fi, value);
1831 /* Add a FT_STRING or FT_STRINGZ to a proto_tree. Creates own copy of string,
1832 * and frees it when the proto_tree is destroyed. */
1834 proto_tree_add_string(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1835 gint length, const char* value)
1839 header_field_info *hfinfo;
1844 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1846 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1847 DISSECTOR_ASSERT(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ);
1849 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1850 DISSECTOR_ASSERT(length >= 0);
1851 proto_tree_set_string(new_fi, value);
1857 proto_tree_add_string_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1858 gint length, const char* value)
1862 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
1866 PROTO_ITEM_SET_HIDDEN(pi);
1872 proto_tree_add_string_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1873 gint start, gint length, const char* value, const char *format,
1879 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
1883 va_start(ap, format);
1884 proto_tree_set_representation_value(pi, format, ap);
1891 proto_tree_add_string_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1892 gint length, const char* value, const char *format, ...)
1897 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
1901 va_start(ap, format);
1902 proto_tree_set_representation(pi, format, ap);
1908 /* Appends string data to a FT_STRING or FT_STRINGZ, allowing progressive
1909 * field info update instead of only updating the representation as does
1910 * proto_item_append_text()
1912 /* NOTE: this function will break with the TRY_TO_FAKE_THIS_ITEM()
1913 * speed optimization.
1914 * Currently only WSP use this function so it is not that bad but try to
1915 * avoid using this one if possible.
1916 * IF you must use this function you MUST also disable the
1917 * TRY_TO_FAKE_THIS_ITEM() optimization for your dissector/function
1918 * using proto_item_append_string().
1919 * Do that by faking that the tree is visible by setting :
1920 * PTREE_DATA(tree)->visible=1; (see packet-wsp.c)
1921 * BEFORE you create the item you are later going to use
1922 * proto_item_append_string() on.
1925 proto_item_append_string(proto_item *pi, const char *str)
1928 header_field_info *hfinfo;
1929 gchar *old_str, *new_str;
1936 fi = PITEM_FINFO(pi);
1937 hfinfo = fi->hfinfo;
1938 if (hfinfo->type == FT_PROTOCOL) {
1939 /* TRY_TO_FAKE_THIS_ITEM() speed optimization: silently skip */
1942 DISSECTOR_ASSERT(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ);
1943 old_str = fvalue_get(&fi->value);
1944 new_str = ep_strdup_printf("%s%s", old_str, str);
1945 fvalue_set(&fi->value, new_str, FALSE);
1948 /* Set the FT_STRING value */
1950 proto_tree_set_string(field_info *fi, const char* value)
1953 fvalue_set(&fi->value, (gpointer) value, FALSE);
1955 fvalue_set(&fi->value, (gpointer) "[ Null ]", FALSE);
1959 proto_tree_set_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
1964 length = tvb_ensure_length_remaining(tvb, start);
1967 string = tvb_get_ephemeral_string(tvb, start, length);
1968 proto_tree_set_string(fi, string);
1971 /* Add a FT_ETHER to a proto_tree */
1973 proto_tree_add_ether(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1974 const guint8* value)
1978 header_field_info *hfinfo;
1983 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1985 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1986 DISSECTOR_ASSERT(hfinfo->type == FT_ETHER);
1988 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1989 proto_tree_set_ether(new_fi, value);
1995 proto_tree_add_ether_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1996 const guint8* value)
2000 pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
2004 PROTO_ITEM_SET_HIDDEN(pi);
2010 proto_tree_add_ether_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2011 gint start, gint length, const guint8* value,
2012 const char *format, ...)
2017 pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
2021 va_start(ap, format);
2022 proto_tree_set_representation_value(pi, format, ap);
2029 proto_tree_add_ether_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2030 const guint8* value, const char *format, ...)
2035 pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
2039 va_start(ap, format);
2040 proto_tree_set_representation(pi, format, ap);
2046 /* Set the FT_ETHER value */
2048 proto_tree_set_ether(field_info *fi, const guint8* value)
2050 fvalue_set(&fi->value, (gpointer) value, FALSE);
2054 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start)
2056 proto_tree_set_ether(fi, tvb_get_ptr(tvb, start, 6));
2059 /* Add a FT_BOOLEAN to a proto_tree */
2061 proto_tree_add_boolean(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2066 header_field_info *hfinfo;
2071 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
2073 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2074 DISSECTOR_ASSERT(hfinfo->type == FT_BOOLEAN);
2076 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2077 proto_tree_set_boolean(new_fi, value);
2083 proto_tree_add_boolean_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2088 pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
2092 PROTO_ITEM_SET_HIDDEN(pi);
2098 proto_tree_add_boolean_format_value(proto_tree *tree, int hfindex,
2099 tvbuff_t *tvb, gint start, gint length, guint32 value,
2100 const char *format, ...)
2105 pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
2109 va_start(ap, format);
2110 proto_tree_set_representation_value(pi, format, ap);
2117 proto_tree_add_boolean_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2118 guint32 value, const char *format, ...)
2123 pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
2127 va_start(ap, format);
2128 proto_tree_set_representation(pi, format, ap);
2134 /* Set the FT_BOOLEAN value */
2136 proto_tree_set_boolean(field_info *fi, guint32 value)
2138 proto_tree_set_uint(fi, value);
2141 /* Add a FT_FLOAT to a proto_tree */
2143 proto_tree_add_float(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2148 header_field_info *hfinfo;
2153 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
2155 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2156 DISSECTOR_ASSERT(hfinfo->type == FT_FLOAT);
2158 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2159 proto_tree_set_float(new_fi, value);
2165 proto_tree_add_float_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2170 pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
2174 PROTO_ITEM_SET_HIDDEN(pi);
2180 proto_tree_add_float_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2181 gint start, gint length, float value, const char *format, ...)
2186 pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
2190 va_start(ap, format);
2191 proto_tree_set_representation_value(pi, format, ap);
2198 proto_tree_add_float_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2199 float value, const char *format, ...)
2204 pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
2208 va_start(ap, format);
2209 proto_tree_set_representation(pi, format, ap);
2215 /* Set the FT_FLOAT value */
2217 proto_tree_set_float(field_info *fi, float value)
2219 fvalue_set_floating(&fi->value, value);
2222 /* Add a FT_DOUBLE to a proto_tree */
2224 proto_tree_add_double(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2229 header_field_info *hfinfo;
2234 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
2236 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2237 DISSECTOR_ASSERT(hfinfo->type == FT_DOUBLE);
2239 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2240 proto_tree_set_double(new_fi, value);
2246 proto_tree_add_double_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2251 pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
2255 PROTO_ITEM_SET_HIDDEN(pi);
2261 proto_tree_add_double_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2262 gint start, gint length, double value, const char *format, ...)
2267 pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
2271 va_start(ap, format);
2272 proto_tree_set_representation_value(pi, format, ap);
2279 proto_tree_add_double_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2280 double value, const char *format, ...)
2285 pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
2289 va_start(ap, format);
2290 proto_tree_set_representation(pi, format, ap);
2296 /* Set the FT_DOUBLE value */
2298 proto_tree_set_double(field_info *fi, double value)
2300 fvalue_set_floating(&fi->value, value);
2303 /* Add FT_UINT{8,16,24,32} to a proto_tree */
2305 proto_tree_add_uint(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2308 proto_item *pi = NULL;
2310 header_field_info *hfinfo;
2315 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
2317 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2318 switch(hfinfo->type) {
2324 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length,
2326 proto_tree_set_uint(new_fi, value);
2330 DISSECTOR_ASSERT_NOT_REACHED();
2337 proto_tree_add_uint_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2342 pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
2346 PROTO_ITEM_SET_HIDDEN(pi);
2352 proto_tree_add_uint_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2353 gint start, gint length, guint32 value, const char *format, ...)
2358 pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
2362 va_start(ap, format);
2363 proto_tree_set_representation_value(pi, format, ap);
2370 proto_tree_add_uint_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2371 guint32 value, const char *format, ...)
2376 pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
2380 va_start(ap, format);
2381 proto_tree_set_representation(pi, format, ap);
2387 /* Set the FT_UINT{8,16,24,32} value */
2389 proto_tree_set_uint(field_info *fi, guint32 value)
2391 header_field_info *hfinfo;
2394 hfinfo = fi->hfinfo;
2397 if (hfinfo->bitmask) {
2398 /* Mask out irrelevant portions */
2399 integer &= hfinfo->bitmask;
2402 if (hfinfo->bitshift > 0) {
2403 integer >>= hfinfo->bitshift;
2406 fvalue_set_uinteger(&fi->value, integer);
2409 /* Add FT_UINT64 to a proto_tree */
2411 proto_tree_add_uint64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2414 proto_item *pi = NULL;
2416 header_field_info *hfinfo;
2421 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
2423 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2424 DISSECTOR_ASSERT(hfinfo->type == FT_UINT64);
2426 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2427 proto_tree_set_uint64(new_fi, value);
2433 proto_tree_add_uint64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2434 gint start, gint length, guint64 value, const char *format, ...)
2439 pi = proto_tree_add_uint64(tree, hfindex, tvb, start, length, value);
2443 va_start(ap, format);
2444 proto_tree_set_representation_value(pi, format, ap);
2451 proto_tree_add_uint64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2452 guint64 value, const char *format, ...)
2457 pi = proto_tree_add_uint64(tree, hfindex, tvb, start, length, value);
2461 va_start(ap, format);
2462 proto_tree_set_representation(pi, format, ap);
2468 /* Add FT_INT{8,16,24,32} to a proto_tree */
2470 proto_tree_add_int(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2473 proto_item *pi = NULL;
2475 header_field_info *hfinfo;
2480 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
2482 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2483 switch(hfinfo->type) {
2488 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length,
2490 proto_tree_set_int(new_fi, value);
2494 DISSECTOR_ASSERT_NOT_REACHED();
2501 proto_tree_add_int_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2506 pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
2510 PROTO_ITEM_SET_HIDDEN(pi);
2516 proto_tree_add_int_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2517 gint start, gint length, gint32 value, const char *format, ...)
2519 proto_item *pi = NULL;
2522 pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
2526 va_start(ap, format);
2527 proto_tree_set_representation_value(pi, format, ap);
2534 proto_tree_add_int_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2535 gint32 value, const char *format, ...)
2537 proto_item *pi = NULL;
2540 pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
2544 va_start(ap, format);
2545 proto_tree_set_representation(pi, format, ap);
2551 /* Set the FT_INT{8,16,24,32} value */
2553 proto_tree_set_int(field_info *fi, gint32 value)
2555 header_field_info *hfinfo;
2558 hfinfo = fi->hfinfo;
2559 integer = (guint32) value;
2561 if (hfinfo->bitmask) {
2562 /* Mask out irrelevant portions */
2563 integer &= hfinfo->bitmask;
2566 if (hfinfo->bitshift > 0) {
2567 integer >>= hfinfo->bitshift;
2570 fvalue_set_sinteger(&fi->value, integer);
2573 /* Add FT_INT64 to a proto_tree */
2575 proto_tree_add_int64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2578 proto_item *pi = NULL;
2580 header_field_info *hfinfo;
2585 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
2587 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2588 DISSECTOR_ASSERT(hfinfo->type == FT_INT64);
2590 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2591 proto_tree_set_uint64(new_fi, (guint64)value);
2597 proto_tree_add_int64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2598 gint start, gint length, gint64 value, const char *format, ...)
2603 pi = proto_tree_add_int64(tree, hfindex, tvb, start, length, value);
2607 va_start(ap, format);
2608 proto_tree_set_representation_value(pi, format, ap);
2615 proto_tree_add_int64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2616 gint64 value, const char *format, ...)
2621 pi = proto_tree_add_int64(tree, hfindex, tvb, start, length, value);
2625 va_start(ap, format);
2626 proto_tree_set_representation(pi, format, ap);
2632 /* Throw an exception if we exceed this many tree items. */
2633 /* XXX - This should probably be a preference */
2634 #define MAX_TREE_ITEMS (1 * 1000 * 1000)
2635 /* Add a field_info struct to the proto_tree, encapsulating it in a proto_node */
2637 proto_tree_add_node(proto_tree *tree, field_info *fi)
2639 proto_node *pnode, *tnode, *sibling;
2643 * Make sure "tree" is ready to have subtrees under it, by
2644 * checking whether it's been given an ett_ value.
2646 * "tnode->finfo" may be null; that's the case for the root
2647 * node of the protocol tree. That node is not displayed,
2648 * so it doesn't need an ett_ value to remember whether it
2653 if (tfi != NULL && (tfi->tree_type < 0 || tfi->tree_type >= num_tree_types)) {
2654 REPORT_DISSECTOR_BUG(ep_strdup_printf("\"%s\" - \"%s\" tfi->tree_type: %u invalid (%s:%u)",
2655 fi->hfinfo->name, fi->hfinfo->abbrev, tfi->tree_type, __FILE__, __LINE__));
2656 /* XXX - is it safe to continue here? */
2659 DISSECTOR_ASSERT(tfi == NULL ||
2660 (tfi->tree_type >= 0 && tfi->tree_type < num_tree_types));
2662 PTREE_DATA(tree)->count++;
2663 if (PTREE_DATA(tree)->count > MAX_TREE_ITEMS) {
2664 /* Let the exception handler add items to the tree */
2665 PTREE_DATA(tree)->count = 0;
2666 THROW_MESSAGE(DissectorError,
2667 ep_strdup_printf("More than %d items in the tree -- possible infinite loop", MAX_TREE_ITEMS));
2670 PROTO_NODE_NEW(pnode);
2671 pnode->parent = tnode;
2673 pnode->tree_data = PTREE_DATA(tree);
2675 if (tnode->last_child != NULL) {
2676 sibling = tnode->last_child;
2677 DISSECTOR_ASSERT(sibling->next == NULL);
2678 sibling->next = pnode;
2680 tnode->first_child = pnode;
2681 tnode->last_child = pnode;
2683 return (proto_item*)pnode;
2687 /* Generic way to allocate field_info and add to proto_tree.
2688 * Sets *pfi to address of newly-allocated field_info struct, if pfi is
2691 proto_tree_add_pi(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2692 gint *length, field_info **pfi)
2702 fi = alloc_field_info(tree, hfindex, tvb, start, length);
2703 pi = proto_tree_add_node(tree, fi);
2705 /* If the proto_tree wants to keep a record of this finfo
2706 * for quick lookup, then record it. */
2707 if (fi->hfinfo->ref_count) {
2709 hash = PTREE_DATA(tree)->interesting_hfids;
2710 ptrs = g_hash_table_lookup(hash, GINT_TO_POINTER(hfindex));
2712 g_ptr_array_add(ptrs, fi);
2716 /* Does the caller want to know the fi pointer? */
2725 static header_field_info *
2726 get_hfi_and_length(int hfindex, tvbuff_t *tvb, gint start, gint *length,
2729 header_field_info *hfinfo;
2730 gint length_remaining;
2733 * We only allow a null tvbuff if the item has a zero length,
2734 * i.e. if there's no data backing it.
2736 DISSECTOR_ASSERT(tvb != NULL || *length == 0);
2738 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2741 * XXX - in some protocols, there are 32-bit unsigned length
2742 * fields, so lengths in protocol tree and tvbuff routines
2743 * should really be unsigned. We should have, for those
2744 * field types for which "to the end of the tvbuff" makes sense,
2745 * additional routines that take no length argument and
2746 * add fields that run to the end of the tvbuff.
2748 if (*length == -1) {
2750 * For FT_NONE, FT_PROTOCOL, FT_BYTES, and FT_STRING fields,
2751 * a length of -1 means "set the length to what remains in
2754 * The assumption is either that
2756 * 1) the length of the item can only be determined
2757 * by dissection (typically true of items with
2758 * subitems, which are probably FT_NONE or
2763 * 2) if the tvbuff is "short" (either due to a short
2764 * snapshot length or due to lack of reassembly of
2765 * fragments/segments/whatever), we want to display
2766 * what's available in the field (probably FT_BYTES
2767 * or FT_STRING) and then throw an exception later
2771 * 3) the field is defined to be "what's left in the
2774 * so we set the length to what remains in the tvbuff so
2775 * that, if we throw an exception while dissecting, it
2776 * has what is probably the right value.
2778 * For FT_STRINGZ, it means "the string is null-terminated,
2779 * not null-padded; set the length to the actual length
2780 * of the string", and if the tvbuff if short, we just
2781 * throw an exception.
2783 * It's not valid for any other type of field.
2785 switch (hfinfo->type) {
2789 * We allow this to be zero-length - for
2790 * example, an ONC RPC NULL procedure has
2791 * neither arguments nor reply, so the
2792 * payload for that protocol is empty.
2794 * However, if the length is negative, the
2795 * start offset is *past* the byte past the
2796 * end of the tvbuff, so we throw an
2799 *length = tvb_length_remaining(tvb, start);
2802 * Use "tvb_ensure_bytes_exist()"
2803 * to force the appropriate exception
2806 tvb_ensure_bytes_exist(tvb, start, 0);
2808 DISSECTOR_ASSERT(*length >= 0);
2814 *length = tvb_ensure_length_remaining(tvb, start);
2815 DISSECTOR_ASSERT(*length >= 0);
2820 * Leave the length as -1, so our caller knows
2826 DISSECTOR_ASSERT_NOT_REACHED();
2828 *item_length = *length;
2830 *item_length = *length;
2831 if (hfinfo->type == FT_PROTOCOL || hfinfo->type == FT_NONE) {
2833 * These types are for interior nodes of the
2834 * tree, and don't have data associated with
2835 * them; if the length is negative (XXX - see
2836 * above) or goes past the end of the tvbuff,
2837 * cut it short at the end of the tvbuff.
2838 * That way, if this field is selected in
2839 * Wireshark, we don't highlight stuff past
2840 * the end of the data.
2842 /* XXX - what to do, if we don't have a tvb? */
2844 length_remaining = tvb_length_remaining(tvb, start);
2845 if (*item_length < 0 ||
2846 (*item_length > 0 &&
2847 (length_remaining < *item_length)))
2848 *item_length = length_remaining;
2851 if (*item_length < 0) {
2852 THROW(ReportedBoundsError);
2860 new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
2861 gint start, gint item_length)
2867 fi->hfinfo = hfinfo;
2869 fi->start+=(tvb)?TVB_RAW_OFFSET(tvb):0;
2870 fi->length = item_length;
2873 if (!PTREE_DATA(tree)->visible)
2874 FI_SET_FLAG(fi, FI_HIDDEN);
2875 fvalue_init(&fi->value, fi->hfinfo->type);
2878 /* add the data source tvbuff */
2879 fi->ds_tvb=tvb?TVB_GET_DS_TVB(tvb):NULL;
2885 alloc_field_info(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2888 header_field_info *hfinfo;
2891 hfinfo = get_hfi_and_length(hfindex, tvb, start, length, &item_length);
2892 return new_field_info(tree, hfinfo, tvb, start, item_length);
2895 /* If the protocol tree is to be visible, set the representation of a
2896 proto_tree entry with the name of the field for the item and with
2897 the value formatted with the supplied printf-style format and
2900 proto_tree_set_representation_value(proto_item *pi, const char *format, va_list ap)
2902 int ret; /*tmp return value */
2904 field_info *fi = PITEM_FINFO(pi);
2906 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
2907 ITEM_LABEL_NEW(fi->rep);
2909 ret = g_snprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
2910 "%s: ", fi->hfinfo->name);
2911 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH)) {
2912 /* That's all we can put in the representation. */
2913 fi->rep->representation[ITEM_LABEL_LENGTH - 1] = '\0';
2917 ret = g_vsnprintf(fi->rep->representation + replen,
2918 ITEM_LABEL_LENGTH - replen, format, ap);
2919 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH - replen))
2920 fi->rep->representation[ITEM_LABEL_LENGTH - 1] = '\0';
2924 /* If the protocol tree is to be visible, set the representation of a
2925 proto_tree entry with the representation formatted with the supplied
2926 printf-style format and argument list. */
2928 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap)
2930 int ret; /*tmp return value */
2931 field_info *fi = PITEM_FINFO(pi);
2933 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
2934 ITEM_LABEL_NEW(fi->rep);
2935 ret = g_vsnprintf(fi->rep->representation, ITEM_LABEL_LENGTH, format, ap);
2936 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
2937 fi->rep->representation[ITEM_LABEL_LENGTH - 1] = '\0';
2941 /* Set text of proto_item after having already been created. */
2943 proto_item_set_text(proto_item *pi, const char *format, ...)
2945 field_info *fi = NULL;
2952 fi = PITEM_FINFO(pi);
2955 ITEM_LABEL_FREE(fi->rep);
2958 va_start(ap, format);
2959 proto_tree_set_representation(pi, format, ap);
2963 /* Append to text of proto_item after having already been created. */
2965 proto_item_append_text(proto_item *pi, const char *format, ...)
2967 field_info *fi = NULL;
2970 int ret; /*tmp return value */
2976 fi = PITEM_FINFO(pi);
2981 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
2982 va_start(ap, format);
2985 * If we don't already have a representation,
2986 * generate the default representation.
2988 if (fi->rep == NULL) {
2989 ITEM_LABEL_NEW(fi->rep);
2990 proto_item_fill_label(fi, fi->rep->representation);
2993 curlen = strlen(fi->rep->representation);
2994 if (ITEM_LABEL_LENGTH > curlen) {
2995 ret = g_vsnprintf(fi->rep->representation + curlen,
2996 ITEM_LABEL_LENGTH - curlen, format, ap);
2997 if ((ret == -1) || (ret >= (int)(ITEM_LABEL_LENGTH - curlen)))
2998 fi->rep->representation[ITEM_LABEL_LENGTH - 1] = '\0';
3005 proto_item_set_len(proto_item *pi, gint length)
3011 fi = PITEM_FINFO(pi);
3012 DISSECTOR_ASSERT(length >= 0);
3013 fi->length = length;
3017 * Sets the length of the item based on its start and on the specified
3018 * offset, which is the offset past the end of the item; as the start
3019 * in the item is relative to the beginning of the data source tvbuff,
3020 * we need to pass in a tvbuff - the end offset is relative to the beginning
3024 proto_item_set_end(proto_item *pi, tvbuff_t *tvb, gint end)
3030 fi = PITEM_FINFO(pi);
3031 end += TVB_RAW_OFFSET(tvb);
3032 DISSECTOR_ASSERT(end >= fi->start);
3033 fi->length = end - fi->start;
3037 proto_item_get_len(proto_item *pi)
3039 field_info *fi = PITEM_FINFO(pi);
3044 /** clear flags according to the mask and set new flag values */
3045 #define FI_REPLACE_FLAGS(fi, mask, flags_in) { \
3046 (fi->flags = (fi)->flags & ~(mask)); \
3047 (fi->flags = (fi)->flags | (flags_in)); \
3051 proto_item_set_expert_flags(proto_item *pi, int group, int severity)
3053 if(pi == NULL || pi->finfo == NULL)
3056 /* only change things if severity is worse or at least equal than before */
3057 if(severity >= FI_GET_FLAG(pi->finfo, PI_SEVERITY_MASK)) {
3058 FI_REPLACE_FLAGS(pi->finfo, PI_GROUP_MASK, group);
3059 FI_REPLACE_FLAGS(pi->finfo, PI_SEVERITY_MASK, severity);
3070 proto_tree_create_root(void)
3074 /* Initialize the proto_node */
3075 PROTO_NODE_NEW(pnode);
3076 pnode->parent = NULL;
3077 pnode->finfo = NULL;
3078 pnode->tree_data = g_new(tree_data_t, 1);
3080 /* Initialize the tree_data_t */
3081 pnode->tree_data->interesting_hfids =
3082 g_hash_table_new(g_direct_hash, g_direct_equal);
3084 /* Set the default to FALSE so it's easier to
3085 * find errors; if we expect to see the protocol tree
3086 * but for some reason the default 'visible' is not
3087 * changed, then we'll find out very quickly. */
3088 pnode->tree_data->visible = FALSE;
3090 /* Keep track of the number of children */
3091 pnode->tree_data->count = 0;
3093 return (proto_tree*) pnode;
3097 /* "prime" a proto_tree with a single hfid that a dfilter
3098 * is interested in. */
3100 proto_tree_prime_hfid(proto_tree *tree, gint hfid)
3102 header_field_info *hfinfo;
3104 g_hash_table_insert(PTREE_DATA(tree)->interesting_hfids,
3105 GINT_TO_POINTER(hfid), g_ptr_array_new());
3107 PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
3108 /* this field is referenced by a filter so increase the refcount.
3109 also increase the refcount for the parent, i.e the protocol.
3111 hfinfo->ref_count++;
3112 /* only increase the refcount if there is a parent.
3113 if this is a protocol and not a field then parent will be -1
3114 and there is no parent to add any refcounting for.
3116 if (hfinfo->parent != -1) {
3117 header_field_info *parent_hfinfo;
3118 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
3119 parent_hfinfo->ref_count++;
3124 proto_item_add_subtree(proto_item *pi, gint idx) {
3130 fi = PITEM_FINFO(pi);
3131 DISSECTOR_ASSERT(idx >= 0 && idx < num_tree_types);
3132 fi->tree_type = idx;
3134 return (proto_tree*) pi;
3138 proto_item_get_subtree(proto_item *pi) {
3143 fi = PITEM_FINFO(pi);
3144 if ( (!fi) || (fi->tree_type == -1) )
3146 return (proto_tree*) pi;
3150 proto_item_get_parent(proto_item *ti) {
3157 proto_item_get_parent_nth(proto_item *ti, int gen) {
3170 proto_tree_get_parent(proto_tree *tree) {
3173 return (proto_item*) tree;
3177 proto_tree_get_root(proto_tree *tree) {
3180 while (tree->parent) {
3181 tree = tree->parent;
3187 proto_tree_move_item(proto_tree *tree, proto_item *fixed_item, proto_item *item_to_move)
3189 proto_item *curr_item;
3192 /*** cut item_to_move out ***/
3194 /* is item_to_move the first? */
3195 if(tree->first_child == item_to_move) {
3196 /* simply change first child to next */
3197 tree->first_child = item_to_move->next;
3199 /* find previous and change it's next */
3200 for(curr_item = tree->first_child; curr_item != NULL; curr_item = curr_item->next) {
3201 if(curr_item->next == item_to_move) {
3206 DISSECTOR_ASSERT(curr_item);
3208 curr_item->next = item_to_move->next;
3210 /* fix last_child if required */
3211 if(tree->last_child == item_to_move) {
3212 tree->last_child = curr_item;
3216 /*** insert to_move after fixed ***/
3217 item_to_move->next = fixed_item->next;
3218 fixed_item->next = item_to_move;
3219 if(tree->last_child == fixed_item) {
3220 tree->last_child = item_to_move;
3226 proto_register_protocol(const char *name, const char *short_name, const char *filter_name)
3228 protocol_t *protocol;
3229 header_field_info *hfinfo;
3231 char *existing_name;
3235 gboolean found_invalid;
3238 * Make sure there's not already a protocol with any of those
3239 * names. Crash if there is, as that's an error in the code
3240 * or an inappropriate plugin.
3241 * This situation has to be fixed to not register more than one
3242 * protocol with the same name.
3244 * This is done by reducing the number of strcmp (and alike) calls as much as possible,
3245 * as this significally slows down startup time.
3247 * Drawback: As a hash value is used to reduce insert time,
3248 * this might lead to a hash collision.
3249 * However, as we have around 500+ protocols and we're using a 32 bit int this is very,
3253 key = g_malloc (sizeof(gint));
3254 *key = g_str_hash(name);
3255 existing_name = g_hash_table_lookup(proto_names, key);
3256 if (existing_name != NULL) {
3257 /* g_error will terminate the program */
3258 g_error("Duplicate protocol name \"%s\"!"
3259 " This might be caused by an inappropriate plugin or a development error.", name);
3261 g_hash_table_insert(proto_names, key, (gpointer)name);
3263 key = g_malloc (sizeof(gint));
3264 *key = g_str_hash(short_name);
3265 existing_name = g_hash_table_lookup(proto_short_names, key);
3266 if (existing_name != NULL) {
3267 g_error("Duplicate protocol short_name \"%s\"!"
3268 " This might be caused by an inappropriate plugin or a development error.", short_name);
3270 g_hash_table_insert(proto_short_names, key, (gpointer)short_name);
3272 found_invalid = FALSE;
3273 for (i = 0; i < strlen(filter_name); i++) {
3275 if (!(islower(c) || isdigit(c) || c == '-' || c == '_' || c == '.')) {
3276 found_invalid = TRUE;
3279 if (found_invalid) {
3280 g_error("Protocol filter name \"%s\" has one or more invalid characters."
3281 " Allowed are lower characters, digits, '-', '_' and '.'."
3282 " This might be caused by an inappropriate plugin or a development error.", filter_name);
3284 key = g_malloc (sizeof(gint));
3285 *key = g_str_hash(filter_name);
3286 existing_name = g_hash_table_lookup(proto_filter_names, key);
3287 if (existing_name != NULL) {
3288 g_error("Duplicate protocol filter_name \"%s\"!"
3289 " This might be caused by an inappropriate plugin or a development error.", filter_name);
3291 g_hash_table_insert(proto_filter_names, key, (gpointer)filter_name);
3293 /* Add this protocol to the list of known protocols; the list
3294 is sorted by protocol short name. */
3295 protocol = g_malloc(sizeof (protocol_t));
3296 protocol->name = name;
3297 protocol->short_name = short_name;
3298 protocol->filter_name = filter_name;
3299 protocol->fields = NULL;
3300 protocol->is_enabled = TRUE; /* protocol is enabled by default */
3301 protocol->can_toggle = TRUE;
3302 /* list will be sorted later by name, when all protocols completed registering */
3303 protocols = g_list_append(protocols, protocol);
3305 /* Here we do allocate a new header_field_info struct */
3306 hfinfo = g_mem_chunk_alloc(gmc_hfinfo);
3307 hfinfo->name = name;
3308 hfinfo->abbrev = filter_name;
3309 hfinfo->type = FT_PROTOCOL;
3310 hfinfo->strings = protocol;
3311 hfinfo->bitmask = 0;
3312 hfinfo->bitshift = 0;
3313 hfinfo->ref_count = 0;
3314 hfinfo->blurb = NULL;
3315 hfinfo->parent = -1; /* this field differentiates protos and fields */
3317 proto_id = proto_register_field_init(hfinfo, hfinfo->parent);
3318 protocol->proto_id = proto_id;
3323 * Routines to use to iterate over the protocols.
3324 * The argument passed to the iterator routines is an opaque cookie to
3325 * their callers; it's the GList pointer for the current element in
3327 * The ID of the protocol is returned, or -1 if there is no protocol.
3330 proto_get_first_protocol(void **cookie)
3332 protocol_t *protocol;
3334 if (protocols == NULL)
3336 *cookie = protocols;
3337 protocol = protocols->data;
3338 return protocol->proto_id;
3342 proto_get_next_protocol(void **cookie)
3344 GList *list_item = *cookie;
3345 protocol_t *protocol;
3347 list_item = g_list_next(list_item);
3348 if (list_item == NULL)
3350 *cookie = list_item;
3351 protocol = list_item->data;
3352 return protocol->proto_id;
3356 proto_get_first_protocol_field(int proto_id, void **cookie)
3358 protocol_t *protocol = find_protocol_by_id(proto_id);
3359 hf_register_info *ptr;
3361 if ((protocol == NULL) || (protocol->fields == NULL))
3364 *cookie = protocol->fields;
3365 ptr = protocol->fields->data;
3366 return &ptr->hfinfo;
3370 proto_get_next_protocol_field(void **cookie)
3372 GList *list_item = *cookie;
3373 hf_register_info *ptr;
3375 list_item = g_list_next(list_item);
3376 if (list_item == NULL)
3379 *cookie = list_item;
3380 ptr = list_item->data;
3381 return &ptr->hfinfo;
3385 find_protocol_by_id(int proto_id)
3387 header_field_info *hfinfo;
3392 PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
3393 DISSECTOR_ASSERT(hfinfo->type==FT_PROTOCOL);
3394 return (protocol_t *)hfinfo->strings;
3397 static gint compare_filter_name(gconstpointer proto_arg,
3398 gconstpointer filter_name)
3400 const protocol_t *protocol = proto_arg;
3401 const gchar* f_name = filter_name;
3403 return (strcmp(protocol->filter_name, f_name));
3407 proto_get_id(protocol_t *protocol)
3409 return protocol->proto_id;
3412 int proto_get_id_by_filter_name(const gchar* filter_name)
3415 protocol_t *protocol;
3417 list_entry = g_list_find_custom(protocols, filter_name,
3418 compare_filter_name);
3419 if (list_entry == NULL)
3421 protocol = list_entry->data;
3422 return protocol->proto_id;
3426 proto_get_protocol_name(int proto_id)
3428 protocol_t *protocol;
3430 protocol = find_protocol_by_id(proto_id);
3431 return protocol->name;
3435 proto_get_protocol_short_name(protocol_t *protocol)
3437 if (protocol == NULL)
3439 return protocol->short_name;
3443 proto_get_protocol_filter_name(int proto_id)
3445 protocol_t *protocol;
3447 protocol = find_protocol_by_id(proto_id);
3448 return protocol->filter_name;
3452 proto_is_protocol_enabled(protocol_t *protocol)
3454 return protocol->is_enabled;
3458 proto_can_toggle_protocol(int proto_id)
3460 protocol_t *protocol;
3462 protocol = find_protocol_by_id(proto_id);
3463 return protocol->can_toggle;
3467 proto_set_decoding(int proto_id, gboolean enabled)
3469 protocol_t *protocol;
3471 protocol = find_protocol_by_id(proto_id);
3472 DISSECTOR_ASSERT(protocol->can_toggle);
3473 protocol->is_enabled = enabled;
3477 proto_set_cant_toggle(int proto_id)
3479 protocol_t *protocol;
3481 protocol = find_protocol_by_id(proto_id);
3482 protocol->can_toggle = FALSE;
3485 /* for use with static arrays only, since we don't allocate our own copies
3486 of the header_field_info struct contained within the hf_register_info struct */
3488 proto_register_field_array(int parent, hf_register_info *hf, int num_records)
3491 hf_register_info *ptr = hf;
3494 proto = find_protocol_by_id(parent);
3495 for (i = 0; i < num_records; i++, ptr++) {
3497 * Make sure we haven't registered this yet.
3498 * Most fields have variables associated with them
3499 * that are initialized to -1; some have array elements,
3500 * or possibly uninitialized variables, so we also allow
3501 * 0 (which is unlikely to be the field ID we get back
3502 * from "proto_register_field_init()").
3504 if (*ptr->p_id != -1 && *ptr->p_id != 0) {
3506 "Duplicate field detected in call to proto_register_field_array: %s is already registered\n",
3507 ptr->hfinfo.abbrev);
3511 if (proto != NULL) {
3512 if (proto->fields == NULL) {
3513 proto->fields = g_list_append(NULL, ptr);
3514 proto->last_field = proto->fields;
3517 g_list_append(proto->last_field, ptr)->next;
3520 field_id = proto_register_field_init(&ptr->hfinfo, parent);
3521 *ptr->p_id = field_id;
3526 proto_register_field_init(header_field_info *hfinfo, int parent)
3528 /* The field must have a name (with length > 0) */
3529 DISSECTOR_ASSERT(hfinfo->name && hfinfo->name[0]);
3531 /* fields with an empty string for an abbreviation aren't filterable */
3532 DISSECTOR_ASSERT(hfinfo->abbrev);
3534 /* These types of fields are allowed to have value_strings, true_false_strings or a protocol_t struct*/
3535 DISSECTOR_ASSERT((hfinfo->strings == NULL) || (
3536 (hfinfo->type == FT_UINT8) ||
3537 (hfinfo->type == FT_UINT16) ||
3538 (hfinfo->type == FT_UINT24) ||
3539 (hfinfo->type == FT_UINT32) ||
3540 (hfinfo->type == FT_INT8) ||
3541 (hfinfo->type == FT_INT16) ||
3542 (hfinfo->type == FT_INT24) ||
3543 (hfinfo->type == FT_INT32) ||
3544 (hfinfo->type == FT_BOOLEAN) ||
3545 (hfinfo->type == FT_PROTOCOL) ||
3546 (hfinfo->type == FT_FRAMENUM) ));
3548 switch (hfinfo->type) {
3558 /* Require integral types (other than frame number, which is
3559 always displayed in decimal) to have a number base */
3560 DISSECTOR_ASSERT(hfinfo->display != BASE_NONE);
3564 /* Don't allow bitfields or value strings for frame numbers */
3565 DISSECTOR_ASSERT(hfinfo->bitmask == 0);
3566 DISSECTOR_ASSERT(hfinfo->strings == NULL);
3572 /* if this is a bitfield, compute bitshift */
3573 if (hfinfo->bitmask) {
3574 while ((hfinfo->bitmask & (1 << hfinfo->bitshift)) == 0)
3578 hfinfo->parent = parent;
3579 hfinfo->same_name_next = NULL;
3580 hfinfo->same_name_prev = NULL;
3582 /* if we always add and never delete, then id == len - 1 is correct */
3583 if(gpa_hfinfo.len>=gpa_hfinfo.allocated_len){
3584 if(!gpa_hfinfo.hfi){
3585 gpa_hfinfo.allocated_len=1000;
3586 gpa_hfinfo.hfi=g_malloc(sizeof(header_field_info *)*1000);
3588 gpa_hfinfo.allocated_len+=1000;
3589 gpa_hfinfo.hfi=g_realloc(gpa_hfinfo.hfi, sizeof(header_field_info *)*gpa_hfinfo.allocated_len);
3592 gpa_hfinfo.hfi[gpa_hfinfo.len]=hfinfo;
3594 hfinfo->id = gpa_hfinfo.len - 1;
3596 /* if we have real names, enter this field in the name tree */
3597 if ((hfinfo->name[0] != 0) && (hfinfo->abbrev[0] != 0 )) {
3599 header_field_info *same_name_hfinfo, *same_name_next_hfinfo;
3603 /* Check that the filter name (abbreviation) is legal;
3604 * it must contain only alphanumerics, '-', "_", and ".". */
3605 for (p = hfinfo->abbrev; (c = *p) != '\0'; p++) {
3606 if (!(isalnum(c) || c == '-' || c == '_' || c == '.')) {
3607 fprintf(stderr, "OOPS: '%c' in '%s'\n", c, hfinfo->abbrev);
3608 DISSECTOR_ASSERT(isalnum(c) || c == '-' || c == '_' ||
3612 /* We allow multiple hfinfo's to be registered under the same
3613 * abbreviation. This was done for X.25, as, depending
3614 * on whether it's modulo-8 or modulo-128 operation,
3615 * some bitfield fields may be in different bits of
3616 * a byte, and we want to be able to refer to that field
3617 * with one name regardless of whether the packets
3618 * are modulo-8 or modulo-128 packets. */
3619 same_name_hfinfo = g_tree_lookup(gpa_name_tree, hfinfo->abbrev);
3620 if (same_name_hfinfo) {
3621 /* There's already a field with this name.
3622 * Put it after that field in the list of
3623 * fields with this name, then allow the code
3624 * after this if{} block to replace the old
3625 * hfinfo with the new hfinfo in the GTree. Thus,
3626 * we end up with a linked-list of same-named hfinfo's,
3627 * with the root of the list being the hfinfo in the GTree */
3628 same_name_next_hfinfo =
3629 same_name_hfinfo->same_name_next;
3631 hfinfo->same_name_next = same_name_next_hfinfo;
3632 if (same_name_next_hfinfo)
3633 same_name_next_hfinfo->same_name_prev = hfinfo;
3635 same_name_hfinfo->same_name_next = hfinfo;
3636 hfinfo->same_name_prev = same_name_hfinfo;
3638 g_tree_insert(gpa_name_tree, (gpointer) (hfinfo->abbrev), hfinfo);
3645 proto_register_subtree_array(gint *const *indices, int num_indices)
3648 gint *const *ptr = indices;
3651 * If we've already allocated the array of tree types, expand
3652 * it; this lets plugins such as mate add tree types after
3653 * the initial startup. (If we haven't already allocated it,
3654 * we don't allocate it; on the first pass, we just assign
3655 * ett values and keep track of how many we've assigned, and
3656 * when we're finished registering all dissectors we allocate
3657 * the array, so that we do only one allocation rather than
3658 * wasting CPU time and memory by growing the array for each
3659 * dissector that registers ett values.)
3661 if (tree_is_expanded != NULL) {
3663 g_realloc(tree_is_expanded,
3664 (num_tree_types+num_indices)*sizeof (gboolean));
3665 memset(tree_is_expanded + num_tree_types, 0,
3666 num_indices*sizeof (gboolean));
3670 * Assign "num_indices" subtree numbers starting at "num_tree_types",
3671 * returning the indices through the pointers in the array whose
3672 * first element is pointed to by "indices", and update
3673 * "num_tree_types" appropriately.
3675 for (i = 0; i < num_indices; i++, ptr++, num_tree_types++)
3676 **ptr = num_tree_types;
3680 proto_item_fill_label(field_info *fi, gchar *label_str)
3682 header_field_info *hfinfo = fi->hfinfo;
3688 guint32 n_addr; /* network-order IPv4 address */
3690 int ret; /*tmp return value */
3692 switch(hfinfo->type) {
3695 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3696 "%s", hfinfo->name);
3697 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3698 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3702 fill_label_boolean(fi, label_str);
3707 bytes = fvalue_get(&fi->value);
3709 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3710 "%s: %s", hfinfo->name,
3711 bytes_to_str(bytes, fvalue_length(&fi->value)));
3712 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3713 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3716 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3717 "%s: <MISSING>", hfinfo->name);
3718 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3719 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3723 /* Four types of integers to take care of:
3724 * Bitfield, with val_string
3725 * Bitfield, w/o val_string
3726 * Non-bitfield, with val_string
3727 * Non-bitfield, w/o val_string
3734 if (hfinfo->bitmask) {
3735 if (hfinfo->strings) {
3736 fill_label_enumerated_bitfield(fi, label_str);
3739 fill_label_numeric_bitfield(fi, label_str);
3743 if (hfinfo->strings) {
3744 fill_label_enumerated_uint(fi, label_str);
3747 fill_label_uint(fi, label_str);
3753 fill_label_uint64(fi, label_str);
3760 DISSECTOR_ASSERT(!hfinfo->bitmask);
3761 if (hfinfo->strings) {
3762 fill_label_enumerated_int(fi, label_str);
3765 fill_label_int(fi, label_str);
3770 fill_label_int64(fi, label_str);
3774 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3775 "%s: %." STRINGIFY(FLT_DIG) "f",
3776 hfinfo->name, fvalue_get_floating(&fi->value));
3777 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3778 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3782 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3783 "%s: %." STRINGIFY(DBL_DIG) "g",
3784 hfinfo->name, fvalue_get_floating(&fi->value));
3785 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3786 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3789 case FT_ABSOLUTE_TIME:
3790 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3791 "%s: %s", hfinfo->name,
3792 abs_time_to_str(fvalue_get(&fi->value)));
3793 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3794 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3797 case FT_RELATIVE_TIME:
3798 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3799 "%s: %s seconds", hfinfo->name,
3800 rel_time_to_secs_str(fvalue_get(&fi->value)));
3801 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3802 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3806 integer = fvalue_get_uinteger(&fi->value);
3807 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3808 "%s: %s (0x%08X)", hfinfo->name,
3809 get_ipxnet_name(integer), integer);
3810 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3811 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3815 bytes = fvalue_get(&fi->value);
3816 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3817 "%s: %s (%s)", hfinfo->name,
3818 get_ether_name(bytes),
3819 ether_to_str(bytes));
3820 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3821 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3825 ipv4 = fvalue_get(&fi->value);
3826 n_addr = ipv4_get_net_order_addr(ipv4);
3827 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3828 "%s: %s (%s)", hfinfo->name,
3829 get_hostname(n_addr),
3830 ip_to_str((guint8*)&n_addr));
3831 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3832 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3836 bytes = fvalue_get(&fi->value);
3837 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3838 "%s: %s (%s)", hfinfo->name,
3839 get_hostname6((struct e_in6_addr *)bytes),
3840 ip6_to_str((struct e_in6_addr*)bytes));
3841 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3842 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3846 guid = fvalue_get(&fi->value);
3847 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3848 "%s: %s", hfinfo->name,
3850 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3851 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3855 bytes = fvalue_get(&fi->value);
3856 name = (oid_resolv_enabled()) ? get_oid_name(bytes, fvalue_length(&fi->value)) : NULL;
3858 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3859 "%s: %s (%s)", hfinfo->name,
3860 oid_to_str(bytes, fvalue_length(&fi->value)), name);
3862 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3863 "%s: %s", hfinfo->name,
3864 oid_to_str(bytes, fvalue_length(&fi->value)));
3866 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3867 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3872 case FT_UINT_STRING:
3873 bytes = fvalue_get(&fi->value);
3874 if(strlen(bytes) > ITEM_LABEL_LENGTH) {
3875 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3876 "%s [truncated]: %s", hfinfo->name,
3877 format_text(bytes, strlen(bytes)));
3879 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3880 "%s: %s", hfinfo->name,
3881 format_text(bytes, strlen(bytes)));
3883 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3884 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3888 g_error("hfinfo->type %d (%s) not handled\n",
3890 ftype_name(hfinfo->type));
3891 DISSECTOR_ASSERT_NOT_REACHED();
3897 fill_label_boolean(field_info *fi, gchar *label_str)
3899 char *p = label_str;
3900 int bitfield_byte_length = 0, bitwidth;
3901 guint32 unshifted_value;
3903 int ret; /*tmp return value */
3905 header_field_info *hfinfo = fi->hfinfo;
3906 const true_false_string *tfstring = &tfs_true_false;
3908 if (hfinfo->strings) {
3909 tfstring = (const struct true_false_string*) hfinfo->strings;
3912 value = fvalue_get_uinteger(&fi->value);
3913 if (hfinfo->bitmask) {
3914 /* Figure out the bit width */
3915 bitwidth = hfinfo_bitwidth(hfinfo);
3918 unshifted_value = value;
3919 if (hfinfo->bitshift > 0) {
3920 unshifted_value <<= hfinfo->bitshift;
3923 /* Create the bitfield first */
3924 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
3925 bitfield_byte_length = p - label_str;
3928 /* Fill in the textual info */
3929 ret = g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
3930 "%s: %s", hfinfo->name,
3931 value ? tfstring->true_string : tfstring->false_string);
3932 if ((ret == -1) || (ret >= (ITEM_LABEL_LENGTH - bitfield_byte_length)))
3933 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3937 /* Fills data for bitfield ints with val_strings */
3939 fill_label_enumerated_bitfield(field_info *fi, gchar *label_str)
3941 const char *format = NULL;
3943 int bitfield_byte_length, bitwidth;
3944 guint32 unshifted_value;
3946 int ret; /*tmp return value */
3948 header_field_info *hfinfo = fi->hfinfo;
3950 /* Figure out the bit width */
3951 bitwidth = hfinfo_bitwidth(hfinfo);
3953 /* Pick the proper format string */
3954 format = hfinfo_uint_vals_format(hfinfo);
3957 unshifted_value = fvalue_get_uinteger(&fi->value);
3958 value = unshifted_value;
3959 if (hfinfo->bitshift > 0) {
3960 unshifted_value <<= hfinfo->bitshift;
3963 /* Create the bitfield first */
3964 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
3965 bitfield_byte_length = p - label_str;
3967 /* Fill in the textual info using stored (shifted) value */
3968 ret = g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
3969 format, hfinfo->name,
3970 val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
3971 if ((ret == -1) || (ret >= (ITEM_LABEL_LENGTH - bitfield_byte_length)))
3972 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3976 fill_label_numeric_bitfield(field_info *fi, gchar *label_str)
3978 const char *format = NULL;
3980 int bitfield_byte_length, bitwidth;
3981 guint32 unshifted_value;
3983 int ret; /*tmp return value */
3985 header_field_info *hfinfo = fi->hfinfo;
3987 /* Figure out the bit width */
3988 bitwidth = hfinfo_bitwidth(hfinfo);
3990 /* Pick the proper format string */
3991 format = hfinfo_uint_format(hfinfo);
3994 unshifted_value = fvalue_get_uinteger(&fi->value);
3995 value = unshifted_value;
3996 if (hfinfo->bitshift > 0) {
3997 unshifted_value <<= hfinfo->bitshift;
4000 /* Create the bitfield using */
4001 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
4002 bitfield_byte_length = p - label_str;
4004 /* Fill in the textual info using stored (shifted) value */
4005 if (IS_BASE_DUAL(hfinfo->display)) {
4006 ret = g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
4007 format, hfinfo->name, value, value);
4009 ret = g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
4010 format, hfinfo->name, value);
4012 if ((ret == -1) || (ret >= (ITEM_LABEL_LENGTH - bitfield_byte_length)))
4013 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4018 fill_label_enumerated_uint(field_info *fi, gchar *label_str)
4020 const char *format = NULL;
4021 header_field_info *hfinfo = fi->hfinfo;
4023 int ret; /*tmp return value */
4025 /* Pick the proper format string */
4026 format = hfinfo_uint_vals_format(hfinfo);
4028 value = fvalue_get_uinteger(&fi->value);
4030 /* Fill in the textual info */
4031 if (hfinfo->display & BASE_RANGE_STRING) {
4032 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4033 format, hfinfo->name,
4034 rval_to_str(value, hfinfo->strings, "Unknown"), value);
4036 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4037 format, hfinfo->name,
4038 val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
4040 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4041 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4045 fill_label_uint(field_info *fi, gchar *label_str)
4047 const char *format = NULL;
4048 header_field_info *hfinfo = fi->hfinfo;
4050 int ret; /*tmp return value */
4052 /* Pick the proper format string */
4053 format = hfinfo_uint_format(hfinfo);
4054 value = fvalue_get_uinteger(&fi->value);
4056 /* Fill in the textual info */
4057 if (IS_BASE_DUAL(hfinfo->display)) {
4058 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4059 format, hfinfo->name, value, value);
4061 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4062 format, hfinfo->name, value);
4064 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4065 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4069 fill_label_uint64(field_info *fi, gchar *label_str)
4071 const char *format = NULL;
4072 header_field_info *hfinfo = fi->hfinfo;
4074 int ret; /*tmp return value */
4076 /* Pick the proper format string */
4077 format = hfinfo_uint64_format(hfinfo);
4078 value = fvalue_get_integer64(&fi->value);
4080 /* Fill in the textual info */
4081 if (IS_BASE_DUAL(hfinfo->display)) {
4082 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4083 format, hfinfo->name, value, value);
4085 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4086 format, hfinfo->name, value);
4088 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4089 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4093 fill_label_enumerated_int(field_info *fi, gchar *label_str)
4095 const char *format = NULL;
4096 header_field_info *hfinfo = fi->hfinfo;
4098 int ret; /*tmp return value */
4100 /* Pick the proper format string */
4101 format = hfinfo_int_vals_format(hfinfo);
4102 value = fvalue_get_sinteger(&fi->value);
4104 /* Fill in the textual info */
4105 if (hfinfo->display & BASE_RANGE_STRING) {
4106 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4107 format, hfinfo->name,
4108 rval_to_str(value, hfinfo->strings, "Unknown"), value);
4110 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4111 format, hfinfo->name,
4112 val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
4114 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4115 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4119 fill_label_int(field_info *fi, gchar *label_str)
4121 const char *format = NULL;
4122 header_field_info *hfinfo = fi->hfinfo;
4124 int ret; /*tmp return value */
4126 /* Pick the proper format string */
4127 format = hfinfo_int_format(hfinfo);
4128 value = fvalue_get_sinteger(&fi->value);
4130 /* Fill in the textual info */
4131 if (IS_BASE_DUAL(hfinfo->display)) {
4132 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4133 format, hfinfo->name, value, value);
4135 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4136 format, hfinfo->name, value);
4138 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4139 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4143 fill_label_int64(field_info *fi, gchar *label_str)
4145 const char *format = NULL;
4146 header_field_info *hfinfo = fi->hfinfo;
4148 int ret; /*tmp return value */
4150 /* Pick the proper format string */
4151 format = hfinfo_int64_format(hfinfo);
4152 value = fvalue_get_integer64(&fi->value);
4154 /* Fill in the textual info */
4155 if (IS_BASE_DUAL(hfinfo->display)) {
4156 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4157 format, hfinfo->name, value, value);
4159 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4160 format, hfinfo->name, value);
4162 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4163 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4167 hfinfo_bitwidth(header_field_info *hfinfo)
4171 if (!hfinfo->bitmask) {
4175 switch(hfinfo->type) {
4193 bitwidth = hfinfo->display; /* hacky? :) */
4196 DISSECTOR_ASSERT_NOT_REACHED();
4203 hfinfo_uint_vals_format(header_field_info *hfinfo)
4205 const char *format = NULL;
4207 /* bit operation to reset the potential BASE_RANGE_STRING (or others in
4209 switch(hfinfo->display & BASE_STRUCTURE_RESET) {
4212 format = "%s: %s (%u)";
4214 case BASE_OCT: /* I'm lazy */
4215 format = "%s: %s (%o)";
4219 switch(hfinfo->type) {
4221 format = "%s: %s (0x%02x)";
4224 format = "%s: %s (0x%04x)";
4227 format = "%s: %s (0x%06x)";
4230 format = "%s: %s (0x%08x)";
4233 DISSECTOR_ASSERT_NOT_REACHED();
4238 DISSECTOR_ASSERT_NOT_REACHED();
4245 hfinfo_uint_format(header_field_info *hfinfo)
4247 const char *format = NULL;
4249 /* Pick the proper format string */
4250 if (hfinfo->type == FT_FRAMENUM) {
4252 * Frame numbers are always displayed in decimal.
4256 switch(hfinfo->display) {
4261 switch(hfinfo->type) {
4263 format = "%s: %u (0x%02x)";
4266 format = "%s: %u (0x%04x)";
4269 format = "%s: %u (0x%06x)";
4272 format = "%s: %u (0x%08x)";
4275 DISSECTOR_ASSERT_NOT_REACHED();
4279 case BASE_OCT: /* I'm lazy */
4283 switch(hfinfo->type) {
4285 format = "%s: 0x%02x";
4288 format = "%s: 0x%04x";
4291 format = "%s: 0x%06x";
4294 format = "%s: 0x%08x";
4297 DISSECTOR_ASSERT_NOT_REACHED();
4302 switch(hfinfo->type) {
4304 format = "%s: 0x%02x (%u)";
4307 format = "%s: 0x%04x (%u)";
4310 format = "%s: 0x%06x (%u)";
4313 format = "%s: 0x%08x (%u)";
4316 DISSECTOR_ASSERT_NOT_REACHED();
4321 DISSECTOR_ASSERT_NOT_REACHED();
4329 hfinfo_int_vals_format(header_field_info *hfinfo)
4331 const char *format = NULL;
4333 /* bit operation to reset the potential BASE_RANGE_STRING (or others in
4335 switch(hfinfo->display & BASE_STRUCTURE_RESET) {
4338 format = "%s: %s (%d)";
4340 case BASE_OCT: /* I'm lazy */
4341 format = "%s: %s (%o)";
4345 switch(hfinfo->type) {
4347 format = "%s: %s (0x%02x)";
4350 format = "%s: %s (0x%04x)";
4353 format = "%s: %s (0x%06x)";
4356 format = "%s: %s (0x%08x)";
4359 DISSECTOR_ASSERT_NOT_REACHED();
4364 DISSECTOR_ASSERT_NOT_REACHED();
4371 hfinfo_uint64_format(header_field_info *hfinfo)
4373 const char *format = NULL;
4375 /* Pick the proper format string */
4376 switch(hfinfo->display) {
4378 format = "%s: %" PRIu64;
4381 format = "%s: %" PRIu64 " (%" PRIx64 ")";
4383 case BASE_OCT: /* I'm lazy */
4384 format = "%s: %" PRIo64;
4387 format = "%s: 0x%016" PRIx64;
4390 format = "%s: 0x%016" PRIx64 " (%" PRIu64 ")";
4393 DISSECTOR_ASSERT_NOT_REACHED();
4400 hfinfo_int_format(header_field_info *hfinfo)
4402 const char *format = NULL;
4404 /* Pick the proper format string */
4405 switch(hfinfo->display) {
4410 switch(hfinfo->type) {
4412 format = "%s: %d (0x%02x)";
4415 format = "%s: %d (0x%04x)";
4418 format = "%s: %d (0x%06x)";
4421 format = "%s: %d (0x%08x)";
4424 DISSECTOR_ASSERT_NOT_REACHED();
4427 case BASE_OCT: /* I'm lazy */
4431 switch(hfinfo->type) {
4433 format = "%s: 0x%02x";
4436 format = "%s: 0x%04x";
4439 format = "%s: 0x%06x";
4442 format = "%s: 0x%08x";
4445 DISSECTOR_ASSERT_NOT_REACHED();
4450 switch(hfinfo->type) {
4452 format = "%s: 0x%02x (%d)";
4455 format = "%s: 0x%04x (%d)";
4458 format = "%s: 0x%06x (%d)";
4461 format = "%s: 0x%08x (%d)";
4464 DISSECTOR_ASSERT_NOT_REACHED();
4469 DISSECTOR_ASSERT_NOT_REACHED();
4476 hfinfo_int64_format(header_field_info *hfinfo)
4478 const char *format = NULL;
4480 /* Pick the proper format string */
4481 switch(hfinfo->display) {
4483 format = "%s: %" PRId64;
4486 format = "%s: %" PRId64 " (%" PRIx64 ")";
4488 case BASE_OCT: /* I'm lazy */
4489 format = "%s: %" PRIo64;
4492 format = "%s: 0x%016" PRIx64;
4495 format = "%s: 0x%016" PRIx64 " (%" PRId64 ")";
4498 DISSECTOR_ASSERT_NOT_REACHED();
4507 proto_registrar_n(void)
4509 return gpa_hfinfo.len;
4513 proto_registrar_get_name(int n)
4515 header_field_info *hfinfo;
4517 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
4518 return hfinfo->name;
4522 proto_registrar_get_abbrev(int n)
4524 header_field_info *hfinfo;
4526 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
4527 return hfinfo->abbrev;
4531 proto_registrar_get_ftype(int n)
4533 header_field_info *hfinfo;
4535 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
4536 return hfinfo->type;
4540 proto_registrar_get_parent(int n)
4542 header_field_info *hfinfo;
4544 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
4545 return hfinfo->parent;
4549 proto_registrar_is_protocol(int n)
4551 header_field_info *hfinfo;
4553 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
4554 return (hfinfo->parent == -1 ? TRUE : FALSE);
4557 /* Returns length of field in packet (not necessarily the length
4558 * in our internal representation, as in the case of IPv4).
4559 * 0 means undeterminable at time of registration
4560 * -1 means the field is not registered. */
4562 proto_registrar_get_length(int n)
4564 header_field_info *hfinfo;
4566 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
4567 return ftype_length(hfinfo->type);
4572 /* Looks for a protocol or a field in a proto_tree. Returns TRUE if
4573 * it exists anywhere, or FALSE if it exists nowhere. */
4575 proto_check_for_protocol_or_field(proto_tree* tree, int id)
4577 GPtrArray *ptrs = proto_get_finfo_ptr_array(tree, id);
4582 else if (g_ptr_array_len(ptrs) > 0) {
4590 /* Return GPtrArray* of field_info pointers for all hfindex that appear in tree.
4591 * This only works if the hfindex was "primed" before the dissection
4592 * took place, as we just pass back the already-created GPtrArray*.
4593 * The caller should *not* free the GPtrArray*; proto_tree_free_node()
4596 proto_get_finfo_ptr_array(proto_tree *tree, int id)
4598 return g_hash_table_lookup(PTREE_DATA(tree)->interesting_hfids,
4599 GINT_TO_POINTER(id));
4603 /* Helper struct for proto_find_info() and proto_all_finfos() */
4609 /* Helper function for proto_find_info() */
4611 find_finfo(proto_node *node, gpointer data)
4613 field_info *fi = PITEM_FINFO(node);
4614 if (fi && fi->hfinfo) {
4615 if (fi->hfinfo->id == ((ffdata_t*)data)->id) {
4616 g_ptr_array_add(((ffdata_t*)data)->array, fi);
4620 /* Don't stop traversing. */
4624 /* Return GPtrArray* of field_info pointers for all hfindex that appear in a tree.
4625 * This works on any proto_tree, primed or unprimed, but actually searches
4626 * the tree, so it is slower than using proto_get_finfo_ptr_array on a primed tree.
4627 * The caller does need to free the returned GPtrArray with
4628 * g_ptr_array_free(<array>, FALSE).
4631 proto_find_finfo(proto_tree *tree, int id)
4635 ffdata.array = g_ptr_array_new();
4638 proto_tree_traverse_pre_order(tree, find_finfo, &ffdata);
4640 return ffdata.array;
4643 /* Helper function for proto_all_finfos() */
4645 every_finfo(proto_node *node, gpointer data)
4647 field_info *fi = PITEM_FINFO(node);
4648 if (fi && fi->hfinfo) {
4649 g_ptr_array_add(((ffdata_t*)data)->array, fi);
4652 /* Don't stop traversing. */
4656 /* Return GPtrArray* of field_info pointers containing all hfindexes that appear in a tree. */
4658 proto_all_finfos(proto_tree *tree)
4662 ffdata.array = g_ptr_array_new();
4665 proto_tree_traverse_pre_order(tree, every_finfo, &ffdata);
4667 return ffdata.array;
4678 check_for_offset(proto_node *node, gpointer data)
4680 field_info *fi = PITEM_FINFO(node);
4681 offset_search_t *offsearch = data;
4683 /* !fi == the top most container node which holds nothing */
4684 if (fi && !PROTO_ITEM_IS_HIDDEN(node) && fi->ds_tvb && offsearch->tvb == fi->ds_tvb) {
4685 if (offsearch->offset >= (guint) fi->start &&
4686 offsearch->offset < (guint) (fi->start + fi->length)) {
4688 offsearch->finfo = fi;
4689 return FALSE; /* keep traversing */
4692 return FALSE; /* keep traversing */
4695 /* Search a proto_tree backwards (from leaves to root) looking for the field
4696 * whose start/length occupies 'offset' */
4697 /* XXX - I couldn't find an easy way to search backwards, so I search
4698 * forwards, w/o stopping. Therefore, the last finfo I find will the be
4699 * the one I want to return to the user. This algorithm is inefficient
4700 * and could be re-done, but I'd have to handle all the children and
4701 * siblings of each node myself. When I have more time I'll do that.
4704 proto_find_field_from_offset(proto_tree *tree, guint offset, tvbuff_t *tvb)
4706 offset_search_t offsearch;
4708 offsearch.offset = offset;
4709 offsearch.finfo = NULL;
4710 offsearch.tvb = tvb;
4712 proto_tree_traverse_pre_order(tree, check_for_offset, &offsearch);
4714 return offsearch.finfo;
4717 /* Dumps the protocols in the registration database to stdout. An independent
4718 * program can take this output and format it into nice tables or HTML or
4721 * There is one record per line. The fields are tab-delimited.
4723 * Field 1 = protocol name
4724 * Field 2 = protocol short name
4725 * Field 3 = protocol filter name
4728 proto_registrar_dump_protocols(void)
4730 protocol_t *protocol;
4732 void *cookie = NULL;
4734 for (i = proto_get_first_protocol(&cookie); i != -1;
4735 i = proto_get_next_protocol(&cookie)) {
4736 protocol = find_protocol_by_id(i);
4737 printf("%s\t%s\t%s\n", protocol->name, protocol->short_name,
4738 protocol->filter_name);
4742 /* Dumps the value_string and true/false strings for fields that have
4743 * them. There is one record per line. Fields are tab-delimited.
4744 * There are two types of records, Value String records and True/False
4745 * String records. The first field, 'V' or 'T', indicates the type
4751 * Field 2 = field abbreviation to which this value string corresponds
4752 * Field 3 = Integer value
4755 * True/False Strings
4756 * ------------------
4758 * Field 2 = field abbreviation to which this true/false string corresponds
4759 * Field 3 = True String
4760 * Field 4 = False String
4763 proto_registrar_dump_values(void)
4765 header_field_info *hfinfo, *parent_hfinfo;
4767 const value_string *vals;
4768 const true_false_string *tfs;
4770 len = gpa_hfinfo.len;
4771 for (i = 0; i < len ; i++) {
4772 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
4774 if (hfinfo->id == hf_text_only) {
4778 /* ignore protocols */
4779 if (proto_registrar_is_protocol(i)) {
4782 /* process header fields */
4785 * If this field isn't at the head of the list of
4786 * fields with this name, skip this field - all
4787 * fields with the same name are really just versions
4788 * of the same field stored in different bits, and
4789 * should have the same type/radix/value list, and
4790 * just differ in their bit masks. (If a field isn't
4791 * a bitfield, but can be, say, 1 or 2 bytes long,
4792 * it can just be made FT_UINT16, meaning the
4793 * *maximum* length is 2 bytes, and be used
4796 if (hfinfo->same_name_prev != NULL)
4799 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
4804 if (hfinfo->type == FT_UINT8 ||
4805 hfinfo->type == FT_UINT16 ||
4806 hfinfo->type == FT_UINT24 ||
4807 hfinfo->type == FT_UINT32 ||
4808 hfinfo->type == FT_UINT64 ||
4809 hfinfo->type == FT_INT8 ||
4810 hfinfo->type == FT_INT16 ||
4811 hfinfo->type == FT_INT24 ||
4812 hfinfo->type == FT_INT32 ||
4813 hfinfo->type == FT_INT64) {
4815 vals = hfinfo->strings;
4817 else if (hfinfo->type == FT_BOOLEAN) {
4818 tfs = hfinfo->strings;
4821 /* Print value strings? */
4824 while (vals[vi].strptr) {
4825 /* Print in the proper base */
4826 if (hfinfo->display == BASE_HEX) {
4827 printf("V\t%s\t0x%x\t%s\n",
4833 printf("V\t%s\t%u\t%s\n",
4842 /* Print true/false strings? */
4844 printf("T\t%s\t%s\t%s\n", hfinfo->abbrev,
4845 tfs->true_string, tfs->false_string);
4851 /* Dumps the contents of the registration database to stdout. An indepedent
4852 * program can take this output and format it into nice tables or HTML or
4855 * There is one record per line. Each record is either a protocol or a header
4856 * field, differentiated by the first field. The fields are tab-delimited.
4861 * Field 2 = descriptive protocol name
4862 * Field 3 = protocol abbreviation
4868 * Field 2 = descriptive field name
4869 * Field 3 = field abbreviation
4870 * Field 4 = type ( textual representation of the the ftenum type )
4871 * Field 5 = parent protocol abbreviation
4872 * Field 6 = blurb describing field
4876 * Field 2 = descriptive field name
4877 * Field 3 = field abbreviation
4878 * Field 4 = type ( textual representation of the the ftenum type )
4879 * Field 5 = parent protocol abbreviation
4880 * Field 6 = blurb describing field
4881 * Field 7 = base for display (for integer types)
4882 * Field 8 = blurb describing field (yes, apparently we repeated this accidentally)
4886 * Field 2 = descriptive field name
4887 * Field 3 = field abbreviation
4888 * Field 4 = type ( textual representation of the the ftenum type )
4889 * Field 5 = parent protocol abbreviation
4890 * Field 6 = blurb describing field
4891 * Field 7 = base for display (for integer types)
4895 proto_registrar_dump_fields(int format)
4897 header_field_info *hfinfo, *parent_hfinfo;
4899 const char *enum_name;
4900 const char *base_name;
4903 len = gpa_hfinfo.len;
4904 for (i = 0; i < len ; i++) {
4905 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
4908 * Skip the pseudo-field for "proto_tree_add_text()" since
4909 * we don't want it in the list of filterable fields.
4911 if (hfinfo->id == hf_text_only)
4914 /* format for protocols */
4915 if (proto_registrar_is_protocol(i)) {
4916 printf("P\t%s\t%s\n", hfinfo->name, hfinfo->abbrev);
4918 /* format for header fields */
4921 * If this field isn't at the head of the list of
4922 * fields with this name, skip this field - all
4923 * fields with the same name are really just versions
4924 * of the same field stored in different bits, and
4925 * should have the same type/radix/value list, and
4926 * just differ in their bit masks. (If a field isn't
4927 * a bitfield, but can be, say, 1 or 2 bytes long,
4928 * it can just be made FT_UINT16, meaning the
4929 * *maximum* length is 2 bytes, and be used
4932 if (hfinfo->same_name_prev != NULL)
4935 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
4937 enum_name = ftype_name(hfinfo->type);
4941 if (hfinfo->type == FT_UINT8 ||
4942 hfinfo->type == FT_UINT16 ||
4943 hfinfo->type == FT_UINT24 ||
4944 hfinfo->type == FT_UINT32 ||
4945 hfinfo->type == FT_UINT64 ||
4946 hfinfo->type == FT_INT8 ||
4947 hfinfo->type == FT_INT16 ||
4948 hfinfo->type == FT_INT24 ||
4949 hfinfo->type == FT_INT32 ||
4950 hfinfo->type == FT_INT64) {
4953 switch(hfinfo->display) {
4955 base_name = "BASE_NONE";
4958 base_name = "BASE_DEC";
4961 base_name = "BASE_HEX";
4964 base_name = "BASE_OCT";
4967 base_name = "BASE_DEC_HEX";
4970 base_name = "BASE_HEX_DEC";
4976 blurb = hfinfo->blurb;
4980 printf("F\t%s\t%s\t%s\t%s\t%s\n",
4981 hfinfo->name, hfinfo->abbrev, enum_name,
4982 parent_hfinfo->abbrev, blurb);
4984 else if (format == 2) {
4985 printf("F\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n",
4986 hfinfo->name, hfinfo->abbrev, enum_name,
4987 parent_hfinfo->abbrev, blurb,
4990 else if (format == 3) {
4991 printf("F\t%s\t%s\t%s\t%s\t%s\t%s\t%u\n",
4992 hfinfo->name, hfinfo->abbrev, enum_name,
4993 parent_hfinfo->abbrev, blurb,
4994 base_name, hfinfo->bitmask);
4997 g_assert_not_reached();
5004 hfinfo_numeric_format(header_field_info *hfinfo)
5006 const char *format = NULL;
5008 /* Pick the proper format string */
5009 if (hfinfo->type == FT_FRAMENUM) {
5011 * Frame numbers are always displayed in decimal.
5013 format = "%s == %u";
5015 /* Pick the proper format string */
5016 switch(hfinfo->display) {
5019 case BASE_OCT: /* I'm lazy */
5020 switch(hfinfo->type) {
5025 format = "%s == %u";
5028 format = "%s == %" PRIu64;
5034 format = "%s == %d";
5037 format = "%s == %" PRId64;
5040 DISSECTOR_ASSERT_NOT_REACHED();
5046 switch(hfinfo->type) {
5048 format = "%s == 0x%02x";
5051 format = "%s == 0x%04x";
5054 format = "%s == 0x%06x";
5057 format = "%s == 0x%08x";
5060 format = "%s == 0x%016" PRIx64;
5063 DISSECTOR_ASSERT_NOT_REACHED();
5068 DISSECTOR_ASSERT_NOT_REACHED();
5075 /* This function indicates whether it's possible to construct a
5076 * "match selected" display filter string for the specified field,
5077 * returns an indication of whether it's possible, and, if it's
5078 * possible and "filter" is non-null, constructs the filter and
5079 * sets "*filter" to point to it.
5080 * You do not need to [g_]free() this string since it will be automatically
5081 * freed once the next packet is dissected.
5084 construct_match_selected_string(field_info *finfo, epan_dissect_t *edt,
5087 header_field_info *hfinfo;
5093 gint start, length, length_remaining;
5095 gchar is_signed_num = FALSE;
5097 hfinfo = finfo->hfinfo;
5098 DISSECTOR_ASSERT(hfinfo);
5099 abbrev_len = strlen(hfinfo->abbrev);
5102 * XXX - we can't use the "val_to_string_repr" and "string_repr_len"
5103 * functions for FT_UINT and FT_INT types, as we choose the base in
5104 * the string expression based on the display base of the field.
5106 * Note that the base does matter, as this is also used for
5107 * the protocolinfo tap.
5109 * It might be nice to use them in "proto_item_fill_label()"
5110 * as well, although, there, you'd have to deal with the base
5111 * *and* with resolved values for addresses.
5113 * Perhaps we need two different val_to_string routines, one
5114 * to generate items for display filters and one to generate
5115 * strings for display, and pass to both of them the
5116 * "display" and "strings" values in the header_field_info
5117 * structure for the field, so they can get the base and,
5118 * if the field is Boolean or an enumerated integer type,
5119 * the tables used to generate human-readable values.
5121 switch(hfinfo->type) {
5127 is_signed_num = TRUE;
5134 * 4 bytes for " == ".
5137 * a sign + up to 10 digits of 32-bit integer,
5140 * "0x" + 8 digits of 32-bit integer, in hex;
5142 * 11 digits of 32-bit integer, in octal.
5143 * (No, we don't do octal, but this way,
5144 * we know that if we do, this will still
5147 * 1 byte for the trailing '\0'.
5149 if (filter != NULL) {
5150 dfilter_len = abbrev_len + 4 + 11 + 1;
5151 *filter = ep_alloc0(dfilter_len);
5152 format = hfinfo_numeric_format(hfinfo);
5153 g_snprintf(*filter, dfilter_len, format,
5155 is_signed_num ? fvalue_get_sinteger(&finfo->value)
5156 : fvalue_get_uinteger(&finfo->value));
5163 * 4 bytes for " == ".
5166 * a sign + up to 20 digits of 32-bit integer,
5169 * "0x" + 16 digits of 32-bit integer, in hex;
5171 * 22 digits of 32-bit integer, in octal.
5172 * (No, we don't do octal, but this way,
5173 * we know that if we do, this will still
5176 * 1 byte for the trailing '\0'.
5178 if (filter != NULL) {
5179 dfilter_len = abbrev_len + 4 + 22 + 1;
5180 *filter = ep_alloc0(dfilter_len);
5181 format = hfinfo_numeric_format(hfinfo);
5182 g_snprintf(*filter, dfilter_len, format,
5184 fvalue_get_integer64(&finfo->value));
5190 *filter = ep_strdup(finfo->hfinfo->abbrev);
5196 * If the length is 0, just match the name of the
5199 * (Also check for negative values, just in case,
5200 * as we'll cast it to an unsigned value later.)
5202 length = finfo->length;
5205 *filter = ep_strdup(finfo->hfinfo->abbrev);
5212 * This doesn't have a value, so we'd match
5213 * on the raw bytes at this address.
5215 * Should we be allowed to access to the raw bytes?
5216 * If "edt" is NULL, the answer is "no".
5222 * Is this field part of the raw frame tvbuff?
5223 * If not, we can't use "frame[N:M]" to match
5226 * XXX - should this be frame-relative, or
5227 * protocol-relative?
5229 * XXX - does this fallback for non-registered
5230 * fields even make sense?
5232 if (finfo->ds_tvb != edt->tvb)
5233 return FALSE; /* you lose */
5236 * Don't go past the end of that tvbuff.
5238 length_remaining = tvb_length_remaining(finfo->ds_tvb, finfo->start);
5239 if (length > length_remaining)
5240 length = length_remaining;
5244 if (filter != NULL) {
5245 start = finfo->start;
5246 buf_len = 32 + length * 3;
5247 *filter = ep_alloc0(buf_len);
5250 ptr += g_snprintf(ptr, buf_len-(ptr-*filter),
5251 "frame[%d:%d] == ", finfo->start, length);
5252 for (i=0;i<length; i++) {
5253 c = tvb_get_guint8(finfo->ds_tvb, start);
5256 ptr += g_snprintf(ptr, buf_len-(ptr-*filter), "%02x", c);
5259 ptr += g_snprintf(ptr, buf_len-(ptr-*filter), ":%02x", c);
5265 /* By default, use the fvalue's "to_string_repr" method. */
5267 /* Figure out the string length needed.
5268 * The ft_repr length.
5269 * 4 bytes for " == ".
5270 * 1 byte for trailing NUL.
5272 if (filter != NULL) {
5273 dfilter_len = fvalue_string_repr_len(&finfo->value,
5275 dfilter_len += abbrev_len + 4 + 1;
5276 *filter = ep_alloc0(dfilter_len);
5278 /* Create the string */
5279 g_snprintf(*filter, dfilter_len, "%s == ",
5281 fvalue_to_string_repr(&finfo->value,
5283 &(*filter)[abbrev_len + 4]);
5292 * Returns TRUE if we can do a "match selected" on the field, FALSE
5296 proto_can_match_selected(field_info *finfo, epan_dissect_t *edt)
5298 return construct_match_selected_string(finfo, edt, NULL);
5301 /* This function attempts to construct a "match selected" display filter
5302 * string for the specified field; if it can do so, it returns a pointer
5303 * to the string, otherwise it returns NULL.
5305 * The string is allocated with packet lifetime scope.
5306 * You do not need to [g_]free() this string since it will be automatically
5307 * freed once the next packet is dissected.
5310 proto_construct_match_selected_string(field_info *finfo, epan_dissect_t *edt)
5314 if (!construct_match_selected_string(finfo, edt, &filter))
5320 /* This function will dissect a sequence of bytes that describe a
5322 * hf_hdr is a 8/16/24/32 bit integer that describes the bitmask to be dissected.
5323 * This field will form an expansion under which the individual fields of the
5324 * bitmask is dissected and displayed.
5325 * This field must be of the type FT_[U]INT{8|16|24|32}.
5327 * fields is an array of pointers to int that lists all the fields of the
5328 * bitmask. These fields can be either of the type FT_BOOLEAN for flags
5329 * or another integer of the same type/size as hf_hdr with a mask specified.
5330 * This array is terminated by a NULL entry.
5332 * FT_BOOLEAN bits that are set to 1 will have the name added to the expansion.
5333 * FT_integer fields that have a value_string attached will have the
5334 * matched string displayed on the expansion line.
5337 proto_tree_add_bitmask(proto_tree *parent_tree, tvbuff_t *tvb, int offset, int hf_hdr, gint ett, const int **fields, gboolean little_endian)
5339 proto_tree *tree=NULL;
5340 proto_item *item=NULL;
5341 header_field_info *hf_info;
5345 hf_info=proto_registrar_get_nth(hf_hdr);
5346 switch(hf_info->type){
5350 value=tvb_get_guint8(tvb, offset);
5356 value=tvb_get_letohs(tvb, offset);
5358 value=tvb_get_ntohs(tvb, offset);
5365 value=tvb_get_letoh24(tvb, offset);
5367 value=tvb_get_ntoh24(tvb, offset);
5374 value=tvb_get_letohl(tvb, offset);
5376 value=tvb_get_ntohl(tvb, offset);
5380 g_assert_not_reached();
5384 item=proto_tree_add_item(parent_tree, hf_hdr, tvb, offset, len, little_endian);
5385 tree=proto_item_add_subtree(item, ett);
5389 header_field_info *hf_field;
5390 guint32 tmpval, tmpmask;
5392 hf_field=proto_registrar_get_nth(**fields);
5393 switch(hf_field->type){
5402 proto_tree_add_item(tree, **fields, tvb, offset, len, little_endian);
5404 /* Mask and shift out the value */
5405 tmpmask=hf_field->bitmask;
5409 while(!(tmpmask&0x00000001)){
5414 /* Show the value_string content (if there is one) */
5415 if(hf_field->strings){
5416 proto_item_append_text(item, ", %s", val_to_str(tmpval, hf_field->strings, "Unknown"));
5421 proto_tree_add_item(tree, **fields, tvb, offset, len, little_endian);
5422 /* if the flag is set, show the name */
5423 if(hf_field->bitmask&value){
5424 proto_item_append_text(item, ", %s", hf_field->name);
5428 g_assert_not_reached();