Ethereal shouldn't use "file_seek()", "file_read()", or "file_write()"
[obnox/wireshark/wip.git] / proto.c
1 /* proto.c
2  * Routines for protocol tree
3  *
4  * $Id: proto.c,v 1.52 2000/01/22 04:59:55 guy 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 static proto_item *
79 proto_tree_add_item_value(proto_tree *tree, int hfindex, gint start,
80         gint length, int include_format, int visible, va_list ap);
81
82 static void fill_label_boolean(field_info *fi, gchar *label_str);
83 static void fill_label_uint(field_info *fi, gchar *label_str);
84 static void fill_label_enumerated_uint(field_info *fi, gchar *label_str);
85 static void fill_label_enumerated_bitfield(field_info *fi, gchar *label_str);
86 static void fill_label_numeric_bitfield(field_info *fi, gchar *label_str);
87 static void fill_label_int(field_info *fi, gchar *label_str);
88 static void fill_label_enumerated_int(field_info *fi, gchar *label_str);
89
90 static int hfinfo_bitwidth(header_field_info *hfinfo);
91 static char* hfinfo_uint_vals_format(header_field_info *hfinfo);
92 static char* hfinfo_uint_format(header_field_info *hfinfo);
93 static char* hfinfo_int_vals_format(header_field_info *hfinfo);
94 static char* hfinfo_int_format(header_field_info *hfinfo);
95
96 static gboolean check_for_protocol_or_field_id(GNode *node, gpointer data);
97 static gboolean check_for_field_within_protocol(GNode *node, gpointer data);
98
99 static int proto_register_field_init(header_field_info *hfinfo, int parent);
100
101 /* special-case header field used within proto.c */
102 int hf_text_only = 1;
103
104 /* Contains information about protocols and header fields. Used when
105  * dissectors register their data */
106 GMemChunk *gmc_hfinfo = NULL;
107
108 /* Contains information about a field when a dissector calls
109  * proto_tree_add_item.  */
110 GMemChunk *gmc_field_info = NULL;
111
112 /* String space for protocol and field items for the GUI */
113 GMemChunk *gmc_item_labels = NULL;
114
115 /* List which stores protocols and fields that have been registered */
116 GPtrArray *gpa_hfinfo = NULL;
117
118 /* Points to the first element of an array of Booleans, indexed by
119    a subtree item type; that array element is TRUE if subtrees of
120    an item of that type are to be expanded. */
121 gboolean        *tree_is_expanded;
122
123 /* Number of elements in that array. */
124 int             num_tree_types;
125
126 /* Is the parsing being done for a visible proto_tree or an invisible one?
127  * By setting this correctly, the proto_tree creation is sped up by not
128  * having to call vsnprintf and copy strings around.
129  */
130 gboolean proto_tree_is_visible = TRUE;
131
132 /* initialize data structures and register protocols and fields */
133 void
134 proto_init(void)
135 {
136         static hf_register_info hf[] = {
137                 { &hf_text_only,
138                 { "Text",       "text", FT_TEXT_ONLY, BASE_NONE, NULL, 0x0,
139                         "" }},
140         };
141
142         if (gmc_hfinfo)
143                 g_mem_chunk_destroy(gmc_hfinfo);
144         if (gmc_field_info)
145                 g_mem_chunk_destroy(gmc_field_info);
146         if (gmc_item_labels)
147                 g_mem_chunk_destroy(gmc_item_labels);
148         if (gpa_hfinfo)
149                 g_ptr_array_free(gpa_hfinfo, FALSE);
150         if (tree_is_expanded != NULL)
151                 g_free(tree_is_expanded);
152
153         gmc_hfinfo = g_mem_chunk_new("gmc_hfinfo",
154                 sizeof(struct header_field_info), 50 * sizeof(struct 
155                 header_field_info), G_ALLOC_ONLY);
156         gmc_field_info = g_mem_chunk_new("gmc_field_info",
157                 sizeof(struct field_info), 200 * sizeof(struct field_info),
158                 G_ALLOC_AND_FREE);
159         gmc_item_labels = g_mem_chunk_new("gmc_item_labels",
160                 ITEM_LABEL_LENGTH, 20 * ITEM_LABEL_LENGTH,
161                 G_ALLOC_AND_FREE);
162         gpa_hfinfo = g_ptr_array_new();
163
164         /* Allocate "tree_is_expanded", with one element for ETT_NONE,
165            and initialize that element to FALSE. */
166         tree_is_expanded = g_malloc(sizeof (gint));
167         tree_is_expanded[0] = FALSE;
168         num_tree_types = 1;
169
170         /* Have each dissector register its protocols and fields. */
171         register_all_protocols();
172
173         /* Register one special-case FT_TEXT_ONLY field for use when
174                 converting ethereal to new-style proto_tree. These fields
175                 are merely strings on the GUI tree; they are not filterable */
176         proto_register_field_array(-1, hf, array_length(hf));
177
178         /* We've assigned all the subtree type values; allocate the array
179            for them, and zero it out. */
180         tree_is_expanded = g_malloc(num_tree_types*sizeof (gint *));
181         memset(tree_is_expanded, '\0', num_tree_types*sizeof (gint *));
182 }
183
184 void
185 proto_cleanup(void)
186 {
187         if (gmc_hfinfo)
188                 g_mem_chunk_destroy(gmc_hfinfo);
189         if (gmc_field_info)
190                 g_mem_chunk_destroy(gmc_field_info);
191         if (gmc_item_labels)
192                 g_mem_chunk_destroy(gmc_item_labels);
193         if (gpa_hfinfo)
194                 g_ptr_array_free(gpa_hfinfo, FALSE);
195 }
196
197 /* frees the resources that the dissection a proto_tree uses */
198 void
199 proto_tree_free(proto_tree *tree)
200 {
201         g_node_traverse((GNode*)tree, G_IN_ORDER, G_TRAVERSE_ALL, -1,
202                 proto_tree_free_node, NULL);
203         g_node_destroy((GNode*)tree);
204 }
205
206 static gboolean
207 proto_tree_free_node(GNode *node, gpointer data)
208 {
209         field_info *fi = (field_info*) (node->data);
210
211         if (fi != NULL) {
212                 if (fi->representation)
213                         g_mem_chunk_free(gmc_item_labels, fi->representation);
214                 if (fi->hfinfo->type == FT_STRING)
215                         g_free(fi->value.string);
216                 else if (fi->hfinfo->type == FT_BYTES) 
217                         g_free(fi->value.bytes);
218                 g_mem_chunk_free(gmc_field_info, fi);
219         }
220         return FALSE; /* FALSE = do not end traversal of GNode tree */
221 }       
222
223 /* Finds a record in the hf_info_records array. */
224 static struct header_field_info*
225 find_hfinfo_record(int hfindex)
226 {
227         g_assert(hfindex >= 0 && hfindex < gpa_hfinfo->len);
228         return g_ptr_array_index(gpa_hfinfo, hfindex);
229 }
230
231 proto_item *
232 proto_tree_add_item(proto_tree *tree, int hfindex, gint start, gint length, ...)
233 {
234         proto_item      *pi;
235         va_list         ap;
236
237         va_start(ap, length);
238         pi = proto_tree_add_item_value(tree, hfindex, start, length, 0, 1, ap);
239         va_end(ap);
240
241         return pi;
242 }
243
244 proto_item *
245 proto_tree_add_item_hidden(proto_tree *tree, int hfindex, gint start, gint length, ...)
246 {
247         proto_item      *pi;
248         va_list         ap;
249
250         va_start(ap, length);
251         pi = proto_tree_add_item_value(tree, hfindex, start, length, 0, 0, ap);
252         va_end(ap);
253
254         return pi;
255 }
256
257 proto_item *
258 proto_tree_add_item_format(proto_tree *tree, int hfindex, gint start, gint length, ...)
259 {
260         proto_item      *pi;
261         va_list         ap;
262
263         va_start(ap, length);
264         pi = proto_tree_add_item_value(tree, hfindex, start, length, 1, 1, ap);
265         va_end(ap);
266
267         return pi;
268 }
269
270 proto_item *
271 proto_tree_add_notext(proto_tree *tree, gint start, gint length, ...)
272 {
273         proto_item      *pi;
274         va_list         ap;
275
276         va_start(ap, length);
277         pi = proto_tree_add_item_value(tree, hf_text_only, start, length, 0, 1, ap);
278         va_end(ap);
279
280         return pi;
281 }
282
283 proto_item *
284 proto_tree_add_text(proto_tree *tree, gint start, gint length, ...)
285 {
286         proto_item      *pi;
287         va_list         ap;
288
289         va_start(ap, length);
290         pi = proto_tree_add_item_value(tree, hf_text_only, start, length, 1, 1, ap);
291         va_end(ap);
292
293         return pi;
294 }
295
296 static proto_item *
297 proto_tree_add_item_value(proto_tree *tree, int hfindex, gint start,
298         gint length, int include_format, int visible, va_list ap)
299 {
300         proto_item      *pi;
301         field_info      *fi;
302         char            *junk, *format;
303         header_field_info *hfinfo;
304
305         if (!tree)
306                 return(NULL);
307
308         /* either visibility flag can nullify the other */
309         visible = proto_tree_is_visible && visible;
310
311         fi = g_mem_chunk_alloc(gmc_field_info);
312
313         fi->hfinfo = find_hfinfo_record(hfindex);
314         g_assert(fi->hfinfo != NULL);
315         fi->start = start;
316         fi->length = length;
317         fi->tree_type = ETT_NONE;
318         fi->visible = visible;
319
320         /* for convenience */
321
322         hfinfo = fi->hfinfo;
323 /* from the stdarg man page on Solaris 2.6:
324 NOTES
325      It is up to the calling routine to specify  in  some  manner
326      how  many arguments there are, since it is not always possi-
327      ble to determine the number  of  arguments  from  the  stack
328      frame.   For example, execl is passed a zero pointer to sig-
329      nal the end of the list.  printf can tell how many arguments
330      there  are  by  the format.  It is non-portable to specify a
331      second argument of char, short, or float to va_arg,  because
332      arguments  seen  by the called function are not char, short,
333      or float.  C converts char and short arguments  to  int  and
334      converts  float arguments to double before passing them to a
335      function.
336 */
337         switch(hfinfo->type) {
338                 case FT_NONE:
339                         junk = va_arg(ap, guint8*);
340                         break;
341
342                 case FT_BYTES:
343                         /* This g_malloc'ed memory is freed in
344                            proto_tree_free_node() */
345                         fi->value.bytes = (guint8 *)g_malloc(length);
346                         memcpy(fi->value.bytes, va_arg(ap, guint8*), length);
347                         break;
348
349                 case FT_BOOLEAN:
350                 case FT_UINT8:
351                 case FT_UINT16:
352                 case FT_UINT24:
353                 case FT_UINT32:
354                 case FT_INT8:
355                 case FT_INT16:
356                 case FT_INT24:
357                 case FT_INT32:
358                         fi->value.numeric = va_arg(ap, unsigned int);
359                         if (hfinfo->bitmask) {
360                                 /* Mask out irrelevant portions */
361                                 fi->value.numeric &= hfinfo->bitmask;
362
363                                 /* Shift bits */
364                                 if (hfinfo->bitshift > 0) {
365                                         fi->value.numeric >>= hfinfo->bitshift;
366                                 }
367                         }
368                         break;
369
370                 case FT_IPv4:
371                         ipv4_addr_set_net_order_addr(&(fi->value.ipv4), va_arg(ap, unsigned int));
372                         ipv4_addr_set_netmask_bits(&(fi->value.ipv4), 32);
373                         break;
374
375                 case FT_IPXNET:
376                         fi->value.numeric = va_arg(ap, unsigned int);
377                         break;
378
379                 case FT_IPv6:
380                         memcpy(fi->value.ipv6, va_arg(ap, guint8*), 16);
381                         break;
382
383                 case FT_DOUBLE:
384                         fi->value.floating = va_arg(ap, double);
385                         break;
386
387                 case FT_ETHER:
388                         memcpy(fi->value.ether, va_arg(ap, guint8*), 6);
389                         break;
390
391                 case FT_ABSOLUTE_TIME:
392                 case FT_RELATIVE_TIME:
393                         memcpy(&fi->value.time, va_arg(ap, struct timeval*),
394                                 sizeof(struct timeval));
395                         break;
396
397                 case FT_STRING:
398                         /* This g_strdup'ed memory is freed in proto_tree_free_node() */
399                         fi->value.string = g_strdup(va_arg(ap, char*));
400                         break;
401
402                 case FT_TEXT_ONLY:
403                         ; /* nothing */
404                         break;
405
406                 default:
407                         g_error("hfinfo->type %d not handled\n", hfinfo->type);
408                         break;
409         }
410
411         pi = (proto_item*) g_node_new(fi);
412         g_node_append((GNode*)tree, (GNode*)pi);
413
414         /* are there any formatting arguments? */
415         if (visible && include_format) {
416                 format = va_arg(ap, char*);
417                 fi->representation = g_mem_chunk_alloc(gmc_item_labels);
418                 vsnprintf(fi->representation, ITEM_LABEL_LENGTH,
419                                 format, ap);
420         }
421         else {
422                 fi->representation = NULL;
423         }
424
425         return pi;
426 }
427
428 void
429 proto_item_set_text(proto_item *pi, ...)
430 {
431         field_info *fi = (field_info*) (((GNode*)pi)->data);
432         va_list ap;
433         char *format;
434
435         if (fi->representation)
436                 g_mem_chunk_free(gmc_item_labels, fi->representation);
437
438         fi->representation = g_mem_chunk_alloc(gmc_item_labels);
439         va_start(ap, pi);
440         format = va_arg(ap, char*);
441         vsnprintf(fi->representation, ITEM_LABEL_LENGTH,
442                                 format, ap);
443         va_end(ap);
444 }
445
446 void
447 proto_item_set_len(proto_item *pi, gint length)
448 {
449         field_info *fi = (field_info*) (((GNode*)pi)->data);
450         fi->length = length;
451 }
452
453 proto_tree*
454 proto_tree_create_root(void)
455 {
456         return (proto_tree*) g_node_new(NULL);
457 }
458
459 proto_tree*
460 proto_item_add_subtree(proto_item *pi,  gint idx) {
461         field_info *fi = (field_info*) (((GNode*)pi)->data);
462         g_assert(idx >= 0 && idx < num_tree_types);
463         fi->tree_type = idx;
464         return (proto_tree*) pi;
465 }
466
467
468 int
469 proto_register_protocol(char *name, char *abbrev)
470 {
471         struct header_field_info *hfinfo;
472
473         /* Here we do allocate a new header_field_info struct */
474         hfinfo = g_mem_chunk_alloc(gmc_hfinfo);
475         hfinfo->name = name;
476         hfinfo->abbrev = abbrev;
477         hfinfo->type = FT_NONE;
478         hfinfo->strings = NULL;
479         hfinfo->bitmask = 0;
480         hfinfo->bitshift = 0;
481         hfinfo->blurb = "";
482         hfinfo->parent = -1; /* this field differentiates protos and fields */
483
484         return proto_register_field_init(hfinfo, hfinfo->parent);
485 }
486
487 /* for use with static arrays only, since we don't allocate our own copies
488 of the header_field_info struct contained withing the hf_register_info struct */
489 void
490 proto_register_field_array(int parent, hf_register_info *hf, int num_records)
491 {
492         int                     field_id, i;
493         hf_register_info        *ptr = hf;
494
495         for (i = 0; i < num_records; i++, ptr++) {
496                 field_id = proto_register_field_init(&ptr->hfinfo, parent);
497                 *ptr->p_id = field_id;
498         }
499 }
500
501 static int
502 proto_register_field_init(header_field_info *hfinfo, int parent)
503 {
504         /* These types of fields are allowed to have value_strings or true_false_strings */
505         g_assert((hfinfo->strings == NULL) || (
506                         (hfinfo->type == FT_UINT8) ||
507                         (hfinfo->type == FT_UINT16) ||
508                         (hfinfo->type == FT_UINT24) ||
509                         (hfinfo->type == FT_UINT32) ||
510                         (hfinfo->type == FT_INT8) ||
511                         (hfinfo->type == FT_INT16) ||
512                         (hfinfo->type == FT_INT24) ||
513                         (hfinfo->type == FT_INT32) ||
514                         (hfinfo->type == FT_BOOLEAN) ));
515
516         /* if this is a bitfield, compure bitshift */
517         if (hfinfo->bitmask) {
518                 while ((hfinfo->bitmask & (1 << hfinfo->bitshift)) == 0)
519                         hfinfo->bitshift++;
520         }
521
522         hfinfo->parent = parent;
523
524         /* if we always add and never delete, then id == len - 1 is correct */
525         g_ptr_array_add(gpa_hfinfo, hfinfo);
526         hfinfo->id = gpa_hfinfo->len - 1;
527         return hfinfo->id;
528 }
529
530 void
531 proto_register_subtree_array(gint **indices, int num_indices)
532 {
533         int     i;
534         gint    **ptr = indices;
535
536         /*
537          * Add "num_indices" elements to "tree_is_expanded".
538          */
539         tree_is_expanded = g_realloc(tree_is_expanded,
540             (num_tree_types + num_indices)*sizeof (gint));
541
542         /*
543          * Assign "num_indices" subtree numbers starting at "num_tree_types",
544          * returning the indices through the pointers in the array whose
545          * first element is pointed to by "indices", set to FALSE the
546          * elements to which those subtree numbers refer, and update
547          * "num_tree_types" appropriately.
548          */
549         for (i = 0; i < num_indices; i++, ptr++, num_tree_types++) {
550                 tree_is_expanded[num_tree_types] = FALSE;
551                 **ptr = num_tree_types;
552         }
553 }
554
555 void
556 proto_item_fill_label(field_info *fi, gchar *label_str)
557 {
558         struct header_field_info        *hfinfo = fi->hfinfo;
559         guint32                         n_addr; /* network-order IPv4 address */
560
561         switch(hfinfo->type) {
562                 case FT_NONE:
563                         snprintf(label_str, ITEM_LABEL_LENGTH,
564                                 "%s", hfinfo->name);
565                         break;
566
567                 case FT_BOOLEAN:
568                         fill_label_boolean(fi, label_str);
569                         break;
570
571                 case FT_BYTES:
572                         snprintf(label_str, ITEM_LABEL_LENGTH,
573                                 "%s: %s", hfinfo->name, 
574                                  bytes_to_str(fi->value.bytes, fi->length));
575                         break;
576
577                 /* Four types of integers to take care of:
578                  *      Bitfield, with val_string
579                  *      Bitfield, w/o val_string
580                  *      Non-bitfield, with val_string
581                  *      Non-bitfield, w/o val_string
582                  */
583                 case FT_UINT8:
584                 case FT_UINT16:
585                 case FT_UINT24:
586                 case FT_UINT32:
587                         if (hfinfo->bitmask) {
588                                 if (hfinfo->strings) {
589                                         fill_label_enumerated_bitfield(fi, label_str);
590                                 }
591                                 else {
592                                         fill_label_numeric_bitfield(fi, label_str);
593                                 }
594                         }
595                         else {
596                                 if (hfinfo->strings) {
597                                         fill_label_enumerated_uint(fi, label_str);
598                                 }
599                                 else {
600                                         fill_label_uint(fi, label_str);
601                                 }
602                         }
603                         break;
604
605                 case FT_INT8:
606                 case FT_INT16:
607                 case FT_INT24:
608                 case FT_INT32:
609                         g_assert(!hfinfo->bitmask);
610                         if (hfinfo->strings) {
611                                 fill_label_enumerated_int(fi, label_str);
612                         }
613                         else {
614                                 fill_label_int(fi, label_str);
615                         }
616                         break;
617
618                 case FT_DOUBLE:
619                         snprintf(label_str, ITEM_LABEL_LENGTH,
620                                 "%s: %g", fi->hfinfo->name,
621                                 fi->value.floating);
622                         break;
623
624                 case FT_ABSOLUTE_TIME:
625                         snprintf(label_str, ITEM_LABEL_LENGTH,
626                                 "%s: %s", fi->hfinfo->name,
627                                 abs_time_to_str(&fi->value.time));
628                         break;
629
630                 case FT_RELATIVE_TIME:
631                         snprintf(label_str, ITEM_LABEL_LENGTH,
632                                 "%s: %s seconds", fi->hfinfo->name,
633                                 rel_time_to_str(&fi->value.time));
634                         break;
635
636                 case FT_IPXNET:
637                         snprintf(label_str, ITEM_LABEL_LENGTH,
638                                 "%s: 0x%08X (%s)", fi->hfinfo->name,
639                                 fi->value.numeric, get_ipxnet_name(fi->value.numeric));
640                         break;
641
642                 case FT_ETHER:
643                         snprintf(label_str, ITEM_LABEL_LENGTH,
644                                 "%s: %s (%s)", fi->hfinfo->name,
645                                 ether_to_str(fi->value.ether),
646                                 get_ether_name(fi->value.ether));
647                         break;
648
649                 case FT_IPv4:
650                         n_addr = ipv4_get_net_order_addr(&fi->value.ipv4);
651                         snprintf(label_str, ITEM_LABEL_LENGTH,
652                                 "%s: %s (%s)", fi->hfinfo->name,
653                                 get_hostname(n_addr),
654                                 ip_to_str((guint8*)&n_addr));
655                         break;
656
657                 case FT_IPv6:
658                         snprintf(label_str, ITEM_LABEL_LENGTH,
659                                 "%s: %s (%s)", fi->hfinfo->name,
660                                 get_hostname6((struct e_in6_addr *)fi->value.ipv6),
661                                 ip6_to_str((struct e_in6_addr*)fi->value.ipv6));
662                         break;
663         
664                 case FT_STRING:
665                         snprintf(label_str, ITEM_LABEL_LENGTH,
666                                 "%s: %s", fi->hfinfo->name, fi->value.string);
667                         break;
668
669                 default:
670                         g_error("hfinfo->type %d not handled\n", fi->hfinfo->type);
671                         break;
672         }
673 }
674
675 static void
676 fill_label_boolean(field_info *fi, gchar *label_str)
677 {
678         char *p = label_str;
679         int bitfield_byte_length = 0, bitwidth;
680         guint32 unshifted_value;
681
682         struct header_field_info        *hfinfo = fi->hfinfo;
683         struct true_false_string        default_tf = { "True", "False" };
684         struct true_false_string        *tfstring = &default_tf;
685
686         if (hfinfo->strings) {
687                 tfstring = (struct true_false_string*) hfinfo->strings;
688         }
689
690         if (hfinfo->bitmask) {
691                 /* Figure out the bit width */
692                 bitwidth = hfinfo_bitwidth(hfinfo);
693
694                 /* Un-shift bits */
695                 unshifted_value = fi->value.numeric;
696                 if (hfinfo->bitshift > 0) {
697                         unshifted_value <<= hfinfo->bitshift;
698                 }
699
700                 /* Create the bitfield first */
701                 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
702                 bitfield_byte_length = p - label_str;
703         }
704
705         /* Fill in the textual info */
706         snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
707                 "%s: %s",  hfinfo->name,
708                 fi->value.numeric ? tfstring->true_string : tfstring->false_string);
709 }
710
711
712 /* Fills data for bitfield ints with val_strings */
713 static void
714 fill_label_enumerated_bitfield(field_info *fi, gchar *label_str)
715 {
716         char *format = NULL, *p;
717         int bitfield_byte_length, bitwidth;
718         guint32 unshifted_value;
719
720         struct header_field_info        *hfinfo = fi->hfinfo;
721
722         /* Figure out the bit width */
723         bitwidth = hfinfo_bitwidth(hfinfo);
724
725         /* Pick the proper format string */
726         format = hfinfo_uint_vals_format(hfinfo);
727
728         /* Un-shift bits */
729         unshifted_value = fi->value.numeric;
730         if (hfinfo->bitshift > 0) {
731                 unshifted_value <<= hfinfo->bitshift;
732         }
733
734         /* Create the bitfield first */
735         p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
736         bitfield_byte_length = p - label_str;
737
738         /* Fill in the textual info using stored (shifted) value */
739         snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
740                         format,  hfinfo->name,
741                         val_to_str(fi->value.numeric, cVALS(hfinfo->strings), "Unknown"),
742                         fi->value.numeric);
743 }
744
745 static void
746 fill_label_numeric_bitfield(field_info *fi, gchar *label_str)
747 {
748         char *format = NULL, *p;
749         int bitfield_byte_length, bitwidth;
750         guint32 unshifted_value;
751
752         struct header_field_info        *hfinfo = fi->hfinfo;
753
754         /* Figure out the bit width */
755         bitwidth = hfinfo_bitwidth(hfinfo);
756
757         /* Pick the proper format string */
758         format = hfinfo_uint_format(hfinfo);
759
760         /* Un-shift bits */
761         unshifted_value = fi->value.numeric;
762         if (hfinfo->bitshift > 0) {
763                 unshifted_value <<= hfinfo->bitshift;
764         }
765
766         /* Create the bitfield using */
767         p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
768         bitfield_byte_length = p - label_str;
769
770         /* Fill in the textual info using stored (shifted) value */
771         snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
772                         format,  hfinfo->name, fi->value.numeric);
773 }
774
775 static void
776 fill_label_enumerated_uint(field_info *fi, gchar *label_str)
777 {
778         char *format = NULL;
779         struct header_field_info        *hfinfo = fi->hfinfo;
780
781         /* Pick the proper format string */
782         format = hfinfo_uint_vals_format(hfinfo);
783
784         /* Fill in the textual info */
785         snprintf(label_str, ITEM_LABEL_LENGTH,
786                         format,  hfinfo->name,
787                         val_to_str(fi->value.numeric, cVALS(hfinfo->strings), "Unknown"),
788                         fi->value.numeric);
789 }
790
791 static void
792 fill_label_uint(field_info *fi, gchar *label_str)
793 {
794         char *format = NULL;
795         struct header_field_info        *hfinfo = fi->hfinfo;
796
797         /* Pick the proper format string */
798         format = hfinfo_uint_format(hfinfo);
799
800         /* Fill in the textual info */
801         snprintf(label_str, ITEM_LABEL_LENGTH,
802                         format,  hfinfo->name, fi->value.numeric);
803 }
804
805 static void
806 fill_label_enumerated_int(field_info *fi, gchar *label_str)
807 {
808         char *format = NULL;
809         struct header_field_info        *hfinfo = fi->hfinfo;
810
811         /* Pick the proper format string */
812         format = hfinfo_int_vals_format(hfinfo);
813
814         /* Fill in the textual info */
815         snprintf(label_str, ITEM_LABEL_LENGTH,
816                         format,  hfinfo->name,
817                         val_to_str(fi->value.numeric, cVALS(hfinfo->strings), "Unknown"),
818                         fi->value.numeric);
819 }
820
821 static void
822 fill_label_int(field_info *fi, gchar *label_str)
823 {
824         char *format = NULL;
825         struct header_field_info        *hfinfo = fi->hfinfo;
826
827         /* Pick the proper format string */
828         format = hfinfo_int_format(hfinfo);
829
830         /* Fill in the textual info */
831         snprintf(label_str, ITEM_LABEL_LENGTH,
832                         format,  hfinfo->name, fi->value.numeric);
833 }
834
835 static int
836 hfinfo_bitwidth(header_field_info *hfinfo)
837 {
838         int bitwidth = 0;
839
840         if (!hfinfo->bitmask) {
841                 return 0;
842         }
843
844         switch(hfinfo->type) {
845                 case FT_UINT8:
846                 case FT_INT8:
847                         bitwidth = 8;
848                         break;
849                 case FT_UINT16:
850                 case FT_INT16:
851                         bitwidth = 16;
852                         break;
853                 case FT_UINT24:
854                 case FT_INT24:
855                         bitwidth = 24;
856                         break;
857                 case FT_UINT32:
858                 case FT_INT32:
859                         bitwidth = 32;
860                         break;
861                 case FT_BOOLEAN:
862                         bitwidth = hfinfo->display; /* hacky? :) */
863                         break;
864                 default:
865                         g_assert_not_reached();
866                         ;
867         }
868         return bitwidth;
869 }
870
871 static char*
872 hfinfo_uint_vals_format(header_field_info *hfinfo)
873 {
874         char *format = NULL;
875
876         switch(hfinfo->display) {
877                 case BASE_DEC:
878                 case BASE_NONE:
879                 case BASE_OCT: /* I'm lazy */
880                 case BASE_BIN: /* I'm lazy */
881                         format = "%s: %s (%u)";
882                         break;
883                 case BASE_HEX:
884                         switch(hfinfo->type) {
885                                 case FT_UINT8:
886                                         format = "%s: %s (0x%02x)";
887                                         break;
888                                 case FT_UINT16:
889                                         format = "%s: %s (0x%04x)";
890                                         break;
891                                 case FT_UINT24:
892                                         format = "%s: %s (0x%06x)";
893                                         break;
894                                 case FT_UINT32:
895                                         format = "%s: %s (0x%08x)";
896                                         break;
897                                 default:
898                                         g_assert_not_reached();
899                                         ;
900                         }
901                         break;
902                 default:
903                         g_assert_not_reached();
904                         ;
905         }
906         return format;
907 }
908
909 static char*
910 hfinfo_uint_format(header_field_info *hfinfo)
911 {
912         char *format = NULL;
913
914         /* Pick the proper format string */
915         switch(hfinfo->display) {
916                 case BASE_DEC:
917                 case BASE_NONE:
918                 case BASE_OCT: /* I'm lazy */
919                 case BASE_BIN: /* I'm lazy */
920                         format = "%s: %u";
921                         break;
922                 case BASE_HEX:
923                         switch(hfinfo->type) {
924                                 case FT_UINT8:
925                                         format = "%s: 0x%02x";
926                                         break;
927                                 case FT_UINT16:
928                                         format = "%s: 0x%04x";
929                                         break;
930                                 case FT_UINT24:
931                                         format = "%s: 0x%06x";
932                                         break;
933                                 case FT_UINT32:
934                                         format = "%s: 0x%08x";
935                                         break;
936                                 default:
937                                         g_assert_not_reached();
938                                         ;
939                         }
940                         break;
941                 default:
942                         g_assert_not_reached();
943                         ;
944         }
945         return format;
946 }
947
948 static char*
949 hfinfo_int_vals_format(header_field_info *hfinfo)
950 {
951         char *format = NULL;
952
953         switch(hfinfo->display) {
954                 case BASE_DEC:
955                 case BASE_NONE:
956                 case BASE_OCT: /* I'm lazy */
957                 case BASE_BIN: /* I'm lazy */
958                         format = "%s: %s (%d)";
959                         break;
960                 case BASE_HEX:
961                         switch(hfinfo->type) {
962                                 case FT_INT8:
963                                         format = "%s: %s (0x%02x)";
964                                         break;
965                                 case FT_INT16:
966                                         format = "%s: %s (0x%04x)";
967                                         break;
968                                 case FT_INT24:
969                                         format = "%s: %s (0x%06x)";
970                                         break;
971                                 case FT_INT32:
972                                         format = "%s: %s (0x%08x)";
973                                         break;
974                                 default:
975                                         g_assert_not_reached();
976                                         ;
977                         }
978                         break;
979                 default:
980                         g_assert_not_reached();
981                         ;
982         }
983         return format;
984 }
985
986 static char*
987 hfinfo_int_format(header_field_info *hfinfo)
988 {
989         char *format = NULL;
990
991         /* Pick the proper format string */
992         switch(hfinfo->display) {
993                 case BASE_DEC:
994                 case BASE_NONE:
995                 case BASE_OCT: /* I'm lazy */
996                 case BASE_BIN: /* I'm lazy */
997                         format = "%s: %d";
998                         break;
999                 case BASE_HEX:
1000                         switch(hfinfo->type) {
1001                                 case FT_INT8:
1002                                         format = "%s: 0x%02x";
1003                                         break;
1004                                 case FT_INT16:
1005                                         format = "%s: 0x%04x";
1006                                         break;
1007                                 case FT_INT24:
1008                                         format = "%s: 0x%06x";
1009                                         break;
1010                                 case FT_INT32:
1011                                         format = "%s: 0x%08x";
1012                                         break;
1013                                 default:
1014                                         g_assert_not_reached();
1015                                         ;
1016                         }
1017                         break;
1018                 default:
1019                         g_assert_not_reached();
1020                         ;
1021         }
1022         return format;
1023 }
1024
1025
1026
1027 int
1028 proto_registrar_n(void)
1029 {
1030         return gpa_hfinfo->len;
1031 }
1032
1033 char*
1034 proto_registrar_get_name(int n)
1035 {
1036     struct header_field_info *hfinfo;
1037     hfinfo = find_hfinfo_record(n);
1038     if (hfinfo)
1039         return hfinfo->name;
1040     else        return NULL;
1041 }
1042
1043 char*
1044 proto_registrar_get_abbrev(int n)
1045 {
1046         struct header_field_info *hfinfo;
1047
1048         hfinfo = find_hfinfo_record(n);
1049         if (hfinfo)
1050                 return hfinfo->abbrev;
1051         else
1052                 return NULL;
1053 }
1054
1055 int
1056 proto_registrar_get_ftype(int n)
1057 {
1058         struct header_field_info *hfinfo;
1059
1060         hfinfo = find_hfinfo_record(n);
1061         if (hfinfo)
1062                 return hfinfo->type;
1063         else
1064                 return -1;
1065 }
1066
1067 int
1068 proto_registrar_get_parent(int n)
1069 {
1070         struct header_field_info *hfinfo;
1071
1072         hfinfo = find_hfinfo_record(n);
1073         if (hfinfo)
1074                 return hfinfo->parent;
1075         else
1076                 return -2;
1077 }
1078
1079 gboolean
1080 proto_registrar_is_protocol(int n)
1081 {
1082         struct header_field_info *hfinfo;
1083
1084         hfinfo = find_hfinfo_record(n);
1085         if (hfinfo)
1086                 return (hfinfo->parent == -1 ? TRUE : FALSE);
1087         else
1088                 return FALSE;
1089 }
1090
1091 /* Returns length of field in packet (not necessarily the length
1092  * in our internal representation, as in the case of IPv4).
1093  * 0 means undeterminable at time of registration
1094  * -1 means the field is not registered. */
1095 gint
1096 proto_registrar_get_length(int n)
1097 {
1098         struct header_field_info *hfinfo;
1099
1100         hfinfo = find_hfinfo_record(n);
1101         if (!hfinfo)
1102                 return -1;
1103
1104         switch (hfinfo->type) {
1105                 case FT_TEXT_ONLY: /* not filterable */
1106                 case NUM_FIELD_TYPES: /* satisfy picky compilers */
1107                         return -1;
1108
1109                 case FT_NONE:
1110                 case FT_BYTES:
1111                 case FT_BOOLEAN:
1112                 case FT_STRING:
1113                 case FT_DOUBLE:
1114                 case FT_ABSOLUTE_TIME:
1115                 case FT_RELATIVE_TIME:
1116                         return 0;
1117
1118                 case FT_UINT8:
1119                 case FT_INT8:
1120                         return 1;
1121
1122                 case FT_UINT16:
1123                 case FT_INT16:
1124                         return 2;
1125
1126                 case FT_UINT24:
1127                 case FT_INT24:
1128                         return 3;
1129
1130                 case FT_UINT32:
1131                 case FT_INT32:
1132                 case FT_IPXNET:
1133                 case FT_IPv4:
1134                         return 4;
1135
1136                 case FT_ETHER:
1137                         return 6;
1138
1139                 case FT_IPv6:
1140                         return 16;
1141         }
1142         g_assert_not_reached();
1143         return -1;
1144 }
1145
1146 /* Looks for a protocol or a field in a proto_tree. Returns TRUE if
1147  * it exists anywhere, or FALSE if it exists nowhere. */
1148 gboolean
1149 proto_check_for_protocol_or_field(proto_tree* tree, int id)
1150 {
1151         proto_tree_search_info  sinfo;
1152
1153         sinfo.target = id;
1154         sinfo.result.node = NULL;
1155         sinfo.parent = -1;
1156         sinfo.traverse_func = NULL;
1157
1158         /* do a quicker check if target is a protocol */
1159         if (proto_registrar_is_protocol(id) == TRUE) {
1160                 proto_find_protocol_multi(tree, id, &check_for_protocol_or_field_id, &sinfo);
1161         }
1162         else {
1163                 /* find the field's parent protocol */
1164                 sinfo.parent = proto_registrar_get_parent(id);
1165
1166                 /* Go through each protocol subtree, checking if the protocols
1167                  * is the parent protocol of the field that we're looking for.
1168                  * We may have protocols that occur more than once (e.g., IP in IP),
1169                  * so we do indeed have to check all protocol subtrees, looking
1170                  * for the parent protocol. That's why proto_find_protocol()
1171                  * is not used --- it assumes a protocol occurs only once. */
1172                 g_node_traverse((GNode*)tree, G_IN_ORDER, G_TRAVERSE_ALL, 2,
1173                                                 check_for_field_within_protocol, &sinfo);
1174         }
1175
1176         if (sinfo.result.node)
1177                 return TRUE;
1178         else
1179                 return FALSE;
1180 }
1181
1182 static gboolean
1183 check_for_protocol_or_field_id(GNode *node, gpointer data)
1184 {
1185         field_info              *fi = (field_info*) (node->data);
1186         proto_tree_search_info  *sinfo = (proto_tree_search_info*) data;
1187
1188         if (fi) { /* !fi == the top most container node which holds nothing */
1189                 if (fi->hfinfo->id == sinfo->target) {
1190                         sinfo->result.node = node;
1191                         return TRUE; /* halt traversal */
1192                 }
1193         }
1194         return FALSE; /* keep traversing */
1195 }
1196
1197 static gboolean
1198 check_for_field_within_protocol(GNode *node, gpointer data)
1199 {
1200         field_info              *fi = (field_info*) (node->data);
1201         proto_tree_search_info  *sinfo = (proto_tree_search_info*) data;
1202
1203         if (fi) { /* !fi == the top most container node which holds nothing */
1204                 if (fi->hfinfo->id == sinfo->parent) {
1205                         g_node_traverse(node, G_IN_ORDER, G_TRAVERSE_ALL, -1,
1206                                         check_for_protocol_or_field_id, sinfo);
1207                         if (sinfo->result.node)
1208                                 return TRUE; /* halt traversal */
1209                 }
1210         }
1211         return FALSE; /* keep traversing */
1212 }
1213
1214 /* Looks for a protocol at the top layer of the tree. The protocol can occur
1215  * more than once, for those encapsulated protocols. For each protocol subtree
1216  * that is found, the callback function is called.
1217  */
1218 void
1219 proto_find_protocol_multi(proto_tree* tree, int target, GNodeTraverseFunc callback,
1220                         proto_tree_search_info *sinfo)
1221 {
1222         g_assert(callback != NULL);
1223         g_node_traverse((GNode*)tree, G_IN_ORDER, G_TRAVERSE_ALL, 2, callback, (gpointer*)sinfo);
1224 }
1225
1226 /* Simple wrappter to traverse all nodes, calling the sinfo traverse function with sinfo as an arg */
1227 gboolean
1228 proto_get_field_values(proto_tree* subtree, proto_tree_search_info *sinfo)
1229 {
1230         /* Don't try to check value of top-level NULL GNode */
1231         if (!((GNode*)subtree)->data) {
1232                 return FALSE; /* don't halt */
1233         }
1234         g_node_traverse((GNode*)subtree, G_IN_ORDER, G_TRAVERSE_ALL, -1, sinfo->traverse_func, (gpointer*)sinfo);
1235         return FALSE; /* don't halt */
1236 }
1237
1238 /* Dumps the contents of the registration database to stdout. An indepedent program can take
1239  * this output and format it into nice tables or HTML or whatever.
1240  *
1241  * There is one record per line. Each record is either a protocol or a header
1242  * field, differentiated by the first field. The fields are tab-delimited.
1243  *
1244  * Protocols
1245  * ---------
1246  * Field 1 = 'P'
1247  * Field 2 = protocol name
1248  * Field 3 = protocol abbreviation
1249  *
1250  * Header Fields
1251  * -------------
1252  * Field 1 = 'F'
1253  * Field 2 = field name
1254  * Field 3 = field abbreviation
1255  * Field 4 = type ( textual representation of the the ftenum type )
1256  * Field 5 = parent protocol abbreviation
1257  */
1258 void
1259 proto_registrar_dump(void)
1260 {
1261         header_field_info       *hfinfo, *parent_hfinfo;
1262         int                     i, len;
1263         const char              *enum_name;
1264
1265         len = gpa_hfinfo->len;
1266         for (i = 0; i < len ; i++) {
1267                 hfinfo = find_hfinfo_record(i);
1268
1269                 /* format for protocols */
1270                 if (proto_registrar_is_protocol(i)) {
1271                         printf("P\t%s\t%s\n", hfinfo->name, hfinfo->abbrev);
1272                 }
1273                 /* format for header fields */
1274                 else {
1275                         parent_hfinfo = find_hfinfo_record(hfinfo->parent);
1276                         g_assert(parent_hfinfo);
1277
1278                         switch(hfinfo->type) {
1279                         case FT_NONE:
1280                                 enum_name = "FT_NONE";
1281                                 break;
1282                         case FT_BOOLEAN:
1283                                 enum_name = "FT_BOOLEAN";
1284                                 break;
1285                         case FT_UINT8:
1286                                 enum_name = "FT_UINT8";
1287                                 break;
1288                         case FT_UINT16:
1289                                 enum_name = "FT_UINT16";
1290                                 break;
1291                         case FT_UINT24:
1292                                 enum_name = "FT_UINT24";
1293                                 break;
1294                         case FT_UINT32:
1295                                 enum_name = "FT_UINT32";
1296                                 break;
1297                         case FT_INT8:
1298                                 enum_name = "FT_INT8";
1299                                 break;
1300                         case FT_INT16:
1301                                 enum_name = "FT_INT16";
1302                                 break;
1303                         case FT_INT24:
1304                                 enum_name = "FT_INT24";
1305                                 break;
1306                         case FT_INT32:
1307                                 enum_name = "FT_INT32";
1308                                 break;
1309                         case FT_DOUBLE:
1310                                 enum_name = "FT_DOUBLE";
1311                                 break;
1312                         case FT_ABSOLUTE_TIME:
1313                                 enum_name = "FT_ABSOLUTE_TIME";
1314                                 break;
1315                         case FT_RELATIVE_TIME:
1316                                 enum_name = "FT_RELATIVE_TIME";
1317                                 break;
1318                         case FT_STRING:
1319                                 enum_name = "FT_STRING";
1320                                 break;
1321                         case FT_ETHER:
1322                                 enum_name = "FT_ETHER";
1323                                 break;
1324                         case FT_BYTES:
1325                                 enum_name = "FT_BYTES";
1326                                 break;
1327                         case FT_IPv4:
1328                                 enum_name = "FT_IPv4";
1329                                 break;
1330                         case FT_IPv6:
1331                                 enum_name = "FT_IPv6";
1332                                 break;
1333                         case FT_IPXNET:
1334                                 enum_name = "FT_IPXNET";
1335                                 break;
1336                         case FT_TEXT_ONLY:
1337                                 enum_name = "FT_TEXT_ONLY";
1338                                 break;
1339                         default:
1340                                 enum_name = "UNKNOWN";
1341                                 break;
1342                         }
1343                         printf("F\t%s\t%s\t%s\t%s\n", hfinfo->name, hfinfo->abbrev,
1344                                 enum_name,parent_hfinfo->abbrev);
1345                 }
1346         }
1347 }