2 * Routines for protocol tree
4 * $Id: proto.c,v 1.53 2000/02/07 17:07:45 gram 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 static void fill_label_boolean(field_info *fi, gchar *label_str);
80 static void fill_label_uint(field_info *fi, gchar *label_str);
81 static void fill_label_enumerated_uint(field_info *fi, gchar *label_str);
82 static void fill_label_enumerated_bitfield(field_info *fi, gchar *label_str);
83 static void fill_label_numeric_bitfield(field_info *fi, gchar *label_str);
84 static void fill_label_int(field_info *fi, gchar *label_str);
85 static void fill_label_enumerated_int(field_info *fi, gchar *label_str);
87 static int hfinfo_bitwidth(header_field_info *hfinfo);
88 static char* hfinfo_uint_vals_format(header_field_info *hfinfo);
89 static char* hfinfo_uint_format(header_field_info *hfinfo);
90 static char* hfinfo_int_vals_format(header_field_info *hfinfo);
91 static char* hfinfo_int_format(header_field_info *hfinfo);
93 static gboolean check_for_protocol_or_field_id(GNode *node, gpointer data);
94 static gboolean check_for_field_within_protocol(GNode *node, gpointer data);
96 static int proto_register_field_init(header_field_info *hfinfo, int parent);
98 /* special-case header field used within proto.c */
101 /* Contains information about protocols and header fields. Used when
102 * dissectors register their data */
103 GMemChunk *gmc_hfinfo = NULL;
105 /* Contains information about a field when a dissector calls
106 * proto_tree_add_item. */
107 GMemChunk *gmc_field_info = NULL;
109 /* String space for protocol and field items for the GUI */
110 GMemChunk *gmc_item_labels = NULL;
112 /* List which stores protocols and fields that have been registered */
113 GPtrArray *gpa_hfinfo = NULL;
115 /* Points to the first element of an array of Booleans, indexed by
116 a subtree item type; that array element is TRUE if subtrees of
117 an item of that type are to be expanded. */
118 gboolean *tree_is_expanded;
120 /* Number of elements in that array. */
123 /* Is the parsing being done for a visible proto_tree or an invisible one?
124 * By setting this correctly, the proto_tree creation is sped up by not
125 * having to call vsnprintf and copy strings around.
127 gboolean proto_tree_is_visible = TRUE;
129 /* initialize data structures and register protocols and fields */
133 static hf_register_info hf[] = {
135 { "Text", "text", FT_TEXT_ONLY, BASE_NONE, NULL, 0x0,
140 g_mem_chunk_destroy(gmc_hfinfo);
142 g_mem_chunk_destroy(gmc_field_info);
144 g_mem_chunk_destroy(gmc_item_labels);
146 g_ptr_array_free(gpa_hfinfo, FALSE);
147 if (tree_is_expanded != NULL)
148 g_free(tree_is_expanded);
150 gmc_hfinfo = g_mem_chunk_new("gmc_hfinfo",
151 sizeof(struct header_field_info), 50 * sizeof(struct
152 header_field_info), G_ALLOC_ONLY);
153 gmc_field_info = g_mem_chunk_new("gmc_field_info",
154 sizeof(struct field_info), 200 * sizeof(struct field_info),
156 gmc_item_labels = g_mem_chunk_new("gmc_item_labels",
157 ITEM_LABEL_LENGTH, 20 * ITEM_LABEL_LENGTH,
159 gpa_hfinfo = g_ptr_array_new();
161 /* Allocate "tree_is_expanded", with one element for ETT_NONE,
162 and initialize that element to FALSE. */
163 tree_is_expanded = g_malloc(sizeof (gint));
164 tree_is_expanded[0] = FALSE;
167 /* Have each dissector register its protocols and fields. */
168 register_all_protocols();
170 /* Register one special-case FT_TEXT_ONLY field for use when
171 converting ethereal to new-style proto_tree. These fields
172 are merely strings on the GUI tree; they are not filterable */
173 proto_register_field_array(-1, hf, array_length(hf));
175 /* We've assigned all the subtree type values; allocate the array
176 for them, and zero it out. */
177 tree_is_expanded = g_malloc(num_tree_types*sizeof (gint *));
178 memset(tree_is_expanded, '\0', num_tree_types*sizeof (gint *));
185 g_mem_chunk_destroy(gmc_hfinfo);
187 g_mem_chunk_destroy(gmc_field_info);
189 g_mem_chunk_destroy(gmc_item_labels);
191 g_ptr_array_free(gpa_hfinfo, FALSE);
194 /* frees the resources that the dissection a proto_tree uses */
196 proto_tree_free(proto_tree *tree)
198 g_node_traverse((GNode*)tree, G_IN_ORDER, G_TRAVERSE_ALL, -1,
199 proto_tree_free_node, NULL);
200 g_node_destroy((GNode*)tree);
204 proto_tree_free_node(GNode *node, gpointer data)
206 field_info *fi = (field_info*) (node->data);
209 if (fi->representation)
210 g_mem_chunk_free(gmc_item_labels, fi->representation);
211 if (fi->hfinfo->type == FT_STRING)
212 g_free(fi->value.string);
213 else if (fi->hfinfo->type == FT_BYTES)
214 g_free(fi->value.bytes);
215 g_mem_chunk_free(gmc_field_info, fi);
217 return FALSE; /* FALSE = do not end traversal of GNode tree */
220 /* Finds a record in the hf_info_records array. */
221 static struct header_field_info*
222 find_hfinfo_record(int hfindex)
224 g_assert(hfindex >= 0 && hfindex < gpa_hfinfo->len);
225 return g_ptr_array_index(gpa_hfinfo, hfindex);
229 proto_tree_add_item(proto_tree *tree, int hfindex, gint start, gint length, ...)
234 va_start(ap, length);
235 pi = _proto_tree_add_item_value(tree, hfindex, start, length, 0, 1, ap);
242 proto_tree_add_item_hidden(proto_tree *tree, int hfindex, gint start, gint length, ...)
247 va_start(ap, length);
248 pi = _proto_tree_add_item_value(tree, hfindex, start, length, 0, 0, ap);
255 proto_tree_add_item_format(proto_tree *tree, int hfindex, gint start, gint length, ...)
260 va_start(ap, length);
261 pi = _proto_tree_add_item_value(tree, hfindex, start, length, 1, 1, ap);
268 proto_tree_add_notext(proto_tree *tree, gint start, gint length, ...)
273 va_start(ap, length);
274 pi = _proto_tree_add_item_value(tree, hf_text_only, start, length, 0, 1, ap);
281 proto_tree_add_text(proto_tree *tree, gint start, gint length, ...)
286 va_start(ap, length);
287 pi = _proto_tree_add_item_value(tree, hf_text_only, start, length, 1, 1, ap);
294 _proto_tree_add_item_value(proto_tree *tree, int hfindex, gint start,
295 gint length, int include_format, int visible, va_list ap)
300 header_field_info *hfinfo;
305 /* either visibility flag can nullify the other */
306 visible = proto_tree_is_visible && visible;
308 fi = g_mem_chunk_alloc(gmc_field_info);
310 fi->hfinfo = find_hfinfo_record(hfindex);
311 g_assert(fi->hfinfo != NULL);
314 fi->tree_type = ETT_NONE;
315 fi->visible = visible;
317 /* for convenience */
320 /* from the stdarg man page on Solaris 2.6:
322 It is up to the calling routine to specify in some manner
323 how many arguments there are, since it is not always possi-
324 ble to determine the number of arguments from the stack
325 frame. For example, execl is passed a zero pointer to sig-
326 nal the end of the list. printf can tell how many arguments
327 there are by the format. It is non-portable to specify a
328 second argument of char, short, or float to va_arg, because
329 arguments seen by the called function are not char, short,
330 or float. C converts char and short arguments to int and
331 converts float arguments to double before passing them to a
334 switch(hfinfo->type) {
336 junk = va_arg(ap, guint8*);
340 /* This g_malloc'ed memory is freed in
341 proto_tree_free_node() */
342 fi->value.bytes = (guint8 *)g_malloc(length);
343 memcpy(fi->value.bytes, va_arg(ap, guint8*), length);
355 fi->value.numeric = va_arg(ap, unsigned int);
356 if (hfinfo->bitmask) {
357 /* Mask out irrelevant portions */
358 fi->value.numeric &= hfinfo->bitmask;
361 if (hfinfo->bitshift > 0) {
362 fi->value.numeric >>= hfinfo->bitshift;
368 ipv4_addr_set_net_order_addr(&(fi->value.ipv4), va_arg(ap, unsigned int));
369 ipv4_addr_set_netmask_bits(&(fi->value.ipv4), 32);
373 fi->value.numeric = va_arg(ap, unsigned int);
377 memcpy(fi->value.ipv6, va_arg(ap, guint8*), 16);
381 fi->value.floating = va_arg(ap, double);
385 memcpy(fi->value.ether, va_arg(ap, guint8*), 6);
388 case FT_ABSOLUTE_TIME:
389 case FT_RELATIVE_TIME:
390 memcpy(&fi->value.time, va_arg(ap, struct timeval*),
391 sizeof(struct timeval));
395 /* This g_strdup'ed memory is freed in proto_tree_free_node() */
396 fi->value.string = g_strdup(va_arg(ap, char*));
404 g_error("hfinfo->type %d not handled\n", hfinfo->type);
408 pi = (proto_item*) g_node_new(fi);
409 g_node_append((GNode*)tree, (GNode*)pi);
411 /* are there any formatting arguments? */
412 if (visible && include_format) {
413 format = va_arg(ap, char*);
414 fi->representation = g_mem_chunk_alloc(gmc_item_labels);
415 vsnprintf(fi->representation, ITEM_LABEL_LENGTH,
419 fi->representation = NULL;
426 proto_item_set_text(proto_item *pi, ...)
428 field_info *fi = (field_info*) (((GNode*)pi)->data);
432 if (fi->representation)
433 g_mem_chunk_free(gmc_item_labels, fi->representation);
435 fi->representation = g_mem_chunk_alloc(gmc_item_labels);
437 format = va_arg(ap, char*);
438 vsnprintf(fi->representation, ITEM_LABEL_LENGTH,
444 proto_item_set_len(proto_item *pi, gint length)
446 field_info *fi = (field_info*) (((GNode*)pi)->data);
451 proto_tree_create_root(void)
453 return (proto_tree*) g_node_new(NULL);
457 proto_item_add_subtree(proto_item *pi, gint idx) {
458 field_info *fi = (field_info*) (((GNode*)pi)->data);
459 g_assert(idx >= 0 && idx < num_tree_types);
461 return (proto_tree*) pi;
466 proto_register_protocol(char *name, char *abbrev)
468 struct header_field_info *hfinfo;
470 /* Here we do allocate a new header_field_info struct */
471 hfinfo = g_mem_chunk_alloc(gmc_hfinfo);
473 hfinfo->abbrev = abbrev;
474 hfinfo->type = FT_NONE;
475 hfinfo->strings = NULL;
477 hfinfo->bitshift = 0;
479 hfinfo->parent = -1; /* this field differentiates protos and fields */
481 return proto_register_field_init(hfinfo, hfinfo->parent);
484 /* for use with static arrays only, since we don't allocate our own copies
485 of the header_field_info struct contained withing the hf_register_info struct */
487 proto_register_field_array(int parent, hf_register_info *hf, int num_records)
490 hf_register_info *ptr = hf;
492 for (i = 0; i < num_records; i++, ptr++) {
493 field_id = proto_register_field_init(&ptr->hfinfo, parent);
494 *ptr->p_id = field_id;
499 proto_register_field_init(header_field_info *hfinfo, int parent)
501 /* These types of fields are allowed to have value_strings or true_false_strings */
502 g_assert((hfinfo->strings == NULL) || (
503 (hfinfo->type == FT_UINT8) ||
504 (hfinfo->type == FT_UINT16) ||
505 (hfinfo->type == FT_UINT24) ||
506 (hfinfo->type == FT_UINT32) ||
507 (hfinfo->type == FT_INT8) ||
508 (hfinfo->type == FT_INT16) ||
509 (hfinfo->type == FT_INT24) ||
510 (hfinfo->type == FT_INT32) ||
511 (hfinfo->type == FT_BOOLEAN) ));
513 /* if this is a bitfield, compure bitshift */
514 if (hfinfo->bitmask) {
515 while ((hfinfo->bitmask & (1 << hfinfo->bitshift)) == 0)
519 hfinfo->parent = parent;
521 /* if we always add and never delete, then id == len - 1 is correct */
522 g_ptr_array_add(gpa_hfinfo, hfinfo);
523 hfinfo->id = gpa_hfinfo->len - 1;
528 proto_register_subtree_array(gint **indices, int num_indices)
531 gint **ptr = indices;
534 * Add "num_indices" elements to "tree_is_expanded".
536 tree_is_expanded = g_realloc(tree_is_expanded,
537 (num_tree_types + num_indices)*sizeof (gint));
540 * Assign "num_indices" subtree numbers starting at "num_tree_types",
541 * returning the indices through the pointers in the array whose
542 * first element is pointed to by "indices", set to FALSE the
543 * elements to which those subtree numbers refer, and update
544 * "num_tree_types" appropriately.
546 for (i = 0; i < num_indices; i++, ptr++, num_tree_types++) {
547 tree_is_expanded[num_tree_types] = FALSE;
548 **ptr = num_tree_types;
553 proto_item_fill_label(field_info *fi, gchar *label_str)
555 struct header_field_info *hfinfo = fi->hfinfo;
556 guint32 n_addr; /* network-order IPv4 address */
558 switch(hfinfo->type) {
560 snprintf(label_str, ITEM_LABEL_LENGTH,
565 fill_label_boolean(fi, label_str);
569 snprintf(label_str, ITEM_LABEL_LENGTH,
570 "%s: %s", hfinfo->name,
571 bytes_to_str(fi->value.bytes, fi->length));
574 /* Four types of integers to take care of:
575 * Bitfield, with val_string
576 * Bitfield, w/o val_string
577 * Non-bitfield, with val_string
578 * Non-bitfield, w/o val_string
584 if (hfinfo->bitmask) {
585 if (hfinfo->strings) {
586 fill_label_enumerated_bitfield(fi, label_str);
589 fill_label_numeric_bitfield(fi, label_str);
593 if (hfinfo->strings) {
594 fill_label_enumerated_uint(fi, label_str);
597 fill_label_uint(fi, label_str);
606 g_assert(!hfinfo->bitmask);
607 if (hfinfo->strings) {
608 fill_label_enumerated_int(fi, label_str);
611 fill_label_int(fi, label_str);
616 snprintf(label_str, ITEM_LABEL_LENGTH,
617 "%s: %g", fi->hfinfo->name,
621 case FT_ABSOLUTE_TIME:
622 snprintf(label_str, ITEM_LABEL_LENGTH,
623 "%s: %s", fi->hfinfo->name,
624 abs_time_to_str(&fi->value.time));
627 case FT_RELATIVE_TIME:
628 snprintf(label_str, ITEM_LABEL_LENGTH,
629 "%s: %s seconds", fi->hfinfo->name,
630 rel_time_to_str(&fi->value.time));
634 snprintf(label_str, ITEM_LABEL_LENGTH,
635 "%s: 0x%08X (%s)", fi->hfinfo->name,
636 fi->value.numeric, get_ipxnet_name(fi->value.numeric));
640 snprintf(label_str, ITEM_LABEL_LENGTH,
641 "%s: %s (%s)", fi->hfinfo->name,
642 ether_to_str(fi->value.ether),
643 get_ether_name(fi->value.ether));
647 n_addr = ipv4_get_net_order_addr(&fi->value.ipv4);
648 snprintf(label_str, ITEM_LABEL_LENGTH,
649 "%s: %s (%s)", fi->hfinfo->name,
650 get_hostname(n_addr),
651 ip_to_str((guint8*)&n_addr));
655 snprintf(label_str, ITEM_LABEL_LENGTH,
656 "%s: %s (%s)", fi->hfinfo->name,
657 get_hostname6((struct e_in6_addr *)fi->value.ipv6),
658 ip6_to_str((struct e_in6_addr*)fi->value.ipv6));
662 snprintf(label_str, ITEM_LABEL_LENGTH,
663 "%s: %s", fi->hfinfo->name, fi->value.string);
667 g_error("hfinfo->type %d not handled\n", fi->hfinfo->type);
673 fill_label_boolean(field_info *fi, gchar *label_str)
676 int bitfield_byte_length = 0, bitwidth;
677 guint32 unshifted_value;
679 struct header_field_info *hfinfo = fi->hfinfo;
680 struct true_false_string default_tf = { "True", "False" };
681 struct true_false_string *tfstring = &default_tf;
683 if (hfinfo->strings) {
684 tfstring = (struct true_false_string*) hfinfo->strings;
687 if (hfinfo->bitmask) {
688 /* Figure out the bit width */
689 bitwidth = hfinfo_bitwidth(hfinfo);
692 unshifted_value = fi->value.numeric;
693 if (hfinfo->bitshift > 0) {
694 unshifted_value <<= hfinfo->bitshift;
697 /* Create the bitfield first */
698 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
699 bitfield_byte_length = p - label_str;
702 /* Fill in the textual info */
703 snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
704 "%s: %s", hfinfo->name,
705 fi->value.numeric ? tfstring->true_string : tfstring->false_string);
709 /* Fills data for bitfield ints with val_strings */
711 fill_label_enumerated_bitfield(field_info *fi, gchar *label_str)
713 char *format = NULL, *p;
714 int bitfield_byte_length, bitwidth;
715 guint32 unshifted_value;
717 struct header_field_info *hfinfo = fi->hfinfo;
719 /* Figure out the bit width */
720 bitwidth = hfinfo_bitwidth(hfinfo);
722 /* Pick the proper format string */
723 format = hfinfo_uint_vals_format(hfinfo);
726 unshifted_value = fi->value.numeric;
727 if (hfinfo->bitshift > 0) {
728 unshifted_value <<= hfinfo->bitshift;
731 /* Create the bitfield first */
732 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
733 bitfield_byte_length = p - label_str;
735 /* Fill in the textual info using stored (shifted) value */
736 snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
737 format, hfinfo->name,
738 val_to_str(fi->value.numeric, cVALS(hfinfo->strings), "Unknown"),
743 fill_label_numeric_bitfield(field_info *fi, gchar *label_str)
745 char *format = NULL, *p;
746 int bitfield_byte_length, bitwidth;
747 guint32 unshifted_value;
749 struct header_field_info *hfinfo = fi->hfinfo;
751 /* Figure out the bit width */
752 bitwidth = hfinfo_bitwidth(hfinfo);
754 /* Pick the proper format string */
755 format = hfinfo_uint_format(hfinfo);
758 unshifted_value = fi->value.numeric;
759 if (hfinfo->bitshift > 0) {
760 unshifted_value <<= hfinfo->bitshift;
763 /* Create the bitfield using */
764 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
765 bitfield_byte_length = p - label_str;
767 /* Fill in the textual info using stored (shifted) value */
768 snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
769 format, hfinfo->name, fi->value.numeric);
773 fill_label_enumerated_uint(field_info *fi, gchar *label_str)
776 struct header_field_info *hfinfo = fi->hfinfo;
778 /* Pick the proper format string */
779 format = hfinfo_uint_vals_format(hfinfo);
781 /* Fill in the textual info */
782 snprintf(label_str, ITEM_LABEL_LENGTH,
783 format, hfinfo->name,
784 val_to_str(fi->value.numeric, cVALS(hfinfo->strings), "Unknown"),
789 fill_label_uint(field_info *fi, gchar *label_str)
792 struct header_field_info *hfinfo = fi->hfinfo;
794 /* Pick the proper format string */
795 format = hfinfo_uint_format(hfinfo);
797 /* Fill in the textual info */
798 snprintf(label_str, ITEM_LABEL_LENGTH,
799 format, hfinfo->name, fi->value.numeric);
803 fill_label_enumerated_int(field_info *fi, gchar *label_str)
806 struct header_field_info *hfinfo = fi->hfinfo;
808 /* Pick the proper format string */
809 format = hfinfo_int_vals_format(hfinfo);
811 /* Fill in the textual info */
812 snprintf(label_str, ITEM_LABEL_LENGTH,
813 format, hfinfo->name,
814 val_to_str(fi->value.numeric, cVALS(hfinfo->strings), "Unknown"),
819 fill_label_int(field_info *fi, gchar *label_str)
822 struct header_field_info *hfinfo = fi->hfinfo;
824 /* Pick the proper format string */
825 format = hfinfo_int_format(hfinfo);
827 /* Fill in the textual info */
828 snprintf(label_str, ITEM_LABEL_LENGTH,
829 format, hfinfo->name, fi->value.numeric);
833 hfinfo_bitwidth(header_field_info *hfinfo)
837 if (!hfinfo->bitmask) {
841 switch(hfinfo->type) {
859 bitwidth = hfinfo->display; /* hacky? :) */
862 g_assert_not_reached();
869 hfinfo_uint_vals_format(header_field_info *hfinfo)
873 switch(hfinfo->display) {
876 case BASE_OCT: /* I'm lazy */
877 case BASE_BIN: /* I'm lazy */
878 format = "%s: %s (%u)";
881 switch(hfinfo->type) {
883 format = "%s: %s (0x%02x)";
886 format = "%s: %s (0x%04x)";
889 format = "%s: %s (0x%06x)";
892 format = "%s: %s (0x%08x)";
895 g_assert_not_reached();
900 g_assert_not_reached();
907 hfinfo_uint_format(header_field_info *hfinfo)
911 /* Pick the proper format string */
912 switch(hfinfo->display) {
915 case BASE_OCT: /* I'm lazy */
916 case BASE_BIN: /* I'm lazy */
920 switch(hfinfo->type) {
922 format = "%s: 0x%02x";
925 format = "%s: 0x%04x";
928 format = "%s: 0x%06x";
931 format = "%s: 0x%08x";
934 g_assert_not_reached();
939 g_assert_not_reached();
946 hfinfo_int_vals_format(header_field_info *hfinfo)
950 switch(hfinfo->display) {
953 case BASE_OCT: /* I'm lazy */
954 case BASE_BIN: /* I'm lazy */
955 format = "%s: %s (%d)";
958 switch(hfinfo->type) {
960 format = "%s: %s (0x%02x)";
963 format = "%s: %s (0x%04x)";
966 format = "%s: %s (0x%06x)";
969 format = "%s: %s (0x%08x)";
972 g_assert_not_reached();
977 g_assert_not_reached();
984 hfinfo_int_format(header_field_info *hfinfo)
988 /* Pick the proper format string */
989 switch(hfinfo->display) {
992 case BASE_OCT: /* I'm lazy */
993 case BASE_BIN: /* I'm lazy */
997 switch(hfinfo->type) {
999 format = "%s: 0x%02x";
1002 format = "%s: 0x%04x";
1005 format = "%s: 0x%06x";
1008 format = "%s: 0x%08x";
1011 g_assert_not_reached();
1016 g_assert_not_reached();
1025 proto_registrar_n(void)
1027 return gpa_hfinfo->len;
1031 proto_registrar_get_name(int n)
1033 struct header_field_info *hfinfo;
1034 hfinfo = find_hfinfo_record(n);
1036 return hfinfo->name;
1041 proto_registrar_get_abbrev(int n)
1043 struct header_field_info *hfinfo;
1045 hfinfo = find_hfinfo_record(n);
1047 return hfinfo->abbrev;
1053 proto_registrar_get_ftype(int n)
1055 struct header_field_info *hfinfo;
1057 hfinfo = find_hfinfo_record(n);
1059 return hfinfo->type;
1065 proto_registrar_get_parent(int n)
1067 struct header_field_info *hfinfo;
1069 hfinfo = find_hfinfo_record(n);
1071 return hfinfo->parent;
1077 proto_registrar_is_protocol(int n)
1079 struct header_field_info *hfinfo;
1081 hfinfo = find_hfinfo_record(n);
1083 return (hfinfo->parent == -1 ? TRUE : FALSE);
1088 /* Returns length of field in packet (not necessarily the length
1089 * in our internal representation, as in the case of IPv4).
1090 * 0 means undeterminable at time of registration
1091 * -1 means the field is not registered. */
1093 proto_registrar_get_length(int n)
1095 struct header_field_info *hfinfo;
1097 hfinfo = find_hfinfo_record(n);
1101 switch (hfinfo->type) {
1102 case FT_TEXT_ONLY: /* not filterable */
1103 case NUM_FIELD_TYPES: /* satisfy picky compilers */
1111 case FT_ABSOLUTE_TIME:
1112 case FT_RELATIVE_TIME:
1139 g_assert_not_reached();
1143 /* Looks for a protocol or a field in a proto_tree. Returns TRUE if
1144 * it exists anywhere, or FALSE if it exists nowhere. */
1146 proto_check_for_protocol_or_field(proto_tree* tree, int id)
1148 proto_tree_search_info sinfo;
1151 sinfo.result.node = NULL;
1153 sinfo.traverse_func = NULL;
1155 /* do a quicker check if target is a protocol */
1156 if (proto_registrar_is_protocol(id) == TRUE) {
1157 proto_find_protocol_multi(tree, id, &check_for_protocol_or_field_id, &sinfo);
1160 /* find the field's parent protocol */
1161 sinfo.parent = proto_registrar_get_parent(id);
1163 /* Go through each protocol subtree, checking if the protocols
1164 * is the parent protocol of the field that we're looking for.
1165 * We may have protocols that occur more than once (e.g., IP in IP),
1166 * so we do indeed have to check all protocol subtrees, looking
1167 * for the parent protocol. That's why proto_find_protocol()
1168 * is not used --- it assumes a protocol occurs only once. */
1169 g_node_traverse((GNode*)tree, G_IN_ORDER, G_TRAVERSE_ALL, 2,
1170 check_for_field_within_protocol, &sinfo);
1173 if (sinfo.result.node)
1180 check_for_protocol_or_field_id(GNode *node, gpointer data)
1182 field_info *fi = (field_info*) (node->data);
1183 proto_tree_search_info *sinfo = (proto_tree_search_info*) data;
1185 if (fi) { /* !fi == the top most container node which holds nothing */
1186 if (fi->hfinfo->id == sinfo->target) {
1187 sinfo->result.node = node;
1188 return TRUE; /* halt traversal */
1191 return FALSE; /* keep traversing */
1195 check_for_field_within_protocol(GNode *node, gpointer data)
1197 field_info *fi = (field_info*) (node->data);
1198 proto_tree_search_info *sinfo = (proto_tree_search_info*) data;
1200 if (fi) { /* !fi == the top most container node which holds nothing */
1201 if (fi->hfinfo->id == sinfo->parent) {
1202 g_node_traverse(node, G_IN_ORDER, G_TRAVERSE_ALL, -1,
1203 check_for_protocol_or_field_id, sinfo);
1204 if (sinfo->result.node)
1205 return TRUE; /* halt traversal */
1208 return FALSE; /* keep traversing */
1211 /* Looks for a protocol at the top layer of the tree. The protocol can occur
1212 * more than once, for those encapsulated protocols. For each protocol subtree
1213 * that is found, the callback function is called.
1216 proto_find_protocol_multi(proto_tree* tree, int target, GNodeTraverseFunc callback,
1217 proto_tree_search_info *sinfo)
1219 g_assert(callback != NULL);
1220 g_node_traverse((GNode*)tree, G_IN_ORDER, G_TRAVERSE_ALL, 2, callback, (gpointer*)sinfo);
1223 /* Simple wrappter to traverse all nodes, calling the sinfo traverse function with sinfo as an arg */
1225 proto_get_field_values(proto_tree* subtree, proto_tree_search_info *sinfo)
1227 /* Don't try to check value of top-level NULL GNode */
1228 if (!((GNode*)subtree)->data) {
1229 return FALSE; /* don't halt */
1231 g_node_traverse((GNode*)subtree, G_IN_ORDER, G_TRAVERSE_ALL, -1, sinfo->traverse_func, (gpointer*)sinfo);
1232 return FALSE; /* don't halt */
1235 /* Dumps the contents of the registration database to stdout. An indepedent program can take
1236 * this output and format it into nice tables or HTML or whatever.
1238 * There is one record per line. Each record is either a protocol or a header
1239 * field, differentiated by the first field. The fields are tab-delimited.
1244 * Field 2 = protocol name
1245 * Field 3 = protocol abbreviation
1250 * Field 2 = field name
1251 * Field 3 = field abbreviation
1252 * Field 4 = type ( textual representation of the the ftenum type )
1253 * Field 5 = parent protocol abbreviation
1256 proto_registrar_dump(void)
1258 header_field_info *hfinfo, *parent_hfinfo;
1260 const char *enum_name;
1262 len = gpa_hfinfo->len;
1263 for (i = 0; i < len ; i++) {
1264 hfinfo = find_hfinfo_record(i);
1266 /* format for protocols */
1267 if (proto_registrar_is_protocol(i)) {
1268 printf("P\t%s\t%s\n", hfinfo->name, hfinfo->abbrev);
1270 /* format for header fields */
1272 parent_hfinfo = find_hfinfo_record(hfinfo->parent);
1273 g_assert(parent_hfinfo);
1275 switch(hfinfo->type) {
1277 enum_name = "FT_NONE";
1280 enum_name = "FT_BOOLEAN";
1283 enum_name = "FT_UINT8";
1286 enum_name = "FT_UINT16";
1289 enum_name = "FT_UINT24";
1292 enum_name = "FT_UINT32";
1295 enum_name = "FT_INT8";
1298 enum_name = "FT_INT16";
1301 enum_name = "FT_INT24";
1304 enum_name = "FT_INT32";
1307 enum_name = "FT_DOUBLE";
1309 case FT_ABSOLUTE_TIME:
1310 enum_name = "FT_ABSOLUTE_TIME";
1312 case FT_RELATIVE_TIME:
1313 enum_name = "FT_RELATIVE_TIME";
1316 enum_name = "FT_STRING";
1319 enum_name = "FT_ETHER";
1322 enum_name = "FT_BYTES";
1325 enum_name = "FT_IPv4";
1328 enum_name = "FT_IPv6";
1331 enum_name = "FT_IPXNET";
1334 enum_name = "FT_TEXT_ONLY";
1337 enum_name = "UNKNOWN";
1340 printf("F\t%s\t%s\t%s\t%s\n", hfinfo->name, hfinfo->abbrev,
1341 enum_name,parent_hfinfo->abbrev);