2 * Routines for protocol tree
4 * $Id: proto.c,v 1.76 2000/08/11 13:35:33 deniel Exp $
6 * Ethereal - Network traffic analyzer
7 * By Gerald Combs <gerald@zing.org>
8 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
30 #ifdef HAVE_SYS_TYPES_H
31 # include <sys/types.h>
38 #ifdef NEED_SNPRINTF_H
39 # include "snprintf.h"
45 #include "packet-ipv6.h"
48 #define cVALS(x) (const value_string*)(x)
51 proto_tree_free_node(GNode *node, gpointer data);
53 static void fill_label_boolean(field_info *fi, gchar *label_str);
54 static void fill_label_uint(field_info *fi, gchar *label_str);
55 static void fill_label_enumerated_uint(field_info *fi, gchar *label_str);
56 static void fill_label_enumerated_bitfield(field_info *fi, gchar *label_str);
57 static void fill_label_numeric_bitfield(field_info *fi, gchar *label_str);
58 static void fill_label_int(field_info *fi, gchar *label_str);
59 static void fill_label_enumerated_int(field_info *fi, gchar *label_str);
61 static int hfinfo_bitwidth(header_field_info *hfinfo);
62 static char* hfinfo_uint_vals_format(header_field_info *hfinfo);
63 static char* hfinfo_uint_format(header_field_info *hfinfo);
64 static char* hfinfo_int_vals_format(header_field_info *hfinfo);
65 static char* hfinfo_int_format(header_field_info *hfinfo);
67 static gboolean check_for_protocol_or_field_id(GNode *node, gpointer data);
70 proto_tree_add_node(proto_tree *tree, field_info *fi);
73 alloc_field_info(int hfindex, tvbuff_t *tvb, gint start, gint length);
76 proto_tree_add_pi(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
79 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap);
82 proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length);
84 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length);
86 proto_tree_set_time(field_info *fi, struct timeval *value_ptr);
88 proto_tree_set_string(field_info *fi, const char* value);
90 proto_tree_set_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
92 proto_tree_set_ether(field_info *fi, const guint8* value);
94 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start);
96 proto_tree_set_ipxnet(field_info *fi, guint32 value);
98 proto_tree_set_ipv4(field_info *fi, guint32 value);
100 proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr);
102 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start);
104 proto_tree_set_boolean(field_info *fi, guint32 value);
106 proto_tree_set_double(field_info *fi, double value);
108 proto_tree_set_uint(field_info *fi, guint32 value);
110 proto_tree_set_int(field_info *fi, gint32 value);
112 static int proto_register_field_init(header_field_info *hfinfo, int parent);
114 /* special-case header field used within proto.c */
115 int hf_text_only = 1;
117 /* Contains information about protocols and header fields. Used when
118 * dissectors register their data */
119 GMemChunk *gmc_hfinfo = NULL;
121 /* Contains information about a field when a dissector calls
122 * proto_tree_add_item. */
123 GMemChunk *gmc_field_info = NULL;
125 /* String space for protocol and field items for the GUI */
126 GMemChunk *gmc_item_labels = NULL;
128 /* List which stores protocols and fields that have been registered */
129 GPtrArray *gpa_hfinfo = NULL;
131 /* Points to the first element of an array of Booleans, indexed by
132 a subtree item type; that array element is TRUE if subtrees of
133 an item of that type are to be expanded. */
134 gboolean *tree_is_expanded;
136 /* Number of elements in that array. */
139 /* Is the parsing being done for a visible proto_tree or an invisible one?
140 * By setting this correctly, the proto_tree creation is sped up by not
141 * having to call vsnprintf and copy strings around.
143 gboolean proto_tree_is_visible = FALSE;
145 /* initialize data structures and register protocols and fields */
149 static hf_register_info hf[] = {
151 { "Text", "text", FT_TEXT_ONLY, BASE_NONE, NULL, 0x0,
156 g_mem_chunk_destroy(gmc_hfinfo);
158 g_mem_chunk_destroy(gmc_field_info);
160 g_mem_chunk_destroy(gmc_item_labels);
162 g_ptr_array_free(gpa_hfinfo, FALSE);
163 if (tree_is_expanded != NULL)
164 g_free(tree_is_expanded);
166 gmc_hfinfo = g_mem_chunk_new("gmc_hfinfo",
167 sizeof(struct header_field_info), 50 * sizeof(struct
168 header_field_info), G_ALLOC_ONLY);
169 gmc_field_info = g_mem_chunk_new("gmc_field_info",
170 sizeof(struct field_info), 200 * sizeof(struct field_info),
172 gmc_item_labels = g_mem_chunk_new("gmc_item_labels",
173 ITEM_LABEL_LENGTH, 20 * ITEM_LABEL_LENGTH,
175 gpa_hfinfo = g_ptr_array_new();
177 /* Allocate "tree_is_expanded", with one element for ETT_NONE,
178 and initialize that element to FALSE. */
179 tree_is_expanded = g_malloc(sizeof (gint));
180 tree_is_expanded[0] = FALSE;
183 /* Have each dissector register its protocols and fields, and
184 do whatever one-time initialization it needs to do. */
185 register_all_protocols();
187 /* Now have the ones that register a "handoff", i.e. that
188 specify that another dissector for a protocol under which
189 this dissector's protocol lives call it. */
190 register_all_protocol_handoffs();
192 /* Register one special-case FT_TEXT_ONLY field for use when
193 converting ethereal to new-style proto_tree. These fields
194 are merely strings on the GUI tree; they are not filterable */
195 proto_register_field_array(-1, hf, array_length(hf));
197 /* We've assigned all the subtree type values; allocate the array
198 for them, and zero it out. */
199 tree_is_expanded = g_malloc(num_tree_types*sizeof (gint *));
200 memset(tree_is_expanded, '\0', num_tree_types*sizeof (gint *));
207 g_mem_chunk_destroy(gmc_hfinfo);
209 g_mem_chunk_destroy(gmc_field_info);
211 g_mem_chunk_destroy(gmc_item_labels);
213 g_ptr_array_free(gpa_hfinfo, FALSE);
216 /* frees the resources that the dissection a proto_tree uses */
218 proto_tree_free(proto_tree *tree)
220 g_node_traverse((GNode*)tree, G_IN_ORDER, G_TRAVERSE_ALL, -1,
221 proto_tree_free_node, NULL);
222 g_node_destroy((GNode*)tree);
226 proto_tree_free_node(GNode *node, gpointer data)
228 field_info *fi = (field_info*) (node->data);
231 if (fi->representation)
232 g_mem_chunk_free(gmc_item_labels, fi->representation);
233 if (fi->hfinfo->type == FT_STRING)
234 g_free(fi->value.string);
235 else if (fi->hfinfo->type == FT_NSTRING_UINT8)
236 g_free(fi->value.string);
237 else if (fi->hfinfo->type == FT_BYTES)
238 g_free(fi->value.bytes);
239 g_mem_chunk_free(gmc_field_info, fi);
241 return FALSE; /* FALSE = do not end traversal of GNode tree */
244 /* Finds a record in the hf_info_records array by id. */
245 struct header_field_info*
246 proto_registrar_get_nth(int hfindex)
248 g_assert(hfindex >= 0 && hfindex < gpa_hfinfo->len);
249 return g_ptr_array_index(gpa_hfinfo, hfindex);
253 /* Add a node with no text */
255 proto_tree_add_notext(proto_tree *tree, tvbuff_t *tvb, gint start, gint length)
259 pi = proto_tree_add_pi(tree, hf_text_only, tvb, start, length, NULL);
266 /* Add a text-only node to the proto_tree */
268 proto_tree_add_text(proto_tree *tree, tvbuff_t *tvb, gint start, gint length,
269 const char *format, ...)
274 pi = proto_tree_add_notext(tree, tvb, start, length);
278 va_start(ap, format);
279 proto_tree_set_representation(pi, format, ap);
285 /* Add a text-only node to the proto_tree (va_list version) */
287 proto_tree_add_text_valist(proto_tree *tree, tvbuff_t *tvb, gint start,
288 gint length, const char *format, va_list ap)
292 pi = proto_tree_add_notext(tree, tvb, start, length);
296 proto_tree_set_representation(pi, format, ap);
301 /* Add a text-only node for debugging purposes. The caller doesn't need
302 * to worry about tvbuff, start, or length. Debug message gets sent to
305 proto_tree_add_debug_text(proto_tree *tree, const char *format, ...)
310 pi = proto_tree_add_notext(tree, NULL, 0, 0);
314 va_start(ap, format);
315 proto_tree_set_representation(pi, format, ap);
325 get_uint_value(tvbuff_t *tvb, gint offset, gint length, gboolean little_endian)
332 value = tvb_get_guint8(tvb, offset);
336 value = little_endian ? tvb_get_letohs(tvb, offset)
337 : tvb_get_ntohs(tvb, offset);
341 value = little_endian ? tvb_get_letoh24(tvb, offset)
342 : tvb_get_ntoh24(tvb, offset);
346 value = little_endian ? tvb_get_letohl(tvb, offset)
347 : tvb_get_ntohl(tvb, offset);
351 g_assert_not_reached();
359 get_int_value(tvbuff_t *tvb, gint offset, gint length, gboolean little_endian)
366 value = (gint8)tvb_get_guint8(tvb, offset);
370 value = (gint16) (little_endian ? tvb_get_letohs(tvb, offset)
371 : tvb_get_ntohs(tvb, offset));
375 value = little_endian ? tvb_get_letoh24(tvb, offset)
376 : tvb_get_ntoh24(tvb, offset);
377 if (value & 0x00800000) {
378 /* Sign bit is set; sign-extend it. */
384 value = little_endian ? tvb_get_letohl(tvb, offset)
385 : tvb_get_ntohl(tvb, offset);
389 g_assert_not_reached();
396 /* Add an item to a proto_tree, using the text label registered to that item;
397 the item is extracted from the tvbuff handed to it. */
399 proto_tree_add_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
400 gint start, gint length, gboolean little_endian)
406 new_fi = alloc_field_info(hfindex, tvb, start, length);
411 switch(new_fi->hfinfo->type) {
413 /* no value to set for FT_NONE */
417 proto_tree_set_bytes_tvb(new_fi, tvb, start, length);
421 proto_tree_set_boolean(new_fi,
422 get_uint_value(tvb, start, length, little_endian));
425 /* XXX - make these just FT_UINT? */
430 proto_tree_set_uint(new_fi,
431 get_uint_value(tvb, start, length, little_endian));
434 /* XXX - make these just FT_INT? */
439 proto_tree_set_int(new_fi,
440 get_int_value(tvb, start, length, little_endian));
444 g_assert(length == 4);
445 tvb_memcpy(tvb, (guint8 *)&value, start, 4);
446 proto_tree_set_ipv4(new_fi, value);
450 g_assert(length == 4);
451 proto_tree_set_ipxnet(new_fi,
452 get_uint_value(tvb, start, 4, FALSE));
456 g_assert(length == 16);
457 proto_tree_set_ipv6_tvb(new_fi, tvb, start);
461 g_assert(length == 6);
462 proto_tree_set_ether_tvb(new_fi, tvb, start);
466 /* This g_strdup'ed memory is freed in proto_tree_free_node() */
467 proto_tree_set_string_tvb(new_fi, tvb, start, length);
470 case FT_NSTRING_UINT8:
471 n = tvb_get_guint8(tvb, start);
472 /* This g_strdup'ed memory is freed in proto_tree_free_node() */
473 proto_tree_set_string_tvb(new_fi, tvb, start + 1, n);
474 /* Instead of calling proto_item_set_len(), since we don't yet
475 * have a proto_item, we set the field_info's length ourselves. */
476 new_fi->length = n + 1;
480 g_error("new_fi->hfinfo->type %d not handled\n", new_fi->hfinfo->type);
481 g_assert_not_reached();
485 /* Don't add to proto_item to proto_tree until now so that any exceptions
486 * raised by a tvbuff access method doesn't leave junk in the proto_tree. */
487 pi = proto_tree_add_node(tree, new_fi);
493 proto_tree_add_item_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb,
494 gint start, gint length, gboolean little_endian)
499 pi = proto_tree_add_item(tree, hfindex, tvb, start, length, little_endian);
503 fi = (field_info*) (((GNode*)pi)->data);
510 /* Add a FT_NONE to a proto_tree */
512 proto_tree_add_protocol_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
513 gint length, const char *format, ...)
517 header_field_info *hfinfo;
522 hfinfo = proto_registrar_get_nth(hfindex);
523 g_assert(hfinfo->type == FT_NONE);
525 pi = proto_tree_add_pi(tree, hfindex, tvb, start, length, NULL);
527 va_start(ap, format);
528 proto_tree_set_representation(pi, format, ap);
531 /* no value to set for FT_NONE */
536 /* Add a FT_BYTES to a proto_tree */
538 proto_tree_add_bytes(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
539 gint length, const guint8 *start_ptr)
543 header_field_info *hfinfo;
548 hfinfo = proto_registrar_get_nth(hfindex);
549 g_assert(hfinfo->type == FT_BYTES);
551 pi = proto_tree_add_pi(tree, hfindex, tvb, start, length, &new_fi);
552 proto_tree_set_bytes(new_fi, start_ptr, length);
558 proto_tree_add_bytes_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
559 gint length, const guint8 *start_ptr)
564 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length, start_ptr);
568 fi = (field_info*) (((GNode*)pi)->data);
575 proto_tree_add_bytes_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
576 gint length, const guint8 *start_ptr, const char *format, ...)
581 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length, start_ptr);
585 va_start(ap, format);
586 proto_tree_set_representation(pi, format, ap);
592 /* Set the FT_BYTES value */
594 proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length)
596 g_assert(start_ptr != NULL);
599 /* This g_malloc'ed memory is freed in
600 proto_tree_free_node() */
601 fi->value.bytes = g_malloc(length);
602 memcpy(fi->value.bytes, start_ptr, length);
605 fi->value.bytes = NULL;
610 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length)
613 /* This g_malloc'ed memory is freed in
614 proto_tree_free_node() */
615 fi->value.bytes = tvb_memdup(tvb, offset, length);
618 fi->value.bytes = NULL;
622 /* Add a FT_*TIME to a proto_tree */
624 proto_tree_add_time(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
625 struct timeval *value_ptr)
629 header_field_info *hfinfo;
634 hfinfo = proto_registrar_get_nth(hfindex);
635 g_assert(hfinfo->type == FT_ABSOLUTE_TIME ||
636 hfinfo->type == FT_RELATIVE_TIME);
638 pi = proto_tree_add_pi(tree, hfindex, tvb, start, length, &new_fi);
639 proto_tree_set_time(new_fi, value_ptr);
645 proto_tree_add_time_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
646 struct timeval *value_ptr)
651 pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
655 fi = (field_info*) (((GNode*)pi)->data);
662 proto_tree_add_time_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
663 struct timeval *value_ptr, const char *format, ...)
668 pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
672 va_start(ap, format);
673 proto_tree_set_representation(pi, format, ap);
679 /* Set the FT_*TIME value */
681 proto_tree_set_time(field_info *fi, struct timeval *value_ptr)
683 memcpy(&fi->value.time, value_ptr, sizeof(struct timeval));
686 /* Add a FT_IPXNET to a proto_tree */
688 proto_tree_add_ipxnet(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
693 header_field_info *hfinfo;
698 hfinfo = proto_registrar_get_nth(hfindex);
699 g_assert(hfinfo->type == FT_IPXNET);
701 pi = proto_tree_add_pi(tree, hfindex, tvb, start, length, &new_fi);
702 proto_tree_set_ipxnet(new_fi, value);
708 proto_tree_add_ipxnet_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
714 pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
718 fi = (field_info*) (((GNode*)pi)->data);
725 proto_tree_add_ipxnet_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
726 guint32 value, const char *format, ...)
731 pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
735 va_start(ap, format);
736 proto_tree_set_representation(pi, format, ap);
742 /* Set the FT_IPXNET value */
744 proto_tree_set_ipxnet(field_info *fi, guint32 value)
746 fi->value.numeric = value;
749 /* Add a FT_IPv4 to a proto_tree */
751 proto_tree_add_ipv4(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
756 header_field_info *hfinfo;
761 hfinfo = proto_registrar_get_nth(hfindex);
762 g_assert(hfinfo->type == FT_IPv4);
764 pi = proto_tree_add_pi(tree, hfindex, tvb, start, length, &new_fi);
765 proto_tree_set_ipv4(new_fi, value);
771 proto_tree_add_ipv4_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
777 pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
781 fi = (field_info*) (((GNode*)pi)->data);
788 proto_tree_add_ipv4_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
789 guint32 value, const char *format, ...)
794 pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
798 va_start(ap, format);
799 proto_tree_set_representation(pi, format, ap);
805 /* Set the FT_IPv4 value */
807 proto_tree_set_ipv4(field_info *fi, guint32 value)
809 ipv4_addr_set_net_order_addr(&(fi->value.ipv4), value);
810 ipv4_addr_set_netmask_bits(&(fi->value.ipv4), 32);
813 /* Add a FT_IPv6 to a proto_tree */
815 proto_tree_add_ipv6(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
816 const guint8* value_ptr)
820 header_field_info *hfinfo;
825 hfinfo = proto_registrar_get_nth(hfindex);
826 g_assert(hfinfo->type == FT_IPv6);
828 pi = proto_tree_add_pi(tree, hfindex, tvb, start, length, &new_fi);
829 proto_tree_set_ipv6(new_fi, value_ptr);
835 proto_tree_add_ipv6_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
836 const guint8* value_ptr)
841 pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
845 fi = (field_info*) (((GNode*)pi)->data);
852 proto_tree_add_ipv6_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
853 const guint8* value_ptr, const char *format, ...)
858 pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
862 va_start(ap, format);
863 proto_tree_set_representation(pi, format, ap);
869 /* Set the FT_IPv6 value */
871 proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr)
873 memcpy(fi->value.ipv6, value_ptr, 16);
877 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start)
879 tvb_memcpy(tvb, fi->value.ipv6, start, 16);
882 /* Add a FT_STRING to a proto_tree */
884 proto_tree_add_string(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
885 gint length, const char* value)
889 header_field_info *hfinfo;
894 hfinfo = proto_registrar_get_nth(hfindex);
895 g_assert(hfinfo->type == FT_STRING);
897 pi = proto_tree_add_pi(tree, hfindex, tvb, start, length, &new_fi);
898 proto_tree_set_string(new_fi, value);
904 proto_tree_add_string_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
905 gint length, const char* value)
910 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
914 fi = (field_info*) (((GNode*)pi)->data);
921 proto_tree_add_string_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
922 gint length, const char* value, const char *format, ...)
927 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
931 va_start(ap, format);
932 proto_tree_set_representation(pi, format, ap);
938 /* Set the FT_STRING value */
940 proto_tree_set_string(field_info *fi, const char* value)
942 /* This g_strdup'ed memory is freed in proto_tree_free_node() */
943 fi->value.string = g_strdup(value);
947 proto_tree_set_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
949 /* This memory is freed in proto_tree_free_node() */
950 fi->value.string = g_malloc(length + 1);
951 tvb_memcpy(tvb, fi->value.string, start, length);
952 fi->value.string[length] = '\0';
955 /* Add a FT_ETHER to a proto_tree */
957 proto_tree_add_ether(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
962 header_field_info *hfinfo;
967 hfinfo = proto_registrar_get_nth(hfindex);
968 g_assert(hfinfo->type == FT_ETHER);
970 pi = proto_tree_add_pi(tree, hfindex, tvb, start, length, &new_fi);
971 proto_tree_set_ether(new_fi, value);
977 proto_tree_add_ether_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
983 pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
987 fi = (field_info*) (((GNode*)pi)->data);
994 proto_tree_add_ether_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
995 const guint8* value, const char *format, ...)
1000 pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
1004 va_start(ap, format);
1005 proto_tree_set_representation(pi, format, ap);
1011 /* Set the FT_ETHER value */
1013 proto_tree_set_ether(field_info *fi, const guint8* value)
1015 memcpy(fi->value.ether, value, 6);
1019 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start)
1021 tvb_memcpy(tvb, fi->value.ether, start, 6);
1024 /* Add a FT_BOOLEAN to a proto_tree */
1026 proto_tree_add_boolean(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1031 header_field_info *hfinfo;
1036 hfinfo = proto_registrar_get_nth(hfindex);
1037 g_assert(hfinfo->type == FT_BOOLEAN);
1039 pi = proto_tree_add_pi(tree, hfindex, tvb, start, length, &new_fi);
1040 proto_tree_set_boolean(new_fi, value);
1046 proto_tree_add_boolean_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1052 pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
1056 fi = (field_info*) (((GNode*)pi)->data);
1057 fi->visible = FALSE;
1063 proto_tree_add_boolean_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1064 guint32 value, const char *format, ...)
1069 pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
1073 va_start(ap, format);
1074 proto_tree_set_representation(pi, format, ap);
1080 /* Set the FT_BOOLEAN value */
1082 proto_tree_set_boolean(field_info *fi, guint32 value)
1084 proto_tree_set_uint(fi, value);
1087 /* Add a FT_DOUBLE to a proto_tree */
1089 proto_tree_add_double(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1094 header_field_info *hfinfo;
1099 hfinfo = proto_registrar_get_nth(hfindex);
1100 g_assert(hfinfo->type == FT_DOUBLE);
1102 pi = proto_tree_add_pi(tree, hfindex, tvb, start, length, &new_fi);
1103 proto_tree_set_double(new_fi, value);
1109 proto_tree_add_double_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1115 pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
1119 fi = (field_info*) (((GNode*)pi)->data);
1120 fi->visible = FALSE;
1126 proto_tree_add_double_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1127 double value, const char *format, ...)
1132 pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
1136 va_start(ap, format);
1137 proto_tree_set_representation(pi, format, ap);
1143 /* Set the FT_DOUBLE value */
1145 proto_tree_set_double(field_info *fi, double value)
1147 fi->value.floating = value;
1150 /* Add any FT_UINT* to a proto_tree */
1152 proto_tree_add_uint(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1155 proto_item *pi = NULL;
1157 header_field_info *hfinfo;
1162 hfinfo = proto_registrar_get_nth(hfindex);
1163 switch(hfinfo->type) {
1168 pi = proto_tree_add_pi(tree, hfindex, tvb, start, length,
1170 proto_tree_set_uint(new_fi, value);
1174 g_assert_not_reached();
1181 proto_tree_add_uint_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1187 pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
1191 fi = (field_info*) (((GNode*)pi)->data);
1192 fi->visible = FALSE;
1198 proto_tree_add_uint_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1199 guint32 value, const char *format, ...)
1204 pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
1208 va_start(ap, format);
1209 proto_tree_set_representation(pi, format, ap);
1215 /* Set the FT_UINT* value */
1217 proto_tree_set_uint(field_info *fi, guint32 value)
1219 header_field_info *hfinfo;
1221 hfinfo = fi->hfinfo;
1222 fi->value.numeric = value;
1223 if (hfinfo->bitmask) {
1224 /* Mask out irrelevant portions */
1225 fi->value.numeric &= hfinfo->bitmask;
1228 if (hfinfo->bitshift > 0) {
1229 fi->value.numeric >>= hfinfo->bitshift;
1234 /* Add any FT_INT* to a proto_tree */
1236 proto_tree_add_int(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1239 proto_item *pi = NULL;
1241 header_field_info *hfinfo;
1246 hfinfo = proto_registrar_get_nth(hfindex);
1247 switch(hfinfo->type) {
1252 pi = proto_tree_add_pi(tree, hfindex, tvb, start, length,
1254 proto_tree_set_int(new_fi, value);
1258 g_assert_not_reached();
1265 proto_tree_add_int_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1271 pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
1275 fi = (field_info*) (((GNode*)pi)->data);
1276 fi->visible = FALSE;
1282 proto_tree_add_int_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1283 gint32 value, const char *format, ...)
1285 proto_item *pi = NULL;
1288 pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
1292 va_start(ap, format);
1293 proto_tree_set_representation(pi, format, ap);
1299 /* Set the FT_INT* value */
1301 proto_tree_set_int(field_info *fi, gint32 value)
1303 header_field_info *hfinfo;
1305 hfinfo = fi->hfinfo;
1306 fi->value.numeric = (guint32) value;
1307 if (hfinfo->bitmask) {
1308 /* Mask out irrelevant portions */
1309 fi->value.numeric &= hfinfo->bitmask;
1312 if (hfinfo->bitshift > 0) {
1313 fi->value.numeric >>= hfinfo->bitshift;
1319 /* Add a field_info struct to the proto_tree, encapsulating it in a GNode (proto_item) */
1321 proto_tree_add_node(proto_tree *tree, field_info *fi)
1325 pi = (proto_item*) g_node_new(fi);
1326 g_node_append((GNode*)tree, (GNode*)pi);
1332 /* Generic way to allocate field_info and add to proto_tree.
1333 * Sets *pfi to address of newly-allocated field_info struct, if pfi is non-NULL. */
1335 proto_tree_add_pi(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1344 fi = alloc_field_info(hfindex, tvb, start, length);
1345 pi = proto_tree_add_node(tree, fi);
1355 alloc_field_info(int hfindex, tvbuff_t *tvb, gint start, gint length)
1359 fi = g_mem_chunk_alloc(gmc_field_info);
1361 g_assert(hfindex >= 0 && hfindex < gpa_hfinfo->len);
1362 fi->hfinfo = proto_registrar_get_nth(hfindex);
1363 g_assert(fi->hfinfo != NULL);
1366 fi->start += tvb_raw_offset(tvb);
1368 fi->length = length;
1369 fi->tree_type = ETT_NONE;
1370 fi->visible = proto_tree_is_visible;
1371 fi->representation = NULL;
1376 /* Set representation of a proto_tree entry, if the protocol tree is to
1379 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap)
1381 field_info *fi = (field_info*) (((GNode*)pi)->data);
1384 fi->representation = g_mem_chunk_alloc(gmc_item_labels);
1385 vsnprintf(fi->representation, ITEM_LABEL_LENGTH, format, ap);
1390 proto_item_set_text(proto_item *pi, const char *format, ...)
1392 field_info *fi = (field_info*) (((GNode*)pi)->data);
1395 if (fi->representation)
1396 g_mem_chunk_free(gmc_item_labels, fi->representation);
1398 va_start(ap, format);
1399 proto_tree_set_representation(pi, format, ap);
1404 proto_item_set_len(proto_item *pi, gint length)
1406 field_info *fi = (field_info*) (((GNode*)pi)->data);
1407 fi->length = length;
1411 proto_item_get_len(proto_item *pi)
1413 field_info *fi = (field_info*) (((GNode*)pi)->data);
1418 proto_tree_create_root(void)
1420 return (proto_tree*) g_node_new(NULL);
1424 proto_item_add_subtree(proto_item *pi, gint idx) {
1425 field_info *fi = (field_info*) (((GNode*)pi)->data);
1426 g_assert(idx >= 0 && idx < num_tree_types);
1427 fi->tree_type = idx;
1428 return (proto_tree*) pi;
1433 proto_register_protocol(char *name, char *abbrev)
1435 struct header_field_info *hfinfo;
1437 /* Here we do allocate a new header_field_info struct */
1438 hfinfo = g_mem_chunk_alloc(gmc_hfinfo);
1439 hfinfo->name = name;
1440 hfinfo->abbrev = abbrev;
1441 hfinfo->type = FT_NONE;
1442 hfinfo->strings = NULL;
1443 hfinfo->bitmask = 0;
1444 hfinfo->bitshift = 0;
1446 hfinfo->parent = -1; /* this field differentiates protos and fields */
1448 return proto_register_field_init(hfinfo, hfinfo->parent);
1451 /* for use with static arrays only, since we don't allocate our own copies
1452 of the header_field_info struct contained withing the hf_register_info struct */
1454 proto_register_field_array(int parent, hf_register_info *hf, int num_records)
1457 hf_register_info *ptr = hf;
1459 for (i = 0; i < num_records; i++, ptr++) {
1460 field_id = proto_register_field_init(&ptr->hfinfo, parent);
1461 *ptr->p_id = field_id;
1466 proto_register_field_init(header_field_info *hfinfo, int parent)
1468 /* These types of fields are allowed to have value_strings or true_false_strings */
1469 g_assert((hfinfo->strings == NULL) || (
1470 (hfinfo->type == FT_UINT8) ||
1471 (hfinfo->type == FT_UINT16) ||
1472 (hfinfo->type == FT_UINT24) ||
1473 (hfinfo->type == FT_UINT32) ||
1474 (hfinfo->type == FT_INT8) ||
1475 (hfinfo->type == FT_INT16) ||
1476 (hfinfo->type == FT_INT24) ||
1477 (hfinfo->type == FT_INT32) ||
1478 (hfinfo->type == FT_BOOLEAN) ));
1480 /* if this is a bitfield, compure bitshift */
1481 if (hfinfo->bitmask) {
1482 while ((hfinfo->bitmask & (1 << hfinfo->bitshift)) == 0)
1486 hfinfo->parent = parent;
1488 /* if we always add and never delete, then id == len - 1 is correct */
1489 g_ptr_array_add(gpa_hfinfo, hfinfo);
1490 hfinfo->id = gpa_hfinfo->len - 1;
1495 proto_register_subtree_array(gint **indices, int num_indices)
1498 gint **ptr = indices;
1501 * Add "num_indices" elements to "tree_is_expanded".
1503 tree_is_expanded = g_realloc(tree_is_expanded,
1504 (num_tree_types + num_indices)*sizeof (gint));
1507 * Assign "num_indices" subtree numbers starting at "num_tree_types",
1508 * returning the indices through the pointers in the array whose
1509 * first element is pointed to by "indices", set to FALSE the
1510 * elements to which those subtree numbers refer, and update
1511 * "num_tree_types" appropriately.
1513 for (i = 0; i < num_indices; i++, ptr++, num_tree_types++) {
1514 tree_is_expanded[num_tree_types] = FALSE;
1515 **ptr = num_tree_types;
1520 proto_item_fill_label(field_info *fi, gchar *label_str)
1522 struct header_field_info *hfinfo = fi->hfinfo;
1523 guint32 n_addr; /* network-order IPv4 address */
1525 switch(hfinfo->type) {
1527 snprintf(label_str, ITEM_LABEL_LENGTH,
1528 "%s", hfinfo->name);
1532 fill_label_boolean(fi, label_str);
1536 if (fi->value.bytes) {
1537 snprintf(label_str, ITEM_LABEL_LENGTH,
1538 "%s: %s", hfinfo->name,
1539 bytes_to_str(fi->value.bytes, fi->length));
1542 snprintf(label_str, ITEM_LABEL_LENGTH,
1543 "%s: <MISSING>", hfinfo->name);
1547 /* Four types of integers to take care of:
1548 * Bitfield, with val_string
1549 * Bitfield, w/o val_string
1550 * Non-bitfield, with val_string
1551 * Non-bitfield, w/o val_string
1557 if (hfinfo->bitmask) {
1558 if (hfinfo->strings) {
1559 fill_label_enumerated_bitfield(fi, label_str);
1562 fill_label_numeric_bitfield(fi, label_str);
1566 if (hfinfo->strings) {
1567 fill_label_enumerated_uint(fi, label_str);
1570 fill_label_uint(fi, label_str);
1579 g_assert(!hfinfo->bitmask);
1580 if (hfinfo->strings) {
1581 fill_label_enumerated_int(fi, label_str);
1584 fill_label_int(fi, label_str);
1589 snprintf(label_str, ITEM_LABEL_LENGTH,
1590 "%s: %g", fi->hfinfo->name,
1591 fi->value.floating);
1594 case FT_ABSOLUTE_TIME:
1595 snprintf(label_str, ITEM_LABEL_LENGTH,
1596 "%s: %s", fi->hfinfo->name,
1597 abs_time_to_str(&fi->value.time));
1600 case FT_RELATIVE_TIME:
1601 snprintf(label_str, ITEM_LABEL_LENGTH,
1602 "%s: %s seconds", fi->hfinfo->name,
1603 rel_time_to_str(&fi->value.time));
1607 snprintf(label_str, ITEM_LABEL_LENGTH,
1608 "%s: 0x%08X (%s)", fi->hfinfo->name,
1609 fi->value.numeric, get_ipxnet_name(fi->value.numeric));
1613 snprintf(label_str, ITEM_LABEL_LENGTH,
1614 "%s: %s (%s)", fi->hfinfo->name,
1615 ether_to_str(fi->value.ether),
1616 get_ether_name(fi->value.ether));
1620 n_addr = ipv4_get_net_order_addr(&fi->value.ipv4);
1621 snprintf(label_str, ITEM_LABEL_LENGTH,
1622 "%s: %s (%s)", fi->hfinfo->name,
1623 get_hostname(n_addr),
1624 ip_to_str((guint8*)&n_addr));
1628 snprintf(label_str, ITEM_LABEL_LENGTH,
1629 "%s: %s (%s)", fi->hfinfo->name,
1630 get_hostname6((struct e_in6_addr *)fi->value.ipv6),
1631 ip6_to_str((struct e_in6_addr*)fi->value.ipv6));
1635 case FT_NSTRING_UINT8:
1636 snprintf(label_str, ITEM_LABEL_LENGTH,
1637 "%s: %s", fi->hfinfo->name, fi->value.string);
1641 g_error("hfinfo->type %d not handled\n", fi->hfinfo->type);
1647 fill_label_boolean(field_info *fi, gchar *label_str)
1649 char *p = label_str;
1650 int bitfield_byte_length = 0, bitwidth;
1651 guint32 unshifted_value;
1653 struct header_field_info *hfinfo = fi->hfinfo;
1654 struct true_false_string default_tf = { "True", "False" };
1655 struct true_false_string *tfstring = &default_tf;
1657 if (hfinfo->strings) {
1658 tfstring = (struct true_false_string*) hfinfo->strings;
1661 if (hfinfo->bitmask) {
1662 /* Figure out the bit width */
1663 bitwidth = hfinfo_bitwidth(hfinfo);
1666 unshifted_value = fi->value.numeric;
1667 if (hfinfo->bitshift > 0) {
1668 unshifted_value <<= hfinfo->bitshift;
1671 /* Create the bitfield first */
1672 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
1673 bitfield_byte_length = p - label_str;
1676 /* Fill in the textual info */
1677 snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
1678 "%s: %s", hfinfo->name,
1679 fi->value.numeric ? tfstring->true_string : tfstring->false_string);
1683 /* Fills data for bitfield ints with val_strings */
1685 fill_label_enumerated_bitfield(field_info *fi, gchar *label_str)
1687 char *format = NULL, *p;
1688 int bitfield_byte_length, bitwidth;
1689 guint32 unshifted_value;
1691 struct header_field_info *hfinfo = fi->hfinfo;
1693 /* Figure out the bit width */
1694 bitwidth = hfinfo_bitwidth(hfinfo);
1696 /* Pick the proper format string */
1697 format = hfinfo_uint_vals_format(hfinfo);
1700 unshifted_value = fi->value.numeric;
1701 if (hfinfo->bitshift > 0) {
1702 unshifted_value <<= hfinfo->bitshift;
1705 /* Create the bitfield first */
1706 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
1707 bitfield_byte_length = p - label_str;
1709 /* Fill in the textual info using stored (shifted) value */
1710 snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
1711 format, hfinfo->name,
1712 val_to_str(fi->value.numeric, cVALS(hfinfo->strings), "Unknown"),
1717 fill_label_numeric_bitfield(field_info *fi, gchar *label_str)
1719 char *format = NULL, *p;
1720 int bitfield_byte_length, bitwidth;
1721 guint32 unshifted_value;
1723 struct header_field_info *hfinfo = fi->hfinfo;
1725 /* Figure out the bit width */
1726 bitwidth = hfinfo_bitwidth(hfinfo);
1728 /* Pick the proper format string */
1729 format = hfinfo_uint_format(hfinfo);
1732 unshifted_value = fi->value.numeric;
1733 if (hfinfo->bitshift > 0) {
1734 unshifted_value <<= hfinfo->bitshift;
1737 /* Create the bitfield using */
1738 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
1739 bitfield_byte_length = p - label_str;
1741 /* Fill in the textual info using stored (shifted) value */
1742 snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
1743 format, hfinfo->name, fi->value.numeric);
1747 fill_label_enumerated_uint(field_info *fi, gchar *label_str)
1749 char *format = NULL;
1750 struct header_field_info *hfinfo = fi->hfinfo;
1752 /* Pick the proper format string */
1753 format = hfinfo_uint_vals_format(hfinfo);
1755 /* Fill in the textual info */
1756 snprintf(label_str, ITEM_LABEL_LENGTH,
1757 format, hfinfo->name,
1758 val_to_str(fi->value.numeric, cVALS(hfinfo->strings), "Unknown"),
1763 fill_label_uint(field_info *fi, gchar *label_str)
1765 char *format = NULL;
1766 struct header_field_info *hfinfo = fi->hfinfo;
1768 /* Pick the proper format string */
1769 format = hfinfo_uint_format(hfinfo);
1771 /* Fill in the textual info */
1772 snprintf(label_str, ITEM_LABEL_LENGTH,
1773 format, hfinfo->name, fi->value.numeric);
1777 fill_label_enumerated_int(field_info *fi, gchar *label_str)
1779 char *format = NULL;
1780 struct header_field_info *hfinfo = fi->hfinfo;
1782 /* Pick the proper format string */
1783 format = hfinfo_int_vals_format(hfinfo);
1785 /* Fill in the textual info */
1786 snprintf(label_str, ITEM_LABEL_LENGTH,
1787 format, hfinfo->name,
1788 val_to_str(fi->value.numeric, cVALS(hfinfo->strings), "Unknown"),
1793 fill_label_int(field_info *fi, gchar *label_str)
1795 char *format = NULL;
1796 struct header_field_info *hfinfo = fi->hfinfo;
1798 /* Pick the proper format string */
1799 format = hfinfo_int_format(hfinfo);
1801 /* Fill in the textual info */
1802 snprintf(label_str, ITEM_LABEL_LENGTH,
1803 format, hfinfo->name, fi->value.numeric);
1807 hfinfo_bitwidth(header_field_info *hfinfo)
1811 if (!hfinfo->bitmask) {
1815 switch(hfinfo->type) {
1833 bitwidth = hfinfo->display; /* hacky? :) */
1836 g_assert_not_reached();
1843 hfinfo_uint_vals_format(header_field_info *hfinfo)
1845 char *format = NULL;
1847 switch(hfinfo->display) {
1850 case BASE_OCT: /* I'm lazy */
1851 case BASE_BIN: /* I'm lazy */
1852 format = "%s: %s (%u)";
1855 switch(hfinfo->type) {
1857 format = "%s: %s (0x%02x)";
1860 format = "%s: %s (0x%04x)";
1863 format = "%s: %s (0x%06x)";
1866 format = "%s: %s (0x%08x)";
1869 g_assert_not_reached();
1874 g_assert_not_reached();
1881 hfinfo_uint_format(header_field_info *hfinfo)
1883 char *format = NULL;
1885 /* Pick the proper format string */
1886 switch(hfinfo->display) {
1889 case BASE_OCT: /* I'm lazy */
1890 case BASE_BIN: /* I'm lazy */
1894 switch(hfinfo->type) {
1896 format = "%s: 0x%02x";
1899 format = "%s: 0x%04x";
1902 format = "%s: 0x%06x";
1905 format = "%s: 0x%08x";
1908 g_assert_not_reached();
1913 g_assert_not_reached();
1920 hfinfo_int_vals_format(header_field_info *hfinfo)
1922 char *format = NULL;
1924 switch(hfinfo->display) {
1927 case BASE_OCT: /* I'm lazy */
1928 case BASE_BIN: /* I'm lazy */
1929 format = "%s: %s (%d)";
1932 switch(hfinfo->type) {
1934 format = "%s: %s (0x%02x)";
1937 format = "%s: %s (0x%04x)";
1940 format = "%s: %s (0x%06x)";
1943 format = "%s: %s (0x%08x)";
1946 g_assert_not_reached();
1951 g_assert_not_reached();
1958 hfinfo_int_format(header_field_info *hfinfo)
1960 char *format = NULL;
1962 /* Pick the proper format string */
1963 switch(hfinfo->display) {
1966 case BASE_OCT: /* I'm lazy */
1967 case BASE_BIN: /* I'm lazy */
1971 switch(hfinfo->type) {
1973 format = "%s: 0x%02x";
1976 format = "%s: 0x%04x";
1979 format = "%s: 0x%06x";
1982 format = "%s: 0x%08x";
1985 g_assert_not_reached();
1990 g_assert_not_reached();
1999 proto_registrar_n(void)
2001 return gpa_hfinfo->len;
2005 proto_registrar_get_name(int n)
2007 struct header_field_info *hfinfo;
2008 hfinfo = proto_registrar_get_nth(n);
2010 return hfinfo->name;
2015 proto_registrar_get_abbrev(int n)
2017 struct header_field_info *hfinfo;
2019 hfinfo = proto_registrar_get_nth(n);
2021 return hfinfo->abbrev;
2027 proto_registrar_get_ftype(int n)
2029 struct header_field_info *hfinfo;
2031 hfinfo = proto_registrar_get_nth(n);
2033 return hfinfo->type;
2039 proto_registrar_get_parent(int n)
2041 struct header_field_info *hfinfo;
2043 hfinfo = proto_registrar_get_nth(n);
2045 return hfinfo->parent;
2051 proto_registrar_is_protocol(int n)
2053 struct header_field_info *hfinfo;
2055 hfinfo = proto_registrar_get_nth(n);
2057 return (hfinfo->parent == -1 ? TRUE : FALSE);
2062 /* Returns length of field in packet (not necessarily the length
2063 * in our internal representation, as in the case of IPv4).
2064 * 0 means undeterminable at time of registration
2065 * -1 means the field is not registered. */
2067 proto_registrar_get_length(int n)
2069 struct header_field_info *hfinfo;
2071 hfinfo = proto_registrar_get_nth(n);
2075 switch (hfinfo->type) {
2076 case FT_TEXT_ONLY: /* not filterable */
2077 case NUM_FIELD_TYPES: /* satisfy picky compilers */
2084 case FT_NSTRING_UINT8:
2086 case FT_ABSOLUTE_TIME:
2087 case FT_RELATIVE_TIME:
2114 g_assert_not_reached();
2119 /* =================================================================== */
2120 /* used when calling proto search functions */
2124 const guint8 *packet_data;
2126 gboolean halt_on_first_hit;
2127 GNodeTraverseFunc traverse_func; /* for traverse_subtree_for_field() */
2129 GPtrArray *ptr_array;
2132 } proto_tree_search_info;
2134 /* Looks for a protocol at the top layer of the tree. The protocol can occur
2135 * more than once, for those encapsulated protocols. For each protocol subtree
2136 * that is found, the callback function is called.
2139 proto_find_protocol_multi(proto_tree* tree, int target, GNodeTraverseFunc callback,
2140 proto_tree_search_info *sinfo)
2142 g_assert(callback != NULL);
2143 g_node_traverse((GNode*)tree, G_IN_ORDER, G_TRAVERSE_ALL, 2, callback, (gpointer*)sinfo);
2146 /* Calls a traversal function for all subtrees where:
2147 * 1. Subtree is immediate child of root node. That is, subtree is a "protocol"
2148 * 2. Subtree has finfo such that finfo->hfinfo->id == sinfo->parent
2151 traverse_subtree_for_field(GNode *node, gpointer data)
2153 field_info *fi = (field_info*) (node->data);
2154 proto_tree_search_info *sinfo = (proto_tree_search_info*) data;
2156 if (fi) { /* !fi == the top most container node which holds nothing */
2157 if (fi->hfinfo->id == sinfo->parent) {
2158 g_node_traverse(node, G_IN_ORDER, G_TRAVERSE_ALL, -1,
2159 sinfo->traverse_func, sinfo);
2160 if (sinfo->result.node)
2161 return sinfo->halt_on_first_hit; /* halt? continue? */
2164 return FALSE; /* keep traversing */
2168 check_for_protocol_or_field_id(GNode *node, gpointer data)
2170 field_info *fi = (field_info*) (node->data);
2171 proto_tree_search_info *sinfo = (proto_tree_search_info*) data;
2173 if (fi) { /* !fi == the top most container node which holds nothing */
2174 if (fi->hfinfo->id == sinfo->target) {
2175 sinfo->result.node = node;
2176 return TRUE; /* halt traversal */
2179 return FALSE; /* keep traversing */
2182 /* Looks for a protocol or a field in a proto_tree. Returns TRUE if
2183 * it exists anywhere, or FALSE if it exists nowhere. */
2185 proto_check_for_protocol_or_field(proto_tree* tree, int id)
2187 proto_tree_search_info sinfo;
2190 sinfo.result.node = NULL;
2192 sinfo.traverse_func = check_for_protocol_or_field_id;
2193 sinfo.halt_on_first_hit = TRUE;
2195 /* do a quicker check if target is a protocol */
2196 if (proto_registrar_is_protocol(id) == TRUE) {
2197 proto_find_protocol_multi(tree, id, check_for_protocol_or_field_id, &sinfo);
2200 /* find the field's parent protocol */
2201 sinfo.parent = proto_registrar_get_parent(id);
2203 /* Go through each protocol subtree, checking if the protocols
2204 * is the parent protocol of the field that we're looking for.
2205 * We may have protocols that occur more than once (e.g., IP in IP),
2206 * so we do indeed have to check all protocol subtrees, looking
2207 * for the parent protocol. That's why proto_find_protocol()
2208 * is not used --- it assumes a protocol occurs only once. */
2209 g_node_traverse((GNode*)tree, G_IN_ORDER, G_TRAVERSE_ALL, 2,
2210 traverse_subtree_for_field, &sinfo);
2213 if (sinfo.result.node)
2222 get_finfo_ptr_array(GNode *node, gpointer data)
2224 field_info *fi = (field_info*) (node->data);
2225 proto_tree_search_info *sinfo = (proto_tree_search_info*) data;
2227 if (fi) { /* !fi == the top most container node which holds nothing */
2228 if (fi->hfinfo->id == sinfo->target) {
2229 if (!sinfo->result.ptr_array) {
2230 sinfo->result.ptr_array = g_ptr_array_new();
2232 g_ptr_array_add(sinfo->result.ptr_array,
2234 return FALSE; /* keep traversing */
2237 return FALSE; /* keep traversing */
2240 /* Return GPtrArray* of field_info pointers for all hfindex that appear in tree
2241 * (we assume that a field will only appear under its registered parent's subtree) */
2243 proto_get_finfo_ptr_array(proto_tree *tree, int id)
2245 proto_tree_search_info sinfo;
2248 sinfo.result.ptr_array = NULL;
2250 sinfo.traverse_func = get_finfo_ptr_array;
2251 sinfo.halt_on_first_hit = FALSE;
2253 /* do a quicker check if target is a protocol */
2254 if (proto_registrar_is_protocol(id) == TRUE) {
2255 proto_find_protocol_multi(tree, id, get_finfo_ptr_array, &sinfo);
2258 /* find the field's parent protocol */
2259 sinfo.parent = proto_registrar_get_parent(id);
2261 /* Go through each protocol subtree, checking if the protocols
2262 * is the parent protocol of the field that we're looking for.
2263 * We may have protocols that occur more than once (e.g., IP in IP),
2264 * so we do indeed have to check all protocol subtrees, looking
2265 * for the parent protocol. That's why proto_find_protocol()
2266 * is not used --- it assumes a protocol occurs only once. */
2267 sinfo.traverse_func = get_finfo_ptr_array;
2268 g_node_traverse((GNode*)tree, G_IN_ORDER, G_TRAVERSE_ALL, 2,
2269 traverse_subtree_for_field, &sinfo);
2272 return sinfo.result.ptr_array;
2276 /* Dumps the contents of the registration database to stdout. An indepedent program can take
2277 * this output and format it into nice tables or HTML or whatever.
2279 * There is one record per line. Each record is either a protocol or a header
2280 * field, differentiated by the first field. The fields are tab-delimited.
2285 * Field 2 = protocol name
2286 * Field 3 = protocol abbreviation
2291 * Field 2 = field name
2292 * Field 3 = field abbreviation
2293 * Field 4 = type ( textual representation of the the ftenum type )
2294 * Field 5 = parent protocol abbreviation
2297 proto_registrar_dump(void)
2299 header_field_info *hfinfo, *parent_hfinfo;
2301 const char *enum_name;
2303 len = gpa_hfinfo->len;
2304 for (i = 0; i < len ; i++) {
2305 hfinfo = proto_registrar_get_nth(i);
2307 /* format for protocols */
2308 if (proto_registrar_is_protocol(i)) {
2309 printf("P\t%s\t%s\n", hfinfo->name, hfinfo->abbrev);
2311 /* format for header fields */
2313 parent_hfinfo = proto_registrar_get_nth(hfinfo->parent);
2314 g_assert(parent_hfinfo);
2316 switch(hfinfo->type) {
2318 enum_name = "FT_NONE";
2321 enum_name = "FT_BOOLEAN";
2324 enum_name = "FT_UINT8";
2327 enum_name = "FT_UINT16";
2330 enum_name = "FT_UINT24";
2333 enum_name = "FT_UINT32";
2336 enum_name = "FT_INT8";
2339 enum_name = "FT_INT16";
2342 enum_name = "FT_INT24";
2345 enum_name = "FT_INT32";
2348 enum_name = "FT_DOUBLE";
2350 case FT_ABSOLUTE_TIME:
2351 enum_name = "FT_ABSOLUTE_TIME";
2353 case FT_RELATIVE_TIME:
2354 enum_name = "FT_RELATIVE_TIME";
2356 case FT_NSTRING_UINT8:
2357 enum_name = "FT_NSTRING_UINT8";
2360 enum_name = "FT_STRING";
2363 enum_name = "FT_ETHER";
2366 enum_name = "FT_BYTES";
2369 enum_name = "FT_IPv4";
2372 enum_name = "FT_IPv6";
2375 enum_name = "FT_IPXNET";
2378 enum_name = "FT_TEXT_ONLY";
2381 g_assert_not_reached();
2384 printf("F\t%s\t%s\t%s\t%s\n", hfinfo->name, hfinfo->abbrev,
2385 enum_name,parent_hfinfo->abbrev);