2 * Routines for protocol tree
4 * $Id: proto.c,v 1.47 2001/12/07 03:39:26 gram Exp $
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.
29 #ifdef HAVE_SYS_TYPES_H
30 # include <sys/types.h>
37 #ifdef NEED_SNPRINTF_H
38 # include "snprintf.h"
45 #include "ipv6-utils.h"
47 #include "int-64bit.h"
49 #define cVALS(x) (const value_string*)(x)
52 proto_tree_free_node(GNode *node, gpointer data);
54 static void fill_label_boolean(field_info *fi, gchar *label_str);
55 static void fill_label_uint(field_info *fi, gchar *label_str);
56 static void fill_label_uint64(field_info *fi, gchar *label_str);
57 static void fill_label_int64(field_info *fi, gchar *label_str);
58 static void fill_label_enumerated_uint(field_info *fi, gchar *label_str);
59 static void fill_label_enumerated_bitfield(field_info *fi, gchar *label_str);
60 static void fill_label_numeric_bitfield(field_info *fi, gchar *label_str);
61 static void fill_label_int(field_info *fi, gchar *label_str);
62 static void fill_label_enumerated_int(field_info *fi, gchar *label_str);
64 int hfinfo_bitwidth(header_field_info *hfinfo);
65 static char* hfinfo_uint_vals_format(header_field_info *hfinfo);
66 static char* hfinfo_uint_format(header_field_info *hfinfo);
67 static char* hfinfo_int_vals_format(header_field_info *hfinfo);
68 static char* hfinfo_int_format(header_field_info *hfinfo);
70 static gboolean check_for_protocol_or_field_id(GNode *node, gpointer data);
73 proto_tree_add_node(proto_tree *tree, field_info *fi);
76 alloc_field_info(int hfindex, tvbuff_t *tvb, gint start, gint length);
79 proto_tree_add_pi(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
82 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap);
85 proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb);
87 proto_tree_set_uint64(field_info *fi, const guint8 *value_ptr, gboolean little_endian);
89 proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start, gboolean little_endian);
91 proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length);
93 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length);
95 proto_tree_set_time(field_info *fi, nstime_t *value_ptr);
97 proto_tree_set_string(field_info *fi, const char* value);
99 proto_tree_set_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
101 proto_tree_set_ether(field_info *fi, const guint8* value);
103 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start);
105 proto_tree_set_ipxnet(field_info *fi, guint32 value);
107 proto_tree_set_ipv4(field_info *fi, guint32 value);
109 proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr);
111 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start);
113 proto_tree_set_boolean(field_info *fi, guint32 value);
115 proto_tree_set_double(field_info *fi, double value);
117 proto_tree_set_uint(field_info *fi, guint32 value);
119 proto_tree_set_int(field_info *fi, gint32 value);
121 static int proto_register_field_init(header_field_info *hfinfo, int parent);
123 /* special-case header field used within proto.c */
124 int hf_text_only = 1;
126 /* Structure for information about a protocol */
128 char *name; /* long description */
129 char *short_name; /* short description */
130 char *filter_name; /* name of this protocol in filters */
131 int proto_id; /* field ID for this protocol */
132 GList *fields; /* fields for this protocol */
133 GList *last_field; /* pointer to end of list of fields */
134 gboolean is_enabled; /* TRUE if protocol is enabled */
135 gboolean can_disable; /* TRUE if protocol can be disabled */
138 /* List of all protocols */
139 static GList *protocols;
141 /* Contains information about protocols and header fields. Used when
142 * dissectors register their data */
143 static GMemChunk *gmc_hfinfo = NULL;
145 /* Contains information about a field when a dissector calls
146 * proto_tree_add_item. */
147 static GMemChunk *gmc_field_info = NULL;
149 /* String space for protocol and field items for the GUI */
150 static GMemChunk *gmc_item_labels = NULL;
152 /* List which stores protocols and fields that have been registered */
153 static GPtrArray *gpa_hfinfo = NULL;
155 /* Points to the first element of an array of Booleans, indexed by
156 a subtree item type; that array element is TRUE if subtrees of
157 an item of that type are to be expanded. */
158 gboolean *tree_is_expanded;
160 /* Number of elements in that array. */
163 /* Is the parsing being done for a visible proto_tree or an invisible one?
164 * By setting this correctly, the proto_tree creation is sped up by not
165 * having to call vsnprintf and copy strings around.
167 gboolean proto_tree_is_visible = FALSE;
169 /* initialize data structures and register protocols and fields */
171 proto_init(const char *plugin_dir,void (register_all_protocols)(void),
172 void (register_all_protocol_handoffs)(void))
174 static hf_register_info hf[] = {
176 { "", "", FT_NONE, BASE_NONE, NULL, 0x0,
181 g_mem_chunk_destroy(gmc_hfinfo);
183 g_mem_chunk_destroy(gmc_field_info);
185 g_mem_chunk_destroy(gmc_item_labels);
187 g_ptr_array_free(gpa_hfinfo, TRUE);
188 if (tree_is_expanded != NULL)
189 g_free(tree_is_expanded);
191 gmc_hfinfo = g_mem_chunk_new("gmc_hfinfo",
192 sizeof(header_field_info), 50 * sizeof(header_field_info), G_ALLOC_ONLY);
193 gmc_field_info = g_mem_chunk_new("gmc_field_info",
194 sizeof(struct field_info), 200 * sizeof(struct field_info),
196 gmc_item_labels = g_mem_chunk_new("gmc_item_labels",
197 ITEM_LABEL_LENGTH, 20 * ITEM_LABEL_LENGTH,
199 gpa_hfinfo = g_ptr_array_new();
201 /* Allocate "tree_is_expanded", with one element for ETT_NONE,
202 and initialize that element to FALSE. */
203 tree_is_expanded = g_malloc(sizeof (gint));
204 tree_is_expanded[0] = FALSE;
207 /* Initialize the ftype subsystem */
210 /* Have each built-in dissector register its protocols, fields,
211 dissector tables, and dissectors to be called through a
212 handle, and do whatever one-time initialization it needs to
214 register_all_protocols();
217 /* Now scan for plugins and load all the ones we find, calling
218 their register routines to do the stuff described above. */
219 init_plugins(plugin_dir);
222 /* Now call the "handoff registration" routines of all built-in
223 dissectors; those routines register the dissector in other
224 dissectors' handoff tables, and fetch any dissector handles
226 register_all_protocol_handoffs();
229 /* Now do the same with plugins. */
230 register_all_plugin_handoffs();
233 /* Register one special-case FT_TEXT_ONLY field for use when
234 converting ethereal to new-style proto_tree. These fields
235 are merely strings on the GUI tree; they are not filterable */
236 proto_register_field_array(-1, hf, array_length(hf));
238 /* We've assigned all the subtree type values; allocate the array
239 for them, and zero it out. */
240 tree_is_expanded = g_malloc(num_tree_types*sizeof (gint *));
241 memset(tree_is_expanded, '\0', num_tree_types*sizeof (gint *));
248 g_mem_chunk_destroy(gmc_hfinfo);
250 g_mem_chunk_destroy(gmc_field_info);
252 g_mem_chunk_destroy(gmc_item_labels);
254 g_ptr_array_free(gpa_hfinfo, TRUE);
256 /* Cleanup the ftype subsystem */
260 /* frees the resources that the dissection a proto_tree uses */
262 proto_tree_free(proto_tree *tree)
264 g_node_traverse((GNode*)tree, G_IN_ORDER, G_TRAVERSE_ALL, -1,
265 proto_tree_free_node, NULL);
266 g_node_destroy((GNode*)tree);
269 /* We accept a void* instead of a field_info* to satisfy CLEANUP_POP */
271 free_field_info(void *fi)
273 g_mem_chunk_free(gmc_field_info, (field_info*)fi);
277 proto_tree_free_node(GNode *node, gpointer data)
279 field_info *fi = (field_info*) (node->data);
282 if (fi->representation) {
283 g_mem_chunk_free(gmc_item_labels, fi->representation);
285 fvalue_free(fi->value);
288 return FALSE; /* FALSE = do not end traversal of GNode tree */
291 /* Finds a record in the hf_info_records array by id. */
293 proto_registrar_get_nth(int hfindex)
295 g_assert(hfindex >= 0 && (guint) hfindex < gpa_hfinfo->len);
296 return g_ptr_array_index(gpa_hfinfo, hfindex);
300 /* Add a text-only node, leaving it to our caller to fill the text in */
302 proto_tree_add_text_node(proto_tree *tree, tvbuff_t *tvb, gint start, gint length)
306 pi = proto_tree_add_pi(tree, hf_text_only, tvb, start, length, NULL);
313 /* Add a text-only node to the proto_tree */
315 proto_tree_add_text(proto_tree *tree, tvbuff_t *tvb, gint start, gint length,
316 const char *format, ...)
321 pi = proto_tree_add_text_node(tree, tvb, start, length);
325 va_start(ap, format);
326 proto_tree_set_representation(pi, format, ap);
332 /* Add a text-only node to the proto_tree (va_list version) */
334 proto_tree_add_text_valist(proto_tree *tree, tvbuff_t *tvb, gint start,
335 gint length, const char *format, va_list ap)
339 pi = proto_tree_add_text_node(tree, tvb, start, length);
343 proto_tree_set_representation(pi, format, ap);
348 /* Add a text-only node for debugging purposes. The caller doesn't need
349 * to worry about tvbuff, start, or length. Debug message gets sent to
352 proto_tree_add_debug_text(proto_tree *tree, const char *format, ...)
357 pi = proto_tree_add_text_node(tree, NULL, 0, 0);
361 va_start(ap, format);
362 proto_tree_set_representation(pi, format, ap);
372 get_uint_value(tvbuff_t *tvb, gint offset, gint length, gboolean little_endian)
379 value = tvb_get_guint8(tvb, offset);
383 value = little_endian ? tvb_get_letohs(tvb, offset)
384 : tvb_get_ntohs(tvb, offset);
388 value = little_endian ? tvb_get_letoh24(tvb, offset)
389 : tvb_get_ntoh24(tvb, offset);
393 value = little_endian ? tvb_get_letohl(tvb, offset)
394 : tvb_get_ntohl(tvb, offset);
398 g_assert_not_reached();
406 get_int_value(tvbuff_t *tvb, gint offset, gint length, gboolean little_endian)
413 value = (gint8)tvb_get_guint8(tvb, offset);
417 value = (gint16) (little_endian ? tvb_get_letohs(tvb, offset)
418 : tvb_get_ntohs(tvb, offset));
422 value = little_endian ? tvb_get_letoh24(tvb, offset)
423 : tvb_get_ntoh24(tvb, offset);
424 if (value & 0x00800000) {
425 /* Sign bit is set; sign-extend it. */
431 value = little_endian ? tvb_get_letohl(tvb, offset)
432 : tvb_get_ntohl(tvb, offset);
436 g_assert_not_reached();
443 /* Add an item to a proto_tree, using the text label registered to that item;
444 the item is extracted from the tvbuff handed to it. */
446 proto_tree_add_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
447 gint start, gint length, gboolean little_endian)
458 new_fi = alloc_field_info(hfindex, tvb, start, length);
463 /* Register a cleanup function in case on of our tvbuff accesses
464 * throws an exception. We need to clean up new_fi. */
465 CLEANUP_PUSH(free_field_info, new_fi);
467 switch(new_fi->hfinfo->type) {
469 /* no value to set for FT_NONE */
473 proto_tree_set_protocol_tvb(new_fi, tvb);
477 proto_tree_set_bytes_tvb(new_fi, tvb, start, length);
481 proto_tree_set_boolean(new_fi,
482 get_uint_value(tvb, start, length, little_endian));
485 /* XXX - make these just FT_UINT? */
490 proto_tree_set_uint(new_fi,
491 get_uint_value(tvb, start, length, little_endian));
496 g_assert(length == 8);
497 proto_tree_set_uint64_tvb(new_fi, tvb, start, little_endian);
500 /* XXX - make these just FT_INT? */
505 proto_tree_set_int(new_fi,
506 get_int_value(tvb, start, length, little_endian));
510 g_assert(length == 4);
511 tvb_memcpy(tvb, (guint8 *)&value, start, 4);
512 proto_tree_set_ipv4(new_fi, value);
516 g_assert(length == 4);
517 proto_tree_set_ipxnet(new_fi,
518 get_uint_value(tvb, start, 4, FALSE));
522 g_assert(length == 16);
523 proto_tree_set_ipv6_tvb(new_fi, tvb, start);
527 g_assert(length == 6);
528 proto_tree_set_ether_tvb(new_fi, tvb, start);
532 /* This g_strdup'ed memory is freed in proto_tree_free_node() */
533 proto_tree_set_string_tvb(new_fi, tvb, start, length);
537 /* This g_strdup'ed memory is freed in proto_tree_free_node() */
538 string = g_malloc(length);
540 CLEANUP_PUSH(g_free, string);
542 found_length = tvb_get_nstringz(tvb, start, length, string);
543 if (found_length < 1) {
544 found_length = tvb_get_nstringz0(tvb, start, length, string);
549 proto_tree_set_string(new_fi, string);
550 new_fi->length = found_length + 1;
555 /* This g_strdup'ed memory is freed in proto_tree_free_node() */
556 n = get_uint_value(tvb, start, length, little_endian);
557 proto_tree_set_string_tvb(new_fi, tvb, start + length, n);
559 /* Instead of calling proto_item_set_len(), since we don't yet
560 * have a proto_item, we set the field_info's length ourselves. */
561 new_fi->length = n + length;
564 g_error("new_fi->hfinfo->type %d (%s) not handled\n",
565 new_fi->hfinfo->type,
566 ftype_name(new_fi->hfinfo->type));
567 g_assert_not_reached();
573 /* Don't add to proto_item to proto_tree until now so that any exceptions
574 * raised by a tvbuff access method doesn't leave junk in the proto_tree. */
575 pi = proto_tree_add_node(tree, new_fi);
581 proto_tree_add_item_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb,
582 gint start, gint length, gboolean little_endian)
587 pi = proto_tree_add_item(tree, hfindex, tvb, start, length, little_endian);
591 fi = (field_info*) (((GNode*)pi)->data);
598 /* Add a FT_NONE to a proto_tree */
600 proto_tree_add_none_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
601 gint length, const char *format, ...)
605 header_field_info *hfinfo;
610 hfinfo = proto_registrar_get_nth(hfindex);
611 g_assert(hfinfo->type == FT_NONE);
613 pi = proto_tree_add_pi(tree, hfindex, tvb, start, length, NULL);
615 va_start(ap, format);
616 proto_tree_set_representation(pi, format, ap);
619 /* no value to set for FT_NONE */
625 proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb)
627 fvalue_set(fi->value, tvb, TRUE);
630 /* Add a FT_PROTOCOL to a proto_tree */
632 proto_tree_add_protocol_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
633 gint length, const char *format, ...)
637 header_field_info *hfinfo;
643 hfinfo = proto_registrar_get_nth(hfindex);
644 g_assert(hfinfo->type == FT_PROTOCOL);
646 pi = proto_tree_add_pi(tree, hfindex, tvb, start, length, &new_fi);
648 va_start(ap, format);
649 proto_tree_set_representation(pi, format, ap);
653 proto_tree_set_protocol_tvb(new_fi, tvb);
656 proto_tree_set_protocol_tvb(new_fi, NULL);
662 /* Add a FT_BYTES to a proto_tree */
664 proto_tree_add_bytes(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
665 gint length, const guint8 *start_ptr)
669 header_field_info *hfinfo;
674 hfinfo = proto_registrar_get_nth(hfindex);
675 g_assert(hfinfo->type == FT_BYTES);
677 pi = proto_tree_add_pi(tree, hfindex, tvb, start, length, &new_fi);
678 proto_tree_set_bytes(new_fi, start_ptr, length);
684 proto_tree_add_bytes_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
685 gint length, const guint8 *start_ptr)
690 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length, start_ptr);
694 fi = (field_info*) (((GNode*)pi)->data);
701 proto_tree_add_bytes_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
702 gint length, const guint8 *start_ptr, const char *format, ...)
707 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length, start_ptr);
711 va_start(ap, format);
712 proto_tree_set_representation(pi, format, ap);
719 proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length)
723 bytes = g_byte_array_new();
725 g_byte_array_append(bytes, start_ptr, length);
727 fvalue_set(fi->value, bytes, TRUE);
732 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length)
734 proto_tree_set_bytes(fi, tvb_get_ptr(tvb, offset, length), length);
737 /* Add a FT_*TIME to a proto_tree */
739 proto_tree_add_time(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
744 header_field_info *hfinfo;
749 hfinfo = proto_registrar_get_nth(hfindex);
750 g_assert(hfinfo->type == FT_ABSOLUTE_TIME ||
751 hfinfo->type == FT_RELATIVE_TIME);
753 pi = proto_tree_add_pi(tree, hfindex, tvb, start, length, &new_fi);
754 proto_tree_set_time(new_fi, value_ptr);
760 proto_tree_add_time_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
766 pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
770 fi = (field_info*) (((GNode*)pi)->data);
777 proto_tree_add_time_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
778 nstime_t *value_ptr, const char *format, ...)
783 pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
787 va_start(ap, format);
788 proto_tree_set_representation(pi, format, ap);
794 /* Set the FT_*TIME value */
796 proto_tree_set_time(field_info *fi, nstime_t *value_ptr)
798 fvalue_set(fi->value, value_ptr, FALSE);
801 /* Add a FT_IPXNET to a proto_tree */
803 proto_tree_add_ipxnet(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
808 header_field_info *hfinfo;
813 hfinfo = proto_registrar_get_nth(hfindex);
814 g_assert(hfinfo->type == FT_IPXNET);
816 pi = proto_tree_add_pi(tree, hfindex, tvb, start, length, &new_fi);
817 proto_tree_set_ipxnet(new_fi, value);
823 proto_tree_add_ipxnet_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
829 pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
833 fi = (field_info*) (((GNode*)pi)->data);
840 proto_tree_add_ipxnet_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
841 guint32 value, const char *format, ...)
846 pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
850 va_start(ap, format);
851 proto_tree_set_representation(pi, format, ap);
857 /* Set the FT_IPXNET value */
859 proto_tree_set_ipxnet(field_info *fi, guint32 value)
861 fvalue_set_integer(fi->value, value);
864 /* Add a FT_IPv4 to a proto_tree */
866 proto_tree_add_ipv4(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
871 header_field_info *hfinfo;
876 hfinfo = proto_registrar_get_nth(hfindex);
877 g_assert(hfinfo->type == FT_IPv4);
879 pi = proto_tree_add_pi(tree, hfindex, tvb, start, length, &new_fi);
880 proto_tree_set_ipv4(new_fi, value);
886 proto_tree_add_ipv4_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
892 pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
896 fi = (field_info*) (((GNode*)pi)->data);
903 proto_tree_add_ipv4_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
904 guint32 value, const char *format, ...)
909 pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
913 va_start(ap, format);
914 proto_tree_set_representation(pi, format, ap);
920 /* Set the FT_IPv4 value */
922 proto_tree_set_ipv4(field_info *fi, guint32 value)
924 fvalue_set_integer(fi->value, value);
927 /* Add a FT_IPv6 to a proto_tree */
929 proto_tree_add_ipv6(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
930 const guint8* value_ptr)
934 header_field_info *hfinfo;
939 hfinfo = proto_registrar_get_nth(hfindex);
940 g_assert(hfinfo->type == FT_IPv6);
942 pi = proto_tree_add_pi(tree, hfindex, tvb, start, length, &new_fi);
943 proto_tree_set_ipv6(new_fi, value_ptr);
949 proto_tree_add_ipv6_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
950 const guint8* value_ptr)
955 pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
959 fi = (field_info*) (((GNode*)pi)->data);
966 proto_tree_add_ipv6_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
967 const guint8* value_ptr, const char *format, ...)
972 pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
976 va_start(ap, format);
977 proto_tree_set_representation(pi, format, ap);
983 /* Set the FT_IPv6 value */
985 proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr)
987 fvalue_set(fi->value, (gpointer) value_ptr, FALSE);
991 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start)
993 proto_tree_set_ipv6(fi, tvb_get_ptr(tvb, start, 16));
997 proto_tree_set_uint64(field_info *fi, const guint8 *value_ptr, gboolean little_endian)
1000 unsigned char buffer[8];
1004 buffer[i]=value_ptr[7-i];
1006 fvalue_set(fi->value, (gpointer)buffer, FALSE);
1008 fvalue_set(fi->value, (gpointer)value_ptr, FALSE);
1013 proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start, gboolean little_endian)
1015 proto_tree_set_uint64(fi, tvb_get_ptr(tvb, start, 8), little_endian);
1018 /* Add a FT_STRING to a proto_tree */
1020 proto_tree_add_string(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1021 gint length, const char* value)
1025 header_field_info *hfinfo;
1030 hfinfo = proto_registrar_get_nth(hfindex);
1031 g_assert(hfinfo->type == FT_STRING);
1033 pi = proto_tree_add_pi(tree, hfindex, tvb, start, length, &new_fi);
1034 proto_tree_set_string(new_fi, value);
1040 proto_tree_add_string_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1041 gint length, const char* value)
1046 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
1050 fi = (field_info*) (((GNode*)pi)->data);
1051 fi->visible = FALSE;
1057 proto_tree_add_string_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1058 gint length, const char* value, const char *format, ...)
1063 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
1067 va_start(ap, format);
1068 proto_tree_set_representation(pi, format, ap);
1074 /* Set the FT_STRING value */
1076 proto_tree_set_string(field_info *fi, const char* value)
1078 fvalue_set(fi->value, (gpointer) value, FALSE);
1082 proto_tree_set_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
1086 /* This memory is freed in proto_tree_free_node() */
1087 string = g_malloc(length + 1);
1088 tvb_memcpy(tvb, string, start, length);
1089 string[length] = '\0';
1090 fvalue_set(fi->value, string, TRUE);
1093 /* Add a FT_ETHER to a proto_tree */
1095 proto_tree_add_ether(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1096 const guint8* value)
1100 header_field_info *hfinfo;
1105 hfinfo = proto_registrar_get_nth(hfindex);
1106 g_assert(hfinfo->type == FT_ETHER);
1108 pi = proto_tree_add_pi(tree, hfindex, tvb, start, length, &new_fi);
1109 proto_tree_set_ether(new_fi, value);
1115 proto_tree_add_ether_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1116 const guint8* value)
1121 pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
1125 fi = (field_info*) (((GNode*)pi)->data);
1126 fi->visible = FALSE;
1132 proto_tree_add_ether_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1133 const guint8* value, const char *format, ...)
1138 pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
1142 va_start(ap, format);
1143 proto_tree_set_representation(pi, format, ap);
1149 /* Set the FT_ETHER value */
1151 proto_tree_set_ether(field_info *fi, const guint8* value)
1153 fvalue_set(fi->value, (gpointer) value, FALSE);
1157 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start)
1159 proto_tree_set_ether(fi, tvb_get_ptr(tvb, start, 6));
1162 /* Add a FT_BOOLEAN to a proto_tree */
1164 proto_tree_add_boolean(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1169 header_field_info *hfinfo;
1174 hfinfo = proto_registrar_get_nth(hfindex);
1175 g_assert(hfinfo->type == FT_BOOLEAN);
1177 pi = proto_tree_add_pi(tree, hfindex, tvb, start, length, &new_fi);
1178 proto_tree_set_boolean(new_fi, value);
1184 proto_tree_add_boolean_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1190 pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
1194 fi = (field_info*) (((GNode*)pi)->data);
1195 fi->visible = FALSE;
1201 proto_tree_add_boolean_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1202 guint32 value, const char *format, ...)
1207 pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
1211 va_start(ap, format);
1212 proto_tree_set_representation(pi, format, ap);
1218 /* Set the FT_BOOLEAN value */
1220 proto_tree_set_boolean(field_info *fi, guint32 value)
1222 proto_tree_set_uint(fi, value);
1225 /* Add a FT_DOUBLE to a proto_tree */
1227 proto_tree_add_double(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1232 header_field_info *hfinfo;
1237 hfinfo = proto_registrar_get_nth(hfindex);
1238 g_assert(hfinfo->type == FT_DOUBLE);
1240 pi = proto_tree_add_pi(tree, hfindex, tvb, start, length, &new_fi);
1241 proto_tree_set_double(new_fi, value);
1247 proto_tree_add_double_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1253 pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
1257 fi = (field_info*) (((GNode*)pi)->data);
1258 fi->visible = FALSE;
1264 proto_tree_add_double_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1265 double value, const char *format, ...)
1270 pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
1274 va_start(ap, format);
1275 proto_tree_set_representation(pi, format, ap);
1281 /* Set the FT_DOUBLE value */
1283 proto_tree_set_double(field_info *fi, double value)
1285 fvalue_set_floating(fi->value, value);
1288 /* Add any FT_UINT* to a proto_tree */
1290 proto_tree_add_uint(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1293 proto_item *pi = NULL;
1295 header_field_info *hfinfo;
1300 hfinfo = proto_registrar_get_nth(hfindex);
1301 switch(hfinfo->type) {
1306 pi = proto_tree_add_pi(tree, hfindex, tvb, start, length,
1308 proto_tree_set_uint(new_fi, value);
1312 g_assert_not_reached();
1319 proto_tree_add_uint_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1325 pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
1329 fi = (field_info*) (((GNode*)pi)->data);
1330 fi->visible = FALSE;
1336 proto_tree_add_uint_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1337 guint32 value, const char *format, ...)
1342 pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
1346 va_start(ap, format);
1347 proto_tree_set_representation(pi, format, ap);
1353 /* Set the FT_UINT* value */
1355 proto_tree_set_uint(field_info *fi, guint32 value)
1357 header_field_info *hfinfo;
1360 hfinfo = fi->hfinfo;
1363 if (hfinfo->bitmask) {
1364 /* Mask out irrelevant portions */
1365 integer &= hfinfo->bitmask;
1368 if (hfinfo->bitshift > 0) {
1369 integer >>= hfinfo->bitshift;
1372 fvalue_set_integer(fi->value, integer);
1375 /* Add any FT_INT* to a proto_tree */
1377 proto_tree_add_int(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1380 proto_item *pi = NULL;
1382 header_field_info *hfinfo;
1387 hfinfo = proto_registrar_get_nth(hfindex);
1388 switch(hfinfo->type) {
1393 pi = proto_tree_add_pi(tree, hfindex, tvb, start, length,
1395 proto_tree_set_int(new_fi, value);
1399 g_assert_not_reached();
1406 proto_tree_add_int_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1412 pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
1416 fi = (field_info*) (((GNode*)pi)->data);
1417 fi->visible = FALSE;
1423 proto_tree_add_int_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1424 gint32 value, const char *format, ...)
1426 proto_item *pi = NULL;
1429 pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
1433 va_start(ap, format);
1434 proto_tree_set_representation(pi, format, ap);
1440 /* Set the FT_INT* value */
1442 proto_tree_set_int(field_info *fi, gint32 value)
1444 header_field_info *hfinfo;
1447 hfinfo = fi->hfinfo;
1448 integer = (guint32) value;
1450 if (hfinfo->bitmask) {
1451 /* Mask out irrelevant portions */
1452 integer &= hfinfo->bitmask;
1455 if (hfinfo->bitshift > 0) {
1456 integer >>= hfinfo->bitshift;
1459 fvalue_set_integer(fi->value, integer);
1463 /* Add a field_info struct to the proto_tree, encapsulating it in a GNode (proto_item) */
1465 proto_tree_add_node(proto_tree *tree, field_info *fi)
1469 pi = (proto_item*) g_node_new(fi);
1470 g_node_append((GNode*)tree, (GNode*)pi);
1476 /* Generic way to allocate field_info and add to proto_tree.
1477 * Sets *pfi to address of newly-allocated field_info struct, if pfi is non-NULL. */
1479 proto_tree_add_pi(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1488 fi = alloc_field_info(hfindex, tvb, start, length);
1489 pi = proto_tree_add_node(tree, fi);
1499 alloc_field_info(int hfindex, tvbuff_t *tvb, gint start, gint length)
1503 fi = g_mem_chunk_alloc(gmc_field_info);
1505 g_assert(hfindex >= 0 && (guint) hfindex < gpa_hfinfo->len);
1508 * We only allow a null tvbuff if the item has a zero length,
1509 * i.e. if there's no data backing it.
1511 g_assert(tvb != NULL || length == 0);
1512 fi->hfinfo = proto_registrar_get_nth(hfindex);
1513 g_assert(fi->hfinfo != NULL);
1516 fi->start += tvb_raw_offset(tvb);
1518 fi->length = length;
1519 fi->tree_type = ETT_NONE;
1520 fi->visible = proto_tree_is_visible;
1521 fi->representation = NULL;
1523 fi->value = fvalue_new(fi->hfinfo->type);
1525 /* add the data source name */
1527 fi->ds_name = tvb_get_name(tvb);
1535 /* Set representation of a proto_tree entry, if the protocol tree is to
1538 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap)
1540 field_info *fi = (field_info*) (((GNode*)pi)->data);
1543 fi->representation = g_mem_chunk_alloc(gmc_item_labels);
1544 vsnprintf(fi->representation, ITEM_LABEL_LENGTH, format, ap);
1548 /* Set text of proto_item after having already been created. */
1550 proto_item_set_text(proto_item *pi, const char *format, ...)
1552 field_info *fi = NULL;
1559 fi = (field_info *)(((GNode*)pi)->data);
1561 if (fi->representation)
1562 g_mem_chunk_free(gmc_item_labels, fi->representation);
1564 va_start(ap, format);
1565 proto_tree_set_representation(pi, format, ap);
1569 /* Append to text of proto_item after having already been created. */
1571 proto_item_append_text(proto_item *pi, const char *format, ...)
1573 field_info *fi = NULL;
1581 fi = (field_info*) (((GNode*)pi)->data);
1584 va_start(ap, format);
1586 * XXX - this will blow up if we haven't already set
1587 * "fi->representation"; that seems OK to me - you
1588 * can't append to something that doesn't exist - but
1589 * there might be cases where that's not convenient.
1591 curlen = strlen(fi->representation);
1592 if (ITEM_LABEL_LENGTH > curlen)
1593 vsnprintf(fi->representation + curlen,
1594 ITEM_LABEL_LENGTH - curlen, format, ap);
1600 proto_item_set_len(proto_item *pi, gint length)
1606 fi = (field_info*) (((GNode*)pi)->data);
1607 fi->length = length;
1611 proto_item_get_len(proto_item *pi)
1613 field_info *fi = (field_info*) (((GNode*)pi)->data);
1618 proto_tree_create_root(void)
1620 return (proto_tree*) g_node_new(NULL);
1624 proto_item_add_subtree(proto_item *pi, gint idx) {
1630 fi = (field_info*) (((GNode*)pi)->data);
1631 g_assert(idx >= 0 && idx < num_tree_types);
1632 fi->tree_type = idx;
1633 return (proto_tree*) pi;
1637 proto_compare_name(gconstpointer p1_arg, gconstpointer p2_arg)
1639 const protocol_t *p1 = p1_arg;
1640 const protocol_t *p2 = p2_arg;
1642 return g_strcasecmp(p1->short_name, p2->short_name);
1646 proto_register_protocol(char *name, char *short_name, char *filter_name)
1648 protocol_t *protocol;
1649 header_field_info *hfinfo;
1652 /* Add this protocol to the list of known protocols; the list
1653 is sorted by protocol short name. */
1654 protocol = g_malloc(sizeof (protocol_t));
1655 protocol->name = name;
1656 protocol->short_name = short_name;
1657 protocol->filter_name = filter_name;
1658 protocol->fields = NULL;
1659 protocol->is_enabled = TRUE; /* protocol is enabled by default */
1660 protocol->can_disable = TRUE;
1661 protocols = g_list_insert_sorted(protocols, protocol,
1662 proto_compare_name);
1664 /* Here we do allocate a new header_field_info struct */
1665 hfinfo = g_mem_chunk_alloc(gmc_hfinfo);
1666 hfinfo->name = name;
1667 hfinfo->abbrev = filter_name;
1668 hfinfo->type = FT_PROTOCOL;
1669 hfinfo->strings = NULL;
1670 hfinfo->bitmask = 0;
1671 hfinfo->bitshift = 0;
1673 hfinfo->parent = -1; /* this field differentiates protos and fields */
1675 proto_id = proto_register_field_init(hfinfo, hfinfo->parent);
1676 protocol->proto_id = proto_id;
1681 * Routines to use to iterate over the protocols.
1682 * The argument passed to the iterator routines is an opaque cookie to
1683 * their callers; it's the GList pointer for the current element in
1685 * The ID of the protocol is returned, or -1 if there is no protocol.
1688 proto_get_first_protocol(void **cookie)
1690 protocol_t *protocol;
1692 if (protocols == NULL)
1694 *cookie = protocols;
1695 protocol = protocols->data;
1696 return protocol->proto_id;
1700 proto_get_next_protocol(void **cookie)
1702 GList *list_item = *cookie;
1703 protocol_t *protocol;
1705 list_item = g_list_next(list_item);
1706 if (list_item == NULL)
1708 *cookie = list_item;
1709 protocol = list_item->data;
1710 return protocol->proto_id;
1714 * Find the protocol list entry for a protocol given its field ID.
1717 compare_proto_id(gconstpointer proto_arg, gconstpointer id_arg)
1719 const protocol_t *protocol = proto_arg;
1720 const int *id_ptr = id_arg;
1722 return (protocol->proto_id == *id_ptr) ? 0 : 1;
1726 find_protocol_by_id(int proto_id)
1730 list_entry = g_list_find_custom(protocols, &proto_id, compare_proto_id);
1731 if (list_entry == NULL)
1733 return list_entry->data;
1736 static gint compare_filter_name(gconstpointer proto_arg,
1737 gconstpointer filter_name)
1739 const protocol_t *protocol = proto_arg;
1740 const gchar* f_name = filter_name;
1741 return (strcmp(protocol->filter_name, f_name));
1744 int proto_get_id_by_filter_name(gchar* filter_name)
1747 protocol_t *protocol;
1748 list_entry = g_list_find_custom(protocols,filter_name,compare_filter_name);
1749 if(list_entry == NULL)
1751 protocol = list_entry->data;
1752 return(protocol->proto_id);
1756 proto_get_protocol_name(int proto_id)
1758 protocol_t *protocol;
1760 protocol = find_protocol_by_id(proto_id);
1761 return protocol->name;
1765 proto_get_protocol_short_name(int proto_id)
1767 protocol_t *protocol;
1771 protocol = find_protocol_by_id(proto_id);
1772 return protocol->short_name;
1776 proto_get_protocol_filter_name(int proto_id)
1778 protocol_t *protocol;
1780 protocol = find_protocol_by_id(proto_id);
1781 return protocol->filter_name;
1785 proto_is_protocol_enabled(int proto_id)
1787 protocol_t *protocol;
1789 protocol = find_protocol_by_id(proto_id);
1790 return protocol->is_enabled;
1794 proto_can_disable_protocol(int proto_id)
1796 protocol_t *protocol;
1798 protocol = find_protocol_by_id(proto_id);
1799 return protocol->can_disable;
1803 proto_set_decoding(int proto_id, gboolean enabled)
1805 protocol_t *protocol;
1807 protocol = find_protocol_by_id(proto_id);
1808 g_assert(enabled || protocol->can_disable);
1809 protocol->is_enabled = enabled;
1813 proto_set_cant_disable(int proto_id)
1815 protocol_t *protocol;
1817 protocol = find_protocol_by_id(proto_id);
1818 protocol->can_disable = FALSE;
1821 /* for use with static arrays only, since we don't allocate our own copies
1822 of the header_field_info struct contained withing the hf_register_info struct */
1824 proto_register_field_array(int parent, hf_register_info *hf, int num_records)
1827 hf_register_info *ptr = hf;
1830 proto = find_protocol_by_id(parent);
1831 for (i = 0; i < num_records; i++, ptr++) {
1832 if (proto != NULL) {
1833 if (proto->fields == NULL) {
1834 proto->fields = g_list_append(NULL, ptr);
1835 proto->last_field = proto->fields;
1838 g_list_append(proto->last_field, ptr)->next;
1841 field_id = proto_register_field_init(&ptr->hfinfo, parent);
1842 *ptr->p_id = field_id;
1847 proto_register_field_init(header_field_info *hfinfo, int parent)
1849 /* These types of fields are allowed to have value_strings or true_false_strings */
1850 g_assert((hfinfo->strings == NULL) || (
1851 (hfinfo->type == FT_UINT8) ||
1852 (hfinfo->type == FT_UINT16) ||
1853 (hfinfo->type == FT_UINT24) ||
1854 (hfinfo->type == FT_UINT32) ||
1855 (hfinfo->type == FT_INT8) ||
1856 (hfinfo->type == FT_INT16) ||
1857 (hfinfo->type == FT_INT24) ||
1858 (hfinfo->type == FT_INT32) ||
1859 (hfinfo->type == FT_BOOLEAN) ));
1861 /* Require integral types to have a number base */
1862 switch (hfinfo->type) {
1872 g_assert(hfinfo->display != BASE_NONE);
1878 /* if this is a bitfield, compure bitshift */
1879 if (hfinfo->bitmask) {
1880 while ((hfinfo->bitmask & (1 << hfinfo->bitshift)) == 0)
1884 hfinfo->parent = parent;
1885 hfinfo->same_name_next = NULL;
1886 hfinfo->same_name_prev = NULL;
1888 /* if we always add and never delete, then id == len - 1 is correct */
1889 g_ptr_array_add(gpa_hfinfo, hfinfo);
1890 hfinfo->id = gpa_hfinfo->len - 1;
1895 proto_register_subtree_array(gint **indices, int num_indices)
1898 gint **ptr = indices;
1901 * Add "num_indices" elements to "tree_is_expanded".
1903 tree_is_expanded = g_realloc(tree_is_expanded,
1904 (num_tree_types + num_indices)*sizeof (gint));
1907 * Assign "num_indices" subtree numbers starting at "num_tree_types",
1908 * returning the indices through the pointers in the array whose
1909 * first element is pointed to by "indices", set to FALSE the
1910 * elements to which those subtree numbers refer, and update
1911 * "num_tree_types" appropriately.
1913 for (i = 0; i < num_indices; i++, ptr++, num_tree_types++) {
1914 tree_is_expanded[num_tree_types] = FALSE;
1915 **ptr = num_tree_types;
1920 proto_item_fill_label(field_info *fi, gchar *label_str)
1922 header_field_info *hfinfo = fi->hfinfo;
1927 guint32 n_addr; /* network-order IPv4 address */
1929 switch(hfinfo->type) {
1932 snprintf(label_str, ITEM_LABEL_LENGTH,
1933 "%s", hfinfo->name);
1937 fill_label_boolean(fi, label_str);
1941 bytes = fvalue_get(fi->value);
1943 snprintf(label_str, ITEM_LABEL_LENGTH,
1944 "%s: %s", hfinfo->name,
1945 bytes_to_str(bytes, fi->length));
1948 snprintf(label_str, ITEM_LABEL_LENGTH,
1949 "%s: <MISSING>", hfinfo->name);
1953 /* Four types of integers to take care of:
1954 * Bitfield, with val_string
1955 * Bitfield, w/o val_string
1956 * Non-bitfield, with val_string
1957 * Non-bitfield, w/o val_string
1963 if (hfinfo->bitmask) {
1964 if (hfinfo->strings) {
1965 fill_label_enumerated_bitfield(fi, label_str);
1968 fill_label_numeric_bitfield(fi, label_str);
1972 if (hfinfo->strings) {
1973 fill_label_enumerated_uint(fi, label_str);
1976 fill_label_uint(fi, label_str);
1982 fill_label_uint64(fi, label_str);
1989 g_assert(!hfinfo->bitmask);
1990 if (hfinfo->strings) {
1991 fill_label_enumerated_int(fi, label_str);
1994 fill_label_int(fi, label_str);
1999 fill_label_int64(fi, label_str);
2003 snprintf(label_str, ITEM_LABEL_LENGTH,
2004 "%s: %g", hfinfo->name, fvalue_get_floating(fi->value));
2007 case FT_ABSOLUTE_TIME:
2008 snprintf(label_str, ITEM_LABEL_LENGTH,
2009 "%s: %s", hfinfo->name,
2010 abs_time_to_str(fvalue_get(fi->value)));
2013 case FT_RELATIVE_TIME:
2014 snprintf(label_str, ITEM_LABEL_LENGTH,
2015 "%s: %s seconds", hfinfo->name,
2016 rel_time_to_secs_str(fvalue_get(fi->value)));
2020 integer = fvalue_get_integer(fi->value);
2021 snprintf(label_str, ITEM_LABEL_LENGTH,
2022 "%s: 0x%08X (%s)", hfinfo->name,
2023 integer, get_ipxnet_name(integer));
2027 bytes = fvalue_get(fi->value);
2028 snprintf(label_str, ITEM_LABEL_LENGTH,
2029 "%s: %s (%s)", hfinfo->name,
2030 ether_to_str(bytes),
2031 get_ether_name(bytes));
2035 ipv4 = fvalue_get(fi->value);
2036 n_addr = ipv4_get_net_order_addr(ipv4);
2037 snprintf(label_str, ITEM_LABEL_LENGTH,
2038 "%s: %s (%s)", hfinfo->name,
2039 get_hostname(n_addr),
2040 ip_to_str((guint8*)&n_addr));
2044 bytes = fvalue_get(fi->value);
2045 snprintf(label_str, ITEM_LABEL_LENGTH,
2046 "%s: %s (%s)", hfinfo->name,
2047 get_hostname6((struct e_in6_addr *)bytes),
2048 ip6_to_str((struct e_in6_addr*)bytes));
2053 case FT_UINT_STRING:
2054 snprintf(label_str, ITEM_LABEL_LENGTH,
2055 "%s: %s", hfinfo->name, (char*) fvalue_get(fi->value));
2059 g_error("hfinfo->type %d (%s) not handled\n",
2061 ftype_name(hfinfo->type));
2062 g_assert_not_reached();
2068 fill_label_uint64(field_info *fi, gchar *label_str)
2070 unsigned char *bytes;
2071 header_field_info *hfinfo = fi->hfinfo;
2073 bytes=fvalue_get(fi->value);
2074 switch(hfinfo->display){
2076 snprintf(label_str, ITEM_LABEL_LENGTH,
2077 "%s: %s", hfinfo->name,
2081 snprintf(label_str, ITEM_LABEL_LENGTH,
2082 "%s: %s", hfinfo->name,
2086 g_assert_not_reached();
2092 fill_label_int64(field_info *fi, gchar *label_str)
2094 unsigned char *bytes;
2095 header_field_info *hfinfo = fi->hfinfo;
2097 bytes=fvalue_get(fi->value);
2098 switch(hfinfo->display){
2100 snprintf(label_str, ITEM_LABEL_LENGTH,
2101 "%s: %s", hfinfo->name,
2105 snprintf(label_str, ITEM_LABEL_LENGTH,
2106 "%s: %s", hfinfo->name,
2110 g_assert_not_reached();
2116 fill_label_boolean(field_info *fi, gchar *label_str)
2118 char *p = label_str;
2119 int bitfield_byte_length = 0, bitwidth;
2120 guint32 unshifted_value;
2123 header_field_info *hfinfo = fi->hfinfo;
2124 static true_false_string default_tf = { "True", "False" };
2125 true_false_string *tfstring = &default_tf;
2127 if (hfinfo->strings) {
2128 tfstring = (struct true_false_string*) hfinfo->strings;
2131 value = fvalue_get_integer(fi->value);
2132 if (hfinfo->bitmask) {
2133 /* Figure out the bit width */
2134 bitwidth = hfinfo_bitwidth(hfinfo);
2137 unshifted_value = value;
2138 if (hfinfo->bitshift > 0) {
2139 unshifted_value <<= hfinfo->bitshift;
2142 /* Create the bitfield first */
2143 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
2144 bitfield_byte_length = p - label_str;
2147 /* Fill in the textual info */
2148 snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
2149 "%s: %s", hfinfo->name,
2150 value ? tfstring->true_string : tfstring->false_string);
2154 /* Fills data for bitfield ints with val_strings */
2156 fill_label_enumerated_bitfield(field_info *fi, gchar *label_str)
2158 char *format = NULL, *p;
2159 int bitfield_byte_length, bitwidth;
2160 guint32 unshifted_value;
2163 header_field_info *hfinfo = fi->hfinfo;
2165 /* Figure out the bit width */
2166 bitwidth = hfinfo_bitwidth(hfinfo);
2168 /* Pick the proper format string */
2169 format = hfinfo_uint_vals_format(hfinfo);
2172 unshifted_value = fvalue_get_integer(fi->value);
2173 value = unshifted_value;
2174 if (hfinfo->bitshift > 0) {
2175 unshifted_value <<= hfinfo->bitshift;
2178 /* Create the bitfield first */
2179 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
2180 bitfield_byte_length = p - label_str;
2182 /* Fill in the textual info using stored (shifted) value */
2183 snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
2184 format, hfinfo->name,
2185 val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
2189 fill_label_numeric_bitfield(field_info *fi, gchar *label_str)
2191 char *format = NULL, *p;
2192 int bitfield_byte_length, bitwidth;
2193 guint32 unshifted_value;
2196 header_field_info *hfinfo = fi->hfinfo;
2198 /* Figure out the bit width */
2199 bitwidth = hfinfo_bitwidth(hfinfo);
2201 /* Pick the proper format string */
2202 format = hfinfo_uint_format(hfinfo);
2205 unshifted_value = fvalue_get_integer(fi->value);
2206 value = unshifted_value;
2207 if (hfinfo->bitshift > 0) {
2208 unshifted_value <<= hfinfo->bitshift;
2211 /* Create the bitfield using */
2212 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
2213 bitfield_byte_length = p - label_str;
2215 /* Fill in the textual info using stored (shifted) value */
2216 snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
2217 format, hfinfo->name, value);
2221 fill_label_enumerated_uint(field_info *fi, gchar *label_str)
2223 char *format = NULL;
2224 header_field_info *hfinfo = fi->hfinfo;
2227 /* Pick the proper format string */
2228 format = hfinfo_uint_vals_format(hfinfo);
2230 value = fvalue_get_integer(fi->value);
2232 /* Fill in the textual info */
2233 snprintf(label_str, ITEM_LABEL_LENGTH,
2234 format, hfinfo->name,
2235 val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
2239 fill_label_uint(field_info *fi, gchar *label_str)
2241 char *format = NULL;
2242 header_field_info *hfinfo = fi->hfinfo;
2245 /* Pick the proper format string */
2246 format = hfinfo_uint_format(hfinfo);
2247 value = fvalue_get_integer(fi->value);
2249 /* Fill in the textual info */
2250 snprintf(label_str, ITEM_LABEL_LENGTH,
2251 format, hfinfo->name, value);
2255 fill_label_enumerated_int(field_info *fi, gchar *label_str)
2257 char *format = NULL;
2258 header_field_info *hfinfo = fi->hfinfo;
2261 /* Pick the proper format string */
2262 format = hfinfo_int_vals_format(hfinfo);
2263 value = fvalue_get_integer(fi->value);
2265 /* Fill in the textual info */
2266 snprintf(label_str, ITEM_LABEL_LENGTH,
2267 format, hfinfo->name,
2268 val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
2272 fill_label_int(field_info *fi, gchar *label_str)
2274 char *format = NULL;
2275 header_field_info *hfinfo = fi->hfinfo;
2278 /* Pick the proper format string */
2279 format = hfinfo_int_format(hfinfo);
2280 value = fvalue_get_integer(fi->value);
2282 /* Fill in the textual info */
2283 snprintf(label_str, ITEM_LABEL_LENGTH,
2284 format, hfinfo->name, value);
2288 hfinfo_bitwidth(header_field_info *hfinfo)
2292 if (!hfinfo->bitmask) {
2296 switch(hfinfo->type) {
2314 bitwidth = hfinfo->display; /* hacky? :) */
2317 g_assert_not_reached();
2324 hfinfo_uint_vals_format(header_field_info *hfinfo)
2326 char *format = NULL;
2328 switch(hfinfo->display) {
2330 case BASE_BIN: /* I'm lazy */
2331 format = "%s: %s (%u)";
2333 case BASE_OCT: /* I'm lazy */
2334 format = "%s: %s (%o)";
2337 switch(hfinfo->type) {
2339 format = "%s: %s (0x%02x)";
2342 format = "%s: %s (0x%04x)";
2345 format = "%s: %s (0x%06x)";
2348 format = "%s: %s (0x%08x)";
2351 g_assert_not_reached();
2356 g_assert_not_reached();
2363 hfinfo_uint_format(header_field_info *hfinfo)
2365 char *format = NULL;
2367 /* Pick the proper format string */
2368 switch(hfinfo->display) {
2370 case BASE_BIN: /* I'm lazy */
2373 case BASE_OCT: /* I'm lazy */
2377 switch(hfinfo->type) {
2379 format = "%s: 0x%02x";
2382 format = "%s: 0x%04x";
2385 format = "%s: 0x%06x";
2388 format = "%s: 0x%08x";
2391 g_assert_not_reached();
2396 g_assert_not_reached();
2403 hfinfo_int_vals_format(header_field_info *hfinfo)
2405 char *format = NULL;
2407 switch(hfinfo->display) {
2409 case BASE_BIN: /* I'm lazy */
2410 format = "%s: %s (%d)";
2412 case BASE_OCT: /* I'm lazy */
2413 format = "%s: %s (%o)";
2416 switch(hfinfo->type) {
2418 format = "%s: %s (0x%02x)";
2421 format = "%s: %s (0x%04x)";
2424 format = "%s: %s (0x%06x)";
2427 format = "%s: %s (0x%08x)";
2430 g_assert_not_reached();
2435 g_assert_not_reached();
2442 hfinfo_int_format(header_field_info *hfinfo)
2444 char *format = NULL;
2446 /* Pick the proper format string */
2447 switch(hfinfo->display) {
2449 case BASE_BIN: /* I'm lazy */
2452 case BASE_OCT: /* I'm lazy */
2456 switch(hfinfo->type) {
2458 format = "%s: 0x%02x";
2461 format = "%s: 0x%04x";
2464 format = "%s: 0x%06x";
2467 format = "%s: 0x%08x";
2470 g_assert_not_reached();
2475 g_assert_not_reached();
2484 proto_registrar_n(void)
2486 return gpa_hfinfo->len;
2490 proto_registrar_get_name(int n)
2492 header_field_info *hfinfo;
2494 hfinfo = proto_registrar_get_nth(n);
2496 return hfinfo->name;
2502 proto_registrar_get_abbrev(int n)
2504 header_field_info *hfinfo;
2506 hfinfo = proto_registrar_get_nth(n);
2508 return hfinfo->abbrev;
2514 proto_registrar_get_ftype(int n)
2516 header_field_info *hfinfo;
2518 hfinfo = proto_registrar_get_nth(n);
2520 return hfinfo->type;
2526 proto_registrar_get_parent(int n)
2528 header_field_info *hfinfo;
2530 hfinfo = proto_registrar_get_nth(n);
2532 return hfinfo->parent;
2538 proto_registrar_is_protocol(int n)
2540 header_field_info *hfinfo;
2542 hfinfo = proto_registrar_get_nth(n);
2544 return (hfinfo->parent == -1 ? TRUE : FALSE);
2549 /* Returns length of field in packet (not necessarily the length
2550 * in our internal representation, as in the case of IPv4).
2551 * 0 means undeterminable at time of registration
2552 * -1 means the field is not registered. */
2554 proto_registrar_get_length(int n)
2556 header_field_info *hfinfo;
2558 hfinfo = proto_registrar_get_nth(n);
2562 return ftype_length(hfinfo->type);
2566 /* =================================================================== */
2567 /* used when calling proto search functions */
2569 header_field_info *target;
2570 const guint8 *packet_data;
2572 gboolean halt_on_first_hit;
2573 GNodeTraverseFunc traverse_func; /* for traverse_subtree_for_field() */
2575 GPtrArray *ptr_array;
2578 } proto_tree_search_info;
2580 /* Looks for a protocol at the top layer of the tree. The protocol can occur
2581 * more than once, for those encapsulated protocols. For each protocol subtree
2582 * that is found, the callback function is called.
2585 proto_find_protocol_multi(proto_tree* tree, GNodeTraverseFunc callback,
2586 proto_tree_search_info *sinfo)
2588 g_assert(callback != NULL);
2589 g_node_traverse((GNode*)tree, G_IN_ORDER, G_TRAVERSE_ALL, 2, callback, (gpointer*)sinfo);
2592 /* Calls a traversal function for all subtrees.
2595 traverse_subtree_for_field(GNode *node, gpointer data)
2597 field_info *fi = (field_info*) (node->data);
2598 proto_tree_search_info *sinfo = (proto_tree_search_info*) data;
2600 if (fi) { /* !fi == the top most container node which holds nothing */
2601 g_node_traverse(node, G_IN_ORDER, G_TRAVERSE_ALL, -1,
2602 sinfo->traverse_func, sinfo);
2603 if (sinfo->result.node)
2604 return sinfo->halt_on_first_hit; /* halt? continue? */
2606 return FALSE; /* keep traversing */
2610 check_for_protocol_or_field_id(GNode *node, gpointer data)
2612 field_info *fi = (field_info*) (node->data);
2613 proto_tree_search_info *sinfo = (proto_tree_search_info*) data;
2614 header_field_info *hfinfo;
2616 if (fi) { /* !fi == the top most container node which holds nothing */
2617 /* Is this field one of the fields in the specified list
2619 for (hfinfo = sinfo->target; hfinfo != NULL;
2620 hfinfo = hfinfo->same_name_next) {
2621 if (fi->hfinfo == hfinfo) {
2622 sinfo->result.node = node;
2623 return TRUE; /* halt traversal */
2627 return FALSE; /* keep traversing */
2630 /* Looks for a protocol or a field in a proto_tree. Returns TRUE if
2631 * it exists anywhere, or FALSE if it exists nowhere. */
2633 proto_check_for_protocol_or_field(proto_tree* tree, int id)
2635 proto_tree_search_info sinfo;
2636 header_field_info *hfinfo;
2638 hfinfo = proto_registrar_get_nth(id);
2640 /* Find the first entry on the list of fields with the same
2641 * name as this field. */
2642 while (hfinfo->same_name_prev != NULL)
2643 hfinfo = hfinfo->same_name_prev;
2645 sinfo.target = hfinfo;
2646 sinfo.result.node = NULL;
2647 sinfo.traverse_func = check_for_protocol_or_field_id;
2648 sinfo.halt_on_first_hit = TRUE;
2650 /* do a quicker check if target is a protocol */
2651 if (proto_registrar_is_protocol(id) == TRUE) {
2652 proto_find_protocol_multi(tree, check_for_protocol_or_field_id, &sinfo);
2655 /* Go through each protocol subtree. */
2656 g_node_traverse((GNode*)tree, G_IN_ORDER, G_TRAVERSE_ALL, 2,
2657 traverse_subtree_for_field, &sinfo);
2660 if (sinfo.result.node)
2669 get_finfo_ptr_array(GNode *node, gpointer data)
2671 field_info *fi = (field_info*) (node->data);
2672 proto_tree_search_info *sinfo = (proto_tree_search_info*) data;
2673 header_field_info *hfinfo;
2675 if (fi) { /* !fi == the top most container node which holds nothing */
2676 /* Is this field one of the fields in the specified list
2678 for (hfinfo = sinfo->target; hfinfo != NULL;
2679 hfinfo = hfinfo->same_name_next) {
2680 if (fi->hfinfo == hfinfo) {
2681 if (!sinfo->result.ptr_array) {
2682 sinfo->result.ptr_array = g_ptr_array_new();
2684 g_ptr_array_add(sinfo->result.ptr_array,
2686 return FALSE; /* keep traversing */
2690 return FALSE; /* keep traversing */
2693 /* Return GPtrArray* of field_info pointers for all hfindex that appear in tree
2694 * (we assume that a field will only appear under its registered parent's subtree) */
2696 proto_get_finfo_ptr_array(proto_tree *tree, int id)
2698 proto_tree_search_info sinfo;
2699 header_field_info *hfinfo;
2701 hfinfo = proto_registrar_get_nth(id);
2703 /* Find the first entry on the list of fields with the same
2704 * name as this field. */
2705 while (hfinfo->same_name_prev != NULL)
2706 hfinfo = hfinfo->same_name_prev;
2708 sinfo.target = hfinfo;
2709 sinfo.result.ptr_array = NULL;
2710 sinfo.traverse_func = get_finfo_ptr_array;
2711 sinfo.halt_on_first_hit = FALSE;
2713 /* do a quicker check if target is a protocol */
2714 if (proto_registrar_is_protocol(id) == TRUE) {
2715 proto_find_protocol_multi(tree, get_finfo_ptr_array, &sinfo);
2718 /* Go through each protocol subtree. */
2719 sinfo.traverse_func = get_finfo_ptr_array;
2720 g_node_traverse((GNode*)tree, G_IN_ORDER, G_TRAVERSE_ALL, 2,
2721 traverse_subtree_for_field, &sinfo);
2724 return sinfo.result.ptr_array;
2736 check_for_offset(GNode *node, gpointer data)
2738 field_info *fi = node->data;
2739 offset_search_t *offsearch = data;
2741 /* !fi == the top most container node which holds nothing */
2742 if (fi && fi->visible && fi->ds_name &&
2743 strcmp(offsearch->name, fi->ds_name) == 0) {
2744 if (offsearch->offset >= (guint) fi->start &&
2745 offsearch->offset < (guint) (fi->start + fi->length)) {
2747 offsearch->finfo = fi;
2748 return FALSE; /* keep traversing */
2751 return FALSE; /* keep traversing */
2754 /* Search a proto_tree backwards (from leaves to root) looking for the field
2755 * whose start/length occupies 'offset' */
2756 /* XXX - I couldn't find an easy way to search backwards, so I search
2757 * forwards, w/o stopping. Therefore, the last finfo I find will the be
2758 * the one I want to return to the user. This algorithm is inefficient
2759 * and could be re-done, but I'd have to handle all the children and
2760 * siblings of each node myself. When I have more time I'll do that.
2763 proto_find_field_from_offset(proto_tree *tree, guint offset, char* ds_name)
2765 offset_search_t offsearch;
2767 offsearch.offset = offset;
2768 offsearch.finfo = NULL;
2769 offsearch.name = ds_name;
2771 g_node_traverse((GNode*)tree, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
2772 check_for_offset, &offsearch);
2774 return offsearch.finfo;
2781 /* Dumps the contents of the registration database to stdout. An indepedent program can take
2782 * this output and format it into nice tables or HTML or whatever.
2784 * There is one record per line. Each record is either a protocol or a header
2785 * field, differentiated by the first field. The fields are tab-delimited.
2790 * Field 2 = protocol name
2791 * Field 3 = protocol abbreviation
2796 * Field 2 = field name
2797 * Field 3 = field abbreviation
2798 * Field 4 = type ( textual representation of the the ftenum type )
2799 * Field 5 = parent protocol abbreviation
2802 proto_registrar_dump(void)
2804 header_field_info *hfinfo, *parent_hfinfo;
2806 const char *enum_name;
2808 len = gpa_hfinfo->len;
2809 for (i = 0; i < len ; i++) {
2810 hfinfo = proto_registrar_get_nth(i);
2813 * Skip fields with zero-length names or abbreviations;
2814 * the pseudo-field for "proto_tree_add_text()" is such
2815 * a field, and we don't want it in the list of filterable
2819 * XXX - perhaps the name and abbrev field should be null
2820 * pointers rather than null strings for that pseudo-field,
2821 * but we'd have to add checks for null pointers in some
2822 * places if we did that.
2824 * Or perhaps protocol tree items added with
2825 * "proto_tree_add_text()" should have -1 as the field index,
2826 * with no pseudo-field being used, but that might also
2827 * require special checks for -1 to be added.
2829 if (strlen(hfinfo->name) == 0 || strlen(hfinfo->abbrev) == 0)
2832 /* format for protocols */
2833 if (proto_registrar_is_protocol(i)) {
2834 printf("P\t%s\t%s\n", hfinfo->name, hfinfo->abbrev);
2836 /* format for header fields */
2839 * If this field isn't at the head of the list of
2840 * fields with this name, skip this field - all
2841 * fields with the same name are really just versions
2842 * of the same field stored in different bits, and
2843 * should have the same type/radix/value list, and
2844 * just differ in their bit masks. (If a field isn't
2845 * a bitfield, but can be, say, 1 or 2 bytes long,
2846 * it can just be made FT_UINT16, meaning the
2847 * *maximum* length is 2 bytes, and be used
2850 if (hfinfo->same_name_prev != NULL)
2853 parent_hfinfo = proto_registrar_get_nth(hfinfo->parent);
2854 g_assert(parent_hfinfo);
2856 enum_name = ftype_name(hfinfo->type);
2857 printf("F\t%s\t%s\t%s\t%s\n", hfinfo->name, hfinfo->abbrev,
2858 enum_name,parent_hfinfo->abbrev);
2864 hfinfo_numeric_format(header_field_info *hfinfo)
2866 char *format = NULL;
2868 /* Pick the proper format string */
2869 switch(hfinfo->display) {
2871 case BASE_OCT: /* I'm lazy */
2872 case BASE_BIN: /* I'm lazy */
2873 switch(hfinfo->type) {
2878 format = "%s == %u";
2884 format = "%s == %d";
2887 g_assert_not_reached();
2892 switch(hfinfo->type) {
2894 format = "%s == 0x%02x";
2897 format = "%s == 0x%04x";
2900 format = "%s == 0x%06x";
2903 format = "%s == 0x%08x";
2906 g_assert_not_reached();
2911 g_assert_not_reached();
2918 * Returns TRUE if we can do a "match selected" on the field, FALSE
2922 proto_can_match_selected(field_info *finfo)
2924 header_field_info *hfinfo;
2926 hfinfo = finfo->hfinfo;
2929 switch(hfinfo->type) {
2947 case FT_ABSOLUTE_TIME:
2948 case FT_RELATIVE_TIME:
2952 * These all have values, so we can match.
2958 * This doesn't have a value, so we'd match
2959 * on the raw bytes at this address;
2960 * however, if the length is 0, there's nothing
2961 * to match, so we can't match.
2963 return (finfo->length != 0);
2968 proto_alloc_dfilter_string(field_info *finfo, guint8 *pd)
2970 header_field_info *hfinfo;
2972 char *buf, *stringified, *format, *ptr, *value_str;
2976 hfinfo = finfo->hfinfo;
2978 abbrev_len = strlen(hfinfo->abbrev);
2980 switch(hfinfo->type) {
2983 dfilter_len = abbrev_len + 6;
2984 buf = g_malloc0(dfilter_len);
2985 snprintf(buf, dfilter_len, "%s == %s",
2987 fvalue_get_integer(finfo->value) ? "1" : "0");
2998 dfilter_len = abbrev_len + 20;
2999 buf = g_malloc0(dfilter_len);
3000 format = hfinfo_numeric_format(hfinfo);
3001 snprintf(buf, dfilter_len, format, hfinfo->abbrev, fvalue_get_integer(finfo->value));
3005 stringified = u64toa(fvalue_get(finfo->value));
3006 dfilter_len = abbrev_len + 4 + strlen(stringified) +1;
3007 buf = g_malloc0(dfilter_len);
3008 snprintf(buf, dfilter_len, "%s == %s", hfinfo->abbrev,
3013 stringified = i64toa(fvalue_get(finfo->value));
3014 dfilter_len = abbrev_len + 4 + strlen(stringified) +1;
3015 buf = g_malloc0(dfilter_len);
3016 snprintf(buf, dfilter_len, "%s == %s", hfinfo->abbrev,
3021 dfilter_len = abbrev_len + 4 + 15 + 1;
3022 buf = g_malloc0(dfilter_len);
3023 snprintf(buf, dfilter_len, "%s == %s", hfinfo->abbrev,
3024 ipv4_addr_str(fvalue_get(finfo->value)));
3028 dfilter_len = abbrev_len + 15;
3029 buf = g_malloc0(dfilter_len);
3030 snprintf(buf, dfilter_len, "%s == 0x%08x", hfinfo->abbrev,
3031 fvalue_get_integer(finfo->value));
3035 stringified = ip6_to_str((struct e_in6_addr*) fvalue_get(finfo->value));
3036 dfilter_len = abbrev_len + 4 + strlen(stringified) + 1;
3037 buf = g_malloc0(dfilter_len);
3038 snprintf(buf, dfilter_len, "%s == %s", hfinfo->abbrev,
3043 dfilter_len = abbrev_len + 30;
3044 buf = g_malloc0(dfilter_len);
3045 snprintf(buf, dfilter_len, "%s == %f", hfinfo->abbrev,
3046 fvalue_get_floating(finfo->value));
3050 dfilter_len = abbrev_len + 22;
3051 buf = g_malloc0(dfilter_len);
3052 snprintf(buf, dfilter_len, "%s == %s",
3054 ether_to_str(fvalue_get(finfo->value)));
3057 case FT_ABSOLUTE_TIME:
3059 abs_time_to_str((nstime_t *)fvalue_get(finfo->value));
3060 dfilter_len = abbrev_len + strlen(value_str) + 7;
3061 buf = g_malloc0(dfilter_len);
3062 snprintf(buf, dfilter_len, "%s == \"%s\"",
3063 hfinfo->abbrev, value_str);
3066 case FT_RELATIVE_TIME:
3068 rel_time_to_secs_str((nstime_t *)fvalue_get(finfo->value));
3069 dfilter_len = abbrev_len + strlen(value_str) + 4;
3070 buf = g_malloc0(dfilter_len);
3071 snprintf(buf, dfilter_len, "%s == %s",
3072 hfinfo->abbrev, value_str);
3082 value_str = fvalue_get(finfo->value);
3083 dfilter_len = abbrev_len + strlen(value_str) + 7;
3084 buf = g_malloc0(dfilter_len);
3085 snprintf(buf, dfilter_len, "%s == \"%s\"",
3086 hfinfo->abbrev, value_str);
3090 dfilter_len = finfo->length*3 - 1;
3091 dfilter_len += abbrev_len + 7;
3092 buf = g_malloc0(dfilter_len);
3093 snprintf(buf, dfilter_len, "%s == %s",
3095 bytes_to_str_punct(fvalue_get(finfo->value), finfo->length,':'));
3099 c = pd + finfo->start;
3100 buf = g_malloc0(32 + finfo->length * 3);
3103 sprintf(ptr, "frame[%d] == ", finfo->start);
3104 ptr = buf+strlen(buf);
3106 for (i=0;i<finfo->length; i++) {
3108 sprintf(ptr, "%02x", *c++);
3111 sprintf(ptr, ":%02x", *c++);
3113 ptr = buf+strlen(buf);