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.
37 #include "addr_resolv.h"
40 #include "epan_dissect.h"
45 #define cVALS(x) (const value_string*)(x)
48 #define TRY_TO_FAKE_THIS_ITEM(tree, hfindex) \
49 /* If this item is not referenced we dont have to do much work \
50 at all but we should still return a node so that \
51 field items below this node ( think proto_item_add_subtree() )\
52 will still have somewhere to attach to \
53 or else filtering will not work (they would be ignored since tree\
55 DONT try to fake a node where PITEM_FINFO(pi) is NULL \
56 since dissectors that want to do proto_item_set_len() ot \
57 other operations that dereference this would crash. \
58 We dont fake FT_PROTOCOL either since these are cheap and \
59 some stuff (proto hier stat) assumes they always exist. \
61 if(!(PTREE_DATA(tree)->visible)){ \
62 if(PITEM_FINFO(tree)){ \
63 register header_field_info *hfinfo; \
64 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo); \
65 if((hfinfo->ref_count == 0) \
66 && (hfinfo->type!=FT_PROTOCOL)){ \
67 /* just return tree back to the caller */\
73 #define TRY_TO_FAKE_THIS_ITEM(tree, hfindex) ;
77 proto_tree_free_node(proto_node *node, gpointer data);
79 static void fill_label_boolean(field_info *fi, gchar *label_str);
80 static void fill_label_uint(field_info *fi, gchar *label_str);
81 static void fill_label_uint64(field_info *fi, gchar *label_str);
82 static void fill_label_enumerated_uint(field_info *fi, gchar *label_str);
83 static void fill_label_enumerated_bitfield(field_info *fi, gchar *label_str);
84 static void fill_label_numeric_bitfield(field_info *fi, gchar *label_str);
85 static void fill_label_int(field_info *fi, gchar *label_str);
86 static void fill_label_int64(field_info *fi, gchar *label_str);
87 static void fill_label_enumerated_int(field_info *fi, gchar *label_str);
89 int hfinfo_bitwidth(header_field_info *hfinfo);
90 static const char* hfinfo_uint_vals_format(header_field_info *hfinfo);
91 static const char* hfinfo_uint_format(header_field_info *hfinfo);
92 static const char* hfinfo_uint64_format(header_field_info *hfinfo);
93 static const char* hfinfo_int_vals_format(header_field_info *hfinfo);
94 static const char* hfinfo_int_format(header_field_info *hfinfo);
95 static const char* hfinfo_int64_format(header_field_info *hfinfo);
98 proto_tree_add_node(proto_tree *tree, field_info *fi);
101 alloc_field_info(proto_tree *tree, int hfindex, tvbuff_t *tvb,
102 gint start, gint *length);
105 proto_tree_add_pi(proto_tree *tree, int hfindex, tvbuff_t *tvb,
106 gint start, gint *length, field_info **pfi);
109 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap);
112 proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb);
114 proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length);
116 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length);
118 proto_tree_set_time(field_info *fi, nstime_t *value_ptr);
120 proto_tree_set_string(field_info *fi, const char* value, gboolean);
122 proto_tree_set_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
124 proto_tree_set_ether(field_info *fi, const guint8* value);
126 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start);
128 proto_tree_set_ipxnet(field_info *fi, guint32 value);
130 proto_tree_set_ipv4(field_info *fi, guint32 value);
132 proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr);
134 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start);
136 proto_tree_set_guid(field_info *fi, const guint8* value_ptr);
138 proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, gint start);
140 proto_tree_set_boolean(field_info *fi, guint32 value);
142 proto_tree_set_float(field_info *fi, float value);
144 proto_tree_set_double(field_info *fi, double value);
146 proto_tree_set_uint(field_info *fi, guint32 value);
148 proto_tree_set_int(field_info *fi, gint32 value);
150 proto_tree_set_uint64(field_info *fi, guint64 value);
152 proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start, gboolean little_endian);
154 static int proto_register_field_init(header_field_info *hfinfo, int parent);
156 /* Comparision function for tree insertion. A wrapper around strcmp() */
157 static int g_strcmp(gconstpointer a, gconstpointer b);
159 /* special-case header field used within proto.c */
160 int hf_text_only = -1;
162 /* Structure for information about a protocol */
164 const char *name; /* long description */
165 const char *short_name; /* short description */
166 const char *filter_name; /* name of this protocol in filters */
167 int proto_id; /* field ID for this protocol */
168 GList *fields; /* fields for this protocol */
169 GList *last_field; /* pointer to end of list of fields */
170 gboolean is_enabled; /* TRUE if protocol is enabled */
171 gboolean can_toggle; /* TRUE if is_enabled can be changed */
174 /* List of all protocols */
175 static GList *protocols = NULL;
177 #define INITIAL_NUM_PROTOCOL_HFINFO 200
180 /* Contains information about protocols and header fields. Used when
181 * dissectors register their data */
182 static GMemChunk *gmc_hfinfo = NULL;
184 /* Contains information about a field when a dissector calls
185 * proto_tree_add_item. */
186 SLAB_ITEM_TYPE_DEFINE(field_info)
187 static SLAB_FREE_LIST_DEFINE(field_info)
188 static field_info *field_info_tmp=NULL;
189 #define FIELD_INFO_NEW(fi) \
190 SLAB_ALLOC(fi, field_info)
191 #define FIELD_INFO_FREE(fi) \
192 SLAB_FREE(fi, field_info)
196 /* Contains the space for proto_nodes. */
197 SLAB_ITEM_TYPE_DEFINE(proto_node)
198 static SLAB_FREE_LIST_DEFINE(proto_node)
199 #define PROTO_NODE_NEW(node) \
200 SLAB_ALLOC(node, proto_node) \
201 node->first_child = NULL; \
202 node->last_child = NULL; \
205 #define PROTO_NODE_FREE(node) \
206 SLAB_FREE(node, proto_node)
210 /* String space for protocol and field items for the GUI */
211 SLAB_ITEM_TYPE_DEFINE(item_label_t)
212 static SLAB_FREE_LIST_DEFINE(item_label_t)
213 #define ITEM_LABEL_NEW(il) \
214 SLAB_ALLOC(il, item_label_t)
215 #define ITEM_LABEL_FREE(il) \
216 SLAB_FREE(il, item_label_t)
219 #define PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo) \
220 DISSECTOR_ASSERT((guint)hfindex < gpa_hfinfo.len); \
221 hfinfo=gpa_hfinfo.hfi[hfindex];
224 /* List which stores protocols and fields that have been registered */
225 typedef struct _gpa_hfinfo_t {
227 guint32 allocated_len;
228 header_field_info **hfi;
230 gpa_hfinfo_t gpa_hfinfo;
232 /* Balanced tree of abbreviations and IDs */
233 static GTree *gpa_name_tree = NULL;
235 /* Points to the first element of an array of Booleans, indexed by
236 a subtree item type; that array element is TRUE if subtrees of
237 an item of that type are to be expanded. */
238 gboolean *tree_is_expanded;
240 /* Number of elements in that array. */
243 /* Name hashtables for fast detection of duplicate names */
244 static GHashTable* proto_names = NULL;
245 static GHashTable* proto_short_names = NULL;
246 static GHashTable* proto_filter_names = NULL;
249 proto_compare_name(gconstpointer p1_arg, gconstpointer p2_arg)
251 const protocol_t *p1 = p1_arg;
252 const protocol_t *p2 = p2_arg;
254 return g_strcasecmp(p1->short_name, p2->short_name);
258 /* initialize data structures and register protocols and fields */
260 proto_init(const char *plugin_dir
265 void (register_all_protocols)(void),
266 void (register_all_protocol_handoffs)(void))
268 static hf_register_info hf[] = {
270 { "", "", FT_NONE, BASE_NONE, NULL, 0x0,
275 proto_names = g_hash_table_new(g_int_hash, g_int_equal);
276 proto_short_names = g_hash_table_new(g_int_hash, g_int_equal);
277 proto_filter_names = g_hash_table_new(g_int_hash, g_int_equal);
281 gmc_hfinfo = g_mem_chunk_new("gmc_hfinfo",
282 sizeof(header_field_info),
283 INITIAL_NUM_PROTOCOL_HFINFO * sizeof(header_field_info),
287 gpa_hfinfo.allocated_len=0;
289 gpa_name_tree = g_tree_new(g_strcmp);
291 /* Initialize the ftype subsystem */
294 /* Register one special-case FT_TEXT_ONLY field for use when
295 converting ethereal to new-style proto_tree. These fields
296 are merely strings on the GUI tree; they are not filterable */
297 proto_register_field_array(-1, hf, array_length(hf));
299 /* Have each built-in dissector register its protocols, fields,
300 dissector tables, and dissectors to be called through a
301 handle, and do whatever one-time initialization it needs to
303 register_all_protocols();
306 /* Now scan for plugins and load all the ones we find, calling
307 their register routines to do the stuff described above. */
308 init_plugins(plugin_dir);
311 /* Now call the "handoff registration" routines of all built-in
312 dissectors; those routines register the dissector in other
313 dissectors' handoff tables, and fetch any dissector handles
315 register_all_protocol_handoffs();
318 /* Now do the same with plugins. */
319 register_all_plugin_handoffs();
322 /* sort the protocols by protocol name */
323 protocols = g_list_sort(protocols, proto_compare_name);
325 /* We've assigned all the subtree type values; allocate the array
326 for them, and zero it out. */
327 tree_is_expanded = g_malloc(num_tree_types*sizeof (gint *));
328 memset(tree_is_expanded, 0, num_tree_types*sizeof (gint *));
331 /* String comparison func for dfilter_token GTree */
333 g_strcmp(gconstpointer a, gconstpointer b)
335 return strcmp((const char*)a, (const char*)b);
341 /* Free the abbrev/ID GTree */
343 g_tree_destroy(gpa_name_tree);
344 gpa_name_tree = NULL;
348 g_mem_chunk_destroy(gmc_hfinfo);
350 if(gpa_hfinfo.allocated_len){
352 gpa_hfinfo.allocated_len=0;
353 g_free(gpa_hfinfo.hfi);
356 if (tree_is_expanded != NULL)
357 g_free(tree_is_expanded);
361 typedef gboolean (*proto_tree_traverse_func)(proto_node *, gpointer);
364 proto_tree_traverse_pre_order(proto_tree *tree, proto_tree_traverse_func func,
367 proto_node *pnode = tree;
371 if (func(pnode, data))
374 child = pnode->first_child;
375 while (child != NULL) {
377 * The routine we call might modify the child, e.g. by
378 * freeing it, so we get the child's successor before
379 * calling that routine.
382 child = current->next;
383 if (proto_tree_traverse_pre_order((proto_tree *)current, func,
392 proto_tree_traverse_in_order(proto_tree *tree, proto_tree_traverse_func func,
395 proto_node *pnode = tree;
399 child = pnode->first_child;
402 * The routine we call might modify the child, e.g. by
403 * freeing it, so we get the child's successor before
404 * calling that routine.
407 child = current->next;
409 if (proto_tree_traverse_in_order((proto_tree *)current, func,
413 if (func(pnode, data))
416 while (child != NULL) {
418 * The routine we call might modify the child, e.g. by
419 * freeing it, so we get the child's successor before
420 * calling that routine.
423 child = current->next;
424 if (proto_tree_traverse_in_order((proto_tree *)current,
429 if (func(pnode, data))
437 proto_tree_children_foreach(proto_tree *tree, proto_tree_foreach_func func,
440 proto_node *node = tree;
443 node = node->first_child;
444 while (node != NULL) {
446 node = current->next;
447 func((proto_tree *)current, data);
451 /* frees the resources that the dissection a proto_tree uses */
453 proto_tree_free(proto_tree *tree)
455 proto_tree_traverse_in_order(tree, proto_tree_free_node, NULL);
459 free_GPtrArray_value(gpointer key _U_, gpointer value, gpointer user_data _U_)
461 GPtrArray *ptrs = value;
462 gint hfid = (gint)key;
463 header_field_info *hfinfo;
466 PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
467 if(hfinfo->ref_count){
468 /* when a field is referenced by a filter this also
469 affects the refcount for the parent protocol so we need
470 to adjust the refcount for the parent as well
472 if( (hfinfo->parent != -1) && (hfinfo->ref_count) ){
473 header_field_info *parent_hfinfo;
474 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
475 parent_hfinfo->ref_count -= hfinfo->ref_count;
477 hfinfo->ref_count = 0;
480 g_ptr_array_free(ptrs, TRUE);
484 free_node_tree_data(tree_data_t *tree_data)
486 /* Free all the GPtrArray's in the interesting_hfids hash. */
487 g_hash_table_foreach(tree_data->interesting_hfids,
488 free_GPtrArray_value, NULL);
490 /* And then destroy the hash. */
491 g_hash_table_destroy(tree_data->interesting_hfids);
493 /* And finally the tree_data_t itself. */
497 #define FREE_NODE_FIELD_INFO(finfo) \
499 ITEM_LABEL_FREE(finfo->rep); \
501 FVALUE_CLEANUP(&finfo->value); \
502 FIELD_INFO_FREE(finfo);
505 proto_tree_free_node(proto_node *node, gpointer data _U_)
507 field_info *finfo = PITEM_FINFO(node);
510 /* This is the root node. Destroy the per-tree data.
511 * There is no field_info to destroy. */
512 free_node_tree_data(PTREE_DATA(node));
515 /* This is a child node. Don't free the per-tree data, but
516 * do free the field_info data. */
517 FREE_NODE_FIELD_INFO(finfo);
520 /* Free the proto_node. */
521 PROTO_NODE_FREE(node);
523 return FALSE; /* FALSE = do not end traversal of protocol tree */
526 /* Is the parsing being done for a visible proto_tree or an invisible one?
527 * By setting this correctly, the proto_tree creation is sped up by not
528 * having to call g_vsnprintf and copy strings around.
531 proto_tree_set_visible(proto_tree *tree, gboolean visible)
533 PTREE_DATA(tree)->visible = visible;
536 /* Assume dissector set only its protocol fields.
537 This function is called by dissectors and allowes to speed up filtering
538 in ethereal, if this function returns FALSE it is safe to reset tree to NULL
539 and thus skip calling most of the expensive proto_tree_add_...()
541 If the tree is visible we implicitely assume the field is referenced.
544 proto_field_is_referenced(proto_tree *tree, int proto_id)
546 register header_field_info *hfinfo;
552 if (PTREE_DATA(tree)->visible)
555 PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
556 if (hfinfo->ref_count != 0)
563 /* Finds a record in the hf_info_records array by id. */
565 proto_registrar_get_nth(guint hfindex)
567 register header_field_info *hfinfo;
569 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
573 /* Finds a record in the hf_info_records array by name.
576 proto_registrar_get_byname(const char *field_name)
578 DISSECTOR_ASSERT(field_name != NULL);
579 return g_tree_lookup(gpa_name_tree, field_name);
582 /* Add a text-only node, leaving it to our caller to fill the text in */
584 proto_tree_add_text_node(proto_tree *tree, tvbuff_t *tvb, gint start, gint length)
588 pi = proto_tree_add_pi(tree, hf_text_only, tvb, start, &length, NULL);
595 /* Add a text-only node to the proto_tree */
597 proto_tree_add_text(proto_tree *tree, tvbuff_t *tvb, gint start, gint length,
598 const char *format, ...)
603 pi = proto_tree_add_text_node(tree, tvb, start, length);
607 va_start(ap, format);
608 proto_tree_set_representation(pi, format, ap);
614 /* Add a text-only node to the proto_tree (va_list version) */
616 proto_tree_add_text_valist(proto_tree *tree, tvbuff_t *tvb, gint start,
617 gint length, const char *format, va_list ap)
621 pi = proto_tree_add_text_node(tree, tvb, start, length);
625 proto_tree_set_representation(pi, format, ap);
630 /* Add a text-only node for debugging purposes. The caller doesn't need
631 * to worry about tvbuff, start, or length. Debug message gets sent to
634 proto_tree_add_debug_text(proto_tree *tree, const char *format, ...)
639 pi = proto_tree_add_text_node(tree, NULL, 0, 0);
643 va_start(ap, format);
644 proto_tree_set_representation(pi, format, ap);
654 get_uint_value(tvbuff_t *tvb, gint offset, gint length, gboolean little_endian)
661 value = tvb_get_guint8(tvb, offset);
665 value = little_endian ? tvb_get_letohs(tvb, offset)
666 : tvb_get_ntohs(tvb, offset);
670 value = little_endian ? tvb_get_letoh24(tvb, offset)
671 : tvb_get_ntoh24(tvb, offset);
675 value = little_endian ? tvb_get_letohl(tvb, offset)
676 : tvb_get_ntohl(tvb, offset);
680 THROW(ReportedBoundsError);
688 get_int_value(tvbuff_t *tvb, gint offset, gint length, gboolean little_endian)
695 value = (gint8)tvb_get_guint8(tvb, offset);
699 value = (gint16) (little_endian ? tvb_get_letohs(tvb, offset)
700 : tvb_get_ntohs(tvb, offset));
704 value = little_endian ? tvb_get_letoh24(tvb, offset)
705 : tvb_get_ntoh24(tvb, offset);
706 if (value & 0x00800000) {
707 /* Sign bit is set; sign-extend it. */
713 value = little_endian ? tvb_get_letohl(tvb, offset)
714 : tvb_get_ntohl(tvb, offset);
718 THROW(ReportedBoundsError);
725 /* Add an item to a proto_tree, using the text label registered to that item;
726 the item is extracted from the tvbuff handed to it. */
728 proto_tree_add_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
729 gint start, gint length, gboolean little_endian)
743 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
745 new_fi = alloc_field_info(tree, hfindex, tvb, start, &length);
750 /* there is a possibility here that we might raise an exception
751 * and thus would lose track of the field_info.
752 * store it in a temp so that if we come here again we can reclaim
753 * the field_info without leaking memory.
755 /* XXX this only keeps track of one field_info struct,
756 if we ever go multithreaded for calls to this function
757 we have to change this code to use per thread variable.
760 /* oops, last one we got must have been lost due
762 * good thing we saved it, now we can reverse the
763 * memory leak and reclaim it.
765 SLAB_FREE(field_info_tmp, field_info);
767 /* we might throw an exception, keep track of this one
768 * across the "dangerous" section below.
770 field_info_tmp=new_fi;
772 switch(new_fi->hfinfo->type) {
774 /* no value to set for FT_NONE */
778 proto_tree_set_protocol_tvb(new_fi, tvb);
782 proto_tree_set_bytes_tvb(new_fi, tvb, start, length);
786 n = get_uint_value(tvb, start, length, little_endian);
787 proto_tree_set_bytes_tvb(new_fi, tvb, start + length, n);
789 /* Instead of calling proto_item_set_len(), since we don't yet
790 * have a proto_item, we set the field_info's length ourselves. */
791 new_fi->length = n + length;
795 proto_tree_set_boolean(new_fi,
796 get_uint_value(tvb, start, length, little_endian));
799 /* XXX - make these just FT_UINT? */
804 proto_tree_set_uint(new_fi,
805 get_uint_value(tvb, start, length, little_endian));
810 DISSECTOR_ASSERT(length == 8);
811 proto_tree_set_uint64_tvb(new_fi, tvb, start, little_endian);
814 /* XXX - make these just FT_INT? */
819 proto_tree_set_int(new_fi,
820 get_int_value(tvb, start, length, little_endian));
824 DISSECTOR_ASSERT(length == 4);
825 value = tvb_get_ipv4(tvb, start);
826 proto_tree_set_ipv4(new_fi, little_endian ? GUINT32_SWAP_LE_BE(value) : value);
830 DISSECTOR_ASSERT(length == 4);
831 proto_tree_set_ipxnet(new_fi,
832 get_uint_value(tvb, start, 4, FALSE));
836 DISSECTOR_ASSERT(length == 16);
837 proto_tree_set_ipv6_tvb(new_fi, tvb, start);
841 DISSECTOR_ASSERT(length == 6);
842 proto_tree_set_ether_tvb(new_fi, tvb, start);
846 DISSECTOR_ASSERT(length == 16);
847 proto_tree_set_guid_tvb(new_fi, tvb, start);
851 DISSECTOR_ASSERT(length == 4);
853 floatval = tvb_get_letohieee_float(tvb, start);
855 floatval = tvb_get_ntohieee_float(tvb, start);
856 proto_tree_set_float(new_fi, floatval);
860 DISSECTOR_ASSERT(length == 8);
862 doubleval = tvb_get_letohieee_double(tvb, start);
864 doubleval = tvb_get_ntohieee_double(tvb, start);
865 proto_tree_set_double(new_fi, doubleval);
869 /* This g_strdup'ed memory is freed in proto_tree_free_node() */
870 proto_tree_set_string_tvb(new_fi, tvb, start, length);
874 DISSECTOR_ASSERT(length >= -1);
875 /* Instead of calling proto_item_set_len(),
876 * since we don't yet have a proto_item, we
877 * set the field_info's length ourselves.
879 * XXX - our caller can't use that length to
880 * advance an offset unless they arrange that
881 * there always be a protocol tree into which
882 * we're putting this item.
885 /* This can throw an exception */
886 length = tvb_strsize(tvb, start);
888 /* This g_malloc'ed memory is freed
889 in proto_tree_free_node() */
890 string = g_malloc(length);
892 tvb_memcpy(tvb, string, start, length);
893 } else if (length == 0) {
894 string = g_strdup("[Empty]");
896 /* In this case, length signifies
897 * the length of the string.
899 * This could either be a null-padded
900 * string, which doesn't necessarily
901 * have a '\0' at the end, or a
902 * null-terminated string, with a
903 * trailing '\0'. (Yes, there are
904 * cases where you have a string
905 * that's both counted and null-
908 * In the first case, we must
909 * allocate a buffer of length
910 * "length+1", to make room for
913 * In the second case, we don't
914 * assume that there is a trailing
915 * '\0' there, as the packet might
916 * be malformed. (XXX - should we
917 * throw an exception if there's no
918 * trailing '\0'?) Therefore, we
919 * allocate a buffer of length
920 * "length+1", and put in a trailing
921 * '\0', just to be safe.
923 * (XXX - this would change if
924 * we made string values counted
925 * rather than null-terminated.)
928 /* This g_malloc'ed memory is freed
929 * in proto_tree_free_node() */
930 string = tvb_get_string(tvb, start,
933 new_fi->length = length;
934 proto_tree_set_string(new_fi, string, TRUE);
938 /* This g_strdup'ed memory is freed in proto_tree_free_node() */
939 n = get_uint_value(tvb, start, length, little_endian);
940 proto_tree_set_string_tvb(new_fi, tvb, start + length, n);
942 /* Instead of calling proto_item_set_len(), since we
943 * don't yet have a proto_item, we set the
944 * field_info's length ourselves.
946 * XXX - our caller can't use that length to
947 * advance an offset unless they arrange that
948 * there always be a protocol tree into which
949 * we're putting this item.
951 new_fi->length = n + length;
955 g_error("new_fi->hfinfo->type %d (%s) not handled\n",
956 new_fi->hfinfo->type,
957 ftype_name(new_fi->hfinfo->type));
958 DISSECTOR_ASSERT_NOT_REACHED();
962 /* Don't add new node to proto_tree until now so that any exceptions
963 * raised by a tvbuff access method doesn't leave junk in the proto_tree. */
964 pi = proto_tree_add_node(tree, new_fi);
966 /* we did not raise an exception so we dont have to remember this
967 * field_info struct any more.
971 /* If the proto_tree wants to keep a record of this finfo
972 * for quick lookup, then record it. */
973 if (new_fi->hfinfo->ref_count) {
974 hash = PTREE_DATA(tree)->interesting_hfids;
975 ptrs = g_hash_table_lookup(hash, GINT_TO_POINTER(hfindex));
977 g_ptr_array_add(ptrs, new_fi);
985 proto_tree_add_item_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb,
986 gint start, gint length, gboolean little_endian)
990 pi = proto_tree_add_item(tree, hfindex, tvb, start, length, little_endian);
994 PROTO_ITEM_SET_HIDDEN(pi);
1000 /* Add a FT_NONE to a proto_tree */
1002 proto_tree_add_none_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1003 gint length, const char *format, ...)
1007 header_field_info *hfinfo;
1012 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1013 DISSECTOR_ASSERT(hfinfo->type == FT_NONE);
1015 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, NULL);
1017 va_start(ap, format);
1018 proto_tree_set_representation(pi, format, ap);
1021 /* no value to set for FT_NONE */
1027 proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb)
1029 fvalue_set(&fi->value, tvb, TRUE);
1032 /* Add a FT_PROTOCOL to a proto_tree */
1034 proto_tree_add_protocol_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1035 gint length, const char *format, ...)
1039 header_field_info *hfinfo;
1045 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1046 DISSECTOR_ASSERT(hfinfo->type == FT_PROTOCOL);
1048 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1050 va_start(ap, format);
1051 proto_tree_set_representation(pi, format, ap);
1055 proto_tree_set_protocol_tvb(new_fi, tvb);
1058 proto_tree_set_protocol_tvb(new_fi, NULL);
1064 /* Add a FT_BYTES to a proto_tree */
1066 proto_tree_add_bytes(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1067 gint length, const guint8 *start_ptr)
1071 header_field_info *hfinfo;
1076 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1078 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1079 DISSECTOR_ASSERT(hfinfo->type == FT_BYTES);
1081 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1082 proto_tree_set_bytes(new_fi, start_ptr, length);
1088 proto_tree_add_bytes_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1089 gint length, const guint8 *start_ptr)
1093 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length, start_ptr);
1097 PROTO_ITEM_SET_HIDDEN(pi);
1103 proto_tree_add_bytes_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1104 gint length, const guint8 *start_ptr, const char *format, ...)
1109 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length, start_ptr);
1113 va_start(ap, format);
1114 proto_tree_set_representation(pi, format, ap);
1121 proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length)
1125 bytes = g_byte_array_new();
1127 g_byte_array_append(bytes, start_ptr, length);
1129 fvalue_set(&fi->value, bytes, TRUE);
1134 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length)
1136 proto_tree_set_bytes(fi, tvb_get_ptr(tvb, offset, length), length);
1139 /* Add a FT_*TIME to a proto_tree */
1141 proto_tree_add_time(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1142 nstime_t *value_ptr)
1146 header_field_info *hfinfo;
1151 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1153 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1154 DISSECTOR_ASSERT(hfinfo->type == FT_ABSOLUTE_TIME ||
1155 hfinfo->type == FT_RELATIVE_TIME);
1157 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1158 proto_tree_set_time(new_fi, value_ptr);
1164 proto_tree_add_time_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1165 nstime_t *value_ptr)
1169 pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
1173 PROTO_ITEM_SET_HIDDEN(pi);
1179 proto_tree_add_time_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1180 nstime_t *value_ptr, const char *format, ...)
1185 pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
1189 va_start(ap, format);
1190 proto_tree_set_representation(pi, format, ap);
1196 /* Set the FT_*TIME value */
1198 proto_tree_set_time(field_info *fi, nstime_t *value_ptr)
1200 DISSECTOR_ASSERT(value_ptr != NULL);
1201 fvalue_set(&fi->value, value_ptr, FALSE);
1204 /* Add a FT_IPXNET to a proto_tree */
1206 proto_tree_add_ipxnet(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1211 header_field_info *hfinfo;
1216 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1218 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1219 DISSECTOR_ASSERT(hfinfo->type == FT_IPXNET);
1221 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1222 proto_tree_set_ipxnet(new_fi, value);
1228 proto_tree_add_ipxnet_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1233 pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
1237 PROTO_ITEM_SET_HIDDEN(pi);
1243 proto_tree_add_ipxnet_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1244 guint32 value, const char *format, ...)
1249 pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
1253 va_start(ap, format);
1254 proto_tree_set_representation(pi, format, ap);
1260 /* Set the FT_IPXNET value */
1262 proto_tree_set_ipxnet(field_info *fi, guint32 value)
1264 fvalue_set_integer(&fi->value, value);
1267 /* Add a FT_IPv4 to a proto_tree */
1269 proto_tree_add_ipv4(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1274 header_field_info *hfinfo;
1279 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1281 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1282 DISSECTOR_ASSERT(hfinfo->type == FT_IPv4);
1284 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1285 proto_tree_set_ipv4(new_fi, value);
1291 proto_tree_add_ipv4_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1296 pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
1300 PROTO_ITEM_SET_HIDDEN(pi);
1306 proto_tree_add_ipv4_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1307 guint32 value, const char *format, ...)
1312 pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
1316 va_start(ap, format);
1317 proto_tree_set_representation(pi, format, ap);
1323 /* Set the FT_IPv4 value */
1325 proto_tree_set_ipv4(field_info *fi, guint32 value)
1327 fvalue_set_integer(&fi->value, value);
1330 /* Add a FT_IPv6 to a proto_tree */
1332 proto_tree_add_ipv6(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1333 const guint8* value_ptr)
1337 header_field_info *hfinfo;
1342 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1344 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1345 DISSECTOR_ASSERT(hfinfo->type == FT_IPv6);
1347 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1348 proto_tree_set_ipv6(new_fi, value_ptr);
1354 proto_tree_add_ipv6_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1355 const guint8* value_ptr)
1359 pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
1363 PROTO_ITEM_SET_HIDDEN(pi);
1369 proto_tree_add_ipv6_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1370 const guint8* value_ptr, const char *format, ...)
1375 pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
1379 va_start(ap, format);
1380 proto_tree_set_representation(pi, format, ap);
1386 /* Set the FT_IPv6 value */
1388 proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr)
1390 DISSECTOR_ASSERT(value_ptr != NULL);
1391 fvalue_set(&fi->value, (gpointer) value_ptr, FALSE);
1395 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start)
1397 proto_tree_set_ipv6(fi, tvb_get_ptr(tvb, start, 16));
1400 /* Add a FT_GUID to a proto_tree */
1402 proto_tree_add_guid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1403 const guint8* value_ptr)
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_GUID);
1417 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1418 proto_tree_set_guid(new_fi, value_ptr);
1424 proto_tree_add_guid_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1425 const guint8* value_ptr)
1429 pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
1433 PROTO_ITEM_SET_HIDDEN(pi);
1439 proto_tree_add_guid_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1440 const guint8* value_ptr, const char *format, ...)
1445 pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
1449 va_start(ap, format);
1450 proto_tree_set_representation(pi, format, ap);
1456 /* Set the FT_GUID value */
1458 proto_tree_set_guid(field_info *fi, const guint8* value_ptr)
1460 DISSECTOR_ASSERT(value_ptr != NULL);
1461 fvalue_set(&fi->value, (gpointer) value_ptr, FALSE);
1465 proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, gint start)
1467 proto_tree_set_guid(fi, tvb_get_ptr(tvb, start, 16));
1471 proto_tree_set_uint64(field_info *fi, guint64 value)
1473 fvalue_set_integer64(&fi->value, value);
1477 proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start, gboolean little_endian)
1481 value = little_endian ? tvb_get_letoh64(tvb, start)
1482 : tvb_get_ntoh64(tvb, start);
1484 proto_tree_set_uint64(fi, value);
1487 /* Add a FT_STRING or FT_STRINGZ to a proto_tree. Creates own copy of string,
1488 * and frees it when the proto_tree is destroyed. */
1490 proto_tree_add_string(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1491 gint length, const char* value)
1495 header_field_info *hfinfo;
1500 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1502 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1503 DISSECTOR_ASSERT(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ);
1505 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1506 DISSECTOR_ASSERT(length >= 0);
1507 proto_tree_set_string(new_fi, value, FALSE);
1513 proto_tree_add_string_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1514 gint length, const char* value)
1518 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
1522 PROTO_ITEM_SET_HIDDEN(pi);
1528 proto_tree_add_string_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1529 gint length, const char* value, const char *format, ...)
1534 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
1538 va_start(ap, format);
1539 proto_tree_set_representation(pi, format, ap);
1545 /* Appends string data to a FT_STRING or FT_STRINGZ, allowing progressive
1546 * field info update instead of only updating the representation as does
1547 * proto_item_append_text()
1549 /* NOTE: this function will break with the TRY_TO_FAKE_THIS_ITEM()
1550 * speed optimization.
1551 * Currently only WSP use this function so it is not that bad but try to
1552 * avoid using this one if possible.
1553 * IF you must use this function you MUST also disable the
1554 * TRY_TO_FAKE_THIS_ITEM() optimization for your dissector/function
1555 * using proto_item_append_string().
1556 * Do that by faking that the tree is visible by setting :
1557 * PTREE_DATA(tree)->visible=1; (see packet-wsp.c)
1558 * BEFORE you create the item you are later going to use
1559 * proto_item_append_string() on.
1562 proto_item_append_string(proto_item *pi, const char *str)
1565 header_field_info *hfinfo;
1566 gchar *old_str, *new_str;
1573 fi = PITEM_FINFO(pi);
1574 hfinfo = fi->hfinfo;
1575 if (hfinfo->type == FT_PROTOCOL) {
1576 /* TRY_TO_FAKE_THIS_ITEM() speed optimization: silently skip */
1579 DISSECTOR_ASSERT(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ);
1580 old_str = fvalue_get(&fi->value);
1581 new_str = g_strdup_printf("%s%s", old_str, str);
1582 fvalue_set(&fi->value, new_str, TRUE);
1585 /* Set the FT_STRING value */
1587 proto_tree_set_string(field_info *fi, const char* value,
1588 gboolean already_allocated)
1591 fvalue_set(&fi->value, (gpointer) value, already_allocated);
1593 fvalue_set(&fi->value, (gpointer) "[ Null ]", already_allocated);
1597 proto_tree_set_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
1602 length = tvb_ensure_length_remaining(tvb, start);
1605 /* This memory is freed in proto_tree_free_node() */
1606 string = tvb_get_string(tvb, start, length);
1607 proto_tree_set_string(fi, string, TRUE);
1610 /* Add a FT_ETHER to a proto_tree */
1612 proto_tree_add_ether(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1613 const guint8* value)
1617 header_field_info *hfinfo;
1622 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1624 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1625 DISSECTOR_ASSERT(hfinfo->type == FT_ETHER);
1627 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1628 proto_tree_set_ether(new_fi, value);
1634 proto_tree_add_ether_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1635 const guint8* value)
1639 pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
1643 PROTO_ITEM_SET_HIDDEN(pi);
1649 proto_tree_add_ether_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1650 const guint8* value, const char *format, ...)
1655 pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
1659 va_start(ap, format);
1660 proto_tree_set_representation(pi, format, ap);
1666 /* Set the FT_ETHER value */
1668 proto_tree_set_ether(field_info *fi, const guint8* value)
1670 fvalue_set(&fi->value, (gpointer) value, FALSE);
1674 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start)
1676 proto_tree_set_ether(fi, tvb_get_ptr(tvb, start, 6));
1679 /* Add a FT_BOOLEAN to a proto_tree */
1681 proto_tree_add_boolean(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1686 header_field_info *hfinfo;
1691 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1693 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1694 DISSECTOR_ASSERT(hfinfo->type == FT_BOOLEAN);
1696 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1697 proto_tree_set_boolean(new_fi, value);
1703 proto_tree_add_boolean_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1708 pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
1712 PROTO_ITEM_SET_HIDDEN(pi);
1718 proto_tree_add_boolean_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1719 guint32 value, const char *format, ...)
1724 pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
1728 va_start(ap, format);
1729 proto_tree_set_representation(pi, format, ap);
1735 /* Set the FT_BOOLEAN value */
1737 proto_tree_set_boolean(field_info *fi, guint32 value)
1739 proto_tree_set_uint(fi, value);
1742 /* Add a FT_FLOAT to a proto_tree */
1744 proto_tree_add_float(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1749 header_field_info *hfinfo;
1754 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1756 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1757 DISSECTOR_ASSERT(hfinfo->type == FT_FLOAT);
1759 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1760 proto_tree_set_float(new_fi, value);
1766 proto_tree_add_float_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1771 pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
1775 PROTO_ITEM_SET_HIDDEN(pi);
1781 proto_tree_add_float_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1782 float value, const char *format, ...)
1787 pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
1791 va_start(ap, format);
1792 proto_tree_set_representation(pi, format, ap);
1798 /* Set the FT_FLOAT value */
1800 proto_tree_set_float(field_info *fi, float value)
1802 fvalue_set_floating(&fi->value, value);
1805 /* Add a FT_DOUBLE to a proto_tree */
1807 proto_tree_add_double(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1812 header_field_info *hfinfo;
1817 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1819 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1820 DISSECTOR_ASSERT(hfinfo->type == FT_DOUBLE);
1822 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1823 proto_tree_set_double(new_fi, value);
1829 proto_tree_add_double_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1834 pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
1838 PROTO_ITEM_SET_HIDDEN(pi);
1844 proto_tree_add_double_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1845 double value, const char *format, ...)
1850 pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
1854 va_start(ap, format);
1855 proto_tree_set_representation(pi, format, ap);
1861 /* Set the FT_DOUBLE value */
1863 proto_tree_set_double(field_info *fi, double value)
1865 fvalue_set_floating(&fi->value, value);
1868 /* Add FT_UINT{8,16,24,32} to a proto_tree */
1870 proto_tree_add_uint(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1873 proto_item *pi = NULL;
1875 header_field_info *hfinfo;
1880 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1882 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1883 switch(hfinfo->type) {
1889 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length,
1891 proto_tree_set_uint(new_fi, value);
1895 DISSECTOR_ASSERT_NOT_REACHED();
1902 proto_tree_add_uint_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1907 pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
1911 PROTO_ITEM_SET_HIDDEN(pi);
1917 proto_tree_add_uint_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1918 guint32 value, const char *format, ...)
1923 pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
1927 va_start(ap, format);
1928 proto_tree_set_representation(pi, format, ap);
1934 /* Set the FT_UINT{8,16,24,32} value */
1936 proto_tree_set_uint(field_info *fi, guint32 value)
1938 header_field_info *hfinfo;
1941 hfinfo = fi->hfinfo;
1944 if (hfinfo->bitmask) {
1945 /* Mask out irrelevant portions */
1946 integer &= hfinfo->bitmask;
1949 if (hfinfo->bitshift > 0) {
1950 integer >>= hfinfo->bitshift;
1953 fvalue_set_integer(&fi->value, integer);
1956 /* Add FT_UINT64 to a proto_tree */
1958 proto_tree_add_uint64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1961 proto_item *pi = NULL;
1963 header_field_info *hfinfo;
1968 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1970 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1971 DISSECTOR_ASSERT(hfinfo->type == FT_UINT64);
1973 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1974 proto_tree_set_uint64(new_fi, value);
1980 proto_tree_add_uint64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1981 guint64 value, const char *format, ...)
1986 pi = proto_tree_add_uint64(tree, hfindex, tvb, start, length, value);
1990 va_start(ap, format);
1991 proto_tree_set_representation(pi, format, ap);
1997 /* Add FT_INT{8,16,24,32} to a proto_tree */
1999 proto_tree_add_int(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2002 proto_item *pi = NULL;
2004 header_field_info *hfinfo;
2009 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
2011 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2012 switch(hfinfo->type) {
2017 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length,
2019 proto_tree_set_int(new_fi, value);
2023 DISSECTOR_ASSERT_NOT_REACHED();
2030 proto_tree_add_int_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2035 pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
2039 PROTO_ITEM_SET_HIDDEN(pi);
2045 proto_tree_add_int_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2046 gint32 value, const char *format, ...)
2048 proto_item *pi = NULL;
2051 pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
2055 va_start(ap, format);
2056 proto_tree_set_representation(pi, format, ap);
2062 /* Set the FT_INT{8,16,24,32} value */
2064 proto_tree_set_int(field_info *fi, gint32 value)
2066 header_field_info *hfinfo;
2069 hfinfo = fi->hfinfo;
2070 integer = (guint32) value;
2072 if (hfinfo->bitmask) {
2073 /* Mask out irrelevant portions */
2074 integer &= hfinfo->bitmask;
2077 if (hfinfo->bitshift > 0) {
2078 integer >>= hfinfo->bitshift;
2081 fvalue_set_integer(&fi->value, integer);
2084 /* Add FT_INT64 to a proto_tree */
2086 proto_tree_add_int64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2089 proto_item *pi = NULL;
2091 header_field_info *hfinfo;
2096 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
2098 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2099 DISSECTOR_ASSERT(hfinfo->type == FT_INT64);
2101 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2102 proto_tree_set_uint64(new_fi, (guint64)value);
2108 proto_tree_add_int64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2109 gint64 value, const char *format, ...)
2114 pi = proto_tree_add_int64(tree, hfindex, tvb, start, length, value);
2118 va_start(ap, format);
2119 proto_tree_set_representation(pi, format, ap);
2126 /* Add a field_info struct to the proto_tree, encapsulating it in a proto_node */
2128 proto_tree_add_node(proto_tree *tree, field_info *fi)
2130 proto_node *pnode, *tnode, *sibling;
2134 * Make sure "tree" is ready to have subtrees under it, by
2135 * checking whether it's been given an ett_ value.
2137 * "tnode->finfo" may be null; that's the case for the root
2138 * node of the protocol tree. That node is not displayed,
2139 * so it doesn't need an ett_ value to remember whether it
2144 if (tfi != NULL && (tfi->tree_type < 0 || tfi->tree_type >= num_tree_types)) {
2145 REPORT_DISSECTOR_BUG(g_strdup_printf("\"%s\" - \"%s\" tfi->tree_type: %u invalid (%s:%u)",
2146 fi->hfinfo->name, fi->hfinfo->abbrev, tfi->tree_type, __FILE__, __LINE__));
2147 /* XXX - is it safe to continue here? */
2150 DISSECTOR_ASSERT(tfi == NULL ||
2151 (tfi->tree_type >= 0 && tfi->tree_type < num_tree_types));
2153 PROTO_NODE_NEW(pnode);
2154 pnode->parent = tnode;
2156 pnode->tree_data = PTREE_DATA(tree);
2158 if (tnode->last_child != NULL) {
2159 sibling = tnode->last_child;
2160 DISSECTOR_ASSERT(sibling->next == NULL);
2161 sibling->next = pnode;
2163 tnode->first_child = pnode;
2164 tnode->last_child = pnode;
2166 return (proto_item*)pnode;
2170 /* Generic way to allocate field_info and add to proto_tree.
2171 * Sets *pfi to address of newly-allocated field_info struct, if pfi is
2174 proto_tree_add_pi(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2175 gint *length, field_info **pfi)
2185 fi = alloc_field_info(tree, hfindex, tvb, start, length);
2186 pi = proto_tree_add_node(tree, fi);
2188 /* If the proto_tree wants to keep a record of this finfo
2189 * for quick lookup, then record it. */
2190 if (fi->hfinfo->ref_count) {
2191 hash = PTREE_DATA(tree)->interesting_hfids;
2192 ptrs = g_hash_table_lookup(hash, GINT_TO_POINTER(hfindex));
2194 g_ptr_array_add(ptrs, fi);
2198 /* Does the caller want to know the fi pointer? */
2207 alloc_field_info(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2210 header_field_info *hfinfo;
2213 gint length_remaining;
2216 * We only allow a null tvbuff if the item has a zero length,
2217 * i.e. if there's no data backing it.
2219 DISSECTOR_ASSERT(tvb != NULL || *length == 0);
2221 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2224 * XXX - in some protocols, there are 32-bit unsigned length
2225 * fields, so lengths in protocol tree and tvbuff routines
2226 * should really be unsigned. We should have, for those
2227 * field types for which "to the end of the tvbuff" makes sense,
2228 * additional routines that take no length argument and
2229 * add fields that run to the end of the tvbuff.
2231 if (*length == -1) {
2233 * For FT_NONE, FT_PROTOCOL, FT_BYTES, and FT_STRING fields,
2234 * a length of -1 means "set the length to what remains in
2237 * The assumption is either that
2239 * 1) the length of the item can only be determined
2240 * by dissection (typically true of items with
2241 * subitems, which are probably FT_NONE or
2246 * 2) if the tvbuff is "short" (either due to a short
2247 * snapshot length or due to lack of reassembly of
2248 * fragments/segments/whatever), we want to display
2249 * what's available in the field (probably FT_BYTES
2250 * or FT_STRING) and then throw an exception later
2254 * 3) the field is defined to be "what's left in the
2257 * so we set the length to what remains in the tvbuff so
2258 * that, if we throw an exception while dissecting, it
2259 * has what is probably the right value.
2261 * For FT_STRINGZ, it means "the string is null-terminated,
2262 * not null-padded; set the length to the actual length
2263 * of the string", and if the tvbuff if short, we just
2264 * throw an exception.
2266 * It's not valid for any other type of field.
2268 switch (hfinfo->type) {
2272 * We allow this to be zero-length - for
2273 * example, an ONC RPC NULL procedure has
2274 * neither arguments nor reply, so the
2275 * payload for that protocol is empty.
2277 * However, if the length is negative, the
2278 * start offset is *past* the byte past the
2279 * end of the tvbuff, so we throw an
2282 *length = tvb_length_remaining(tvb, start);
2285 * Use "tvb_ensure_bytes_exist()"
2286 * to force the appropriate exception
2289 tvb_ensure_bytes_exist(tvb, start, 0);
2291 DISSECTOR_ASSERT(*length >= 0);
2297 *length = tvb_ensure_length_remaining(tvb, start);
2298 DISSECTOR_ASSERT(*length >= 0);
2303 * Leave the length as -1, so our caller knows
2309 DISSECTOR_ASSERT_NOT_REACHED();
2311 item_length = *length;
2313 item_length = *length;
2314 if (hfinfo->type == FT_PROTOCOL || hfinfo->type == FT_NONE) {
2316 * These types are for interior nodes of the
2317 * tree, and don't have data associated with
2318 * them; if the length is negative (XXX - see
2319 * above) or goes past the end of the tvbuff,
2320 * cut it short at the end of the tvbuff.
2321 * That way, if this field is selected in
2322 * Ethereal, we don't highlight stuff past
2323 * the end of the data.
2325 /* XXX - what to do, if we don't have a tvb? */
2327 length_remaining = tvb_length_remaining(tvb, start);
2328 if (item_length < 0 || (item_length > 0 && (length_remaining < item_length)))
2329 item_length = length_remaining;
2332 if (item_length < 0) {
2333 THROW(ReportedBoundsError);
2339 fi->hfinfo = hfinfo;
2341 fi->start+=(tvb)?TVB_RAW_OFFSET(tvb):0;
2342 fi->length = item_length;
2345 if (!PTREE_DATA(tree)->visible)
2346 FI_SET_FLAG(fi, FI_HIDDEN);
2347 fvalue_init(&fi->value, fi->hfinfo->type);
2350 /* add the data source tvbuff */
2351 fi->ds_tvb=tvb?TVB_GET_DS_TVB(tvb):NULL;
2356 /* Set representation of a proto_tree entry, if the protocol tree is to
2359 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap)
2361 int ret; /*tmp return value */
2362 field_info *fi = PITEM_FINFO(pi);
2364 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
2365 ITEM_LABEL_NEW(fi->rep);
2366 ret = g_vsnprintf(fi->rep->representation, ITEM_LABEL_LENGTH, format, ap);
2367 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
2368 fi->rep->representation[ITEM_LABEL_LENGTH - 1] = '\0';
2372 /* Set text of proto_item after having already been created. */
2374 proto_item_set_text(proto_item *pi, const char *format, ...)
2376 field_info *fi = NULL;
2383 fi = PITEM_FINFO(pi);
2386 ITEM_LABEL_FREE(fi->rep);
2389 va_start(ap, format);
2390 proto_tree_set_representation(pi, format, ap);
2394 /* Append to text of proto_item after having already been created. */
2396 proto_item_append_text(proto_item *pi, const char *format, ...)
2398 field_info *fi = NULL;
2401 int ret; /*tmp return value */
2407 fi = PITEM_FINFO(pi);
2409 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
2410 va_start(ap, format);
2413 * If we don't already have a representation,
2414 * generate the default representation.
2416 if (fi->rep == NULL) {
2417 ITEM_LABEL_NEW(fi->rep);
2418 proto_item_fill_label(fi, fi->rep->representation);
2421 curlen = strlen(fi->rep->representation);
2422 if (ITEM_LABEL_LENGTH > curlen) {
2423 ret = g_vsnprintf(fi->rep->representation + curlen,
2424 ITEM_LABEL_LENGTH - curlen, format, ap);
2425 if ((ret == -1) || (ret >= (int)(ITEM_LABEL_LENGTH - curlen)))
2426 fi->rep->representation[ITEM_LABEL_LENGTH - 1] = '\0';
2433 proto_item_set_len(proto_item *pi, gint length)
2439 fi = PITEM_FINFO(pi);
2440 DISSECTOR_ASSERT(length >= 0);
2441 fi->length = length;
2445 * Sets the length of the item based on its start and on the specified
2446 * offset, which is the offset past the end of the item; as the start
2447 * in the item is relative to the beginning of the data source tvbuff,
2448 * we need to pass in a tvbuff - the end offset is relative to the beginning
2452 proto_item_set_end(proto_item *pi, tvbuff_t *tvb, gint end)
2458 fi = PITEM_FINFO(pi);
2459 end += TVB_RAW_OFFSET(tvb);
2460 DISSECTOR_ASSERT(end >= fi->start);
2461 fi->length = end - fi->start;
2465 proto_item_get_len(proto_item *pi)
2467 field_info *fi = PITEM_FINFO(pi);
2472 /** clear flags according to the mask and set new flag values */
2473 #define FI_REPLACE_FLAGS(fi, mask, flags_in) { \
2474 (fi->flags = (fi)->flags & ~(mask)); \
2475 (fi->flags = (fi)->flags | (flags_in)); \
2479 proto_item_set_expert_flags(proto_item *pi, int group, int severity)
2481 if(pi == NULL || pi->finfo == NULL)
2484 /* only change things if severity is worse or at least equal than before */
2485 if(severity >= FI_GET_FLAG(pi->finfo, PI_SEVERITY_MASK)) {
2486 FI_REPLACE_FLAGS(pi->finfo, PI_GROUP_MASK, group);
2487 FI_REPLACE_FLAGS(pi->finfo, PI_SEVERITY_MASK, severity);
2498 proto_tree_create_root(void)
2502 /* Initialize the proto_node */
2503 PROTO_NODE_NEW(pnode);
2504 pnode->parent = NULL;
2505 pnode->finfo = NULL;
2506 pnode->tree_data = g_new(tree_data_t, 1);
2508 /* Initialize the tree_data_t */
2509 pnode->tree_data->interesting_hfids =
2510 g_hash_table_new(g_direct_hash, g_direct_equal);
2512 /* Set the default to FALSE so it's easier to
2513 * find errors; if we expect to see the protocol tree
2514 * but for some reason the default 'visible' is not
2515 * changed, then we'll find out very quickly. */
2516 pnode->tree_data->visible = FALSE;
2518 return (proto_tree*) pnode;
2522 /* "prime" a proto_tree with a single hfid that a dfilter
2523 * is interested in. */
2525 proto_tree_prime_hfid(proto_tree *tree, gint hfid)
2527 header_field_info *hfinfo;
2529 g_hash_table_insert(PTREE_DATA(tree)->interesting_hfids,
2530 GINT_TO_POINTER(hfid), g_ptr_array_new());
2532 PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
2533 /* this field is referenced by a filter so increase the refcount.
2534 also increase the refcount for the parent, i.e the protocol.
2536 hfinfo->ref_count++;
2537 /* only increase the refcount if there is a parent.
2538 if this is a protocol and not a field then parent will be -1
2539 and there is no parent to add any refcounting for.
2541 if (hfinfo->parent != -1) {
2542 header_field_info *parent_hfinfo;
2543 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
2544 parent_hfinfo->ref_count++;
2549 proto_item_add_subtree(proto_item *pi, gint idx) {
2555 fi = PITEM_FINFO(pi);
2556 DISSECTOR_ASSERT(idx >= 0 && idx < num_tree_types);
2557 fi->tree_type = idx;
2559 return (proto_tree*) pi;
2563 proto_item_get_subtree(proto_item *pi) {
2568 fi = PITEM_FINFO(pi);
2569 if ( (!fi) || (fi->tree_type == -1) )
2571 return (proto_tree*) pi;
2575 proto_item_get_parent(proto_item *ti) {
2576 /* dont bother if tree is not visible */
2577 if( (!ti) || (!(PTREE_DATA(ti)->visible)) )
2583 proto_item_get_parent_nth(proto_item *ti, int gen) {
2584 /* dont bother if tree is not visible */
2585 if( (!ti) || (!(PTREE_DATA(ti)->visible)) )
2597 proto_tree_get_parent(proto_tree *tree) {
2598 /* dont bother if tree is not visible */
2599 if( (!tree) || (!(PTREE_DATA(tree)->visible)) )
2601 return (proto_item*) tree;
2606 proto_tree_move_item(proto_tree *tree, proto_item *fixed_item, proto_item *item_to_move)
2608 proto_item *curr_item;
2611 /*** cut item_to_move out ***/
2613 /* is item_to_move the first? */
2614 if(tree->first_child == item_to_move) {
2615 /* simply change first child to next */
2616 tree->first_child = item_to_move->next;
2618 /* find previous and change it's next */
2619 for(curr_item = tree->first_child; curr_item != NULL; curr_item = curr_item->next) {
2620 if(curr_item->next == item_to_move) {
2625 DISSECTOR_ASSERT(curr_item);
2627 curr_item->next = item_to_move->next;
2629 /* fix last_child if required */
2630 if(tree->last_child == item_to_move) {
2631 tree->last_child = curr_item;
2635 /*** insert to_move after fixed ***/
2636 item_to_move->next = fixed_item->next;
2637 fixed_item->next = item_to_move;
2638 if(tree->last_child == fixed_item) {
2639 tree->last_child = item_to_move;
2645 proto_register_protocol(const char *name, const char *short_name, const char *filter_name)
2647 protocol_t *protocol;
2648 header_field_info *hfinfo;
2650 char *existing_name;
2653 gboolean found_invalid;
2656 * Make sure there's not already a protocol with any of those
2657 * names. Crash if there is, as that's an error in the code
2658 * or an inappropriate plugin.
2659 * This situation has to be fixed to not register more than one
2660 * protocol with the same name.
2662 * This is done by reducing the number of strcmp (and alike) calls as much as possible,
2663 * as this significally slows down startup time.
2665 * Drawback: As a hash value is used to reduce insert time,
2666 * this might lead to a hash collision.
2667 * However, as we have around 500+ protocols and we're using a 32 bit int this is very,
2671 key = g_malloc (sizeof(gint));
2672 *key = g_str_hash(name);
2673 existing_name = g_hash_table_lookup(proto_names, key);
2674 if (existing_name != NULL) {
2675 /* g_error will terminate the program */
2676 g_error("Duplicate protocol name \"%s\"!"
2677 " This might be caused by an inappropriate plugin or a development error.", name);
2679 g_hash_table_insert(proto_names, key, (gpointer)name);
2681 key = g_malloc (sizeof(gint));
2682 *key = g_str_hash(short_name);
2683 existing_name = g_hash_table_lookup(proto_short_names, key);
2684 if (existing_name != NULL) {
2685 g_error("Duplicate protocol short_name \"%s\"!"
2686 " This might be caused by an inappropriate plugin or a development error.", short_name);
2688 g_hash_table_insert(proto_short_names, key, (gpointer)short_name);
2690 found_invalid = FALSE;
2691 for (i = 0; i < strlen(filter_name); i++) {
2692 if (! (islower(filter_name[i]) ||
2693 isdigit(filter_name[i]) ||
2694 filter_name[i] == '-' ||
2695 filter_name[i] == '_' ||
2696 filter_name[i] == '.' )) {
2697 found_invalid = TRUE;
2700 if (found_invalid) {
2701 g_warning("Protocol filter name \"%s\" has one or more invalid characters.", filter_name);
2703 key = g_malloc (sizeof(gint));
2704 *key = g_str_hash(filter_name);
2705 existing_name = g_hash_table_lookup(proto_filter_names, key);
2706 if (existing_name != NULL) {
2707 g_error("Duplicate protocol filter_name \"%s\"!"
2708 " This might be caused by an inappropriate plugin or a development error.", filter_name);
2710 g_hash_table_insert(proto_filter_names, key, (gpointer)filter_name);
2712 /* Add this protocol to the list of known protocols; the list
2713 is sorted by protocol short name. */
2714 protocol = g_malloc(sizeof (protocol_t));
2715 protocol->name = name;
2716 protocol->short_name = short_name;
2717 protocol->filter_name = filter_name;
2718 protocol->fields = NULL;
2719 protocol->is_enabled = TRUE; /* protocol is enabled by default */
2720 protocol->can_toggle = TRUE;
2721 /* list will be sorted later by name, when all protocols completed registering */
2722 protocols = g_list_append(protocols, protocol);
2724 /* Here we do allocate a new header_field_info struct */
2725 hfinfo = g_mem_chunk_alloc(gmc_hfinfo);
2726 hfinfo->name = name;
2727 hfinfo->abbrev = filter_name;
2728 hfinfo->type = FT_PROTOCOL;
2729 hfinfo->strings = protocol;
2730 hfinfo->bitmask = 0;
2731 hfinfo->bitshift = 0;
2732 hfinfo->ref_count = 0;
2734 hfinfo->parent = -1; /* this field differentiates protos and fields */
2736 proto_id = proto_register_field_init(hfinfo, hfinfo->parent);
2737 protocol->proto_id = proto_id;
2742 * Routines to use to iterate over the protocols.
2743 * The argument passed to the iterator routines is an opaque cookie to
2744 * their callers; it's the GList pointer for the current element in
2746 * The ID of the protocol is returned, or -1 if there is no protocol.
2749 proto_get_first_protocol(void **cookie)
2751 protocol_t *protocol;
2753 if (protocols == NULL)
2755 *cookie = protocols;
2756 protocol = protocols->data;
2757 return protocol->proto_id;
2761 proto_get_next_protocol(void **cookie)
2763 GList *list_item = *cookie;
2764 protocol_t *protocol;
2766 list_item = g_list_next(list_item);
2767 if (list_item == NULL)
2769 *cookie = list_item;
2770 protocol = list_item->data;
2771 return protocol->proto_id;
2775 proto_get_first_protocol_field(int proto_id, void **cookie)
2777 protocol_t *protocol = find_protocol_by_id(proto_id);
2778 hf_register_info *ptr;
2780 if ((protocol == NULL) || (protocol->fields == NULL))
2783 *cookie = protocol->fields;
2784 ptr = protocol->fields->data;
2785 return &ptr->hfinfo;
2789 proto_get_next_protocol_field(void **cookie)
2791 GList *list_item = *cookie;
2792 hf_register_info *ptr;
2794 list_item = g_list_next(list_item);
2795 if (list_item == NULL)
2798 *cookie = list_item;
2799 ptr = list_item->data;
2800 return &ptr->hfinfo;
2804 find_protocol_by_id(int proto_id)
2806 header_field_info *hfinfo;
2811 PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
2812 DISSECTOR_ASSERT(hfinfo->type==FT_PROTOCOL);
2813 return (protocol_t *)hfinfo->strings;
2816 static gint compare_filter_name(gconstpointer proto_arg,
2817 gconstpointer filter_name)
2819 const protocol_t *protocol = proto_arg;
2820 const gchar* f_name = filter_name;
2822 return (strcmp(protocol->filter_name, f_name));
2826 proto_get_id(protocol_t *protocol)
2828 return protocol->proto_id;
2831 int proto_get_id_by_filter_name(const gchar* filter_name)
2834 protocol_t *protocol;
2836 list_entry = g_list_find_custom(protocols, filter_name,
2837 compare_filter_name);
2838 if (list_entry == NULL)
2840 protocol = list_entry->data;
2841 return protocol->proto_id;
2845 proto_get_protocol_name(int proto_id)
2847 protocol_t *protocol;
2849 protocol = find_protocol_by_id(proto_id);
2850 return protocol->name;
2854 proto_get_protocol_short_name(protocol_t *protocol)
2856 if (protocol == NULL)
2858 return protocol->short_name;
2862 proto_get_protocol_filter_name(int proto_id)
2864 protocol_t *protocol;
2866 protocol = find_protocol_by_id(proto_id);
2867 return protocol->filter_name;
2871 proto_is_protocol_enabled(protocol_t *protocol)
2873 return protocol->is_enabled;
2877 proto_can_toggle_protocol(int proto_id)
2879 protocol_t *protocol;
2881 protocol = find_protocol_by_id(proto_id);
2882 return protocol->can_toggle;
2886 proto_set_decoding(int proto_id, gboolean enabled)
2888 protocol_t *protocol;
2890 protocol = find_protocol_by_id(proto_id);
2891 DISSECTOR_ASSERT(protocol->can_toggle);
2892 protocol->is_enabled = enabled;
2896 proto_set_cant_toggle(int proto_id)
2898 protocol_t *protocol;
2900 protocol = find_protocol_by_id(proto_id);
2901 protocol->can_toggle = FALSE;
2904 /* for use with static arrays only, since we don't allocate our own copies
2905 of the header_field_info struct contained within the hf_register_info struct */
2907 proto_register_field_array(int parent, hf_register_info *hf, int num_records)
2910 hf_register_info *ptr = hf;
2913 proto = find_protocol_by_id(parent);
2914 for (i = 0; i < num_records; i++, ptr++) {
2916 * Make sure we haven't registered this yet.
2917 * Most fields have variables associated with them
2918 * that are initialized to -1; some have array elements,
2919 * or possibly uninitialized variables, so we also allow
2920 * 0 (which is unlikely to be the field ID we get back
2921 * from "proto_register_field_init()").
2923 DISSECTOR_ASSERT((*ptr->p_id == -1 || *ptr->p_id == 0) && "Duplicate field detected in call to proto_register_field_array");
2925 if (proto != NULL) {
2926 if (proto->fields == NULL) {
2927 proto->fields = g_list_append(NULL, ptr);
2928 proto->last_field = proto->fields;
2931 g_list_append(proto->last_field, ptr)->next;
2934 field_id = proto_register_field_init(&ptr->hfinfo, parent);
2935 *ptr->p_id = field_id;
2940 proto_register_field_init(header_field_info *hfinfo, int parent)
2942 /* The field must have names */
2943 DISSECTOR_ASSERT(hfinfo->name);
2944 DISSECTOR_ASSERT(hfinfo->abbrev);
2946 /* These types of fields are allowed to have value_strings, true_false_strings or a protocol_t struct*/
2947 DISSECTOR_ASSERT((hfinfo->strings == NULL) || (
2948 (hfinfo->type == FT_UINT8) ||
2949 (hfinfo->type == FT_UINT16) ||
2950 (hfinfo->type == FT_UINT24) ||
2951 (hfinfo->type == FT_UINT32) ||
2952 (hfinfo->type == FT_INT8) ||
2953 (hfinfo->type == FT_INT16) ||
2954 (hfinfo->type == FT_INT24) ||
2955 (hfinfo->type == FT_INT32) ||
2956 (hfinfo->type == FT_BOOLEAN) ||
2957 (hfinfo->type == FT_PROTOCOL) ||
2958 (hfinfo->type == FT_FRAMENUM) ));
2960 switch (hfinfo->type) {
2970 /* Require integral types (other than frame number, which is
2971 always displayed in decimal) to have a number base */
2972 DISSECTOR_ASSERT(hfinfo->display != BASE_NONE);
2976 /* Don't allow bitfields or value strings for frame numbers */
2977 DISSECTOR_ASSERT(hfinfo->bitmask == 0);
2978 DISSECTOR_ASSERT(hfinfo->strings == NULL);
2984 /* if this is a bitfield, compute bitshift */
2985 if (hfinfo->bitmask) {
2986 while ((hfinfo->bitmask & (1 << hfinfo->bitshift)) == 0)
2990 hfinfo->parent = parent;
2991 hfinfo->same_name_next = NULL;
2992 hfinfo->same_name_prev = NULL;
2994 /* if we always add and never delete, then id == len - 1 is correct */
2995 if(gpa_hfinfo.len>=gpa_hfinfo.allocated_len){
2996 if(!gpa_hfinfo.hfi){
2997 gpa_hfinfo.allocated_len=1000;
2998 gpa_hfinfo.hfi=g_malloc(sizeof(header_field_info *)*1000);
3000 gpa_hfinfo.allocated_len+=1000;
3001 gpa_hfinfo.hfi=g_realloc(gpa_hfinfo.hfi, sizeof(header_field_info *)*gpa_hfinfo.allocated_len);
3004 gpa_hfinfo.hfi[gpa_hfinfo.len]=hfinfo;
3006 hfinfo->id = gpa_hfinfo.len - 1;
3008 /* if we have real names, enter this field in the name tree */
3009 if ((hfinfo->name[0] != 0) && (hfinfo->abbrev[0] != 0 )) {
3011 header_field_info *same_name_hfinfo, *same_name_next_hfinfo;
3015 /* Check that the filter name (abbreviation) is legal;
3016 * it must contain only alphanumerics, '-', "_", and ".". */
3017 for (p = hfinfo->abbrev; (c = *p) != '\0'; p++)
3018 DISSECTOR_ASSERT(isalnum(c) || c == '-' || c == '_' ||
3021 /* We allow multiple hfinfo's to be registered under the same
3022 * abbreviation. This was done for X.25, as, depending
3023 * on whether it's modulo-8 or modulo-128 operation,
3024 * some bitfield fields may be in different bits of
3025 * a byte, and we want to be able to refer to that field
3026 * with one name regardless of whether the packets
3027 * are modulo-8 or modulo-128 packets. */
3028 same_name_hfinfo = g_tree_lookup(gpa_name_tree, hfinfo->abbrev);
3029 if (same_name_hfinfo) {
3030 /* There's already a field with this name.
3031 * Put it after that field in the list of
3032 * fields with this name, then allow the code
3033 * after this if{} block to replace the old
3034 * hfinfo with the new hfinfo in the GTree. Thus,
3035 * we end up with a linked-list of same-named hfinfo's,
3036 * with the root of the list being the hfinfo in the GTree */
3037 same_name_next_hfinfo =
3038 same_name_hfinfo->same_name_next;
3040 hfinfo->same_name_next = same_name_next_hfinfo;
3041 if (same_name_next_hfinfo)
3042 same_name_next_hfinfo->same_name_prev = hfinfo;
3044 same_name_hfinfo->same_name_next = hfinfo;
3045 hfinfo->same_name_prev = same_name_hfinfo;
3047 g_tree_insert(gpa_name_tree, (gpointer) (hfinfo->abbrev), hfinfo);
3054 proto_register_subtree_array(gint *const *indices, int num_indices)
3057 gint *const *ptr = indices;
3060 * If we've already allocated the array of tree types, expand
3061 * it; this lets plugins such as mate add tree types after
3062 * the initial startup. (If we haven't already allocated it,
3063 * we don't allocate it; on the first pass, we just assign
3064 * ett values and keep track of how many we've assigned, and
3065 * when we're finished registering all dissectors we allocate
3066 * the array, so that we do only one allocation rather than
3067 * wasting CPU time and memory by growing the array for each
3068 * dissector that registers ett values.)
3070 if (tree_is_expanded != NULL) {
3072 g_realloc(tree_is_expanded,
3073 (num_tree_types+num_indices)*sizeof (gint *));
3074 memset(tree_is_expanded + num_tree_types, 0,
3075 num_indices*sizeof (gint *));
3079 * Assign "num_indices" subtree numbers starting at "num_tree_types",
3080 * returning the indices through the pointers in the array whose
3081 * first element is pointed to by "indices", and update
3082 * "num_tree_types" appropriately.
3084 for (i = 0; i < num_indices; i++, ptr++, num_tree_types++)
3085 **ptr = num_tree_types;
3089 proto_item_fill_label(field_info *fi, gchar *label_str)
3091 header_field_info *hfinfo = fi->hfinfo;
3096 guint32 n_addr; /* network-order IPv4 address */
3097 int ret; /*tmp return value */
3099 switch(hfinfo->type) {
3102 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3103 "%s", hfinfo->name);
3104 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3105 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3109 fill_label_boolean(fi, label_str);
3114 bytes = fvalue_get(&fi->value);
3116 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3117 "%s: %s", hfinfo->name,
3118 bytes_to_str(bytes, fvalue_length(&fi->value)));
3119 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3120 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3123 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3124 "%s: <MISSING>", hfinfo->name);
3125 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3126 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3130 /* Four types of integers to take care of:
3131 * Bitfield, with val_string
3132 * Bitfield, w/o val_string
3133 * Non-bitfield, with val_string
3134 * Non-bitfield, w/o val_string
3141 if (hfinfo->bitmask) {
3142 if (hfinfo->strings) {
3143 fill_label_enumerated_bitfield(fi, label_str);
3146 fill_label_numeric_bitfield(fi, label_str);
3150 if (hfinfo->strings) {
3151 fill_label_enumerated_uint(fi, label_str);
3154 fill_label_uint(fi, label_str);
3160 fill_label_uint64(fi, label_str);
3167 DISSECTOR_ASSERT(!hfinfo->bitmask);
3168 if (hfinfo->strings) {
3169 fill_label_enumerated_int(fi, label_str);
3172 fill_label_int(fi, label_str);
3177 fill_label_int64(fi, label_str);
3181 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3182 "%s: %." STRINGIFY(FLT_DIG) "f",
3183 hfinfo->name, fvalue_get_floating(&fi->value));
3184 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3185 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3189 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3190 "%s: %." STRINGIFY(DBL_DIG) "g",
3191 hfinfo->name, fvalue_get_floating(&fi->value));
3192 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3193 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3196 case FT_ABSOLUTE_TIME:
3197 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3198 "%s: %s", hfinfo->name,
3199 abs_time_to_str(fvalue_get(&fi->value)));
3200 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3201 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3204 case FT_RELATIVE_TIME:
3205 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3206 "%s: %s seconds", hfinfo->name,
3207 rel_time_to_secs_str(fvalue_get(&fi->value)));
3208 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3209 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3213 integer = fvalue_get_integer(&fi->value);
3214 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3215 "%s: %s (0x%08X)", hfinfo->name,
3216 get_ipxnet_name(integer), integer);
3217 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3218 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3222 bytes = fvalue_get(&fi->value);
3223 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3224 "%s: %s (%s)", hfinfo->name,
3225 get_ether_name(bytes),
3226 ether_to_str(bytes));
3227 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3228 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3232 ipv4 = fvalue_get(&fi->value);
3233 n_addr = ipv4_get_net_order_addr(ipv4);
3234 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3235 "%s: %s (%s)", hfinfo->name,
3236 get_hostname(n_addr),
3237 ip_to_str((guint8*)&n_addr));
3238 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3239 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3243 bytes = fvalue_get(&fi->value);
3244 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3245 "%s: %s (%s)", hfinfo->name,
3246 get_hostname6((struct e_in6_addr *)bytes),
3247 ip6_to_str((struct e_in6_addr*)bytes));
3248 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3249 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3253 bytes = fvalue_get(&fi->value);
3254 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3255 "%s: %s", hfinfo->name,
3256 guid_to_str(bytes));
3257 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3258 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3263 case FT_UINT_STRING:
3264 bytes = fvalue_get(&fi->value);
3265 if(strlen(bytes) > ITEM_LABEL_LENGTH) {
3266 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3267 "%s [truncated]: %s", hfinfo->name,
3268 format_text(bytes, strlen(bytes)));
3270 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3271 "%s: %s", hfinfo->name,
3272 format_text(bytes, strlen(bytes)));
3274 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3275 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3279 g_error("hfinfo->type %d (%s) not handled\n",
3281 ftype_name(hfinfo->type));
3282 DISSECTOR_ASSERT_NOT_REACHED();
3288 fill_label_boolean(field_info *fi, gchar *label_str)
3290 char *p = label_str;
3291 int bitfield_byte_length = 0, bitwidth;
3292 guint32 unshifted_value;
3294 int ret; /*tmp return value */
3296 header_field_info *hfinfo = fi->hfinfo;
3297 static const true_false_string default_tf = { "True", "False" };
3298 const true_false_string *tfstring = &default_tf;
3300 if (hfinfo->strings) {
3301 tfstring = (const struct true_false_string*) hfinfo->strings;
3304 value = fvalue_get_integer(&fi->value);
3305 if (hfinfo->bitmask) {
3306 /* Figure out the bit width */
3307 bitwidth = hfinfo_bitwidth(hfinfo);
3310 unshifted_value = value;
3311 if (hfinfo->bitshift > 0) {
3312 unshifted_value <<= hfinfo->bitshift;
3315 /* Create the bitfield first */
3316 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
3317 bitfield_byte_length = p - label_str;
3320 /* Fill in the textual info */
3321 ret = g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
3322 "%s: %s", hfinfo->name,
3323 value ? tfstring->true_string : tfstring->false_string);
3324 if ((ret == -1) || (ret >= (ITEM_LABEL_LENGTH - bitfield_byte_length)))
3325 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3329 /* Fills data for bitfield ints with val_strings */
3331 fill_label_enumerated_bitfield(field_info *fi, gchar *label_str)
3333 const char *format = NULL;
3335 int bitfield_byte_length, bitwidth;
3336 guint32 unshifted_value;
3338 int ret; /*tmp return value */
3340 header_field_info *hfinfo = fi->hfinfo;
3342 /* Figure out the bit width */
3343 bitwidth = hfinfo_bitwidth(hfinfo);
3345 /* Pick the proper format string */
3346 format = hfinfo_uint_vals_format(hfinfo);
3349 unshifted_value = fvalue_get_integer(&fi->value);
3350 value = unshifted_value;
3351 if (hfinfo->bitshift > 0) {
3352 unshifted_value <<= hfinfo->bitshift;
3355 /* Create the bitfield first */
3356 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
3357 bitfield_byte_length = p - label_str;
3359 /* Fill in the textual info using stored (shifted) value */
3360 ret = g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
3361 format, hfinfo->name,
3362 val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
3363 if ((ret == -1) || (ret >= (ITEM_LABEL_LENGTH - bitfield_byte_length)))
3364 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3368 fill_label_numeric_bitfield(field_info *fi, gchar *label_str)
3370 const char *format = NULL;
3372 int bitfield_byte_length, bitwidth;
3373 guint32 unshifted_value;
3375 int ret; /*tmp return value */
3377 header_field_info *hfinfo = fi->hfinfo;
3379 /* Figure out the bit width */
3380 bitwidth = hfinfo_bitwidth(hfinfo);
3382 /* Pick the proper format string */
3383 format = hfinfo_uint_format(hfinfo);
3386 unshifted_value = fvalue_get_integer(&fi->value);
3387 value = unshifted_value;
3388 if (hfinfo->bitshift > 0) {
3389 unshifted_value <<= hfinfo->bitshift;
3392 /* Create the bitfield using */
3393 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
3394 bitfield_byte_length = p - label_str;
3396 /* Fill in the textual info using stored (shifted) value */
3397 if (IS_BASE_DUAL(hfinfo->display)) {
3398 ret = g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
3399 format, hfinfo->name, value, value);
3401 ret = g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
3402 format, hfinfo->name, value);
3404 if ((ret == -1) || (ret >= (ITEM_LABEL_LENGTH - bitfield_byte_length)))
3405 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3410 fill_label_enumerated_uint(field_info *fi, gchar *label_str)
3412 const char *format = NULL;
3413 header_field_info *hfinfo = fi->hfinfo;
3415 int ret; /*tmp return value */
3417 /* Pick the proper format string */
3418 format = hfinfo_uint_vals_format(hfinfo);
3420 value = fvalue_get_integer(&fi->value);
3422 /* Fill in the textual info */
3423 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3424 format, hfinfo->name,
3425 val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
3426 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3427 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3431 fill_label_uint(field_info *fi, gchar *label_str)
3433 const char *format = NULL;
3434 header_field_info *hfinfo = fi->hfinfo;
3436 int ret; /*tmp return value */
3438 /* Pick the proper format string */
3439 format = hfinfo_uint_format(hfinfo);
3440 value = fvalue_get_integer(&fi->value);
3442 /* Fill in the textual info */
3443 if (IS_BASE_DUAL(hfinfo->display)) {
3444 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3445 format, hfinfo->name, value, value);
3447 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3448 format, hfinfo->name, value);
3450 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3451 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3455 fill_label_uint64(field_info *fi, gchar *label_str)
3457 const char *format = NULL;
3458 header_field_info *hfinfo = fi->hfinfo;
3460 int ret; /*tmp return value */
3462 /* Pick the proper format string */
3463 format = hfinfo_uint64_format(hfinfo);
3464 value = fvalue_get_integer64(&fi->value);
3466 /* Fill in the textual info */
3467 if (IS_BASE_DUAL(hfinfo->display)) {
3468 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3469 format, hfinfo->name, value, value);
3471 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3472 format, hfinfo->name, value);
3474 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3475 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3479 fill_label_enumerated_int(field_info *fi, gchar *label_str)
3481 const char *format = NULL;
3482 header_field_info *hfinfo = fi->hfinfo;
3484 int ret; /*tmp return value */
3486 /* Pick the proper format string */
3487 format = hfinfo_int_vals_format(hfinfo);
3488 value = fvalue_get_integer(&fi->value);
3490 /* Fill in the textual info */
3491 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3492 format, hfinfo->name,
3493 val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
3494 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3495 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3499 fill_label_int(field_info *fi, gchar *label_str)
3501 const char *format = NULL;
3502 header_field_info *hfinfo = fi->hfinfo;
3504 int ret; /*tmp return value */
3506 /* Pick the proper format string */
3507 format = hfinfo_int_format(hfinfo);
3508 value = fvalue_get_integer(&fi->value);
3510 /* Fill in the textual info */
3511 if (IS_BASE_DUAL(hfinfo->display)) {
3512 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3513 format, hfinfo->name, value, value);
3515 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3516 format, hfinfo->name, value);
3518 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3519 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3523 fill_label_int64(field_info *fi, gchar *label_str)
3525 const char *format = NULL;
3526 header_field_info *hfinfo = fi->hfinfo;
3528 int ret; /*tmp return value */
3530 /* Pick the proper format string */
3531 format = hfinfo_int64_format(hfinfo);
3532 value = fvalue_get_integer64(&fi->value);
3534 /* Fill in the textual info */
3535 if (IS_BASE_DUAL(hfinfo->display)) {
3536 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3537 format, hfinfo->name, value, value);
3539 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3540 format, hfinfo->name, value);
3542 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3543 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3547 hfinfo_bitwidth(header_field_info *hfinfo)
3551 if (!hfinfo->bitmask) {
3555 switch(hfinfo->type) {
3573 bitwidth = hfinfo->display; /* hacky? :) */
3576 DISSECTOR_ASSERT_NOT_REACHED();
3583 hfinfo_uint_vals_format(header_field_info *hfinfo)
3585 const char *format = NULL;
3587 switch(hfinfo->display) {
3590 format = "%s: %s (%u)";
3592 case BASE_OCT: /* I'm lazy */
3593 format = "%s: %s (%o)";
3597 switch(hfinfo->type) {
3599 format = "%s: %s (0x%02x)";
3602 format = "%s: %s (0x%04x)";
3605 format = "%s: %s (0x%06x)";
3608 format = "%s: %s (0x%08x)";
3611 DISSECTOR_ASSERT_NOT_REACHED();
3616 DISSECTOR_ASSERT_NOT_REACHED();
3623 hfinfo_uint_format(header_field_info *hfinfo)
3625 const char *format = NULL;
3627 /* Pick the proper format string */
3628 if (hfinfo->type == FT_FRAMENUM) {
3630 * Frame numbers are always displayed in decimal.
3634 switch(hfinfo->display) {
3639 switch(hfinfo->type) {
3641 format = "%s: %u (0x%02x)";
3644 format = "%s: %u (0x%04x)";
3647 format = "%s: %u (0x%06x)";
3650 format = "%s: %u (0x%08x)";
3653 DISSECTOR_ASSERT_NOT_REACHED();
3657 case BASE_OCT: /* I'm lazy */
3661 switch(hfinfo->type) {
3663 format = "%s: 0x%02x";
3666 format = "%s: 0x%04x";
3669 format = "%s: 0x%06x";
3672 format = "%s: 0x%08x";
3675 DISSECTOR_ASSERT_NOT_REACHED();
3680 switch(hfinfo->type) {
3682 format = "%s: 0x%02x (%u)";
3685 format = "%s: 0x%04x (%u)";
3688 format = "%s: 0x%06x (%u)";
3691 format = "%s: 0x%08x (%u)";
3694 DISSECTOR_ASSERT_NOT_REACHED();
3699 DISSECTOR_ASSERT_NOT_REACHED();
3707 hfinfo_int_vals_format(header_field_info *hfinfo)
3709 const char *format = NULL;
3711 switch(hfinfo->display) {
3714 format = "%s: %s (%d)";
3716 case BASE_OCT: /* I'm lazy */
3717 format = "%s: %s (%o)";
3721 switch(hfinfo->type) {
3723 format = "%s: %s (0x%02x)";
3726 format = "%s: %s (0x%04x)";
3729 format = "%s: %s (0x%06x)";
3732 format = "%s: %s (0x%08x)";
3735 DISSECTOR_ASSERT_NOT_REACHED();
3740 DISSECTOR_ASSERT_NOT_REACHED();
3747 hfinfo_uint64_format(header_field_info *hfinfo)
3749 const char *format = NULL;
3751 /* Pick the proper format string */
3752 switch(hfinfo->display) {
3754 format = "%s: %" PRIu64;
3757 format = "%s: %" PRIu64 " (%" PRIx64 ")";
3759 case BASE_OCT: /* I'm lazy */
3760 format = "%s: %" PRIo64;
3763 format = "%s: 0x%016" PRIx64;
3766 format = "%s: 0x%016" PRIx64 " (%" PRIu64 ")";
3769 DISSECTOR_ASSERT_NOT_REACHED();
3776 hfinfo_int_format(header_field_info *hfinfo)
3778 const char *format = NULL;
3780 /* Pick the proper format string */
3781 switch(hfinfo->display) {
3786 switch(hfinfo->type) {
3788 format = "%s: %d (0x%02x)";
3791 format = "%s: %d (0x%04x)";
3794 format = "%s: %d (0x%06x)";
3797 format = "%s: %d (0x%08x)";
3800 DISSECTOR_ASSERT_NOT_REACHED();
3803 case BASE_OCT: /* I'm lazy */
3807 switch(hfinfo->type) {
3809 format = "%s: 0x%02x";
3812 format = "%s: 0x%04x";
3815 format = "%s: 0x%06x";
3818 format = "%s: 0x%08x";
3821 DISSECTOR_ASSERT_NOT_REACHED();
3825 switch(hfinfo->type) {
3827 format = "%s: 0x%02x (%d)";
3830 format = "%s: 0x%04x (%d)";
3833 format = "%s: 0x%06x (%d)";
3836 format = "%s: 0x%08x (%d)";
3839 DISSECTOR_ASSERT_NOT_REACHED();
3844 DISSECTOR_ASSERT_NOT_REACHED();
3851 hfinfo_int64_format(header_field_info *hfinfo)
3853 const char *format = NULL;
3855 /* Pick the proper format string */
3856 switch(hfinfo->display) {
3858 format = "%s: %" PRId64;
3861 format = "%s: %" PRId64 " (%" PRIx64 ")";
3863 case BASE_OCT: /* I'm lazy */
3864 format = "%s: %" PRIo64;
3867 format = "%s: 0x%016" PRIx64;
3870 format = "%s: 0x%016" PRIx64 " (%" PRId64 ")";
3873 DISSECTOR_ASSERT_NOT_REACHED();
3882 proto_registrar_n(void)
3884 return gpa_hfinfo.len;
3888 proto_registrar_get_name(int n)
3890 header_field_info *hfinfo;
3892 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
3893 return hfinfo->name;
3897 proto_registrar_get_abbrev(int n)
3899 header_field_info *hfinfo;
3901 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
3902 return hfinfo->abbrev;
3906 proto_registrar_get_ftype(int n)
3908 header_field_info *hfinfo;
3910 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
3911 return hfinfo->type;
3915 proto_registrar_get_parent(int n)
3917 header_field_info *hfinfo;
3919 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
3920 return hfinfo->parent;
3924 proto_registrar_is_protocol(int n)
3926 header_field_info *hfinfo;
3928 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
3929 return (hfinfo->parent == -1 ? TRUE : FALSE);
3932 /* Returns length of field in packet (not necessarily the length
3933 * in our internal representation, as in the case of IPv4).
3934 * 0 means undeterminable at time of registration
3935 * -1 means the field is not registered. */
3937 proto_registrar_get_length(int n)
3939 header_field_info *hfinfo;
3941 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
3942 return ftype_length(hfinfo->type);
3947 /* Looks for a protocol or a field in a proto_tree. Returns TRUE if
3948 * it exists anywhere, or FALSE if it exists nowhere. */
3950 proto_check_for_protocol_or_field(proto_tree* tree, int id)
3952 GPtrArray *ptrs = proto_get_finfo_ptr_array(tree, id);
3957 else if (g_ptr_array_len(ptrs) > 0) {
3965 /* Return GPtrArray* of field_info pointers for all hfindex that appear in tree.
3966 * This only works if the hfindex was "primed" before the dissection
3967 * took place, as we just pass back the already-created GPtrArray*.
3968 * The caller should *not* free the GPtrArray*; proto_tree_free_node()
3971 proto_get_finfo_ptr_array(proto_tree *tree, int id)
3973 return g_hash_table_lookup(PTREE_DATA(tree)->interesting_hfids,
3974 GINT_TO_POINTER(id));
3978 /* Helper struct and function for proto_find_info() */
3985 find_finfo(proto_node *node, gpointer data)
3987 field_info *fi = PITEM_FINFO(node);
3988 if (fi && fi->hfinfo) {
3989 if (fi->hfinfo->id == ((ffdata_t*)data)->id) {
3990 g_ptr_array_add(((ffdata_t*)data)->array, fi);
3994 /* Don't stop traversing. */
3998 /* Return GPtrArray* of field_info pointers for all hfindex that appear in a tree.
3999 * This works on any proto_tree, primed or unprimed, but actually searches
4000 * the tree, so it is slower than using proto_get_finfo_ptr_array on a primed tree.
4001 * The caller does need to free the returned GPtrArray with
4002 * g_ptr_array_free(<array>, FALSE).
4005 proto_find_finfo(proto_tree *tree, int id)
4009 ffdata.array = g_ptr_array_new();
4012 proto_tree_traverse_pre_order(tree, find_finfo, &ffdata);
4014 return ffdata.array;
4025 check_for_offset(proto_node *node, gpointer data)
4027 field_info *fi = PITEM_FINFO(node);
4028 offset_search_t *offsearch = data;
4030 /* !fi == the top most container node which holds nothing */
4031 if (fi && !PROTO_ITEM_IS_HIDDEN(node) && fi->ds_tvb && offsearch->tvb == fi->ds_tvb) {
4032 if (offsearch->offset >= (guint) fi->start &&
4033 offsearch->offset < (guint) (fi->start + fi->length)) {
4035 offsearch->finfo = fi;
4036 return FALSE; /* keep traversing */
4039 return FALSE; /* keep traversing */
4042 /* Search a proto_tree backwards (from leaves to root) looking for the field
4043 * whose start/length occupies 'offset' */
4044 /* XXX - I couldn't find an easy way to search backwards, so I search
4045 * forwards, w/o stopping. Therefore, the last finfo I find will the be
4046 * the one I want to return to the user. This algorithm is inefficient
4047 * and could be re-done, but I'd have to handle all the children and
4048 * siblings of each node myself. When I have more time I'll do that.
4051 proto_find_field_from_offset(proto_tree *tree, guint offset, tvbuff_t *tvb)
4053 offset_search_t offsearch;
4055 offsearch.offset = offset;
4056 offsearch.finfo = NULL;
4057 offsearch.tvb = tvb;
4059 proto_tree_traverse_pre_order(tree, check_for_offset, &offsearch);
4061 return offsearch.finfo;
4064 /* Dumps the protocols in the registration database to stdout. An independent
4065 * program can take this output and format it into nice tables or HTML or
4068 * There is one record per line. The fields are tab-delimited.
4070 * Field 1 = protocol name
4071 * Field 2 = protocol short name
4072 * Field 3 = protocol filter name
4075 proto_registrar_dump_protocols(void)
4077 protocol_t *protocol;
4081 for (i = proto_get_first_protocol(&cookie); i != -1;
4082 i = proto_get_next_protocol(&cookie)) {
4083 protocol = find_protocol_by_id(i);
4084 printf("%s\t%s\t%s\n", protocol->name, protocol->short_name,
4085 protocol->filter_name);
4089 /* Dumps the value_string and true/false strings for fields that have
4090 * them. There is one record per line. Fields are tab-delimited.
4091 * There are two types of records, Value String records and True/False
4092 * String records. The first field, 'V' or 'T', indicates the type
4098 * Field 2 = field abbreviation to which this value string corresponds
4099 * Field 3 = Integer value
4102 * True/False Strings
4103 * ------------------
4105 * Field 2 = field abbreviation to which this true/false string corresponds
4106 * Field 3 = True String
4107 * Field 4 = False String
4110 proto_registrar_dump_values(void)
4112 header_field_info *hfinfo, *parent_hfinfo;
4114 const value_string *vals;
4115 const true_false_string *tfs;
4117 len = gpa_hfinfo.len;
4118 for (i = 0; i < len ; i++) {
4119 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
4121 if (hfinfo->id == hf_text_only) {
4125 /* ignore protocols */
4126 if (proto_registrar_is_protocol(i)) {
4129 /* process header fields */
4132 * If this field isn't at the head of the list of
4133 * fields with this name, skip this field - all
4134 * fields with the same name are really just versions
4135 * of the same field stored in different bits, and
4136 * should have the same type/radix/value list, and
4137 * just differ in their bit masks. (If a field isn't
4138 * a bitfield, but can be, say, 1 or 2 bytes long,
4139 * it can just be made FT_UINT16, meaning the
4140 * *maximum* length is 2 bytes, and be used
4143 if (hfinfo->same_name_prev != NULL)
4146 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
4151 if (hfinfo->type == FT_UINT8 ||
4152 hfinfo->type == FT_UINT16 ||
4153 hfinfo->type == FT_UINT24 ||
4154 hfinfo->type == FT_UINT32 ||
4155 hfinfo->type == FT_UINT64 ||
4156 hfinfo->type == FT_INT8 ||
4157 hfinfo->type == FT_INT16 ||
4158 hfinfo->type == FT_INT24 ||
4159 hfinfo->type == FT_INT32 ||
4160 hfinfo->type == FT_INT64) {
4162 vals = hfinfo->strings;
4164 else if (hfinfo->type == FT_BOOLEAN) {
4165 tfs = hfinfo->strings;
4168 /* Print value strings? */
4171 while (vals[vi].strptr) {
4172 /* Print in the proper base */
4173 if (hfinfo->display == BASE_HEX) {
4174 printf("V\t%s\t0x%x\t%s\n",
4180 printf("V\t%s\t%u\t%s\n",
4189 /* Print true/false strings? */
4191 printf("T\t%s\t%s\t%s\n", hfinfo->abbrev,
4192 tfs->true_string, tfs->false_string);
4198 /* Dumps the contents of the registration database to stdout. An indepedent
4199 * program can take this output and format it into nice tables or HTML or
4202 * There is one record per line. Each record is either a protocol or a header
4203 * field, differentiated by the first field. The fields are tab-delimited.
4208 * Field 2 = descriptive protocol name
4209 * Field 3 = protocol abbreviation
4215 * Field 2 = descriptive field name
4216 * Field 3 = field abbreviation
4217 * Field 4 = type ( textual representation of the the ftenum type )
4218 * Field 5 = parent protocol abbreviation
4219 * Field 6 = blurb describing field
4223 * Field 2 = descriptive field name
4224 * Field 3 = field abbreviation
4225 * Field 4 = type ( textual representation of the the ftenum type )
4226 * Field 5 = parent protocol abbreviation
4227 * Field 6 = blurb describing field
4228 * Field 7 = base for display (for integer types)
4229 * Field 8 = blurb describing field (yes, apparently we repeated this accidentally)
4233 * Field 2 = descriptive field name
4234 * Field 3 = field abbreviation
4235 * Field 4 = type ( textual representation of the the ftenum type )
4236 * Field 5 = parent protocol abbreviation
4237 * Field 6 = blurb describing field
4238 * Field 7 = base for display (for integer types)
4242 proto_registrar_dump_fields(int format)
4244 header_field_info *hfinfo, *parent_hfinfo;
4246 const char *enum_name;
4247 const char *base_name;
4249 len = gpa_hfinfo.len;
4250 for (i = 0; i < len ; i++) {
4251 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
4254 * Skip fields with zero-length names or abbreviations;
4255 * the pseudo-field for "proto_tree_add_text()" is such
4256 * a field, and we don't want it in the list of filterable
4260 * XXX - perhaps the name and abbrev field should be null
4261 * pointers rather than null strings for that pseudo-field,
4262 * but we'd have to add checks for null pointers in some
4263 * places if we did that.
4265 * Or perhaps protocol tree items added with
4266 * "proto_tree_add_text()" should have -1 as the field index,
4267 * with no pseudo-field being used, but that might also
4268 * require special checks for -1 to be added.
4270 /* XXX - we could just skip the special text
4271 * pseudo-field by testing: if (hfinfo->id == hf_text_only)
4273 if (hfinfo->name[0] == 0 || hfinfo->abbrev[0] == 0)
4276 /* format for protocols */
4277 if (proto_registrar_is_protocol(i)) {
4278 printf("P\t%s\t%s\n", hfinfo->name, hfinfo->abbrev);
4280 /* format for header fields */
4283 * If this field isn't at the head of the list of
4284 * fields with this name, skip this field - all
4285 * fields with the same name are really just versions
4286 * of the same field stored in different bits, and
4287 * should have the same type/radix/value list, and
4288 * just differ in their bit masks. (If a field isn't
4289 * a bitfield, but can be, say, 1 or 2 bytes long,
4290 * it can just be made FT_UINT16, meaning the
4291 * *maximum* length is 2 bytes, and be used
4294 if (hfinfo->same_name_prev != NULL)
4297 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
4299 enum_name = ftype_name(hfinfo->type);
4303 if (hfinfo->type == FT_UINT8 ||
4304 hfinfo->type == FT_UINT16 ||
4305 hfinfo->type == FT_UINT24 ||
4306 hfinfo->type == FT_UINT32 ||
4307 hfinfo->type == FT_UINT64 ||
4308 hfinfo->type == FT_INT8 ||
4309 hfinfo->type == FT_INT16 ||
4310 hfinfo->type == FT_INT24 ||
4311 hfinfo->type == FT_INT32 ||
4312 hfinfo->type == FT_INT64) {
4315 switch(hfinfo->display) {
4317 base_name = "BASE_NONE";
4320 base_name = "BASE_DEC";
4323 base_name = "BASE_HEX";
4326 base_name = "BASE_OCT";
4329 base_name = "BASE_DEC_HEX";
4332 base_name = "BASE_HEX_DEC";
4339 printf("F\t%s\t%s\t%s\t%s\t%s\n", hfinfo->name, hfinfo->abbrev,
4340 enum_name,parent_hfinfo->abbrev, hfinfo->blurb);
4342 else if (format == 2) {
4343 printf("F\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n",
4344 hfinfo->name, hfinfo->abbrev,
4345 enum_name,parent_hfinfo->abbrev, hfinfo->blurb,
4346 base_name, hfinfo->blurb);
4348 else if (format == 3) {
4349 printf("F\t%s\t%s\t%s\t%s\t%s\t%s\t%u\n",
4350 hfinfo->name, hfinfo->abbrev,
4351 enum_name,parent_hfinfo->abbrev, hfinfo->blurb,
4352 base_name, hfinfo->bitmask);
4355 g_assert_not_reached();
4362 hfinfo_numeric_format(header_field_info *hfinfo)
4364 const char *format = NULL;
4366 /* Pick the proper format string */
4367 if (hfinfo->type == FT_FRAMENUM) {
4369 * Frame numbers are always displayed in decimal.
4371 format = "%s == %u";
4373 /* Pick the proper format string */
4374 switch(hfinfo->display) {
4377 case BASE_OCT: /* I'm lazy */
4378 switch(hfinfo->type) {
4383 format = "%s == %u";
4386 format = "%s == %" PRIu64;
4392 format = "%s == %d";
4395 format = "%s == %" PRId64;
4398 DISSECTOR_ASSERT_NOT_REACHED();
4404 switch(hfinfo->type) {
4406 format = "%s == 0x%02x";
4409 format = "%s == 0x%04x";
4412 format = "%s == 0x%06x";
4415 format = "%s == 0x%08x";
4418 format = "%s == 0x%016" PRIx64;
4421 DISSECTOR_ASSERT_NOT_REACHED();
4426 DISSECTOR_ASSERT_NOT_REACHED();
4434 * Returns TRUE if we can do a "match selected" on the field, FALSE
4438 proto_can_match_selected(field_info *finfo, epan_dissect_t *edt)
4440 header_field_info *hfinfo;
4443 hfinfo = finfo->hfinfo;
4444 DISSECTOR_ASSERT(hfinfo);
4446 switch(hfinfo->type) {
4465 case FT_ABSOLUTE_TIME:
4466 case FT_RELATIVE_TIME:
4469 case FT_UINT_STRING:
4476 * These all have values, so we can match.
4482 * This doesn't have a value, so we'd match
4483 * on the raw bytes at this address.
4485 * Should we be allowed to access to the raw bytes?
4486 * If "edt" is NULL, the answer is "no".
4492 * Is this field part of the raw frame tvbuff?
4493 * If not, we can't use "frame[N:M]" to match
4496 * XXX - should this be frame-relative, or
4497 * protocol-relative?
4499 * XXX - does this fallback for non-registered
4500 * fields even make sense?
4502 if (finfo->ds_tvb != edt->tvb)
4506 * If the length is 0, there's nothing to match, so
4507 * we can't match. (Also check for negative values,
4508 * just in case, as we'll cast it to an unsigned
4511 length = finfo->length;
4516 * Don't go past the end of that tvbuff.
4518 if ((guint)length > tvb_length(finfo->ds_tvb))
4519 length = tvb_length(finfo->ds_tvb);
4526 /* This function returns a string allocated with packet lifetime scope.
4527 * You do not need to [g_]free() this string since it willb e automatically
4528 * freed once the next packet is dissected.
4531 proto_construct_dfilter_string(field_info *finfo, epan_dissect_t *edt)
4533 header_field_info *hfinfo;
4535 char *buf, *stringified, *ptr;
4539 gint start, length, length_remaining;
4542 hfinfo = finfo->hfinfo;
4543 DISSECTOR_ASSERT(hfinfo);
4544 abbrev_len = strlen(hfinfo->abbrev);
4547 * XXX - we should add "val_to_string_repr" and "string_repr_len"
4548 * functions for more types, and use them whenever possible.
4550 * The FT_UINT and FT_INT types are the only tricky ones, as
4551 * we choose the base in the string expression based on the
4552 * display base of the field.
4554 * Note that the base does matter, as this is also used for
4555 * the protocolinfo tap.
4557 * It might be nice to use that in "proto_item_fill_label()"
4558 * as well, although, there, you'd have to deal with the base
4559 * *and* with resolved values for addresses.
4561 * Perhaps we need two different val_to_string routines, one
4562 * to generate items for display filters and one to generate
4563 * strings for display, and pass to both of them the
4564 * "display" and "strings" values in the header_field_info
4565 * structure for the field, so they can get the base and,
4566 * if the field is Boolean or an enumerated integer type,
4567 * the tables used to generate human-readable values.
4569 switch(hfinfo->type) {
4581 * 4 bytes for " == ".
4584 * a sign + up to 10 digits of 32-bit integer,
4587 * "0x" + 8 digits of 32-bit integer, in hex;
4589 * 11 digits of 32-bit integer, in octal.
4590 * (No, we don't do octal, but this way,
4591 * we know that if we do, this will still
4594 * 1 byte for the trailing '\0'.
4596 dfilter_len = abbrev_len + 4 + 11 + 1;
4597 buf = ep_alloc0(dfilter_len);
4598 format = hfinfo_numeric_format(hfinfo);
4599 g_snprintf(buf, dfilter_len, format, hfinfo->abbrev, fvalue_get_integer(&finfo->value));
4605 * 4 bytes for " == ".
4608 * a sign + up to 20 digits of 32-bit integer,
4611 * "0x" + 16 digits of 32-bit integer, in hex;
4613 * 22 digits of 32-bit integer, in octal.
4614 * (No, we don't do octal, but this way,
4615 * we know that if we do, this will still
4618 * 1 byte for the trailing '\0'.
4620 dfilter_len = abbrev_len + 4 + 22 + 1;
4621 buf = ep_alloc0(dfilter_len);
4622 format = hfinfo_numeric_format(hfinfo);
4623 g_snprintf(buf, dfilter_len, format, hfinfo->abbrev, fvalue_get_integer64(&finfo->value));
4628 * 4 bytes for " == ".
4630 * 8 bytes for 8 digits of 32-bit hex number.
4631 * 1 byte for the trailing '\0'.
4633 dfilter_len = abbrev_len + 4 + 2 + 8 + 1;
4634 buf = ep_alloc0(dfilter_len);
4635 g_snprintf(buf, dfilter_len, "%s == 0x%08x", hfinfo->abbrev,
4636 fvalue_get_integer(&finfo->value));
4641 * 4 bytes for " == ".
4642 * N bytes for the string for the address.
4643 * 1 byte for the trailing '\0'.
4645 stringified = ip6_to_str((struct e_in6_addr*) fvalue_get(&finfo->value));
4646 dfilter_len = abbrev_len + 4 + strlen(stringified) + 1;
4647 buf = ep_alloc0(dfilter_len);
4648 g_snprintf(buf, dfilter_len, "%s == %s", hfinfo->abbrev,
4652 /* These use the fvalue's "to_string_repr" method. */
4660 case FT_ABSOLUTE_TIME:
4661 case FT_RELATIVE_TIME:
4664 /* Figure out the string length needed.
4665 * The ft_repr length.
4666 * 4 bytes for " == ".
4667 * 1 byte for trailing NUL.
4669 dfilter_len = fvalue_string_repr_len(&finfo->value,
4671 dfilter_len += abbrev_len + 4 + 1;
4672 buf = ep_alloc0(dfilter_len);
4674 /* Create the string */
4675 g_snprintf(buf, dfilter_len, "%s == ", hfinfo->abbrev);
4676 fvalue_to_string_repr(&finfo->value,
4678 &buf[abbrev_len + 4]);
4682 buf = ep_strdup(finfo->hfinfo->abbrev);
4687 * This doesn't have a value, so we'd match
4688 * on the raw bytes at this address.
4690 * Should we be allowed to access to the raw bytes?
4691 * If "edt" is NULL, the answer is "no".
4697 * Is this field part of the raw frame tvbuff?
4698 * If not, we can't use "frame[N:M]" to match
4701 * XXX - should this be frame-relative, or
4702 * protocol-relative?
4704 * XXX - does this fallback for non-registered
4705 * fields even make sense?
4707 if (finfo->ds_tvb != edt->tvb)
4708 return NULL; /* you lose */
4711 * If the length is 0, there's nothing to match, so
4712 * we can't match. (Also check for negative values,
4713 * just in case, as we'll cast it to an unsigned
4716 length = finfo->length;
4721 * Don't go past the end of that tvbuff.
4723 length_remaining = tvb_length_remaining(finfo->ds_tvb, finfo->start);
4724 if (length > length_remaining)
4725 length = length_remaining;
4729 start = finfo->start;
4730 buf_len = 32 + length * 3;
4731 buf = ep_alloc0(buf_len);
4734 ptr += g_snprintf(ptr, buf_len-(ptr-buf), "frame[%d:%d] == ", finfo->start, length);
4735 for (i=0;i<length; i++) {
4736 c = tvb_get_guint8(finfo->ds_tvb, start);
4739 ptr += g_snprintf(ptr, buf_len-(ptr-buf), "%02x", c);
4742 ptr += snprintf(ptr, buf_len-(ptr-buf), ":%02x", c);