2 * Routines for protocol tree
4 * $Id: proto.c,v 1.51 1999/12/05 02:33:52 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_text(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, 1, 1, ap);
284 proto_tree_add_item_value(proto_tree *tree, int hfindex, gint start,
285 gint length, int include_format, int visible, va_list ap)
290 header_field_info *hfinfo;
295 /* either visibility flag can nullify the other */
296 visible = proto_tree_is_visible && visible;
298 fi = g_mem_chunk_alloc(gmc_field_info);
300 fi->hfinfo = find_hfinfo_record(hfindex);
301 g_assert(fi->hfinfo != NULL);
304 fi->tree_type = ETT_NONE;
305 fi->visible = visible;
307 /* for convenience */
310 /* from the stdarg man page on Solaris 2.6:
312 It is up to the calling routine to specify in some manner
313 how many arguments there are, since it is not always possi-
314 ble to determine the number of arguments from the stack
315 frame. For example, execl is passed a zero pointer to sig-
316 nal the end of the list. printf can tell how many arguments
317 there are by the format. It is non-portable to specify a
318 second argument of char, short, or float to va_arg, because
319 arguments seen by the called function are not char, short,
320 or float. C converts char and short arguments to int and
321 converts float arguments to double before passing them to a
324 switch(hfinfo->type) {
326 junk = va_arg(ap, guint8*);
330 /* This g_malloc'ed memory is freed in
331 proto_tree_free_node() */
332 fi->value.bytes = (guint8 *)g_malloc(length);
333 memcpy(fi->value.bytes, va_arg(ap, guint8*), length);
345 fi->value.numeric = va_arg(ap, unsigned int);
346 if (hfinfo->bitmask) {
347 /* Mask out irrelevant portions */
348 fi->value.numeric &= hfinfo->bitmask;
351 if (hfinfo->bitshift > 0) {
352 fi->value.numeric >>= hfinfo->bitshift;
358 ipv4_addr_set_net_order_addr(&(fi->value.ipv4), va_arg(ap, unsigned int));
359 ipv4_addr_set_netmask_bits(&(fi->value.ipv4), 32);
363 fi->value.numeric = va_arg(ap, unsigned int);
367 memcpy(fi->value.ipv6, va_arg(ap, guint8*), 16);
371 fi->value.floating = va_arg(ap, double);
375 memcpy(fi->value.ether, va_arg(ap, guint8*), 6);
378 case FT_ABSOLUTE_TIME:
379 case FT_RELATIVE_TIME:
380 memcpy(&fi->value.time, va_arg(ap, struct timeval*),
381 sizeof(struct timeval));
385 /* This g_strdup'ed memory is freed in proto_tree_free_node() */
386 fi->value.string = g_strdup(va_arg(ap, char*));
394 g_error("hfinfo->type %d not handled\n", hfinfo->type);
398 pi = (proto_item*) g_node_new(fi);
399 g_node_append((GNode*)tree, (GNode*)pi);
401 /* are there any formatting arguments? */
402 if (visible && include_format) {
403 fi->representation = g_mem_chunk_alloc(gmc_item_labels);
404 format = va_arg(ap, char*);
405 vsnprintf(fi->representation, ITEM_LABEL_LENGTH,
409 fi->representation = NULL;
416 proto_item_set_len(proto_item *pi, gint length)
418 field_info *fi = (field_info*) (((GNode*)pi)->data);
423 proto_tree_create_root(void)
425 return (proto_tree*) g_node_new(NULL);
429 proto_item_add_subtree(proto_item *pi, gint idx) {
430 field_info *fi = (field_info*) (((GNode*)pi)->data);
431 g_assert(idx >= 0 && idx < num_tree_types);
433 return (proto_tree*) pi;
438 proto_register_protocol(char *name, char *abbrev)
440 struct header_field_info *hfinfo;
442 /* Here we do allocate a new header_field_info struct */
443 hfinfo = g_mem_chunk_alloc(gmc_hfinfo);
445 hfinfo->abbrev = abbrev;
446 hfinfo->type = FT_NONE;
447 hfinfo->strings = NULL;
449 hfinfo->bitshift = 0;
451 hfinfo->parent = -1; /* this field differentiates protos and fields */
453 return proto_register_field_init(hfinfo, hfinfo->parent);
456 /* for use with static arrays only, since we don't allocate our own copies
457 of the header_field_info struct contained withing the hf_register_info struct */
459 proto_register_field_array(int parent, hf_register_info *hf, int num_records)
462 hf_register_info *ptr = hf;
464 for (i = 0; i < num_records; i++, ptr++) {
465 field_id = proto_register_field_init(&ptr->hfinfo, parent);
466 *ptr->p_id = field_id;
471 proto_register_field_init(header_field_info *hfinfo, int parent)
473 /* These types of fields are allowed to have value_strings or true_false_strings */
474 g_assert((hfinfo->strings == NULL) || (
475 (hfinfo->type == FT_UINT8) ||
476 (hfinfo->type == FT_UINT16) ||
477 (hfinfo->type == FT_UINT24) ||
478 (hfinfo->type == FT_UINT32) ||
479 (hfinfo->type == FT_INT8) ||
480 (hfinfo->type == FT_INT16) ||
481 (hfinfo->type == FT_INT24) ||
482 (hfinfo->type == FT_INT32) ||
483 (hfinfo->type == FT_BOOLEAN) ));
485 /* if this is a bitfield, compure bitshift */
486 if (hfinfo->bitmask) {
487 while ((hfinfo->bitmask & (1 << hfinfo->bitshift)) == 0)
491 hfinfo->parent = parent;
493 /* if we always add and never delete, then id == len - 1 is correct */
494 g_ptr_array_add(gpa_hfinfo, hfinfo);
495 hfinfo->id = gpa_hfinfo->len - 1;
500 proto_register_subtree_array(gint **indices, int num_indices)
503 gint **ptr = indices;
506 * Add "num_indices" elements to "tree_is_expanded".
508 tree_is_expanded = g_realloc(tree_is_expanded,
509 (num_tree_types + num_indices)*sizeof (gint));
512 * Assign "num_indices" subtree numbers starting at "num_tree_types",
513 * returning the indices through the pointers in the array whose
514 * first element is pointed to by "indices", set to FALSE the
515 * elements to which those subtree numbers refer, and update
516 * "num_tree_types" appropriately.
518 for (i = 0; i < num_indices; i++, ptr++, num_tree_types++) {
519 tree_is_expanded[num_tree_types] = FALSE;
520 **ptr = num_tree_types;
525 proto_item_fill_label(field_info *fi, gchar *label_str)
527 struct header_field_info *hfinfo = fi->hfinfo;
528 guint32 n_addr; /* network-order IPv4 address */
530 switch(hfinfo->type) {
532 snprintf(label_str, ITEM_LABEL_LENGTH,
537 fill_label_boolean(fi, label_str);
541 snprintf(label_str, ITEM_LABEL_LENGTH,
542 "%s: %s", hfinfo->name,
543 bytes_to_str(fi->value.bytes, fi->length));
546 /* Four types of integers to take care of:
547 * Bitfield, with val_string
548 * Bitfield, w/o val_string
549 * Non-bitfield, with val_string
550 * Non-bitfield, w/o val_string
556 if (hfinfo->bitmask) {
557 if (hfinfo->strings) {
558 fill_label_enumerated_bitfield(fi, label_str);
561 fill_label_numeric_bitfield(fi, label_str);
565 if (hfinfo->strings) {
566 fill_label_enumerated_uint(fi, label_str);
569 fill_label_uint(fi, label_str);
578 g_assert(!hfinfo->bitmask);
579 if (hfinfo->strings) {
580 fill_label_enumerated_int(fi, label_str);
583 fill_label_int(fi, label_str);
588 snprintf(label_str, ITEM_LABEL_LENGTH,
589 "%s: %g", fi->hfinfo->name,
593 case FT_ABSOLUTE_TIME:
594 snprintf(label_str, ITEM_LABEL_LENGTH,
595 "%s: %s", fi->hfinfo->name,
596 abs_time_to_str(&fi->value.time));
599 case FT_RELATIVE_TIME:
600 snprintf(label_str, ITEM_LABEL_LENGTH,
601 "%s: %s seconds", fi->hfinfo->name,
602 rel_time_to_str(&fi->value.time));
606 snprintf(label_str, ITEM_LABEL_LENGTH,
607 "%s: 0x%08X (%s)", fi->hfinfo->name,
608 fi->value.numeric, get_ipxnet_name(fi->value.numeric));
612 snprintf(label_str, ITEM_LABEL_LENGTH,
613 "%s: %s (%s)", fi->hfinfo->name,
614 ether_to_str(fi->value.ether),
615 get_ether_name(fi->value.ether));
619 n_addr = ipv4_get_net_order_addr(&fi->value.ipv4);
620 snprintf(label_str, ITEM_LABEL_LENGTH,
621 "%s: %s (%s)", fi->hfinfo->name,
622 get_hostname(n_addr),
623 ip_to_str((guint8*)&n_addr));
627 snprintf(label_str, ITEM_LABEL_LENGTH,
628 "%s: %s (%s)", fi->hfinfo->name,
629 get_hostname6((struct e_in6_addr *)fi->value.ipv6),
630 ip6_to_str((struct e_in6_addr*)fi->value.ipv6));
634 snprintf(label_str, ITEM_LABEL_LENGTH,
635 "%s: %s", fi->hfinfo->name, fi->value.string);
639 g_error("hfinfo->type %d not handled\n", fi->hfinfo->type);
645 fill_label_boolean(field_info *fi, gchar *label_str)
648 int bitfield_byte_length = 0, bitwidth;
649 guint32 unshifted_value;
651 struct header_field_info *hfinfo = fi->hfinfo;
652 struct true_false_string default_tf = { "True", "False" };
653 struct true_false_string *tfstring = &default_tf;
655 if (hfinfo->strings) {
656 tfstring = (struct true_false_string*) hfinfo->strings;
659 if (hfinfo->bitmask) {
660 /* Figure out the bit width */
661 bitwidth = hfinfo_bitwidth(hfinfo);
664 unshifted_value = fi->value.numeric;
665 if (hfinfo->bitshift > 0) {
666 unshifted_value <<= hfinfo->bitshift;
669 /* Create the bitfield first */
670 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
671 bitfield_byte_length = p - label_str;
674 /* Fill in the textual info */
675 snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
676 "%s: %s", hfinfo->name,
677 fi->value.numeric ? tfstring->true_string : tfstring->false_string);
681 /* Fills data for bitfield ints with val_strings */
683 fill_label_enumerated_bitfield(field_info *fi, gchar *label_str)
685 char *format = NULL, *p;
686 int bitfield_byte_length, bitwidth;
687 guint32 unshifted_value;
689 struct header_field_info *hfinfo = fi->hfinfo;
691 /* Figure out the bit width */
692 bitwidth = hfinfo_bitwidth(hfinfo);
694 /* Pick the proper format string */
695 format = hfinfo_uint_vals_format(hfinfo);
698 unshifted_value = fi->value.numeric;
699 if (hfinfo->bitshift > 0) {
700 unshifted_value <<= hfinfo->bitshift;
703 /* Create the bitfield first */
704 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
705 bitfield_byte_length = p - label_str;
707 /* Fill in the textual info using stored (shifted) value */
708 snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
709 format, hfinfo->name,
710 val_to_str(fi->value.numeric, cVALS(hfinfo->strings), "Unknown"),
715 fill_label_numeric_bitfield(field_info *fi, gchar *label_str)
717 char *format = NULL, *p;
718 int bitfield_byte_length, bitwidth;
719 guint32 unshifted_value;
721 struct header_field_info *hfinfo = fi->hfinfo;
723 /* Figure out the bit width */
724 bitwidth = hfinfo_bitwidth(hfinfo);
726 /* Pick the proper format string */
727 format = hfinfo_uint_format(hfinfo);
730 unshifted_value = fi->value.numeric;
731 if (hfinfo->bitshift > 0) {
732 unshifted_value <<= hfinfo->bitshift;
735 /* Create the bitfield using */
736 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
737 bitfield_byte_length = p - label_str;
739 /* Fill in the textual info using stored (shifted) value */
740 snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
741 format, hfinfo->name, fi->value.numeric);
745 fill_label_enumerated_uint(field_info *fi, gchar *label_str)
748 struct header_field_info *hfinfo = fi->hfinfo;
750 /* Pick the proper format string */
751 format = hfinfo_uint_vals_format(hfinfo);
753 /* Fill in the textual info */
754 snprintf(label_str, ITEM_LABEL_LENGTH,
755 format, hfinfo->name,
756 val_to_str(fi->value.numeric, cVALS(hfinfo->strings), "Unknown"),
761 fill_label_uint(field_info *fi, gchar *label_str)
764 struct header_field_info *hfinfo = fi->hfinfo;
766 /* Pick the proper format string */
767 format = hfinfo_uint_format(hfinfo);
769 /* Fill in the textual info */
770 snprintf(label_str, ITEM_LABEL_LENGTH,
771 format, hfinfo->name, fi->value.numeric);
775 fill_label_enumerated_int(field_info *fi, gchar *label_str)
778 struct header_field_info *hfinfo = fi->hfinfo;
780 /* Pick the proper format string */
781 format = hfinfo_int_vals_format(hfinfo);
783 /* Fill in the textual info */
784 snprintf(label_str, ITEM_LABEL_LENGTH,
785 format, hfinfo->name,
786 val_to_str(fi->value.numeric, cVALS(hfinfo->strings), "Unknown"),
791 fill_label_int(field_info *fi, gchar *label_str)
794 struct header_field_info *hfinfo = fi->hfinfo;
796 /* Pick the proper format string */
797 format = hfinfo_int_format(hfinfo);
799 /* Fill in the textual info */
800 snprintf(label_str, ITEM_LABEL_LENGTH,
801 format, hfinfo->name, fi->value.numeric);
805 hfinfo_bitwidth(header_field_info *hfinfo)
809 if (!hfinfo->bitmask) {
813 switch(hfinfo->type) {
831 bitwidth = hfinfo->display; /* hacky? :) */
834 g_assert_not_reached();
841 hfinfo_uint_vals_format(header_field_info *hfinfo)
845 switch(hfinfo->display) {
848 case BASE_OCT: /* I'm lazy */
849 case BASE_BIN: /* I'm lazy */
850 format = "%s: %s (%u)";
853 switch(hfinfo->type) {
855 format = "%s: %s (0x%02x)";
858 format = "%s: %s (0x%04x)";
861 format = "%s: %s (0x%06x)";
864 format = "%s: %s (0x%08x)";
867 g_assert_not_reached();
872 g_assert_not_reached();
879 hfinfo_uint_format(header_field_info *hfinfo)
883 /* Pick the proper format string */
884 switch(hfinfo->display) {
887 case BASE_OCT: /* I'm lazy */
888 case BASE_BIN: /* I'm lazy */
892 switch(hfinfo->type) {
894 format = "%s: 0x%02x";
897 format = "%s: 0x%04x";
900 format = "%s: 0x%06x";
903 format = "%s: 0x%08x";
906 g_assert_not_reached();
911 g_assert_not_reached();
918 hfinfo_int_vals_format(header_field_info *hfinfo)
922 switch(hfinfo->display) {
925 case BASE_OCT: /* I'm lazy */
926 case BASE_BIN: /* I'm lazy */
927 format = "%s: %s (%d)";
930 switch(hfinfo->type) {
932 format = "%s: %s (0x%02x)";
935 format = "%s: %s (0x%04x)";
938 format = "%s: %s (0x%06x)";
941 format = "%s: %s (0x%08x)";
944 g_assert_not_reached();
949 g_assert_not_reached();
956 hfinfo_int_format(header_field_info *hfinfo)
960 /* Pick the proper format string */
961 switch(hfinfo->display) {
964 case BASE_OCT: /* I'm lazy */
965 case BASE_BIN: /* I'm lazy */
969 switch(hfinfo->type) {
971 format = "%s: 0x%02x";
974 format = "%s: 0x%04x";
977 format = "%s: 0x%06x";
980 format = "%s: 0x%08x";
983 g_assert_not_reached();
988 g_assert_not_reached();
997 proto_registrar_n(void)
999 return gpa_hfinfo->len;
1003 proto_registrar_get_name(int n)
1005 struct header_field_info *hfinfo;
1006 hfinfo = find_hfinfo_record(n);
1008 return hfinfo->name;
1013 proto_registrar_get_abbrev(int n)
1015 struct header_field_info *hfinfo;
1017 hfinfo = find_hfinfo_record(n);
1019 return hfinfo->abbrev;
1025 proto_registrar_get_ftype(int n)
1027 struct header_field_info *hfinfo;
1029 hfinfo = find_hfinfo_record(n);
1031 return hfinfo->type;
1037 proto_registrar_get_parent(int n)
1039 struct header_field_info *hfinfo;
1041 hfinfo = find_hfinfo_record(n);
1043 return hfinfo->parent;
1049 proto_registrar_is_protocol(int n)
1051 struct header_field_info *hfinfo;
1053 hfinfo = find_hfinfo_record(n);
1055 return (hfinfo->parent == -1 ? TRUE : FALSE);
1060 /* Returns length of field in packet (not necessarily the length
1061 * in our internal representation, as in the case of IPv4).
1062 * 0 means undeterminable at time of registration
1063 * -1 means the field is not registered. */
1065 proto_registrar_get_length(int n)
1067 struct header_field_info *hfinfo;
1069 hfinfo = find_hfinfo_record(n);
1073 switch (hfinfo->type) {
1074 case FT_TEXT_ONLY: /* not filterable */
1075 case NUM_FIELD_TYPES: /* satisfy picky compilers */
1083 case FT_ABSOLUTE_TIME:
1084 case FT_RELATIVE_TIME:
1111 g_assert_not_reached();
1115 /* Looks for a protocol or a field in a proto_tree. Returns TRUE if
1116 * it exists anywhere, or FALSE if it exists nowhere. */
1118 proto_check_for_protocol_or_field(proto_tree* tree, int id)
1120 proto_tree_search_info sinfo;
1123 sinfo.result.node = NULL;
1125 sinfo.traverse_func = NULL;
1127 /* do a quicker check if target is a protocol */
1128 if (proto_registrar_is_protocol(id) == TRUE) {
1129 proto_find_protocol_multi(tree, id, &check_for_protocol_or_field_id, &sinfo);
1132 /* find the field's parent protocol */
1133 sinfo.parent = proto_registrar_get_parent(id);
1135 /* Go through each protocol subtree, checking if the protocols
1136 * is the parent protocol of the field that we're looking for.
1137 * We may have protocols that occur more than once (e.g., IP in IP),
1138 * so we do indeed have to check all protocol subtrees, looking
1139 * for the parent protocol. That's why proto_find_protocol()
1140 * is not used --- it assumes a protocol occurs only once. */
1141 g_node_traverse((GNode*)tree, G_IN_ORDER, G_TRAVERSE_ALL, 2,
1142 check_for_field_within_protocol, &sinfo);
1145 if (sinfo.result.node)
1152 check_for_protocol_or_field_id(GNode *node, gpointer data)
1154 field_info *fi = (field_info*) (node->data);
1155 proto_tree_search_info *sinfo = (proto_tree_search_info*) data;
1157 if (fi) { /* !fi == the top most container node which holds nothing */
1158 if (fi->hfinfo->id == sinfo->target) {
1159 sinfo->result.node = node;
1160 return TRUE; /* halt traversal */
1163 return FALSE; /* keep traversing */
1167 check_for_field_within_protocol(GNode *node, gpointer data)
1169 field_info *fi = (field_info*) (node->data);
1170 proto_tree_search_info *sinfo = (proto_tree_search_info*) data;
1172 if (fi) { /* !fi == the top most container node which holds nothing */
1173 if (fi->hfinfo->id == sinfo->parent) {
1174 g_node_traverse(node, G_IN_ORDER, G_TRAVERSE_ALL, -1,
1175 check_for_protocol_or_field_id, sinfo);
1176 if (sinfo->result.node)
1177 return TRUE; /* halt traversal */
1180 return FALSE; /* keep traversing */
1183 /* Looks for a protocol at the top layer of the tree. The protocol can occur
1184 * more than once, for those encapsulated protocols. For each protocol subtree
1185 * that is found, the callback function is called.
1188 proto_find_protocol_multi(proto_tree* tree, int target, GNodeTraverseFunc callback,
1189 proto_tree_search_info *sinfo)
1191 g_assert(callback != NULL);
1192 g_node_traverse((GNode*)tree, G_IN_ORDER, G_TRAVERSE_ALL, 2, callback, (gpointer*)sinfo);
1195 /* Simple wrappter to traverse all nodes, calling the sinfo traverse function with sinfo as an arg */
1197 proto_get_field_values(proto_tree* subtree, proto_tree_search_info *sinfo)
1199 /* Don't try to check value of top-level NULL GNode */
1200 if (!((GNode*)subtree)->data) {
1201 return FALSE; /* don't halt */
1203 g_node_traverse((GNode*)subtree, G_IN_ORDER, G_TRAVERSE_ALL, -1, sinfo->traverse_func, (gpointer*)sinfo);
1204 return FALSE; /* don't halt */
1207 /* Dumps the contents of the registration database to stdout. An indepedent program can take
1208 * this output and format it into nice tables or HTML or whatever.
1210 * There is one record per line. Each record is either a protocol or a header
1211 * field, differentiated by the first field. The fields are tab-delimited.
1216 * Field 2 = protocol name
1217 * Field 3 = protocol abbreviation
1222 * Field 2 = field name
1223 * Field 3 = field abbreviation
1224 * Field 4 = type ( textual representation of the the ftenum type )
1225 * Field 5 = parent protocol abbreviation
1228 proto_registrar_dump(void)
1230 header_field_info *hfinfo, *parent_hfinfo;
1232 const char *enum_name;
1234 len = gpa_hfinfo->len;
1235 for (i = 0; i < len ; i++) {
1236 hfinfo = find_hfinfo_record(i);
1238 /* format for protocols */
1239 if (proto_registrar_is_protocol(i)) {
1240 printf("P\t%s\t%s\n", hfinfo->name, hfinfo->abbrev);
1242 /* format for header fields */
1244 parent_hfinfo = find_hfinfo_record(hfinfo->parent);
1245 g_assert(parent_hfinfo);
1247 switch(hfinfo->type) {
1249 enum_name = "FT_NONE";
1252 enum_name = "FT_BOOLEAN";
1255 enum_name = "FT_UINT8";
1258 enum_name = "FT_UINT16";
1261 enum_name = "FT_UINT24";
1264 enum_name = "FT_UINT32";
1267 enum_name = "FT_INT8";
1270 enum_name = "FT_INT16";
1273 enum_name = "FT_INT24";
1276 enum_name = "FT_INT32";
1279 enum_name = "FT_DOUBLE";
1281 case FT_ABSOLUTE_TIME:
1282 enum_name = "FT_ABSOLUTE_TIME";
1284 case FT_RELATIVE_TIME:
1285 enum_name = "FT_RELATIVE_TIME";
1288 enum_name = "FT_STRING";
1291 enum_name = "FT_ETHER";
1294 enum_name = "FT_BYTES";
1297 enum_name = "FT_IPv4";
1300 enum_name = "FT_IPv6";
1303 enum_name = "FT_IPXNET";
1306 enum_name = "FT_TEXT_ONLY";
1309 enum_name = "UNKNOWN";
1312 printf("F\t%s\t%s\t%s\t%s\n", hfinfo->name, hfinfo->abbrev,
1313 enum_name,parent_hfinfo->abbrev);