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"
43 #include "ipv6-utils.h"
45 #include "int-64bit.h"
46 #include "epan_dissect.h"
50 #define cVALS(x) (const value_string*)(x)
53 proto_tree_free_node(proto_node *node, gpointer data);
55 static void fill_label_boolean(field_info *fi, gchar *label_str);
56 static void fill_label_uint(field_info *fi, gchar *label_str);
57 static void fill_label_uint64(field_info *fi, gchar *label_str);
58 static void fill_label_int64(field_info *fi, gchar *label_str);
59 static void fill_label_enumerated_uint(field_info *fi, gchar *label_str);
60 static void fill_label_enumerated_bitfield(field_info *fi, gchar *label_str);
61 static void fill_label_numeric_bitfield(field_info *fi, gchar *label_str);
62 static void fill_label_int(field_info *fi, gchar *label_str);
63 static void fill_label_enumerated_int(field_info *fi, gchar *label_str);
65 int hfinfo_bitwidth(header_field_info *hfinfo);
66 static char* hfinfo_uint_vals_format(header_field_info *hfinfo);
67 static char* hfinfo_uint_format(header_field_info *hfinfo);
68 static char* hfinfo_int_vals_format(header_field_info *hfinfo);
69 static char* hfinfo_int_format(header_field_info *hfinfo);
72 proto_tree_add_node(proto_tree *tree, field_info *fi);
75 alloc_field_info(proto_tree *tree, int hfindex, tvbuff_t *tvb,
76 gint start, gint *length);
79 proto_tree_add_pi(proto_tree *tree, int hfindex, tvbuff_t *tvb,
80 gint start, gint *length, field_info **pfi);
83 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap);
86 proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb);
88 proto_tree_set_uint64(field_info *fi, const guint8 *value_ptr, gboolean little_endian);
90 proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start, gboolean little_endian);
92 proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length);
94 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length);
96 proto_tree_set_time(field_info *fi, nstime_t *value_ptr);
98 proto_tree_set_string(field_info *fi, const char* value, gboolean);
100 proto_tree_set_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
102 proto_tree_set_ether(field_info *fi, const guint8* value);
104 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start);
106 proto_tree_set_ipxnet(field_info *fi, guint32 value);
108 proto_tree_set_ipv4(field_info *fi, guint32 value);
110 proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr);
112 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start);
114 proto_tree_set_boolean(field_info *fi, guint32 value);
116 proto_tree_set_float(field_info *fi, float value);
118 proto_tree_set_double(field_info *fi, double value);
120 proto_tree_set_uint(field_info *fi, guint32 value);
122 proto_tree_set_int(field_info *fi, gint32 value);
124 static int proto_register_field_init(header_field_info *hfinfo, int parent);
126 /* Comparision function for tree insertion. A wrapper around strcmp() */
127 static int g_strcmp(gconstpointer a, gconstpointer b);
129 /* special-case header field used within proto.c */
130 int hf_text_only = -1;
132 /* Structure for information about a protocol */
134 char *name; /* long description */
135 char *short_name; /* short description */
136 char *filter_name; /* name of this protocol in filters */
137 int proto_id; /* field ID for this protocol */
138 GList *fields; /* fields for this protocol */
139 GList *last_field; /* pointer to end of list of fields */
140 gboolean is_enabled; /* TRUE if protocol is enabled */
141 gboolean can_toggle; /* TRUE if is_enabled can be changed */
144 /* List of all protocols */
145 static GList *protocols;
147 #define INITIAL_NUM_PROTOCOL_HFINFO 200
150 /* Contains information about protocols and header fields. Used when
151 * dissectors register their data */
152 static GMemChunk *gmc_hfinfo = NULL;
154 /* Contains information about a field when a dissector calls
155 * proto_tree_add_item. */
156 SLAB_ITEM_TYPE_DEFINE(field_info)
157 static SLAB_FREE_LIST_DEFINE(field_info)
158 static field_info *field_info_tmp=NULL;
159 #define FIELD_INFO_NEW(fi) \
160 SLAB_ALLOC(fi, field_info)
161 #define FIELD_INFO_FREE(fi) \
162 SLAB_FREE(fi, field_info)
166 /* Contains the space for proto_nodes. */
167 SLAB_ITEM_TYPE_DEFINE(proto_node)
168 static SLAB_FREE_LIST_DEFINE(proto_node)
169 #define PROTO_NODE_NEW(node) \
170 SLAB_ALLOC(node, proto_node) \
171 node->first_child = NULL; \
172 node->last_child = NULL; \
175 #define PROTO_NODE_FREE(node) \
176 SLAB_FREE(node, proto_node)
180 /* String space for protocol and field items for the GUI */
181 SLAB_ITEM_TYPE_DEFINE(item_label_t)
182 static SLAB_FREE_LIST_DEFINE(item_label_t)
183 #define ITEM_LABEL_NEW(il) \
184 SLAB_ALLOC(il, item_label_t)
185 #define ITEM_LABEL_FREE(il) \
186 SLAB_FREE(il, item_label_t)
190 /* List which stores protocols and fields that have been registered */
191 typedef struct _gpa_hfinfo_t {
193 guint32 allocated_len;
194 header_field_info **hfi;
196 gpa_hfinfo_t gpa_hfinfo;
198 /* Balanced tree of abbreviations and IDs */
199 static GTree *gpa_name_tree = NULL;
201 /* Points to the first element of an array of Booleans, indexed by
202 a subtree item type; that array element is TRUE if subtrees of
203 an item of that type are to be expanded. */
204 gboolean *tree_is_expanded;
206 /* Number of elements in that array. */
209 /* initialize data structures and register protocols and fields */
211 proto_init(const char *plugin_dir
216 void (register_all_protocols)(void),
217 void (register_all_protocol_handoffs)(void))
219 static hf_register_info hf[] = {
221 { "", "", FT_NONE, BASE_NONE, NULL, 0x0,
227 gmc_hfinfo = g_mem_chunk_new("gmc_hfinfo",
228 sizeof(header_field_info),
229 INITIAL_NUM_PROTOCOL_HFINFO * sizeof(header_field_info),
233 gpa_hfinfo.allocated_len=0;
235 gpa_name_tree = g_tree_new(g_strcmp);
237 /* Initialize the ftype subsystem */
240 /* Register one special-case FT_TEXT_ONLY field for use when
241 converting ethereal to new-style proto_tree. These fields
242 are merely strings on the GUI tree; they are not filterable */
243 proto_register_field_array(-1, hf, array_length(hf));
245 /* Have each built-in dissector register its protocols, fields,
246 dissector tables, and dissectors to be called through a
247 handle, and do whatever one-time initialization it needs to
249 register_all_protocols();
252 /* Now scan for plugins and load all the ones we find, calling
253 their register routines to do the stuff described above. */
254 init_plugins(plugin_dir);
257 /* Now call the "handoff registration" routines of all built-in
258 dissectors; those routines register the dissector in other
259 dissectors' handoff tables, and fetch any dissector handles
261 register_all_protocol_handoffs();
264 /* Now do the same with plugins. */
265 register_all_plugin_handoffs();
268 /* We've assigned all the subtree type values; allocate the array
269 for them, and zero it out. */
270 tree_is_expanded = g_malloc(num_tree_types*sizeof (gint *));
271 memset(tree_is_expanded, 0, num_tree_types*sizeof (gint *));
274 /* String comparison func for dfilter_token GTree */
276 g_strcmp(gconstpointer a, gconstpointer b)
278 return strcmp((const char*)a, (const char*)b);
284 /* Free the abbrev/ID GTree */
286 g_tree_destroy(gpa_name_tree);
287 gpa_name_tree = NULL;
291 g_mem_chunk_destroy(gmc_hfinfo);
293 if(gpa_hfinfo.allocated_len){
295 gpa_hfinfo.allocated_len=0;
296 g_free(gpa_hfinfo.hfi);
299 if (tree_is_expanded != NULL)
300 g_free(tree_is_expanded);
304 typedef gboolean (*proto_tree_traverse_func)(proto_node *, gpointer);
307 proto_tree_traverse_pre_order(proto_tree *tree, proto_tree_traverse_func func,
310 proto_node *pnode = tree;
314 if (func(pnode, data))
317 child = pnode->first_child;
318 while (child != NULL) {
320 * The routine we call might modify the child, e.g. by
321 * freeing it, so we get the child's successor before
322 * calling that routine.
325 child = current->next;
326 if (proto_tree_traverse_pre_order((proto_tree *)current, func,
335 proto_tree_traverse_in_order(proto_tree *tree, proto_tree_traverse_func func,
338 proto_node *pnode = tree;
342 child = pnode->first_child;
345 * The routine we call might modify the child, e.g. by
346 * freeing it, so we get the child's successor before
347 * calling that routine.
350 child = current->next;
352 if (proto_tree_traverse_in_order((proto_tree *)current, func,
356 if (func(pnode, data))
359 while (child != NULL) {
361 * The routine we call might modify the child, e.g. by
362 * freeing it, so we get the child's successor before
363 * calling that routine.
366 child = current->next;
367 if (proto_tree_traverse_in_order((proto_tree *)current,
372 if (func(pnode, data))
380 proto_tree_children_foreach(proto_tree *tree, proto_tree_foreach_func func,
383 proto_node *node = tree;
386 node = node->first_child;
387 while (node != NULL) {
389 node = current->next;
390 func((proto_tree *)current, data);
394 /* frees the resources that the dissection a proto_tree uses */
396 proto_tree_free(proto_tree *tree)
398 proto_tree_traverse_in_order(tree, proto_tree_free_node, NULL);
402 free_GPtrArray_value(gpointer key _U_, gpointer value, gpointer user_data _U_)
404 GPtrArray *ptrs = value;
406 g_ptr_array_free(ptrs, TRUE);
410 free_node_tree_data(tree_data_t *tree_data)
412 /* Free all the GPtrArray's in the interesting_hfids hash. */
413 g_hash_table_foreach(tree_data->interesting_hfids,
414 free_GPtrArray_value, NULL);
416 /* And then destroy the hash. */
417 g_hash_table_destroy(tree_data->interesting_hfids);
419 /* And finally the tree_data_t itself. */
423 #define FREE_NODE_FIELD_INFO(finfo) \
425 ITEM_LABEL_FREE(finfo->rep); \
427 FVALUE_CLEANUP(&finfo->value); \
428 FIELD_INFO_FREE(finfo);
431 proto_tree_free_node(proto_node *node, gpointer data _U_)
433 field_info *finfo = PITEM_FINFO(node);
436 /* This is the root node. Destroy the per-tree data.
437 * There is no field_info to destroy. */
438 free_node_tree_data(PTREE_DATA(node));
441 /* This is a child node. Don't free the per-tree data, but
442 * do free the field_info data. */
443 FREE_NODE_FIELD_INFO(finfo);
446 /* Free the proto_node. */
447 PROTO_NODE_FREE(node);
449 return FALSE; /* FALSE = do not end traversal of protocol tree */
452 /* Is the parsing being done for a visible proto_tree or an invisible one?
453 * By setting this correctly, the proto_tree creation is sped up by not
454 * having to call vsnprintf and copy strings around.
457 proto_tree_set_visible(proto_tree *tree, gboolean visible)
459 PTREE_DATA(tree)->visible = visible;
462 #define PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo) \
463 g_assert((guint)hfindex < gpa_hfinfo.len); \
464 hfinfo=gpa_hfinfo.hfi[hfindex];
466 /* Finds a record in the hf_info_records array by id. */
468 proto_registrar_get_nth(guint hfindex)
470 register header_field_info *hfinfo;
472 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
476 /* Finds a record in the hf_info_records array by name.
479 proto_registrar_get_byname(char *field_name)
481 g_assert(field_name != NULL);
482 return g_tree_lookup(gpa_name_tree, field_name);
485 /* Add a text-only node, leaving it to our caller to fill the text in */
487 proto_tree_add_text_node(proto_tree *tree, tvbuff_t *tvb, gint start, gint length)
491 pi = proto_tree_add_pi(tree, hf_text_only, tvb, start, &length, NULL);
498 /* Add a text-only node to the proto_tree */
500 proto_tree_add_text(proto_tree *tree, tvbuff_t *tvb, gint start, gint length,
501 const char *format, ...)
506 pi = proto_tree_add_text_node(tree, tvb, start, length);
510 va_start(ap, format);
511 proto_tree_set_representation(pi, format, ap);
517 /* Add a text-only node to the proto_tree (va_list version) */
519 proto_tree_add_text_valist(proto_tree *tree, tvbuff_t *tvb, gint start,
520 gint length, const char *format, va_list ap)
524 pi = proto_tree_add_text_node(tree, tvb, start, length);
528 proto_tree_set_representation(pi, format, ap);
533 /* Add a text-only node for debugging purposes. The caller doesn't need
534 * to worry about tvbuff, start, or length. Debug message gets sent to
537 proto_tree_add_debug_text(proto_tree *tree, const char *format, ...)
542 pi = proto_tree_add_text_node(tree, NULL, 0, 0);
546 va_start(ap, format);
547 proto_tree_set_representation(pi, format, ap);
557 get_uint_value(tvbuff_t *tvb, gint offset, gint length, gboolean little_endian)
564 value = tvb_get_guint8(tvb, offset);
568 value = little_endian ? tvb_get_letohs(tvb, offset)
569 : tvb_get_ntohs(tvb, offset);
573 value = little_endian ? tvb_get_letoh24(tvb, offset)
574 : tvb_get_ntoh24(tvb, offset);
578 value = little_endian ? tvb_get_letohl(tvb, offset)
579 : tvb_get_ntohl(tvb, offset);
583 g_assert_not_reached();
591 get_int_value(tvbuff_t *tvb, gint offset, gint length, gboolean little_endian)
598 value = (gint8)tvb_get_guint8(tvb, offset);
602 value = (gint16) (little_endian ? tvb_get_letohs(tvb, offset)
603 : tvb_get_ntohs(tvb, offset));
607 value = little_endian ? tvb_get_letoh24(tvb, offset)
608 : tvb_get_ntoh24(tvb, offset);
609 if (value & 0x00800000) {
610 /* Sign bit is set; sign-extend it. */
616 value = little_endian ? tvb_get_letohl(tvb, offset)
617 : tvb_get_ntohl(tvb, offset);
621 g_assert_not_reached();
628 /* Add an item to a proto_tree, using the text label registered to that item;
629 the item is extracted from the tvbuff handed to it. */
631 proto_tree_add_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
632 gint start, gint length, gboolean little_endian)
644 new_fi = alloc_field_info(tree, hfindex, tvb, start, &length);
649 /* there is a possibility here that we might raise an exception
650 * and thus would lose track of the field_info.
651 * store it in a temp so that if we come here again we can reclaim
652 * the field_info without leaking memory.
654 /* XXX this only keeps track of one field_info struct,
655 if we ever go multithreaded for calls to this function
656 we have to change this code to use per thread variable.
659 /* oops, last one we got must have been lost due
661 * good thing we saved it, now we can reverse the
662 * memory leak and reclaim it.
664 SLAB_FREE(field_info_tmp, field_info);
666 /* we might throw an exception, keep track of this one
667 * across the "dangerous" section below.
669 field_info_tmp=new_fi;
671 switch(new_fi->hfinfo->type) {
673 /* no value to set for FT_NONE */
677 proto_tree_set_protocol_tvb(new_fi, tvb);
681 proto_tree_set_bytes_tvb(new_fi, tvb, start, length);
685 n = get_uint_value(tvb, start, length, little_endian);
686 proto_tree_set_bytes_tvb(new_fi, tvb, start + length, n);
688 /* Instead of calling proto_item_set_len(), since we don't yet
689 * have a proto_item, we set the field_info's length ourselves. */
690 new_fi->length = n + length;
694 proto_tree_set_boolean(new_fi,
695 get_uint_value(tvb, start, length, little_endian));
698 /* XXX - make these just FT_UINT? */
703 proto_tree_set_uint(new_fi,
704 get_uint_value(tvb, start, length, little_endian));
709 g_assert(length == 8);
710 proto_tree_set_uint64_tvb(new_fi, tvb, start, little_endian);
713 /* XXX - make these just FT_INT? */
718 proto_tree_set_int(new_fi,
719 get_int_value(tvb, start, length, little_endian));
723 g_assert(length == 4);
724 tvb_memcpy(tvb, (guint8 *)&value, start, 4);
725 proto_tree_set_ipv4(new_fi, value);
729 g_assert(length == 4);
730 proto_tree_set_ipxnet(new_fi,
731 get_uint_value(tvb, start, 4, FALSE));
735 g_assert(length == 16);
736 proto_tree_set_ipv6_tvb(new_fi, tvb, start);
740 g_assert(length == 6);
741 proto_tree_set_ether_tvb(new_fi, tvb, start);
745 /* This g_strdup'ed memory is freed in proto_tree_free_node() */
746 proto_tree_set_string_tvb(new_fi, tvb, start, length);
750 if (length != 0) { /* XXX - Should we throw an exception instead? */
751 /* Instead of calling proto_item_set_len(),
752 * since we don't yet have a proto_item, we
753 * set the field_info's length ourselves.
755 * XXX - our caller can't use that length to
756 * advance an offset unless they arrange that
757 * there always be a protocol tree into which
758 * we're putting this item.
761 /* This can throw an exception */
762 length = tvb_strsize(tvb, start);
764 /* This g_malloc'ed memory is freed
765 in proto_tree_free_node() */
766 string = g_malloc(length);
768 tvb_memcpy(tvb, string, start, length);
769 new_fi->length = length;
772 /* In this case, length signifies
773 * the length of the string.
775 * This could either be a null-padded
776 * string, which doesn't necessarily
777 * have a '\0' at the end, or a
778 * null-terminated string, with a
779 * trailing '\0'. (Yes, there are
780 * cases where you have a string
781 * that's both counted and null-
784 * In the first case, we must
785 * allocate a buffer of length
786 * "length+1", to make room for
789 * In the second case, we don't
790 * assume that there is a trailing
791 * '\0' there, as the packet might
792 * be malformed. (XXX - should we
793 * throw an exception if there's no
794 * trailing '\0'?) Therefore, we
795 * allocate a buffer of length
796 * "length+1", and put in a trailing
797 * '\0', just to be safe.
799 * (XXX - this would change if
800 * we made string values counted
801 * rather than null-terminated.)
804 /* This g_malloc'ed memory is freed
805 * in proto_tree_free_node() */
806 string = tvb_get_string(tvb, start,
808 new_fi->length = length;
810 proto_tree_set_string(new_fi, string, TRUE);
815 /* This g_strdup'ed memory is freed in proto_tree_free_node() */
816 n = get_uint_value(tvb, start, length, little_endian);
817 proto_tree_set_string_tvb(new_fi, tvb, start + length, n);
819 /* Instead of calling proto_item_set_len(), since we
820 * don't yet have a proto_item, we set the
821 * field_info's length ourselves.
823 * XXX - our caller can't use that length to
824 * advance an offset unless they arrange that
825 * there always be a protocol tree into which
826 * we're putting this item.
828 new_fi->length = n + length;
832 g_error("new_fi->hfinfo->type %d (%s) not handled\n",
833 new_fi->hfinfo->type,
834 ftype_name(new_fi->hfinfo->type));
835 g_assert_not_reached();
839 /* Don't add new node to proto_tree until now so that any exceptions
840 * raised by a tvbuff access method doesn't leave junk in the proto_tree. */
841 pi = proto_tree_add_node(tree, new_fi);
843 /* we did not raise an exception so we dont have to remember this
844 * field_info struct any more.
848 /* If the proto_tree wants to keep a record of this finfo
849 * for quick lookup, then record it. */
850 hash = PTREE_DATA(tree)->interesting_hfids;
851 ptrs = g_hash_table_lookup(hash, GINT_TO_POINTER(hfindex));
853 g_ptr_array_add(ptrs, new_fi);
860 proto_tree_add_item_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb,
861 gint start, gint length, gboolean little_endian)
865 pi = proto_tree_add_item(tree, hfindex, tvb, start, length, little_endian);
869 PROTO_ITEM_SET_HIDDEN(pi);
875 /* Add a FT_NONE to a proto_tree */
877 proto_tree_add_none_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
878 gint length, const char *format, ...)
882 header_field_info *hfinfo;
887 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
888 g_assert(hfinfo->type == FT_NONE);
890 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, NULL);
892 va_start(ap, format);
893 proto_tree_set_representation(pi, format, ap);
896 /* no value to set for FT_NONE */
902 proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb)
904 fvalue_set(&fi->value, tvb, TRUE);
907 /* Add a FT_PROTOCOL to a proto_tree */
909 proto_tree_add_protocol_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
910 gint length, const char *format, ...)
914 header_field_info *hfinfo;
920 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
921 g_assert(hfinfo->type == FT_PROTOCOL);
923 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
925 va_start(ap, format);
926 proto_tree_set_representation(pi, format, ap);
930 proto_tree_set_protocol_tvb(new_fi, tvb);
933 proto_tree_set_protocol_tvb(new_fi, NULL);
939 /* Add a FT_BYTES to a proto_tree */
941 proto_tree_add_bytes(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
942 gint length, const guint8 *start_ptr)
946 header_field_info *hfinfo;
951 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
952 g_assert(hfinfo->type == FT_BYTES);
954 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
955 proto_tree_set_bytes(new_fi, start_ptr, length);
961 proto_tree_add_bytes_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
962 gint length, const guint8 *start_ptr)
966 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length, start_ptr);
970 PROTO_ITEM_SET_HIDDEN(pi);
976 proto_tree_add_bytes_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
977 gint length, const guint8 *start_ptr, const char *format, ...)
982 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length, start_ptr);
986 va_start(ap, format);
987 proto_tree_set_representation(pi, format, ap);
994 proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length)
998 bytes = g_byte_array_new();
1000 g_byte_array_append(bytes, start_ptr, length);
1002 fvalue_set(&fi->value, bytes, TRUE);
1007 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length)
1009 proto_tree_set_bytes(fi, tvb_get_ptr(tvb, offset, length), length);
1012 /* Add a FT_*TIME to a proto_tree */
1014 proto_tree_add_time(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1015 nstime_t *value_ptr)
1019 header_field_info *hfinfo;
1024 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1025 g_assert(hfinfo->type == FT_ABSOLUTE_TIME ||
1026 hfinfo->type == FT_RELATIVE_TIME);
1028 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1029 proto_tree_set_time(new_fi, value_ptr);
1035 proto_tree_add_time_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1036 nstime_t *value_ptr)
1040 pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
1044 PROTO_ITEM_SET_HIDDEN(pi);
1050 proto_tree_add_time_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1051 nstime_t *value_ptr, const char *format, ...)
1056 pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
1060 va_start(ap, format);
1061 proto_tree_set_representation(pi, format, ap);
1067 /* Set the FT_*TIME value */
1069 proto_tree_set_time(field_info *fi, nstime_t *value_ptr)
1071 fvalue_set(&fi->value, value_ptr, FALSE);
1074 /* Add a FT_IPXNET to a proto_tree */
1076 proto_tree_add_ipxnet(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1081 header_field_info *hfinfo;
1086 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1087 g_assert(hfinfo->type == FT_IPXNET);
1089 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1090 proto_tree_set_ipxnet(new_fi, value);
1096 proto_tree_add_ipxnet_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1101 pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
1105 PROTO_ITEM_SET_HIDDEN(pi);
1111 proto_tree_add_ipxnet_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1112 guint32 value, const char *format, ...)
1117 pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
1121 va_start(ap, format);
1122 proto_tree_set_representation(pi, format, ap);
1128 /* Set the FT_IPXNET value */
1130 proto_tree_set_ipxnet(field_info *fi, guint32 value)
1132 fvalue_set_integer(&fi->value, value);
1135 /* Add a FT_IPv4 to a proto_tree */
1137 proto_tree_add_ipv4(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1142 header_field_info *hfinfo;
1147 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1148 g_assert(hfinfo->type == FT_IPv4);
1150 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1151 proto_tree_set_ipv4(new_fi, value);
1157 proto_tree_add_ipv4_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1162 pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
1166 PROTO_ITEM_SET_HIDDEN(pi);
1172 proto_tree_add_ipv4_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1173 guint32 value, const char *format, ...)
1178 pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
1182 va_start(ap, format);
1183 proto_tree_set_representation(pi, format, ap);
1189 /* Set the FT_IPv4 value */
1191 proto_tree_set_ipv4(field_info *fi, guint32 value)
1193 fvalue_set_integer(&fi->value, value);
1196 /* Add a FT_IPv6 to a proto_tree */
1198 proto_tree_add_ipv6(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1199 const guint8* value_ptr)
1203 header_field_info *hfinfo;
1208 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1209 g_assert(hfinfo->type == FT_IPv6);
1211 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1212 proto_tree_set_ipv6(new_fi, value_ptr);
1218 proto_tree_add_ipv6_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1219 const guint8* value_ptr)
1223 pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
1227 PROTO_ITEM_SET_HIDDEN(pi);
1233 proto_tree_add_ipv6_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1234 const guint8* value_ptr, const char *format, ...)
1239 pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
1243 va_start(ap, format);
1244 proto_tree_set_representation(pi, format, ap);
1250 /* Set the FT_IPv6 value */
1252 proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr)
1254 fvalue_set(&fi->value, (gpointer) value_ptr, FALSE);
1258 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start)
1260 proto_tree_set_ipv6(fi, tvb_get_ptr(tvb, start, 16));
1264 proto_tree_set_uint64(field_info *fi, const guint8 *value_ptr, gboolean little_endian)
1267 unsigned char buffer[8];
1271 buffer[i]=value_ptr[7-i];
1273 fvalue_set(&fi->value, (gpointer)buffer, FALSE);
1275 fvalue_set(&fi->value, (gpointer)value_ptr, FALSE);
1280 proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start, gboolean little_endian)
1282 proto_tree_set_uint64(fi, tvb_get_ptr(tvb, start, 8), little_endian);
1285 /* Add a FT_STRING or FT_STRINGZ to a proto_tree. Creates own copy of string,
1286 * and frees it when the proto_tree is destroyed. */
1288 proto_tree_add_string(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1289 gint length, const char* value)
1293 header_field_info *hfinfo;
1298 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1299 g_assert(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ);
1301 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1302 proto_tree_set_string(new_fi, value, FALSE);
1308 proto_tree_add_string_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1309 gint length, const char* value)
1313 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
1317 PROTO_ITEM_SET_HIDDEN(pi);
1323 proto_tree_add_string_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1324 gint length, const char* value, const char *format, ...)
1329 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
1333 va_start(ap, format);
1334 proto_tree_set_representation(pi, format, ap);
1340 /* Appends string data to a FT_STRING or FT_STRINGZ, allowing progressive
1341 * field info update instead of only updating the representation as does
1342 * proto_item_append_text()
1345 proto_item_append_string(proto_item *pi, const char *str)
1348 header_field_info *hfinfo;
1349 gchar *old_str, *new_str;
1356 fi = PITEM_FINFO(pi);
1357 hfinfo = fi->hfinfo;
1358 g_assert(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ);
1359 old_str = fvalue_get(&fi->value);
1360 new_str = g_malloc(strlen(old_str) + strlen(str) + 1);
1361 sprintf(new_str, "%s%s", old_str, str);
1362 fvalue_set(&fi->value, new_str, TRUE);
1365 /* Set the FT_STRING value */
1367 proto_tree_set_string(field_info *fi, const char* value,
1368 gboolean already_allocated)
1370 fvalue_set(&fi->value, (gpointer) value, already_allocated);
1374 proto_tree_set_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
1379 length = tvb_ensure_length_remaining(tvb, start);
1382 /* This memory is freed in proto_tree_free_node() */
1383 string = tvb_get_string(tvb, start, length);
1384 proto_tree_set_string(fi, string, TRUE);
1387 /* Add a FT_ETHER to a proto_tree */
1389 proto_tree_add_ether(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1390 const guint8* value)
1394 header_field_info *hfinfo;
1399 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1400 g_assert(hfinfo->type == FT_ETHER);
1402 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1403 proto_tree_set_ether(new_fi, value);
1409 proto_tree_add_ether_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1410 const guint8* value)
1414 pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
1418 PROTO_ITEM_SET_HIDDEN(pi);
1424 proto_tree_add_ether_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1425 const guint8* value, const char *format, ...)
1430 pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
1434 va_start(ap, format);
1435 proto_tree_set_representation(pi, format, ap);
1441 /* Set the FT_ETHER value */
1443 proto_tree_set_ether(field_info *fi, const guint8* value)
1445 fvalue_set(&fi->value, (gpointer) value, FALSE);
1449 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start)
1451 proto_tree_set_ether(fi, tvb_get_ptr(tvb, start, 6));
1454 /* Add a FT_BOOLEAN to a proto_tree */
1456 proto_tree_add_boolean(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1461 header_field_info *hfinfo;
1466 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1467 g_assert(hfinfo->type == FT_BOOLEAN);
1469 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1470 proto_tree_set_boolean(new_fi, value);
1476 proto_tree_add_boolean_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1481 pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
1485 PROTO_ITEM_SET_HIDDEN(pi);
1491 proto_tree_add_boolean_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1492 guint32 value, const char *format, ...)
1497 pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
1501 va_start(ap, format);
1502 proto_tree_set_representation(pi, format, ap);
1508 /* Set the FT_BOOLEAN value */
1510 proto_tree_set_boolean(field_info *fi, guint32 value)
1512 proto_tree_set_uint(fi, value);
1515 /* Add a FT_FLOAT to a proto_tree */
1517 proto_tree_add_float(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1522 header_field_info *hfinfo;
1527 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1528 g_assert(hfinfo->type == FT_FLOAT);
1530 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1531 proto_tree_set_float(new_fi, value);
1537 proto_tree_add_float_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1542 pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
1546 PROTO_ITEM_SET_HIDDEN(pi);
1552 proto_tree_add_float_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1553 float value, const char *format, ...)
1558 pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
1562 va_start(ap, format);
1563 proto_tree_set_representation(pi, format, ap);
1569 /* Set the FT_FLOAT value */
1571 proto_tree_set_float(field_info *fi, float value)
1573 fvalue_set_floating(&fi->value, value);
1576 /* Add a FT_DOUBLE to a proto_tree */
1578 proto_tree_add_double(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1583 header_field_info *hfinfo;
1588 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1589 g_assert(hfinfo->type == FT_DOUBLE);
1591 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1592 proto_tree_set_double(new_fi, value);
1598 proto_tree_add_double_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1603 pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
1607 PROTO_ITEM_SET_HIDDEN(pi);
1613 proto_tree_add_double_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1614 double value, const char *format, ...)
1619 pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
1623 va_start(ap, format);
1624 proto_tree_set_representation(pi, format, ap);
1630 /* Set the FT_DOUBLE value */
1632 proto_tree_set_double(field_info *fi, double value)
1634 fvalue_set_floating(&fi->value, value);
1637 /* Add any FT_UINT* to a proto_tree */
1639 proto_tree_add_uint(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1642 proto_item *pi = NULL;
1644 header_field_info *hfinfo;
1649 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1650 switch(hfinfo->type) {
1656 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length,
1658 proto_tree_set_uint(new_fi, value);
1662 g_assert_not_reached();
1669 proto_tree_add_uint_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1674 pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
1678 PROTO_ITEM_SET_HIDDEN(pi);
1684 proto_tree_add_uint_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1685 guint32 value, const char *format, ...)
1690 pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
1694 va_start(ap, format);
1695 proto_tree_set_representation(pi, format, ap);
1701 /* Set the FT_UINT* value */
1703 proto_tree_set_uint(field_info *fi, guint32 value)
1705 header_field_info *hfinfo;
1708 hfinfo = fi->hfinfo;
1711 if (hfinfo->bitmask) {
1712 /* Mask out irrelevant portions */
1713 integer &= hfinfo->bitmask;
1716 if (hfinfo->bitshift > 0) {
1717 integer >>= hfinfo->bitshift;
1720 fvalue_set_integer(&fi->value, integer);
1723 /* Add any FT_INT* to a proto_tree */
1725 proto_tree_add_int(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1728 proto_item *pi = NULL;
1730 header_field_info *hfinfo;
1735 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1736 switch(hfinfo->type) {
1741 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length,
1743 proto_tree_set_int(new_fi, value);
1747 g_assert_not_reached();
1754 proto_tree_add_int_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1759 pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
1763 PROTO_ITEM_SET_HIDDEN(pi);
1769 proto_tree_add_int_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1770 gint32 value, const char *format, ...)
1772 proto_item *pi = NULL;
1775 pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
1779 va_start(ap, format);
1780 proto_tree_set_representation(pi, format, ap);
1786 /* Set the FT_INT* value */
1788 proto_tree_set_int(field_info *fi, gint32 value)
1790 header_field_info *hfinfo;
1793 hfinfo = fi->hfinfo;
1794 integer = (guint32) value;
1796 if (hfinfo->bitmask) {
1797 /* Mask out irrelevant portions */
1798 integer &= hfinfo->bitmask;
1801 if (hfinfo->bitshift > 0) {
1802 integer >>= hfinfo->bitshift;
1805 fvalue_set_integer(&fi->value, integer);
1809 /* Add a field_info struct to the proto_tree, encapsulating it in a proto_node */
1811 proto_tree_add_node(proto_tree *tree, field_info *fi)
1813 proto_node *pnode, *tnode, *sibling;
1817 * Make sure "tree" is ready to have subtrees under it, by
1818 * checking whether it's been given an ett_ value.
1820 * "tnode->finfo" may be null; that's the case for the root
1821 * node of the protocol tree. That node is not displayed,
1822 * so it doesn't need an ett_ value to remember whether it
1827 g_assert(tfi == NULL ||
1828 (tfi->tree_type >= 0 && tfi->tree_type < num_tree_types));
1830 PROTO_NODE_NEW(pnode);
1831 pnode->parent = tnode;
1833 pnode->tree_data = PTREE_DATA(tree);
1835 if (tnode->last_child != NULL) {
1836 sibling = tnode->last_child;
1837 g_assert(sibling->next == NULL);
1838 sibling->next = pnode;
1840 tnode->first_child = pnode;
1841 tnode->last_child = pnode;
1843 return (proto_item*)pnode;
1847 /* Generic way to allocate field_info and add to proto_tree.
1848 * Sets *pfi to address of newly-allocated field_info struct, if pfi is
1851 proto_tree_add_pi(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1852 gint *length, field_info **pfi)
1862 fi = alloc_field_info(tree, hfindex, tvb, start, length);
1863 pi = proto_tree_add_node(tree, fi);
1865 /* If the proto_tree wants to keep a record of this finfo
1866 * for quick lookup, then record it. */
1867 hash = PTREE_DATA(tree)->interesting_hfids;
1868 ptrs = g_hash_table_lookup(hash, GINT_TO_POINTER(hfindex));
1870 g_ptr_array_add(ptrs, fi);
1873 /* Does the caller want to know the fi pointer? */
1882 alloc_field_info(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1885 header_field_info *hfinfo;
1889 * We only allow a null tvbuff if the item has a zero length,
1890 * i.e. if there's no data backing it.
1892 g_assert(tvb != NULL || *length == 0);
1894 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1896 if (*length == -1) {
1898 * For FT_NONE, FT_PROTOCOL, FT_BYTES, and FT_STRING fields,
1899 * a length of -1 means "set the length to what remains in
1902 * The assumption is either that
1904 * 1) the length of the item can only be determined
1905 * by dissection (typically true of items with
1906 * subitems, which are probably FT_NONE or
1911 * 2) if the tvbuff is "short" (either due to a short
1912 * snapshot length or due to lack of reassembly of
1913 * fragments/segments/whatever), we want to display
1914 * what's available in the field (probably FT_BYTES
1915 * or FT_STRING) and then throw an exception later
1919 * 3) the field is defined to be "what's left in the
1922 * so we set the length to what remains in the tvbuff so
1923 * that, if we throw an exception while dissecting, it
1924 * has what is probably the right value.
1926 * For FT_STRINGZ, it means "the string is null-terminated,
1927 * not null-padded; set the length to the actual length
1928 * of the string", and if the tvbuff if short, we just
1929 * throw an exception.
1931 * It's not valid for any other type of field.
1933 switch (hfinfo->type) {
1937 * We allow this to be zero-length - for
1938 * example, an ONC RPC NULL procedure has
1939 * neither arguments nor reply, so the
1940 * payload for that protocol is empty.
1942 * However, if the length is negative, the
1943 * start offset is *past* the byte past the
1944 * end of the tvbuff, so we throw an
1947 *length = tvb_length_remaining(tvb, start);
1950 * Use "tvb_ensure_bytes_exist()"
1951 * to force the appropriate exception
1954 tvb_ensure_bytes_exist(tvb, start, 0);
1961 *length = tvb_ensure_length_remaining(tvb, start);
1966 * Leave the length as -1, so our caller knows
1972 g_assert_not_reached();
1978 fi->hfinfo = hfinfo;
1980 fi->start+=(tvb)?TVB_RAW_OFFSET(tvb):0;
1981 fi->length = *length;
1984 if(!PTREE_DATA(tree)->visible) {
1985 FI_SET_FLAG(fi, FI_HIDDEN);
1987 fvalue_init(&fi->value, fi->hfinfo->type);
1990 /* add the data source tvbuff */
1991 fi->ds_tvb=tvb?TVB_GET_DS_TVB(tvb):NULL;
1996 /* Set representation of a proto_tree entry, if the protocol tree is to
1999 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap)
2001 int ret; /*tmp return value */
2002 field_info *fi = PITEM_FINFO(pi);
2004 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
2005 ITEM_LABEL_NEW(fi->rep);
2006 ret = vsnprintf(fi->rep->representation, ITEM_LABEL_LENGTH, format, ap);
2007 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
2008 fi->rep->representation[ITEM_LABEL_LENGTH - 1] = '\0';
2012 /* Set text of proto_item after having already been created. */
2014 proto_item_set_text(proto_item *pi, const char *format, ...)
2016 field_info *fi = NULL;
2023 fi = PITEM_FINFO(pi);
2026 ITEM_LABEL_FREE(fi->rep);
2029 va_start(ap, format);
2030 proto_tree_set_representation(pi, format, ap);
2034 /* Append to text of proto_item after having already been created. */
2036 proto_item_append_text(proto_item *pi, const char *format, ...)
2038 field_info *fi = NULL;
2041 int ret; /*tmp return value */
2047 fi = PITEM_FINFO(pi);
2049 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
2050 va_start(ap, format);
2053 * If we don't already have a representation,
2054 * generate the default representation.
2056 if (fi->rep == NULL) {
2057 ITEM_LABEL_NEW(fi->rep);
2058 proto_item_fill_label(fi, fi->rep->representation);
2061 curlen = strlen(fi->rep->representation);
2062 if (ITEM_LABEL_LENGTH > curlen) {
2063 ret = vsnprintf(fi->rep->representation + curlen,
2064 ITEM_LABEL_LENGTH - curlen, format, ap);
2065 if ((ret == -1) || (ret >= (int)(ITEM_LABEL_LENGTH - curlen)))
2066 fi->rep->representation[ITEM_LABEL_LENGTH - 1] = '\0';
2073 proto_item_set_len(proto_item *pi, gint length)
2079 fi = PITEM_FINFO(pi);
2080 fi->length = length;
2084 * Sets the length of the item based on its start and on the specified
2085 * offset, which is the offset past the end of the item; as the start
2086 * in the item is relative to the beginning of the data source tvbuff,
2087 * we need to pass in a tvbuff - the end offset is relative to the beginning
2091 proto_item_set_end(proto_item *pi, tvbuff_t *tvb, gint end)
2097 fi = PITEM_FINFO(pi);
2098 end += TVB_RAW_OFFSET(tvb);
2099 fi->length = end - fi->start;
2103 proto_item_get_len(proto_item *pi)
2105 field_info *fi = PITEM_FINFO(pi);
2110 proto_tree_create_root(void)
2114 /* Initialize the proto_node */
2115 PROTO_NODE_NEW(pnode);
2116 pnode->parent = NULL;
2117 pnode->finfo = NULL;
2118 pnode->tree_data = g_new(tree_data_t, 1);
2120 /* Initialize the tree_data_t */
2121 pnode->tree_data->interesting_hfids =
2122 g_hash_table_new(g_direct_hash, g_direct_equal);
2124 /* Set the default to FALSE so it's easier to
2125 * find errors; if we expect to see the protocol tree
2126 * but for some reason the default 'visible' is not
2127 * changed, then we'll find out very quickly. */
2128 pnode->tree_data->visible = FALSE;
2130 return (proto_tree*) pnode;
2134 /* "prime" a proto_tree with a single hfid that a dfilter
2135 * is interested in. */
2137 proto_tree_prime_hfid(proto_tree *tree, gint hfid)
2139 g_hash_table_insert(PTREE_DATA(tree)->interesting_hfids,
2140 GINT_TO_POINTER(hfid), g_ptr_array_new());
2145 proto_item_add_subtree(proto_item *pi, gint idx) {
2151 fi = PITEM_FINFO(pi);
2152 g_assert(idx >= 0 && idx < num_tree_types);
2153 fi->tree_type = idx;
2154 return (proto_tree*) pi;
2158 proto_item_get_subtree(proto_item *pi) {
2163 fi = PITEM_FINFO(pi);
2164 if (fi->tree_type == -1)
2166 return (proto_tree*) pi;
2170 proto_item_get_parent(proto_item *ti) {
2177 proto_item_get_parent_nth(proto_item *ti, int gen) {
2190 proto_tree_get_parent(proto_tree *tree) {
2193 return (proto_item*) tree;
2197 proto_match_short_name(gconstpointer p_arg, gconstpointer name_arg)
2199 const protocol_t *p = p_arg;
2200 const char *name = name_arg;
2202 return g_strcasecmp(p->short_name, name);
2206 proto_match_name(gconstpointer p_arg, gconstpointer name_arg)
2208 const protocol_t *p = p_arg;
2209 const char *name = name_arg;
2211 return g_strcasecmp(p->name, name);
2215 proto_match_filter_name(gconstpointer p_arg, gconstpointer name_arg)
2217 const protocol_t *p = p_arg;
2218 const char *name = name_arg;
2220 return g_strcasecmp(p->filter_name, name);
2224 proto_compare_name(gconstpointer p1_arg, gconstpointer p2_arg)
2226 const protocol_t *p1 = p1_arg;
2227 const protocol_t *p2 = p2_arg;
2229 return g_strcasecmp(p1->short_name, p2->short_name);
2233 proto_register_protocol(char *name, char *short_name, char *filter_name)
2235 protocol_t *protocol;
2236 header_field_info *hfinfo;
2240 * Make sure there's not already a protocol with any of those
2241 * names. Crash if there is, as that's an error in the code,
2242 * and the code has to be fixed not to register more than one
2243 * protocol with the same name.
2245 g_assert(g_list_find_custom(protocols, name, proto_match_name) == NULL);
2246 g_assert(g_list_find_custom(protocols, short_name, proto_match_short_name) == NULL);
2247 g_assert(g_list_find_custom(protocols, filter_name, proto_match_filter_name) == NULL);
2249 /* Add this protocol to the list of known protocols; the list
2250 is sorted by protocol short name. */
2251 protocol = g_malloc(sizeof (protocol_t));
2252 protocol->name = name;
2253 protocol->short_name = short_name;
2254 protocol->filter_name = filter_name;
2255 protocol->fields = NULL;
2256 protocol->is_enabled = TRUE; /* protocol is enabled by default */
2257 protocol->can_toggle = TRUE;
2258 protocols = g_list_insert_sorted(protocols, protocol,
2259 proto_compare_name);
2261 /* Here we do allocate a new header_field_info struct */
2262 hfinfo = g_mem_chunk_alloc(gmc_hfinfo);
2263 hfinfo->name = name;
2264 hfinfo->abbrev = filter_name;
2265 hfinfo->type = FT_PROTOCOL;
2266 hfinfo->strings = NULL;
2267 hfinfo->bitmask = 0;
2268 hfinfo->bitshift = 0;
2270 hfinfo->parent = -1; /* this field differentiates protos and fields */
2272 proto_id = proto_register_field_init(hfinfo, hfinfo->parent);
2273 protocol->proto_id = proto_id;
2278 * Routines to use to iterate over the protocols.
2279 * The argument passed to the iterator routines is an opaque cookie to
2280 * their callers; it's the GList pointer for the current element in
2282 * The ID of the protocol is returned, or -1 if there is no protocol.
2285 proto_get_first_protocol(void **cookie)
2287 protocol_t *protocol;
2289 if (protocols == NULL)
2291 *cookie = protocols;
2292 protocol = protocols->data;
2293 return protocol->proto_id;
2297 proto_get_next_protocol(void **cookie)
2299 GList *list_item = *cookie;
2300 protocol_t *protocol;
2302 list_item = g_list_next(list_item);
2303 if (list_item == NULL)
2305 *cookie = list_item;
2306 protocol = list_item->data;
2307 return protocol->proto_id;
2311 proto_get_first_protocol_field(int proto_id, void **cookie)
2313 protocol_t *protocol = find_protocol_by_id(proto_id);
2314 hf_register_info *ptr;
2316 if ((protocol == NULL) || (protocol->fields == NULL))
2319 *cookie = protocol->fields;
2320 ptr = protocol->fields->data;
2321 return &ptr->hfinfo;
2325 proto_get_next_protocol_field(void **cookie)
2327 GList *list_item = *cookie;
2328 hf_register_info *ptr;
2330 list_item = g_list_next(list_item);
2331 if (list_item == NULL)
2334 *cookie = list_item;
2335 ptr = list_item->data;
2336 return &ptr->hfinfo;
2340 * Find the protocol list entry for a protocol given its field ID.
2343 compare_proto_id(gconstpointer proto_arg, gconstpointer id_arg)
2345 const protocol_t *protocol = proto_arg;
2346 const int *id_ptr = id_arg;
2348 return (protocol->proto_id == *id_ptr) ? 0 : 1;
2352 find_protocol_by_id(int proto_id)
2356 list_entry = g_list_find_custom(protocols, &proto_id, compare_proto_id);
2357 if (list_entry == NULL)
2359 return list_entry->data;
2362 static gint compare_filter_name(gconstpointer proto_arg,
2363 gconstpointer filter_name)
2365 const protocol_t *protocol = proto_arg;
2366 const gchar* f_name = filter_name;
2368 return (strcmp(protocol->filter_name, f_name));
2372 proto_get_id(protocol_t *protocol)
2374 return protocol->proto_id;
2377 int proto_get_id_by_filter_name(gchar* filter_name)
2380 protocol_t *protocol;
2382 list_entry = g_list_find_custom(protocols, filter_name,
2383 compare_filter_name);
2384 if (list_entry == NULL)
2386 protocol = list_entry->data;
2387 return protocol->proto_id;
2391 proto_get_protocol_name(int proto_id)
2393 protocol_t *protocol;
2395 protocol = find_protocol_by_id(proto_id);
2396 return protocol->name;
2400 proto_get_protocol_short_name(protocol_t *protocol)
2402 if (protocol == NULL)
2404 return protocol->short_name;
2408 proto_get_protocol_filter_name(int proto_id)
2410 protocol_t *protocol;
2412 protocol = find_protocol_by_id(proto_id);
2413 return protocol->filter_name;
2417 proto_is_protocol_enabled(protocol_t *protocol)
2419 return protocol->is_enabled;
2423 proto_can_toggle_protocol(int proto_id)
2425 protocol_t *protocol;
2427 protocol = find_protocol_by_id(proto_id);
2428 return protocol->can_toggle;
2432 proto_set_decoding(int proto_id, gboolean enabled)
2434 protocol_t *protocol;
2436 protocol = find_protocol_by_id(proto_id);
2437 g_assert(protocol->can_toggle);
2438 protocol->is_enabled = enabled;
2442 proto_set_cant_toggle(int proto_id)
2444 protocol_t *protocol;
2446 protocol = find_protocol_by_id(proto_id);
2447 protocol->can_toggle = FALSE;
2450 /* for use with static arrays only, since we don't allocate our own copies
2451 of the header_field_info struct contained within the hf_register_info struct */
2453 proto_register_field_array(int parent, hf_register_info *hf, int num_records)
2456 hf_register_info *ptr = hf;
2459 proto = find_protocol_by_id(parent);
2460 for (i = 0; i < num_records; i++, ptr++) {
2462 * Make sure we haven't registed this yet.
2463 * Most fields have variables associated with them
2464 * that are initialized to -1; some have array elements,
2465 * or possibly uninitialized variables, so we also allow
2466 * 0 (which is unlikely to be the field ID we get back
2467 * from "proto_register_field_init()").
2469 g_assert(*ptr->p_id == -1 || *ptr->p_id == 0);
2471 if (proto != NULL) {
2472 if (proto->fields == NULL) {
2473 proto->fields = g_list_append(NULL, ptr);
2474 proto->last_field = proto->fields;
2477 g_list_append(proto->last_field, ptr)->next;
2480 field_id = proto_register_field_init(&ptr->hfinfo, parent);
2481 *ptr->p_id = field_id;
2486 proto_register_field_init(header_field_info *hfinfo, int parent)
2488 /* The field must have names */
2489 g_assert(hfinfo->name);
2490 g_assert(hfinfo->abbrev);
2492 /* These types of fields are allowed to have value_strings or true_false_strings */
2493 g_assert((hfinfo->strings == NULL) || (
2494 (hfinfo->type == FT_UINT8) ||
2495 (hfinfo->type == FT_UINT16) ||
2496 (hfinfo->type == FT_UINT24) ||
2497 (hfinfo->type == FT_UINT32) ||
2498 (hfinfo->type == FT_INT8) ||
2499 (hfinfo->type == FT_INT16) ||
2500 (hfinfo->type == FT_INT24) ||
2501 (hfinfo->type == FT_INT32) ||
2502 (hfinfo->type == FT_BOOLEAN) ||
2503 (hfinfo->type == FT_FRAMENUM) ));
2505 switch (hfinfo->type) {
2515 /* Require integral types (other than frame number, which is
2516 always displayed in decimal) to have a number base */
2517 g_assert(hfinfo->display != BASE_NONE);
2521 /* Don't allow bitfields or value strings for frame numbers */
2522 g_assert(hfinfo->bitmask == 0);
2523 g_assert(hfinfo->strings == NULL);
2529 /* if this is a bitfield, compute bitshift */
2530 if (hfinfo->bitmask) {
2531 while ((hfinfo->bitmask & (1 << hfinfo->bitshift)) == 0)
2535 hfinfo->parent = parent;
2536 hfinfo->same_name_next = NULL;
2537 hfinfo->same_name_prev = NULL;
2539 /* if we always add and never delete, then id == len - 1 is correct */
2540 if(gpa_hfinfo.len>=gpa_hfinfo.allocated_len){
2541 if(!gpa_hfinfo.hfi){
2542 gpa_hfinfo.allocated_len=1000;
2543 gpa_hfinfo.hfi=g_malloc(sizeof(header_field_info *)*1000);
2545 gpa_hfinfo.allocated_len+=1000;
2546 gpa_hfinfo.hfi=g_realloc(gpa_hfinfo.hfi, sizeof(header_field_info *)*gpa_hfinfo.allocated_len);
2549 gpa_hfinfo.hfi[gpa_hfinfo.len]=hfinfo;
2551 hfinfo->id = gpa_hfinfo.len - 1;
2553 /* if we have real names, enter this field in the name tree */
2554 if ((hfinfo->name[0] != 0) && (hfinfo->abbrev[0] != 0 )) {
2556 header_field_info *same_name_hfinfo, *same_name_next_hfinfo;
2560 /* Check that the filter name (abbreviation) is legal;
2561 * it must contain only alphanumerics, '-', "_", and ".". */
2562 for (p = hfinfo->abbrev; (c = *p) != '\0'; p++)
2563 g_assert(isalnum(c) || c == '-' || c == '_' ||
2566 /* We allow multiple hfinfo's to be registered under the same
2567 * abbreviation. This was done for X.25, as, depending
2568 * on whether it's modulo-8 or modulo-128 operation,
2569 * some bitfield fields may be in different bits of
2570 * a byte, and we want to be able to refer to that field
2571 * with one name regardless of whether the packets
2572 * are modulo-8 or modulo-128 packets. */
2573 same_name_hfinfo = g_tree_lookup(gpa_name_tree, hfinfo->abbrev);
2574 if (same_name_hfinfo) {
2575 /* There's already a field with this name.
2576 * Put it after that field in the list of
2577 * fields with this name, then allow the code
2578 * after this if{} block to replace the old
2579 * hfinfo with the new hfinfo in the GTree. Thus,
2580 * we end up with a linked-list of same-named hfinfo's,
2581 * with the root of the list being the hfinfo in the GTree */
2582 same_name_next_hfinfo =
2583 same_name_hfinfo->same_name_next;
2585 hfinfo->same_name_next = same_name_next_hfinfo;
2586 if (same_name_next_hfinfo)
2587 same_name_next_hfinfo->same_name_prev = hfinfo;
2589 same_name_hfinfo->same_name_next = hfinfo;
2590 hfinfo->same_name_prev = same_name_hfinfo;
2592 g_tree_insert(gpa_name_tree, hfinfo->abbrev, hfinfo);
2599 proto_register_subtree_array(gint **indices, int num_indices)
2602 gint **ptr = indices;
2605 * Make sure we haven't already allocated the array of "tree is
2608 * XXX - if it's *really* important to allow more ett_ values to
2609 * be given out after "proto_init()" is called, we could expand
2612 g_assert(tree_is_expanded == NULL);
2615 * Assign "num_indices" subtree numbers starting at "num_tree_types",
2616 * returning the indices through the pointers in the array whose
2617 * first element is pointed to by "indices", and update
2618 * "num_tree_types" appropriately.
2620 for (i = 0; i < num_indices; i++, ptr++, num_tree_types++)
2621 **ptr = num_tree_types;
2625 proto_item_fill_label(field_info *fi, gchar *label_str)
2627 header_field_info *hfinfo = fi->hfinfo;
2632 guint32 n_addr; /* network-order IPv4 address */
2633 int ret; /*tmp return value */
2635 switch(hfinfo->type) {
2638 ret = snprintf(label_str, ITEM_LABEL_LENGTH,
2639 "%s", hfinfo->name);
2640 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
2641 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
2645 fill_label_boolean(fi, label_str);
2650 bytes = fvalue_get(&fi->value);
2652 ret = snprintf(label_str, ITEM_LABEL_LENGTH,
2653 "%s: %s", hfinfo->name,
2654 bytes_to_str(bytes, fvalue_length(&fi->value)));
2655 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
2656 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
2659 ret = snprintf(label_str, ITEM_LABEL_LENGTH,
2660 "%s: <MISSING>", hfinfo->name);
2661 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
2662 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
2666 /* Four types of integers to take care of:
2667 * Bitfield, with val_string
2668 * Bitfield, w/o val_string
2669 * Non-bitfield, with val_string
2670 * Non-bitfield, w/o val_string
2677 if (hfinfo->bitmask) {
2678 if (hfinfo->strings) {
2679 fill_label_enumerated_bitfield(fi, label_str);
2682 fill_label_numeric_bitfield(fi, label_str);
2686 if (hfinfo->strings) {
2687 fill_label_enumerated_uint(fi, label_str);
2690 fill_label_uint(fi, label_str);
2696 fill_label_uint64(fi, label_str);
2703 g_assert(!hfinfo->bitmask);
2704 if (hfinfo->strings) {
2705 fill_label_enumerated_int(fi, label_str);
2708 fill_label_int(fi, label_str);
2713 fill_label_int64(fi, label_str);
2717 ret = snprintf(label_str, ITEM_LABEL_LENGTH,
2718 "%s: %." STRINGIFY(FLT_DIG) "f",
2719 hfinfo->name, fvalue_get_floating(&fi->value));
2720 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
2721 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
2725 ret = snprintf(label_str, ITEM_LABEL_LENGTH,
2726 "%s: %." STRINGIFY(DBL_DIG) "g",
2727 hfinfo->name, fvalue_get_floating(&fi->value));
2728 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
2729 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
2732 case FT_ABSOLUTE_TIME:
2733 ret = snprintf(label_str, ITEM_LABEL_LENGTH,
2734 "%s: %s", hfinfo->name,
2735 abs_time_to_str(fvalue_get(&fi->value)));
2736 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
2737 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
2740 case FT_RELATIVE_TIME:
2741 ret = snprintf(label_str, ITEM_LABEL_LENGTH,
2742 "%s: %s seconds", hfinfo->name,
2743 rel_time_to_secs_str(fvalue_get(&fi->value)));
2744 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
2745 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
2749 integer = fvalue_get_integer(&fi->value);
2750 ret = snprintf(label_str, ITEM_LABEL_LENGTH,
2751 "%s: 0x%08X (%s)", hfinfo->name,
2752 integer, get_ipxnet_name(integer));
2753 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
2754 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
2758 bytes = fvalue_get(&fi->value);
2759 ret = snprintf(label_str, ITEM_LABEL_LENGTH,
2760 "%s: %s (%s)", hfinfo->name,
2761 ether_to_str(bytes),
2762 get_ether_name(bytes));
2763 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
2764 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
2768 ipv4 = fvalue_get(&fi->value);
2769 n_addr = ipv4_get_net_order_addr(ipv4);
2770 ret = snprintf(label_str, ITEM_LABEL_LENGTH,
2771 "%s: %s (%s)", hfinfo->name,
2772 get_hostname(n_addr),
2773 ip_to_str((guint8*)&n_addr));
2774 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
2775 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
2779 bytes = fvalue_get(&fi->value);
2780 ret = snprintf(label_str, ITEM_LABEL_LENGTH,
2781 "%s: %s (%s)", hfinfo->name,
2782 get_hostname6((struct e_in6_addr *)bytes),
2783 ip6_to_str((struct e_in6_addr*)bytes));
2784 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
2785 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
2790 case FT_UINT_STRING:
2791 bytes = fvalue_get(&fi->value);
2792 ret = snprintf(label_str, ITEM_LABEL_LENGTH,
2793 "%s: %s", hfinfo->name,
2794 format_text(bytes, strlen(bytes)));
2795 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
2796 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
2800 g_error("hfinfo->type %d (%s) not handled\n",
2802 ftype_name(hfinfo->type));
2803 g_assert_not_reached();
2809 fill_label_uint64(field_info *fi, gchar *label_str)
2811 unsigned char *bytes;
2812 header_field_info *hfinfo = fi->hfinfo;
2813 int ret; /*tmp return value */
2815 bytes=fvalue_get(&fi->value);
2816 switch(hfinfo->display){
2818 ret = snprintf(label_str, ITEM_LABEL_LENGTH,
2819 "%s: %s", hfinfo->name,
2821 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
2822 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
2825 ret = snprintf(label_str, ITEM_LABEL_LENGTH,
2826 "%s: %s", hfinfo->name,
2828 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
2829 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
2832 g_assert_not_reached();
2838 fill_label_int64(field_info *fi, gchar *label_str)
2840 unsigned char *bytes;
2841 header_field_info *hfinfo = fi->hfinfo;
2842 int ret; /*tmp return value */
2844 bytes=fvalue_get(&fi->value);
2845 switch(hfinfo->display){
2847 ret = snprintf(label_str, ITEM_LABEL_LENGTH,
2848 "%s: %s", hfinfo->name,
2850 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
2851 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
2854 ret = snprintf(label_str, ITEM_LABEL_LENGTH,
2855 "%s: %s", hfinfo->name,
2857 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
2858 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
2861 g_assert_not_reached();
2867 fill_label_boolean(field_info *fi, gchar *label_str)
2869 char *p = label_str;
2870 int bitfield_byte_length = 0, bitwidth;
2871 guint32 unshifted_value;
2873 int ret; /*tmp return value */
2875 header_field_info *hfinfo = fi->hfinfo;
2876 static const true_false_string default_tf = { "True", "False" };
2877 const true_false_string *tfstring = &default_tf;
2879 if (hfinfo->strings) {
2880 tfstring = (const struct true_false_string*) hfinfo->strings;
2883 value = fvalue_get_integer(&fi->value);
2884 if (hfinfo->bitmask) {
2885 /* Figure out the bit width */
2886 bitwidth = hfinfo_bitwidth(hfinfo);
2889 unshifted_value = value;
2890 if (hfinfo->bitshift > 0) {
2891 unshifted_value <<= hfinfo->bitshift;
2894 /* Create the bitfield first */
2895 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
2896 bitfield_byte_length = p - label_str;
2899 /* Fill in the textual info */
2900 ret = snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
2901 "%s: %s", hfinfo->name,
2902 value ? tfstring->true_string : tfstring->false_string);
2903 if ((ret == -1) || (ret >= (ITEM_LABEL_LENGTH - bitfield_byte_length)))
2904 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
2908 /* Fills data for bitfield ints with val_strings */
2910 fill_label_enumerated_bitfield(field_info *fi, gchar *label_str)
2912 char *format = NULL, *p;
2913 int bitfield_byte_length, bitwidth;
2914 guint32 unshifted_value;
2916 int ret; /*tmp return value */
2918 header_field_info *hfinfo = fi->hfinfo;
2920 /* Figure out the bit width */
2921 bitwidth = hfinfo_bitwidth(hfinfo);
2923 /* Pick the proper format string */
2924 format = hfinfo_uint_vals_format(hfinfo);
2927 unshifted_value = fvalue_get_integer(&fi->value);
2928 value = unshifted_value;
2929 if (hfinfo->bitshift > 0) {
2930 unshifted_value <<= hfinfo->bitshift;
2933 /* Create the bitfield first */
2934 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
2935 bitfield_byte_length = p - label_str;
2937 /* Fill in the textual info using stored (shifted) value */
2938 ret = snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
2939 format, hfinfo->name,
2940 val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
2941 if ((ret == -1) || (ret >= (ITEM_LABEL_LENGTH - bitfield_byte_length)))
2942 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
2946 fill_label_numeric_bitfield(field_info *fi, gchar *label_str)
2948 char *format = NULL, *p;
2949 int bitfield_byte_length, bitwidth;
2950 guint32 unshifted_value;
2952 int ret; /*tmp return value */
2954 header_field_info *hfinfo = fi->hfinfo;
2956 /* Figure out the bit width */
2957 bitwidth = hfinfo_bitwidth(hfinfo);
2959 /* Pick the proper format string */
2960 format = hfinfo_uint_format(hfinfo);
2963 unshifted_value = fvalue_get_integer(&fi->value);
2964 value = unshifted_value;
2965 if (hfinfo->bitshift > 0) {
2966 unshifted_value <<= hfinfo->bitshift;
2969 /* Create the bitfield using */
2970 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
2971 bitfield_byte_length = p - label_str;
2973 /* Fill in the textual info using stored (shifted) value */
2974 ret = snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
2975 format, hfinfo->name, value);
2976 if ((ret == -1) || (ret >= (ITEM_LABEL_LENGTH - bitfield_byte_length)))
2977 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
2982 fill_label_enumerated_uint(field_info *fi, gchar *label_str)
2984 char *format = NULL;
2985 header_field_info *hfinfo = fi->hfinfo;
2987 int ret; /*tmp return value */
2989 /* Pick the proper format string */
2990 format = hfinfo_uint_vals_format(hfinfo);
2992 value = fvalue_get_integer(&fi->value);
2994 /* Fill in the textual info */
2995 ret = snprintf(label_str, ITEM_LABEL_LENGTH,
2996 format, hfinfo->name,
2997 val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
2998 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
2999 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3003 fill_label_uint(field_info *fi, gchar *label_str)
3005 char *format = NULL;
3006 header_field_info *hfinfo = fi->hfinfo;
3008 int ret; /*tmp return value */
3010 /* Pick the proper format string */
3011 format = hfinfo_uint_format(hfinfo);
3012 value = fvalue_get_integer(&fi->value);
3014 /* Fill in the textual info */
3015 ret = snprintf(label_str, ITEM_LABEL_LENGTH,
3016 format, hfinfo->name, value);
3017 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3018 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3022 fill_label_enumerated_int(field_info *fi, gchar *label_str)
3024 char *format = NULL;
3025 header_field_info *hfinfo = fi->hfinfo;
3027 int ret; /*tmp return value */
3029 /* Pick the proper format string */
3030 format = hfinfo_int_vals_format(hfinfo);
3031 value = fvalue_get_integer(&fi->value);
3033 /* Fill in the textual info */
3034 ret = snprintf(label_str, ITEM_LABEL_LENGTH,
3035 format, hfinfo->name,
3036 val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
3037 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3038 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3042 fill_label_int(field_info *fi, gchar *label_str)
3044 char *format = NULL;
3045 header_field_info *hfinfo = fi->hfinfo;
3047 int ret; /*tmp return value */
3049 /* Pick the proper format string */
3050 format = hfinfo_int_format(hfinfo);
3051 value = fvalue_get_integer(&fi->value);
3053 /* Fill in the textual info */
3054 ret = snprintf(label_str, ITEM_LABEL_LENGTH,
3055 format, hfinfo->name, value);
3056 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3057 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3061 hfinfo_bitwidth(header_field_info *hfinfo)
3065 if (!hfinfo->bitmask) {
3069 switch(hfinfo->type) {
3087 bitwidth = hfinfo->display; /* hacky? :) */
3090 g_assert_not_reached();
3097 hfinfo_uint_vals_format(header_field_info *hfinfo)
3099 char *format = NULL;
3101 switch(hfinfo->display) {
3103 format = "%s: %s (%u)";
3105 case BASE_OCT: /* I'm lazy */
3106 format = "%s: %s (%o)";
3109 switch(hfinfo->type) {
3111 format = "%s: %s (0x%02x)";
3114 format = "%s: %s (0x%04x)";
3117 format = "%s: %s (0x%06x)";
3120 format = "%s: %s (0x%08x)";
3123 g_assert_not_reached();
3128 g_assert_not_reached();
3135 hfinfo_uint_format(header_field_info *hfinfo)
3137 char *format = NULL;
3139 /* Pick the proper format string */
3140 if (hfinfo->type == FT_FRAMENUM) {
3142 * Frame numbers are always displayed in decimal.
3146 switch(hfinfo->display) {
3150 case BASE_OCT: /* I'm lazy */
3154 switch(hfinfo->type) {
3156 format = "%s: 0x%02x";
3159 format = "%s: 0x%04x";
3162 format = "%s: 0x%06x";
3165 format = "%s: 0x%08x";
3168 g_assert_not_reached();
3173 g_assert_not_reached();
3181 hfinfo_int_vals_format(header_field_info *hfinfo)
3183 char *format = NULL;
3185 switch(hfinfo->display) {
3187 format = "%s: %s (%d)";
3189 case BASE_OCT: /* I'm lazy */
3190 format = "%s: %s (%o)";
3193 switch(hfinfo->type) {
3195 format = "%s: %s (0x%02x)";
3198 format = "%s: %s (0x%04x)";
3201 format = "%s: %s (0x%06x)";
3204 format = "%s: %s (0x%08x)";
3207 g_assert_not_reached();
3212 g_assert_not_reached();
3219 hfinfo_int_format(header_field_info *hfinfo)
3221 char *format = NULL;
3223 /* Pick the proper format string */
3224 switch(hfinfo->display) {
3228 case BASE_OCT: /* I'm lazy */
3232 switch(hfinfo->type) {
3234 format = "%s: 0x%02x";
3237 format = "%s: 0x%04x";
3240 format = "%s: 0x%06x";
3243 format = "%s: 0x%08x";
3246 g_assert_not_reached();
3251 g_assert_not_reached();
3260 proto_registrar_n(void)
3262 return gpa_hfinfo.len;
3266 proto_registrar_get_name(int n)
3268 header_field_info *hfinfo;
3270 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
3271 return hfinfo->name;
3275 proto_registrar_get_abbrev(int n)
3277 header_field_info *hfinfo;
3279 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
3280 return hfinfo->abbrev;
3284 proto_registrar_get_ftype(int n)
3286 header_field_info *hfinfo;
3288 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
3289 return hfinfo->type;
3293 proto_registrar_get_parent(int n)
3295 header_field_info *hfinfo;
3297 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
3298 return hfinfo->parent;
3302 proto_registrar_is_protocol(int n)
3304 header_field_info *hfinfo;
3306 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
3307 return (hfinfo->parent == -1 ? TRUE : FALSE);
3310 /* Returns length of field in packet (not necessarily the length
3311 * in our internal representation, as in the case of IPv4).
3312 * 0 means undeterminable at time of registration
3313 * -1 means the field is not registered. */
3315 proto_registrar_get_length(int n)
3317 header_field_info *hfinfo;
3319 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
3320 return ftype_length(hfinfo->type);
3325 /* Looks for a protocol or a field in a proto_tree. Returns TRUE if
3326 * it exists anywhere, or FALSE if it exists nowhere. */
3328 proto_check_for_protocol_or_field(proto_tree* tree, int id)
3330 GPtrArray *ptrs = proto_get_finfo_ptr_array(tree, id);
3335 else if (g_ptr_array_len(ptrs) > 0) {
3343 /* Return GPtrArray* of field_info pointers for all hfindex that appear in tree.
3344 * This only works if the hfindex was "primed" before the dissection
3345 * took place, as we just pass back the already-created GPtrArray*.
3346 * The caller should *not* free the GPtrArray*; proto_tree_free_node()
3349 proto_get_finfo_ptr_array(proto_tree *tree, int id)
3351 return g_hash_table_lookup(PTREE_DATA(tree)->interesting_hfids,
3352 GINT_TO_POINTER(id));
3356 /* Helper struct and function for proto_find_info() */
3363 find_finfo(proto_node *node, gpointer data)
3365 field_info *fi = PITEM_FINFO(node);
3366 if (fi && fi->hfinfo) {
3367 if (fi->hfinfo->id == ((ffdata_t*)data)->id) {
3368 g_ptr_array_add(((ffdata_t*)data)->array, fi);
3372 /* Don't stop traversing. */
3376 /* Return GPtrArray* of field_info pointers for all hfindex that appear in a tree.
3377 * This works on any proto_tree, primed or unprimed, but actually searches
3378 * the tree, so it is slower than using proto_get_finfo_ptr_array on a primed tree.
3379 * The caller does need to free the returned GPtrArray with
3380 * g_ptr_array_free(<array>, FALSE).
3383 proto_find_finfo(proto_tree *tree, int id)
3387 ffdata.array = g_ptr_array_new();
3390 proto_tree_traverse_pre_order(tree, find_finfo, &ffdata);
3392 return ffdata.array;
3403 check_for_offset(proto_node *node, gpointer data)
3405 field_info *fi = PITEM_FINFO(node);
3406 offset_search_t *offsearch = data;
3408 /* !fi == the top most container node which holds nothing */
3409 if (fi && !PROTO_ITEM_IS_HIDDEN(node) && fi->ds_tvb && offsearch->tvb == fi->ds_tvb) {
3410 if (offsearch->offset >= (guint) fi->start &&
3411 offsearch->offset < (guint) (fi->start + fi->length)) {
3413 offsearch->finfo = fi;
3414 return FALSE; /* keep traversing */
3417 return FALSE; /* keep traversing */
3420 /* Search a proto_tree backwards (from leaves to root) looking for the field
3421 * whose start/length occupies 'offset' */
3422 /* XXX - I couldn't find an easy way to search backwards, so I search
3423 * forwards, w/o stopping. Therefore, the last finfo I find will the be
3424 * the one I want to return to the user. This algorithm is inefficient
3425 * and could be re-done, but I'd have to handle all the children and
3426 * siblings of each node myself. When I have more time I'll do that.
3429 proto_find_field_from_offset(proto_tree *tree, guint offset, tvbuff_t *tvb)
3431 offset_search_t offsearch;
3433 offsearch.offset = offset;
3434 offsearch.finfo = NULL;
3435 offsearch.tvb = tvb;
3437 proto_tree_traverse_pre_order(tree, check_for_offset, &offsearch);
3439 return offsearch.finfo;
3442 /* Dumps the protocols in the registration database to stdout. An independent
3443 * program can take this output and format it into nice tables or HTML or
3446 * There is one record per line. The fields are tab-delimited.
3448 * Field 1 = protocol name
3449 * Field 2 = protocol short name
3450 * Field 3 = protocol filter name
3453 proto_registrar_dump_protocols(void)
3455 protocol_t *protocol;
3459 for (i = proto_get_first_protocol(&cookie); i != -1;
3460 i = proto_get_next_protocol(&cookie)) {
3461 protocol = find_protocol_by_id(i);
3462 printf("%s\t%s\t%s\n", protocol->name, protocol->short_name,
3463 protocol->filter_name);
3467 /* Dumps the contents of the registration database to stdout. An indepedent
3468 * program can take this output and format it into nice tables or HTML or
3471 * There is one record per line. Each record is either a protocol or a header
3472 * field, differentiated by the first field. The fields are tab-delimited.
3477 * Field 2 = protocol name
3478 * Field 3 = protocol abbreviation
3483 * Field 2 = field name
3484 * Field 3 = field abbreviation
3485 * Field 4 = type ( textual representation of the the ftenum type )
3486 * Field 5 = parent protocol abbreviation
3489 proto_registrar_dump_fields(void)
3491 header_field_info *hfinfo, *parent_hfinfo;
3493 const char *enum_name;
3495 len = gpa_hfinfo.len;
3496 for (i = 0; i < len ; i++) {
3497 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
3500 * Skip fields with zero-length names or abbreviations;
3501 * the pseudo-field for "proto_tree_add_text()" is such
3502 * a field, and we don't want it in the list of filterable
3506 * XXX - perhaps the name and abbrev field should be null
3507 * pointers rather than null strings for that pseudo-field,
3508 * but we'd have to add checks for null pointers in some
3509 * places if we did that.
3511 * Or perhaps protocol tree items added with
3512 * "proto_tree_add_text()" should have -1 as the field index,
3513 * with no pseudo-field being used, but that might also
3514 * require special checks for -1 to be added.
3516 if (hfinfo->name[0] == 0 || hfinfo->abbrev[0] == 0)
3519 /* format for protocols */
3520 if (proto_registrar_is_protocol(i)) {
3521 printf("P\t%s\t%s\n", hfinfo->name, hfinfo->abbrev);
3523 /* format for header fields */
3526 * If this field isn't at the head of the list of
3527 * fields with this name, skip this field - all
3528 * fields with the same name are really just versions
3529 * of the same field stored in different bits, and
3530 * should have the same type/radix/value list, and
3531 * just differ in their bit masks. (If a field isn't
3532 * a bitfield, but can be, say, 1 or 2 bytes long,
3533 * it can just be made FT_UINT16, meaning the
3534 * *maximum* length is 2 bytes, and be used
3537 if (hfinfo->same_name_prev != NULL)
3540 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
3542 enum_name = ftype_name(hfinfo->type);
3543 printf("F\t%s\t%s\t%s\t%s\t%s\n", hfinfo->name, hfinfo->abbrev,
3544 enum_name,parent_hfinfo->abbrev, hfinfo->blurb);
3550 hfinfo_numeric_format(header_field_info *hfinfo)
3552 char *format = NULL;
3554 /* Pick the proper format string */
3555 if (hfinfo->type == FT_FRAMENUM) {
3557 * Frame numbers are always displayed in decimal.
3559 format = "%s == %u";
3561 /* Pick the proper format string */
3562 switch(hfinfo->display) {
3564 case BASE_OCT: /* I'm lazy */
3565 switch(hfinfo->type) {
3570 format = "%s == %u";
3576 format = "%s == %d";
3579 g_assert_not_reached();
3584 switch(hfinfo->type) {
3586 format = "%s == 0x%02x";
3589 format = "%s == 0x%04x";
3592 format = "%s == 0x%06x";
3595 format = "%s == 0x%08x";
3598 g_assert_not_reached();
3603 g_assert_not_reached();
3611 * Returns TRUE if we can do a "match selected" on the field, FALSE
3615 proto_can_match_selected(field_info *finfo, epan_dissect_t *edt)
3617 header_field_info *hfinfo;
3620 hfinfo = finfo->hfinfo;
3623 switch(hfinfo->type) {
3642 case FT_ABSOLUTE_TIME:
3643 case FT_RELATIVE_TIME:
3646 case FT_UINT_STRING:
3652 * These all have values, so we can match.
3658 * This doesn't have a value, so we'd match
3659 * on the raw bytes at this address.
3661 * Should we be allowed to access to the raw bytes?
3662 * If "edt" is NULL, the answer is "no".
3668 * Is this field part of the raw frame tvbuff?
3669 * If not, we can't use "frame[N:M]" to match
3672 * XXX - should this be frame-relative, or
3673 * protocol-relative?
3675 * XXX - does this fallback for non-registered
3676 * fields even make sense?
3678 if (finfo->ds_tvb != edt->tvb)
3682 * If the length is 0, there's nothing to match, so
3683 * we can't match. (Also check for negative values,
3684 * just in case, as we'll cast it to an unsigned
3687 length = finfo->length;
3692 * Don't go past the end of that tvbuff.
3694 if ((guint)length > tvb_length(finfo->ds_tvb))
3695 length = tvb_length(finfo->ds_tvb);
3703 proto_construct_dfilter_string(field_info *finfo, epan_dissect_t *edt)
3705 header_field_info *hfinfo;
3707 char *buf, *stringified, *format, *ptr;
3709 gint start, length, length_remaining;
3712 hfinfo = finfo->hfinfo;
3714 abbrev_len = strlen(hfinfo->abbrev);
3717 * XXX - we should add "val_to_string_repr" and "string_repr_len"
3718 * functions for more types, and use them whenever possible.
3720 * The FT_UINT and FT_INT types are the only tricky ones, as
3721 * we choose the base in the string expression based on the
3722 * display base of the field.
3724 * Note that the base does matter, as this is also used for
3725 * the protocolinfo tap.
3727 * It might be nice to use that in "proto_item_fill_label()"
3728 * as well, although, there, you'd have to deal with the base
3729 * *and* with resolved values for addresses.
3731 * Perhaps we need two different val_to_string routines, one
3732 * to generate items for display filters and one to generate
3733 * strings for display, and pass to both of them the
3734 * "display" and "strings" values in the header_field_info
3735 * structure for the field, so they can get the base and,
3736 * if the field is Boolean or an enumerated integer type,
3737 * the tables used to generate human-readable values.
3739 switch(hfinfo->type) {
3751 * 4 bytes for " == ".
3754 * a sign + up to 10 digits of 32-bit integer,
3757 * "0x" + 8 digits of 32-bit integer, in hex;
3759 * 11 digits of 32-bit integer, in octal.
3760 * (No, we don't do octal, but this way,
3761 * we know that if we do, this will still
3764 * 1 byte for the trailing '\0'.
3766 dfilter_len = abbrev_len + 4 + 11 + 1;
3767 buf = g_malloc0(dfilter_len);
3768 format = hfinfo_numeric_format(hfinfo);
3769 snprintf(buf, dfilter_len, format, hfinfo->abbrev, fvalue_get_integer(&finfo->value));
3774 * 4 bytes for " == ".
3775 * N bytes for the string for the number.
3776 * 1 byte for the trailing '\0'.
3778 stringified = u64toa(fvalue_get(&finfo->value));
3779 dfilter_len = abbrev_len + 4 + strlen(stringified) +1;
3780 buf = g_malloc0(dfilter_len);
3781 snprintf(buf, dfilter_len, "%s == %s", hfinfo->abbrev,
3787 * 4 bytes for " == ".
3788 * N bytes for the string for the number.
3789 * 1 byte for the trailing '\0'.
3791 stringified = i64toa(fvalue_get(&finfo->value));
3792 dfilter_len = abbrev_len + 4 + strlen(stringified) +1;
3793 buf = g_malloc0(dfilter_len);
3794 snprintf(buf, dfilter_len, "%s == %s", hfinfo->abbrev,
3800 * 4 bytes for " == ".
3802 * 8 bytes for 8 digits of 32-bit hex number.
3803 * 1 byte for the trailing '\0'.
3805 dfilter_len = abbrev_len + 4 + 2 + 8 + 1;
3806 buf = g_malloc0(dfilter_len);
3807 snprintf(buf, dfilter_len, "%s == 0x%08x", hfinfo->abbrev,
3808 fvalue_get_integer(&finfo->value));
3813 * 4 bytes for " == ".
3814 * N bytes for the string for the address.
3815 * 1 byte for the trailing '\0'.
3817 stringified = ip6_to_str((struct e_in6_addr*) fvalue_get(&finfo->value));
3818 dfilter_len = abbrev_len + 4 + strlen(stringified) + 1;
3819 buf = g_malloc0(dfilter_len);
3820 snprintf(buf, dfilter_len, "%s == %s", hfinfo->abbrev,
3824 /* These use the fvalue's "to_string_repr" method. */
3832 case FT_ABSOLUTE_TIME:
3833 case FT_RELATIVE_TIME:
3835 /* Figure out the string length needed.
3836 * The ft_repr length.
3837 * 4 bytes for " == ".
3838 * 1 byte for trailing NUL.
3840 dfilter_len = fvalue_string_repr_len(&finfo->value,
3842 dfilter_len += abbrev_len + 4 + 1;
3843 buf = g_malloc0(dfilter_len);
3845 /* Create the string */
3846 snprintf(buf, dfilter_len, "%s == ", hfinfo->abbrev);
3847 fvalue_to_string_repr(&finfo->value,
3849 &buf[abbrev_len + 4]);
3853 buf = g_strdup(finfo->hfinfo->abbrev);
3858 * This doesn't have a value, so we'd match
3859 * on the raw bytes at this address.
3861 * Should we be allowed to access to the raw bytes?
3862 * If "edt" is NULL, the answer is "no".
3868 * Is this field part of the raw frame tvbuff?
3869 * If not, we can't use "frame[N:M]" to match
3872 * XXX - should this be frame-relative, or
3873 * protocol-relative?
3875 * XXX - does this fallback for non-registered
3876 * fields even make sense?
3878 if (finfo->ds_tvb != edt->tvb)
3879 return NULL; /* you lose */
3882 * If the length is 0, there's nothing to match, so
3883 * we can't match. (Also check for negative values,
3884 * just in case, as we'll cast it to an unsigned
3887 length = finfo->length;
3892 * Don't go past the end of that tvbuff.
3894 length_remaining = tvb_length_remaining(finfo->ds_tvb, finfo->start);
3895 if (length > length_remaining)
3896 length = length_remaining;
3900 start = finfo->start;
3901 buf = g_malloc0(32 + length * 3);
3904 sprintf(ptr, "frame[%d:%d] == ", finfo->start, length);
3905 ptr = buf+strlen(buf);
3907 for (i=0;i<length; i++) {
3908 c = tvb_get_guint8(finfo->ds_tvb, start);
3911 sprintf(ptr, "%02x", c);
3914 sprintf(ptr, ":%02x", c);
3916 ptr = buf+strlen(buf);