2 * Routines for protocol tree
4 * $Id: proto.c,v 1.52 2000/01/22 04:59:55 guy 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>
44 #ifdef NEED_SNPRINTF_H
45 # include "snprintf.h"
64 #ifndef __REGISTER_H__
68 #include "packet-ipv6.h"
70 #define cVALS(x) (const value_string*)(x)
73 proto_tree_free_node(GNode *node, gpointer data);
75 static struct header_field_info*
76 find_hfinfo_record(int hfindex);
79 proto_tree_add_item_value(proto_tree *tree, int hfindex, gint start,
80 gint length, int include_format, int visible, va_list ap);
82 static void fill_label_boolean(field_info *fi, gchar *label_str);
83 static void fill_label_uint(field_info *fi, gchar *label_str);
84 static void fill_label_enumerated_uint(field_info *fi, gchar *label_str);
85 static void fill_label_enumerated_bitfield(field_info *fi, gchar *label_str);
86 static void fill_label_numeric_bitfield(field_info *fi, gchar *label_str);
87 static void fill_label_int(field_info *fi, gchar *label_str);
88 static void fill_label_enumerated_int(field_info *fi, gchar *label_str);
90 static int hfinfo_bitwidth(header_field_info *hfinfo);
91 static char* hfinfo_uint_vals_format(header_field_info *hfinfo);
92 static char* hfinfo_uint_format(header_field_info *hfinfo);
93 static char* hfinfo_int_vals_format(header_field_info *hfinfo);
94 static char* hfinfo_int_format(header_field_info *hfinfo);
96 static gboolean check_for_protocol_or_field_id(GNode *node, gpointer data);
97 static gboolean check_for_field_within_protocol(GNode *node, gpointer data);
99 static int proto_register_field_init(header_field_info *hfinfo, int parent);
101 /* special-case header field used within proto.c */
102 int hf_text_only = 1;
104 /* Contains information about protocols and header fields. Used when
105 * dissectors register their data */
106 GMemChunk *gmc_hfinfo = NULL;
108 /* Contains information about a field when a dissector calls
109 * proto_tree_add_item. */
110 GMemChunk *gmc_field_info = NULL;
112 /* String space for protocol and field items for the GUI */
113 GMemChunk *gmc_item_labels = NULL;
115 /* List which stores protocols and fields that have been registered */
116 GPtrArray *gpa_hfinfo = NULL;
118 /* Points to the first element of an array of Booleans, indexed by
119 a subtree item type; that array element is TRUE if subtrees of
120 an item of that type are to be expanded. */
121 gboolean *tree_is_expanded;
123 /* Number of elements in that array. */
126 /* Is the parsing being done for a visible proto_tree or an invisible one?
127 * By setting this correctly, the proto_tree creation is sped up by not
128 * having to call vsnprintf and copy strings around.
130 gboolean proto_tree_is_visible = TRUE;
132 /* initialize data structures and register protocols and fields */
136 static hf_register_info hf[] = {
138 { "Text", "text", FT_TEXT_ONLY, BASE_NONE, NULL, 0x0,
143 g_mem_chunk_destroy(gmc_hfinfo);
145 g_mem_chunk_destroy(gmc_field_info);
147 g_mem_chunk_destroy(gmc_item_labels);
149 g_ptr_array_free(gpa_hfinfo, FALSE);
150 if (tree_is_expanded != NULL)
151 g_free(tree_is_expanded);
153 gmc_hfinfo = g_mem_chunk_new("gmc_hfinfo",
154 sizeof(struct header_field_info), 50 * sizeof(struct
155 header_field_info), G_ALLOC_ONLY);
156 gmc_field_info = g_mem_chunk_new("gmc_field_info",
157 sizeof(struct field_info), 200 * sizeof(struct field_info),
159 gmc_item_labels = g_mem_chunk_new("gmc_item_labels",
160 ITEM_LABEL_LENGTH, 20 * ITEM_LABEL_LENGTH,
162 gpa_hfinfo = g_ptr_array_new();
164 /* Allocate "tree_is_expanded", with one element for ETT_NONE,
165 and initialize that element to FALSE. */
166 tree_is_expanded = g_malloc(sizeof (gint));
167 tree_is_expanded[0] = FALSE;
170 /* Have each dissector register its protocols and fields. */
171 register_all_protocols();
173 /* Register one special-case FT_TEXT_ONLY field for use when
174 converting ethereal to new-style proto_tree. These fields
175 are merely strings on the GUI tree; they are not filterable */
176 proto_register_field_array(-1, hf, array_length(hf));
178 /* We've assigned all the subtree type values; allocate the array
179 for them, and zero it out. */
180 tree_is_expanded = g_malloc(num_tree_types*sizeof (gint *));
181 memset(tree_is_expanded, '\0', num_tree_types*sizeof (gint *));
188 g_mem_chunk_destroy(gmc_hfinfo);
190 g_mem_chunk_destroy(gmc_field_info);
192 g_mem_chunk_destroy(gmc_item_labels);
194 g_ptr_array_free(gpa_hfinfo, FALSE);
197 /* frees the resources that the dissection a proto_tree uses */
199 proto_tree_free(proto_tree *tree)
201 g_node_traverse((GNode*)tree, G_IN_ORDER, G_TRAVERSE_ALL, -1,
202 proto_tree_free_node, NULL);
203 g_node_destroy((GNode*)tree);
207 proto_tree_free_node(GNode *node, gpointer data)
209 field_info *fi = (field_info*) (node->data);
212 if (fi->representation)
213 g_mem_chunk_free(gmc_item_labels, fi->representation);
214 if (fi->hfinfo->type == FT_STRING)
215 g_free(fi->value.string);
216 else if (fi->hfinfo->type == FT_BYTES)
217 g_free(fi->value.bytes);
218 g_mem_chunk_free(gmc_field_info, fi);
220 return FALSE; /* FALSE = do not end traversal of GNode tree */
223 /* Finds a record in the hf_info_records array. */
224 static struct header_field_info*
225 find_hfinfo_record(int hfindex)
227 g_assert(hfindex >= 0 && hfindex < gpa_hfinfo->len);
228 return g_ptr_array_index(gpa_hfinfo, hfindex);
232 proto_tree_add_item(proto_tree *tree, int hfindex, gint start, gint length, ...)
237 va_start(ap, length);
238 pi = proto_tree_add_item_value(tree, hfindex, start, length, 0, 1, ap);
245 proto_tree_add_item_hidden(proto_tree *tree, int hfindex, gint start, gint length, ...)
250 va_start(ap, length);
251 pi = proto_tree_add_item_value(tree, hfindex, start, length, 0, 0, ap);
258 proto_tree_add_item_format(proto_tree *tree, int hfindex, gint start, gint length, ...)
263 va_start(ap, length);
264 pi = proto_tree_add_item_value(tree, hfindex, start, length, 1, 1, ap);
271 proto_tree_add_notext(proto_tree *tree, gint start, gint length, ...)
276 va_start(ap, length);
277 pi = proto_tree_add_item_value(tree, hf_text_only, start, length, 0, 1, ap);
284 proto_tree_add_text(proto_tree *tree, gint start, gint length, ...)
289 va_start(ap, length);
290 pi = proto_tree_add_item_value(tree, hf_text_only, start, length, 1, 1, ap);
297 proto_tree_add_item_value(proto_tree *tree, int hfindex, gint start,
298 gint length, int include_format, int visible, va_list ap)
303 header_field_info *hfinfo;
308 /* either visibility flag can nullify the other */
309 visible = proto_tree_is_visible && visible;
311 fi = g_mem_chunk_alloc(gmc_field_info);
313 fi->hfinfo = find_hfinfo_record(hfindex);
314 g_assert(fi->hfinfo != NULL);
317 fi->tree_type = ETT_NONE;
318 fi->visible = visible;
320 /* for convenience */
323 /* from the stdarg man page on Solaris 2.6:
325 It is up to the calling routine to specify in some manner
326 how many arguments there are, since it is not always possi-
327 ble to determine the number of arguments from the stack
328 frame. For example, execl is passed a zero pointer to sig-
329 nal the end of the list. printf can tell how many arguments
330 there are by the format. It is non-portable to specify a
331 second argument of char, short, or float to va_arg, because
332 arguments seen by the called function are not char, short,
333 or float. C converts char and short arguments to int and
334 converts float arguments to double before passing them to a
337 switch(hfinfo->type) {
339 junk = va_arg(ap, guint8*);
343 /* This g_malloc'ed memory is freed in
344 proto_tree_free_node() */
345 fi->value.bytes = (guint8 *)g_malloc(length);
346 memcpy(fi->value.bytes, va_arg(ap, guint8*), length);
358 fi->value.numeric = va_arg(ap, unsigned int);
359 if (hfinfo->bitmask) {
360 /* Mask out irrelevant portions */
361 fi->value.numeric &= hfinfo->bitmask;
364 if (hfinfo->bitshift > 0) {
365 fi->value.numeric >>= hfinfo->bitshift;
371 ipv4_addr_set_net_order_addr(&(fi->value.ipv4), va_arg(ap, unsigned int));
372 ipv4_addr_set_netmask_bits(&(fi->value.ipv4), 32);
376 fi->value.numeric = va_arg(ap, unsigned int);
380 memcpy(fi->value.ipv6, va_arg(ap, guint8*), 16);
384 fi->value.floating = va_arg(ap, double);
388 memcpy(fi->value.ether, va_arg(ap, guint8*), 6);
391 case FT_ABSOLUTE_TIME:
392 case FT_RELATIVE_TIME:
393 memcpy(&fi->value.time, va_arg(ap, struct timeval*),
394 sizeof(struct timeval));
398 /* This g_strdup'ed memory is freed in proto_tree_free_node() */
399 fi->value.string = g_strdup(va_arg(ap, char*));
407 g_error("hfinfo->type %d not handled\n", hfinfo->type);
411 pi = (proto_item*) g_node_new(fi);
412 g_node_append((GNode*)tree, (GNode*)pi);
414 /* are there any formatting arguments? */
415 if (visible && include_format) {
416 format = va_arg(ap, char*);
417 fi->representation = g_mem_chunk_alloc(gmc_item_labels);
418 vsnprintf(fi->representation, ITEM_LABEL_LENGTH,
422 fi->representation = NULL;
429 proto_item_set_text(proto_item *pi, ...)
431 field_info *fi = (field_info*) (((GNode*)pi)->data);
435 if (fi->representation)
436 g_mem_chunk_free(gmc_item_labels, fi->representation);
438 fi->representation = g_mem_chunk_alloc(gmc_item_labels);
440 format = va_arg(ap, char*);
441 vsnprintf(fi->representation, ITEM_LABEL_LENGTH,
447 proto_item_set_len(proto_item *pi, gint length)
449 field_info *fi = (field_info*) (((GNode*)pi)->data);
454 proto_tree_create_root(void)
456 return (proto_tree*) g_node_new(NULL);
460 proto_item_add_subtree(proto_item *pi, gint idx) {
461 field_info *fi = (field_info*) (((GNode*)pi)->data);
462 g_assert(idx >= 0 && idx < num_tree_types);
464 return (proto_tree*) pi;
469 proto_register_protocol(char *name, char *abbrev)
471 struct header_field_info *hfinfo;
473 /* Here we do allocate a new header_field_info struct */
474 hfinfo = g_mem_chunk_alloc(gmc_hfinfo);
476 hfinfo->abbrev = abbrev;
477 hfinfo->type = FT_NONE;
478 hfinfo->strings = NULL;
480 hfinfo->bitshift = 0;
482 hfinfo->parent = -1; /* this field differentiates protos and fields */
484 return proto_register_field_init(hfinfo, hfinfo->parent);
487 /* for use with static arrays only, since we don't allocate our own copies
488 of the header_field_info struct contained withing the hf_register_info struct */
490 proto_register_field_array(int parent, hf_register_info *hf, int num_records)
493 hf_register_info *ptr = hf;
495 for (i = 0; i < num_records; i++, ptr++) {
496 field_id = proto_register_field_init(&ptr->hfinfo, parent);
497 *ptr->p_id = field_id;
502 proto_register_field_init(header_field_info *hfinfo, int parent)
504 /* These types of fields are allowed to have value_strings or true_false_strings */
505 g_assert((hfinfo->strings == NULL) || (
506 (hfinfo->type == FT_UINT8) ||
507 (hfinfo->type == FT_UINT16) ||
508 (hfinfo->type == FT_UINT24) ||
509 (hfinfo->type == FT_UINT32) ||
510 (hfinfo->type == FT_INT8) ||
511 (hfinfo->type == FT_INT16) ||
512 (hfinfo->type == FT_INT24) ||
513 (hfinfo->type == FT_INT32) ||
514 (hfinfo->type == FT_BOOLEAN) ));
516 /* if this is a bitfield, compure bitshift */
517 if (hfinfo->bitmask) {
518 while ((hfinfo->bitmask & (1 << hfinfo->bitshift)) == 0)
522 hfinfo->parent = parent;
524 /* if we always add and never delete, then id == len - 1 is correct */
525 g_ptr_array_add(gpa_hfinfo, hfinfo);
526 hfinfo->id = gpa_hfinfo->len - 1;
531 proto_register_subtree_array(gint **indices, int num_indices)
534 gint **ptr = indices;
537 * Add "num_indices" elements to "tree_is_expanded".
539 tree_is_expanded = g_realloc(tree_is_expanded,
540 (num_tree_types + num_indices)*sizeof (gint));
543 * Assign "num_indices" subtree numbers starting at "num_tree_types",
544 * returning the indices through the pointers in the array whose
545 * first element is pointed to by "indices", set to FALSE the
546 * elements to which those subtree numbers refer, and update
547 * "num_tree_types" appropriately.
549 for (i = 0; i < num_indices; i++, ptr++, num_tree_types++) {
550 tree_is_expanded[num_tree_types] = FALSE;
551 **ptr = num_tree_types;
556 proto_item_fill_label(field_info *fi, gchar *label_str)
558 struct header_field_info *hfinfo = fi->hfinfo;
559 guint32 n_addr; /* network-order IPv4 address */
561 switch(hfinfo->type) {
563 snprintf(label_str, ITEM_LABEL_LENGTH,
568 fill_label_boolean(fi, label_str);
572 snprintf(label_str, ITEM_LABEL_LENGTH,
573 "%s: %s", hfinfo->name,
574 bytes_to_str(fi->value.bytes, fi->length));
577 /* Four types of integers to take care of:
578 * Bitfield, with val_string
579 * Bitfield, w/o val_string
580 * Non-bitfield, with val_string
581 * Non-bitfield, w/o val_string
587 if (hfinfo->bitmask) {
588 if (hfinfo->strings) {
589 fill_label_enumerated_bitfield(fi, label_str);
592 fill_label_numeric_bitfield(fi, label_str);
596 if (hfinfo->strings) {
597 fill_label_enumerated_uint(fi, label_str);
600 fill_label_uint(fi, label_str);
609 g_assert(!hfinfo->bitmask);
610 if (hfinfo->strings) {
611 fill_label_enumerated_int(fi, label_str);
614 fill_label_int(fi, label_str);
619 snprintf(label_str, ITEM_LABEL_LENGTH,
620 "%s: %g", fi->hfinfo->name,
624 case FT_ABSOLUTE_TIME:
625 snprintf(label_str, ITEM_LABEL_LENGTH,
626 "%s: %s", fi->hfinfo->name,
627 abs_time_to_str(&fi->value.time));
630 case FT_RELATIVE_TIME:
631 snprintf(label_str, ITEM_LABEL_LENGTH,
632 "%s: %s seconds", fi->hfinfo->name,
633 rel_time_to_str(&fi->value.time));
637 snprintf(label_str, ITEM_LABEL_LENGTH,
638 "%s: 0x%08X (%s)", fi->hfinfo->name,
639 fi->value.numeric, get_ipxnet_name(fi->value.numeric));
643 snprintf(label_str, ITEM_LABEL_LENGTH,
644 "%s: %s (%s)", fi->hfinfo->name,
645 ether_to_str(fi->value.ether),
646 get_ether_name(fi->value.ether));
650 n_addr = ipv4_get_net_order_addr(&fi->value.ipv4);
651 snprintf(label_str, ITEM_LABEL_LENGTH,
652 "%s: %s (%s)", fi->hfinfo->name,
653 get_hostname(n_addr),
654 ip_to_str((guint8*)&n_addr));
658 snprintf(label_str, ITEM_LABEL_LENGTH,
659 "%s: %s (%s)", fi->hfinfo->name,
660 get_hostname6((struct e_in6_addr *)fi->value.ipv6),
661 ip6_to_str((struct e_in6_addr*)fi->value.ipv6));
665 snprintf(label_str, ITEM_LABEL_LENGTH,
666 "%s: %s", fi->hfinfo->name, fi->value.string);
670 g_error("hfinfo->type %d not handled\n", fi->hfinfo->type);
676 fill_label_boolean(field_info *fi, gchar *label_str)
679 int bitfield_byte_length = 0, bitwidth;
680 guint32 unshifted_value;
682 struct header_field_info *hfinfo = fi->hfinfo;
683 struct true_false_string default_tf = { "True", "False" };
684 struct true_false_string *tfstring = &default_tf;
686 if (hfinfo->strings) {
687 tfstring = (struct true_false_string*) hfinfo->strings;
690 if (hfinfo->bitmask) {
691 /* Figure out the bit width */
692 bitwidth = hfinfo_bitwidth(hfinfo);
695 unshifted_value = fi->value.numeric;
696 if (hfinfo->bitshift > 0) {
697 unshifted_value <<= hfinfo->bitshift;
700 /* Create the bitfield first */
701 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
702 bitfield_byte_length = p - label_str;
705 /* Fill in the textual info */
706 snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
707 "%s: %s", hfinfo->name,
708 fi->value.numeric ? tfstring->true_string : tfstring->false_string);
712 /* Fills data for bitfield ints with val_strings */
714 fill_label_enumerated_bitfield(field_info *fi, gchar *label_str)
716 char *format = NULL, *p;
717 int bitfield_byte_length, bitwidth;
718 guint32 unshifted_value;
720 struct header_field_info *hfinfo = fi->hfinfo;
722 /* Figure out the bit width */
723 bitwidth = hfinfo_bitwidth(hfinfo);
725 /* Pick the proper format string */
726 format = hfinfo_uint_vals_format(hfinfo);
729 unshifted_value = fi->value.numeric;
730 if (hfinfo->bitshift > 0) {
731 unshifted_value <<= hfinfo->bitshift;
734 /* Create the bitfield first */
735 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
736 bitfield_byte_length = p - label_str;
738 /* Fill in the textual info using stored (shifted) value */
739 snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
740 format, hfinfo->name,
741 val_to_str(fi->value.numeric, cVALS(hfinfo->strings), "Unknown"),
746 fill_label_numeric_bitfield(field_info *fi, gchar *label_str)
748 char *format = NULL, *p;
749 int bitfield_byte_length, bitwidth;
750 guint32 unshifted_value;
752 struct header_field_info *hfinfo = fi->hfinfo;
754 /* Figure out the bit width */
755 bitwidth = hfinfo_bitwidth(hfinfo);
757 /* Pick the proper format string */
758 format = hfinfo_uint_format(hfinfo);
761 unshifted_value = fi->value.numeric;
762 if (hfinfo->bitshift > 0) {
763 unshifted_value <<= hfinfo->bitshift;
766 /* Create the bitfield using */
767 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
768 bitfield_byte_length = p - label_str;
770 /* Fill in the textual info using stored (shifted) value */
771 snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
772 format, hfinfo->name, fi->value.numeric);
776 fill_label_enumerated_uint(field_info *fi, gchar *label_str)
779 struct header_field_info *hfinfo = fi->hfinfo;
781 /* Pick the proper format string */
782 format = hfinfo_uint_vals_format(hfinfo);
784 /* Fill in the textual info */
785 snprintf(label_str, ITEM_LABEL_LENGTH,
786 format, hfinfo->name,
787 val_to_str(fi->value.numeric, cVALS(hfinfo->strings), "Unknown"),
792 fill_label_uint(field_info *fi, gchar *label_str)
795 struct header_field_info *hfinfo = fi->hfinfo;
797 /* Pick the proper format string */
798 format = hfinfo_uint_format(hfinfo);
800 /* Fill in the textual info */
801 snprintf(label_str, ITEM_LABEL_LENGTH,
802 format, hfinfo->name, fi->value.numeric);
806 fill_label_enumerated_int(field_info *fi, gchar *label_str)
809 struct header_field_info *hfinfo = fi->hfinfo;
811 /* Pick the proper format string */
812 format = hfinfo_int_vals_format(hfinfo);
814 /* Fill in the textual info */
815 snprintf(label_str, ITEM_LABEL_LENGTH,
816 format, hfinfo->name,
817 val_to_str(fi->value.numeric, cVALS(hfinfo->strings), "Unknown"),
822 fill_label_int(field_info *fi, gchar *label_str)
825 struct header_field_info *hfinfo = fi->hfinfo;
827 /* Pick the proper format string */
828 format = hfinfo_int_format(hfinfo);
830 /* Fill in the textual info */
831 snprintf(label_str, ITEM_LABEL_LENGTH,
832 format, hfinfo->name, fi->value.numeric);
836 hfinfo_bitwidth(header_field_info *hfinfo)
840 if (!hfinfo->bitmask) {
844 switch(hfinfo->type) {
862 bitwidth = hfinfo->display; /* hacky? :) */
865 g_assert_not_reached();
872 hfinfo_uint_vals_format(header_field_info *hfinfo)
876 switch(hfinfo->display) {
879 case BASE_OCT: /* I'm lazy */
880 case BASE_BIN: /* I'm lazy */
881 format = "%s: %s (%u)";
884 switch(hfinfo->type) {
886 format = "%s: %s (0x%02x)";
889 format = "%s: %s (0x%04x)";
892 format = "%s: %s (0x%06x)";
895 format = "%s: %s (0x%08x)";
898 g_assert_not_reached();
903 g_assert_not_reached();
910 hfinfo_uint_format(header_field_info *hfinfo)
914 /* Pick the proper format string */
915 switch(hfinfo->display) {
918 case BASE_OCT: /* I'm lazy */
919 case BASE_BIN: /* I'm lazy */
923 switch(hfinfo->type) {
925 format = "%s: 0x%02x";
928 format = "%s: 0x%04x";
931 format = "%s: 0x%06x";
934 format = "%s: 0x%08x";
937 g_assert_not_reached();
942 g_assert_not_reached();
949 hfinfo_int_vals_format(header_field_info *hfinfo)
953 switch(hfinfo->display) {
956 case BASE_OCT: /* I'm lazy */
957 case BASE_BIN: /* I'm lazy */
958 format = "%s: %s (%d)";
961 switch(hfinfo->type) {
963 format = "%s: %s (0x%02x)";
966 format = "%s: %s (0x%04x)";
969 format = "%s: %s (0x%06x)";
972 format = "%s: %s (0x%08x)";
975 g_assert_not_reached();
980 g_assert_not_reached();
987 hfinfo_int_format(header_field_info *hfinfo)
991 /* Pick the proper format string */
992 switch(hfinfo->display) {
995 case BASE_OCT: /* I'm lazy */
996 case BASE_BIN: /* I'm lazy */
1000 switch(hfinfo->type) {
1002 format = "%s: 0x%02x";
1005 format = "%s: 0x%04x";
1008 format = "%s: 0x%06x";
1011 format = "%s: 0x%08x";
1014 g_assert_not_reached();
1019 g_assert_not_reached();
1028 proto_registrar_n(void)
1030 return gpa_hfinfo->len;
1034 proto_registrar_get_name(int n)
1036 struct header_field_info *hfinfo;
1037 hfinfo = find_hfinfo_record(n);
1039 return hfinfo->name;
1044 proto_registrar_get_abbrev(int n)
1046 struct header_field_info *hfinfo;
1048 hfinfo = find_hfinfo_record(n);
1050 return hfinfo->abbrev;
1056 proto_registrar_get_ftype(int n)
1058 struct header_field_info *hfinfo;
1060 hfinfo = find_hfinfo_record(n);
1062 return hfinfo->type;
1068 proto_registrar_get_parent(int n)
1070 struct header_field_info *hfinfo;
1072 hfinfo = find_hfinfo_record(n);
1074 return hfinfo->parent;
1080 proto_registrar_is_protocol(int n)
1082 struct header_field_info *hfinfo;
1084 hfinfo = find_hfinfo_record(n);
1086 return (hfinfo->parent == -1 ? TRUE : FALSE);
1091 /* Returns length of field in packet (not necessarily the length
1092 * in our internal representation, as in the case of IPv4).
1093 * 0 means undeterminable at time of registration
1094 * -1 means the field is not registered. */
1096 proto_registrar_get_length(int n)
1098 struct header_field_info *hfinfo;
1100 hfinfo = find_hfinfo_record(n);
1104 switch (hfinfo->type) {
1105 case FT_TEXT_ONLY: /* not filterable */
1106 case NUM_FIELD_TYPES: /* satisfy picky compilers */
1114 case FT_ABSOLUTE_TIME:
1115 case FT_RELATIVE_TIME:
1142 g_assert_not_reached();
1146 /* Looks for a protocol or a field in a proto_tree. Returns TRUE if
1147 * it exists anywhere, or FALSE if it exists nowhere. */
1149 proto_check_for_protocol_or_field(proto_tree* tree, int id)
1151 proto_tree_search_info sinfo;
1154 sinfo.result.node = NULL;
1156 sinfo.traverse_func = NULL;
1158 /* do a quicker check if target is a protocol */
1159 if (proto_registrar_is_protocol(id) == TRUE) {
1160 proto_find_protocol_multi(tree, id, &check_for_protocol_or_field_id, &sinfo);
1163 /* find the field's parent protocol */
1164 sinfo.parent = proto_registrar_get_parent(id);
1166 /* Go through each protocol subtree, checking if the protocols
1167 * is the parent protocol of the field that we're looking for.
1168 * We may have protocols that occur more than once (e.g., IP in IP),
1169 * so we do indeed have to check all protocol subtrees, looking
1170 * for the parent protocol. That's why proto_find_protocol()
1171 * is not used --- it assumes a protocol occurs only once. */
1172 g_node_traverse((GNode*)tree, G_IN_ORDER, G_TRAVERSE_ALL, 2,
1173 check_for_field_within_protocol, &sinfo);
1176 if (sinfo.result.node)
1183 check_for_protocol_or_field_id(GNode *node, gpointer data)
1185 field_info *fi = (field_info*) (node->data);
1186 proto_tree_search_info *sinfo = (proto_tree_search_info*) data;
1188 if (fi) { /* !fi == the top most container node which holds nothing */
1189 if (fi->hfinfo->id == sinfo->target) {
1190 sinfo->result.node = node;
1191 return TRUE; /* halt traversal */
1194 return FALSE; /* keep traversing */
1198 check_for_field_within_protocol(GNode *node, gpointer data)
1200 field_info *fi = (field_info*) (node->data);
1201 proto_tree_search_info *sinfo = (proto_tree_search_info*) data;
1203 if (fi) { /* !fi == the top most container node which holds nothing */
1204 if (fi->hfinfo->id == sinfo->parent) {
1205 g_node_traverse(node, G_IN_ORDER, G_TRAVERSE_ALL, -1,
1206 check_for_protocol_or_field_id, sinfo);
1207 if (sinfo->result.node)
1208 return TRUE; /* halt traversal */
1211 return FALSE; /* keep traversing */
1214 /* Looks for a protocol at the top layer of the tree. The protocol can occur
1215 * more than once, for those encapsulated protocols. For each protocol subtree
1216 * that is found, the callback function is called.
1219 proto_find_protocol_multi(proto_tree* tree, int target, GNodeTraverseFunc callback,
1220 proto_tree_search_info *sinfo)
1222 g_assert(callback != NULL);
1223 g_node_traverse((GNode*)tree, G_IN_ORDER, G_TRAVERSE_ALL, 2, callback, (gpointer*)sinfo);
1226 /* Simple wrappter to traverse all nodes, calling the sinfo traverse function with sinfo as an arg */
1228 proto_get_field_values(proto_tree* subtree, proto_tree_search_info *sinfo)
1230 /* Don't try to check value of top-level NULL GNode */
1231 if (!((GNode*)subtree)->data) {
1232 return FALSE; /* don't halt */
1234 g_node_traverse((GNode*)subtree, G_IN_ORDER, G_TRAVERSE_ALL, -1, sinfo->traverse_func, (gpointer*)sinfo);
1235 return FALSE; /* don't halt */
1238 /* Dumps the contents of the registration database to stdout. An indepedent program can take
1239 * this output and format it into nice tables or HTML or whatever.
1241 * There is one record per line. Each record is either a protocol or a header
1242 * field, differentiated by the first field. The fields are tab-delimited.
1247 * Field 2 = protocol name
1248 * Field 3 = protocol abbreviation
1253 * Field 2 = field name
1254 * Field 3 = field abbreviation
1255 * Field 4 = type ( textual representation of the the ftenum type )
1256 * Field 5 = parent protocol abbreviation
1259 proto_registrar_dump(void)
1261 header_field_info *hfinfo, *parent_hfinfo;
1263 const char *enum_name;
1265 len = gpa_hfinfo->len;
1266 for (i = 0; i < len ; i++) {
1267 hfinfo = find_hfinfo_record(i);
1269 /* format for protocols */
1270 if (proto_registrar_is_protocol(i)) {
1271 printf("P\t%s\t%s\n", hfinfo->name, hfinfo->abbrev);
1273 /* format for header fields */
1275 parent_hfinfo = find_hfinfo_record(hfinfo->parent);
1276 g_assert(parent_hfinfo);
1278 switch(hfinfo->type) {
1280 enum_name = "FT_NONE";
1283 enum_name = "FT_BOOLEAN";
1286 enum_name = "FT_UINT8";
1289 enum_name = "FT_UINT16";
1292 enum_name = "FT_UINT24";
1295 enum_name = "FT_UINT32";
1298 enum_name = "FT_INT8";
1301 enum_name = "FT_INT16";
1304 enum_name = "FT_INT24";
1307 enum_name = "FT_INT32";
1310 enum_name = "FT_DOUBLE";
1312 case FT_ABSOLUTE_TIME:
1313 enum_name = "FT_ABSOLUTE_TIME";
1315 case FT_RELATIVE_TIME:
1316 enum_name = "FT_RELATIVE_TIME";
1319 enum_name = "FT_STRING";
1322 enum_name = "FT_ETHER";
1325 enum_name = "FT_BYTES";
1328 enum_name = "FT_IPv4";
1331 enum_name = "FT_IPv6";
1334 enum_name = "FT_IPXNET";
1337 enum_name = "FT_TEXT_ONLY";
1340 enum_name = "UNKNOWN";
1343 printf("F\t%s\t%s\t%s\t%s\n", hfinfo->name, hfinfo->abbrev,
1344 enum_name,parent_hfinfo->abbrev);