2 * Routines for protocol tree
6 * Ethereal - Network traffic analyzer
7 * By Gerald Combs <gerald@ethereal.com>
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.
35 #ifdef NEED_SNPRINTF_H
36 # include "snprintf.h"
41 #include "addr_resolv.h"
43 #include "ipv6-utils.h"
45 #include "epan_dissect.h"
49 #define cVALS(x) (const value_string*)(x)
52 #define TRY_TO_FAKE_THIS_ITEM(tree, hfindex) \
53 /* If this item is not referenced we dont have to do much work \
54 at all but we should still return a node so that \
55 field items below this node ( think proto_item_add_subtree() )\
56 will still have somewhere to attach to \
57 or else filtering will not work (they would be ignored since tree\
59 DONT try to fake a node where PITEM_FINFO(pi) is NULL \
60 since dissectors that want to do proto_item_set_len() ot \
61 other operations that dereference this would crash. \
62 We dont fake FT_PROTOCOL either since these are cheap and \
63 some stuff (proto hier stat) assumes they always exist. \
65 if(!(PTREE_DATA(tree)->visible)){ \
66 if(PITEM_FINFO(tree)){ \
67 register header_field_info *hfinfo; \
68 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo); \
69 if((hfinfo->ref_count == 0) \
70 && (hfinfo->type!=FT_PROTOCOL)){ \
71 /* just return tree back to the caller */\
77 #define TRY_TO_FAKE_THIS_ITEM(tree, hfindex) ;
81 proto_tree_free_node(proto_node *node, gpointer data);
83 static void fill_label_boolean(field_info *fi, gchar *label_str);
84 static void fill_label_uint(field_info *fi, gchar *label_str);
85 static void fill_label_uint64(field_info *fi, gchar *label_str);
86 static void fill_label_enumerated_uint(field_info *fi, gchar *label_str);
87 static void fill_label_enumerated_bitfield(field_info *fi, gchar *label_str);
88 static void fill_label_numeric_bitfield(field_info *fi, gchar *label_str);
89 static void fill_label_int(field_info *fi, gchar *label_str);
90 static void fill_label_int64(field_info *fi, gchar *label_str);
91 static void fill_label_enumerated_int(field_info *fi, gchar *label_str);
93 int hfinfo_bitwidth(header_field_info *hfinfo);
94 static char* hfinfo_uint_vals_format(header_field_info *hfinfo);
95 static char* hfinfo_uint_format(header_field_info *hfinfo);
96 static char* hfinfo_uint64_format(header_field_info *hfinfo);
97 static char* hfinfo_int_vals_format(header_field_info *hfinfo);
98 static char* hfinfo_int_format(header_field_info *hfinfo);
99 static char* hfinfo_int64_format(header_field_info *hfinfo);
102 proto_tree_add_node(proto_tree *tree, field_info *fi);
105 alloc_field_info(proto_tree *tree, int hfindex, tvbuff_t *tvb,
106 gint start, gint *length);
109 proto_tree_add_pi(proto_tree *tree, int hfindex, tvbuff_t *tvb,
110 gint start, gint *length, field_info **pfi);
113 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap);
116 proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb);
118 proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length);
120 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length);
122 proto_tree_set_time(field_info *fi, nstime_t *value_ptr);
124 proto_tree_set_string(field_info *fi, const char* value, gboolean);
126 proto_tree_set_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
128 proto_tree_set_ether(field_info *fi, const guint8* value);
130 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start);
132 proto_tree_set_ipxnet(field_info *fi, guint32 value);
134 proto_tree_set_ipv4(field_info *fi, guint32 value);
136 proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr);
138 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start);
140 proto_tree_set_guid(field_info *fi, const guint8* value_ptr);
142 proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, gint start);
144 proto_tree_set_boolean(field_info *fi, guint32 value);
146 proto_tree_set_float(field_info *fi, float value);
148 proto_tree_set_double(field_info *fi, double value);
150 proto_tree_set_uint(field_info *fi, guint32 value);
152 proto_tree_set_int(field_info *fi, gint32 value);
154 proto_tree_set_uint64(field_info *fi, guint64 value);
156 proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start, gboolean little_endian);
158 static int proto_register_field_init(header_field_info *hfinfo, int parent);
160 /* Comparision function for tree insertion. A wrapper around strcmp() */
161 static int g_strcmp(gconstpointer a, gconstpointer b);
163 /* special-case header field used within proto.c */
164 int hf_text_only = -1;
166 /* Structure for information about a protocol */
168 const char *name; /* long description */
169 const char *short_name; /* short description */
170 const char *filter_name; /* name of this protocol in filters */
171 int proto_id; /* field ID for this protocol */
172 GList *fields; /* fields for this protocol */
173 GList *last_field; /* pointer to end of list of fields */
174 gboolean is_enabled; /* TRUE if protocol is enabled */
175 gboolean can_toggle; /* TRUE if is_enabled can be changed */
178 /* List of all protocols */
179 static GList *protocols = NULL;
181 #define INITIAL_NUM_PROTOCOL_HFINFO 200
184 /* Contains information about protocols and header fields. Used when
185 * dissectors register their data */
186 static GMemChunk *gmc_hfinfo = NULL;
188 /* Contains information about a field when a dissector calls
189 * proto_tree_add_item. */
190 SLAB_ITEM_TYPE_DEFINE(field_info)
191 static SLAB_FREE_LIST_DEFINE(field_info)
192 static field_info *field_info_tmp=NULL;
193 #define FIELD_INFO_NEW(fi) \
194 SLAB_ALLOC(fi, field_info)
195 #define FIELD_INFO_FREE(fi) \
196 SLAB_FREE(fi, field_info)
200 /* Contains the space for proto_nodes. */
201 SLAB_ITEM_TYPE_DEFINE(proto_node)
202 static SLAB_FREE_LIST_DEFINE(proto_node)
203 #define PROTO_NODE_NEW(node) \
204 SLAB_ALLOC(node, proto_node) \
205 node->first_child = NULL; \
206 node->last_child = NULL; \
209 #define PROTO_NODE_FREE(node) \
210 SLAB_FREE(node, proto_node)
214 /* String space for protocol and field items for the GUI */
215 SLAB_ITEM_TYPE_DEFINE(item_label_t)
216 static SLAB_FREE_LIST_DEFINE(item_label_t)
217 #define ITEM_LABEL_NEW(il) \
218 SLAB_ALLOC(il, item_label_t)
219 #define ITEM_LABEL_FREE(il) \
220 SLAB_FREE(il, item_label_t)
223 #define PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo) \
224 DISSECTOR_ASSERT((guint)hfindex < gpa_hfinfo.len); \
225 hfinfo=gpa_hfinfo.hfi[hfindex];
228 /* List which stores protocols and fields that have been registered */
229 typedef struct _gpa_hfinfo_t {
231 guint32 allocated_len;
232 header_field_info **hfi;
234 gpa_hfinfo_t gpa_hfinfo;
236 /* Balanced tree of abbreviations and IDs */
237 static GTree *gpa_name_tree = NULL;
239 /* Points to the first element of an array of Booleans, indexed by
240 a subtree item type; that array element is TRUE if subtrees of
241 an item of that type are to be expanded. */
242 gboolean *tree_is_expanded;
244 /* Number of elements in that array. */
247 /* Name hashtables for fast detection of duplicate names */
248 static GHashTable* proto_names = NULL;
249 static GHashTable* proto_short_names = NULL;
250 static GHashTable* proto_filter_names = NULL;
253 proto_compare_name(gconstpointer p1_arg, gconstpointer p2_arg)
255 const protocol_t *p1 = p1_arg;
256 const protocol_t *p2 = p2_arg;
258 return g_strcasecmp(p1->short_name, p2->short_name);
262 /* initialize data structures and register protocols and fields */
264 proto_init(const char *plugin_dir
269 void (register_all_protocols)(void),
270 void (register_all_protocol_handoffs)(void))
272 static hf_register_info hf[] = {
274 { "", "", FT_NONE, BASE_NONE, NULL, 0x0,
279 proto_names = g_hash_table_new(g_int_hash, g_int_equal);
280 proto_short_names = g_hash_table_new(g_int_hash, g_int_equal);
281 proto_filter_names = g_hash_table_new(g_int_hash, g_int_equal);
285 gmc_hfinfo = g_mem_chunk_new("gmc_hfinfo",
286 sizeof(header_field_info),
287 INITIAL_NUM_PROTOCOL_HFINFO * sizeof(header_field_info),
291 gpa_hfinfo.allocated_len=0;
293 gpa_name_tree = g_tree_new(g_strcmp);
295 /* Initialize the ftype subsystem */
298 /* Register one special-case FT_TEXT_ONLY field for use when
299 converting ethereal to new-style proto_tree. These fields
300 are merely strings on the GUI tree; they are not filterable */
301 proto_register_field_array(-1, hf, array_length(hf));
303 /* Have each built-in dissector register its protocols, fields,
304 dissector tables, and dissectors to be called through a
305 handle, and do whatever one-time initialization it needs to
307 register_all_protocols();
310 /* Now scan for plugins and load all the ones we find, calling
311 their register routines to do the stuff described above. */
312 init_plugins(plugin_dir);
315 /* Now call the "handoff registration" routines of all built-in
316 dissectors; those routines register the dissector in other
317 dissectors' handoff tables, and fetch any dissector handles
319 register_all_protocol_handoffs();
322 /* Now do the same with plugins. */
323 register_all_plugin_handoffs();
326 /* sort the protocols by protocol name */
327 protocols = g_list_sort(protocols, proto_compare_name);
329 /* We've assigned all the subtree type values; allocate the array
330 for them, and zero it out. */
331 tree_is_expanded = g_malloc(num_tree_types*sizeof (gint *));
332 memset(tree_is_expanded, 0, num_tree_types*sizeof (gint *));
335 /* String comparison func for dfilter_token GTree */
337 g_strcmp(gconstpointer a, gconstpointer b)
339 return strcmp((const char*)a, (const char*)b);
345 /* Free the abbrev/ID GTree */
347 g_tree_destroy(gpa_name_tree);
348 gpa_name_tree = NULL;
352 g_mem_chunk_destroy(gmc_hfinfo);
354 if(gpa_hfinfo.allocated_len){
356 gpa_hfinfo.allocated_len=0;
357 g_free(gpa_hfinfo.hfi);
360 if (tree_is_expanded != NULL)
361 g_free(tree_is_expanded);
365 typedef gboolean (*proto_tree_traverse_func)(proto_node *, gpointer);
368 proto_tree_traverse_pre_order(proto_tree *tree, proto_tree_traverse_func func,
371 proto_node *pnode = tree;
375 if (func(pnode, data))
378 child = pnode->first_child;
379 while (child != NULL) {
381 * The routine we call might modify the child, e.g. by
382 * freeing it, so we get the child's successor before
383 * calling that routine.
386 child = current->next;
387 if (proto_tree_traverse_pre_order((proto_tree *)current, func,
396 proto_tree_traverse_in_order(proto_tree *tree, proto_tree_traverse_func func,
399 proto_node *pnode = tree;
403 child = pnode->first_child;
406 * The routine we call might modify the child, e.g. by
407 * freeing it, so we get the child's successor before
408 * calling that routine.
411 child = current->next;
413 if (proto_tree_traverse_in_order((proto_tree *)current, func,
417 if (func(pnode, data))
420 while (child != NULL) {
422 * The routine we call might modify the child, e.g. by
423 * freeing it, so we get the child's successor before
424 * calling that routine.
427 child = current->next;
428 if (proto_tree_traverse_in_order((proto_tree *)current,
433 if (func(pnode, data))
441 proto_tree_children_foreach(proto_tree *tree, proto_tree_foreach_func func,
444 proto_node *node = tree;
447 node = node->first_child;
448 while (node != NULL) {
450 node = current->next;
451 func((proto_tree *)current, data);
455 /* frees the resources that the dissection a proto_tree uses */
457 proto_tree_free(proto_tree *tree)
459 proto_tree_traverse_in_order(tree, proto_tree_free_node, NULL);
463 free_GPtrArray_value(gpointer key _U_, gpointer value, gpointer user_data _U_)
465 GPtrArray *ptrs = value;
466 gint hfid = (gint)key;
467 header_field_info *hfinfo;
470 PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
471 if(hfinfo->ref_count){
472 /* when a field is referenced by a filter this also
473 affects the refcount for the parent protocol so we need
474 to adjust the refcount for the parent as well
476 if( (hfinfo->parent != -1) && (hfinfo->ref_count) ){
477 header_field_info *parent_hfinfo;
478 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
479 parent_hfinfo->ref_count -= hfinfo->ref_count;
481 hfinfo->ref_count = 0;
484 g_ptr_array_free(ptrs, TRUE);
488 free_node_tree_data(tree_data_t *tree_data)
490 /* Free all the GPtrArray's in the interesting_hfids hash. */
491 g_hash_table_foreach(tree_data->interesting_hfids,
492 free_GPtrArray_value, NULL);
494 /* And then destroy the hash. */
495 g_hash_table_destroy(tree_data->interesting_hfids);
497 /* And finally the tree_data_t itself. */
501 #define FREE_NODE_FIELD_INFO(finfo) \
503 ITEM_LABEL_FREE(finfo->rep); \
505 FVALUE_CLEANUP(&finfo->value); \
506 FIELD_INFO_FREE(finfo);
509 proto_tree_free_node(proto_node *node, gpointer data _U_)
511 field_info *finfo = PITEM_FINFO(node);
514 /* This is the root node. Destroy the per-tree data.
515 * There is no field_info to destroy. */
516 free_node_tree_data(PTREE_DATA(node));
519 /* This is a child node. Don't free the per-tree data, but
520 * do free the field_info data. */
521 FREE_NODE_FIELD_INFO(finfo);
524 /* Free the proto_node. */
525 PROTO_NODE_FREE(node);
527 return FALSE; /* FALSE = do not end traversal of protocol tree */
530 /* Is the parsing being done for a visible proto_tree or an invisible one?
531 * By setting this correctly, the proto_tree creation is sped up by not
532 * having to call vsnprintf and copy strings around.
535 proto_tree_set_visible(proto_tree *tree, gboolean visible)
537 PTREE_DATA(tree)->visible = visible;
540 /* Assume dissector set only its protocol fields.
541 This function is called by dissectors and allowes to speed up filtering
542 in ethereal, if this function returns FALSE it is safe to reset tree to NULL
543 and thus skip calling most of the expensive proto_tree_add_...()
545 If the tree is visible we implicitely assume the field is referenced.
548 proto_field_is_referenced(proto_tree *tree, int proto_id)
550 register header_field_info *hfinfo;
556 if (PTREE_DATA(tree)->visible)
559 PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
560 if (hfinfo->ref_count != 0)
567 /* Finds a record in the hf_info_records array by id. */
569 proto_registrar_get_nth(guint hfindex)
571 register header_field_info *hfinfo;
573 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
577 /* Finds a record in the hf_info_records array by name.
580 proto_registrar_get_byname(const char *field_name)
582 DISSECTOR_ASSERT(field_name != NULL);
583 return g_tree_lookup(gpa_name_tree, field_name);
586 /* Add a text-only node, leaving it to our caller to fill the text in */
588 proto_tree_add_text_node(proto_tree *tree, tvbuff_t *tvb, gint start, gint length)
592 pi = proto_tree_add_pi(tree, hf_text_only, tvb, start, &length, NULL);
599 /* Add a text-only node to the proto_tree */
601 proto_tree_add_text(proto_tree *tree, tvbuff_t *tvb, gint start, gint length,
602 const char *format, ...)
607 pi = proto_tree_add_text_node(tree, tvb, start, length);
611 va_start(ap, format);
612 proto_tree_set_representation(pi, format, ap);
618 /* Add a text-only node to the proto_tree (va_list version) */
620 proto_tree_add_text_valist(proto_tree *tree, tvbuff_t *tvb, gint start,
621 gint length, const char *format, va_list ap)
625 pi = proto_tree_add_text_node(tree, tvb, start, length);
629 proto_tree_set_representation(pi, format, ap);
634 /* Add a text-only node for debugging purposes. The caller doesn't need
635 * to worry about tvbuff, start, or length. Debug message gets sent to
638 proto_tree_add_debug_text(proto_tree *tree, const char *format, ...)
643 pi = proto_tree_add_text_node(tree, NULL, 0, 0);
647 va_start(ap, format);
648 proto_tree_set_representation(pi, format, ap);
658 get_uint_value(tvbuff_t *tvb, gint offset, gint length, gboolean little_endian)
665 value = tvb_get_guint8(tvb, offset);
669 value = little_endian ? tvb_get_letohs(tvb, offset)
670 : tvb_get_ntohs(tvb, offset);
674 value = little_endian ? tvb_get_letoh24(tvb, offset)
675 : tvb_get_ntoh24(tvb, offset);
679 value = little_endian ? tvb_get_letohl(tvb, offset)
680 : tvb_get_ntohl(tvb, offset);
684 THROW(ReportedBoundsError);
692 get_int_value(tvbuff_t *tvb, gint offset, gint length, gboolean little_endian)
699 value = (gint8)tvb_get_guint8(tvb, offset);
703 value = (gint16) (little_endian ? tvb_get_letohs(tvb, offset)
704 : tvb_get_ntohs(tvb, offset));
708 value = little_endian ? tvb_get_letoh24(tvb, offset)
709 : tvb_get_ntoh24(tvb, offset);
710 if (value & 0x00800000) {
711 /* Sign bit is set; sign-extend it. */
717 value = little_endian ? tvb_get_letohl(tvb, offset)
718 : tvb_get_ntohl(tvb, offset);
722 THROW(ReportedBoundsError);
729 /* Add an item to a proto_tree, using the text label registered to that item;
730 the item is extracted from the tvbuff handed to it. */
732 proto_tree_add_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
733 gint start, gint length, gboolean little_endian)
747 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
749 new_fi = alloc_field_info(tree, hfindex, tvb, start, &length);
754 /* there is a possibility here that we might raise an exception
755 * and thus would lose track of the field_info.
756 * store it in a temp so that if we come here again we can reclaim
757 * the field_info without leaking memory.
759 /* XXX this only keeps track of one field_info struct,
760 if we ever go multithreaded for calls to this function
761 we have to change this code to use per thread variable.
764 /* oops, last one we got must have been lost due
766 * good thing we saved it, now we can reverse the
767 * memory leak and reclaim it.
769 SLAB_FREE(field_info_tmp, field_info);
771 /* we might throw an exception, keep track of this one
772 * across the "dangerous" section below.
774 field_info_tmp=new_fi;
776 switch(new_fi->hfinfo->type) {
778 /* no value to set for FT_NONE */
782 proto_tree_set_protocol_tvb(new_fi, tvb);
786 proto_tree_set_bytes_tvb(new_fi, tvb, start, length);
790 n = get_uint_value(tvb, start, length, little_endian);
791 proto_tree_set_bytes_tvb(new_fi, tvb, start + length, n);
793 /* Instead of calling proto_item_set_len(), since we don't yet
794 * have a proto_item, we set the field_info's length ourselves. */
795 new_fi->length = n + length;
799 proto_tree_set_boolean(new_fi,
800 get_uint_value(tvb, start, length, little_endian));
803 /* XXX - make these just FT_UINT? */
808 proto_tree_set_uint(new_fi,
809 get_uint_value(tvb, start, length, little_endian));
814 DISSECTOR_ASSERT(length == 8);
815 proto_tree_set_uint64_tvb(new_fi, tvb, start, little_endian);
818 /* XXX - make these just FT_INT? */
823 proto_tree_set_int(new_fi,
824 get_int_value(tvb, start, length, little_endian));
828 DISSECTOR_ASSERT(length == 4);
829 tvb_memcpy(tvb, (guint8 *)&value, start, 4);
830 proto_tree_set_ipv4(new_fi, little_endian ? GUINT32_SWAP_LE_BE(value) : value);
834 DISSECTOR_ASSERT(length == 4);
835 proto_tree_set_ipxnet(new_fi,
836 get_uint_value(tvb, start, 4, FALSE));
840 DISSECTOR_ASSERT(length == 16);
841 proto_tree_set_ipv6_tvb(new_fi, tvb, start);
845 DISSECTOR_ASSERT(length == 6);
846 proto_tree_set_ether_tvb(new_fi, tvb, start);
850 DISSECTOR_ASSERT(length == 16);
851 proto_tree_set_guid_tvb(new_fi, tvb, start);
855 DISSECTOR_ASSERT(length == 4);
857 floatval = tvb_get_letohieee_float(tvb, start);
859 floatval = tvb_get_ntohieee_float(tvb, start);
860 proto_tree_set_float(new_fi, floatval);
864 DISSECTOR_ASSERT(length == 8);
866 doubleval = tvb_get_letohieee_double(tvb, start);
868 doubleval = tvb_get_ntohieee_double(tvb, start);
869 proto_tree_set_double(new_fi, doubleval);
873 /* This g_strdup'ed memory is freed in proto_tree_free_node() */
874 proto_tree_set_string_tvb(new_fi, tvb, start, length);
878 DISSECTOR_ASSERT(length >= -1);
879 /* Instead of calling proto_item_set_len(),
880 * since we don't yet have a proto_item, we
881 * set the field_info's length ourselves.
883 * XXX - our caller can't use that length to
884 * advance an offset unless they arrange that
885 * there always be a protocol tree into which
886 * we're putting this item.
889 /* This can throw an exception */
890 length = tvb_strsize(tvb, start);
892 /* This g_malloc'ed memory is freed
893 in proto_tree_free_node() */
894 string = g_malloc(length);
896 tvb_memcpy(tvb, string, start, length);
897 } else if (length == 0) {
898 string = g_strdup("[Empty]");
900 /* In this case, length signifies
901 * the length of the string.
903 * This could either be a null-padded
904 * string, which doesn't necessarily
905 * have a '\0' at the end, or a
906 * null-terminated string, with a
907 * trailing '\0'. (Yes, there are
908 * cases where you have a string
909 * that's both counted and null-
912 * In the first case, we must
913 * allocate a buffer of length
914 * "length+1", to make room for
917 * In the second case, we don't
918 * assume that there is a trailing
919 * '\0' there, as the packet might
920 * be malformed. (XXX - should we
921 * throw an exception if there's no
922 * trailing '\0'?) Therefore, we
923 * allocate a buffer of length
924 * "length+1", and put in a trailing
925 * '\0', just to be safe.
927 * (XXX - this would change if
928 * we made string values counted
929 * rather than null-terminated.)
932 /* This g_malloc'ed memory is freed
933 * in proto_tree_free_node() */
934 string = tvb_get_string(tvb, start,
937 new_fi->length = length;
938 proto_tree_set_string(new_fi, string, TRUE);
942 /* This g_strdup'ed memory is freed in proto_tree_free_node() */
943 n = get_uint_value(tvb, start, length, little_endian);
944 proto_tree_set_string_tvb(new_fi, tvb, start + length, n);
946 /* Instead of calling proto_item_set_len(), since we
947 * don't yet have a proto_item, we set the
948 * field_info's length ourselves.
950 * XXX - our caller can't use that length to
951 * advance an offset unless they arrange that
952 * there always be a protocol tree into which
953 * we're putting this item.
955 new_fi->length = n + length;
959 g_error("new_fi->hfinfo->type %d (%s) not handled\n",
960 new_fi->hfinfo->type,
961 ftype_name(new_fi->hfinfo->type));
962 DISSECTOR_ASSERT_NOT_REACHED();
966 /* Don't add new node to proto_tree until now so that any exceptions
967 * raised by a tvbuff access method doesn't leave junk in the proto_tree. */
968 pi = proto_tree_add_node(tree, new_fi);
970 /* we did not raise an exception so we dont have to remember this
971 * field_info struct any more.
975 /* If the proto_tree wants to keep a record of this finfo
976 * for quick lookup, then record it. */
977 if (new_fi->hfinfo->ref_count) {
978 hash = PTREE_DATA(tree)->interesting_hfids;
979 ptrs = g_hash_table_lookup(hash, GINT_TO_POINTER(hfindex));
981 g_ptr_array_add(ptrs, new_fi);
989 proto_tree_add_item_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb,
990 gint start, gint length, gboolean little_endian)
994 pi = proto_tree_add_item(tree, hfindex, tvb, start, length, little_endian);
998 PROTO_ITEM_SET_HIDDEN(pi);
1004 /* Add a FT_NONE to a proto_tree */
1006 proto_tree_add_none_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1007 gint length, const char *format, ...)
1011 header_field_info *hfinfo;
1016 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1017 DISSECTOR_ASSERT(hfinfo->type == FT_NONE);
1019 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, NULL);
1021 va_start(ap, format);
1022 proto_tree_set_representation(pi, format, ap);
1025 /* no value to set for FT_NONE */
1031 proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb)
1033 fvalue_set(&fi->value, tvb, TRUE);
1036 /* Add a FT_PROTOCOL to a proto_tree */
1038 proto_tree_add_protocol_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1039 gint length, const char *format, ...)
1043 header_field_info *hfinfo;
1049 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1050 DISSECTOR_ASSERT(hfinfo->type == FT_PROTOCOL);
1052 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1054 va_start(ap, format);
1055 proto_tree_set_representation(pi, format, ap);
1059 proto_tree_set_protocol_tvb(new_fi, tvb);
1062 proto_tree_set_protocol_tvb(new_fi, NULL);
1068 /* Add a FT_BYTES to a proto_tree */
1070 proto_tree_add_bytes(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1071 gint length, const guint8 *start_ptr)
1075 header_field_info *hfinfo;
1080 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1082 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1083 DISSECTOR_ASSERT(hfinfo->type == FT_BYTES);
1085 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1086 proto_tree_set_bytes(new_fi, start_ptr, length);
1092 proto_tree_add_bytes_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1093 gint length, const guint8 *start_ptr)
1097 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length, start_ptr);
1101 PROTO_ITEM_SET_HIDDEN(pi);
1107 proto_tree_add_bytes_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1108 gint length, const guint8 *start_ptr, const char *format, ...)
1113 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length, start_ptr);
1117 va_start(ap, format);
1118 proto_tree_set_representation(pi, format, ap);
1125 proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length)
1129 bytes = g_byte_array_new();
1131 g_byte_array_append(bytes, start_ptr, length);
1133 fvalue_set(&fi->value, bytes, TRUE);
1138 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length)
1140 proto_tree_set_bytes(fi, tvb_get_ptr(tvb, offset, length), length);
1143 /* Add a FT_*TIME to a proto_tree */
1145 proto_tree_add_time(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1146 nstime_t *value_ptr)
1150 header_field_info *hfinfo;
1155 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1157 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1158 DISSECTOR_ASSERT(hfinfo->type == FT_ABSOLUTE_TIME ||
1159 hfinfo->type == FT_RELATIVE_TIME);
1161 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1162 proto_tree_set_time(new_fi, value_ptr);
1168 proto_tree_add_time_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1169 nstime_t *value_ptr)
1173 pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
1177 PROTO_ITEM_SET_HIDDEN(pi);
1183 proto_tree_add_time_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1184 nstime_t *value_ptr, const char *format, ...)
1189 pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
1193 va_start(ap, format);
1194 proto_tree_set_representation(pi, format, ap);
1200 /* Set the FT_*TIME value */
1202 proto_tree_set_time(field_info *fi, nstime_t *value_ptr)
1204 fvalue_set(&fi->value, value_ptr, FALSE);
1207 /* Add a FT_IPXNET to a proto_tree */
1209 proto_tree_add_ipxnet(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1214 header_field_info *hfinfo;
1219 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1221 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1222 DISSECTOR_ASSERT(hfinfo->type == FT_IPXNET);
1224 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1225 proto_tree_set_ipxnet(new_fi, value);
1231 proto_tree_add_ipxnet_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1236 pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
1240 PROTO_ITEM_SET_HIDDEN(pi);
1246 proto_tree_add_ipxnet_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1247 guint32 value, const char *format, ...)
1252 pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
1256 va_start(ap, format);
1257 proto_tree_set_representation(pi, format, ap);
1263 /* Set the FT_IPXNET value */
1265 proto_tree_set_ipxnet(field_info *fi, guint32 value)
1267 fvalue_set_integer(&fi->value, value);
1270 /* Add a FT_IPv4 to a proto_tree */
1272 proto_tree_add_ipv4(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1277 header_field_info *hfinfo;
1282 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1284 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1285 DISSECTOR_ASSERT(hfinfo->type == FT_IPv4);
1287 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1288 proto_tree_set_ipv4(new_fi, value);
1294 proto_tree_add_ipv4_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1299 pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
1303 PROTO_ITEM_SET_HIDDEN(pi);
1309 proto_tree_add_ipv4_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1310 guint32 value, const char *format, ...)
1315 pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
1319 va_start(ap, format);
1320 proto_tree_set_representation(pi, format, ap);
1326 /* Set the FT_IPv4 value */
1328 proto_tree_set_ipv4(field_info *fi, guint32 value)
1330 fvalue_set_integer(&fi->value, value);
1333 /* Add a FT_IPv6 to a proto_tree */
1335 proto_tree_add_ipv6(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1336 const guint8* value_ptr)
1340 header_field_info *hfinfo;
1345 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1347 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1348 DISSECTOR_ASSERT(hfinfo->type == FT_IPv6);
1350 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1351 proto_tree_set_ipv6(new_fi, value_ptr);
1357 proto_tree_add_ipv6_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1358 const guint8* value_ptr)
1362 pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
1366 PROTO_ITEM_SET_HIDDEN(pi);
1372 proto_tree_add_ipv6_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1373 const guint8* value_ptr, const char *format, ...)
1378 pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
1382 va_start(ap, format);
1383 proto_tree_set_representation(pi, format, ap);
1389 /* Set the FT_IPv6 value */
1391 proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr)
1393 fvalue_set(&fi->value, (gpointer) value_ptr, FALSE);
1397 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start)
1399 proto_tree_set_ipv6(fi, tvb_get_ptr(tvb, start, 16));
1402 /* Add a FT_GUID to a proto_tree */
1404 proto_tree_add_guid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1405 const guint8* value_ptr)
1409 header_field_info *hfinfo;
1414 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1416 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1417 DISSECTOR_ASSERT(hfinfo->type == FT_GUID);
1419 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1420 proto_tree_set_guid(new_fi, value_ptr);
1426 proto_tree_add_guid_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1427 const guint8* value_ptr)
1431 pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
1435 PROTO_ITEM_SET_HIDDEN(pi);
1441 proto_tree_add_guid_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1442 const guint8* value_ptr, const char *format, ...)
1447 pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
1451 va_start(ap, format);
1452 proto_tree_set_representation(pi, format, ap);
1458 /* Set the FT_GUID value */
1460 proto_tree_set_guid(field_info *fi, const guint8* value_ptr)
1462 fvalue_set(&fi->value, (gpointer) value_ptr, FALSE);
1466 proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, gint start)
1468 proto_tree_set_guid(fi, tvb_get_ptr(tvb, start, 16));
1472 proto_tree_set_uint64(field_info *fi, guint64 value)
1474 fvalue_set_integer64(&fi->value, value);
1478 proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start, gboolean little_endian)
1482 value = little_endian ? tvb_get_letoh64(tvb, start)
1483 : tvb_get_ntoh64(tvb, start);
1485 proto_tree_set_uint64(fi, value);
1488 /* Add a FT_STRING or FT_STRINGZ to a proto_tree. Creates own copy of string,
1489 * and frees it when the proto_tree is destroyed. */
1491 proto_tree_add_string(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1492 gint length, const char* value)
1496 header_field_info *hfinfo;
1501 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1503 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1504 DISSECTOR_ASSERT(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ);
1506 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1507 DISSECTOR_ASSERT(length >= 0);
1508 proto_tree_set_string(new_fi, value, FALSE);
1514 proto_tree_add_string_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1515 gint length, const char* value)
1519 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
1523 PROTO_ITEM_SET_HIDDEN(pi);
1529 proto_tree_add_string_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1530 gint length, const char* value, const char *format, ...)
1535 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
1539 va_start(ap, format);
1540 proto_tree_set_representation(pi, format, ap);
1546 /* Appends string data to a FT_STRING or FT_STRINGZ, allowing progressive
1547 * field info update instead of only updating the representation as does
1548 * proto_item_append_text()
1550 /* NOTE: this function will break with the TRY_TO_FAKE_THIS_ITEM()
1551 * speed optimization.
1552 * Currently only WSP use this function so it is not that bad but try to
1553 * avoid using this one if possible.
1554 * IF you must use this function you MUST also disable the
1555 * TRY_TO_FAKE_THIS_ITEM() optimization for your dissector/function
1556 * using proto_item_append_string().
1557 * Do that by faking that the tree is visible by setting :
1558 * PTREE_DATA(tree)->visible=1; (see packet-wsp.c)
1559 * BEFORE you create the item you are later going to use
1560 * proto_item_append_string() on.
1563 proto_item_append_string(proto_item *pi, const char *str)
1566 header_field_info *hfinfo;
1567 gchar *old_str, *new_str;
1574 fi = PITEM_FINFO(pi);
1575 hfinfo = fi->hfinfo;
1576 DISSECTOR_ASSERT(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ);
1577 old_str = fvalue_get(&fi->value);
1578 new_str = g_malloc(strlen(old_str) + strlen(str) + 1);
1579 sprintf(new_str, "%s%s", old_str, str);
1580 fvalue_set(&fi->value, new_str, TRUE);
1583 /* Set the FT_STRING value */
1585 proto_tree_set_string(field_info *fi, const char* value,
1586 gboolean already_allocated)
1589 fvalue_set(&fi->value, (gpointer) value, already_allocated);
1591 fvalue_set(&fi->value, (gpointer) "[ Null ]", already_allocated);
1595 proto_tree_set_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
1600 length = tvb_ensure_length_remaining(tvb, start);
1603 /* This memory is freed in proto_tree_free_node() */
1604 string = tvb_get_string(tvb, start, length);
1605 proto_tree_set_string(fi, string, TRUE);
1608 /* Add a FT_ETHER to a proto_tree */
1610 proto_tree_add_ether(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1611 const guint8* value)
1615 header_field_info *hfinfo;
1620 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1622 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1623 DISSECTOR_ASSERT(hfinfo->type == FT_ETHER);
1625 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1626 proto_tree_set_ether(new_fi, value);
1632 proto_tree_add_ether_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1633 const guint8* value)
1637 pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
1641 PROTO_ITEM_SET_HIDDEN(pi);
1647 proto_tree_add_ether_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1648 const guint8* value, const char *format, ...)
1653 pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
1657 va_start(ap, format);
1658 proto_tree_set_representation(pi, format, ap);
1664 /* Set the FT_ETHER value */
1666 proto_tree_set_ether(field_info *fi, const guint8* value)
1668 fvalue_set(&fi->value, (gpointer) value, FALSE);
1672 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start)
1674 proto_tree_set_ether(fi, tvb_get_ptr(tvb, start, 6));
1677 /* Add a FT_BOOLEAN to a proto_tree */
1679 proto_tree_add_boolean(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1684 header_field_info *hfinfo;
1689 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1691 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1692 DISSECTOR_ASSERT(hfinfo->type == FT_BOOLEAN);
1694 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1695 proto_tree_set_boolean(new_fi, value);
1701 proto_tree_add_boolean_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1706 pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
1710 PROTO_ITEM_SET_HIDDEN(pi);
1716 proto_tree_add_boolean_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1717 guint32 value, const char *format, ...)
1722 pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
1726 va_start(ap, format);
1727 proto_tree_set_representation(pi, format, ap);
1733 /* Set the FT_BOOLEAN value */
1735 proto_tree_set_boolean(field_info *fi, guint32 value)
1737 proto_tree_set_uint(fi, value);
1740 /* Add a FT_FLOAT to a proto_tree */
1742 proto_tree_add_float(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1747 header_field_info *hfinfo;
1752 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1754 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1755 DISSECTOR_ASSERT(hfinfo->type == FT_FLOAT);
1757 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1758 proto_tree_set_float(new_fi, value);
1764 proto_tree_add_float_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1769 pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
1773 PROTO_ITEM_SET_HIDDEN(pi);
1779 proto_tree_add_float_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1780 float value, const char *format, ...)
1785 pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
1789 va_start(ap, format);
1790 proto_tree_set_representation(pi, format, ap);
1796 /* Set the FT_FLOAT value */
1798 proto_tree_set_float(field_info *fi, float value)
1800 fvalue_set_floating(&fi->value, value);
1803 /* Add a FT_DOUBLE to a proto_tree */
1805 proto_tree_add_double(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1810 header_field_info *hfinfo;
1815 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1817 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1818 DISSECTOR_ASSERT(hfinfo->type == FT_DOUBLE);
1820 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1821 proto_tree_set_double(new_fi, value);
1827 proto_tree_add_double_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1832 pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
1836 PROTO_ITEM_SET_HIDDEN(pi);
1842 proto_tree_add_double_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1843 double value, const char *format, ...)
1848 pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
1852 va_start(ap, format);
1853 proto_tree_set_representation(pi, format, ap);
1859 /* Set the FT_DOUBLE value */
1861 proto_tree_set_double(field_info *fi, double value)
1863 fvalue_set_floating(&fi->value, value);
1866 /* Add FT_UINT{8,16,24,32} to a proto_tree */
1868 proto_tree_add_uint(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1871 proto_item *pi = NULL;
1873 header_field_info *hfinfo;
1878 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1880 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1881 switch(hfinfo->type) {
1887 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length,
1889 proto_tree_set_uint(new_fi, value);
1893 DISSECTOR_ASSERT_NOT_REACHED();
1900 proto_tree_add_uint_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1905 pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
1909 PROTO_ITEM_SET_HIDDEN(pi);
1915 proto_tree_add_uint_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1916 guint32 value, const char *format, ...)
1921 pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
1925 va_start(ap, format);
1926 proto_tree_set_representation(pi, format, ap);
1932 /* Set the FT_UINT{8,16,24,32} value */
1934 proto_tree_set_uint(field_info *fi, guint32 value)
1936 header_field_info *hfinfo;
1939 hfinfo = fi->hfinfo;
1942 if (hfinfo->bitmask) {
1943 /* Mask out irrelevant portions */
1944 integer &= hfinfo->bitmask;
1947 if (hfinfo->bitshift > 0) {
1948 integer >>= hfinfo->bitshift;
1951 fvalue_set_integer(&fi->value, integer);
1954 /* Add FT_UINT64 to a proto_tree */
1956 proto_tree_add_uint64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1959 proto_item *pi = NULL;
1961 header_field_info *hfinfo;
1966 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1968 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1969 DISSECTOR_ASSERT(hfinfo->type == FT_UINT64);
1971 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1972 proto_tree_set_uint64(new_fi, value);
1978 proto_tree_add_uint64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1979 guint64 value, const char *format, ...)
1984 pi = proto_tree_add_uint64(tree, hfindex, tvb, start, length, value);
1988 va_start(ap, format);
1989 proto_tree_set_representation(pi, format, ap);
1995 /* Add FT_INT{8,16,24,32} to a proto_tree */
1997 proto_tree_add_int(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2000 proto_item *pi = NULL;
2002 header_field_info *hfinfo;
2007 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
2009 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2010 switch(hfinfo->type) {
2015 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length,
2017 proto_tree_set_int(new_fi, value);
2021 DISSECTOR_ASSERT_NOT_REACHED();
2028 proto_tree_add_int_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2033 pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
2037 PROTO_ITEM_SET_HIDDEN(pi);
2043 proto_tree_add_int_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2044 gint32 value, const char *format, ...)
2046 proto_item *pi = NULL;
2049 pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
2053 va_start(ap, format);
2054 proto_tree_set_representation(pi, format, ap);
2060 /* Set the FT_INT{8,16,24,32} value */
2062 proto_tree_set_int(field_info *fi, gint32 value)
2064 header_field_info *hfinfo;
2067 hfinfo = fi->hfinfo;
2068 integer = (guint32) value;
2070 if (hfinfo->bitmask) {
2071 /* Mask out irrelevant portions */
2072 integer &= hfinfo->bitmask;
2075 if (hfinfo->bitshift > 0) {
2076 integer >>= hfinfo->bitshift;
2079 fvalue_set_integer(&fi->value, integer);
2082 /* Add FT_INT64 to a proto_tree */
2084 proto_tree_add_int64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2087 proto_item *pi = NULL;
2089 header_field_info *hfinfo;
2094 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
2096 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2097 DISSECTOR_ASSERT(hfinfo->type == FT_INT64);
2099 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2100 proto_tree_set_uint64(new_fi, (guint64)value);
2106 proto_tree_add_int64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2107 gint64 value, const char *format, ...)
2112 pi = proto_tree_add_int64(tree, hfindex, tvb, start, length, value);
2116 va_start(ap, format);
2117 proto_tree_set_representation(pi, format, ap);
2124 /* Add a field_info struct to the proto_tree, encapsulating it in a proto_node */
2126 proto_tree_add_node(proto_tree *tree, field_info *fi)
2128 proto_node *pnode, *tnode, *sibling;
2132 * Make sure "tree" is ready to have subtrees under it, by
2133 * checking whether it's been given an ett_ value.
2135 * "tnode->finfo" may be null; that's the case for the root
2136 * node of the protocol tree. That node is not displayed,
2137 * so it doesn't need an ett_ value to remember whether it
2142 if (tfi != NULL && (tfi->tree_type < 0 || tfi->tree_type >= num_tree_types)) {
2143 REPORT_DISSECTOR_BUG(g_strdup_printf("\"%s\" - \"%s\" tfi->tree_type: %u invalid (%s:%u)",
2144 fi->hfinfo->name, fi->hfinfo->abbrev, tfi->tree_type, __FILE__, __LINE__));
2145 /* XXX - is it safe to continue here? */
2148 DISSECTOR_ASSERT(tfi == NULL ||
2149 (tfi->tree_type >= 0 && tfi->tree_type < num_tree_types));
2151 PROTO_NODE_NEW(pnode);
2152 pnode->parent = tnode;
2154 pnode->tree_data = PTREE_DATA(tree);
2156 if (tnode->last_child != NULL) {
2157 sibling = tnode->last_child;
2158 DISSECTOR_ASSERT(sibling->next == NULL);
2159 sibling->next = pnode;
2161 tnode->first_child = pnode;
2162 tnode->last_child = pnode;
2164 return (proto_item*)pnode;
2168 /* Generic way to allocate field_info and add to proto_tree.
2169 * Sets *pfi to address of newly-allocated field_info struct, if pfi is
2172 proto_tree_add_pi(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2173 gint *length, field_info **pfi)
2183 fi = alloc_field_info(tree, hfindex, tvb, start, length);
2184 pi = proto_tree_add_node(tree, fi);
2186 /* If the proto_tree wants to keep a record of this finfo
2187 * for quick lookup, then record it. */
2188 if (fi->hfinfo->ref_count) {
2189 hash = PTREE_DATA(tree)->interesting_hfids;
2190 ptrs = g_hash_table_lookup(hash, GINT_TO_POINTER(hfindex));
2192 g_ptr_array_add(ptrs, fi);
2196 /* Does the caller want to know the fi pointer? */
2205 alloc_field_info(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2208 header_field_info *hfinfo;
2211 gint length_remaining;
2214 * We only allow a null tvbuff if the item has a zero length,
2215 * i.e. if there's no data backing it.
2217 DISSECTOR_ASSERT(tvb != NULL || *length == 0);
2219 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2222 * XXX - in some protocols, there are 32-bit unsigned length
2223 * fields, so lengths in protocol tree and tvbuff routines
2224 * should really be unsigned. We should have, for those
2225 * field types for which "to the end of the tvbuff" makes sense,
2226 * additional routines that take no length argument and
2227 * add fields that run to the end of the tvbuff.
2229 if (*length == -1) {
2231 * For FT_NONE, FT_PROTOCOL, FT_BYTES, and FT_STRING fields,
2232 * a length of -1 means "set the length to what remains in
2235 * The assumption is either that
2237 * 1) the length of the item can only be determined
2238 * by dissection (typically true of items with
2239 * subitems, which are probably FT_NONE or
2244 * 2) if the tvbuff is "short" (either due to a short
2245 * snapshot length or due to lack of reassembly of
2246 * fragments/segments/whatever), we want to display
2247 * what's available in the field (probably FT_BYTES
2248 * or FT_STRING) and then throw an exception later
2252 * 3) the field is defined to be "what's left in the
2255 * so we set the length to what remains in the tvbuff so
2256 * that, if we throw an exception while dissecting, it
2257 * has what is probably the right value.
2259 * For FT_STRINGZ, it means "the string is null-terminated,
2260 * not null-padded; set the length to the actual length
2261 * of the string", and if the tvbuff if short, we just
2262 * throw an exception.
2264 * It's not valid for any other type of field.
2266 switch (hfinfo->type) {
2270 * We allow this to be zero-length - for
2271 * example, an ONC RPC NULL procedure has
2272 * neither arguments nor reply, so the
2273 * payload for that protocol is empty.
2275 * However, if the length is negative, the
2276 * start offset is *past* the byte past the
2277 * end of the tvbuff, so we throw an
2280 *length = tvb_length_remaining(tvb, start);
2283 * Use "tvb_ensure_bytes_exist()"
2284 * to force the appropriate exception
2287 tvb_ensure_bytes_exist(tvb, start, 0);
2289 DISSECTOR_ASSERT(*length >= 0);
2295 *length = tvb_ensure_length_remaining(tvb, start);
2296 DISSECTOR_ASSERT(*length >= 0);
2301 * Leave the length as -1, so our caller knows
2307 DISSECTOR_ASSERT_NOT_REACHED();
2309 item_length = *length;
2311 item_length = *length;
2312 if (hfinfo->type == FT_PROTOCOL || hfinfo->type == FT_NONE) {
2314 * These types are for interior nodes of the
2315 * tree, and don't have data associated with
2316 * them; if the length is negative (XXX - see
2317 * above) or goes past the end of the tvbuff,
2318 * cut it short at the end of the tvbuff.
2319 * That way, if this field is selected in
2320 * Ethereal, we don't highlight stuff past
2321 * the end of the data.
2323 /* XXX - what to do, if we don't have a tvb? */
2325 length_remaining = tvb_length_remaining(tvb, start);
2326 if (item_length < 0 || (item_length > 0 && (length_remaining < item_length)))
2327 item_length = length_remaining;
2330 if (item_length < 0) {
2331 THROW(ReportedBoundsError);
2337 fi->hfinfo = hfinfo;
2339 fi->start+=(tvb)?TVB_RAW_OFFSET(tvb):0;
2340 fi->length = item_length;
2343 if (!PTREE_DATA(tree)->visible)
2344 FI_SET_FLAG(fi, FI_HIDDEN);
2345 fvalue_init(&fi->value, fi->hfinfo->type);
2348 /* add the data source tvbuff */
2349 fi->ds_tvb=tvb?TVB_GET_DS_TVB(tvb):NULL;
2354 /* Set representation of a proto_tree entry, if the protocol tree is to
2357 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap)
2359 int ret; /*tmp return value */
2360 field_info *fi = PITEM_FINFO(pi);
2362 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
2363 ITEM_LABEL_NEW(fi->rep);
2364 ret = vsnprintf(fi->rep->representation, ITEM_LABEL_LENGTH, format, ap);
2365 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
2366 fi->rep->representation[ITEM_LABEL_LENGTH - 1] = '\0';
2370 /* Set text of proto_item after having already been created. */
2372 proto_item_set_text(proto_item *pi, const char *format, ...)
2374 field_info *fi = NULL;
2381 fi = PITEM_FINFO(pi);
2384 ITEM_LABEL_FREE(fi->rep);
2387 va_start(ap, format);
2388 proto_tree_set_representation(pi, format, ap);
2392 /* Append to text of proto_item after having already been created. */
2394 proto_item_append_text(proto_item *pi, const char *format, ...)
2396 field_info *fi = NULL;
2399 int ret; /*tmp return value */
2405 fi = PITEM_FINFO(pi);
2407 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
2408 va_start(ap, format);
2411 * If we don't already have a representation,
2412 * generate the default representation.
2414 if (fi->rep == NULL) {
2415 ITEM_LABEL_NEW(fi->rep);
2416 proto_item_fill_label(fi, fi->rep->representation);
2419 curlen = strlen(fi->rep->representation);
2420 if (ITEM_LABEL_LENGTH > curlen) {
2421 ret = vsnprintf(fi->rep->representation + curlen,
2422 ITEM_LABEL_LENGTH - curlen, format, ap);
2423 if ((ret == -1) || (ret >= (int)(ITEM_LABEL_LENGTH - curlen)))
2424 fi->rep->representation[ITEM_LABEL_LENGTH - 1] = '\0';
2431 proto_item_set_len(proto_item *pi, gint length)
2437 fi = PITEM_FINFO(pi);
2438 DISSECTOR_ASSERT(length >= 0);
2439 fi->length = length;
2443 * Sets the length of the item based on its start and on the specified
2444 * offset, which is the offset past the end of the item; as the start
2445 * in the item is relative to the beginning of the data source tvbuff,
2446 * we need to pass in a tvbuff - the end offset is relative to the beginning
2450 proto_item_set_end(proto_item *pi, tvbuff_t *tvb, gint end)
2456 fi = PITEM_FINFO(pi);
2457 end += TVB_RAW_OFFSET(tvb);
2458 DISSECTOR_ASSERT(end >= fi->start);
2459 fi->length = end - fi->start;
2463 proto_item_get_len(proto_item *pi)
2465 field_info *fi = PITEM_FINFO(pi);
2470 proto_tree_create_root(void)
2474 /* Initialize the proto_node */
2475 PROTO_NODE_NEW(pnode);
2476 pnode->parent = NULL;
2477 pnode->finfo = NULL;
2478 pnode->tree_data = g_new(tree_data_t, 1);
2480 /* Initialize the tree_data_t */
2481 pnode->tree_data->interesting_hfids =
2482 g_hash_table_new(g_direct_hash, g_direct_equal);
2484 /* Set the default to FALSE so it's easier to
2485 * find errors; if we expect to see the protocol tree
2486 * but for some reason the default 'visible' is not
2487 * changed, then we'll find out very quickly. */
2488 pnode->tree_data->visible = FALSE;
2490 return (proto_tree*) pnode;
2494 /* "prime" a proto_tree with a single hfid that a dfilter
2495 * is interested in. */
2497 proto_tree_prime_hfid(proto_tree *tree, gint hfid)
2499 header_field_info *hfinfo;
2501 g_hash_table_insert(PTREE_DATA(tree)->interesting_hfids,
2502 GINT_TO_POINTER(hfid), g_ptr_array_new());
2504 PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
2505 /* this field is referenced by a filter so increase the refcount.
2506 also increase the refcount for the parent, i.e the protocol.
2508 hfinfo->ref_count++;
2509 /* only increase the refcount if there is a parent.
2510 if this is a protocol and not a field then parent will be -1
2511 and there is no parent to add any refcounting for.
2513 if (hfinfo->parent != -1) {
2514 header_field_info *parent_hfinfo;
2515 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
2516 parent_hfinfo->ref_count++;
2521 proto_item_add_subtree(proto_item *pi, gint idx) {
2527 fi = PITEM_FINFO(pi);
2528 DISSECTOR_ASSERT(idx >= 0 && idx < num_tree_types);
2529 fi->tree_type = idx;
2531 return (proto_tree*) pi;
2535 proto_item_get_subtree(proto_item *pi) {
2540 fi = PITEM_FINFO(pi);
2541 if ( (!fi) || (fi->tree_type == -1) )
2543 return (proto_tree*) pi;
2547 proto_item_get_parent(proto_item *ti) {
2548 /* dont bother if tree is not visible */
2549 if( (!ti) || (!(PTREE_DATA(ti)->visible)) )
2555 proto_item_get_parent_nth(proto_item *ti, int gen) {
2556 /* dont bother if tree is not visible */
2557 if( (!ti) || (!(PTREE_DATA(ti)->visible)) )
2569 proto_tree_get_parent(proto_tree *tree) {
2570 /* dont bother if tree is not visible */
2571 if( (!tree) || (!(PTREE_DATA(tree)->visible)) )
2573 return (proto_item*) tree;
2578 proto_tree_move_item(proto_tree *tree, proto_item *fixed_item, proto_item *item_to_move)
2580 proto_item *curr_item;
2583 /*** cut item_to_move out ***/
2585 /* is item_to_move the first? */
2586 if(tree->first_child == item_to_move) {
2587 /* simply change first child to next */
2588 tree->first_child = item_to_move->next;
2590 /* find previous and change it's next */
2591 for(curr_item = tree->first_child; curr_item != NULL; curr_item = curr_item->next) {
2592 if(curr_item->next == item_to_move) {
2597 DISSECTOR_ASSERT(curr_item);
2599 curr_item->next = item_to_move->next;
2601 /* fix last_child if required */
2602 if(tree->last_child == item_to_move) {
2603 tree->last_child = curr_item;
2607 /*** insert to_move after fixed ***/
2608 item_to_move->next = fixed_item->next;
2609 fixed_item->next = item_to_move;
2610 if(tree->last_child == fixed_item) {
2611 tree->last_child = item_to_move;
2617 proto_register_protocol(const char *name, const char *short_name, const char *filter_name)
2619 protocol_t *protocol;
2620 header_field_info *hfinfo;
2622 char *existing_name;
2625 gboolean found_invalid;
2628 * Make sure there's not already a protocol with any of those
2629 * names. Crash if there is, as that's an error in the code
2630 * or an inappropriate plugin.
2631 * This situation has to be fixed to not register more than one
2632 * protocol with the same name.
2634 * This is done by reducing the number of strcmp (and alike) calls as much as possible,
2635 * as this significally slows down startup time.
2637 * Drawback: As a hash value is used to reduce insert time,
2638 * this might lead to a hash collision.
2639 * However, as we have around 500+ protocols and we're using a 32 bit int this is very,
2643 key = g_malloc (sizeof(gint));
2644 *key = g_str_hash(name);
2645 existing_name = g_hash_table_lookup(proto_names, key);
2646 if (existing_name != NULL) {
2647 /* g_error will terminate the program */
2648 g_error("Duplicate protocol name \"%s\"!"
2649 " This might be caused by an inappropriate plugin or a development error.", name);
2651 g_hash_table_insert(proto_names, key, (gpointer)name);
2653 key = g_malloc (sizeof(gint));
2654 *key = g_str_hash(short_name);
2655 existing_name = g_hash_table_lookup(proto_short_names, key);
2656 if (existing_name != NULL) {
2657 g_error("Duplicate protocol short_name \"%s\"!"
2658 " This might be caused by an inappropriate plugin or a development error.", short_name);
2660 g_hash_table_insert(proto_short_names, key, (gpointer)short_name);
2662 found_invalid = FALSE;
2663 for (i = 0; i < strlen(filter_name); i++) {
2664 if (! (islower(filter_name[i]) ||
2665 isdigit(filter_name[i]) ||
2666 filter_name[i] == '-' ||
2667 filter_name[i] == '_' ||
2668 filter_name[i] == '.' )) {
2669 found_invalid = TRUE;
2672 if (found_invalid) {
2673 g_warning("Protocol filter name \"%s\" has one or more invalid characters.", filter_name);
2675 key = g_malloc (sizeof(gint));
2676 *key = g_str_hash(filter_name);
2677 existing_name = g_hash_table_lookup(proto_filter_names, key);
2678 if (existing_name != NULL) {
2679 g_error("Duplicate protocol filter_name \"%s\"!"
2680 " This might be caused by an inappropriate plugin or a development error.", filter_name);
2682 g_hash_table_insert(proto_filter_names, key, (gpointer)filter_name);
2684 /* Add this protocol to the list of known protocols; the list
2685 is sorted by protocol short name. */
2686 protocol = g_malloc(sizeof (protocol_t));
2687 protocol->name = name;
2688 protocol->short_name = short_name;
2689 protocol->filter_name = filter_name;
2690 protocol->fields = NULL;
2691 protocol->is_enabled = TRUE; /* protocol is enabled by default */
2692 protocol->can_toggle = TRUE;
2693 /* list will be sorted later by name, when all protocols completed registering */
2694 protocols = g_list_append(protocols, protocol);
2696 /* Here we do allocate a new header_field_info struct */
2697 hfinfo = g_mem_chunk_alloc(gmc_hfinfo);
2698 hfinfo->name = name;
2699 hfinfo->abbrev = filter_name;
2700 hfinfo->type = FT_PROTOCOL;
2701 hfinfo->strings = protocol;
2702 hfinfo->bitmask = 0;
2703 hfinfo->bitshift = 0;
2704 hfinfo->ref_count = 0;
2706 hfinfo->parent = -1; /* this field differentiates protos and fields */
2708 proto_id = proto_register_field_init(hfinfo, hfinfo->parent);
2709 protocol->proto_id = proto_id;
2714 * Routines to use to iterate over the protocols.
2715 * The argument passed to the iterator routines is an opaque cookie to
2716 * their callers; it's the GList pointer for the current element in
2718 * The ID of the protocol is returned, or -1 if there is no protocol.
2721 proto_get_first_protocol(void **cookie)
2723 protocol_t *protocol;
2725 if (protocols == NULL)
2727 *cookie = protocols;
2728 protocol = protocols->data;
2729 return protocol->proto_id;
2733 proto_get_next_protocol(void **cookie)
2735 GList *list_item = *cookie;
2736 protocol_t *protocol;
2738 list_item = g_list_next(list_item);
2739 if (list_item == NULL)
2741 *cookie = list_item;
2742 protocol = list_item->data;
2743 return protocol->proto_id;
2747 proto_get_first_protocol_field(int proto_id, void **cookie)
2749 protocol_t *protocol = find_protocol_by_id(proto_id);
2750 hf_register_info *ptr;
2752 if ((protocol == NULL) || (protocol->fields == NULL))
2755 *cookie = protocol->fields;
2756 ptr = protocol->fields->data;
2757 return &ptr->hfinfo;
2761 proto_get_next_protocol_field(void **cookie)
2763 GList *list_item = *cookie;
2764 hf_register_info *ptr;
2766 list_item = g_list_next(list_item);
2767 if (list_item == NULL)
2770 *cookie = list_item;
2771 ptr = list_item->data;
2772 return &ptr->hfinfo;
2776 find_protocol_by_id(int proto_id)
2778 header_field_info *hfinfo;
2783 PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
2784 DISSECTOR_ASSERT(hfinfo->type==FT_PROTOCOL);
2785 return (protocol_t *)hfinfo->strings;
2788 static gint compare_filter_name(gconstpointer proto_arg,
2789 gconstpointer filter_name)
2791 const protocol_t *protocol = proto_arg;
2792 const gchar* f_name = filter_name;
2794 return (strcmp(protocol->filter_name, f_name));
2798 proto_get_id(protocol_t *protocol)
2800 return protocol->proto_id;
2803 int proto_get_id_by_filter_name(const gchar* filter_name)
2806 protocol_t *protocol;
2808 list_entry = g_list_find_custom(protocols, filter_name,
2809 compare_filter_name);
2810 if (list_entry == NULL)
2812 protocol = list_entry->data;
2813 return protocol->proto_id;
2817 proto_get_protocol_name(int proto_id)
2819 protocol_t *protocol;
2821 protocol = find_protocol_by_id(proto_id);
2822 return protocol->name;
2826 proto_get_protocol_short_name(protocol_t *protocol)
2828 if (protocol == NULL)
2830 return protocol->short_name;
2834 proto_get_protocol_filter_name(int proto_id)
2836 protocol_t *protocol;
2838 protocol = find_protocol_by_id(proto_id);
2839 return protocol->filter_name;
2843 proto_is_protocol_enabled(protocol_t *protocol)
2845 return protocol->is_enabled;
2849 proto_can_toggle_protocol(int proto_id)
2851 protocol_t *protocol;
2853 protocol = find_protocol_by_id(proto_id);
2854 return protocol->can_toggle;
2858 proto_set_decoding(int proto_id, gboolean enabled)
2860 protocol_t *protocol;
2862 protocol = find_protocol_by_id(proto_id);
2863 DISSECTOR_ASSERT(protocol->can_toggle);
2864 protocol->is_enabled = enabled;
2868 proto_set_cant_toggle(int proto_id)
2870 protocol_t *protocol;
2872 protocol = find_protocol_by_id(proto_id);
2873 protocol->can_toggle = FALSE;
2876 /* for use with static arrays only, since we don't allocate our own copies
2877 of the header_field_info struct contained within the hf_register_info struct */
2879 proto_register_field_array(int parent, hf_register_info *hf, int num_records)
2882 hf_register_info *ptr = hf;
2885 proto = find_protocol_by_id(parent);
2886 for (i = 0; i < num_records; i++, ptr++) {
2888 * Make sure we haven't registered this yet.
2889 * Most fields have variables associated with them
2890 * that are initialized to -1; some have array elements,
2891 * or possibly uninitialized variables, so we also allow
2892 * 0 (which is unlikely to be the field ID we get back
2893 * from "proto_register_field_init()").
2895 DISSECTOR_ASSERT(*ptr->p_id == -1 || *ptr->p_id == 0);
2897 if (proto != NULL) {
2898 if (proto->fields == NULL) {
2899 proto->fields = g_list_append(NULL, ptr);
2900 proto->last_field = proto->fields;
2903 g_list_append(proto->last_field, ptr)->next;
2906 field_id = proto_register_field_init(&ptr->hfinfo, parent);
2907 *ptr->p_id = field_id;
2912 proto_register_field_init(header_field_info *hfinfo, int parent)
2914 /* The field must have names */
2915 DISSECTOR_ASSERT(hfinfo->name);
2916 DISSECTOR_ASSERT(hfinfo->abbrev);
2918 /* These types of fields are allowed to have value_strings, true_false_strings or a protocol_t struct*/
2919 DISSECTOR_ASSERT((hfinfo->strings == NULL) || (
2920 (hfinfo->type == FT_UINT8) ||
2921 (hfinfo->type == FT_UINT16) ||
2922 (hfinfo->type == FT_UINT24) ||
2923 (hfinfo->type == FT_UINT32) ||
2924 (hfinfo->type == FT_INT8) ||
2925 (hfinfo->type == FT_INT16) ||
2926 (hfinfo->type == FT_INT24) ||
2927 (hfinfo->type == FT_INT32) ||
2928 (hfinfo->type == FT_BOOLEAN) ||
2929 (hfinfo->type == FT_PROTOCOL) ||
2930 (hfinfo->type == FT_FRAMENUM) ));
2932 switch (hfinfo->type) {
2942 /* Require integral types (other than frame number, which is
2943 always displayed in decimal) to have a number base */
2944 DISSECTOR_ASSERT(hfinfo->display != BASE_NONE);
2948 /* Don't allow bitfields or value strings for frame numbers */
2949 DISSECTOR_ASSERT(hfinfo->bitmask == 0);
2950 DISSECTOR_ASSERT(hfinfo->strings == NULL);
2956 /* if this is a bitfield, compute bitshift */
2957 if (hfinfo->bitmask) {
2958 while ((hfinfo->bitmask & (1 << hfinfo->bitshift)) == 0)
2962 hfinfo->parent = parent;
2963 hfinfo->same_name_next = NULL;
2964 hfinfo->same_name_prev = NULL;
2966 /* if we always add and never delete, then id == len - 1 is correct */
2967 if(gpa_hfinfo.len>=gpa_hfinfo.allocated_len){
2968 if(!gpa_hfinfo.hfi){
2969 gpa_hfinfo.allocated_len=1000;
2970 gpa_hfinfo.hfi=g_malloc(sizeof(header_field_info *)*1000);
2972 gpa_hfinfo.allocated_len+=1000;
2973 gpa_hfinfo.hfi=g_realloc(gpa_hfinfo.hfi, sizeof(header_field_info *)*gpa_hfinfo.allocated_len);
2976 gpa_hfinfo.hfi[gpa_hfinfo.len]=hfinfo;
2978 hfinfo->id = gpa_hfinfo.len - 1;
2980 /* if we have real names, enter this field in the name tree */
2981 if ((hfinfo->name[0] != 0) && (hfinfo->abbrev[0] != 0 )) {
2983 header_field_info *same_name_hfinfo, *same_name_next_hfinfo;
2987 /* Check that the filter name (abbreviation) is legal;
2988 * it must contain only alphanumerics, '-', "_", and ".". */
2989 for (p = hfinfo->abbrev; (c = *p) != '\0'; p++)
2990 DISSECTOR_ASSERT(isalnum(c) || c == '-' || c == '_' ||
2993 /* We allow multiple hfinfo's to be registered under the same
2994 * abbreviation. This was done for X.25, as, depending
2995 * on whether it's modulo-8 or modulo-128 operation,
2996 * some bitfield fields may be in different bits of
2997 * a byte, and we want to be able to refer to that field
2998 * with one name regardless of whether the packets
2999 * are modulo-8 or modulo-128 packets. */
3000 same_name_hfinfo = g_tree_lookup(gpa_name_tree, hfinfo->abbrev);
3001 if (same_name_hfinfo) {
3002 /* There's already a field with this name.
3003 * Put it after that field in the list of
3004 * fields with this name, then allow the code
3005 * after this if{} block to replace the old
3006 * hfinfo with the new hfinfo in the GTree. Thus,
3007 * we end up with a linked-list of same-named hfinfo's,
3008 * with the root of the list being the hfinfo in the GTree */
3009 same_name_next_hfinfo =
3010 same_name_hfinfo->same_name_next;
3012 hfinfo->same_name_next = same_name_next_hfinfo;
3013 if (same_name_next_hfinfo)
3014 same_name_next_hfinfo->same_name_prev = hfinfo;
3016 same_name_hfinfo->same_name_next = hfinfo;
3017 hfinfo->same_name_prev = same_name_hfinfo;
3019 g_tree_insert(gpa_name_tree, (gpointer) (hfinfo->abbrev), hfinfo);
3026 proto_register_subtree_array(gint *const *indices, int num_indices)
3029 gint *const *ptr = indices;
3032 * If we've already allocated the array of tree types, expand
3033 * it; this lets plugins such as mate add tree types after
3034 * the initial startup. (If we haven't already allocated it,
3035 * we don't allocate it; on the first pass, we just assign
3036 * ett values and keep track of how many we've assigned, and
3037 * when we're finished registering all dissectors we allocate
3038 * the array, so that we do only one allocation rather than
3039 * wasting CPU time and memory by growing the array for each
3040 * dissector that registers ett values.)
3042 if (tree_is_expanded != NULL) {
3044 g_realloc(tree_is_expanded,
3045 (num_tree_types+num_indices)*sizeof (gint *));
3046 memset(tree_is_expanded + num_tree_types, 0,
3047 num_indices*sizeof (gint *));
3051 * Assign "num_indices" subtree numbers starting at "num_tree_types",
3052 * returning the indices through the pointers in the array whose
3053 * first element is pointed to by "indices", and update
3054 * "num_tree_types" appropriately.
3056 for (i = 0; i < num_indices; i++, ptr++, num_tree_types++)
3057 **ptr = num_tree_types;
3061 proto_item_fill_label(field_info *fi, gchar *label_str)
3063 header_field_info *hfinfo = fi->hfinfo;
3068 guint32 n_addr; /* network-order IPv4 address */
3069 int ret; /*tmp return value */
3071 switch(hfinfo->type) {
3074 ret = snprintf(label_str, ITEM_LABEL_LENGTH,
3075 "%s", hfinfo->name);
3076 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3077 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3081 fill_label_boolean(fi, label_str);
3086 bytes = fvalue_get(&fi->value);
3088 ret = snprintf(label_str, ITEM_LABEL_LENGTH,
3089 "%s: %s", hfinfo->name,
3090 bytes_to_str(bytes, fvalue_length(&fi->value)));
3091 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3092 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3095 ret = snprintf(label_str, ITEM_LABEL_LENGTH,
3096 "%s: <MISSING>", hfinfo->name);
3097 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3098 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3102 /* Four types of integers to take care of:
3103 * Bitfield, with val_string
3104 * Bitfield, w/o val_string
3105 * Non-bitfield, with val_string
3106 * Non-bitfield, w/o val_string
3113 if (hfinfo->bitmask) {
3114 if (hfinfo->strings) {
3115 fill_label_enumerated_bitfield(fi, label_str);
3118 fill_label_numeric_bitfield(fi, label_str);
3122 if (hfinfo->strings) {
3123 fill_label_enumerated_uint(fi, label_str);
3126 fill_label_uint(fi, label_str);
3132 fill_label_uint64(fi, label_str);
3139 DISSECTOR_ASSERT(!hfinfo->bitmask);
3140 if (hfinfo->strings) {
3141 fill_label_enumerated_int(fi, label_str);
3144 fill_label_int(fi, label_str);
3149 fill_label_int64(fi, label_str);
3153 ret = snprintf(label_str, ITEM_LABEL_LENGTH,
3154 "%s: %." STRINGIFY(FLT_DIG) "f",
3155 hfinfo->name, fvalue_get_floating(&fi->value));
3156 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3157 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3161 ret = snprintf(label_str, ITEM_LABEL_LENGTH,
3162 "%s: %." STRINGIFY(DBL_DIG) "g",
3163 hfinfo->name, fvalue_get_floating(&fi->value));
3164 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3165 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3168 case FT_ABSOLUTE_TIME:
3169 ret = snprintf(label_str, ITEM_LABEL_LENGTH,
3170 "%s: %s", hfinfo->name,
3171 abs_time_to_str(fvalue_get(&fi->value)));
3172 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3173 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3176 case FT_RELATIVE_TIME:
3177 ret = snprintf(label_str, ITEM_LABEL_LENGTH,
3178 "%s: %s seconds", hfinfo->name,
3179 rel_time_to_secs_str(fvalue_get(&fi->value)));
3180 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3181 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3185 integer = fvalue_get_integer(&fi->value);
3186 ret = snprintf(label_str, ITEM_LABEL_LENGTH,
3187 "%s: %s (0x%08X)", hfinfo->name,
3188 get_ipxnet_name(integer), integer);
3189 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3190 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3194 bytes = fvalue_get(&fi->value);
3195 ret = snprintf(label_str, ITEM_LABEL_LENGTH,
3196 "%s: %s (%s)", hfinfo->name,
3197 get_ether_name(bytes),
3198 ether_to_str(bytes));
3199 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3200 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3204 ipv4 = fvalue_get(&fi->value);
3205 n_addr = ipv4_get_net_order_addr(ipv4);
3206 ret = snprintf(label_str, ITEM_LABEL_LENGTH,
3207 "%s: %s (%s)", hfinfo->name,
3208 get_hostname(n_addr),
3209 ip_to_str((guint8*)&n_addr));
3210 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3211 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3215 bytes = fvalue_get(&fi->value);
3216 ret = snprintf(label_str, ITEM_LABEL_LENGTH,
3217 "%s: %s (%s)", hfinfo->name,
3218 get_hostname6((struct e_in6_addr *)bytes),
3219 ip6_to_str((struct e_in6_addr*)bytes));
3220 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3221 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3225 bytes = fvalue_get(&fi->value);
3226 ret = snprintf(label_str, ITEM_LABEL_LENGTH,
3227 "%s: %s", hfinfo->name,
3228 guid_to_str(bytes));
3229 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3230 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3235 case FT_UINT_STRING:
3236 bytes = fvalue_get(&fi->value);
3237 if(strlen(bytes) > ITEM_LABEL_LENGTH) {
3238 ret = snprintf(label_str, ITEM_LABEL_LENGTH,
3239 "%s [truncated]: %s", hfinfo->name,
3240 format_text(bytes, strlen(bytes)));
3242 ret = snprintf(label_str, ITEM_LABEL_LENGTH,
3243 "%s: %s", hfinfo->name,
3244 format_text(bytes, strlen(bytes)));
3246 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3247 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3251 g_error("hfinfo->type %d (%s) not handled\n",
3253 ftype_name(hfinfo->type));
3254 DISSECTOR_ASSERT_NOT_REACHED();
3260 fill_label_boolean(field_info *fi, gchar *label_str)
3262 char *p = label_str;
3263 int bitfield_byte_length = 0, bitwidth;
3264 guint32 unshifted_value;
3266 int ret; /*tmp return value */
3268 header_field_info *hfinfo = fi->hfinfo;
3269 static const true_false_string default_tf = { "True", "False" };
3270 const true_false_string *tfstring = &default_tf;
3272 if (hfinfo->strings) {
3273 tfstring = (const struct true_false_string*) hfinfo->strings;
3276 value = fvalue_get_integer(&fi->value);
3277 if (hfinfo->bitmask) {
3278 /* Figure out the bit width */
3279 bitwidth = hfinfo_bitwidth(hfinfo);
3282 unshifted_value = value;
3283 if (hfinfo->bitshift > 0) {
3284 unshifted_value <<= hfinfo->bitshift;
3287 /* Create the bitfield first */
3288 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
3289 bitfield_byte_length = p - label_str;
3292 /* Fill in the textual info */
3293 ret = snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
3294 "%s: %s", hfinfo->name,
3295 value ? tfstring->true_string : tfstring->false_string);
3296 if ((ret == -1) || (ret >= (ITEM_LABEL_LENGTH - bitfield_byte_length)))
3297 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3301 /* Fills data for bitfield ints with val_strings */
3303 fill_label_enumerated_bitfield(field_info *fi, gchar *label_str)
3305 char *format = NULL, *p;
3306 int bitfield_byte_length, bitwidth;
3307 guint32 unshifted_value;
3309 int ret; /*tmp return value */
3311 header_field_info *hfinfo = fi->hfinfo;
3313 /* Figure out the bit width */
3314 bitwidth = hfinfo_bitwidth(hfinfo);
3316 /* Pick the proper format string */
3317 format = hfinfo_uint_vals_format(hfinfo);
3320 unshifted_value = fvalue_get_integer(&fi->value);
3321 value = unshifted_value;
3322 if (hfinfo->bitshift > 0) {
3323 unshifted_value <<= hfinfo->bitshift;
3326 /* Create the bitfield first */
3327 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
3328 bitfield_byte_length = p - label_str;
3330 /* Fill in the textual info using stored (shifted) value */
3331 ret = snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
3332 format, hfinfo->name,
3333 val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
3334 if ((ret == -1) || (ret >= (ITEM_LABEL_LENGTH - bitfield_byte_length)))
3335 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3339 fill_label_numeric_bitfield(field_info *fi, gchar *label_str)
3341 char *format = NULL, *p;
3342 int bitfield_byte_length, bitwidth;
3343 guint32 unshifted_value;
3345 int ret; /*tmp return value */
3347 header_field_info *hfinfo = fi->hfinfo;
3349 /* Figure out the bit width */
3350 bitwidth = hfinfo_bitwidth(hfinfo);
3352 /* Pick the proper format string */
3353 format = hfinfo_uint_format(hfinfo);
3356 unshifted_value = fvalue_get_integer(&fi->value);
3357 value = unshifted_value;
3358 if (hfinfo->bitshift > 0) {
3359 unshifted_value <<= hfinfo->bitshift;
3362 /* Create the bitfield using */
3363 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
3364 bitfield_byte_length = p - label_str;
3366 /* Fill in the textual info using stored (shifted) value */
3367 ret = snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
3368 format, hfinfo->name, value);
3369 if ((ret == -1) || (ret >= (ITEM_LABEL_LENGTH - bitfield_byte_length)))
3370 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3375 fill_label_enumerated_uint(field_info *fi, gchar *label_str)
3377 char *format = NULL;
3378 header_field_info *hfinfo = fi->hfinfo;
3380 int ret; /*tmp return value */
3382 /* Pick the proper format string */
3383 format = hfinfo_uint_vals_format(hfinfo);
3385 value = fvalue_get_integer(&fi->value);
3387 /* Fill in the textual info */
3388 ret = snprintf(label_str, ITEM_LABEL_LENGTH,
3389 format, hfinfo->name,
3390 val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
3391 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3392 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3396 fill_label_uint(field_info *fi, gchar *label_str)
3398 char *format = NULL;
3399 header_field_info *hfinfo = fi->hfinfo;
3401 int ret; /*tmp return value */
3403 /* Pick the proper format string */
3404 format = hfinfo_uint_format(hfinfo);
3405 value = fvalue_get_integer(&fi->value);
3407 /* Fill in the textual info */
3408 ret = snprintf(label_str, ITEM_LABEL_LENGTH,
3409 format, hfinfo->name, value);
3410 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3411 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3415 fill_label_uint64(field_info *fi, gchar *label_str)
3417 char *format = NULL;
3418 header_field_info *hfinfo = fi->hfinfo;
3420 int ret; /*tmp return value */
3422 /* Pick the proper format string */
3423 format = hfinfo_uint64_format(hfinfo);
3424 value = fvalue_get_integer64(&fi->value);
3426 /* Fill in the textual info */
3427 ret = snprintf(label_str, ITEM_LABEL_LENGTH,
3428 format, hfinfo->name, value);
3429 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3430 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3434 fill_label_enumerated_int(field_info *fi, gchar *label_str)
3436 char *format = NULL;
3437 header_field_info *hfinfo = fi->hfinfo;
3439 int ret; /*tmp return value */
3441 /* Pick the proper format string */
3442 format = hfinfo_int_vals_format(hfinfo);
3443 value = fvalue_get_integer(&fi->value);
3445 /* Fill in the textual info */
3446 ret = snprintf(label_str, ITEM_LABEL_LENGTH,
3447 format, hfinfo->name,
3448 val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
3449 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3450 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3454 fill_label_int(field_info *fi, gchar *label_str)
3456 char *format = NULL;
3457 header_field_info *hfinfo = fi->hfinfo;
3459 int ret; /*tmp return value */
3461 /* Pick the proper format string */
3462 format = hfinfo_int_format(hfinfo);
3463 value = fvalue_get_integer(&fi->value);
3465 /* Fill in the textual info */
3466 ret = snprintf(label_str, ITEM_LABEL_LENGTH,
3467 format, hfinfo->name, value);
3468 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3469 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3473 fill_label_int64(field_info *fi, gchar *label_str)
3475 char *format = NULL;
3476 header_field_info *hfinfo = fi->hfinfo;
3478 int ret; /*tmp return value */
3480 /* Pick the proper format string */
3481 format = hfinfo_int64_format(hfinfo);
3482 value = fvalue_get_integer64(&fi->value);
3484 /* Fill in the textual info */
3485 ret = snprintf(label_str, ITEM_LABEL_LENGTH,
3486 format, hfinfo->name, value);
3487 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3488 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3492 hfinfo_bitwidth(header_field_info *hfinfo)
3496 if (!hfinfo->bitmask) {
3500 switch(hfinfo->type) {
3518 bitwidth = hfinfo->display; /* hacky? :) */
3521 DISSECTOR_ASSERT_NOT_REACHED();
3528 hfinfo_uint_vals_format(header_field_info *hfinfo)
3530 char *format = NULL;
3532 switch(hfinfo->display) {
3534 format = "%s: %s (%u)";
3536 case BASE_OCT: /* I'm lazy */
3537 format = "%s: %s (%o)";
3540 switch(hfinfo->type) {
3542 format = "%s: %s (0x%02x)";
3545 format = "%s: %s (0x%04x)";
3548 format = "%s: %s (0x%06x)";
3551 format = "%s: %s (0x%08x)";
3554 DISSECTOR_ASSERT_NOT_REACHED();
3559 DISSECTOR_ASSERT_NOT_REACHED();
3566 hfinfo_uint_format(header_field_info *hfinfo)
3568 char *format = NULL;
3570 /* Pick the proper format string */
3571 if (hfinfo->type == FT_FRAMENUM) {
3573 * Frame numbers are always displayed in decimal.
3577 switch(hfinfo->display) {
3581 case BASE_OCT: /* I'm lazy */
3585 switch(hfinfo->type) {
3587 format = "%s: 0x%02x";
3590 format = "%s: 0x%04x";
3593 format = "%s: 0x%06x";
3596 format = "%s: 0x%08x";
3599 DISSECTOR_ASSERT_NOT_REACHED();
3604 DISSECTOR_ASSERT_NOT_REACHED();
3612 hfinfo_int_vals_format(header_field_info *hfinfo)
3614 char *format = NULL;
3616 switch(hfinfo->display) {
3618 format = "%s: %s (%d)";
3620 case BASE_OCT: /* I'm lazy */
3621 format = "%s: %s (%o)";
3624 switch(hfinfo->type) {
3626 format = "%s: %s (0x%02x)";
3629 format = "%s: %s (0x%04x)";
3632 format = "%s: %s (0x%06x)";
3635 format = "%s: %s (0x%08x)";
3638 DISSECTOR_ASSERT_NOT_REACHED();
3643 DISSECTOR_ASSERT_NOT_REACHED();
3650 hfinfo_uint64_format(header_field_info *hfinfo)
3652 char *format = NULL;
3654 /* Pick the proper format string */
3655 switch(hfinfo->display) {
3657 format = "%s: %" PRIu64;
3659 case BASE_OCT: /* I'm lazy */
3660 format = "%s: %" PRIo64;
3663 format = "%s: 0x%016" PRIx64;
3666 DISSECTOR_ASSERT_NOT_REACHED();
3673 hfinfo_int_format(header_field_info *hfinfo)
3675 char *format = NULL;
3677 /* Pick the proper format string */
3678 switch(hfinfo->display) {
3682 case BASE_OCT: /* I'm lazy */
3686 switch(hfinfo->type) {
3688 format = "%s: 0x%02x";
3691 format = "%s: 0x%04x";
3694 format = "%s: 0x%06x";
3697 format = "%s: 0x%08x";
3700 DISSECTOR_ASSERT_NOT_REACHED();
3705 DISSECTOR_ASSERT_NOT_REACHED();
3712 hfinfo_int64_format(header_field_info *hfinfo)
3714 char *format = NULL;
3716 /* Pick the proper format string */
3717 switch(hfinfo->display) {
3719 format = "%s: %" PRId64;
3721 case BASE_OCT: /* I'm lazy */
3722 format = "%s: %" PRIo64;
3725 format = "%s: 0x%016" PRIx64;
3728 DISSECTOR_ASSERT_NOT_REACHED();
3737 proto_registrar_n(void)
3739 return gpa_hfinfo.len;
3743 proto_registrar_get_name(int n)
3745 header_field_info *hfinfo;
3747 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
3748 return hfinfo->name;
3752 proto_registrar_get_abbrev(int n)
3754 header_field_info *hfinfo;
3756 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
3757 return hfinfo->abbrev;
3761 proto_registrar_get_ftype(int n)
3763 header_field_info *hfinfo;
3765 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
3766 return hfinfo->type;
3770 proto_registrar_get_parent(int n)
3772 header_field_info *hfinfo;
3774 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
3775 return hfinfo->parent;
3779 proto_registrar_is_protocol(int n)
3781 header_field_info *hfinfo;
3783 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
3784 return (hfinfo->parent == -1 ? TRUE : FALSE);
3787 /* Returns length of field in packet (not necessarily the length
3788 * in our internal representation, as in the case of IPv4).
3789 * 0 means undeterminable at time of registration
3790 * -1 means the field is not registered. */
3792 proto_registrar_get_length(int n)
3794 header_field_info *hfinfo;
3796 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
3797 return ftype_length(hfinfo->type);
3802 /* Looks for a protocol or a field in a proto_tree. Returns TRUE if
3803 * it exists anywhere, or FALSE if it exists nowhere. */
3805 proto_check_for_protocol_or_field(proto_tree* tree, int id)
3807 GPtrArray *ptrs = proto_get_finfo_ptr_array(tree, id);
3812 else if (g_ptr_array_len(ptrs) > 0) {
3820 /* Return GPtrArray* of field_info pointers for all hfindex that appear in tree.
3821 * This only works if the hfindex was "primed" before the dissection
3822 * took place, as we just pass back the already-created GPtrArray*.
3823 * The caller should *not* free the GPtrArray*; proto_tree_free_node()
3826 proto_get_finfo_ptr_array(proto_tree *tree, int id)
3828 return g_hash_table_lookup(PTREE_DATA(tree)->interesting_hfids,
3829 GINT_TO_POINTER(id));
3833 /* Helper struct and function for proto_find_info() */
3840 find_finfo(proto_node *node, gpointer data)
3842 field_info *fi = PITEM_FINFO(node);
3843 if (fi && fi->hfinfo) {
3844 if (fi->hfinfo->id == ((ffdata_t*)data)->id) {
3845 g_ptr_array_add(((ffdata_t*)data)->array, fi);
3849 /* Don't stop traversing. */
3853 /* Return GPtrArray* of field_info pointers for all hfindex that appear in a tree.
3854 * This works on any proto_tree, primed or unprimed, but actually searches
3855 * the tree, so it is slower than using proto_get_finfo_ptr_array on a primed tree.
3856 * The caller does need to free the returned GPtrArray with
3857 * g_ptr_array_free(<array>, FALSE).
3860 proto_find_finfo(proto_tree *tree, int id)
3864 ffdata.array = g_ptr_array_new();
3867 proto_tree_traverse_pre_order(tree, find_finfo, &ffdata);
3869 return ffdata.array;
3880 check_for_offset(proto_node *node, gpointer data)
3882 field_info *fi = PITEM_FINFO(node);
3883 offset_search_t *offsearch = data;
3885 /* !fi == the top most container node which holds nothing */
3886 if (fi && !PROTO_ITEM_IS_HIDDEN(node) && fi->ds_tvb && offsearch->tvb == fi->ds_tvb) {
3887 if (offsearch->offset >= (guint) fi->start &&
3888 offsearch->offset < (guint) (fi->start + fi->length)) {
3890 offsearch->finfo = fi;
3891 return FALSE; /* keep traversing */
3894 return FALSE; /* keep traversing */
3897 /* Search a proto_tree backwards (from leaves to root) looking for the field
3898 * whose start/length occupies 'offset' */
3899 /* XXX - I couldn't find an easy way to search backwards, so I search
3900 * forwards, w/o stopping. Therefore, the last finfo I find will the be
3901 * the one I want to return to the user. This algorithm is inefficient
3902 * and could be re-done, but I'd have to handle all the children and
3903 * siblings of each node myself. When I have more time I'll do that.
3906 proto_find_field_from_offset(proto_tree *tree, guint offset, tvbuff_t *tvb)
3908 offset_search_t offsearch;
3910 offsearch.offset = offset;
3911 offsearch.finfo = NULL;
3912 offsearch.tvb = tvb;
3914 proto_tree_traverse_pre_order(tree, check_for_offset, &offsearch);
3916 return offsearch.finfo;
3919 /* Dumps the protocols in the registration database to stdout. An independent
3920 * program can take this output and format it into nice tables or HTML or
3923 * There is one record per line. The fields are tab-delimited.
3925 * Field 1 = protocol name
3926 * Field 2 = protocol short name
3927 * Field 3 = protocol filter name
3930 proto_registrar_dump_protocols(void)
3932 protocol_t *protocol;
3936 for (i = proto_get_first_protocol(&cookie); i != -1;
3937 i = proto_get_next_protocol(&cookie)) {
3938 protocol = find_protocol_by_id(i);
3939 printf("%s\t%s\t%s\n", protocol->name, protocol->short_name,
3940 protocol->filter_name);
3944 /* Dumps the value_string and true/false strings for fields that have
3945 * them. There is one record per line. Fields are tab-delimited.
3946 * There are two types of records, Value String records and True/False
3947 * String records. The first field, 'V' or 'T', indicates the type
3953 * Field 2 = field abbreviation to which this value string corresponds
3954 * Field 3 = Integer value
3957 * True/False Strings
3958 * ------------------
3960 * Field 2 = field abbreviation to which this true/false string corresponds
3961 * Field 3 = True String
3962 * Field 4 = False String
3965 proto_registrar_dump_values(void)
3967 header_field_info *hfinfo, *parent_hfinfo;
3969 const value_string *vals;
3970 const true_false_string *tfs;
3972 len = gpa_hfinfo.len;
3973 for (i = 0; i < len ; i++) {
3974 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
3976 if (hfinfo->id == hf_text_only) {
3980 /* ignore protocols */
3981 if (proto_registrar_is_protocol(i)) {
3984 /* process header fields */
3987 * If this field isn't at the head of the list of
3988 * fields with this name, skip this field - all
3989 * fields with the same name are really just versions
3990 * of the same field stored in different bits, and
3991 * should have the same type/radix/value list, and
3992 * just differ in their bit masks. (If a field isn't
3993 * a bitfield, but can be, say, 1 or 2 bytes long,
3994 * it can just be made FT_UINT16, meaning the
3995 * *maximum* length is 2 bytes, and be used
3998 if (hfinfo->same_name_prev != NULL)
4001 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
4006 if (hfinfo->type == FT_UINT8 ||
4007 hfinfo->type == FT_UINT16 ||
4008 hfinfo->type == FT_UINT24 ||
4009 hfinfo->type == FT_UINT32 ||
4010 hfinfo->type == FT_UINT64 ||
4011 hfinfo->type == FT_INT8 ||
4012 hfinfo->type == FT_INT16 ||
4013 hfinfo->type == FT_INT24 ||
4014 hfinfo->type == FT_INT32 ||
4015 hfinfo->type == FT_INT64) {
4017 vals = hfinfo->strings;
4019 else if (hfinfo->type == FT_BOOLEAN) {
4020 tfs = hfinfo->strings;
4023 /* Print value strings? */
4026 while (vals[vi].strptr) {
4027 /* Print in the proper base */
4028 if (hfinfo->display == BASE_HEX) {
4029 printf("V\t%s\t0x%x\t%s\n",
4035 printf("V\t%s\t%u\t%s\n",
4044 /* Print true/false strings? */
4046 printf("T\t%s\t%s\t%s\n", hfinfo->abbrev,
4047 tfs->true_string, tfs->false_string);
4053 /* Dumps the contents of the registration database to stdout. An indepedent
4054 * program can take this output and format it into nice tables or HTML or
4057 * There is one record per line. Each record is either a protocol or a header
4058 * field, differentiated by the first field. The fields are tab-delimited.
4063 * Field 2 = descriptive protocol name
4064 * Field 3 = protocol abbreviation
4070 * Field 2 = descriptive field name
4071 * Field 3 = field abbreviation
4072 * Field 4 = type ( textual representation of the the ftenum type )
4073 * Field 5 = parent protocol abbreviation
4074 * Field 6 = blurb describing field
4078 * Field 2 = descriptive field name
4079 * Field 3 = field abbreviation
4080 * Field 4 = type ( textual representation of the the ftenum type )
4081 * Field 5 = parent protocol abbreviation
4082 * Field 6 = blurb describing field
4083 * Field 7 = base for display (for integer types)
4084 * Field 8 = blurb describing field (yes, apparently we repeated this accidentally)
4088 * Field 2 = descriptive field name
4089 * Field 3 = field abbreviation
4090 * Field 4 = type ( textual representation of the the ftenum type )
4091 * Field 5 = parent protocol abbreviation
4092 * Field 6 = blurb describing field
4093 * Field 7 = base for display (for integer types)
4097 proto_registrar_dump_fields(int format)
4099 header_field_info *hfinfo, *parent_hfinfo;
4101 const char *enum_name;
4102 const char *base_name;
4104 len = gpa_hfinfo.len;
4105 for (i = 0; i < len ; i++) {
4106 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
4109 * Skip fields with zero-length names or abbreviations;
4110 * the pseudo-field for "proto_tree_add_text()" is such
4111 * a field, and we don't want it in the list of filterable
4115 * XXX - perhaps the name and abbrev field should be null
4116 * pointers rather than null strings for that pseudo-field,
4117 * but we'd have to add checks for null pointers in some
4118 * places if we did that.
4120 * Or perhaps protocol tree items added with
4121 * "proto_tree_add_text()" should have -1 as the field index,
4122 * with no pseudo-field being used, but that might also
4123 * require special checks for -1 to be added.
4125 /* XXX - we could just skip the special text
4126 * pseudo-field by testing: if (hfinfo->id == hf_text_only)
4128 if (hfinfo->name[0] == 0 || hfinfo->abbrev[0] == 0)
4131 /* format for protocols */
4132 if (proto_registrar_is_protocol(i)) {
4133 printf("P\t%s\t%s\n", hfinfo->name, hfinfo->abbrev);
4135 /* format for header fields */
4138 * If this field isn't at the head of the list of
4139 * fields with this name, skip this field - all
4140 * fields with the same name are really just versions
4141 * of the same field stored in different bits, and
4142 * should have the same type/radix/value list, and
4143 * just differ in their bit masks. (If a field isn't
4144 * a bitfield, but can be, say, 1 or 2 bytes long,
4145 * it can just be made FT_UINT16, meaning the
4146 * *maximum* length is 2 bytes, and be used
4149 if (hfinfo->same_name_prev != NULL)
4152 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
4154 enum_name = ftype_name(hfinfo->type);
4158 if (hfinfo->type == FT_UINT8 ||
4159 hfinfo->type == FT_UINT16 ||
4160 hfinfo->type == FT_UINT24 ||
4161 hfinfo->type == FT_UINT32 ||
4162 hfinfo->type == FT_UINT64 ||
4163 hfinfo->type == FT_INT8 ||
4164 hfinfo->type == FT_INT16 ||
4165 hfinfo->type == FT_INT24 ||
4166 hfinfo->type == FT_INT32 ||
4167 hfinfo->type == FT_INT64) {
4170 switch(hfinfo->display) {
4172 base_name = "BASE_NONE";
4175 base_name = "BASE_DEC";
4178 base_name = "BASE_HEX";
4181 base_name = "BASE_OCT";
4188 printf("F\t%s\t%s\t%s\t%s\t%s\n", hfinfo->name, hfinfo->abbrev,
4189 enum_name,parent_hfinfo->abbrev, hfinfo->blurb);
4191 else if (format == 2) {
4192 printf("F\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n",
4193 hfinfo->name, hfinfo->abbrev,
4194 enum_name,parent_hfinfo->abbrev, hfinfo->blurb,
4195 base_name, hfinfo->blurb);
4197 else if (format == 3) {
4198 printf("F\t%s\t%s\t%s\t%s\t%s\t%s\t%u\n",
4199 hfinfo->name, hfinfo->abbrev,
4200 enum_name,parent_hfinfo->abbrev, hfinfo->blurb,
4201 base_name, hfinfo->bitmask);
4204 g_assert_not_reached();
4211 hfinfo_numeric_format(header_field_info *hfinfo)
4213 char *format = NULL;
4215 /* Pick the proper format string */
4216 if (hfinfo->type == FT_FRAMENUM) {
4218 * Frame numbers are always displayed in decimal.
4220 format = "%s == %u";
4222 /* Pick the proper format string */
4223 switch(hfinfo->display) {
4225 case BASE_OCT: /* I'm lazy */
4226 switch(hfinfo->type) {
4231 format = "%s == %u";
4234 format = "%s == %" PRIu64;
4240 format = "%s == %d";
4243 format = "%s == %" PRId64;
4246 DISSECTOR_ASSERT_NOT_REACHED();
4251 switch(hfinfo->type) {
4253 format = "%s == 0x%02x";
4256 format = "%s == 0x%04x";
4259 format = "%s == 0x%06x";
4262 format = "%s == 0x%08x";
4265 format = "%s == 0x%016" PRIx64;
4268 DISSECTOR_ASSERT_NOT_REACHED();
4273 DISSECTOR_ASSERT_NOT_REACHED();
4281 * Returns TRUE if we can do a "match selected" on the field, FALSE
4285 proto_can_match_selected(field_info *finfo, epan_dissect_t *edt)
4287 header_field_info *hfinfo;
4290 hfinfo = finfo->hfinfo;
4291 DISSECTOR_ASSERT(hfinfo);
4293 switch(hfinfo->type) {
4312 case FT_ABSOLUTE_TIME:
4313 case FT_RELATIVE_TIME:
4316 case FT_UINT_STRING:
4323 * These all have values, so we can match.
4329 * This doesn't have a value, so we'd match
4330 * on the raw bytes at this address.
4332 * Should we be allowed to access to the raw bytes?
4333 * If "edt" is NULL, the answer is "no".
4339 * Is this field part of the raw frame tvbuff?
4340 * If not, we can't use "frame[N:M]" to match
4343 * XXX - should this be frame-relative, or
4344 * protocol-relative?
4346 * XXX - does this fallback for non-registered
4347 * fields even make sense?
4349 if (finfo->ds_tvb != edt->tvb)
4353 * If the length is 0, there's nothing to match, so
4354 * we can't match. (Also check for negative values,
4355 * just in case, as we'll cast it to an unsigned
4358 length = finfo->length;
4363 * Don't go past the end of that tvbuff.
4365 if ((guint)length > tvb_length(finfo->ds_tvb))
4366 length = tvb_length(finfo->ds_tvb);
4374 proto_construct_dfilter_string(field_info *finfo, epan_dissect_t *edt)
4376 header_field_info *hfinfo;
4378 char *buf, *stringified, *format, *ptr;
4380 gint start, length, length_remaining;
4383 hfinfo = finfo->hfinfo;
4384 DISSECTOR_ASSERT(hfinfo);
4385 abbrev_len = strlen(hfinfo->abbrev);
4388 * XXX - we should add "val_to_string_repr" and "string_repr_len"
4389 * functions for more types, and use them whenever possible.
4391 * The FT_UINT and FT_INT types are the only tricky ones, as
4392 * we choose the base in the string expression based on the
4393 * display base of the field.
4395 * Note that the base does matter, as this is also used for
4396 * the protocolinfo tap.
4398 * It might be nice to use that in "proto_item_fill_label()"
4399 * as well, although, there, you'd have to deal with the base
4400 * *and* with resolved values for addresses.
4402 * Perhaps we need two different val_to_string routines, one
4403 * to generate items for display filters and one to generate
4404 * strings for display, and pass to both of them the
4405 * "display" and "strings" values in the header_field_info
4406 * structure for the field, so they can get the base and,
4407 * if the field is Boolean or an enumerated integer type,
4408 * the tables used to generate human-readable values.
4410 switch(hfinfo->type) {
4422 * 4 bytes for " == ".
4425 * a sign + up to 10 digits of 32-bit integer,
4428 * "0x" + 8 digits of 32-bit integer, in hex;
4430 * 11 digits of 32-bit integer, in octal.
4431 * (No, we don't do octal, but this way,
4432 * we know that if we do, this will still
4435 * 1 byte for the trailing '\0'.
4437 dfilter_len = abbrev_len + 4 + 11 + 1;
4438 buf = g_malloc0(dfilter_len);
4439 format = hfinfo_numeric_format(hfinfo);
4440 snprintf(buf, dfilter_len, format, hfinfo->abbrev, fvalue_get_integer(&finfo->value));
4446 * 4 bytes for " == ".
4449 * a sign + up to 20 digits of 32-bit integer,
4452 * "0x" + 16 digits of 32-bit integer, in hex;
4454 * 22 digits of 32-bit integer, in octal.
4455 * (No, we don't do octal, but this way,
4456 * we know that if we do, this will still
4459 * 1 byte for the trailing '\0'.
4461 dfilter_len = abbrev_len + 4 + 22 + 1;
4462 buf = g_malloc0(dfilter_len);
4463 format = hfinfo_numeric_format(hfinfo);
4464 snprintf(buf, dfilter_len, format, hfinfo->abbrev, fvalue_get_integer64(&finfo->value));
4469 * 4 bytes for " == ".
4471 * 8 bytes for 8 digits of 32-bit hex number.
4472 * 1 byte for the trailing '\0'.
4474 dfilter_len = abbrev_len + 4 + 2 + 8 + 1;
4475 buf = g_malloc0(dfilter_len);
4476 snprintf(buf, dfilter_len, "%s == 0x%08x", hfinfo->abbrev,
4477 fvalue_get_integer(&finfo->value));
4482 * 4 bytes for " == ".
4483 * N bytes for the string for the address.
4484 * 1 byte for the trailing '\0'.
4486 stringified = ip6_to_str((struct e_in6_addr*) fvalue_get(&finfo->value));
4487 dfilter_len = abbrev_len + 4 + strlen(stringified) + 1;
4488 buf = g_malloc0(dfilter_len);
4489 snprintf(buf, dfilter_len, "%s == %s", hfinfo->abbrev,
4493 /* These use the fvalue's "to_string_repr" method. */
4501 case FT_ABSOLUTE_TIME:
4502 case FT_RELATIVE_TIME:
4505 /* Figure out the string length needed.
4506 * The ft_repr length.
4507 * 4 bytes for " == ".
4508 * 1 byte for trailing NUL.
4510 dfilter_len = fvalue_string_repr_len(&finfo->value,
4512 dfilter_len += abbrev_len + 4 + 1;
4513 buf = g_malloc0(dfilter_len);
4515 /* Create the string */
4516 snprintf(buf, dfilter_len, "%s == ", hfinfo->abbrev);
4517 fvalue_to_string_repr(&finfo->value,
4519 &buf[abbrev_len + 4]);
4523 buf = g_strdup(finfo->hfinfo->abbrev);
4528 * This doesn't have a value, so we'd match
4529 * on the raw bytes at this address.
4531 * Should we be allowed to access to the raw bytes?
4532 * If "edt" is NULL, the answer is "no".
4538 * Is this field part of the raw frame tvbuff?
4539 * If not, we can't use "frame[N:M]" to match
4542 * XXX - should this be frame-relative, or
4543 * protocol-relative?
4545 * XXX - does this fallback for non-registered
4546 * fields even make sense?
4548 if (finfo->ds_tvb != edt->tvb)
4549 return NULL; /* you lose */
4552 * If the length is 0, there's nothing to match, so
4553 * we can't match. (Also check for negative values,
4554 * just in case, as we'll cast it to an unsigned
4557 length = finfo->length;
4562 * Don't go past the end of that tvbuff.
4564 length_remaining = tvb_length_remaining(finfo->ds_tvb, finfo->start);
4565 if (length > length_remaining)
4566 length = length_remaining;
4570 start = finfo->start;
4571 buf = g_malloc0(32 + length * 3);
4574 sprintf(ptr, "frame[%d:%d] == ", finfo->start, length);
4575 ptr = buf+strlen(buf);
4577 for (i=0;i<length; i++) {
4578 c = tvb_get_guint8(finfo->ds_tvb, start);
4581 sprintf(ptr, "%02x", c);
4584 sprintf(ptr, ":%02x", c);
4586 ptr = buf+strlen(buf);