Get rid of the check for NetBSD in the Wiretap "configure.in"; we
[obnox/wireshark/wip.git] / proto.c
1 /* proto.c
2  * Routines for protocol tree
3  *
4  * $Id: proto.c,v 1.53 2000/02/07 17:07:45 gram Exp $
5  *
6  * Ethereal - Network traffic analyzer
7  * By Gerald Combs <gerald@zing.org>
8  * Copyright 1998 Gerald Combs
9  *
10  * 
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.
15  * 
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.
20  * 
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.
24  */
25
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29
30 #ifdef HAVE_SYS_TYPES_H
31 # include <sys/types.h>
32 #endif
33
34 #ifndef _STDIO_H
35 #include <stdio.h>
36 #endif
37
38 #include <stdarg.h>
39
40 #ifndef _STRING_H
41 #include <string.h>
42 #endif
43
44 #ifdef NEED_SNPRINTF_H
45 # include "snprintf.h"
46 #endif
47
48 #ifndef __G_LIB_H__
49 #include <glib.h>
50 #endif
51
52 #ifndef __PROTO_H__
53 #include "proto.h"
54 #endif
55
56 #ifndef __PACKET_H__
57 #include "packet.h"
58 #endif
59
60 #ifndef __RESOLV_H__
61 #include "resolv.h"
62 #endif
63
64 #ifndef __REGISTER_H__
65 #include "register.h"
66 #endif
67
68 #include "packet-ipv6.h"
69
70 #define cVALS(x) (const value_string*)(x)
71
72 static gboolean
73 proto_tree_free_node(GNode *node, gpointer data);
74
75 static struct header_field_info*
76 find_hfinfo_record(int hfindex);
77
78
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);
86
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);
92
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);
95
96 static int proto_register_field_init(header_field_info *hfinfo, int parent);
97
98 /* special-case header field used within proto.c */
99 int hf_text_only = 1;
100
101 /* Contains information about protocols and header fields. Used when
102  * dissectors register their data */
103 GMemChunk *gmc_hfinfo = NULL;
104
105 /* Contains information about a field when a dissector calls
106  * proto_tree_add_item.  */
107 GMemChunk *gmc_field_info = NULL;
108
109 /* String space for protocol and field items for the GUI */
110 GMemChunk *gmc_item_labels = NULL;
111
112 /* List which stores protocols and fields that have been registered */
113 GPtrArray *gpa_hfinfo = NULL;
114
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;
119
120 /* Number of elements in that array. */
121 int             num_tree_types;
122
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.
126  */
127 gboolean proto_tree_is_visible = TRUE;
128
129 /* initialize data structures and register protocols and fields */
130 void
131 proto_init(void)
132 {
133         static hf_register_info hf[] = {
134                 { &hf_text_only,
135                 { "Text",       "text", FT_TEXT_ONLY, BASE_NONE, NULL, 0x0,
136                         "" }},
137         };
138
139         if (gmc_hfinfo)
140                 g_mem_chunk_destroy(gmc_hfinfo);
141         if (gmc_field_info)
142                 g_mem_chunk_destroy(gmc_field_info);
143         if (gmc_item_labels)
144                 g_mem_chunk_destroy(gmc_item_labels);
145         if (gpa_hfinfo)
146                 g_ptr_array_free(gpa_hfinfo, FALSE);
147         if (tree_is_expanded != NULL)
148                 g_free(tree_is_expanded);
149
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),
155                 G_ALLOC_AND_FREE);
156         gmc_item_labels = g_mem_chunk_new("gmc_item_labels",
157                 ITEM_LABEL_LENGTH, 20 * ITEM_LABEL_LENGTH,
158                 G_ALLOC_AND_FREE);
159         gpa_hfinfo = g_ptr_array_new();
160
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;
165         num_tree_types = 1;
166
167         /* Have each dissector register its protocols and fields. */
168         register_all_protocols();
169
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));
174
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 *));
179 }
180
181 void
182 proto_cleanup(void)
183 {
184         if (gmc_hfinfo)
185                 g_mem_chunk_destroy(gmc_hfinfo);
186         if (gmc_field_info)
187                 g_mem_chunk_destroy(gmc_field_info);
188         if (gmc_item_labels)
189                 g_mem_chunk_destroy(gmc_item_labels);
190         if (gpa_hfinfo)
191                 g_ptr_array_free(gpa_hfinfo, FALSE);
192 }
193
194 /* frees the resources that the dissection a proto_tree uses */
195 void
196 proto_tree_free(proto_tree *tree)
197 {
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);
201 }
202
203 static gboolean
204 proto_tree_free_node(GNode *node, gpointer data)
205 {
206         field_info *fi = (field_info*) (node->data);
207
208         if (fi != NULL) {
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);
216         }
217         return FALSE; /* FALSE = do not end traversal of GNode tree */
218 }       
219
220 /* Finds a record in the hf_info_records array. */
221 static struct header_field_info*
222 find_hfinfo_record(int hfindex)
223 {
224         g_assert(hfindex >= 0 && hfindex < gpa_hfinfo->len);
225         return g_ptr_array_index(gpa_hfinfo, hfindex);
226 }
227
228 proto_item *
229 proto_tree_add_item(proto_tree *tree, int hfindex, gint start, gint length, ...)
230 {
231         proto_item      *pi;
232         va_list         ap;
233
234         va_start(ap, length);
235         pi = _proto_tree_add_item_value(tree, hfindex, start, length, 0, 1, ap);
236         va_end(ap);
237
238         return pi;
239 }
240
241 proto_item *
242 proto_tree_add_item_hidden(proto_tree *tree, int hfindex, gint start, gint length, ...)
243 {
244         proto_item      *pi;
245         va_list         ap;
246
247         va_start(ap, length);
248         pi = _proto_tree_add_item_value(tree, hfindex, start, length, 0, 0, ap);
249         va_end(ap);
250
251         return pi;
252 }
253
254 proto_item *
255 proto_tree_add_item_format(proto_tree *tree, int hfindex, gint start, gint length, ...)
256 {
257         proto_item      *pi;
258         va_list         ap;
259
260         va_start(ap, length);
261         pi = _proto_tree_add_item_value(tree, hfindex, start, length, 1, 1, ap);
262         va_end(ap);
263
264         return pi;
265 }
266
267 proto_item *
268 proto_tree_add_notext(proto_tree *tree, gint start, gint length, ...)
269 {
270         proto_item      *pi;
271         va_list         ap;
272
273         va_start(ap, length);
274         pi = _proto_tree_add_item_value(tree, hf_text_only, start, length, 0, 1, ap);
275         va_end(ap);
276
277         return pi;
278 }
279
280 proto_item *
281 proto_tree_add_text(proto_tree *tree, gint start, gint length, ...)
282 {
283         proto_item      *pi;
284         va_list         ap;
285
286         va_start(ap, length);
287         pi = _proto_tree_add_item_value(tree, hf_text_only, start, length, 1, 1, ap);
288         va_end(ap);
289
290         return pi;
291 }
292
293 proto_item *
294 _proto_tree_add_item_value(proto_tree *tree, int hfindex, gint start,
295         gint length, int include_format, int visible, va_list ap)
296 {
297         proto_item      *pi;
298         field_info      *fi;
299         char            *junk, *format;
300         header_field_info *hfinfo;
301
302         if (!tree)
303                 return(NULL);
304
305         /* either visibility flag can nullify the other */
306         visible = proto_tree_is_visible && visible;
307
308         fi = g_mem_chunk_alloc(gmc_field_info);
309
310         fi->hfinfo = find_hfinfo_record(hfindex);
311         g_assert(fi->hfinfo != NULL);
312         fi->start = start;
313         fi->length = length;
314         fi->tree_type = ETT_NONE;
315         fi->visible = visible;
316
317         /* for convenience */
318
319         hfinfo = fi->hfinfo;
320 /* from the stdarg man page on Solaris 2.6:
321 NOTES
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
332      function.
333 */
334         switch(hfinfo->type) {
335                 case FT_NONE:
336                         junk = va_arg(ap, guint8*);
337                         break;
338
339                 case FT_BYTES:
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);
344                         break;
345
346                 case FT_BOOLEAN:
347                 case FT_UINT8:
348                 case FT_UINT16:
349                 case FT_UINT24:
350                 case FT_UINT32:
351                 case FT_INT8:
352                 case FT_INT16:
353                 case FT_INT24:
354                 case FT_INT32:
355                         fi->value.numeric = va_arg(ap, unsigned int);
356                         if (hfinfo->bitmask) {
357                                 /* Mask out irrelevant portions */
358                                 fi->value.numeric &= hfinfo->bitmask;
359
360                                 /* Shift bits */
361                                 if (hfinfo->bitshift > 0) {
362                                         fi->value.numeric >>= hfinfo->bitshift;
363                                 }
364                         }
365                         break;
366
367                 case FT_IPv4:
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);
370                         break;
371
372                 case FT_IPXNET:
373                         fi->value.numeric = va_arg(ap, unsigned int);
374                         break;
375
376                 case FT_IPv6:
377                         memcpy(fi->value.ipv6, va_arg(ap, guint8*), 16);
378                         break;
379
380                 case FT_DOUBLE:
381                         fi->value.floating = va_arg(ap, double);
382                         break;
383
384                 case FT_ETHER:
385                         memcpy(fi->value.ether, va_arg(ap, guint8*), 6);
386                         break;
387
388                 case FT_ABSOLUTE_TIME:
389                 case FT_RELATIVE_TIME:
390                         memcpy(&fi->value.time, va_arg(ap, struct timeval*),
391                                 sizeof(struct timeval));
392                         break;
393
394                 case FT_STRING:
395                         /* This g_strdup'ed memory is freed in proto_tree_free_node() */
396                         fi->value.string = g_strdup(va_arg(ap, char*));
397                         break;
398
399                 case FT_TEXT_ONLY:
400                         ; /* nothing */
401                         break;
402
403                 default:
404                         g_error("hfinfo->type %d not handled\n", hfinfo->type);
405                         break;
406         }
407
408         pi = (proto_item*) g_node_new(fi);
409         g_node_append((GNode*)tree, (GNode*)pi);
410
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,
416                                 format, ap);
417         }
418         else {
419                 fi->representation = NULL;
420         }
421
422         return pi;
423 }
424
425 void
426 proto_item_set_text(proto_item *pi, ...)
427 {
428         field_info *fi = (field_info*) (((GNode*)pi)->data);
429         va_list ap;
430         char *format;
431
432         if (fi->representation)
433                 g_mem_chunk_free(gmc_item_labels, fi->representation);
434
435         fi->representation = g_mem_chunk_alloc(gmc_item_labels);
436         va_start(ap, pi);
437         format = va_arg(ap, char*);
438         vsnprintf(fi->representation, ITEM_LABEL_LENGTH,
439                                 format, ap);
440         va_end(ap);
441 }
442
443 void
444 proto_item_set_len(proto_item *pi, gint length)
445 {
446         field_info *fi = (field_info*) (((GNode*)pi)->data);
447         fi->length = length;
448 }
449
450 proto_tree*
451 proto_tree_create_root(void)
452 {
453         return (proto_tree*) g_node_new(NULL);
454 }
455
456 proto_tree*
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);
460         fi->tree_type = idx;
461         return (proto_tree*) pi;
462 }
463
464
465 int
466 proto_register_protocol(char *name, char *abbrev)
467 {
468         struct header_field_info *hfinfo;
469
470         /* Here we do allocate a new header_field_info struct */
471         hfinfo = g_mem_chunk_alloc(gmc_hfinfo);
472         hfinfo->name = name;
473         hfinfo->abbrev = abbrev;
474         hfinfo->type = FT_NONE;
475         hfinfo->strings = NULL;
476         hfinfo->bitmask = 0;
477         hfinfo->bitshift = 0;
478         hfinfo->blurb = "";
479         hfinfo->parent = -1; /* this field differentiates protos and fields */
480
481         return proto_register_field_init(hfinfo, hfinfo->parent);
482 }
483
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 */
486 void
487 proto_register_field_array(int parent, hf_register_info *hf, int num_records)
488 {
489         int                     field_id, i;
490         hf_register_info        *ptr = hf;
491
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;
495         }
496 }
497
498 static int
499 proto_register_field_init(header_field_info *hfinfo, int parent)
500 {
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) ));
512
513         /* if this is a bitfield, compure bitshift */
514         if (hfinfo->bitmask) {
515                 while ((hfinfo->bitmask & (1 << hfinfo->bitshift)) == 0)
516                         hfinfo->bitshift++;
517         }
518
519         hfinfo->parent = parent;
520
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;
524         return hfinfo->id;
525 }
526
527 void
528 proto_register_subtree_array(gint **indices, int num_indices)
529 {
530         int     i;
531         gint    **ptr = indices;
532
533         /*
534          * Add "num_indices" elements to "tree_is_expanded".
535          */
536         tree_is_expanded = g_realloc(tree_is_expanded,
537             (num_tree_types + num_indices)*sizeof (gint));
538
539         /*
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.
545          */
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;
549         }
550 }
551
552 void
553 proto_item_fill_label(field_info *fi, gchar *label_str)
554 {
555         struct header_field_info        *hfinfo = fi->hfinfo;
556         guint32                         n_addr; /* network-order IPv4 address */
557
558         switch(hfinfo->type) {
559                 case FT_NONE:
560                         snprintf(label_str, ITEM_LABEL_LENGTH,
561                                 "%s", hfinfo->name);
562                         break;
563
564                 case FT_BOOLEAN:
565                         fill_label_boolean(fi, label_str);
566                         break;
567
568                 case FT_BYTES:
569                         snprintf(label_str, ITEM_LABEL_LENGTH,
570                                 "%s: %s", hfinfo->name, 
571                                  bytes_to_str(fi->value.bytes, fi->length));
572                         break;
573
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
579                  */
580                 case FT_UINT8:
581                 case FT_UINT16:
582                 case FT_UINT24:
583                 case FT_UINT32:
584                         if (hfinfo->bitmask) {
585                                 if (hfinfo->strings) {
586                                         fill_label_enumerated_bitfield(fi, label_str);
587                                 }
588                                 else {
589                                         fill_label_numeric_bitfield(fi, label_str);
590                                 }
591                         }
592                         else {
593                                 if (hfinfo->strings) {
594                                         fill_label_enumerated_uint(fi, label_str);
595                                 }
596                                 else {
597                                         fill_label_uint(fi, label_str);
598                                 }
599                         }
600                         break;
601
602                 case FT_INT8:
603                 case FT_INT16:
604                 case FT_INT24:
605                 case FT_INT32:
606                         g_assert(!hfinfo->bitmask);
607                         if (hfinfo->strings) {
608                                 fill_label_enumerated_int(fi, label_str);
609                         }
610                         else {
611                                 fill_label_int(fi, label_str);
612                         }
613                         break;
614
615                 case FT_DOUBLE:
616                         snprintf(label_str, ITEM_LABEL_LENGTH,
617                                 "%s: %g", fi->hfinfo->name,
618                                 fi->value.floating);
619                         break;
620
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));
625                         break;
626
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));
631                         break;
632
633                 case FT_IPXNET:
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));
637                         break;
638
639                 case FT_ETHER:
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));
644                         break;
645
646                 case FT_IPv4:
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));
652                         break;
653
654                 case FT_IPv6:
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));
659                         break;
660         
661                 case FT_STRING:
662                         snprintf(label_str, ITEM_LABEL_LENGTH,
663                                 "%s: %s", fi->hfinfo->name, fi->value.string);
664                         break;
665
666                 default:
667                         g_error("hfinfo->type %d not handled\n", fi->hfinfo->type);
668                         break;
669         }
670 }
671
672 static void
673 fill_label_boolean(field_info *fi, gchar *label_str)
674 {
675         char *p = label_str;
676         int bitfield_byte_length = 0, bitwidth;
677         guint32 unshifted_value;
678
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;
682
683         if (hfinfo->strings) {
684                 tfstring = (struct true_false_string*) hfinfo->strings;
685         }
686
687         if (hfinfo->bitmask) {
688                 /* Figure out the bit width */
689                 bitwidth = hfinfo_bitwidth(hfinfo);
690
691                 /* Un-shift bits */
692                 unshifted_value = fi->value.numeric;
693                 if (hfinfo->bitshift > 0) {
694                         unshifted_value <<= hfinfo->bitshift;
695                 }
696
697                 /* Create the bitfield first */
698                 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
699                 bitfield_byte_length = p - label_str;
700         }
701
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);
706 }
707
708
709 /* Fills data for bitfield ints with val_strings */
710 static void
711 fill_label_enumerated_bitfield(field_info *fi, gchar *label_str)
712 {
713         char *format = NULL, *p;
714         int bitfield_byte_length, bitwidth;
715         guint32 unshifted_value;
716
717         struct header_field_info        *hfinfo = fi->hfinfo;
718
719         /* Figure out the bit width */
720         bitwidth = hfinfo_bitwidth(hfinfo);
721
722         /* Pick the proper format string */
723         format = hfinfo_uint_vals_format(hfinfo);
724
725         /* Un-shift bits */
726         unshifted_value = fi->value.numeric;
727         if (hfinfo->bitshift > 0) {
728                 unshifted_value <<= hfinfo->bitshift;
729         }
730
731         /* Create the bitfield first */
732         p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
733         bitfield_byte_length = p - label_str;
734
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"),
739                         fi->value.numeric);
740 }
741
742 static void
743 fill_label_numeric_bitfield(field_info *fi, gchar *label_str)
744 {
745         char *format = NULL, *p;
746         int bitfield_byte_length, bitwidth;
747         guint32 unshifted_value;
748
749         struct header_field_info        *hfinfo = fi->hfinfo;
750
751         /* Figure out the bit width */
752         bitwidth = hfinfo_bitwidth(hfinfo);
753
754         /* Pick the proper format string */
755         format = hfinfo_uint_format(hfinfo);
756
757         /* Un-shift bits */
758         unshifted_value = fi->value.numeric;
759         if (hfinfo->bitshift > 0) {
760                 unshifted_value <<= hfinfo->bitshift;
761         }
762
763         /* Create the bitfield using */
764         p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
765         bitfield_byte_length = p - label_str;
766
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);
770 }
771
772 static void
773 fill_label_enumerated_uint(field_info *fi, gchar *label_str)
774 {
775         char *format = NULL;
776         struct header_field_info        *hfinfo = fi->hfinfo;
777
778         /* Pick the proper format string */
779         format = hfinfo_uint_vals_format(hfinfo);
780
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"),
785                         fi->value.numeric);
786 }
787
788 static void
789 fill_label_uint(field_info *fi, gchar *label_str)
790 {
791         char *format = NULL;
792         struct header_field_info        *hfinfo = fi->hfinfo;
793
794         /* Pick the proper format string */
795         format = hfinfo_uint_format(hfinfo);
796
797         /* Fill in the textual info */
798         snprintf(label_str, ITEM_LABEL_LENGTH,
799                         format,  hfinfo->name, fi->value.numeric);
800 }
801
802 static void
803 fill_label_enumerated_int(field_info *fi, gchar *label_str)
804 {
805         char *format = NULL;
806         struct header_field_info        *hfinfo = fi->hfinfo;
807
808         /* Pick the proper format string */
809         format = hfinfo_int_vals_format(hfinfo);
810
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"),
815                         fi->value.numeric);
816 }
817
818 static void
819 fill_label_int(field_info *fi, gchar *label_str)
820 {
821         char *format = NULL;
822         struct header_field_info        *hfinfo = fi->hfinfo;
823
824         /* Pick the proper format string */
825         format = hfinfo_int_format(hfinfo);
826
827         /* Fill in the textual info */
828         snprintf(label_str, ITEM_LABEL_LENGTH,
829                         format,  hfinfo->name, fi->value.numeric);
830 }
831
832 static int
833 hfinfo_bitwidth(header_field_info *hfinfo)
834 {
835         int bitwidth = 0;
836
837         if (!hfinfo->bitmask) {
838                 return 0;
839         }
840
841         switch(hfinfo->type) {
842                 case FT_UINT8:
843                 case FT_INT8:
844                         bitwidth = 8;
845                         break;
846                 case FT_UINT16:
847                 case FT_INT16:
848                         bitwidth = 16;
849                         break;
850                 case FT_UINT24:
851                 case FT_INT24:
852                         bitwidth = 24;
853                         break;
854                 case FT_UINT32:
855                 case FT_INT32:
856                         bitwidth = 32;
857                         break;
858                 case FT_BOOLEAN:
859                         bitwidth = hfinfo->display; /* hacky? :) */
860                         break;
861                 default:
862                         g_assert_not_reached();
863                         ;
864         }
865         return bitwidth;
866 }
867
868 static char*
869 hfinfo_uint_vals_format(header_field_info *hfinfo)
870 {
871         char *format = NULL;
872
873         switch(hfinfo->display) {
874                 case BASE_DEC:
875                 case BASE_NONE:
876                 case BASE_OCT: /* I'm lazy */
877                 case BASE_BIN: /* I'm lazy */
878                         format = "%s: %s (%u)";
879                         break;
880                 case BASE_HEX:
881                         switch(hfinfo->type) {
882                                 case FT_UINT8:
883                                         format = "%s: %s (0x%02x)";
884                                         break;
885                                 case FT_UINT16:
886                                         format = "%s: %s (0x%04x)";
887                                         break;
888                                 case FT_UINT24:
889                                         format = "%s: %s (0x%06x)";
890                                         break;
891                                 case FT_UINT32:
892                                         format = "%s: %s (0x%08x)";
893                                         break;
894                                 default:
895                                         g_assert_not_reached();
896                                         ;
897                         }
898                         break;
899                 default:
900                         g_assert_not_reached();
901                         ;
902         }
903         return format;
904 }
905
906 static char*
907 hfinfo_uint_format(header_field_info *hfinfo)
908 {
909         char *format = NULL;
910
911         /* Pick the proper format string */
912         switch(hfinfo->display) {
913                 case BASE_DEC:
914                 case BASE_NONE:
915                 case BASE_OCT: /* I'm lazy */
916                 case BASE_BIN: /* I'm lazy */
917                         format = "%s: %u";
918                         break;
919                 case BASE_HEX:
920                         switch(hfinfo->type) {
921                                 case FT_UINT8:
922                                         format = "%s: 0x%02x";
923                                         break;
924                                 case FT_UINT16:
925                                         format = "%s: 0x%04x";
926                                         break;
927                                 case FT_UINT24:
928                                         format = "%s: 0x%06x";
929                                         break;
930                                 case FT_UINT32:
931                                         format = "%s: 0x%08x";
932                                         break;
933                                 default:
934                                         g_assert_not_reached();
935                                         ;
936                         }
937                         break;
938                 default:
939                         g_assert_not_reached();
940                         ;
941         }
942         return format;
943 }
944
945 static char*
946 hfinfo_int_vals_format(header_field_info *hfinfo)
947 {
948         char *format = NULL;
949
950         switch(hfinfo->display) {
951                 case BASE_DEC:
952                 case BASE_NONE:
953                 case BASE_OCT: /* I'm lazy */
954                 case BASE_BIN: /* I'm lazy */
955                         format = "%s: %s (%d)";
956                         break;
957                 case BASE_HEX:
958                         switch(hfinfo->type) {
959                                 case FT_INT8:
960                                         format = "%s: %s (0x%02x)";
961                                         break;
962                                 case FT_INT16:
963                                         format = "%s: %s (0x%04x)";
964                                         break;
965                                 case FT_INT24:
966                                         format = "%s: %s (0x%06x)";
967                                         break;
968                                 case FT_INT32:
969                                         format = "%s: %s (0x%08x)";
970                                         break;
971                                 default:
972                                         g_assert_not_reached();
973                                         ;
974                         }
975                         break;
976                 default:
977                         g_assert_not_reached();
978                         ;
979         }
980         return format;
981 }
982
983 static char*
984 hfinfo_int_format(header_field_info *hfinfo)
985 {
986         char *format = NULL;
987
988         /* Pick the proper format string */
989         switch(hfinfo->display) {
990                 case BASE_DEC:
991                 case BASE_NONE:
992                 case BASE_OCT: /* I'm lazy */
993                 case BASE_BIN: /* I'm lazy */
994                         format = "%s: %d";
995                         break;
996                 case BASE_HEX:
997                         switch(hfinfo->type) {
998                                 case FT_INT8:
999                                         format = "%s: 0x%02x";
1000                                         break;
1001                                 case FT_INT16:
1002                                         format = "%s: 0x%04x";
1003                                         break;
1004                                 case FT_INT24:
1005                                         format = "%s: 0x%06x";
1006                                         break;
1007                                 case FT_INT32:
1008                                         format = "%s: 0x%08x";
1009                                         break;
1010                                 default:
1011                                         g_assert_not_reached();
1012                                         ;
1013                         }
1014                         break;
1015                 default:
1016                         g_assert_not_reached();
1017                         ;
1018         }
1019         return format;
1020 }
1021
1022
1023
1024 int
1025 proto_registrar_n(void)
1026 {
1027         return gpa_hfinfo->len;
1028 }
1029
1030 char*
1031 proto_registrar_get_name(int n)
1032 {
1033     struct header_field_info *hfinfo;
1034     hfinfo = find_hfinfo_record(n);
1035     if (hfinfo)
1036         return hfinfo->name;
1037     else        return NULL;
1038 }
1039
1040 char*
1041 proto_registrar_get_abbrev(int n)
1042 {
1043         struct header_field_info *hfinfo;
1044
1045         hfinfo = find_hfinfo_record(n);
1046         if (hfinfo)
1047                 return hfinfo->abbrev;
1048         else
1049                 return NULL;
1050 }
1051
1052 int
1053 proto_registrar_get_ftype(int n)
1054 {
1055         struct header_field_info *hfinfo;
1056
1057         hfinfo = find_hfinfo_record(n);
1058         if (hfinfo)
1059                 return hfinfo->type;
1060         else
1061                 return -1;
1062 }
1063
1064 int
1065 proto_registrar_get_parent(int n)
1066 {
1067         struct header_field_info *hfinfo;
1068
1069         hfinfo = find_hfinfo_record(n);
1070         if (hfinfo)
1071                 return hfinfo->parent;
1072         else
1073                 return -2;
1074 }
1075
1076 gboolean
1077 proto_registrar_is_protocol(int n)
1078 {
1079         struct header_field_info *hfinfo;
1080
1081         hfinfo = find_hfinfo_record(n);
1082         if (hfinfo)
1083                 return (hfinfo->parent == -1 ? TRUE : FALSE);
1084         else
1085                 return FALSE;
1086 }
1087
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. */
1092 gint
1093 proto_registrar_get_length(int n)
1094 {
1095         struct header_field_info *hfinfo;
1096
1097         hfinfo = find_hfinfo_record(n);
1098         if (!hfinfo)
1099                 return -1;
1100
1101         switch (hfinfo->type) {
1102                 case FT_TEXT_ONLY: /* not filterable */
1103                 case NUM_FIELD_TYPES: /* satisfy picky compilers */
1104                         return -1;
1105
1106                 case FT_NONE:
1107                 case FT_BYTES:
1108                 case FT_BOOLEAN:
1109                 case FT_STRING:
1110                 case FT_DOUBLE:
1111                 case FT_ABSOLUTE_TIME:
1112                 case FT_RELATIVE_TIME:
1113                         return 0;
1114
1115                 case FT_UINT8:
1116                 case FT_INT8:
1117                         return 1;
1118
1119                 case FT_UINT16:
1120                 case FT_INT16:
1121                         return 2;
1122
1123                 case FT_UINT24:
1124                 case FT_INT24:
1125                         return 3;
1126
1127                 case FT_UINT32:
1128                 case FT_INT32:
1129                 case FT_IPXNET:
1130                 case FT_IPv4:
1131                         return 4;
1132
1133                 case FT_ETHER:
1134                         return 6;
1135
1136                 case FT_IPv6:
1137                         return 16;
1138         }
1139         g_assert_not_reached();
1140         return -1;
1141 }
1142
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. */
1145 gboolean
1146 proto_check_for_protocol_or_field(proto_tree* tree, int id)
1147 {
1148         proto_tree_search_info  sinfo;
1149
1150         sinfo.target = id;
1151         sinfo.result.node = NULL;
1152         sinfo.parent = -1;
1153         sinfo.traverse_func = NULL;
1154
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);
1158         }
1159         else {
1160                 /* find the field's parent protocol */
1161                 sinfo.parent = proto_registrar_get_parent(id);
1162
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);
1171         }
1172
1173         if (sinfo.result.node)
1174                 return TRUE;
1175         else
1176                 return FALSE;
1177 }
1178
1179 static gboolean
1180 check_for_protocol_or_field_id(GNode *node, gpointer data)
1181 {
1182         field_info              *fi = (field_info*) (node->data);
1183         proto_tree_search_info  *sinfo = (proto_tree_search_info*) data;
1184
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 */
1189                 }
1190         }
1191         return FALSE; /* keep traversing */
1192 }
1193
1194 static gboolean
1195 check_for_field_within_protocol(GNode *node, gpointer data)
1196 {
1197         field_info              *fi = (field_info*) (node->data);
1198         proto_tree_search_info  *sinfo = (proto_tree_search_info*) data;
1199
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 */
1206                 }
1207         }
1208         return FALSE; /* keep traversing */
1209 }
1210
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.
1214  */
1215 void
1216 proto_find_protocol_multi(proto_tree* tree, int target, GNodeTraverseFunc callback,
1217                         proto_tree_search_info *sinfo)
1218 {
1219         g_assert(callback != NULL);
1220         g_node_traverse((GNode*)tree, G_IN_ORDER, G_TRAVERSE_ALL, 2, callback, (gpointer*)sinfo);
1221 }
1222
1223 /* Simple wrappter to traverse all nodes, calling the sinfo traverse function with sinfo as an arg */
1224 gboolean
1225 proto_get_field_values(proto_tree* subtree, proto_tree_search_info *sinfo)
1226 {
1227         /* Don't try to check value of top-level NULL GNode */
1228         if (!((GNode*)subtree)->data) {
1229                 return FALSE; /* don't halt */
1230         }
1231         g_node_traverse((GNode*)subtree, G_IN_ORDER, G_TRAVERSE_ALL, -1, sinfo->traverse_func, (gpointer*)sinfo);
1232         return FALSE; /* don't halt */
1233 }
1234
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.
1237  *
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.
1240  *
1241  * Protocols
1242  * ---------
1243  * Field 1 = 'P'
1244  * Field 2 = protocol name
1245  * Field 3 = protocol abbreviation
1246  *
1247  * Header Fields
1248  * -------------
1249  * Field 1 = 'F'
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
1254  */
1255 void
1256 proto_registrar_dump(void)
1257 {
1258         header_field_info       *hfinfo, *parent_hfinfo;
1259         int                     i, len;
1260         const char              *enum_name;
1261
1262         len = gpa_hfinfo->len;
1263         for (i = 0; i < len ; i++) {
1264                 hfinfo = find_hfinfo_record(i);
1265
1266                 /* format for protocols */
1267                 if (proto_registrar_is_protocol(i)) {
1268                         printf("P\t%s\t%s\n", hfinfo->name, hfinfo->abbrev);
1269                 }
1270                 /* format for header fields */
1271                 else {
1272                         parent_hfinfo = find_hfinfo_record(hfinfo->parent);
1273                         g_assert(parent_hfinfo);
1274
1275                         switch(hfinfo->type) {
1276                         case FT_NONE:
1277                                 enum_name = "FT_NONE";
1278                                 break;
1279                         case FT_BOOLEAN:
1280                                 enum_name = "FT_BOOLEAN";
1281                                 break;
1282                         case FT_UINT8:
1283                                 enum_name = "FT_UINT8";
1284                                 break;
1285                         case FT_UINT16:
1286                                 enum_name = "FT_UINT16";
1287                                 break;
1288                         case FT_UINT24:
1289                                 enum_name = "FT_UINT24";
1290                                 break;
1291                         case FT_UINT32:
1292                                 enum_name = "FT_UINT32";
1293                                 break;
1294                         case FT_INT8:
1295                                 enum_name = "FT_INT8";
1296                                 break;
1297                         case FT_INT16:
1298                                 enum_name = "FT_INT16";
1299                                 break;
1300                         case FT_INT24:
1301                                 enum_name = "FT_INT24";
1302                                 break;
1303                         case FT_INT32:
1304                                 enum_name = "FT_INT32";
1305                                 break;
1306                         case FT_DOUBLE:
1307                                 enum_name = "FT_DOUBLE";
1308                                 break;
1309                         case FT_ABSOLUTE_TIME:
1310                                 enum_name = "FT_ABSOLUTE_TIME";
1311                                 break;
1312                         case FT_RELATIVE_TIME:
1313                                 enum_name = "FT_RELATIVE_TIME";
1314                                 break;
1315                         case FT_STRING:
1316                                 enum_name = "FT_STRING";
1317                                 break;
1318                         case FT_ETHER:
1319                                 enum_name = "FT_ETHER";
1320                                 break;
1321                         case FT_BYTES:
1322                                 enum_name = "FT_BYTES";
1323                                 break;
1324                         case FT_IPv4:
1325                                 enum_name = "FT_IPv4";
1326                                 break;
1327                         case FT_IPv6:
1328                                 enum_name = "FT_IPv6";
1329                                 break;
1330                         case FT_IPXNET:
1331                                 enum_name = "FT_IPXNET";
1332                                 break;
1333                         case FT_TEXT_ONLY:
1334                                 enum_name = "FT_TEXT_ONLY";
1335                                 break;
1336                         default:
1337                                 enum_name = "UNKNOWN";
1338                                 break;
1339                         }
1340                         printf("F\t%s\t%s\t%s\t%s\n", hfinfo->name, hfinfo->abbrev,
1341                                 enum_name,parent_hfinfo->abbrev);
1342                 }
1343         }
1344 }