2 * Routines for protocol tree
4 * $Id: proto.c,v 1.36 1999/10/12 19:47:44 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 #include "packet-ipv6.h"
66 #define cVALS(x) (const value_string*)(x)
68 #if defined(HAVE_UCD_SNMP_SNMP_H)
69 # define WITH_SNMP_UCD 1
70 #elif defined(HAVE_SNMP_SNMP_H)
71 # define WITH_SNMP_CMU 1
75 proto_tree_free_node(GNode *node, gpointer data);
77 static struct header_field_info*
78 find_hfinfo_record(int hfindex);
81 proto_tree_add_item_value(proto_tree *tree, int hfindex, gint start,
82 gint length, int include_format, int visible, va_list ap);
84 static void fill_label_boolean(field_info *fi, gchar *label_str);
85 static void fill_label_uint(field_info *fi, gchar *label_str);
86 static void fill_label_enumerated_uint(field_info *fi, gchar *label_str);
87 static void fill_label_enumerated_bitfield(field_info *fi, gchar *label_str);
88 static void fill_label_numeric_bitfield(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);
94 static gboolean check_for_protocol_or_field_id(GNode *node, gpointer data);
95 static gboolean check_for_field_within_protocol(GNode *node, gpointer data);
97 static int proto_register_field_init(header_field_info *hfinfo, int parent);
99 /* centralization of registration functions */
100 void proto_register_aarp(void);
101 void proto_register_arp(void);
102 void proto_register_ascend(void);
103 void proto_register_atalk(void);
104 void proto_register_atm(void);
105 void proto_register_bootp(void);
106 void proto_register_bpdu(void);
107 void proto_register_cdp(void);
108 void proto_register_clnp(void);
109 void proto_register_cotp(void);
110 void proto_register_data(void);
111 void proto_register_dns(void);
112 void proto_register_eth(void);
113 void proto_register_fddi(void);
114 void proto_register_frame(void);
115 void proto_register_ftp(void);
116 void proto_register_giop(void);
117 void proto_register_gre(void);
118 void proto_register_http(void);
119 void proto_register_icmp(void);
120 void proto_register_icmpv6(void);
121 void proto_register_icp(void);
122 void proto_register_igmp(void);
123 void proto_register_ip(void);
124 void proto_register_ipp(void);
125 void proto_register_ipsec(void);
126 void proto_register_ipv6(void);
127 void proto_register_ipx(void);
128 void proto_register_isakmp(void);
129 void proto_register_lapb(void);
130 void proto_register_llc(void);
131 void proto_register_mp(void);
132 void proto_register_nbipx(void);
133 void proto_register_nbt(void);
134 void proto_register_ncp(void);
135 void proto_register_netbios(void);
136 void proto_register_nntp(void);
137 void proto_register_null(void);
138 void proto_register_ospf(void);
139 void proto_register_pop(void);
140 void proto_register_ppp(void);
141 void proto_register_radius(void);
142 void proto_register_rip(void);
143 void proto_register_rsvp(void);
144 void proto_register_rtsp(void);
145 void proto_register_sdp(void);
146 void proto_register_smb(void);
147 void proto_register_sna(void);
148 #if defined(WITH_SNMP_CMU) || defined(WITH_SNMP_UCD)
149 void proto_register_snmp(void);
151 void proto_register_telnet(void);
152 void proto_register_tftp(void);
153 void proto_register_tcp(void);
154 void proto_register_tr(void);
155 void proto_register_trmac(void);
156 void proto_register_udp(void);
157 void proto_register_x25(void);
159 /* special-case header field used within proto.c */
160 int hf_text_only = 1;
162 /* Contains information about protocols and header fields. Used when
163 * dissectors register their data */
164 GMemChunk *gmc_hfinfo = NULL;
166 /* Contains information about a field when a dissector calls
167 * proto_tree_add_item. */
168 GMemChunk *gmc_field_info = NULL;
170 /* String space for protocol and field items for the GUI */
171 GMemChunk *gmc_item_labels = NULL;
173 /* List which stores protocols and fields that have been registered */
174 GPtrArray *gpa_hfinfo = NULL;
176 /* Is the parsing being done for a visible proto_tree or an invisible one?
177 * By setting this correctly, the proto_tree creation is sped up by not
178 * having to call vsnprintf and copy strings around.
180 gboolean proto_tree_is_visible = TRUE;
182 /* initialize data structures and register protocols and fields */
186 static hf_register_info hf[] = {
188 { "Text", "text", FT_TEXT_ONLY, BASE_NONE, NULL, 0x0,
193 g_mem_chunk_destroy(gmc_hfinfo);
195 g_mem_chunk_destroy(gmc_field_info);
197 g_mem_chunk_destroy(gmc_item_labels);
199 g_ptr_array_free(gpa_hfinfo, FALSE);
201 gmc_hfinfo = g_mem_chunk_new("gmc_hfinfo",
202 sizeof(struct header_field_info), 50 * sizeof(struct
203 header_field_info), G_ALLOC_ONLY);
204 gmc_field_info = g_mem_chunk_new("gmc_field_info",
205 sizeof(struct field_info), 200 * sizeof(struct field_info),
207 gmc_item_labels = g_mem_chunk_new("gmc_item_labels",
208 ITEM_LABEL_LENGTH, 20 * ITEM_LABEL_LENGTH,
210 gpa_hfinfo = g_ptr_array_new();
212 /* Have each dissector register its protocols and fields. The
213 * order doesn't matter. Put the calls in alphabetical order
214 * just to make it easy. */
215 proto_register_aarp();
216 proto_register_arp();
217 proto_register_ascend();
218 proto_register_atalk();
219 proto_register_atm();
220 proto_register_bootp();
221 proto_register_bpdu();
222 proto_register_cdp();
223 proto_register_clnp();
224 proto_register_cotp();
225 proto_register_data();
226 proto_register_dns();
227 proto_register_eth();
228 proto_register_fddi();
229 proto_register_frame();
230 proto_register_ftp();
231 proto_register_giop();
232 proto_register_gre();
233 proto_register_http();
234 proto_register_icmp();
235 proto_register_icmpv6();
236 proto_register_icp();
237 proto_register_igmp();
239 proto_register_ipp();
240 proto_register_ipsec();
241 proto_register_ipv6();
242 proto_register_ipx();
243 proto_register_isakmp();
244 proto_register_lapb();
245 proto_register_llc();
247 proto_register_nbipx();
248 proto_register_nbt();
249 proto_register_ncp();
250 proto_register_netbios();
251 proto_register_nntp();
252 proto_register_null();
253 proto_register_ospf();
254 proto_register_pop();
255 proto_register_ppp();
256 proto_register_radius();
257 proto_register_rip();
258 proto_register_rsvp();
259 proto_register_rtsp();
260 proto_register_sdp();
261 proto_register_smb();
262 proto_register_sna();
263 #if defined(WITH_SNMP_CMU) || defined(WITH_SNMP_UCD)
264 proto_register_snmp();
266 proto_register_telnet();
267 proto_register_tftp();
268 proto_register_tcp();
270 proto_register_trmac();
271 proto_register_udp();
272 proto_register_x25();
274 /* Register one special-case FT_TEXT_ONLY field for use when
275 converting ethereal to new-style proto_tree. These fields
276 are merely strings on the GUI tree; they are not filterable */
277 proto_register_field_array(-1, hf, array_length(hf));
284 g_mem_chunk_destroy(gmc_hfinfo);
286 g_mem_chunk_destroy(gmc_field_info);
288 g_mem_chunk_destroy(gmc_item_labels);
290 g_ptr_array_free(gpa_hfinfo, FALSE);
293 /* frees the resources that the dissection a proto_tree uses */
295 proto_tree_free(proto_tree *tree)
297 g_node_traverse((GNode*)tree, G_IN_ORDER, G_TRAVERSE_ALL, -1,
298 proto_tree_free_node, NULL);
299 g_node_destroy((GNode*)tree);
303 proto_tree_free_node(GNode *node, gpointer data)
305 field_info *fi = (field_info*) (node->data);
308 if (fi->representation)
309 g_mem_chunk_free(gmc_item_labels, fi->representation);
310 if (fi->hfinfo->type == FT_STRING)
311 g_free(fi->value.string);
312 else if (fi->hfinfo->type == FT_BYTES)
313 g_free(fi->value.bytes);
314 g_mem_chunk_free(gmc_field_info, fi);
316 return FALSE; /* FALSE = do not end traversal of GNode tree */
319 /* Finds a record in the hf_info_records array. */
320 static struct header_field_info*
321 find_hfinfo_record(int hfindex)
323 g_assert(hfindex >= 0 && hfindex < gpa_hfinfo->len);
324 return g_ptr_array_index(gpa_hfinfo, hfindex);
328 proto_tree_add_item(proto_tree *tree, int hfindex, gint start, gint length, ...)
333 va_start(ap, length);
334 pi = proto_tree_add_item_value(tree, hfindex, start, length, 0, 1, ap);
341 proto_tree_add_item_hidden(proto_tree *tree, int hfindex, gint start, gint length, ...)
346 va_start(ap, length);
347 pi = proto_tree_add_item_value(tree, hfindex, start, length, 0, 0, ap);
354 proto_tree_add_item_format(proto_tree *tree, int hfindex, gint start, gint length, ...)
359 va_start(ap, length);
360 pi = proto_tree_add_item_value(tree, hfindex, start, length, 1, 1, ap);
367 proto_tree_add_text(proto_tree *tree, gint start, gint length, ...)
372 va_start(ap, length);
373 pi = proto_tree_add_item_value(tree, hf_text_only, start, length, 1, 1, ap);
380 proto_tree_add_item_value(proto_tree *tree, int hfindex, gint start,
381 gint length, int include_format, int visible, va_list ap)
386 header_field_info *hfinfo;
391 /* either visibility flag can nullify the other */
392 visible = proto_tree_is_visible && visible;
394 fi = g_mem_chunk_alloc(gmc_field_info);
396 fi->hfinfo = find_hfinfo_record(hfindex);
397 g_assert(fi->hfinfo != NULL);
400 fi->tree_type = ETT_NONE;
401 fi->visible = visible;
403 /* for convenience */
406 /* from the stdarg man page on Solaris 2.6:
408 It is up to the calling routine to specify in some manner
409 how many arguments there are, since it is not always possi-
410 ble to determine the number of arguments from the stack
411 frame. For example, execl is passed a zero pointer to sig-
412 nal the end of the list. printf can tell how many arguments
413 there are by the format. It is non-portable to specify a
414 second argument of char, short, or float to va_arg, because
415 arguments seen by the called function are not char, short,
416 or float. C converts char and short arguments to int and
417 converts float arguments to double before passing them to a
420 switch(hfinfo->type) {
422 junk = va_arg(ap, guint8*);
426 /* This g_malloc'ed memory is freed in
427 proto_tree_free_node() */
428 fi->value.bytes = (guint8 *)g_malloc(length);
429 memcpy(fi->value.bytes, va_arg(ap, guint8*), length);
441 fi->value.numeric = va_arg(ap, unsigned int);
442 if (hfinfo->bitmask) {
443 /* Mask out irrelevant portions */
444 fi->value.numeric &= hfinfo->bitmask;
447 if (hfinfo->bitshift > 0) {
448 fi->value.numeric >>= hfinfo->bitshift;
455 fi->value.numeric = va_arg(ap, unsigned int);
459 memcpy(fi->value.ipv6, va_arg(ap, guint8*), 16);
463 fi->value.floating = va_arg(ap, double);
467 memcpy(fi->value.ether, va_arg(ap, guint8*), 6);
470 case FT_ABSOLUTE_TIME:
471 case FT_RELATIVE_TIME:
472 memcpy(&fi->value.time, va_arg(ap, struct timeval*),
473 sizeof(struct timeval));
477 /* This g_strdup'ed memory is freed in proto_tree_free_node() */
478 fi->value.string = g_strdup(va_arg(ap, char*));
486 g_error("hfinfo->type %d not handled\n", hfinfo->type);
490 pi = (proto_item*) g_node_new(fi);
491 g_node_append((GNode*)tree, (GNode*)pi);
493 /* are there any formatting arguments? */
494 if (visible && include_format) {
495 fi->representation = g_mem_chunk_alloc(gmc_item_labels);
496 format = va_arg(ap, char*);
497 vsnprintf(fi->representation, ITEM_LABEL_LENGTH,
501 fi->representation = NULL;
508 proto_item_set_len(proto_item *pi, gint length)
510 field_info *fi = (field_info*) (((GNode*)pi)->data);
515 proto_tree_create_root(void)
517 return (proto_tree*) g_node_new(NULL);
521 proto_item_add_subtree(proto_item *pi, gint idx) {
522 field_info *fi = (field_info*) (((GNode*)pi)->data);
524 return (proto_tree*) pi;
529 proto_register_protocol(char *name, char *abbrev)
531 struct header_field_info *hfinfo;
533 /* Here we do allocate a new header_field_info struct */
534 hfinfo = g_mem_chunk_alloc(gmc_hfinfo);
536 hfinfo->abbrev = abbrev;
537 hfinfo->type = FT_NONE;
538 hfinfo->strings = NULL;
540 hfinfo->bitshift = 0;
542 hfinfo->parent = -1; /* this field differentiates protos and fields */
544 return proto_register_field_init(hfinfo, hfinfo->parent);
547 /* for use with static arrays only, since we don't allocate our own copies
548 of the header_field_info struct contained withing the hf_register_info struct */
550 proto_register_field_array(int parent, hf_register_info *hf, int num_records)
553 hf_register_info *ptr = hf;
555 for (i = 0; i < num_records; i++, ptr++) {
556 field_id = proto_register_field_init(&ptr->hfinfo, parent);
557 *ptr->p_id = field_id;
562 proto_register_field_init(header_field_info *hfinfo, int parent)
564 /* These types of fields are allowed to have value_strings or true_false_strings */
565 g_assert((hfinfo->strings == NULL) || (
566 (hfinfo->type == FT_UINT8) ||
567 (hfinfo->type == FT_UINT16) ||
568 (hfinfo->type == FT_UINT24) ||
569 (hfinfo->type == FT_UINT32) ||
570 (hfinfo->type == FT_INT8) ||
571 (hfinfo->type == FT_INT16) ||
572 (hfinfo->type == FT_INT24) ||
573 (hfinfo->type == FT_INT32) ||
574 (hfinfo->type == FT_BOOLEAN) ));
576 /* if this is a bitfield, compure bitshift */
577 if (hfinfo->bitmask) {
578 while ((hfinfo->bitmask & (1 << hfinfo->bitshift)) == 0)
582 hfinfo->parent = parent;
584 /* if we always add and never delete, then id == len - 1 is correct */
585 g_ptr_array_add(gpa_hfinfo, hfinfo);
586 hfinfo->id = gpa_hfinfo->len - 1;
591 proto_item_fill_label(field_info *fi, gchar *label_str)
593 struct header_field_info *hfinfo = fi->hfinfo;
595 switch(hfinfo->type) {
597 snprintf(label_str, ITEM_LABEL_LENGTH,
602 fill_label_boolean(fi, label_str);
606 snprintf(label_str, ITEM_LABEL_LENGTH,
607 "%s: %s", hfinfo->name,
608 bytes_to_str(fi->value.bytes, fi->length));
611 /* Four types of integers to take care of:
612 * Bitfield, with val_string
613 * Bitfield, w/o val_string
614 * Non-bitfield, with val_string
615 * Non-bitfield, w/o val_string
623 if (hfinfo->bitmask) {
624 if (hfinfo->strings) {
625 fill_label_enumerated_bitfield(fi, label_str);
628 fill_label_numeric_bitfield(fi, label_str);
632 if (hfinfo->strings) {
633 fill_label_enumerated_uint(fi, label_str);
636 fill_label_uint(fi, label_str);
642 snprintf(label_str, ITEM_LABEL_LENGTH,
643 "%s: %g", fi->hfinfo->name,
647 case FT_ABSOLUTE_TIME:
648 snprintf(label_str, ITEM_LABEL_LENGTH,
649 "%s: %s", fi->hfinfo->name,
650 abs_time_to_str(&fi->value.time));
653 case FT_RELATIVE_TIME:
654 snprintf(label_str, ITEM_LABEL_LENGTH,
655 "%s: %s seconds", fi->hfinfo->name,
656 rel_time_to_str(&fi->value.time));
660 snprintf(label_str, ITEM_LABEL_LENGTH,
661 "%s: 0x%08X", fi->hfinfo->name, fi->value.numeric);
665 snprintf(label_str, ITEM_LABEL_LENGTH,
666 "%s: %s (%s)", fi->hfinfo->name,
667 ether_to_str(fi->value.ether),
668 get_ether_name(fi->value.ether));
672 snprintf(label_str, ITEM_LABEL_LENGTH,
673 "%s: %s (%s)", fi->hfinfo->name,
674 get_hostname(fi->value.numeric),
675 ip_to_str((guint8*)&fi->value.numeric));
679 snprintf(label_str, ITEM_LABEL_LENGTH,
680 "%s: %s (%s)", fi->hfinfo->name,
681 get_hostname6((struct e_in6_addr *)fi->value.ipv6),
682 ip6_to_str((struct e_in6_addr*)fi->value.ipv6));
686 snprintf(label_str, ITEM_LABEL_LENGTH,
687 "%s: %s", fi->hfinfo->name, fi->value.string);
691 g_error("hfinfo->type %d not handled\n", fi->hfinfo->type);
697 fill_label_boolean(field_info *fi, gchar *label_str)
700 int bitfield_byte_length = 0, bitwidth;
701 guint32 unshifted_value;
703 struct header_field_info *hfinfo = fi->hfinfo;
704 struct true_false_string default_tf = { "True", "False" };
705 struct true_false_string *tfstring = &default_tf;
707 if (hfinfo->strings) {
708 tfstring = (struct true_false_string*) hfinfo->strings;
711 if (hfinfo->bitmask) {
712 /* Figure out the bit width */
713 bitwidth = hfinfo_bitwidth(hfinfo);
716 unshifted_value = fi->value.numeric;
717 if (hfinfo->bitshift > 0) {
718 unshifted_value <<= hfinfo->bitshift;
721 /* Create the bitfield first */
722 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
723 bitfield_byte_length = p - label_str;
726 /* Fill in the textual info */
727 snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
728 "%s: %s", hfinfo->name,
729 fi->value.numeric ? tfstring->true_string : tfstring->false_string);
733 /* Fills data for bitfield ints with val_strings */
735 fill_label_enumerated_bitfield(field_info *fi, gchar *label_str)
737 char *format = NULL, *p;
738 int bitfield_byte_length, bitwidth;
739 guint32 unshifted_value;
741 struct header_field_info *hfinfo = fi->hfinfo;
743 /* Figure out the bit width */
744 bitwidth = hfinfo_bitwidth(hfinfo);
746 /* Pick the proper format string */
747 format = hfinfo_uint_vals_format(hfinfo);
750 unshifted_value = fi->value.numeric;
751 if (hfinfo->bitshift > 0) {
752 unshifted_value <<= hfinfo->bitshift;
755 /* Create the bitfield first */
756 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
757 bitfield_byte_length = p - label_str;
759 /* Fill in the textual info using stored (shifted) value */
760 snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
761 format, hfinfo->name,
762 val_to_str(fi->value.numeric, cVALS(hfinfo->strings), "Unknown"),
767 fill_label_numeric_bitfield(field_info *fi, gchar *label_str)
769 char *format = NULL, *p;
770 int bitfield_byte_length, bitwidth;
771 guint32 unshifted_value;
773 struct header_field_info *hfinfo = fi->hfinfo;
775 /* Figure out the bit width */
776 bitwidth = hfinfo_bitwidth(hfinfo);
778 /* Pick the proper format string */
779 format = hfinfo_uint_format(hfinfo);
782 unshifted_value = fi->value.numeric;
783 if (hfinfo->bitshift > 0) {
784 unshifted_value <<= hfinfo->bitshift;
787 /* Create the bitfield using */
788 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
789 bitfield_byte_length = p - label_str;
791 /* Fill in the textual info using stored (shifted) value */
792 snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
793 format, hfinfo->name, fi->value.numeric);
797 fill_label_enumerated_uint(field_info *fi, gchar *label_str)
800 struct header_field_info *hfinfo = fi->hfinfo;
802 /* Pick the proper format string */
803 format = hfinfo_uint_vals_format(hfinfo);
805 /* Fill in the textual info */
806 snprintf(label_str, ITEM_LABEL_LENGTH,
807 format, hfinfo->name,
808 val_to_str(fi->value.numeric, cVALS(hfinfo->strings), "Unknown"),
813 fill_label_uint(field_info *fi, gchar *label_str)
816 struct header_field_info *hfinfo = fi->hfinfo;
818 /* Pick the proper format string */
819 format = hfinfo_uint_format(hfinfo);
821 /* Fill in the textual info */
822 snprintf(label_str, ITEM_LABEL_LENGTH,
823 format, hfinfo->name, fi->value.numeric);
827 hfinfo_bitwidth(header_field_info *hfinfo)
831 if (!hfinfo->bitmask) {
835 switch(hfinfo->type) {
853 bitwidth = hfinfo->display; /* hacky? :) */
856 g_assert_not_reached();
863 hfinfo_uint_vals_format(header_field_info *hfinfo)
867 switch(hfinfo->display) {
870 case BASE_OCT: /* I'm lazy */
871 case BASE_BIN: /* I'm lazy */
872 format = "%s: %s (%u)";
875 switch(hfinfo->type) {
878 format = "%s: %s (0x%02x)";
882 format = "%s: %s (0x%04x)";
886 format = "%s: %s (0x%06x)";
890 format = "%s: %s (0x%08x)";
893 g_assert_not_reached();
898 g_assert_not_reached();
905 hfinfo_uint_format(header_field_info *hfinfo)
909 /* Pick the proper format string */
910 switch(hfinfo->display) {
913 case BASE_OCT: /* I'm lazy */
914 case BASE_BIN: /* I'm lazy */
918 switch(hfinfo->type) {
921 format = "%s: 0x%02x";
925 format = "%s: 0x%04x";
929 format = "%s: 0x%06x";
933 format = "%s: 0x%08x";
936 g_assert_not_reached();
941 g_assert_not_reached();
950 proto_registrar_n(void)
952 return gpa_hfinfo->len;
956 proto_registrar_get_abbrev(int n)
958 struct header_field_info *hfinfo;
960 hfinfo = find_hfinfo_record(n);
962 return hfinfo->abbrev;
968 proto_registrar_get_ftype(int n)
970 struct header_field_info *hfinfo;
972 hfinfo = find_hfinfo_record(n);
980 proto_registrar_get_parent(int n)
982 struct header_field_info *hfinfo;
984 hfinfo = find_hfinfo_record(n);
986 return hfinfo->parent;
992 proto_registrar_is_protocol(int n)
994 struct header_field_info *hfinfo;
996 hfinfo = find_hfinfo_record(n);
998 return (hfinfo->parent == -1 ? TRUE : FALSE);
1003 /* Returns length of field.
1004 * 0 means undeterminable at time of registration
1005 * -1 means the field is not registered. */
1007 proto_registrar_get_length(int n)
1009 struct header_field_info *hfinfo;
1011 hfinfo = find_hfinfo_record(n);
1015 switch (hfinfo->type) {
1016 case FT_TEXT_ONLY: /* not filterable */
1017 case NUM_FIELD_TYPES: /* satisfy picky compilers */
1025 case FT_ABSOLUTE_TIME:
1026 case FT_RELATIVE_TIME:
1053 g_assert_not_reached();
1057 /* Looks for a protocol or a field in a proto_tree. Returns TRUE if
1058 * it exists anywhere, or FALSE if it exists nowhere. */
1060 proto_check_for_protocol_or_field(proto_tree* tree, int id)
1062 proto_tree_search_info sinfo;
1065 sinfo.result.node = NULL;
1067 sinfo.traverse_func = NULL;
1069 /* do a quicker check if target is a protocol */
1070 if (proto_registrar_is_protocol(id) == TRUE) {
1071 proto_find_protocol_multi(tree, id, &check_for_protocol_or_field_id, &sinfo);
1074 /* find the field's parent protocol */
1075 sinfo.parent = proto_registrar_get_parent(id);
1077 /* Go through each protocol subtree, checking if the protocols
1078 * is the parent protocol of the field that we're looking for.
1079 * We may have protocols that occur more than once (e.g., IP in IP),
1080 * so we do indeed have to check all protocol subtrees, looking
1081 * for the parent protocol. That's why proto_find_protocol()
1082 * is not used --- it assumes a protocol occurs only once. */
1083 g_node_traverse((GNode*)tree, G_IN_ORDER, G_TRAVERSE_ALL, 2,
1084 check_for_field_within_protocol, &sinfo);
1087 if (sinfo.result.node)
1094 check_for_protocol_or_field_id(GNode *node, gpointer data)
1096 field_info *fi = (field_info*) (node->data);
1097 proto_tree_search_info *sinfo = (proto_tree_search_info*) data;
1099 if (fi) { /* !fi == the top most container node which holds nothing */
1100 if (fi->hfinfo->id == sinfo->target) {
1101 sinfo->result.node = node;
1102 return TRUE; /* halt traversal */
1105 return FALSE; /* keep traversing */
1109 check_for_field_within_protocol(GNode *node, gpointer data)
1111 field_info *fi = (field_info*) (node->data);
1112 proto_tree_search_info *sinfo = (proto_tree_search_info*) data;
1114 if (fi) { /* !fi == the top most container node which holds nothing */
1115 if (fi->hfinfo->id == sinfo->parent) {
1116 g_node_traverse(node, G_IN_ORDER, G_TRAVERSE_ALL, -1,
1117 check_for_protocol_or_field_id, sinfo);
1118 if (sinfo->result.node)
1119 return TRUE; /* halt traversal */
1122 return FALSE; /* keep traversing */
1125 /* Looks for a protocol at the top layer of the tree. The protocol can occur
1126 * more than once, for those encapsulated protocols. For each protocol subtree
1127 * that is found, the callback function is called.
1130 proto_find_protocol_multi(proto_tree* tree, int target, GNodeTraverseFunc callback,
1131 proto_tree_search_info *sinfo)
1133 g_assert(callback != NULL);
1134 g_node_traverse((GNode*)tree, G_IN_ORDER, G_TRAVERSE_ALL, 2, callback, (gpointer*)sinfo);
1137 /* Simple wrappter to traverse all nodes, calling the sinfo traverse function with sinfo as an arg */
1139 proto_get_field_values(proto_tree* subtree, proto_tree_search_info *sinfo)
1141 /* Don't try to check value of top-level NULL GNode */
1142 if (!((GNode*)subtree)->data) {
1143 return FALSE; /* don't halt */
1145 g_node_traverse((GNode*)subtree, G_IN_ORDER, G_TRAVERSE_ALL, -1, sinfo->traverse_func, (gpointer*)sinfo);
1146 return FALSE; /* don't halt */
1149 /* Dumps the contents of the registration database to stdout. An indepedent program can take
1150 * this output and format it into nice tables or HTML or whatever.
1152 * There is one record per line. Each record is either a protocol or a header
1153 * field, differentiated by the first field. The fields are tab-delimited.
1158 * Field 2 = protocol name
1159 * Field 3 = protocol abbreviation
1164 * Field 2 = field name
1165 * Field 3 = field abbreviation
1166 * Field 4 = type ( textual representation of the the ftenum type )
1167 * Field 5 = parent protocol abbreviation
1170 proto_registrar_dump(void)
1172 header_field_info *hfinfo, *parent_hfinfo;
1174 const char *enum_name;
1176 len = gpa_hfinfo->len;
1177 for (i = 0; i < len ; i++) {
1178 hfinfo = find_hfinfo_record(i);
1180 /* format for protocols */
1181 if (proto_registrar_is_protocol(i)) {
1182 printf("P\t%s\t%s\n", hfinfo->name, hfinfo->abbrev);
1184 /* format for header fields */
1186 parent_hfinfo = find_hfinfo_record(hfinfo->parent);
1187 g_assert(parent_hfinfo);
1189 switch(hfinfo->type) {
1191 enum_name = "FT_NONE";
1194 enum_name = "FT_BOOLEAN";
1197 enum_name = "FT_UINT8";
1200 enum_name = "FT_UINT16";
1203 enum_name = "FT_UINT32";
1206 enum_name = "FT_INT8";
1209 enum_name = "FT_INT16";
1212 enum_name = "FT_INT24";
1215 enum_name = "FT_INT32";
1218 enum_name = "FT_DOUBLE";
1220 case FT_ABSOLUTE_TIME:
1221 enum_name = "FT_ABSOLUTE_TIME";
1223 case FT_RELATIVE_TIME:
1224 enum_name = "FT_RELATIVE_TIME";
1227 enum_name = "FT_STRING";
1230 enum_name = "FT_ETHER";
1233 enum_name = "FT_BYTES";
1236 enum_name = "FT_IPv4";
1239 enum_name = "FT_IPv6";
1242 enum_name = "FT_IPXNET";
1245 enum_name = "FT_TEXT_ONLY";
1248 enum_name = "UNKNOWN";
1251 printf("F\t%s\t%s\t%s\t%s\n", hfinfo->name, hfinfo->abbrev,
1252 enum_name,parent_hfinfo->abbrev);