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