2 * Routines for protocol tree
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
36 #include "ptvcursor.h"
38 #include "addr_resolv.h"
39 #include "oid_resolv.h"
42 #include "epan_dissect.h"
53 #define cVALS(x) (const value_string*)(x)
56 #define TRY_TO_FAKE_THIS_ITEM(tree, hfindex) \
57 /* If this item is not referenced we dont have to do much work \
58 at all but we should still return a node so that \
59 field items below this node ( think proto_item_add_subtree() )\
60 will still have somewhere to attach to \
61 or else filtering will not work (they would be ignored since tree\
63 DONT try to fake a node where PITEM_FINFO(pi) is NULL \
64 since dissectors that want to do proto_item_set_len() ot \
65 other operations that dereference this would crash. \
66 We dont fake FT_PROTOCOL either since these are cheap and \
67 some stuff (proto hier stat) assumes they always exist. \
69 if(!(PTREE_DATA(tree)->visible)){ \
70 if(PITEM_FINFO(tree)){ \
71 register header_field_info *hfinfo; \
72 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo); \
73 if((hfinfo->ref_count == 0) \
74 && (hfinfo->type!=FT_PROTOCOL)){ \
75 /* just return tree back to the caller */\
81 #define TRY_TO_FAKE_THIS_ITEM(tree, hfindex) ;
85 proto_tree_free_node(proto_node *node, gpointer data);
87 static void fill_label_boolean(field_info *fi, gchar *label_str);
88 static void fill_label_uint(field_info *fi, gchar *label_str);
89 static void fill_label_uint64(field_info *fi, gchar *label_str);
90 static void fill_label_enumerated_uint(field_info *fi, gchar *label_str);
91 static void fill_label_enumerated_bitfield(field_info *fi, gchar *label_str);
92 static void fill_label_numeric_bitfield(field_info *fi, gchar *label_str);
93 static void fill_label_int(field_info *fi, gchar *label_str);
94 static void fill_label_int64(field_info *fi, gchar *label_str);
95 static void fill_label_enumerated_int(field_info *fi, gchar *label_str);
97 int hfinfo_bitwidth(header_field_info *hfinfo);
98 static const char* hfinfo_uint_vals_format(header_field_info *hfinfo);
99 static const char* hfinfo_uint_format(header_field_info *hfinfo);
100 static const char* hfinfo_uint64_format(header_field_info *hfinfo);
101 static const char* hfinfo_int_vals_format(header_field_info *hfinfo);
102 static const char* hfinfo_int_format(header_field_info *hfinfo);
103 static const char* hfinfo_int64_format(header_field_info *hfinfo);
106 proto_tree_add_node(proto_tree *tree, field_info *fi);
108 static header_field_info *
109 get_hfi_and_length(int hfindex, tvbuff_t *tvb, gint start, gint *length,
113 new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
114 gint start, gint item_length);
117 alloc_field_info(proto_tree *tree, int hfindex, tvbuff_t *tvb,
118 gint start, gint *length);
121 proto_tree_add_pi(proto_tree *tree, int hfindex, tvbuff_t *tvb,
122 gint start, gint *length, field_info **pfi);
125 proto_tree_set_representation_value(proto_item *pi, const char *format, va_list ap);
127 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap);
130 proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb);
132 proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length);
134 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length);
136 proto_tree_set_time(field_info *fi, nstime_t *value_ptr);
138 proto_tree_set_string(field_info *fi, const char* value);
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 { "", "", 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 THROW(ReportedBoundsError);
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 THROW(ReportedBoundsError);
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_integer(&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_integer(&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_integer(&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_integer(&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);
2978 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
2979 va_start(ap, format);
2982 * If we don't already have a representation,
2983 * generate the default representation.
2985 if (fi->rep == NULL) {
2986 ITEM_LABEL_NEW(fi->rep);
2987 proto_item_fill_label(fi, fi->rep->representation);
2990 curlen = strlen(fi->rep->representation);
2991 if (ITEM_LABEL_LENGTH > curlen) {
2992 ret = g_vsnprintf(fi->rep->representation + curlen,
2993 ITEM_LABEL_LENGTH - curlen, format, ap);
2994 if ((ret == -1) || (ret >= (int)(ITEM_LABEL_LENGTH - curlen)))
2995 fi->rep->representation[ITEM_LABEL_LENGTH - 1] = '\0';
3002 proto_item_set_len(proto_item *pi, gint length)
3008 fi = PITEM_FINFO(pi);
3009 DISSECTOR_ASSERT(length >= 0);
3010 fi->length = length;
3014 * Sets the length of the item based on its start and on the specified
3015 * offset, which is the offset past the end of the item; as the start
3016 * in the item is relative to the beginning of the data source tvbuff,
3017 * we need to pass in a tvbuff - the end offset is relative to the beginning
3021 proto_item_set_end(proto_item *pi, tvbuff_t *tvb, gint end)
3027 fi = PITEM_FINFO(pi);
3028 end += TVB_RAW_OFFSET(tvb);
3029 DISSECTOR_ASSERT(end >= fi->start);
3030 fi->length = end - fi->start;
3034 proto_item_get_len(proto_item *pi)
3036 field_info *fi = PITEM_FINFO(pi);
3041 /** clear flags according to the mask and set new flag values */
3042 #define FI_REPLACE_FLAGS(fi, mask, flags_in) { \
3043 (fi->flags = (fi)->flags & ~(mask)); \
3044 (fi->flags = (fi)->flags | (flags_in)); \
3048 proto_item_set_expert_flags(proto_item *pi, int group, int severity)
3050 if(pi == NULL || pi->finfo == NULL)
3053 /* only change things if severity is worse or at least equal than before */
3054 if(severity >= FI_GET_FLAG(pi->finfo, PI_SEVERITY_MASK)) {
3055 FI_REPLACE_FLAGS(pi->finfo, PI_GROUP_MASK, group);
3056 FI_REPLACE_FLAGS(pi->finfo, PI_SEVERITY_MASK, severity);
3067 proto_tree_create_root(void)
3071 /* Initialize the proto_node */
3072 PROTO_NODE_NEW(pnode);
3073 pnode->parent = NULL;
3074 pnode->finfo = NULL;
3075 pnode->tree_data = g_new(tree_data_t, 1);
3077 /* Initialize the tree_data_t */
3078 pnode->tree_data->interesting_hfids =
3079 g_hash_table_new(g_direct_hash, g_direct_equal);
3081 /* Set the default to FALSE so it's easier to
3082 * find errors; if we expect to see the protocol tree
3083 * but for some reason the default 'visible' is not
3084 * changed, then we'll find out very quickly. */
3085 pnode->tree_data->visible = FALSE;
3087 /* Keep track of the number of children */
3088 pnode->tree_data->count = 0;
3090 return (proto_tree*) pnode;
3094 /* "prime" a proto_tree with a single hfid that a dfilter
3095 * is interested in. */
3097 proto_tree_prime_hfid(proto_tree *tree, gint hfid)
3099 header_field_info *hfinfo;
3101 g_hash_table_insert(PTREE_DATA(tree)->interesting_hfids,
3102 GINT_TO_POINTER(hfid), g_ptr_array_new());
3104 PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
3105 /* this field is referenced by a filter so increase the refcount.
3106 also increase the refcount for the parent, i.e the protocol.
3108 hfinfo->ref_count++;
3109 /* only increase the refcount if there is a parent.
3110 if this is a protocol and not a field then parent will be -1
3111 and there is no parent to add any refcounting for.
3113 if (hfinfo->parent != -1) {
3114 header_field_info *parent_hfinfo;
3115 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
3116 parent_hfinfo->ref_count++;
3121 proto_item_add_subtree(proto_item *pi, gint idx) {
3127 fi = PITEM_FINFO(pi);
3128 DISSECTOR_ASSERT(idx >= 0 && idx < num_tree_types);
3129 fi->tree_type = idx;
3131 return (proto_tree*) pi;
3135 proto_item_get_subtree(proto_item *pi) {
3140 fi = PITEM_FINFO(pi);
3141 if ( (!fi) || (fi->tree_type == -1) )
3143 return (proto_tree*) pi;
3147 proto_item_get_parent(proto_item *ti) {
3148 /* dont bother if tree is not visible */
3149 if( (!ti) || (!(PTREE_DATA(ti)->visible)) )
3155 proto_item_get_parent_nth(proto_item *ti, int gen) {
3156 /* dont bother if tree is not visible */
3157 if( (!ti) || (!(PTREE_DATA(ti)->visible)) )
3169 proto_tree_get_parent(proto_tree *tree) {
3170 /* dont bother if tree is not visible */
3171 if( (!tree) || (!(PTREE_DATA(tree)->visible)) )
3173 return (proto_item*) tree;
3177 proto_tree_get_root(proto_tree *tree) {
3178 /* dont bother if tree is not visible */
3179 if( (!tree) || (!(PTREE_DATA(tree)->visible)) )
3181 while (tree->parent) {
3182 tree = tree->parent;
3188 proto_tree_move_item(proto_tree *tree, proto_item *fixed_item, proto_item *item_to_move)
3190 proto_item *curr_item;
3193 /*** cut item_to_move out ***/
3195 /* is item_to_move the first? */
3196 if(tree->first_child == item_to_move) {
3197 /* simply change first child to next */
3198 tree->first_child = item_to_move->next;
3200 /* find previous and change it's next */
3201 for(curr_item = tree->first_child; curr_item != NULL; curr_item = curr_item->next) {
3202 if(curr_item->next == item_to_move) {
3207 DISSECTOR_ASSERT(curr_item);
3209 curr_item->next = item_to_move->next;
3211 /* fix last_child if required */
3212 if(tree->last_child == item_to_move) {
3213 tree->last_child = curr_item;
3217 /*** insert to_move after fixed ***/
3218 item_to_move->next = fixed_item->next;
3219 fixed_item->next = item_to_move;
3220 if(tree->last_child == fixed_item) {
3221 tree->last_child = item_to_move;
3227 proto_register_protocol(const char *name, const char *short_name, const char *filter_name)
3229 protocol_t *protocol;
3230 header_field_info *hfinfo;
3232 char *existing_name;
3236 gboolean found_invalid;
3239 * Make sure there's not already a protocol with any of those
3240 * names. Crash if there is, as that's an error in the code
3241 * or an inappropriate plugin.
3242 * This situation has to be fixed to not register more than one
3243 * protocol with the same name.
3245 * This is done by reducing the number of strcmp (and alike) calls as much as possible,
3246 * as this significally slows down startup time.
3248 * Drawback: As a hash value is used to reduce insert time,
3249 * this might lead to a hash collision.
3250 * However, as we have around 500+ protocols and we're using a 32 bit int this is very,
3254 key = g_malloc (sizeof(gint));
3255 *key = g_str_hash(name);
3256 existing_name = g_hash_table_lookup(proto_names, key);
3257 if (existing_name != NULL) {
3258 /* g_error will terminate the program */
3259 g_error("Duplicate protocol name \"%s\"!"
3260 " This might be caused by an inappropriate plugin or a development error.", name);
3262 g_hash_table_insert(proto_names, key, (gpointer)name);
3264 key = g_malloc (sizeof(gint));
3265 *key = g_str_hash(short_name);
3266 existing_name = g_hash_table_lookup(proto_short_names, key);
3267 if (existing_name != NULL) {
3268 g_error("Duplicate protocol short_name \"%s\"!"
3269 " This might be caused by an inappropriate plugin or a development error.", short_name);
3271 g_hash_table_insert(proto_short_names, key, (gpointer)short_name);
3273 found_invalid = FALSE;
3274 for (i = 0; i < strlen(filter_name); i++) {
3276 if (!(islower(c) || isdigit(c) || c == '-' || c == '_' || c == '.')) {
3277 found_invalid = TRUE;
3280 if (found_invalid) {
3281 g_error("Protocol filter name \"%s\" has one or more invalid characters."
3282 " Allowed are lower characters, digits, '-', '_' and '.'."
3283 " This might be caused by an inappropriate plugin or a development error.", filter_name);
3285 key = g_malloc (sizeof(gint));
3286 *key = g_str_hash(filter_name);
3287 existing_name = g_hash_table_lookup(proto_filter_names, key);
3288 if (existing_name != NULL) {
3289 g_error("Duplicate protocol filter_name \"%s\"!"
3290 " This might be caused by an inappropriate plugin or a development error.", filter_name);
3292 g_hash_table_insert(proto_filter_names, key, (gpointer)filter_name);
3294 /* Add this protocol to the list of known protocols; the list
3295 is sorted by protocol short name. */
3296 protocol = g_malloc(sizeof (protocol_t));
3297 protocol->name = name;
3298 protocol->short_name = short_name;
3299 protocol->filter_name = filter_name;
3300 protocol->fields = NULL;
3301 protocol->is_enabled = TRUE; /* protocol is enabled by default */
3302 protocol->can_toggle = TRUE;
3303 /* list will be sorted later by name, when all protocols completed registering */
3304 protocols = g_list_append(protocols, protocol);
3306 /* Here we do allocate a new header_field_info struct */
3307 hfinfo = g_mem_chunk_alloc(gmc_hfinfo);
3308 hfinfo->name = name;
3309 hfinfo->abbrev = filter_name;
3310 hfinfo->type = FT_PROTOCOL;
3311 hfinfo->strings = protocol;
3312 hfinfo->bitmask = 0;
3313 hfinfo->bitshift = 0;
3314 hfinfo->ref_count = 0;
3315 hfinfo->blurb = NULL;
3316 hfinfo->parent = -1; /* this field differentiates protos and fields */
3318 proto_id = proto_register_field_init(hfinfo, hfinfo->parent);
3319 protocol->proto_id = proto_id;
3324 * Routines to use to iterate over the protocols.
3325 * The argument passed to the iterator routines is an opaque cookie to
3326 * their callers; it's the GList pointer for the current element in
3328 * The ID of the protocol is returned, or -1 if there is no protocol.
3331 proto_get_first_protocol(void **cookie)
3333 protocol_t *protocol;
3335 if (protocols == NULL)
3337 *cookie = protocols;
3338 protocol = protocols->data;
3339 return protocol->proto_id;
3343 proto_get_next_protocol(void **cookie)
3345 GList *list_item = *cookie;
3346 protocol_t *protocol;
3348 list_item = g_list_next(list_item);
3349 if (list_item == NULL)
3351 *cookie = list_item;
3352 protocol = list_item->data;
3353 return protocol->proto_id;
3357 proto_get_first_protocol_field(int proto_id, void **cookie)
3359 protocol_t *protocol = find_protocol_by_id(proto_id);
3360 hf_register_info *ptr;
3362 if ((protocol == NULL) || (protocol->fields == NULL))
3365 *cookie = protocol->fields;
3366 ptr = protocol->fields->data;
3367 return &ptr->hfinfo;
3371 proto_get_next_protocol_field(void **cookie)
3373 GList *list_item = *cookie;
3374 hf_register_info *ptr;
3376 list_item = g_list_next(list_item);
3377 if (list_item == NULL)
3380 *cookie = list_item;
3381 ptr = list_item->data;
3382 return &ptr->hfinfo;
3386 find_protocol_by_id(int proto_id)
3388 header_field_info *hfinfo;
3393 PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
3394 DISSECTOR_ASSERT(hfinfo->type==FT_PROTOCOL);
3395 return (protocol_t *)hfinfo->strings;
3398 static gint compare_filter_name(gconstpointer proto_arg,
3399 gconstpointer filter_name)
3401 const protocol_t *protocol = proto_arg;
3402 const gchar* f_name = filter_name;
3404 return (strcmp(protocol->filter_name, f_name));
3408 proto_get_id(protocol_t *protocol)
3410 return protocol->proto_id;
3413 int proto_get_id_by_filter_name(const gchar* filter_name)
3416 protocol_t *protocol;
3418 list_entry = g_list_find_custom(protocols, filter_name,
3419 compare_filter_name);
3420 if (list_entry == NULL)
3422 protocol = list_entry->data;
3423 return protocol->proto_id;
3427 proto_get_protocol_name(int proto_id)
3429 protocol_t *protocol;
3431 protocol = find_protocol_by_id(proto_id);
3432 return protocol->name;
3436 proto_get_protocol_short_name(protocol_t *protocol)
3438 if (protocol == NULL)
3440 return protocol->short_name;
3444 proto_get_protocol_filter_name(int proto_id)
3446 protocol_t *protocol;
3448 protocol = find_protocol_by_id(proto_id);
3449 return protocol->filter_name;
3453 proto_is_protocol_enabled(protocol_t *protocol)
3455 return protocol->is_enabled;
3459 proto_can_toggle_protocol(int proto_id)
3461 protocol_t *protocol;
3463 protocol = find_protocol_by_id(proto_id);
3464 return protocol->can_toggle;
3468 proto_set_decoding(int proto_id, gboolean enabled)
3470 protocol_t *protocol;
3472 protocol = find_protocol_by_id(proto_id);
3473 DISSECTOR_ASSERT(protocol->can_toggle);
3474 protocol->is_enabled = enabled;
3478 proto_set_cant_toggle(int proto_id)
3480 protocol_t *protocol;
3482 protocol = find_protocol_by_id(proto_id);
3483 protocol->can_toggle = FALSE;
3486 /* for use with static arrays only, since we don't allocate our own copies
3487 of the header_field_info struct contained within the hf_register_info struct */
3489 proto_register_field_array(int parent, hf_register_info *hf, int num_records)
3492 hf_register_info *ptr = hf;
3495 proto = find_protocol_by_id(parent);
3496 for (i = 0; i < num_records; i++, ptr++) {
3498 * Make sure we haven't registered this yet.
3499 * Most fields have variables associated with them
3500 * that are initialized to -1; some have array elements,
3501 * or possibly uninitialized variables, so we also allow
3502 * 0 (which is unlikely to be the field ID we get back
3503 * from "proto_register_field_init()").
3505 if (*ptr->p_id != -1 && *ptr->p_id != 0) {
3507 "Duplicate field detected in call to proto_register_field_array: %s is already registered\n",
3508 ptr->hfinfo.abbrev);
3512 if (proto != NULL) {
3513 if (proto->fields == NULL) {
3514 proto->fields = g_list_append(NULL, ptr);
3515 proto->last_field = proto->fields;
3518 g_list_append(proto->last_field, ptr)->next;
3521 field_id = proto_register_field_init(&ptr->hfinfo, parent);
3522 *ptr->p_id = field_id;
3527 proto_register_field_init(header_field_info *hfinfo, int parent)
3529 /* The field must have names */
3530 DISSECTOR_ASSERT(hfinfo->name);
3531 DISSECTOR_ASSERT(hfinfo->abbrev);
3533 /* These types of fields are allowed to have value_strings, true_false_strings or a protocol_t struct*/
3534 DISSECTOR_ASSERT((hfinfo->strings == NULL) || (
3535 (hfinfo->type == FT_UINT8) ||
3536 (hfinfo->type == FT_UINT16) ||
3537 (hfinfo->type == FT_UINT24) ||
3538 (hfinfo->type == FT_UINT32) ||
3539 (hfinfo->type == FT_INT8) ||
3540 (hfinfo->type == FT_INT16) ||
3541 (hfinfo->type == FT_INT24) ||
3542 (hfinfo->type == FT_INT32) ||
3543 (hfinfo->type == FT_BOOLEAN) ||
3544 (hfinfo->type == FT_PROTOCOL) ||
3545 (hfinfo->type == FT_FRAMENUM) ));
3547 switch (hfinfo->type) {
3557 /* Require integral types (other than frame number, which is
3558 always displayed in decimal) to have a number base */
3559 DISSECTOR_ASSERT(hfinfo->display != BASE_NONE);
3563 /* Don't allow bitfields or value strings for frame numbers */
3564 DISSECTOR_ASSERT(hfinfo->bitmask == 0);
3565 DISSECTOR_ASSERT(hfinfo->strings == NULL);
3571 /* if this is a bitfield, compute bitshift */
3572 if (hfinfo->bitmask) {
3573 while ((hfinfo->bitmask & (1 << hfinfo->bitshift)) == 0)
3577 hfinfo->parent = parent;
3578 hfinfo->same_name_next = NULL;
3579 hfinfo->same_name_prev = NULL;
3581 /* if we always add and never delete, then id == len - 1 is correct */
3582 if(gpa_hfinfo.len>=gpa_hfinfo.allocated_len){
3583 if(!gpa_hfinfo.hfi){
3584 gpa_hfinfo.allocated_len=1000;
3585 gpa_hfinfo.hfi=g_malloc(sizeof(header_field_info *)*1000);
3587 gpa_hfinfo.allocated_len+=1000;
3588 gpa_hfinfo.hfi=g_realloc(gpa_hfinfo.hfi, sizeof(header_field_info *)*gpa_hfinfo.allocated_len);
3591 gpa_hfinfo.hfi[gpa_hfinfo.len]=hfinfo;
3593 hfinfo->id = gpa_hfinfo.len - 1;
3595 /* if we have real names, enter this field in the name tree */
3596 if ((hfinfo->name[0] != 0) && (hfinfo->abbrev[0] != 0 )) {
3598 header_field_info *same_name_hfinfo, *same_name_next_hfinfo;
3602 /* Check that the filter name (abbreviation) is legal;
3603 * it must contain only alphanumerics, '-', "_", and ".". */
3604 for (p = hfinfo->abbrev; (c = *p) != '\0'; p++) {
3605 if (!(isalnum(c) || c == '-' || c == '_' || c == '.')) {
3606 fprintf(stderr, "OOPS: '%c' in '%s'\n", c, hfinfo->abbrev);
3607 DISSECTOR_ASSERT(isalnum(c) || c == '-' || c == '_' ||
3611 /* We allow multiple hfinfo's to be registered under the same
3612 * abbreviation. This was done for X.25, as, depending
3613 * on whether it's modulo-8 or modulo-128 operation,
3614 * some bitfield fields may be in different bits of
3615 * a byte, and we want to be able to refer to that field
3616 * with one name regardless of whether the packets
3617 * are modulo-8 or modulo-128 packets. */
3618 same_name_hfinfo = g_tree_lookup(gpa_name_tree, hfinfo->abbrev);
3619 if (same_name_hfinfo) {
3620 /* There's already a field with this name.
3621 * Put it after that field in the list of
3622 * fields with this name, then allow the code
3623 * after this if{} block to replace the old
3624 * hfinfo with the new hfinfo in the GTree. Thus,
3625 * we end up with a linked-list of same-named hfinfo's,
3626 * with the root of the list being the hfinfo in the GTree */
3627 same_name_next_hfinfo =
3628 same_name_hfinfo->same_name_next;
3630 hfinfo->same_name_next = same_name_next_hfinfo;
3631 if (same_name_next_hfinfo)
3632 same_name_next_hfinfo->same_name_prev = hfinfo;
3634 same_name_hfinfo->same_name_next = hfinfo;
3635 hfinfo->same_name_prev = same_name_hfinfo;
3637 g_tree_insert(gpa_name_tree, (gpointer) (hfinfo->abbrev), hfinfo);
3644 proto_register_subtree_array(gint *const *indices, int num_indices)
3647 gint *const *ptr = indices;
3650 * If we've already allocated the array of tree types, expand
3651 * it; this lets plugins such as mate add tree types after
3652 * the initial startup. (If we haven't already allocated it,
3653 * we don't allocate it; on the first pass, we just assign
3654 * ett values and keep track of how many we've assigned, and
3655 * when we're finished registering all dissectors we allocate
3656 * the array, so that we do only one allocation rather than
3657 * wasting CPU time and memory by growing the array for each
3658 * dissector that registers ett values.)
3660 if (tree_is_expanded != NULL) {
3662 g_realloc(tree_is_expanded,
3663 (num_tree_types+num_indices)*sizeof (gboolean));
3664 memset(tree_is_expanded + num_tree_types, 0,
3665 num_indices*sizeof (gboolean));
3669 * Assign "num_indices" subtree numbers starting at "num_tree_types",
3670 * returning the indices through the pointers in the array whose
3671 * first element is pointed to by "indices", and update
3672 * "num_tree_types" appropriately.
3674 for (i = 0; i < num_indices; i++, ptr++, num_tree_types++)
3675 **ptr = num_tree_types;
3679 proto_item_fill_label(field_info *fi, gchar *label_str)
3681 header_field_info *hfinfo = fi->hfinfo;
3687 guint32 n_addr; /* network-order IPv4 address */
3689 int ret; /*tmp return value */
3691 switch(hfinfo->type) {
3694 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3695 "%s", hfinfo->name);
3696 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3697 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3701 fill_label_boolean(fi, label_str);
3706 bytes = fvalue_get(&fi->value);
3708 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3709 "%s: %s", hfinfo->name,
3710 bytes_to_str(bytes, fvalue_length(&fi->value)));
3711 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3712 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3715 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3716 "%s: <MISSING>", hfinfo->name);
3717 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3718 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3722 /* Four types of integers to take care of:
3723 * Bitfield, with val_string
3724 * Bitfield, w/o val_string
3725 * Non-bitfield, with val_string
3726 * Non-bitfield, w/o val_string
3733 if (hfinfo->bitmask) {
3734 if (hfinfo->strings) {
3735 fill_label_enumerated_bitfield(fi, label_str);
3738 fill_label_numeric_bitfield(fi, label_str);
3742 if (hfinfo->strings) {
3743 fill_label_enumerated_uint(fi, label_str);
3746 fill_label_uint(fi, label_str);
3752 fill_label_uint64(fi, label_str);
3759 DISSECTOR_ASSERT(!hfinfo->bitmask);
3760 if (hfinfo->strings) {
3761 fill_label_enumerated_int(fi, label_str);
3764 fill_label_int(fi, label_str);
3769 fill_label_int64(fi, label_str);
3773 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3774 "%s: %." STRINGIFY(FLT_DIG) "f",
3775 hfinfo->name, fvalue_get_floating(&fi->value));
3776 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3777 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3781 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3782 "%s: %." STRINGIFY(DBL_DIG) "g",
3783 hfinfo->name, fvalue_get_floating(&fi->value));
3784 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3785 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3788 case FT_ABSOLUTE_TIME:
3789 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3790 "%s: %s", hfinfo->name,
3791 abs_time_to_str(fvalue_get(&fi->value)));
3792 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3793 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3796 case FT_RELATIVE_TIME:
3797 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3798 "%s: %s seconds", hfinfo->name,
3799 rel_time_to_secs_str(fvalue_get(&fi->value)));
3800 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3801 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3805 integer = fvalue_get_integer(&fi->value);
3806 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3807 "%s: %s (0x%08X)", hfinfo->name,
3808 get_ipxnet_name(integer), integer);
3809 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3810 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3814 bytes = fvalue_get(&fi->value);
3815 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3816 "%s: %s (%s)", hfinfo->name,
3817 get_ether_name(bytes),
3818 ether_to_str(bytes));
3819 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3820 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3824 ipv4 = fvalue_get(&fi->value);
3825 n_addr = ipv4_get_net_order_addr(ipv4);
3826 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3827 "%s: %s (%s)", hfinfo->name,
3828 get_hostname(n_addr),
3829 ip_to_str((guint8*)&n_addr));
3830 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3831 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3835 bytes = fvalue_get(&fi->value);
3836 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3837 "%s: %s (%s)", hfinfo->name,
3838 get_hostname6((struct e_in6_addr *)bytes),
3839 ip6_to_str((struct e_in6_addr*)bytes));
3840 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3841 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3845 guid = fvalue_get(&fi->value);
3846 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3847 "%s: %s", hfinfo->name,
3849 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3850 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3854 bytes = fvalue_get(&fi->value);
3855 name = (oid_resolv_enabled()) ? get_oid_name(bytes, fvalue_length(&fi->value)) : NULL;
3857 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3858 "%s: %s (%s)", hfinfo->name,
3859 oid_to_str(bytes, fvalue_length(&fi->value)), name);
3861 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3862 "%s: %s", hfinfo->name,
3863 oid_to_str(bytes, fvalue_length(&fi->value)));
3865 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3866 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3871 case FT_UINT_STRING:
3872 bytes = fvalue_get(&fi->value);
3873 if(strlen(bytes) > ITEM_LABEL_LENGTH) {
3874 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3875 "%s [truncated]: %s", hfinfo->name,
3876 format_text(bytes, strlen(bytes)));
3878 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3879 "%s: %s", hfinfo->name,
3880 format_text(bytes, strlen(bytes)));
3882 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3883 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3887 g_error("hfinfo->type %d (%s) not handled\n",
3889 ftype_name(hfinfo->type));
3890 DISSECTOR_ASSERT_NOT_REACHED();
3896 fill_label_boolean(field_info *fi, gchar *label_str)
3898 char *p = label_str;
3899 int bitfield_byte_length = 0, bitwidth;
3900 guint32 unshifted_value;
3902 int ret; /*tmp return value */
3904 header_field_info *hfinfo = fi->hfinfo;
3905 static const true_false_string default_tf = { "True", "False" };
3906 const true_false_string *tfstring = &default_tf;
3908 if (hfinfo->strings) {
3909 tfstring = (const struct true_false_string*) hfinfo->strings;
3912 value = fvalue_get_integer(&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_integer(&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_integer(&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_integer(&fi->value);
4030 /* Fill in the textual info */
4031 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4032 format, hfinfo->name,
4033 val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
4034 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4035 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4039 fill_label_uint(field_info *fi, gchar *label_str)
4041 const char *format = NULL;
4042 header_field_info *hfinfo = fi->hfinfo;
4044 int ret; /*tmp return value */
4046 /* Pick the proper format string */
4047 format = hfinfo_uint_format(hfinfo);
4048 value = fvalue_get_integer(&fi->value);
4050 /* Fill in the textual info */
4051 if (IS_BASE_DUAL(hfinfo->display)) {
4052 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4053 format, hfinfo->name, value, value);
4055 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4056 format, hfinfo->name, value);
4058 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4059 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4063 fill_label_uint64(field_info *fi, gchar *label_str)
4065 const char *format = NULL;
4066 header_field_info *hfinfo = fi->hfinfo;
4068 int ret; /*tmp return value */
4070 /* Pick the proper format string */
4071 format = hfinfo_uint64_format(hfinfo);
4072 value = fvalue_get_integer64(&fi->value);
4074 /* Fill in the textual info */
4075 if (IS_BASE_DUAL(hfinfo->display)) {
4076 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4077 format, hfinfo->name, value, value);
4079 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4080 format, hfinfo->name, value);
4082 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4083 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4087 fill_label_enumerated_int(field_info *fi, gchar *label_str)
4089 const char *format = NULL;
4090 header_field_info *hfinfo = fi->hfinfo;
4092 int ret; /*tmp return value */
4094 /* Pick the proper format string */
4095 format = hfinfo_int_vals_format(hfinfo);
4096 value = fvalue_get_integer(&fi->value);
4098 /* Fill in the textual info */
4099 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4100 format, hfinfo->name,
4101 val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
4102 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4103 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4107 fill_label_int(field_info *fi, gchar *label_str)
4109 const char *format = NULL;
4110 header_field_info *hfinfo = fi->hfinfo;
4112 int ret; /*tmp return value */
4114 /* Pick the proper format string */
4115 format = hfinfo_int_format(hfinfo);
4116 value = fvalue_get_integer(&fi->value);
4118 /* Fill in the textual info */
4119 if (IS_BASE_DUAL(hfinfo->display)) {
4120 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4121 format, hfinfo->name, value, value);
4123 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4124 format, hfinfo->name, value);
4126 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4127 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4131 fill_label_int64(field_info *fi, gchar *label_str)
4133 const char *format = NULL;
4134 header_field_info *hfinfo = fi->hfinfo;
4136 int ret; /*tmp return value */
4138 /* Pick the proper format string */
4139 format = hfinfo_int64_format(hfinfo);
4140 value = fvalue_get_integer64(&fi->value);
4142 /* Fill in the textual info */
4143 if (IS_BASE_DUAL(hfinfo->display)) {
4144 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4145 format, hfinfo->name, value, value);
4147 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4148 format, hfinfo->name, value);
4150 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4151 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4155 hfinfo_bitwidth(header_field_info *hfinfo)
4159 if (!hfinfo->bitmask) {
4163 switch(hfinfo->type) {
4181 bitwidth = hfinfo->display; /* hacky? :) */
4184 DISSECTOR_ASSERT_NOT_REACHED();
4191 hfinfo_uint_vals_format(header_field_info *hfinfo)
4193 const char *format = NULL;
4195 switch(hfinfo->display) {
4198 format = "%s: %s (%u)";
4200 case BASE_OCT: /* I'm lazy */
4201 format = "%s: %s (%o)";
4205 switch(hfinfo->type) {
4207 format = "%s: %s (0x%02x)";
4210 format = "%s: %s (0x%04x)";
4213 format = "%s: %s (0x%06x)";
4216 format = "%s: %s (0x%08x)";
4219 DISSECTOR_ASSERT_NOT_REACHED();
4224 DISSECTOR_ASSERT_NOT_REACHED();
4231 hfinfo_uint_format(header_field_info *hfinfo)
4233 const char *format = NULL;
4235 /* Pick the proper format string */
4236 if (hfinfo->type == FT_FRAMENUM) {
4238 * Frame numbers are always displayed in decimal.
4242 switch(hfinfo->display) {
4247 switch(hfinfo->type) {
4249 format = "%s: %u (0x%02x)";
4252 format = "%s: %u (0x%04x)";
4255 format = "%s: %u (0x%06x)";
4258 format = "%s: %u (0x%08x)";
4261 DISSECTOR_ASSERT_NOT_REACHED();
4265 case BASE_OCT: /* I'm lazy */
4269 switch(hfinfo->type) {
4271 format = "%s: 0x%02x";
4274 format = "%s: 0x%04x";
4277 format = "%s: 0x%06x";
4280 format = "%s: 0x%08x";
4283 DISSECTOR_ASSERT_NOT_REACHED();
4288 switch(hfinfo->type) {
4290 format = "%s: 0x%02x (%u)";
4293 format = "%s: 0x%04x (%u)";
4296 format = "%s: 0x%06x (%u)";
4299 format = "%s: 0x%08x (%u)";
4302 DISSECTOR_ASSERT_NOT_REACHED();
4307 DISSECTOR_ASSERT_NOT_REACHED();
4315 hfinfo_int_vals_format(header_field_info *hfinfo)
4317 const char *format = NULL;
4319 switch(hfinfo->display) {
4322 format = "%s: %s (%d)";
4324 case BASE_OCT: /* I'm lazy */
4325 format = "%s: %s (%o)";
4329 switch(hfinfo->type) {
4331 format = "%s: %s (0x%02x)";
4334 format = "%s: %s (0x%04x)";
4337 format = "%s: %s (0x%06x)";
4340 format = "%s: %s (0x%08x)";
4343 DISSECTOR_ASSERT_NOT_REACHED();
4348 DISSECTOR_ASSERT_NOT_REACHED();
4355 hfinfo_uint64_format(header_field_info *hfinfo)
4357 const char *format = NULL;
4359 /* Pick the proper format string */
4360 switch(hfinfo->display) {
4362 format = "%s: %" PRIu64;
4365 format = "%s: %" PRIu64 " (%" PRIx64 ")";
4367 case BASE_OCT: /* I'm lazy */
4368 format = "%s: %" PRIo64;
4371 format = "%s: 0x%016" PRIx64;
4374 format = "%s: 0x%016" PRIx64 " (%" PRIu64 ")";
4377 DISSECTOR_ASSERT_NOT_REACHED();
4384 hfinfo_int_format(header_field_info *hfinfo)
4386 const char *format = NULL;
4388 /* Pick the proper format string */
4389 switch(hfinfo->display) {
4394 switch(hfinfo->type) {
4396 format = "%s: %d (0x%02x)";
4399 format = "%s: %d (0x%04x)";
4402 format = "%s: %d (0x%06x)";
4405 format = "%s: %d (0x%08x)";
4408 DISSECTOR_ASSERT_NOT_REACHED();
4411 case BASE_OCT: /* I'm lazy */
4415 switch(hfinfo->type) {
4417 format = "%s: 0x%02x";
4420 format = "%s: 0x%04x";
4423 format = "%s: 0x%06x";
4426 format = "%s: 0x%08x";
4429 DISSECTOR_ASSERT_NOT_REACHED();
4434 switch(hfinfo->type) {
4436 format = "%s: 0x%02x (%d)";
4439 format = "%s: 0x%04x (%d)";
4442 format = "%s: 0x%06x (%d)";
4445 format = "%s: 0x%08x (%d)";
4448 DISSECTOR_ASSERT_NOT_REACHED();
4453 DISSECTOR_ASSERT_NOT_REACHED();
4460 hfinfo_int64_format(header_field_info *hfinfo)
4462 const char *format = NULL;
4464 /* Pick the proper format string */
4465 switch(hfinfo->display) {
4467 format = "%s: %" PRId64;
4470 format = "%s: %" PRId64 " (%" PRIx64 ")";
4472 case BASE_OCT: /* I'm lazy */
4473 format = "%s: %" PRIo64;
4476 format = "%s: 0x%016" PRIx64;
4479 format = "%s: 0x%016" PRIx64 " (%" PRId64 ")";
4482 DISSECTOR_ASSERT_NOT_REACHED();
4491 proto_registrar_n(void)
4493 return gpa_hfinfo.len;
4497 proto_registrar_get_name(int n)
4499 header_field_info *hfinfo;
4501 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
4502 return hfinfo->name;
4506 proto_registrar_get_abbrev(int n)
4508 header_field_info *hfinfo;
4510 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
4511 return hfinfo->abbrev;
4515 proto_registrar_get_ftype(int n)
4517 header_field_info *hfinfo;
4519 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
4520 return hfinfo->type;
4524 proto_registrar_get_parent(int n)
4526 header_field_info *hfinfo;
4528 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
4529 return hfinfo->parent;
4533 proto_registrar_is_protocol(int n)
4535 header_field_info *hfinfo;
4537 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
4538 return (hfinfo->parent == -1 ? TRUE : FALSE);
4541 /* Returns length of field in packet (not necessarily the length
4542 * in our internal representation, as in the case of IPv4).
4543 * 0 means undeterminable at time of registration
4544 * -1 means the field is not registered. */
4546 proto_registrar_get_length(int n)
4548 header_field_info *hfinfo;
4550 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
4551 return ftype_length(hfinfo->type);
4556 /* Looks for a protocol or a field in a proto_tree. Returns TRUE if
4557 * it exists anywhere, or FALSE if it exists nowhere. */
4559 proto_check_for_protocol_or_field(proto_tree* tree, int id)
4561 GPtrArray *ptrs = proto_get_finfo_ptr_array(tree, id);
4566 else if (g_ptr_array_len(ptrs) > 0) {
4574 /* Return GPtrArray* of field_info pointers for all hfindex that appear in tree.
4575 * This only works if the hfindex was "primed" before the dissection
4576 * took place, as we just pass back the already-created GPtrArray*.
4577 * The caller should *not* free the GPtrArray*; proto_tree_free_node()
4580 proto_get_finfo_ptr_array(proto_tree *tree, int id)
4582 return g_hash_table_lookup(PTREE_DATA(tree)->interesting_hfids,
4583 GINT_TO_POINTER(id));
4587 /* Helper struct for proto_find_info() and proto_all_finfos() */
4593 /* Helper function for proto_find_info() */
4595 find_finfo(proto_node *node, gpointer data)
4597 field_info *fi = PITEM_FINFO(node);
4598 if (fi && fi->hfinfo) {
4599 if (fi->hfinfo->id == ((ffdata_t*)data)->id) {
4600 g_ptr_array_add(((ffdata_t*)data)->array, fi);
4604 /* Don't stop traversing. */
4608 /* Return GPtrArray* of field_info pointers for all hfindex that appear in a tree.
4609 * This works on any proto_tree, primed or unprimed, but actually searches
4610 * the tree, so it is slower than using proto_get_finfo_ptr_array on a primed tree.
4611 * The caller does need to free the returned GPtrArray with
4612 * g_ptr_array_free(<array>, FALSE).
4615 proto_find_finfo(proto_tree *tree, int id)
4619 ffdata.array = g_ptr_array_new();
4622 proto_tree_traverse_pre_order(tree, find_finfo, &ffdata);
4624 return ffdata.array;
4627 /* Helper function for proto_all_finfos() */
4629 every_finfo(proto_node *node, gpointer data)
4631 field_info *fi = PITEM_FINFO(node);
4632 if (fi && fi->hfinfo) {
4633 g_ptr_array_add(((ffdata_t*)data)->array, fi);
4636 /* Don't stop traversing. */
4640 /* Return GPtrArray* of field_info pointers containing all hfindexes that appear in a tree. */
4642 proto_all_finfos(proto_tree *tree)
4646 ffdata.array = g_ptr_array_new();
4649 proto_tree_traverse_pre_order(tree, every_finfo, &ffdata);
4651 return ffdata.array;
4662 check_for_offset(proto_node *node, gpointer data)
4664 field_info *fi = PITEM_FINFO(node);
4665 offset_search_t *offsearch = data;
4667 /* !fi == the top most container node which holds nothing */
4668 if (fi && !PROTO_ITEM_IS_HIDDEN(node) && fi->ds_tvb && offsearch->tvb == fi->ds_tvb) {
4669 if (offsearch->offset >= (guint) fi->start &&
4670 offsearch->offset < (guint) (fi->start + fi->length)) {
4672 offsearch->finfo = fi;
4673 return FALSE; /* keep traversing */
4676 return FALSE; /* keep traversing */
4679 /* Search a proto_tree backwards (from leaves to root) looking for the field
4680 * whose start/length occupies 'offset' */
4681 /* XXX - I couldn't find an easy way to search backwards, so I search
4682 * forwards, w/o stopping. Therefore, the last finfo I find will the be
4683 * the one I want to return to the user. This algorithm is inefficient
4684 * and could be re-done, but I'd have to handle all the children and
4685 * siblings of each node myself. When I have more time I'll do that.
4688 proto_find_field_from_offset(proto_tree *tree, guint offset, tvbuff_t *tvb)
4690 offset_search_t offsearch;
4692 offsearch.offset = offset;
4693 offsearch.finfo = NULL;
4694 offsearch.tvb = tvb;
4696 proto_tree_traverse_pre_order(tree, check_for_offset, &offsearch);
4698 return offsearch.finfo;
4701 /* Dumps the protocols in the registration database to stdout. An independent
4702 * program can take this output and format it into nice tables or HTML or
4705 * There is one record per line. The fields are tab-delimited.
4707 * Field 1 = protocol name
4708 * Field 2 = protocol short name
4709 * Field 3 = protocol filter name
4712 proto_registrar_dump_protocols(void)
4714 protocol_t *protocol;
4716 void *cookie = NULL;
4718 for (i = proto_get_first_protocol(&cookie); i != -1;
4719 i = proto_get_next_protocol(&cookie)) {
4720 protocol = find_protocol_by_id(i);
4721 printf("%s\t%s\t%s\n", protocol->name, protocol->short_name,
4722 protocol->filter_name);
4726 /* Dumps the value_string and true/false strings for fields that have
4727 * them. There is one record per line. Fields are tab-delimited.
4728 * There are two types of records, Value String records and True/False
4729 * String records. The first field, 'V' or 'T', indicates the type
4735 * Field 2 = field abbreviation to which this value string corresponds
4736 * Field 3 = Integer value
4739 * True/False Strings
4740 * ------------------
4742 * Field 2 = field abbreviation to which this true/false string corresponds
4743 * Field 3 = True String
4744 * Field 4 = False String
4747 proto_registrar_dump_values(void)
4749 header_field_info *hfinfo, *parent_hfinfo;
4751 const value_string *vals;
4752 const true_false_string *tfs;
4754 len = gpa_hfinfo.len;
4755 for (i = 0; i < len ; i++) {
4756 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
4758 if (hfinfo->id == hf_text_only) {
4762 /* ignore protocols */
4763 if (proto_registrar_is_protocol(i)) {
4766 /* process header fields */
4769 * If this field isn't at the head of the list of
4770 * fields with this name, skip this field - all
4771 * fields with the same name are really just versions
4772 * of the same field stored in different bits, and
4773 * should have the same type/radix/value list, and
4774 * just differ in their bit masks. (If a field isn't
4775 * a bitfield, but can be, say, 1 or 2 bytes long,
4776 * it can just be made FT_UINT16, meaning the
4777 * *maximum* length is 2 bytes, and be used
4780 if (hfinfo->same_name_prev != NULL)
4783 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
4788 if (hfinfo->type == FT_UINT8 ||
4789 hfinfo->type == FT_UINT16 ||
4790 hfinfo->type == FT_UINT24 ||
4791 hfinfo->type == FT_UINT32 ||
4792 hfinfo->type == FT_UINT64 ||
4793 hfinfo->type == FT_INT8 ||
4794 hfinfo->type == FT_INT16 ||
4795 hfinfo->type == FT_INT24 ||
4796 hfinfo->type == FT_INT32 ||
4797 hfinfo->type == FT_INT64) {
4799 vals = hfinfo->strings;
4801 else if (hfinfo->type == FT_BOOLEAN) {
4802 tfs = hfinfo->strings;
4805 /* Print value strings? */
4808 while (vals[vi].strptr) {
4809 /* Print in the proper base */
4810 if (hfinfo->display == BASE_HEX) {
4811 printf("V\t%s\t0x%x\t%s\n",
4817 printf("V\t%s\t%u\t%s\n",
4826 /* Print true/false strings? */
4828 printf("T\t%s\t%s\t%s\n", hfinfo->abbrev,
4829 tfs->true_string, tfs->false_string);
4835 /* Dumps the contents of the registration database to stdout. An indepedent
4836 * program can take this output and format it into nice tables or HTML or
4839 * There is one record per line. Each record is either a protocol or a header
4840 * field, differentiated by the first field. The fields are tab-delimited.
4845 * Field 2 = descriptive protocol name
4846 * Field 3 = protocol abbreviation
4852 * Field 2 = descriptive field name
4853 * Field 3 = field abbreviation
4854 * Field 4 = type ( textual representation of the the ftenum type )
4855 * Field 5 = parent protocol abbreviation
4856 * Field 6 = blurb describing field
4860 * Field 2 = descriptive field name
4861 * Field 3 = field abbreviation
4862 * Field 4 = type ( textual representation of the the ftenum type )
4863 * Field 5 = parent protocol abbreviation
4864 * Field 6 = blurb describing field
4865 * Field 7 = base for display (for integer types)
4866 * Field 8 = blurb describing field (yes, apparently we repeated this accidentally)
4870 * Field 2 = descriptive field name
4871 * Field 3 = field abbreviation
4872 * Field 4 = type ( textual representation of the the ftenum type )
4873 * Field 5 = parent protocol abbreviation
4874 * Field 6 = blurb describing field
4875 * Field 7 = base for display (for integer types)
4879 proto_registrar_dump_fields(int format)
4881 header_field_info *hfinfo, *parent_hfinfo;
4883 const char *enum_name;
4884 const char *base_name;
4887 len = gpa_hfinfo.len;
4888 for (i = 0; i < len ; i++) {
4889 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
4892 * Skip the pseudo-field for "proto_tree_add_text()" since
4893 * we don't want it in the list of filterable fields.
4895 if (hfinfo->id == hf_text_only)
4898 /* format for protocols */
4899 if (proto_registrar_is_protocol(i)) {
4900 printf("P\t%s\t%s\n", hfinfo->name, hfinfo->abbrev);
4902 /* format for header fields */
4905 * If this field isn't at the head of the list of
4906 * fields with this name, skip this field - all
4907 * fields with the same name are really just versions
4908 * of the same field stored in different bits, and
4909 * should have the same type/radix/value list, and
4910 * just differ in their bit masks. (If a field isn't
4911 * a bitfield, but can be, say, 1 or 2 bytes long,
4912 * it can just be made FT_UINT16, meaning the
4913 * *maximum* length is 2 bytes, and be used
4916 if (hfinfo->same_name_prev != NULL)
4919 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
4921 enum_name = ftype_name(hfinfo->type);
4925 if (hfinfo->type == FT_UINT8 ||
4926 hfinfo->type == FT_UINT16 ||
4927 hfinfo->type == FT_UINT24 ||
4928 hfinfo->type == FT_UINT32 ||
4929 hfinfo->type == FT_UINT64 ||
4930 hfinfo->type == FT_INT8 ||
4931 hfinfo->type == FT_INT16 ||
4932 hfinfo->type == FT_INT24 ||
4933 hfinfo->type == FT_INT32 ||
4934 hfinfo->type == FT_INT64) {
4937 switch(hfinfo->display) {
4939 base_name = "BASE_NONE";
4942 base_name = "BASE_DEC";
4945 base_name = "BASE_HEX";
4948 base_name = "BASE_OCT";
4951 base_name = "BASE_DEC_HEX";
4954 base_name = "BASE_HEX_DEC";
4960 blurb = hfinfo->blurb;
4964 printf("F\t%s\t%s\t%s\t%s\t%s\n",
4965 hfinfo->name, hfinfo->abbrev, enum_name,
4966 parent_hfinfo->abbrev, blurb);
4968 else if (format == 2) {
4969 printf("F\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n",
4970 hfinfo->name, hfinfo->abbrev, enum_name,
4971 parent_hfinfo->abbrev, blurb,
4974 else if (format == 3) {
4975 printf("F\t%s\t%s\t%s\t%s\t%s\t%s\t%u\n",
4976 hfinfo->name, hfinfo->abbrev, enum_name,
4977 parent_hfinfo->abbrev, blurb,
4978 base_name, hfinfo->bitmask);
4981 g_assert_not_reached();
4988 hfinfo_numeric_format(header_field_info *hfinfo)
4990 const char *format = NULL;
4992 /* Pick the proper format string */
4993 if (hfinfo->type == FT_FRAMENUM) {
4995 * Frame numbers are always displayed in decimal.
4997 format = "%s == %u";
4999 /* Pick the proper format string */
5000 switch(hfinfo->display) {
5003 case BASE_OCT: /* I'm lazy */
5004 switch(hfinfo->type) {
5009 format = "%s == %u";
5012 format = "%s == %" PRIu64;
5018 format = "%s == %d";
5021 format = "%s == %" PRId64;
5024 DISSECTOR_ASSERT_NOT_REACHED();
5030 switch(hfinfo->type) {
5032 format = "%s == 0x%02x";
5035 format = "%s == 0x%04x";
5038 format = "%s == 0x%06x";
5041 format = "%s == 0x%08x";
5044 format = "%s == 0x%016" PRIx64;
5047 DISSECTOR_ASSERT_NOT_REACHED();
5052 DISSECTOR_ASSERT_NOT_REACHED();
5059 /* This function indicates whether it's possible to construct a
5060 * "match selected" display filter string for the specified field,
5061 * returns an indication of whether it's possible, and, if it's
5062 * possible and "filter" is non-null, constructs the filter and
5063 * sets "*filter" to point to it.
5064 * You do not need to [g_]free() this string since it will be automatically
5065 * freed once the next packet is dissected.
5068 construct_match_selected_string(field_info *finfo, epan_dissect_t *edt,
5071 header_field_info *hfinfo;
5077 gint start, length, length_remaining;
5080 hfinfo = finfo->hfinfo;
5081 DISSECTOR_ASSERT(hfinfo);
5082 abbrev_len = strlen(hfinfo->abbrev);
5085 * XXX - we can't use the "val_to_string_repr" and "string_repr_len"
5086 * functions for FT_UINT and FT_INT types, as we choose the base in
5087 * the string expression based on the display base of the field.
5089 * Note that the base does matter, as this is also used for
5090 * the protocolinfo tap.
5092 * It might be nice to use them in "proto_item_fill_label()"
5093 * as well, although, there, you'd have to deal with the base
5094 * *and* with resolved values for addresses.
5096 * Perhaps we need two different val_to_string routines, one
5097 * to generate items for display filters and one to generate
5098 * strings for display, and pass to both of them the
5099 * "display" and "strings" values in the header_field_info
5100 * structure for the field, so they can get the base and,
5101 * if the field is Boolean or an enumerated integer type,
5102 * the tables used to generate human-readable values.
5104 switch(hfinfo->type) {
5116 * 4 bytes for " == ".
5119 * a sign + up to 10 digits of 32-bit integer,
5122 * "0x" + 8 digits of 32-bit integer, in hex;
5124 * 11 digits of 32-bit integer, in octal.
5125 * (No, we don't do octal, but this way,
5126 * we know that if we do, this will still
5129 * 1 byte for the trailing '\0'.
5131 if (filter != NULL) {
5132 dfilter_len = abbrev_len + 4 + 11 + 1;
5133 *filter = ep_alloc0(dfilter_len);
5134 format = hfinfo_numeric_format(hfinfo);
5135 g_snprintf(*filter, dfilter_len, format,
5137 fvalue_get_integer(&finfo->value));
5144 * 4 bytes for " == ".
5147 * a sign + up to 20 digits of 32-bit integer,
5150 * "0x" + 16 digits of 32-bit integer, in hex;
5152 * 22 digits of 32-bit integer, in octal.
5153 * (No, we don't do octal, but this way,
5154 * we know that if we do, this will still
5157 * 1 byte for the trailing '\0'.
5159 if (filter != NULL) {
5160 dfilter_len = abbrev_len + 4 + 22 + 1;
5161 *filter = ep_alloc0(dfilter_len);
5162 format = hfinfo_numeric_format(hfinfo);
5163 g_snprintf(*filter, dfilter_len, format,
5165 fvalue_get_integer64(&finfo->value));
5171 *filter = ep_strdup(finfo->hfinfo->abbrev);
5177 * If the length is 0, just match the name of the
5180 * (Also check for negative values, just in case,
5181 * as we'll cast it to an unsigned value later.)
5183 length = finfo->length;
5186 *filter = ep_strdup(finfo->hfinfo->abbrev);
5193 * This doesn't have a value, so we'd match
5194 * on the raw bytes at this address.
5196 * Should we be allowed to access to the raw bytes?
5197 * If "edt" is NULL, the answer is "no".
5203 * Is this field part of the raw frame tvbuff?
5204 * If not, we can't use "frame[N:M]" to match
5207 * XXX - should this be frame-relative, or
5208 * protocol-relative?
5210 * XXX - does this fallback for non-registered
5211 * fields even make sense?
5213 if (finfo->ds_tvb != edt->tvb)
5214 return FALSE; /* you lose */
5217 * Don't go past the end of that tvbuff.
5219 length_remaining = tvb_length_remaining(finfo->ds_tvb, finfo->start);
5220 if (length > length_remaining)
5221 length = length_remaining;
5225 if (filter != NULL) {
5226 start = finfo->start;
5227 buf_len = 32 + length * 3;
5228 *filter = ep_alloc0(buf_len);
5231 ptr += g_snprintf(ptr, buf_len-(ptr-*filter),
5232 "frame[%d:%d] == ", finfo->start, length);
5233 for (i=0;i<length; i++) {
5234 c = tvb_get_guint8(finfo->ds_tvb, start);
5237 ptr += g_snprintf(ptr, buf_len-(ptr-*filter), "%02x", c);
5240 ptr += g_snprintf(ptr, buf_len-(ptr-*filter), ":%02x", c);
5246 /* By default, use the fvalue's "to_string_repr" method. */
5248 /* Figure out the string length needed.
5249 * The ft_repr length.
5250 * 4 bytes for " == ".
5251 * 1 byte for trailing NUL.
5253 if (filter != NULL) {
5254 dfilter_len = fvalue_string_repr_len(&finfo->value,
5256 dfilter_len += abbrev_len + 4 + 1;
5257 *filter = ep_alloc0(dfilter_len);
5259 /* Create the string */
5260 g_snprintf(*filter, dfilter_len, "%s == ",
5262 fvalue_to_string_repr(&finfo->value,
5264 &(*filter)[abbrev_len + 4]);
5273 * Returns TRUE if we can do a "match selected" on the field, FALSE
5277 proto_can_match_selected(field_info *finfo, epan_dissect_t *edt)
5279 return construct_match_selected_string(finfo, edt, NULL);
5282 /* This function attempts to construct a "match selected" display filter
5283 * string for the specified field; if it can do so, it returns a pointer
5284 * to the string, otherwise it returns NULL.
5286 * The string is allocated with packet lifetime scope.
5287 * You do not need to [g_]free() this string since it will be automatically
5288 * freed once the next packet is dissected.
5291 proto_construct_match_selected_string(field_info *finfo, epan_dissect_t *edt)
5295 if (!construct_match_selected_string(finfo, edt, &filter))
5301 /* This function will dissect a sequence of bytes that describe a
5303 * hf_hdr is a 8/16/24/32 bit integer that describes the bitmask to be dissected.
5304 * This field will form an expansion under which the individual fields of the
5305 * bitmask is dissected and displayed.
5306 * This field must be of the type FT_[U]INT{8|16|24|32}.
5308 * fields is an array of pointers to int that lists all the fields of the
5309 * bitmask. These fields can be either of the type FT_BOOLEAN for flags
5310 * or another integer of the same type/size as hf_hdr with a mask specified.
5311 * This array is terminated by a NULL entry.
5313 * FT_BOOLEAN bits that are set to 1 will have the name added to the expansion.
5314 * FT_integer fields that have a value_string attached will have the
5315 * matched string displayed on the expansion line.
5318 proto_tree_add_bitmask(proto_tree *parent_tree, tvbuff_t *tvb, int offset, int hf_hdr, gint ett, const int **fields, gboolean little_endian)
5320 proto_tree *tree=NULL;
5321 proto_item *item=NULL;
5322 header_field_info *hf_info;
5326 hf_info=proto_registrar_get_nth(hf_hdr);
5327 switch(hf_info->type){
5331 value=tvb_get_guint8(tvb, offset);
5337 value=tvb_get_letohs(tvb, offset);
5339 value=tvb_get_ntohs(tvb, offset);
5346 value=tvb_get_letoh24(tvb, offset);
5348 value=tvb_get_ntoh24(tvb, offset);
5355 value=tvb_get_letohl(tvb, offset);
5357 value=tvb_get_ntohl(tvb, offset);
5361 g_assert_not_reached();
5365 item=proto_tree_add_item(parent_tree, hf_hdr, tvb, offset, len, little_endian);
5366 tree=proto_item_add_subtree(item, ett);
5370 header_field_info *hf_field;
5371 guint32 tmpval, tmpmask;
5373 hf_field=proto_registrar_get_nth(**fields);
5374 switch(hf_field->type){
5383 proto_tree_add_item(tree, **fields, tvb, offset, len, little_endian);
5385 /* Mask and shift out the value */
5386 tmpmask=hf_field->bitmask;
5390 while(!(tmpmask&0x00000001)){
5395 /* Show the value_string content (if there is one) */
5396 if(hf_field->strings){
5397 proto_item_append_text(item, ", %s", val_to_str(tmpval, hf_field->strings, "Unknown"));
5402 proto_tree_add_item(tree, **fields, tvb, offset, len, little_endian);
5403 /* if the flag is set, show the name */
5404 if(hf_field->bitmask&value){
5405 proto_item_append_text(item, ", %s", hf_field->name);
5409 g_assert_not_reached();