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.
36 #include "ptvcursor.h"
38 #include "addr_resolv.h"
41 #include "epan_dissect.h"
52 #define cVALS(x) (const value_string*)(x)
55 #define TRY_TO_FAKE_THIS_ITEM(tree, hfindex) \
56 /* If this item is not referenced we dont have to do much work \
57 at all but we should still return a node so that \
58 field items below this node ( think proto_item_add_subtree() )\
59 will still have somewhere to attach to \
60 or else filtering will not work (they would be ignored since tree\
62 DONT try to fake a node where PITEM_FINFO(pi) is NULL \
63 since dissectors that want to do proto_item_set_len() ot \
64 other operations that dereference this would crash. \
65 We dont fake FT_PROTOCOL either since these are cheap and \
66 some stuff (proto hier stat) assumes they always exist. \
68 if(!(PTREE_DATA(tree)->visible)){ \
69 if(PITEM_FINFO(tree)){ \
70 register header_field_info *hfinfo; \
71 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo); \
72 if((hfinfo->ref_count == 0) \
73 && (hfinfo->type!=FT_PROTOCOL)){ \
74 /* just return tree back to the caller */\
80 #define TRY_TO_FAKE_THIS_ITEM(tree, hfindex) ;
84 proto_tree_free_node(proto_node *node, gpointer data);
86 static void fill_label_boolean(field_info *fi, gchar *label_str);
87 static void fill_label_uint(field_info *fi, gchar *label_str);
88 static void fill_label_uint64(field_info *fi, gchar *label_str);
89 static void fill_label_enumerated_uint(field_info *fi, gchar *label_str);
90 static void fill_label_enumerated_bitfield(field_info *fi, gchar *label_str);
91 static void fill_label_numeric_bitfield(field_info *fi, gchar *label_str);
92 static void fill_label_int(field_info *fi, gchar *label_str);
93 static void fill_label_int64(field_info *fi, gchar *label_str);
94 static void fill_label_enumerated_int(field_info *fi, gchar *label_str);
96 int hfinfo_bitwidth(header_field_info *hfinfo);
97 static const char* hfinfo_uint_vals_format(header_field_info *hfinfo);
98 static const char* hfinfo_uint_format(header_field_info *hfinfo);
99 static const char* hfinfo_uint64_format(header_field_info *hfinfo);
100 static const char* hfinfo_int_vals_format(header_field_info *hfinfo);
101 static const char* hfinfo_int_format(header_field_info *hfinfo);
102 static const char* hfinfo_int64_format(header_field_info *hfinfo);
105 proto_tree_add_node(proto_tree *tree, field_info *fi);
107 static header_field_info *
108 get_hfi_and_length(int hfindex, tvbuff_t *tvb, gint start, gint *length,
112 new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
113 gint start, gint item_length);
116 alloc_field_info(proto_tree *tree, int hfindex, tvbuff_t *tvb,
117 gint start, gint *length);
120 proto_tree_add_pi(proto_tree *tree, int hfindex, tvbuff_t *tvb,
121 gint start, gint *length, field_info **pfi);
124 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap);
127 proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb);
129 proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length);
131 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length);
133 proto_tree_set_time(field_info *fi, nstime_t *value_ptr);
135 proto_tree_set_string(field_info *fi, const char* value, gboolean);
137 proto_tree_set_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
139 proto_tree_set_ether(field_info *fi, const guint8* value);
141 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start);
143 proto_tree_set_ipxnet(field_info *fi, guint32 value);
145 proto_tree_set_ipv4(field_info *fi, guint32 value);
147 proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr);
149 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start);
151 proto_tree_set_guid(field_info *fi, const guint8* value_ptr);
153 proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, gint start);
155 proto_tree_set_boolean(field_info *fi, guint32 value);
157 proto_tree_set_float(field_info *fi, float value);
159 proto_tree_set_double(field_info *fi, double value);
161 proto_tree_set_uint(field_info *fi, guint32 value);
163 proto_tree_set_int(field_info *fi, gint32 value);
165 proto_tree_set_uint64(field_info *fi, guint64 value);
167 proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start, gboolean little_endian);
169 static int proto_register_field_init(header_field_info *hfinfo, int parent);
171 /* Comparision function for tree insertion. A wrapper around strcmp() */
172 static int g_strcmp(gconstpointer a, gconstpointer b);
174 /* special-case header field used within proto.c */
175 int hf_text_only = -1;
177 /* Structure for information about a protocol */
179 const char *name; /* long description */
180 const char *short_name; /* short description */
181 const char *filter_name; /* name of this protocol in filters */
182 int proto_id; /* field ID for this protocol */
183 GList *fields; /* fields for this protocol */
184 GList *last_field; /* pointer to end of list of fields */
185 gboolean is_enabled; /* TRUE if protocol is enabled */
186 gboolean can_toggle; /* TRUE if is_enabled can be changed */
189 /* List of all protocols */
190 static GList *protocols = NULL;
192 #define INITIAL_NUM_PROTOCOL_HFINFO 200
195 /* Contains information about protocols and header fields. Used when
196 * dissectors register their data */
197 static GMemChunk *gmc_hfinfo = NULL;
199 /* Contains information about a field when a dissector calls
200 * proto_tree_add_item. */
201 SLAB_ITEM_TYPE_DEFINE(field_info)
202 static SLAB_FREE_LIST_DEFINE(field_info)
203 static field_info *field_info_tmp=NULL;
204 #define FIELD_INFO_NEW(fi) \
205 SLAB_ALLOC(fi, field_info)
206 #define FIELD_INFO_FREE(fi) \
207 SLAB_FREE(fi, field_info)
211 /* Contains the space for proto_nodes. */
212 SLAB_ITEM_TYPE_DEFINE(proto_node)
213 static SLAB_FREE_LIST_DEFINE(proto_node)
214 #define PROTO_NODE_NEW(node) \
215 SLAB_ALLOC(node, proto_node) \
216 node->first_child = NULL; \
217 node->last_child = NULL; \
220 #define PROTO_NODE_FREE(node) \
221 SLAB_FREE(node, proto_node)
225 /* String space for protocol and field items for the GUI */
226 SLAB_ITEM_TYPE_DEFINE(item_label_t)
227 static SLAB_FREE_LIST_DEFINE(item_label_t)
228 #define ITEM_LABEL_NEW(il) \
229 SLAB_ALLOC(il, item_label_t)
230 #define ITEM_LABEL_FREE(il) \
231 SLAB_FREE(il, item_label_t)
234 #define PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo) \
235 DISSECTOR_ASSERT((guint)hfindex < gpa_hfinfo.len); \
236 hfinfo=gpa_hfinfo.hfi[hfindex];
239 /* List which stores protocols and fields that have been registered */
240 typedef struct _gpa_hfinfo_t {
242 guint32 allocated_len;
243 header_field_info **hfi;
245 gpa_hfinfo_t gpa_hfinfo;
247 /* Balanced tree of abbreviations and IDs */
248 static GTree *gpa_name_tree = NULL;
250 /* Points to the first element of an array of Booleans, indexed by
251 a subtree item type; that array element is TRUE if subtrees of
252 an item of that type are to be expanded. */
253 gboolean *tree_is_expanded;
255 /* Number of elements in that array. */
258 /* Name hashtables for fast detection of duplicate names */
259 static GHashTable* proto_names = NULL;
260 static GHashTable* proto_short_names = NULL;
261 static GHashTable* proto_filter_names = NULL;
264 proto_compare_name(gconstpointer p1_arg, gconstpointer p2_arg)
266 const protocol_t *p1 = p1_arg;
267 const protocol_t *p2 = p2_arg;
269 return g_strcasecmp(p1->short_name, p2->short_name);
273 /* initialize data structures and register protocols and fields */
275 proto_init(const char *plugin_dir
280 void (register_all_protocols)(void),
281 void (register_all_protocol_handoffs)(void))
283 static hf_register_info hf[] = {
285 { "", "", FT_NONE, BASE_NONE, NULL, 0x0,
290 proto_names = g_hash_table_new(g_int_hash, g_int_equal);
291 proto_short_names = g_hash_table_new(g_int_hash, g_int_equal);
292 proto_filter_names = g_hash_table_new(g_int_hash, g_int_equal);
296 gmc_hfinfo = g_mem_chunk_new("gmc_hfinfo",
297 sizeof(header_field_info),
298 INITIAL_NUM_PROTOCOL_HFINFO * sizeof(header_field_info),
302 gpa_hfinfo.allocated_len=0;
304 gpa_name_tree = g_tree_new(g_strcmp);
306 /* Initialize the ftype subsystem */
309 /* Register one special-case FT_TEXT_ONLY field for use when
310 converting ethereal to new-style proto_tree. These fields
311 are merely strings on the GUI tree; they are not filterable */
312 proto_register_field_array(-1, hf, array_length(hf));
314 /* Have each built-in dissector register its protocols, fields,
315 dissector tables, and dissectors to be called through a
316 handle, and do whatever one-time initialization it needs to
318 register_all_protocols();
321 /* Now scan for plugins and load all the ones we find, calling
322 their register routines to do the stuff described above. */
323 init_plugins(plugin_dir);
326 /* Now call the "handoff registration" routines of all built-in
327 dissectors; those routines register the dissector in other
328 dissectors' handoff tables, and fetch any dissector handles
330 register_all_protocol_handoffs();
333 /* Now do the same with plugins. */
334 register_all_plugin_handoffs();
337 /* sort the protocols by protocol name */
338 protocols = g_list_sort(protocols, proto_compare_name);
340 /* We've assigned all the subtree type values; allocate the array
341 for them, and zero it out. */
342 tree_is_expanded = g_malloc(num_tree_types*sizeof (gint *));
343 memset(tree_is_expanded, 0, num_tree_types*sizeof (gint *));
346 /* String comparison func for dfilter_token GTree */
348 g_strcmp(gconstpointer a, gconstpointer b)
350 return strcmp((const char*)a, (const char*)b);
356 /* Free the abbrev/ID GTree */
358 g_tree_destroy(gpa_name_tree);
359 gpa_name_tree = NULL;
363 g_mem_chunk_destroy(gmc_hfinfo);
365 if(gpa_hfinfo.allocated_len){
367 gpa_hfinfo.allocated_len=0;
368 g_free(gpa_hfinfo.hfi);
371 if (tree_is_expanded != NULL)
372 g_free(tree_is_expanded);
376 typedef gboolean (*proto_tree_traverse_func)(proto_node *, gpointer);
379 proto_tree_traverse_pre_order(proto_tree *tree, proto_tree_traverse_func func,
382 proto_node *pnode = tree;
386 if (func(pnode, data))
389 child = pnode->first_child;
390 while (child != NULL) {
392 * The routine we call might modify the child, e.g. by
393 * freeing it, so we get the child's successor before
394 * calling that routine.
397 child = current->next;
398 if (proto_tree_traverse_pre_order((proto_tree *)current, func,
407 proto_tree_traverse_in_order(proto_tree *tree, proto_tree_traverse_func func,
410 proto_node *pnode = tree;
414 child = pnode->first_child;
417 * The routine we call might modify the child, e.g. by
418 * freeing it, so we get the child's successor before
419 * calling that routine.
422 child = current->next;
424 if (proto_tree_traverse_in_order((proto_tree *)current, func,
428 if (func(pnode, data))
431 while (child != NULL) {
433 * The routine we call might modify the child, e.g. by
434 * freeing it, so we get the child's successor before
435 * calling that routine.
438 child = current->next;
439 if (proto_tree_traverse_in_order((proto_tree *)current,
444 if (func(pnode, data))
452 proto_tree_children_foreach(proto_tree *tree, proto_tree_foreach_func func,
455 proto_node *node = tree;
458 node = node->first_child;
459 while (node != NULL) {
461 node = current->next;
462 func((proto_tree *)current, data);
466 /* frees the resources that the dissection a proto_tree uses */
468 proto_tree_free(proto_tree *tree)
470 proto_tree_traverse_in_order(tree, proto_tree_free_node, NULL);
474 free_GPtrArray_value(gpointer key _U_, gpointer value, gpointer user_data _U_)
476 GPtrArray *ptrs = value;
477 gint hfid = (gint)key;
478 header_field_info *hfinfo;
481 PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
482 if(hfinfo->ref_count){
483 /* when a field is referenced by a filter this also
484 affects the refcount for the parent protocol so we need
485 to adjust the refcount for the parent as well
487 if( (hfinfo->parent != -1) && (hfinfo->ref_count) ){
488 header_field_info *parent_hfinfo;
489 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
490 parent_hfinfo->ref_count -= hfinfo->ref_count;
492 hfinfo->ref_count = 0;
495 g_ptr_array_free(ptrs, TRUE);
499 free_node_tree_data(tree_data_t *tree_data)
501 /* Free all the GPtrArray's in the interesting_hfids hash. */
502 g_hash_table_foreach(tree_data->interesting_hfids,
503 free_GPtrArray_value, NULL);
505 /* And then destroy the hash. */
506 g_hash_table_destroy(tree_data->interesting_hfids);
508 /* And finally the tree_data_t itself. */
512 #define FREE_NODE_FIELD_INFO(finfo) \
514 ITEM_LABEL_FREE(finfo->rep); \
516 FVALUE_CLEANUP(&finfo->value); \
517 FIELD_INFO_FREE(finfo);
520 proto_tree_free_node(proto_node *node, gpointer data _U_)
522 field_info *finfo = PITEM_FINFO(node);
525 /* This is the root node. Destroy the per-tree data.
526 * There is no field_info to destroy. */
527 free_node_tree_data(PTREE_DATA(node));
530 /* This is a child node. Don't free the per-tree data, but
531 * do free the field_info data. */
532 FREE_NODE_FIELD_INFO(finfo);
535 /* Free the proto_node. */
536 PROTO_NODE_FREE(node);
538 return FALSE; /* FALSE = do not end traversal of protocol tree */
541 /* Is the parsing being done for a visible proto_tree or an invisible one?
542 * By setting this correctly, the proto_tree creation is sped up by not
543 * having to call g_vsnprintf and copy strings around.
546 proto_tree_set_visible(proto_tree *tree, gboolean visible)
548 PTREE_DATA(tree)->visible = visible;
551 /* Assume dissector set only its protocol fields.
552 This function is called by dissectors and allowes to speed up filtering
553 in ethereal, if this function returns FALSE it is safe to reset tree to NULL
554 and thus skip calling most of the expensive proto_tree_add_...()
556 If the tree is visible we implicitely assume the field is referenced.
559 proto_field_is_referenced(proto_tree *tree, int proto_id)
561 register header_field_info *hfinfo;
567 if (PTREE_DATA(tree)->visible)
570 PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
571 if (hfinfo->ref_count != 0)
578 /* Finds a record in the hf_info_records array by id. */
580 proto_registrar_get_nth(guint hfindex)
582 register header_field_info *hfinfo;
584 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
588 /* Finds a record in the hf_info_records array by name.
591 proto_registrar_get_byname(const char *field_name)
593 DISSECTOR_ASSERT(field_name != NULL);
594 return g_tree_lookup(gpa_name_tree, field_name);
597 /* Allocates an initializes a ptvcursor_t with 3 variables:
598 * proto_tree, tvbuff, and offset. */
600 ptvcursor_new(proto_tree *tree, tvbuff_t *tvb, gint offset)
604 ptvc = g_new(ptvcursor_t, 1);
607 ptvc->offset = offset;
611 /* Frees memory for ptvcursor_t, but nothing deeper than that. */
613 ptvcursor_free(ptvcursor_t *ptvc)
618 /* Returns tvbuff. */
620 ptvcursor_tvbuff(ptvcursor_t* ptvc)
625 /* Returns current offset. */
627 ptvcursor_current_offset(ptvcursor_t* ptvc)
633 ptvcursor_tree(ptvcursor_t* ptvc)
639 ptvcursor_set_tree(ptvcursor_t* ptvc, proto_tree *tree)
644 /* Add a text-only node, leaving it to our caller to fill the text in */
646 proto_tree_add_text_node(proto_tree *tree, tvbuff_t *tvb, gint start, gint length)
650 pi = proto_tree_add_pi(tree, hf_text_only, tvb, start, &length, NULL);
657 /* Add a text-only node to the proto_tree */
659 proto_tree_add_text(proto_tree *tree, tvbuff_t *tvb, gint start, gint length,
660 const char *format, ...)
665 pi = proto_tree_add_text_node(tree, tvb, start, length);
669 va_start(ap, format);
670 proto_tree_set_representation(pi, format, ap);
676 /* Add a text-only node to the proto_tree (va_list version) */
678 proto_tree_add_text_valist(proto_tree *tree, tvbuff_t *tvb, gint start,
679 gint length, const char *format, va_list ap)
683 pi = proto_tree_add_text_node(tree, tvb, start, length);
687 proto_tree_set_representation(pi, format, ap);
692 /* Add a text-only node for debugging purposes. The caller doesn't need
693 * to worry about tvbuff, start, or length. Debug message gets sent to
696 proto_tree_add_debug_text(proto_tree *tree, const char *format, ...)
701 pi = proto_tree_add_text_node(tree, NULL, 0, 0);
705 va_start(ap, format);
706 proto_tree_set_representation(pi, format, ap);
716 get_uint_value(tvbuff_t *tvb, gint offset, gint length, gboolean little_endian)
723 value = tvb_get_guint8(tvb, offset);
727 value = little_endian ? tvb_get_letohs(tvb, offset)
728 : tvb_get_ntohs(tvb, offset);
732 value = little_endian ? tvb_get_letoh24(tvb, offset)
733 : tvb_get_ntoh24(tvb, offset);
737 value = little_endian ? tvb_get_letohl(tvb, offset)
738 : tvb_get_ntohl(tvb, offset);
742 THROW(ReportedBoundsError);
750 get_int_value(tvbuff_t *tvb, gint offset, gint length, gboolean little_endian)
757 value = (gint8)tvb_get_guint8(tvb, offset);
761 value = (gint16) (little_endian ? tvb_get_letohs(tvb, offset)
762 : tvb_get_ntohs(tvb, offset));
766 value = little_endian ? tvb_get_letoh24(tvb, offset)
767 : tvb_get_ntoh24(tvb, offset);
768 if (value & 0x00800000) {
769 /* Sign bit is set; sign-extend it. */
775 value = little_endian ? tvb_get_letohl(tvb, offset)
776 : tvb_get_ntohl(tvb, offset);
780 THROW(ReportedBoundsError);
787 /* Add an item to a proto_tree, using the text label registered to that item;
788 the item is extracted from the tvbuff handed to it. */
790 proto_tree_new_item(field_info *new_fi, proto_tree *tree, int hfindex,
791 tvbuff_t *tvb, gint start, gint length, gboolean little_endian)
801 /* there is a possibility here that we might raise an exception
802 * and thus would lose track of the field_info.
803 * store it in a temp so that if we come here again we can reclaim
804 * the field_info without leaking memory.
806 /* XXX this only keeps track of one field_info struct,
807 if we ever go multithreaded for calls to this function
808 we have to change this code to use per thread variable.
811 /* oops, last one we got must have been lost due
813 * good thing we saved it, now we can reverse the
814 * memory leak and reclaim it.
816 SLAB_FREE(field_info_tmp, field_info);
818 /* we might throw an exception, keep track of this one
819 * across the "dangerous" section below.
821 field_info_tmp=new_fi;
823 switch(new_fi->hfinfo->type) {
825 /* no value to set for FT_NONE */
829 proto_tree_set_protocol_tvb(new_fi, tvb);
833 proto_tree_set_bytes_tvb(new_fi, tvb, start, length);
837 n = get_uint_value(tvb, start, length, little_endian);
838 proto_tree_set_bytes_tvb(new_fi, tvb, start + length, n);
840 /* Instead of calling proto_item_set_len(), since we don't yet
841 * have a proto_item, we set the field_info's length ourselves. */
842 new_fi->length = n + length;
846 proto_tree_set_boolean(new_fi,
847 get_uint_value(tvb, start, length, little_endian));
850 /* XXX - make these just FT_UINT? */
855 proto_tree_set_uint(new_fi,
856 get_uint_value(tvb, start, length, little_endian));
861 DISSECTOR_ASSERT(length == 8);
862 proto_tree_set_uint64_tvb(new_fi, tvb, start, little_endian);
865 /* XXX - make these just FT_INT? */
870 proto_tree_set_int(new_fi,
871 get_int_value(tvb, start, length, little_endian));
875 DISSECTOR_ASSERT(length == 4);
876 value = tvb_get_ipv4(tvb, start);
877 proto_tree_set_ipv4(new_fi, little_endian ? GUINT32_SWAP_LE_BE(value) : value);
881 DISSECTOR_ASSERT(length == 4);
882 proto_tree_set_ipxnet(new_fi,
883 get_uint_value(tvb, start, 4, FALSE));
887 DISSECTOR_ASSERT(length == 16);
888 proto_tree_set_ipv6_tvb(new_fi, tvb, start);
892 DISSECTOR_ASSERT(length == 6);
893 proto_tree_set_ether_tvb(new_fi, tvb, start);
897 DISSECTOR_ASSERT(length == 16);
898 proto_tree_set_guid_tvb(new_fi, tvb, start);
902 DISSECTOR_ASSERT(length == 4);
904 floatval = tvb_get_letohieee_float(tvb, start);
906 floatval = tvb_get_ntohieee_float(tvb, start);
907 proto_tree_set_float(new_fi, floatval);
911 DISSECTOR_ASSERT(length == 8);
913 doubleval = tvb_get_letohieee_double(tvb, start);
915 doubleval = tvb_get_ntohieee_double(tvb, start);
916 proto_tree_set_double(new_fi, doubleval);
920 /* This g_strdup'ed memory is freed in proto_tree_free_node() */
921 proto_tree_set_string_tvb(new_fi, tvb, start, length);
925 DISSECTOR_ASSERT(length >= -1);
926 /* Instead of calling proto_item_set_len(),
927 * since we don't yet have a proto_item, we
928 * set the field_info's length ourselves.
930 * XXX - our caller can't use that length to
931 * advance an offset unless they arrange that
932 * there always be a protocol tree into which
933 * we're putting this item.
936 /* This can throw an exception */
937 length = tvb_strsize(tvb, start);
939 /* This g_malloc'ed memory is freed
940 in proto_tree_free_node() */
941 string = g_malloc(length);
943 tvb_memcpy(tvb, string, start, length);
944 } else if (length == 0) {
945 string = g_strdup("[Empty]");
947 /* In this case, length signifies
948 * the length of the string.
950 * This could either be a null-padded
951 * string, which doesn't necessarily
952 * have a '\0' at the end, or a
953 * null-terminated string, with a
954 * trailing '\0'. (Yes, there are
955 * cases where you have a string
956 * that's both counted and null-
959 * In the first case, we must
960 * allocate a buffer of length
961 * "length+1", to make room for
964 * In the second case, we don't
965 * assume that there is a trailing
966 * '\0' there, as the packet might
967 * be malformed. (XXX - should we
968 * throw an exception if there's no
969 * trailing '\0'?) Therefore, we
970 * allocate a buffer of length
971 * "length+1", and put in a trailing
972 * '\0', just to be safe.
974 * (XXX - this would change if
975 * we made string values counted
976 * rather than null-terminated.)
979 /* This g_malloc'ed memory is freed
980 * in proto_tree_free_node() */
981 string = tvb_get_string(tvb, start,
984 new_fi->length = length;
985 proto_tree_set_string(new_fi, string, TRUE);
989 /* This g_strdup'ed memory is freed in proto_tree_free_node() */
990 n = get_uint_value(tvb, start, length, little_endian);
991 proto_tree_set_string_tvb(new_fi, tvb, start + length, n);
993 /* Instead of calling proto_item_set_len(), since we
994 * don't yet have a proto_item, we set the
995 * field_info's length ourselves.
997 * XXX - our caller can't use that length to
998 * advance an offset unless they arrange that
999 * there always be a protocol tree into which
1000 * we're putting this item.
1002 new_fi->length = n + length;
1006 g_error("new_fi->hfinfo->type %d (%s) not handled\n",
1007 new_fi->hfinfo->type,
1008 ftype_name(new_fi->hfinfo->type));
1009 DISSECTOR_ASSERT_NOT_REACHED();
1013 /* Don't add new node to proto_tree until now so that any exceptions
1014 * raised by a tvbuff access method doesn't leave junk in the proto_tree. */
1015 pi = proto_tree_add_node(tree, new_fi);
1017 /* we did not raise an exception so we dont have to remember this
1018 * field_info struct any more.
1020 field_info_tmp=NULL;
1022 /* If the proto_tree wants to keep a record of this finfo
1023 * for quick lookup, then record it. */
1024 if (new_fi->hfinfo->ref_count) {
1025 hash = PTREE_DATA(tree)->interesting_hfids;
1026 ptrs = g_hash_table_lookup(hash, GINT_TO_POINTER(hfindex));
1028 g_ptr_array_add(ptrs, new_fi);
1035 /* Gets data from tvbuff, adds it to proto_tree, increments offset,
1036 and returns proto_item* */
1038 ptvcursor_add(ptvcursor_t *ptvc, int hfindex, gint length,
1039 gboolean little_endian)
1042 header_field_info *hfinfo;
1047 offset = ptvc->offset;
1048 hfinfo = get_hfi_and_length(hfindex, ptvc->tvb, offset, &length,
1050 ptvc->offset += length;
1051 if (hfinfo->type == FT_UINT_BYTES || hfinfo->type == FT_UINT_STRING) {
1053 * The length of the rest of the item is in the first N
1054 * bytes of the item.
1056 n = get_uint_value(ptvc->tvb, offset, length, little_endian);
1059 if (ptvc->tree == NULL)
1062 TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfindex);
1064 new_fi = new_field_info(ptvc->tree, hfinfo, ptvc->tvb, offset,
1069 return proto_tree_new_item(new_fi, ptvc->tree, hfindex, ptvc->tvb,
1070 offset, length, little_endian);
1073 /* Add an item to a proto_tree, using the text label registered to that item;
1074 the item is extracted from the tvbuff handed to it. */
1076 proto_tree_add_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1077 gint start, gint length, gboolean little_endian)
1084 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1086 new_fi = alloc_field_info(tree, hfindex, tvb, start, &length);
1091 return proto_tree_new_item(new_fi, tree, hfindex, tvb, start,
1092 length, little_endian);
1096 proto_tree_add_item_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1097 gint start, gint length, gboolean little_endian)
1101 pi = proto_tree_add_item(tree, hfindex, tvb, start, length, little_endian);
1105 PROTO_ITEM_SET_HIDDEN(pi);
1111 /* Add a FT_NONE to a proto_tree */
1113 proto_tree_add_none_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1114 gint length, const char *format, ...)
1118 header_field_info *hfinfo;
1123 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1124 DISSECTOR_ASSERT(hfinfo->type == FT_NONE);
1126 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, NULL);
1128 va_start(ap, format);
1129 proto_tree_set_representation(pi, format, ap);
1132 /* no value to set for FT_NONE */
1136 /* Gets data from tvbuff, adds it to proto_tree, *DOES NOT* increment
1137 * offset, and returns proto_item* */
1139 ptvcursor_add_no_advance(ptvcursor_t* ptvc, int hf, gint length,
1140 gboolean endianness)
1144 item = proto_tree_add_item(ptvc->tree, hf, ptvc->tvb, ptvc->offset,
1145 length, endianness);
1150 /* Advance the ptvcursor's offset within its tvbuff without
1151 * adding anything to the proto_tree. */
1153 ptvcursor_advance(ptvcursor_t* ptvc, gint length)
1155 ptvc->offset += length;
1160 proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb)
1162 fvalue_set(&fi->value, tvb, TRUE);
1165 /* Add a FT_PROTOCOL to a proto_tree */
1167 proto_tree_add_protocol_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1168 gint length, const char *format, ...)
1172 header_field_info *hfinfo;
1178 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1179 DISSECTOR_ASSERT(hfinfo->type == FT_PROTOCOL);
1181 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1183 va_start(ap, format);
1184 proto_tree_set_representation(pi, format, ap);
1188 proto_tree_set_protocol_tvb(new_fi, tvb);
1191 proto_tree_set_protocol_tvb(new_fi, NULL);
1197 /* Add a FT_BYTES to a proto_tree */
1199 proto_tree_add_bytes(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1200 gint length, const guint8 *start_ptr)
1204 header_field_info *hfinfo;
1209 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1211 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1212 DISSECTOR_ASSERT(hfinfo->type == FT_BYTES);
1214 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1215 proto_tree_set_bytes(new_fi, start_ptr, length);
1221 proto_tree_add_bytes_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1222 gint length, const guint8 *start_ptr)
1226 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length, start_ptr);
1230 PROTO_ITEM_SET_HIDDEN(pi);
1236 proto_tree_add_bytes_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1237 gint length, const guint8 *start_ptr, const char *format, ...)
1242 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length, start_ptr);
1246 va_start(ap, format);
1247 proto_tree_set_representation(pi, format, ap);
1254 proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length)
1258 bytes = g_byte_array_new();
1260 g_byte_array_append(bytes, start_ptr, length);
1262 fvalue_set(&fi->value, bytes, TRUE);
1267 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length)
1269 proto_tree_set_bytes(fi, tvb_get_ptr(tvb, offset, length), length);
1272 /* Add a FT_*TIME to a proto_tree */
1274 proto_tree_add_time(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1275 nstime_t *value_ptr)
1279 header_field_info *hfinfo;
1284 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1286 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1287 DISSECTOR_ASSERT(hfinfo->type == FT_ABSOLUTE_TIME ||
1288 hfinfo->type == FT_RELATIVE_TIME);
1290 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1291 proto_tree_set_time(new_fi, value_ptr);
1297 proto_tree_add_time_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1298 nstime_t *value_ptr)
1302 pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
1306 PROTO_ITEM_SET_HIDDEN(pi);
1312 proto_tree_add_time_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1313 nstime_t *value_ptr, const char *format, ...)
1318 pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
1322 va_start(ap, format);
1323 proto_tree_set_representation(pi, format, ap);
1329 /* Set the FT_*TIME value */
1331 proto_tree_set_time(field_info *fi, nstime_t *value_ptr)
1333 DISSECTOR_ASSERT(value_ptr != NULL);
1334 fvalue_set(&fi->value, value_ptr, FALSE);
1337 /* Add a FT_IPXNET to a proto_tree */
1339 proto_tree_add_ipxnet(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1344 header_field_info *hfinfo;
1349 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1351 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1352 DISSECTOR_ASSERT(hfinfo->type == FT_IPXNET);
1354 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1355 proto_tree_set_ipxnet(new_fi, value);
1361 proto_tree_add_ipxnet_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1366 pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
1370 PROTO_ITEM_SET_HIDDEN(pi);
1376 proto_tree_add_ipxnet_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1377 guint32 value, const char *format, ...)
1382 pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
1386 va_start(ap, format);
1387 proto_tree_set_representation(pi, format, ap);
1393 /* Set the FT_IPXNET value */
1395 proto_tree_set_ipxnet(field_info *fi, guint32 value)
1397 fvalue_set_integer(&fi->value, value);
1400 /* Add a FT_IPv4 to a proto_tree */
1402 proto_tree_add_ipv4(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1407 header_field_info *hfinfo;
1412 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1414 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1415 DISSECTOR_ASSERT(hfinfo->type == FT_IPv4);
1417 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1418 proto_tree_set_ipv4(new_fi, value);
1424 proto_tree_add_ipv4_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1429 pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
1433 PROTO_ITEM_SET_HIDDEN(pi);
1439 proto_tree_add_ipv4_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1440 guint32 value, const char *format, ...)
1445 pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
1449 va_start(ap, format);
1450 proto_tree_set_representation(pi, format, ap);
1456 /* Set the FT_IPv4 value */
1458 proto_tree_set_ipv4(field_info *fi, guint32 value)
1460 fvalue_set_integer(&fi->value, value);
1463 /* Add a FT_IPv6 to a proto_tree */
1465 proto_tree_add_ipv6(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1466 const guint8* value_ptr)
1470 header_field_info *hfinfo;
1475 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1477 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1478 DISSECTOR_ASSERT(hfinfo->type == FT_IPv6);
1480 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1481 proto_tree_set_ipv6(new_fi, value_ptr);
1487 proto_tree_add_ipv6_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1488 const guint8* value_ptr)
1492 pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
1496 PROTO_ITEM_SET_HIDDEN(pi);
1502 proto_tree_add_ipv6_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1503 const guint8* value_ptr, const char *format, ...)
1508 pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
1512 va_start(ap, format);
1513 proto_tree_set_representation(pi, format, ap);
1519 /* Set the FT_IPv6 value */
1521 proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr)
1523 DISSECTOR_ASSERT(value_ptr != NULL);
1524 fvalue_set(&fi->value, (gpointer) value_ptr, FALSE);
1528 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start)
1530 proto_tree_set_ipv6(fi, tvb_get_ptr(tvb, start, 16));
1533 /* Add a FT_GUID to a proto_tree */
1535 proto_tree_add_guid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1536 const guint8* value_ptr)
1540 header_field_info *hfinfo;
1545 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1547 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1548 DISSECTOR_ASSERT(hfinfo->type == FT_GUID);
1550 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1551 proto_tree_set_guid(new_fi, value_ptr);
1557 proto_tree_add_guid_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1558 const guint8* value_ptr)
1562 pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
1566 PROTO_ITEM_SET_HIDDEN(pi);
1572 proto_tree_add_guid_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1573 const guint8* value_ptr, const char *format, ...)
1578 pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
1582 va_start(ap, format);
1583 proto_tree_set_representation(pi, format, ap);
1589 /* Set the FT_GUID value */
1591 proto_tree_set_guid(field_info *fi, const guint8* value_ptr)
1593 DISSECTOR_ASSERT(value_ptr != NULL);
1594 fvalue_set(&fi->value, (gpointer) value_ptr, FALSE);
1598 proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, gint start)
1600 proto_tree_set_guid(fi, tvb_get_ptr(tvb, start, 16));
1604 proto_tree_set_uint64(field_info *fi, guint64 value)
1606 fvalue_set_integer64(&fi->value, value);
1610 proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start, gboolean little_endian)
1614 value = little_endian ? tvb_get_letoh64(tvb, start)
1615 : tvb_get_ntoh64(tvb, start);
1617 proto_tree_set_uint64(fi, value);
1620 /* Add a FT_STRING or FT_STRINGZ to a proto_tree. Creates own copy of string,
1621 * and frees it when the proto_tree is destroyed. */
1623 proto_tree_add_string(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1624 gint length, const char* value)
1628 header_field_info *hfinfo;
1633 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1635 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1636 DISSECTOR_ASSERT(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ);
1638 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1639 DISSECTOR_ASSERT(length >= 0);
1640 proto_tree_set_string(new_fi, value, FALSE);
1646 proto_tree_add_string_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1647 gint length, const char* value)
1651 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
1655 PROTO_ITEM_SET_HIDDEN(pi);
1661 proto_tree_add_string_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1662 gint length, const char* value, const char *format, ...)
1667 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
1671 va_start(ap, format);
1672 proto_tree_set_representation(pi, format, ap);
1678 /* Appends string data to a FT_STRING or FT_STRINGZ, allowing progressive
1679 * field info update instead of only updating the representation as does
1680 * proto_item_append_text()
1682 /* NOTE: this function will break with the TRY_TO_FAKE_THIS_ITEM()
1683 * speed optimization.
1684 * Currently only WSP use this function so it is not that bad but try to
1685 * avoid using this one if possible.
1686 * IF you must use this function you MUST also disable the
1687 * TRY_TO_FAKE_THIS_ITEM() optimization for your dissector/function
1688 * using proto_item_append_string().
1689 * Do that by faking that the tree is visible by setting :
1690 * PTREE_DATA(tree)->visible=1; (see packet-wsp.c)
1691 * BEFORE you create the item you are later going to use
1692 * proto_item_append_string() on.
1695 proto_item_append_string(proto_item *pi, const char *str)
1698 header_field_info *hfinfo;
1699 gchar *old_str, *new_str;
1706 fi = PITEM_FINFO(pi);
1707 hfinfo = fi->hfinfo;
1708 if (hfinfo->type == FT_PROTOCOL) {
1709 /* TRY_TO_FAKE_THIS_ITEM() speed optimization: silently skip */
1712 DISSECTOR_ASSERT(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ);
1713 old_str = fvalue_get(&fi->value);
1714 new_str = g_strdup_printf("%s%s", old_str, str);
1715 fvalue_set(&fi->value, new_str, TRUE);
1718 /* Set the FT_STRING value */
1720 proto_tree_set_string(field_info *fi, const char* value,
1721 gboolean already_allocated)
1724 fvalue_set(&fi->value, (gpointer) value, already_allocated);
1726 fvalue_set(&fi->value, (gpointer) "[ Null ]", already_allocated);
1730 proto_tree_set_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
1735 length = tvb_ensure_length_remaining(tvb, start);
1738 /* This memory is freed in proto_tree_free_node() */
1739 string = tvb_get_string(tvb, start, length);
1740 proto_tree_set_string(fi, string, TRUE);
1743 /* Add a FT_ETHER to a proto_tree */
1745 proto_tree_add_ether(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1746 const guint8* value)
1750 header_field_info *hfinfo;
1755 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1757 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1758 DISSECTOR_ASSERT(hfinfo->type == FT_ETHER);
1760 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1761 proto_tree_set_ether(new_fi, value);
1767 proto_tree_add_ether_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1768 const guint8* value)
1772 pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
1776 PROTO_ITEM_SET_HIDDEN(pi);
1782 proto_tree_add_ether_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1783 const guint8* value, const char *format, ...)
1788 pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
1792 va_start(ap, format);
1793 proto_tree_set_representation(pi, format, ap);
1799 /* Set the FT_ETHER value */
1801 proto_tree_set_ether(field_info *fi, const guint8* value)
1803 fvalue_set(&fi->value, (gpointer) value, FALSE);
1807 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start)
1809 proto_tree_set_ether(fi, tvb_get_ptr(tvb, start, 6));
1812 /* Add a FT_BOOLEAN to a proto_tree */
1814 proto_tree_add_boolean(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1819 header_field_info *hfinfo;
1824 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1826 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1827 DISSECTOR_ASSERT(hfinfo->type == FT_BOOLEAN);
1829 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1830 proto_tree_set_boolean(new_fi, value);
1836 proto_tree_add_boolean_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1841 pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
1845 PROTO_ITEM_SET_HIDDEN(pi);
1851 proto_tree_add_boolean_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1852 guint32 value, const char *format, ...)
1857 pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
1861 va_start(ap, format);
1862 proto_tree_set_representation(pi, format, ap);
1868 /* Set the FT_BOOLEAN value */
1870 proto_tree_set_boolean(field_info *fi, guint32 value)
1872 proto_tree_set_uint(fi, value);
1875 /* Add a FT_FLOAT to a proto_tree */
1877 proto_tree_add_float(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1882 header_field_info *hfinfo;
1887 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1889 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1890 DISSECTOR_ASSERT(hfinfo->type == FT_FLOAT);
1892 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1893 proto_tree_set_float(new_fi, value);
1899 proto_tree_add_float_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1904 pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
1908 PROTO_ITEM_SET_HIDDEN(pi);
1914 proto_tree_add_float_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1915 float value, const char *format, ...)
1920 pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
1924 va_start(ap, format);
1925 proto_tree_set_representation(pi, format, ap);
1931 /* Set the FT_FLOAT value */
1933 proto_tree_set_float(field_info *fi, float value)
1935 fvalue_set_floating(&fi->value, value);
1938 /* Add a FT_DOUBLE to a proto_tree */
1940 proto_tree_add_double(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1945 header_field_info *hfinfo;
1950 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1952 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1953 DISSECTOR_ASSERT(hfinfo->type == FT_DOUBLE);
1955 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1956 proto_tree_set_double(new_fi, value);
1962 proto_tree_add_double_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1967 pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
1971 PROTO_ITEM_SET_HIDDEN(pi);
1977 proto_tree_add_double_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1978 double value, const char *format, ...)
1983 pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
1987 va_start(ap, format);
1988 proto_tree_set_representation(pi, format, ap);
1994 /* Set the FT_DOUBLE value */
1996 proto_tree_set_double(field_info *fi, double value)
1998 fvalue_set_floating(&fi->value, value);
2001 /* Add FT_UINT{8,16,24,32} to a proto_tree */
2003 proto_tree_add_uint(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2006 proto_item *pi = NULL;
2008 header_field_info *hfinfo;
2013 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
2015 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2016 switch(hfinfo->type) {
2022 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length,
2024 proto_tree_set_uint(new_fi, value);
2028 DISSECTOR_ASSERT_NOT_REACHED();
2035 proto_tree_add_uint_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2040 pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
2044 PROTO_ITEM_SET_HIDDEN(pi);
2050 proto_tree_add_uint_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2051 guint32 value, const char *format, ...)
2056 pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
2060 va_start(ap, format);
2061 proto_tree_set_representation(pi, format, ap);
2067 /* Set the FT_UINT{8,16,24,32} value */
2069 proto_tree_set_uint(field_info *fi, guint32 value)
2071 header_field_info *hfinfo;
2074 hfinfo = fi->hfinfo;
2077 if (hfinfo->bitmask) {
2078 /* Mask out irrelevant portions */
2079 integer &= hfinfo->bitmask;
2082 if (hfinfo->bitshift > 0) {
2083 integer >>= hfinfo->bitshift;
2086 fvalue_set_integer(&fi->value, integer);
2089 /* Add FT_UINT64 to a proto_tree */
2091 proto_tree_add_uint64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2094 proto_item *pi = NULL;
2096 header_field_info *hfinfo;
2101 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
2103 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2104 DISSECTOR_ASSERT(hfinfo->type == FT_UINT64);
2106 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2107 proto_tree_set_uint64(new_fi, value);
2113 proto_tree_add_uint64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2114 guint64 value, const char *format, ...)
2119 pi = proto_tree_add_uint64(tree, hfindex, tvb, start, length, value);
2123 va_start(ap, format);
2124 proto_tree_set_representation(pi, format, ap);
2130 /* Add FT_INT{8,16,24,32} to a proto_tree */
2132 proto_tree_add_int(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2135 proto_item *pi = NULL;
2137 header_field_info *hfinfo;
2142 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
2144 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2145 switch(hfinfo->type) {
2150 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length,
2152 proto_tree_set_int(new_fi, value);
2156 DISSECTOR_ASSERT_NOT_REACHED();
2163 proto_tree_add_int_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2168 pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
2172 PROTO_ITEM_SET_HIDDEN(pi);
2178 proto_tree_add_int_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2179 gint32 value, const char *format, ...)
2181 proto_item *pi = NULL;
2184 pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
2188 va_start(ap, format);
2189 proto_tree_set_representation(pi, format, ap);
2195 /* Set the FT_INT{8,16,24,32} value */
2197 proto_tree_set_int(field_info *fi, gint32 value)
2199 header_field_info *hfinfo;
2202 hfinfo = fi->hfinfo;
2203 integer = (guint32) value;
2205 if (hfinfo->bitmask) {
2206 /* Mask out irrelevant portions */
2207 integer &= hfinfo->bitmask;
2210 if (hfinfo->bitshift > 0) {
2211 integer >>= hfinfo->bitshift;
2214 fvalue_set_integer(&fi->value, integer);
2217 /* Add FT_INT64 to a proto_tree */
2219 proto_tree_add_int64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2222 proto_item *pi = NULL;
2224 header_field_info *hfinfo;
2229 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
2231 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2232 DISSECTOR_ASSERT(hfinfo->type == FT_INT64);
2234 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2235 proto_tree_set_uint64(new_fi, (guint64)value);
2241 proto_tree_add_int64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2242 gint64 value, const char *format, ...)
2247 pi = proto_tree_add_int64(tree, hfindex, tvb, start, length, value);
2251 va_start(ap, format);
2252 proto_tree_set_representation(pi, format, ap);
2259 /* Add a field_info struct to the proto_tree, encapsulating it in a proto_node */
2261 proto_tree_add_node(proto_tree *tree, field_info *fi)
2263 proto_node *pnode, *tnode, *sibling;
2267 * Make sure "tree" is ready to have subtrees under it, by
2268 * checking whether it's been given an ett_ value.
2270 * "tnode->finfo" may be null; that's the case for the root
2271 * node of the protocol tree. That node is not displayed,
2272 * so it doesn't need an ett_ value to remember whether it
2277 if (tfi != NULL && (tfi->tree_type < 0 || tfi->tree_type >= num_tree_types)) {
2278 REPORT_DISSECTOR_BUG(ep_strdup_printf("\"%s\" - \"%s\" tfi->tree_type: %u invalid (%s:%u)",
2279 fi->hfinfo->name, fi->hfinfo->abbrev, tfi->tree_type, __FILE__, __LINE__));
2280 /* XXX - is it safe to continue here? */
2283 DISSECTOR_ASSERT(tfi == NULL ||
2284 (tfi->tree_type >= 0 && tfi->tree_type < num_tree_types));
2286 PROTO_NODE_NEW(pnode);
2287 pnode->parent = tnode;
2289 pnode->tree_data = PTREE_DATA(tree);
2291 if (tnode->last_child != NULL) {
2292 sibling = tnode->last_child;
2293 DISSECTOR_ASSERT(sibling->next == NULL);
2294 sibling->next = pnode;
2296 tnode->first_child = pnode;
2297 tnode->last_child = pnode;
2299 return (proto_item*)pnode;
2303 /* Generic way to allocate field_info and add to proto_tree.
2304 * Sets *pfi to address of newly-allocated field_info struct, if pfi is
2307 proto_tree_add_pi(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2308 gint *length, field_info **pfi)
2318 fi = alloc_field_info(tree, hfindex, tvb, start, length);
2319 pi = proto_tree_add_node(tree, fi);
2321 /* If the proto_tree wants to keep a record of this finfo
2322 * for quick lookup, then record it. */
2323 if (fi->hfinfo->ref_count) {
2324 hash = PTREE_DATA(tree)->interesting_hfids;
2325 ptrs = g_hash_table_lookup(hash, GINT_TO_POINTER(hfindex));
2327 g_ptr_array_add(ptrs, fi);
2331 /* Does the caller want to know the fi pointer? */
2340 static header_field_info *
2341 get_hfi_and_length(int hfindex, tvbuff_t *tvb, gint start, gint *length,
2344 header_field_info *hfinfo;
2345 gint length_remaining;
2348 * We only allow a null tvbuff if the item has a zero length,
2349 * i.e. if there's no data backing it.
2351 DISSECTOR_ASSERT(tvb != NULL || *length == 0);
2353 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2356 * XXX - in some protocols, there are 32-bit unsigned length
2357 * fields, so lengths in protocol tree and tvbuff routines
2358 * should really be unsigned. We should have, for those
2359 * field types for which "to the end of the tvbuff" makes sense,
2360 * additional routines that take no length argument and
2361 * add fields that run to the end of the tvbuff.
2363 if (*length == -1) {
2365 * For FT_NONE, FT_PROTOCOL, FT_BYTES, and FT_STRING fields,
2366 * a length of -1 means "set the length to what remains in
2369 * The assumption is either that
2371 * 1) the length of the item can only be determined
2372 * by dissection (typically true of items with
2373 * subitems, which are probably FT_NONE or
2378 * 2) if the tvbuff is "short" (either due to a short
2379 * snapshot length or due to lack of reassembly of
2380 * fragments/segments/whatever), we want to display
2381 * what's available in the field (probably FT_BYTES
2382 * or FT_STRING) and then throw an exception later
2386 * 3) the field is defined to be "what's left in the
2389 * so we set the length to what remains in the tvbuff so
2390 * that, if we throw an exception while dissecting, it
2391 * has what is probably the right value.
2393 * For FT_STRINGZ, it means "the string is null-terminated,
2394 * not null-padded; set the length to the actual length
2395 * of the string", and if the tvbuff if short, we just
2396 * throw an exception.
2398 * It's not valid for any other type of field.
2400 switch (hfinfo->type) {
2404 * We allow this to be zero-length - for
2405 * example, an ONC RPC NULL procedure has
2406 * neither arguments nor reply, so the
2407 * payload for that protocol is empty.
2409 * However, if the length is negative, the
2410 * start offset is *past* the byte past the
2411 * end of the tvbuff, so we throw an
2414 *length = tvb_length_remaining(tvb, start);
2417 * Use "tvb_ensure_bytes_exist()"
2418 * to force the appropriate exception
2421 tvb_ensure_bytes_exist(tvb, start, 0);
2423 DISSECTOR_ASSERT(*length >= 0);
2429 *length = tvb_ensure_length_remaining(tvb, start);
2430 DISSECTOR_ASSERT(*length >= 0);
2435 * Leave the length as -1, so our caller knows
2441 DISSECTOR_ASSERT_NOT_REACHED();
2443 *item_length = *length;
2445 *item_length = *length;
2446 if (hfinfo->type == FT_PROTOCOL || hfinfo->type == FT_NONE) {
2448 * These types are for interior nodes of the
2449 * tree, and don't have data associated with
2450 * them; if the length is negative (XXX - see
2451 * above) or goes past the end of the tvbuff,
2452 * cut it short at the end of the tvbuff.
2453 * That way, if this field is selected in
2454 * Ethereal, we don't highlight stuff past
2455 * the end of the data.
2457 /* XXX - what to do, if we don't have a tvb? */
2459 length_remaining = tvb_length_remaining(tvb, start);
2460 if (*item_length < 0 ||
2461 (*item_length > 0 &&
2462 (length_remaining < *item_length)))
2463 *item_length = length_remaining;
2466 if (*item_length < 0) {
2467 THROW(ReportedBoundsError);
2475 new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
2476 gint start, gint item_length)
2482 fi->hfinfo = hfinfo;
2484 fi->start+=(tvb)?TVB_RAW_OFFSET(tvb):0;
2485 fi->length = item_length;
2488 if (!PTREE_DATA(tree)->visible)
2489 FI_SET_FLAG(fi, FI_HIDDEN);
2490 fvalue_init(&fi->value, fi->hfinfo->type);
2493 /* add the data source tvbuff */
2494 fi->ds_tvb=tvb?TVB_GET_DS_TVB(tvb):NULL;
2500 alloc_field_info(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2503 header_field_info *hfinfo;
2506 hfinfo = get_hfi_and_length(hfindex, tvb, start, length, &item_length);
2507 return new_field_info(tree, hfinfo, tvb, start, item_length);
2510 /* Set representation of a proto_tree entry, if the protocol tree is to
2513 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap)
2515 int ret; /*tmp return value */
2516 field_info *fi = PITEM_FINFO(pi);
2518 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
2519 ITEM_LABEL_NEW(fi->rep);
2520 ret = g_vsnprintf(fi->rep->representation, ITEM_LABEL_LENGTH, format, ap);
2521 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
2522 fi->rep->representation[ITEM_LABEL_LENGTH - 1] = '\0';
2526 /* Set text of proto_item after having already been created. */
2528 proto_item_set_text(proto_item *pi, const char *format, ...)
2530 field_info *fi = NULL;
2537 fi = PITEM_FINFO(pi);
2540 ITEM_LABEL_FREE(fi->rep);
2543 va_start(ap, format);
2544 proto_tree_set_representation(pi, format, ap);
2548 /* Append to text of proto_item after having already been created. */
2550 proto_item_append_text(proto_item *pi, const char *format, ...)
2552 field_info *fi = NULL;
2555 int ret; /*tmp return value */
2561 fi = PITEM_FINFO(pi);
2563 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
2564 va_start(ap, format);
2567 * If we don't already have a representation,
2568 * generate the default representation.
2570 if (fi->rep == NULL) {
2571 ITEM_LABEL_NEW(fi->rep);
2572 proto_item_fill_label(fi, fi->rep->representation);
2575 curlen = strlen(fi->rep->representation);
2576 if (ITEM_LABEL_LENGTH > curlen) {
2577 ret = g_vsnprintf(fi->rep->representation + curlen,
2578 ITEM_LABEL_LENGTH - curlen, format, ap);
2579 if ((ret == -1) || (ret >= (int)(ITEM_LABEL_LENGTH - curlen)))
2580 fi->rep->representation[ITEM_LABEL_LENGTH - 1] = '\0';
2587 proto_item_set_len(proto_item *pi, gint length)
2593 fi = PITEM_FINFO(pi);
2594 DISSECTOR_ASSERT(length >= 0);
2595 fi->length = length;
2599 * Sets the length of the item based on its start and on the specified
2600 * offset, which is the offset past the end of the item; as the start
2601 * in the item is relative to the beginning of the data source tvbuff,
2602 * we need to pass in a tvbuff - the end offset is relative to the beginning
2606 proto_item_set_end(proto_item *pi, tvbuff_t *tvb, gint end)
2612 fi = PITEM_FINFO(pi);
2613 end += TVB_RAW_OFFSET(tvb);
2614 DISSECTOR_ASSERT(end >= fi->start);
2615 fi->length = end - fi->start;
2619 proto_item_get_len(proto_item *pi)
2621 field_info *fi = PITEM_FINFO(pi);
2626 /** clear flags according to the mask and set new flag values */
2627 #define FI_REPLACE_FLAGS(fi, mask, flags_in) { \
2628 (fi->flags = (fi)->flags & ~(mask)); \
2629 (fi->flags = (fi)->flags | (flags_in)); \
2633 proto_item_set_expert_flags(proto_item *pi, int group, int severity)
2635 if(pi == NULL || pi->finfo == NULL)
2638 /* only change things if severity is worse or at least equal than before */
2639 if(severity >= FI_GET_FLAG(pi->finfo, PI_SEVERITY_MASK)) {
2640 FI_REPLACE_FLAGS(pi->finfo, PI_GROUP_MASK, group);
2641 FI_REPLACE_FLAGS(pi->finfo, PI_SEVERITY_MASK, severity);
2652 proto_tree_create_root(void)
2656 /* Initialize the proto_node */
2657 PROTO_NODE_NEW(pnode);
2658 pnode->parent = NULL;
2659 pnode->finfo = NULL;
2660 pnode->tree_data = g_new(tree_data_t, 1);
2662 /* Initialize the tree_data_t */
2663 pnode->tree_data->interesting_hfids =
2664 g_hash_table_new(g_direct_hash, g_direct_equal);
2666 /* Set the default to FALSE so it's easier to
2667 * find errors; if we expect to see the protocol tree
2668 * but for some reason the default 'visible' is not
2669 * changed, then we'll find out very quickly. */
2670 pnode->tree_data->visible = FALSE;
2672 return (proto_tree*) pnode;
2676 /* "prime" a proto_tree with a single hfid that a dfilter
2677 * is interested in. */
2679 proto_tree_prime_hfid(proto_tree *tree, gint hfid)
2681 header_field_info *hfinfo;
2683 g_hash_table_insert(PTREE_DATA(tree)->interesting_hfids,
2684 GINT_TO_POINTER(hfid), g_ptr_array_new());
2686 PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
2687 /* this field is referenced by a filter so increase the refcount.
2688 also increase the refcount for the parent, i.e the protocol.
2690 hfinfo->ref_count++;
2691 /* only increase the refcount if there is a parent.
2692 if this is a protocol and not a field then parent will be -1
2693 and there is no parent to add any refcounting for.
2695 if (hfinfo->parent != -1) {
2696 header_field_info *parent_hfinfo;
2697 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
2698 parent_hfinfo->ref_count++;
2703 proto_item_add_subtree(proto_item *pi, gint idx) {
2709 fi = PITEM_FINFO(pi);
2710 DISSECTOR_ASSERT(idx >= 0 && idx < num_tree_types);
2711 fi->tree_type = idx;
2713 return (proto_tree*) pi;
2717 proto_item_get_subtree(proto_item *pi) {
2722 fi = PITEM_FINFO(pi);
2723 if ( (!fi) || (fi->tree_type == -1) )
2725 return (proto_tree*) pi;
2729 proto_item_get_parent(proto_item *ti) {
2730 /* dont bother if tree is not visible */
2731 if( (!ti) || (!(PTREE_DATA(ti)->visible)) )
2737 proto_item_get_parent_nth(proto_item *ti, int gen) {
2738 /* dont bother if tree is not visible */
2739 if( (!ti) || (!(PTREE_DATA(ti)->visible)) )
2751 proto_tree_get_parent(proto_tree *tree) {
2752 /* dont bother if tree is not visible */
2753 if( (!tree) || (!(PTREE_DATA(tree)->visible)) )
2755 return (proto_item*) tree;
2760 proto_tree_move_item(proto_tree *tree, proto_item *fixed_item, proto_item *item_to_move)
2762 proto_item *curr_item;
2765 /*** cut item_to_move out ***/
2767 /* is item_to_move the first? */
2768 if(tree->first_child == item_to_move) {
2769 /* simply change first child to next */
2770 tree->first_child = item_to_move->next;
2772 /* find previous and change it's next */
2773 for(curr_item = tree->first_child; curr_item != NULL; curr_item = curr_item->next) {
2774 if(curr_item->next == item_to_move) {
2779 DISSECTOR_ASSERT(curr_item);
2781 curr_item->next = item_to_move->next;
2783 /* fix last_child if required */
2784 if(tree->last_child == item_to_move) {
2785 tree->last_child = curr_item;
2789 /*** insert to_move after fixed ***/
2790 item_to_move->next = fixed_item->next;
2791 fixed_item->next = item_to_move;
2792 if(tree->last_child == fixed_item) {
2793 tree->last_child = item_to_move;
2799 proto_register_protocol(const char *name, const char *short_name, const char *filter_name)
2801 protocol_t *protocol;
2802 header_field_info *hfinfo;
2804 char *existing_name;
2807 gboolean found_invalid;
2810 * Make sure there's not already a protocol with any of those
2811 * names. Crash if there is, as that's an error in the code
2812 * or an inappropriate plugin.
2813 * This situation has to be fixed to not register more than one
2814 * protocol with the same name.
2816 * This is done by reducing the number of strcmp (and alike) calls as much as possible,
2817 * as this significally slows down startup time.
2819 * Drawback: As a hash value is used to reduce insert time,
2820 * this might lead to a hash collision.
2821 * However, as we have around 500+ protocols and we're using a 32 bit int this is very,
2825 key = g_malloc (sizeof(gint));
2826 *key = g_str_hash(name);
2827 existing_name = g_hash_table_lookup(proto_names, key);
2828 if (existing_name != NULL) {
2829 /* g_error will terminate the program */
2830 g_error("Duplicate protocol name \"%s\"!"
2831 " This might be caused by an inappropriate plugin or a development error.", name);
2833 g_hash_table_insert(proto_names, key, (gpointer)name);
2835 key = g_malloc (sizeof(gint));
2836 *key = g_str_hash(short_name);
2837 existing_name = g_hash_table_lookup(proto_short_names, key);
2838 if (existing_name != NULL) {
2839 g_error("Duplicate protocol short_name \"%s\"!"
2840 " This might be caused by an inappropriate plugin or a development error.", short_name);
2842 g_hash_table_insert(proto_short_names, key, (gpointer)short_name);
2844 found_invalid = FALSE;
2845 for (i = 0; i < strlen(filter_name); i++) {
2846 if (! (islower(filter_name[i]) ||
2847 isdigit(filter_name[i]) ||
2848 filter_name[i] == '-' ||
2849 filter_name[i] == '_' ||
2850 filter_name[i] == '.' )) {
2851 found_invalid = TRUE;
2854 if (found_invalid) {
2855 g_warning("Protocol filter name \"%s\" has one or more invalid characters.", filter_name);
2857 key = g_malloc (sizeof(gint));
2858 *key = g_str_hash(filter_name);
2859 existing_name = g_hash_table_lookup(proto_filter_names, key);
2860 if (existing_name != NULL) {
2861 g_error("Duplicate protocol filter_name \"%s\"!"
2862 " This might be caused by an inappropriate plugin or a development error.", filter_name);
2864 g_hash_table_insert(proto_filter_names, key, (gpointer)filter_name);
2866 /* Add this protocol to the list of known protocols; the list
2867 is sorted by protocol short name. */
2868 protocol = g_malloc(sizeof (protocol_t));
2869 protocol->name = name;
2870 protocol->short_name = short_name;
2871 protocol->filter_name = filter_name;
2872 protocol->fields = NULL;
2873 protocol->is_enabled = TRUE; /* protocol is enabled by default */
2874 protocol->can_toggle = TRUE;
2875 /* list will be sorted later by name, when all protocols completed registering */
2876 protocols = g_list_append(protocols, protocol);
2878 /* Here we do allocate a new header_field_info struct */
2879 hfinfo = g_mem_chunk_alloc(gmc_hfinfo);
2880 hfinfo->name = name;
2881 hfinfo->abbrev = filter_name;
2882 hfinfo->type = FT_PROTOCOL;
2883 hfinfo->strings = protocol;
2884 hfinfo->bitmask = 0;
2885 hfinfo->bitshift = 0;
2886 hfinfo->ref_count = 0;
2888 hfinfo->parent = -1; /* this field differentiates protos and fields */
2890 proto_id = proto_register_field_init(hfinfo, hfinfo->parent);
2891 protocol->proto_id = proto_id;
2896 * Routines to use to iterate over the protocols.
2897 * The argument passed to the iterator routines is an opaque cookie to
2898 * their callers; it's the GList pointer for the current element in
2900 * The ID of the protocol is returned, or -1 if there is no protocol.
2903 proto_get_first_protocol(void **cookie)
2905 protocol_t *protocol;
2907 if (protocols == NULL)
2909 *cookie = protocols;
2910 protocol = protocols->data;
2911 return protocol->proto_id;
2915 proto_get_next_protocol(void **cookie)
2917 GList *list_item = *cookie;
2918 protocol_t *protocol;
2920 list_item = g_list_next(list_item);
2921 if (list_item == NULL)
2923 *cookie = list_item;
2924 protocol = list_item->data;
2925 return protocol->proto_id;
2929 proto_get_first_protocol_field(int proto_id, void **cookie)
2931 protocol_t *protocol = find_protocol_by_id(proto_id);
2932 hf_register_info *ptr;
2934 if ((protocol == NULL) || (protocol->fields == NULL))
2937 *cookie = protocol->fields;
2938 ptr = protocol->fields->data;
2939 return &ptr->hfinfo;
2943 proto_get_next_protocol_field(void **cookie)
2945 GList *list_item = *cookie;
2946 hf_register_info *ptr;
2948 list_item = g_list_next(list_item);
2949 if (list_item == NULL)
2952 *cookie = list_item;
2953 ptr = list_item->data;
2954 return &ptr->hfinfo;
2958 find_protocol_by_id(int proto_id)
2960 header_field_info *hfinfo;
2965 PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
2966 DISSECTOR_ASSERT(hfinfo->type==FT_PROTOCOL);
2967 return (protocol_t *)hfinfo->strings;
2970 static gint compare_filter_name(gconstpointer proto_arg,
2971 gconstpointer filter_name)
2973 const protocol_t *protocol = proto_arg;
2974 const gchar* f_name = filter_name;
2976 return (strcmp(protocol->filter_name, f_name));
2980 proto_get_id(protocol_t *protocol)
2982 return protocol->proto_id;
2985 int proto_get_id_by_filter_name(const gchar* filter_name)
2988 protocol_t *protocol;
2990 list_entry = g_list_find_custom(protocols, filter_name,
2991 compare_filter_name);
2992 if (list_entry == NULL)
2994 protocol = list_entry->data;
2995 return protocol->proto_id;
2999 proto_get_protocol_name(int proto_id)
3001 protocol_t *protocol;
3003 protocol = find_protocol_by_id(proto_id);
3004 return protocol->name;
3008 proto_get_protocol_short_name(protocol_t *protocol)
3010 if (protocol == NULL)
3012 return protocol->short_name;
3016 proto_get_protocol_filter_name(int proto_id)
3018 protocol_t *protocol;
3020 protocol = find_protocol_by_id(proto_id);
3021 return protocol->filter_name;
3025 proto_is_protocol_enabled(protocol_t *protocol)
3027 return protocol->is_enabled;
3031 proto_can_toggle_protocol(int proto_id)
3033 protocol_t *protocol;
3035 protocol = find_protocol_by_id(proto_id);
3036 return protocol->can_toggle;
3040 proto_set_decoding(int proto_id, gboolean enabled)
3042 protocol_t *protocol;
3044 protocol = find_protocol_by_id(proto_id);
3045 DISSECTOR_ASSERT(protocol->can_toggle);
3046 protocol->is_enabled = enabled;
3050 proto_set_cant_toggle(int proto_id)
3052 protocol_t *protocol;
3054 protocol = find_protocol_by_id(proto_id);
3055 protocol->can_toggle = FALSE;
3058 /* for use with static arrays only, since we don't allocate our own copies
3059 of the header_field_info struct contained within the hf_register_info struct */
3061 proto_register_field_array(int parent, hf_register_info *hf, int num_records)
3064 hf_register_info *ptr = hf;
3067 proto = find_protocol_by_id(parent);
3068 for (i = 0; i < num_records; i++, ptr++) {
3070 * Make sure we haven't registered this yet.
3071 * Most fields have variables associated with them
3072 * that are initialized to -1; some have array elements,
3073 * or possibly uninitialized variables, so we also allow
3074 * 0 (which is unlikely to be the field ID we get back
3075 * from "proto_register_field_init()").
3077 if (*ptr->p_id != -1 && *ptr->p_id != 0) {
3079 "Duplicate field detected in call to proto_register_field_array: %s is already registered\n",
3084 if (proto != NULL) {
3085 if (proto->fields == NULL) {
3086 proto->fields = g_list_append(NULL, ptr);
3087 proto->last_field = proto->fields;
3090 g_list_append(proto->last_field, ptr)->next;
3093 field_id = proto_register_field_init(&ptr->hfinfo, parent);
3094 *ptr->p_id = field_id;
3099 proto_register_field_init(header_field_info *hfinfo, int parent)
3101 /* The field must have names */
3102 DISSECTOR_ASSERT(hfinfo->name);
3103 DISSECTOR_ASSERT(hfinfo->abbrev);
3105 /* These types of fields are allowed to have value_strings, true_false_strings or a protocol_t struct*/
3106 DISSECTOR_ASSERT((hfinfo->strings == NULL) || (
3107 (hfinfo->type == FT_UINT8) ||
3108 (hfinfo->type == FT_UINT16) ||
3109 (hfinfo->type == FT_UINT24) ||
3110 (hfinfo->type == FT_UINT32) ||
3111 (hfinfo->type == FT_INT8) ||
3112 (hfinfo->type == FT_INT16) ||
3113 (hfinfo->type == FT_INT24) ||
3114 (hfinfo->type == FT_INT32) ||
3115 (hfinfo->type == FT_BOOLEAN) ||
3116 (hfinfo->type == FT_PROTOCOL) ||
3117 (hfinfo->type == FT_FRAMENUM) ));
3119 switch (hfinfo->type) {
3129 /* Require integral types (other than frame number, which is
3130 always displayed in decimal) to have a number base */
3131 DISSECTOR_ASSERT(hfinfo->display != BASE_NONE);
3135 /* Don't allow bitfields or value strings for frame numbers */
3136 DISSECTOR_ASSERT(hfinfo->bitmask == 0);
3137 DISSECTOR_ASSERT(hfinfo->strings == NULL);
3143 /* if this is a bitfield, compute bitshift */
3144 if (hfinfo->bitmask) {
3145 while ((hfinfo->bitmask & (1 << hfinfo->bitshift)) == 0)
3149 hfinfo->parent = parent;
3150 hfinfo->same_name_next = NULL;
3151 hfinfo->same_name_prev = NULL;
3153 /* if we always add and never delete, then id == len - 1 is correct */
3154 if(gpa_hfinfo.len>=gpa_hfinfo.allocated_len){
3155 if(!gpa_hfinfo.hfi){
3156 gpa_hfinfo.allocated_len=1000;
3157 gpa_hfinfo.hfi=g_malloc(sizeof(header_field_info *)*1000);
3159 gpa_hfinfo.allocated_len+=1000;
3160 gpa_hfinfo.hfi=g_realloc(gpa_hfinfo.hfi, sizeof(header_field_info *)*gpa_hfinfo.allocated_len);
3163 gpa_hfinfo.hfi[gpa_hfinfo.len]=hfinfo;
3165 hfinfo->id = gpa_hfinfo.len - 1;
3167 /* if we have real names, enter this field in the name tree */
3168 if ((hfinfo->name[0] != 0) && (hfinfo->abbrev[0] != 0 )) {
3170 header_field_info *same_name_hfinfo, *same_name_next_hfinfo;
3174 /* Check that the filter name (abbreviation) is legal;
3175 * it must contain only alphanumerics, '-', "_", and ".". */
3176 for (p = hfinfo->abbrev; (c = *p) != '\0'; p++)
3177 DISSECTOR_ASSERT(isalnum(c) || c == '-' || c == '_' ||
3180 /* We allow multiple hfinfo's to be registered under the same
3181 * abbreviation. This was done for X.25, as, depending
3182 * on whether it's modulo-8 or modulo-128 operation,
3183 * some bitfield fields may be in different bits of
3184 * a byte, and we want to be able to refer to that field
3185 * with one name regardless of whether the packets
3186 * are modulo-8 or modulo-128 packets. */
3187 same_name_hfinfo = g_tree_lookup(gpa_name_tree, hfinfo->abbrev);
3188 if (same_name_hfinfo) {
3189 /* There's already a field with this name.
3190 * Put it after that field in the list of
3191 * fields with this name, then allow the code
3192 * after this if{} block to replace the old
3193 * hfinfo with the new hfinfo in the GTree. Thus,
3194 * we end up with a linked-list of same-named hfinfo's,
3195 * with the root of the list being the hfinfo in the GTree */
3196 same_name_next_hfinfo =
3197 same_name_hfinfo->same_name_next;
3199 hfinfo->same_name_next = same_name_next_hfinfo;
3200 if (same_name_next_hfinfo)
3201 same_name_next_hfinfo->same_name_prev = hfinfo;
3203 same_name_hfinfo->same_name_next = hfinfo;
3204 hfinfo->same_name_prev = same_name_hfinfo;
3206 g_tree_insert(gpa_name_tree, (gpointer) (hfinfo->abbrev), hfinfo);
3213 proto_register_subtree_array(gint *const *indices, int num_indices)
3216 gint *const *ptr = indices;
3219 * If we've already allocated the array of tree types, expand
3220 * it; this lets plugins such as mate add tree types after
3221 * the initial startup. (If we haven't already allocated it,
3222 * we don't allocate it; on the first pass, we just assign
3223 * ett values and keep track of how many we've assigned, and
3224 * when we're finished registering all dissectors we allocate
3225 * the array, so that we do only one allocation rather than
3226 * wasting CPU time and memory by growing the array for each
3227 * dissector that registers ett values.)
3229 if (tree_is_expanded != NULL) {
3231 g_realloc(tree_is_expanded,
3232 (num_tree_types+num_indices)*sizeof (gint *));
3233 memset(tree_is_expanded + num_tree_types, 0,
3234 num_indices*sizeof (gint *));
3238 * Assign "num_indices" subtree numbers starting at "num_tree_types",
3239 * returning the indices through the pointers in the array whose
3240 * first element is pointed to by "indices", and update
3241 * "num_tree_types" appropriately.
3243 for (i = 0; i < num_indices; i++, ptr++, num_tree_types++)
3244 **ptr = num_tree_types;
3248 proto_item_fill_label(field_info *fi, gchar *label_str)
3250 header_field_info *hfinfo = fi->hfinfo;
3255 guint32 n_addr; /* network-order IPv4 address */
3256 int ret; /*tmp return value */
3258 switch(hfinfo->type) {
3261 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3262 "%s", hfinfo->name);
3263 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3264 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3268 fill_label_boolean(fi, label_str);
3273 bytes = fvalue_get(&fi->value);
3275 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3276 "%s: %s", hfinfo->name,
3277 bytes_to_str(bytes, fvalue_length(&fi->value)));
3278 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3279 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3282 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3283 "%s: <MISSING>", hfinfo->name);
3284 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3285 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3289 /* Four types of integers to take care of:
3290 * Bitfield, with val_string
3291 * Bitfield, w/o val_string
3292 * Non-bitfield, with val_string
3293 * Non-bitfield, w/o val_string
3300 if (hfinfo->bitmask) {
3301 if (hfinfo->strings) {
3302 fill_label_enumerated_bitfield(fi, label_str);
3305 fill_label_numeric_bitfield(fi, label_str);
3309 if (hfinfo->strings) {
3310 fill_label_enumerated_uint(fi, label_str);
3313 fill_label_uint(fi, label_str);
3319 fill_label_uint64(fi, label_str);
3326 DISSECTOR_ASSERT(!hfinfo->bitmask);
3327 if (hfinfo->strings) {
3328 fill_label_enumerated_int(fi, label_str);
3331 fill_label_int(fi, label_str);
3336 fill_label_int64(fi, label_str);
3340 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3341 "%s: %." STRINGIFY(FLT_DIG) "f",
3342 hfinfo->name, fvalue_get_floating(&fi->value));
3343 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3344 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3348 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3349 "%s: %." STRINGIFY(DBL_DIG) "g",
3350 hfinfo->name, fvalue_get_floating(&fi->value));
3351 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3352 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3355 case FT_ABSOLUTE_TIME:
3356 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3357 "%s: %s", hfinfo->name,
3358 abs_time_to_str(fvalue_get(&fi->value)));
3359 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3360 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3363 case FT_RELATIVE_TIME:
3364 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3365 "%s: %s seconds", hfinfo->name,
3366 rel_time_to_secs_str(fvalue_get(&fi->value)));
3367 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3368 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3372 integer = fvalue_get_integer(&fi->value);
3373 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3374 "%s: %s (0x%08X)", hfinfo->name,
3375 get_ipxnet_name(integer), integer);
3376 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3377 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3381 bytes = fvalue_get(&fi->value);
3382 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3383 "%s: %s (%s)", hfinfo->name,
3384 get_ether_name(bytes),
3385 ether_to_str(bytes));
3386 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3387 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3391 ipv4 = fvalue_get(&fi->value);
3392 n_addr = ipv4_get_net_order_addr(ipv4);
3393 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3394 "%s: %s (%s)", hfinfo->name,
3395 get_hostname(n_addr),
3396 ip_to_str((guint8*)&n_addr));
3397 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3398 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3402 bytes = fvalue_get(&fi->value);
3403 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3404 "%s: %s (%s)", hfinfo->name,
3405 get_hostname6((struct e_in6_addr *)bytes),
3406 ip6_to_str((struct e_in6_addr*)bytes));
3407 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3408 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3412 bytes = fvalue_get(&fi->value);
3413 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3414 "%s: %s", hfinfo->name,
3415 guid_to_str(bytes));
3416 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3417 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3422 case FT_UINT_STRING:
3423 bytes = fvalue_get(&fi->value);
3424 if(strlen(bytes) > ITEM_LABEL_LENGTH) {
3425 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3426 "%s [truncated]: %s", hfinfo->name,
3427 format_text(bytes, strlen(bytes)));
3429 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3430 "%s: %s", hfinfo->name,
3431 format_text(bytes, strlen(bytes)));
3433 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3434 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3438 g_error("hfinfo->type %d (%s) not handled\n",
3440 ftype_name(hfinfo->type));
3441 DISSECTOR_ASSERT_NOT_REACHED();
3447 fill_label_boolean(field_info *fi, gchar *label_str)
3449 char *p = label_str;
3450 int bitfield_byte_length = 0, bitwidth;
3451 guint32 unshifted_value;
3453 int ret; /*tmp return value */
3455 header_field_info *hfinfo = fi->hfinfo;
3456 static const true_false_string default_tf = { "True", "False" };
3457 const true_false_string *tfstring = &default_tf;
3459 if (hfinfo->strings) {
3460 tfstring = (const struct true_false_string*) hfinfo->strings;
3463 value = fvalue_get_integer(&fi->value);
3464 if (hfinfo->bitmask) {
3465 /* Figure out the bit width */
3466 bitwidth = hfinfo_bitwidth(hfinfo);
3469 unshifted_value = value;
3470 if (hfinfo->bitshift > 0) {
3471 unshifted_value <<= hfinfo->bitshift;
3474 /* Create the bitfield first */
3475 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
3476 bitfield_byte_length = p - label_str;
3479 /* Fill in the textual info */
3480 ret = g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
3481 "%s: %s", hfinfo->name,
3482 value ? tfstring->true_string : tfstring->false_string);
3483 if ((ret == -1) || (ret >= (ITEM_LABEL_LENGTH - bitfield_byte_length)))
3484 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3488 /* Fills data for bitfield ints with val_strings */
3490 fill_label_enumerated_bitfield(field_info *fi, gchar *label_str)
3492 const char *format = NULL;
3494 int bitfield_byte_length, bitwidth;
3495 guint32 unshifted_value;
3497 int ret; /*tmp return value */
3499 header_field_info *hfinfo = fi->hfinfo;
3501 /* Figure out the bit width */
3502 bitwidth = hfinfo_bitwidth(hfinfo);
3504 /* Pick the proper format string */
3505 format = hfinfo_uint_vals_format(hfinfo);
3508 unshifted_value = fvalue_get_integer(&fi->value);
3509 value = unshifted_value;
3510 if (hfinfo->bitshift > 0) {
3511 unshifted_value <<= hfinfo->bitshift;
3514 /* Create the bitfield first */
3515 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
3516 bitfield_byte_length = p - label_str;
3518 /* Fill in the textual info using stored (shifted) value */
3519 ret = g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
3520 format, hfinfo->name,
3521 val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
3522 if ((ret == -1) || (ret >= (ITEM_LABEL_LENGTH - bitfield_byte_length)))
3523 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3527 fill_label_numeric_bitfield(field_info *fi, gchar *label_str)
3529 const char *format = NULL;
3531 int bitfield_byte_length, bitwidth;
3532 guint32 unshifted_value;
3534 int ret; /*tmp return value */
3536 header_field_info *hfinfo = fi->hfinfo;
3538 /* Figure out the bit width */
3539 bitwidth = hfinfo_bitwidth(hfinfo);
3541 /* Pick the proper format string */
3542 format = hfinfo_uint_format(hfinfo);
3545 unshifted_value = fvalue_get_integer(&fi->value);
3546 value = unshifted_value;
3547 if (hfinfo->bitshift > 0) {
3548 unshifted_value <<= hfinfo->bitshift;
3551 /* Create the bitfield using */
3552 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
3553 bitfield_byte_length = p - label_str;
3555 /* Fill in the textual info using stored (shifted) value */
3556 if (IS_BASE_DUAL(hfinfo->display)) {
3557 ret = g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
3558 format, hfinfo->name, value, value);
3560 ret = g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
3561 format, hfinfo->name, value);
3563 if ((ret == -1) || (ret >= (ITEM_LABEL_LENGTH - bitfield_byte_length)))
3564 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3569 fill_label_enumerated_uint(field_info *fi, gchar *label_str)
3571 const char *format = NULL;
3572 header_field_info *hfinfo = fi->hfinfo;
3574 int ret; /*tmp return value */
3576 /* Pick the proper format string */
3577 format = hfinfo_uint_vals_format(hfinfo);
3579 value = fvalue_get_integer(&fi->value);
3581 /* Fill in the textual info */
3582 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3583 format, hfinfo->name,
3584 val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
3585 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3586 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3590 fill_label_uint(field_info *fi, gchar *label_str)
3592 const char *format = NULL;
3593 header_field_info *hfinfo = fi->hfinfo;
3595 int ret; /*tmp return value */
3597 /* Pick the proper format string */
3598 format = hfinfo_uint_format(hfinfo);
3599 value = fvalue_get_integer(&fi->value);
3601 /* Fill in the textual info */
3602 if (IS_BASE_DUAL(hfinfo->display)) {
3603 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3604 format, hfinfo->name, value, value);
3606 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3607 format, hfinfo->name, value);
3609 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3610 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3614 fill_label_uint64(field_info *fi, gchar *label_str)
3616 const char *format = NULL;
3617 header_field_info *hfinfo = fi->hfinfo;
3619 int ret; /*tmp return value */
3621 /* Pick the proper format string */
3622 format = hfinfo_uint64_format(hfinfo);
3623 value = fvalue_get_integer64(&fi->value);
3625 /* Fill in the textual info */
3626 if (IS_BASE_DUAL(hfinfo->display)) {
3627 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3628 format, hfinfo->name, value, value);
3630 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3631 format, hfinfo->name, value);
3633 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3634 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3638 fill_label_enumerated_int(field_info *fi, gchar *label_str)
3640 const char *format = NULL;
3641 header_field_info *hfinfo = fi->hfinfo;
3643 int ret; /*tmp return value */
3645 /* Pick the proper format string */
3646 format = hfinfo_int_vals_format(hfinfo);
3647 value = fvalue_get_integer(&fi->value);
3649 /* Fill in the textual info */
3650 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3651 format, hfinfo->name,
3652 val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
3653 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3654 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3658 fill_label_int(field_info *fi, gchar *label_str)
3660 const char *format = NULL;
3661 header_field_info *hfinfo = fi->hfinfo;
3663 int ret; /*tmp return value */
3665 /* Pick the proper format string */
3666 format = hfinfo_int_format(hfinfo);
3667 value = fvalue_get_integer(&fi->value);
3669 /* Fill in the textual info */
3670 if (IS_BASE_DUAL(hfinfo->display)) {
3671 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3672 format, hfinfo->name, value, value);
3674 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3675 format, hfinfo->name, value);
3677 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3678 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3682 fill_label_int64(field_info *fi, gchar *label_str)
3684 const char *format = NULL;
3685 header_field_info *hfinfo = fi->hfinfo;
3687 int ret; /*tmp return value */
3689 /* Pick the proper format string */
3690 format = hfinfo_int64_format(hfinfo);
3691 value = fvalue_get_integer64(&fi->value);
3693 /* Fill in the textual info */
3694 if (IS_BASE_DUAL(hfinfo->display)) {
3695 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3696 format, hfinfo->name, value, value);
3698 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3699 format, hfinfo->name, value);
3701 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3702 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3706 hfinfo_bitwidth(header_field_info *hfinfo)
3710 if (!hfinfo->bitmask) {
3714 switch(hfinfo->type) {
3732 bitwidth = hfinfo->display; /* hacky? :) */
3735 DISSECTOR_ASSERT_NOT_REACHED();
3742 hfinfo_uint_vals_format(header_field_info *hfinfo)
3744 const char *format = NULL;
3746 switch(hfinfo->display) {
3749 format = "%s: %s (%u)";
3751 case BASE_OCT: /* I'm lazy */
3752 format = "%s: %s (%o)";
3756 switch(hfinfo->type) {
3758 format = "%s: %s (0x%02x)";
3761 format = "%s: %s (0x%04x)";
3764 format = "%s: %s (0x%06x)";
3767 format = "%s: %s (0x%08x)";
3770 DISSECTOR_ASSERT_NOT_REACHED();
3775 DISSECTOR_ASSERT_NOT_REACHED();
3782 hfinfo_uint_format(header_field_info *hfinfo)
3784 const char *format = NULL;
3786 /* Pick the proper format string */
3787 if (hfinfo->type == FT_FRAMENUM) {
3789 * Frame numbers are always displayed in decimal.
3793 switch(hfinfo->display) {
3798 switch(hfinfo->type) {
3800 format = "%s: %u (0x%02x)";
3803 format = "%s: %u (0x%04x)";
3806 format = "%s: %u (0x%06x)";
3809 format = "%s: %u (0x%08x)";
3812 DISSECTOR_ASSERT_NOT_REACHED();
3816 case BASE_OCT: /* I'm lazy */
3820 switch(hfinfo->type) {
3822 format = "%s: 0x%02x";
3825 format = "%s: 0x%04x";
3828 format = "%s: 0x%06x";
3831 format = "%s: 0x%08x";
3834 DISSECTOR_ASSERT_NOT_REACHED();
3839 switch(hfinfo->type) {
3841 format = "%s: 0x%02x (%u)";
3844 format = "%s: 0x%04x (%u)";
3847 format = "%s: 0x%06x (%u)";
3850 format = "%s: 0x%08x (%u)";
3853 DISSECTOR_ASSERT_NOT_REACHED();
3858 DISSECTOR_ASSERT_NOT_REACHED();
3866 hfinfo_int_vals_format(header_field_info *hfinfo)
3868 const char *format = NULL;
3870 switch(hfinfo->display) {
3873 format = "%s: %s (%d)";
3875 case BASE_OCT: /* I'm lazy */
3876 format = "%s: %s (%o)";
3880 switch(hfinfo->type) {
3882 format = "%s: %s (0x%02x)";
3885 format = "%s: %s (0x%04x)";
3888 format = "%s: %s (0x%06x)";
3891 format = "%s: %s (0x%08x)";
3894 DISSECTOR_ASSERT_NOT_REACHED();
3899 DISSECTOR_ASSERT_NOT_REACHED();
3906 hfinfo_uint64_format(header_field_info *hfinfo)
3908 const char *format = NULL;
3910 /* Pick the proper format string */
3911 switch(hfinfo->display) {
3913 format = "%s: %" PRIu64;
3916 format = "%s: %" PRIu64 " (%" PRIx64 ")";
3918 case BASE_OCT: /* I'm lazy */
3919 format = "%s: %" PRIo64;
3922 format = "%s: 0x%016" PRIx64;
3925 format = "%s: 0x%016" PRIx64 " (%" PRIu64 ")";
3928 DISSECTOR_ASSERT_NOT_REACHED();
3935 hfinfo_int_format(header_field_info *hfinfo)
3937 const char *format = NULL;
3939 /* Pick the proper format string */
3940 switch(hfinfo->display) {
3945 switch(hfinfo->type) {
3947 format = "%s: %d (0x%02x)";
3950 format = "%s: %d (0x%04x)";
3953 format = "%s: %d (0x%06x)";
3956 format = "%s: %d (0x%08x)";
3959 DISSECTOR_ASSERT_NOT_REACHED();
3962 case BASE_OCT: /* I'm lazy */
3966 switch(hfinfo->type) {
3968 format = "%s: 0x%02x";
3971 format = "%s: 0x%04x";
3974 format = "%s: 0x%06x";
3977 format = "%s: 0x%08x";
3980 DISSECTOR_ASSERT_NOT_REACHED();
3984 switch(hfinfo->type) {
3986 format = "%s: 0x%02x (%d)";
3989 format = "%s: 0x%04x (%d)";
3992 format = "%s: 0x%06x (%d)";
3995 format = "%s: 0x%08x (%d)";
3998 DISSECTOR_ASSERT_NOT_REACHED();
4003 DISSECTOR_ASSERT_NOT_REACHED();
4010 hfinfo_int64_format(header_field_info *hfinfo)
4012 const char *format = NULL;
4014 /* Pick the proper format string */
4015 switch(hfinfo->display) {
4017 format = "%s: %" PRId64;
4020 format = "%s: %" PRId64 " (%" PRIx64 ")";
4022 case BASE_OCT: /* I'm lazy */
4023 format = "%s: %" PRIo64;
4026 format = "%s: 0x%016" PRIx64;
4029 format = "%s: 0x%016" PRIx64 " (%" PRId64 ")";
4032 DISSECTOR_ASSERT_NOT_REACHED();
4041 proto_registrar_n(void)
4043 return gpa_hfinfo.len;
4047 proto_registrar_get_name(int n)
4049 header_field_info *hfinfo;
4051 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
4052 return hfinfo->name;
4056 proto_registrar_get_abbrev(int n)
4058 header_field_info *hfinfo;
4060 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
4061 return hfinfo->abbrev;
4065 proto_registrar_get_ftype(int n)
4067 header_field_info *hfinfo;
4069 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
4070 return hfinfo->type;
4074 proto_registrar_get_parent(int n)
4076 header_field_info *hfinfo;
4078 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
4079 return hfinfo->parent;
4083 proto_registrar_is_protocol(int n)
4085 header_field_info *hfinfo;
4087 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
4088 return (hfinfo->parent == -1 ? TRUE : FALSE);
4091 /* Returns length of field in packet (not necessarily the length
4092 * in our internal representation, as in the case of IPv4).
4093 * 0 means undeterminable at time of registration
4094 * -1 means the field is not registered. */
4096 proto_registrar_get_length(int n)
4098 header_field_info *hfinfo;
4100 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
4101 return ftype_length(hfinfo->type);
4106 /* Looks for a protocol or a field in a proto_tree. Returns TRUE if
4107 * it exists anywhere, or FALSE if it exists nowhere. */
4109 proto_check_for_protocol_or_field(proto_tree* tree, int id)
4111 GPtrArray *ptrs = proto_get_finfo_ptr_array(tree, id);
4116 else if (g_ptr_array_len(ptrs) > 0) {
4124 /* Return GPtrArray* of field_info pointers for all hfindex that appear in tree.
4125 * This only works if the hfindex was "primed" before the dissection
4126 * took place, as we just pass back the already-created GPtrArray*.
4127 * The caller should *not* free the GPtrArray*; proto_tree_free_node()
4130 proto_get_finfo_ptr_array(proto_tree *tree, int id)
4132 return g_hash_table_lookup(PTREE_DATA(tree)->interesting_hfids,
4133 GINT_TO_POINTER(id));
4137 /* Helper struct and function for proto_find_info() */
4144 find_finfo(proto_node *node, gpointer data)
4146 field_info *fi = PITEM_FINFO(node);
4147 if (fi && fi->hfinfo) {
4148 if (fi->hfinfo->id == ((ffdata_t*)data)->id) {
4149 g_ptr_array_add(((ffdata_t*)data)->array, fi);
4153 /* Don't stop traversing. */
4157 /* Return GPtrArray* of field_info pointers for all hfindex that appear in a tree.
4158 * This works on any proto_tree, primed or unprimed, but actually searches
4159 * the tree, so it is slower than using proto_get_finfo_ptr_array on a primed tree.
4160 * The caller does need to free the returned GPtrArray with
4161 * g_ptr_array_free(<array>, FALSE).
4164 proto_find_finfo(proto_tree *tree, int id)
4168 ffdata.array = g_ptr_array_new();
4171 proto_tree_traverse_pre_order(tree, find_finfo, &ffdata);
4173 return ffdata.array;
4184 check_for_offset(proto_node *node, gpointer data)
4186 field_info *fi = PITEM_FINFO(node);
4187 offset_search_t *offsearch = data;
4189 /* !fi == the top most container node which holds nothing */
4190 if (fi && !PROTO_ITEM_IS_HIDDEN(node) && fi->ds_tvb && offsearch->tvb == fi->ds_tvb) {
4191 if (offsearch->offset >= (guint) fi->start &&
4192 offsearch->offset < (guint) (fi->start + fi->length)) {
4194 offsearch->finfo = fi;
4195 return FALSE; /* keep traversing */
4198 return FALSE; /* keep traversing */
4201 /* Search a proto_tree backwards (from leaves to root) looking for the field
4202 * whose start/length occupies 'offset' */
4203 /* XXX - I couldn't find an easy way to search backwards, so I search
4204 * forwards, w/o stopping. Therefore, the last finfo I find will the be
4205 * the one I want to return to the user. This algorithm is inefficient
4206 * and could be re-done, but I'd have to handle all the children and
4207 * siblings of each node myself. When I have more time I'll do that.
4210 proto_find_field_from_offset(proto_tree *tree, guint offset, tvbuff_t *tvb)
4212 offset_search_t offsearch;
4214 offsearch.offset = offset;
4215 offsearch.finfo = NULL;
4216 offsearch.tvb = tvb;
4218 proto_tree_traverse_pre_order(tree, check_for_offset, &offsearch);
4220 return offsearch.finfo;
4223 /* Dumps the protocols in the registration database to stdout. An independent
4224 * program can take this output and format it into nice tables or HTML or
4227 * There is one record per line. The fields are tab-delimited.
4229 * Field 1 = protocol name
4230 * Field 2 = protocol short name
4231 * Field 3 = protocol filter name
4234 proto_registrar_dump_protocols(void)
4236 protocol_t *protocol;
4240 for (i = proto_get_first_protocol(&cookie); i != -1;
4241 i = proto_get_next_protocol(&cookie)) {
4242 protocol = find_protocol_by_id(i);
4243 printf("%s\t%s\t%s\n", protocol->name, protocol->short_name,
4244 protocol->filter_name);
4248 /* Dumps the value_string and true/false strings for fields that have
4249 * them. There is one record per line. Fields are tab-delimited.
4250 * There are two types of records, Value String records and True/False
4251 * String records. The first field, 'V' or 'T', indicates the type
4257 * Field 2 = field abbreviation to which this value string corresponds
4258 * Field 3 = Integer value
4261 * True/False Strings
4262 * ------------------
4264 * Field 2 = field abbreviation to which this true/false string corresponds
4265 * Field 3 = True String
4266 * Field 4 = False String
4269 proto_registrar_dump_values(void)
4271 header_field_info *hfinfo, *parent_hfinfo;
4273 const value_string *vals;
4274 const true_false_string *tfs;
4276 len = gpa_hfinfo.len;
4277 for (i = 0; i < len ; i++) {
4278 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
4280 if (hfinfo->id == hf_text_only) {
4284 /* ignore protocols */
4285 if (proto_registrar_is_protocol(i)) {
4288 /* process header fields */
4291 * If this field isn't at the head of the list of
4292 * fields with this name, skip this field - all
4293 * fields with the same name are really just versions
4294 * of the same field stored in different bits, and
4295 * should have the same type/radix/value list, and
4296 * just differ in their bit masks. (If a field isn't
4297 * a bitfield, but can be, say, 1 or 2 bytes long,
4298 * it can just be made FT_UINT16, meaning the
4299 * *maximum* length is 2 bytes, and be used
4302 if (hfinfo->same_name_prev != NULL)
4305 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
4310 if (hfinfo->type == FT_UINT8 ||
4311 hfinfo->type == FT_UINT16 ||
4312 hfinfo->type == FT_UINT24 ||
4313 hfinfo->type == FT_UINT32 ||
4314 hfinfo->type == FT_UINT64 ||
4315 hfinfo->type == FT_INT8 ||
4316 hfinfo->type == FT_INT16 ||
4317 hfinfo->type == FT_INT24 ||
4318 hfinfo->type == FT_INT32 ||
4319 hfinfo->type == FT_INT64) {
4321 vals = hfinfo->strings;
4323 else if (hfinfo->type == FT_BOOLEAN) {
4324 tfs = hfinfo->strings;
4327 /* Print value strings? */
4330 while (vals[vi].strptr) {
4331 /* Print in the proper base */
4332 if (hfinfo->display == BASE_HEX) {
4333 printf("V\t%s\t0x%x\t%s\n",
4339 printf("V\t%s\t%u\t%s\n",
4348 /* Print true/false strings? */
4350 printf("T\t%s\t%s\t%s\n", hfinfo->abbrev,
4351 tfs->true_string, tfs->false_string);
4357 /* Dumps the contents of the registration database to stdout. An indepedent
4358 * program can take this output and format it into nice tables or HTML or
4361 * There is one record per line. Each record is either a protocol or a header
4362 * field, differentiated by the first field. The fields are tab-delimited.
4367 * Field 2 = descriptive protocol name
4368 * Field 3 = protocol abbreviation
4374 * Field 2 = descriptive field name
4375 * Field 3 = field abbreviation
4376 * Field 4 = type ( textual representation of the the ftenum type )
4377 * Field 5 = parent protocol abbreviation
4378 * Field 6 = blurb describing field
4382 * Field 2 = descriptive field name
4383 * Field 3 = field abbreviation
4384 * Field 4 = type ( textual representation of the the ftenum type )
4385 * Field 5 = parent protocol abbreviation
4386 * Field 6 = blurb describing field
4387 * Field 7 = base for display (for integer types)
4388 * Field 8 = blurb describing field (yes, apparently we repeated this accidentally)
4392 * Field 2 = descriptive field name
4393 * Field 3 = field abbreviation
4394 * Field 4 = type ( textual representation of the the ftenum type )
4395 * Field 5 = parent protocol abbreviation
4396 * Field 6 = blurb describing field
4397 * Field 7 = base for display (for integer types)
4401 proto_registrar_dump_fields(int format)
4403 header_field_info *hfinfo, *parent_hfinfo;
4405 const char *enum_name;
4406 const char *base_name;
4408 len = gpa_hfinfo.len;
4409 for (i = 0; i < len ; i++) {
4410 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
4413 * Skip fields with zero-length names or abbreviations;
4414 * the pseudo-field for "proto_tree_add_text()" is such
4415 * a field, and we don't want it in the list of filterable
4419 * XXX - perhaps the name and abbrev field should be null
4420 * pointers rather than null strings for that pseudo-field,
4421 * but we'd have to add checks for null pointers in some
4422 * places if we did that.
4424 * Or perhaps protocol tree items added with
4425 * "proto_tree_add_text()" should have -1 as the field index,
4426 * with no pseudo-field being used, but that might also
4427 * require special checks for -1 to be added.
4429 /* XXX - we could just skip the special text
4430 * pseudo-field by testing: if (hfinfo->id == hf_text_only)
4432 if (hfinfo->name[0] == 0 || hfinfo->abbrev[0] == 0)
4435 /* format for protocols */
4436 if (proto_registrar_is_protocol(i)) {
4437 printf("P\t%s\t%s\n", hfinfo->name, hfinfo->abbrev);
4439 /* format for header fields */
4442 * If this field isn't at the head of the list of
4443 * fields with this name, skip this field - all
4444 * fields with the same name are really just versions
4445 * of the same field stored in different bits, and
4446 * should have the same type/radix/value list, and
4447 * just differ in their bit masks. (If a field isn't
4448 * a bitfield, but can be, say, 1 or 2 bytes long,
4449 * it can just be made FT_UINT16, meaning the
4450 * *maximum* length is 2 bytes, and be used
4453 if (hfinfo->same_name_prev != NULL)
4456 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
4458 enum_name = ftype_name(hfinfo->type);
4462 if (hfinfo->type == FT_UINT8 ||
4463 hfinfo->type == FT_UINT16 ||
4464 hfinfo->type == FT_UINT24 ||
4465 hfinfo->type == FT_UINT32 ||
4466 hfinfo->type == FT_UINT64 ||
4467 hfinfo->type == FT_INT8 ||
4468 hfinfo->type == FT_INT16 ||
4469 hfinfo->type == FT_INT24 ||
4470 hfinfo->type == FT_INT32 ||
4471 hfinfo->type == FT_INT64) {
4474 switch(hfinfo->display) {
4476 base_name = "BASE_NONE";
4479 base_name = "BASE_DEC";
4482 base_name = "BASE_HEX";
4485 base_name = "BASE_OCT";
4488 base_name = "BASE_DEC_HEX";
4491 base_name = "BASE_HEX_DEC";
4498 printf("F\t%s\t%s\t%s\t%s\t%s\n", hfinfo->name, hfinfo->abbrev,
4499 enum_name,parent_hfinfo->abbrev, hfinfo->blurb);
4501 else if (format == 2) {
4502 printf("F\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n",
4503 hfinfo->name, hfinfo->abbrev,
4504 enum_name,parent_hfinfo->abbrev, hfinfo->blurb,
4505 base_name, hfinfo->blurb);
4507 else if (format == 3) {
4508 printf("F\t%s\t%s\t%s\t%s\t%s\t%s\t%u\n",
4509 hfinfo->name, hfinfo->abbrev,
4510 enum_name,parent_hfinfo->abbrev, hfinfo->blurb,
4511 base_name, hfinfo->bitmask);
4514 g_assert_not_reached();
4521 hfinfo_numeric_format(header_field_info *hfinfo)
4523 const char *format = NULL;
4525 /* Pick the proper format string */
4526 if (hfinfo->type == FT_FRAMENUM) {
4528 * Frame numbers are always displayed in decimal.
4530 format = "%s == %u";
4532 /* Pick the proper format string */
4533 switch(hfinfo->display) {
4536 case BASE_OCT: /* I'm lazy */
4537 switch(hfinfo->type) {
4542 format = "%s == %u";
4545 format = "%s == %" PRIu64;
4551 format = "%s == %d";
4554 format = "%s == %" PRId64;
4557 DISSECTOR_ASSERT_NOT_REACHED();
4563 switch(hfinfo->type) {
4565 format = "%s == 0x%02x";
4568 format = "%s == 0x%04x";
4571 format = "%s == 0x%06x";
4574 format = "%s == 0x%08x";
4577 format = "%s == 0x%016" PRIx64;
4580 DISSECTOR_ASSERT_NOT_REACHED();
4585 DISSECTOR_ASSERT_NOT_REACHED();
4593 * Returns TRUE if we can do a "match selected" on the field, FALSE
4597 proto_can_match_selected(field_info *finfo, epan_dissect_t *edt)
4599 header_field_info *hfinfo;
4602 hfinfo = finfo->hfinfo;
4603 DISSECTOR_ASSERT(hfinfo);
4605 switch(hfinfo->type) {
4624 case FT_ABSOLUTE_TIME:
4625 case FT_RELATIVE_TIME:
4628 case FT_UINT_STRING:
4635 * These all have values, so we can match.
4641 * This doesn't have a value, so we'd match
4642 * on the raw bytes at this address.
4644 * Should we be allowed to access to the raw bytes?
4645 * If "edt" is NULL, the answer is "no".
4651 * Is this field part of the raw frame tvbuff?
4652 * If not, we can't use "frame[N:M]" to match
4655 * XXX - should this be frame-relative, or
4656 * protocol-relative?
4658 * XXX - does this fallback for non-registered
4659 * fields even make sense?
4661 if (finfo->ds_tvb != edt->tvb)
4665 * If the length is 0, there's nothing to match, so
4666 * we can't match. (Also check for negative values,
4667 * just in case, as we'll cast it to an unsigned
4670 length = finfo->length;
4675 * Don't go past the end of that tvbuff.
4677 if ((guint)length > tvb_length(finfo->ds_tvb))
4678 length = tvb_length(finfo->ds_tvb);
4685 /* This function returns a string allocated with packet lifetime scope.
4686 * You do not need to [g_]free() this string since it will be automatically
4687 * freed once the next packet is dissected.
4690 proto_construct_dfilter_string(field_info *finfo, epan_dissect_t *edt)
4692 header_field_info *hfinfo;
4694 char *buf, *stringified, *ptr;
4698 gint start, length, length_remaining;
4701 hfinfo = finfo->hfinfo;
4702 DISSECTOR_ASSERT(hfinfo);
4703 abbrev_len = strlen(hfinfo->abbrev);
4706 * XXX - we can't use the "val_to_string_repr" and "string_repr_len"
4707 * functions for FT_UINT and FT_INT types, as we choose the base in
4708 * the string expression based on the display base of the field.
4710 * Note that the base does matter, as this is also used for
4711 * the protocolinfo tap.
4713 * It might be nice to use them in "proto_item_fill_label()"
4714 * as well, although, there, you'd have to deal with the base
4715 * *and* with resolved values for addresses.
4717 * Perhaps we need two different val_to_string routines, one
4718 * to generate items for display filters and one to generate
4719 * strings for display, and pass to both of them the
4720 * "display" and "strings" values in the header_field_info
4721 * structure for the field, so they can get the base and,
4722 * if the field is Boolean or an enumerated integer type,
4723 * the tables used to generate human-readable values.
4725 switch(hfinfo->type) {
4737 * 4 bytes for " == ".
4740 * a sign + up to 10 digits of 32-bit integer,
4743 * "0x" + 8 digits of 32-bit integer, in hex;
4745 * 11 digits of 32-bit integer, in octal.
4746 * (No, we don't do octal, but this way,
4747 * we know that if we do, this will still
4750 * 1 byte for the trailing '\0'.
4752 dfilter_len = abbrev_len + 4 + 11 + 1;
4753 buf = ep_alloc0(dfilter_len);
4754 format = hfinfo_numeric_format(hfinfo);
4755 g_snprintf(buf, dfilter_len, format, hfinfo->abbrev, fvalue_get_integer(&finfo->value));
4761 * 4 bytes for " == ".
4764 * a sign + up to 20 digits of 32-bit integer,
4767 * "0x" + 16 digits of 32-bit integer, in hex;
4769 * 22 digits of 32-bit integer, in octal.
4770 * (No, we don't do octal, but this way,
4771 * we know that if we do, this will still
4774 * 1 byte for the trailing '\0'.
4776 dfilter_len = abbrev_len + 4 + 22 + 1;
4777 buf = ep_alloc0(dfilter_len);
4778 format = hfinfo_numeric_format(hfinfo);
4779 g_snprintf(buf, dfilter_len, format, hfinfo->abbrev, fvalue_get_integer64(&finfo->value));
4782 /* These use the fvalue's "to_string_repr" method. */
4791 case FT_ABSOLUTE_TIME:
4792 case FT_RELATIVE_TIME:
4796 /* Figure out the string length needed.
4797 * The ft_repr length.
4798 * 4 bytes for " == ".
4799 * 1 byte for trailing NUL.
4801 dfilter_len = fvalue_string_repr_len(&finfo->value,
4803 dfilter_len += abbrev_len + 4 + 1;
4804 buf = ep_alloc0(dfilter_len);
4806 /* Create the string */
4807 g_snprintf(buf, dfilter_len, "%s == ", hfinfo->abbrev);
4808 fvalue_to_string_repr(&finfo->value,
4810 &buf[abbrev_len + 4]);
4814 buf = ep_strdup(finfo->hfinfo->abbrev);
4819 * This doesn't have a value, so we'd match
4820 * on the raw bytes at this address.
4822 * Should we be allowed to access to the raw bytes?
4823 * If "edt" is NULL, the answer is "no".
4829 * Is this field part of the raw frame tvbuff?
4830 * If not, we can't use "frame[N:M]" to match
4833 * XXX - should this be frame-relative, or
4834 * protocol-relative?
4836 * XXX - does this fallback for non-registered
4837 * fields even make sense?
4839 if (finfo->ds_tvb != edt->tvb)
4840 return NULL; /* you lose */
4843 * If the length is 0, there's nothing to match, so
4844 * we can't match. (Also check for negative values,
4845 * just in case, as we'll cast it to an unsigned
4848 length = finfo->length;
4853 * Don't go past the end of that tvbuff.
4855 length_remaining = tvb_length_remaining(finfo->ds_tvb, finfo->start);
4856 if (length > length_remaining)
4857 length = length_remaining;
4861 start = finfo->start;
4862 buf_len = 32 + length * 3;
4863 buf = ep_alloc0(buf_len);
4866 ptr += g_snprintf(ptr, buf_len-(ptr-buf), "frame[%d:%d] == ", finfo->start, length);
4867 for (i=0;i<length; i++) {
4868 c = tvb_get_guint8(finfo->ds_tvb, start);
4871 ptr += g_snprintf(ptr, buf_len-(ptr-buf), "%02x", c);
4874 ptr += snprintf(ptr, buf_len-(ptr-buf), ":%02x", c);