085ad8cc2a40fe70c2a2107095c15aaf994c2b05
[obnox/wireshark/wip.git] / epan / proto.c
1 /* proto.c
2  * Routines for protocol tree
3  *
4  * $Id: proto.c,v 1.53 2002/02/18 22:26:29 guy Exp $
5  *
6  * Ethereal - Network traffic analyzer
7  * By Gerald Combs <gerald@ethereal.com>
8  * Copyright 1998 Gerald Combs
9  * 
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14  * 
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  * 
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
23  */
24
25 #ifdef HAVE_CONFIG_H
26 # include "config.h"
27 #endif
28
29 #ifdef HAVE_SYS_TYPES_H
30 # include <sys/types.h>
31 #endif
32
33 #include <stdio.h>
34 #include <string.h>
35 #include <glib.h>
36
37 #ifdef NEED_SNPRINTF_H
38 # include "snprintf.h"
39 #endif
40
41 #include "packet.h"
42 #include "strutil.h"
43 #include "resolv.h"
44 #include "plugins.h"
45 #include "ipv6-utils.h"
46 #include "proto.h"
47 #include "int-64bit.h"
48
49 #define cVALS(x) (const value_string*)(x)
50
51 static gboolean
52 proto_tree_free_node(GNode *node, gpointer data);
53
54 static void fill_label_boolean(field_info *fi, gchar *label_str);
55 static void fill_label_uint(field_info *fi, gchar *label_str);
56 static void fill_label_uint64(field_info *fi, gchar *label_str);
57 static void fill_label_int64(field_info *fi, gchar *label_str);
58 static void fill_label_enumerated_uint(field_info *fi, gchar *label_str);
59 static void fill_label_enumerated_bitfield(field_info *fi, gchar *label_str);
60 static void fill_label_numeric_bitfield(field_info *fi, gchar *label_str);
61 static void fill_label_int(field_info *fi, gchar *label_str);
62 static void fill_label_enumerated_int(field_info *fi, gchar *label_str);
63
64 int hfinfo_bitwidth(header_field_info *hfinfo);
65 static char* hfinfo_uint_vals_format(header_field_info *hfinfo);
66 static char* hfinfo_uint_format(header_field_info *hfinfo);
67 static char* hfinfo_int_vals_format(header_field_info *hfinfo);
68 static char* hfinfo_int_format(header_field_info *hfinfo);
69
70 static gboolean check_for_protocol_or_field_id(GNode *node, gpointer data);
71
72 static proto_item*
73 proto_tree_add_node(proto_tree *tree, field_info *fi);
74
75 static field_info *
76 alloc_field_info(proto_tree *tree, int hfindex, tvbuff_t *tvb,
77         gint start, gint *length);
78
79 static proto_item *
80 proto_tree_add_pi(proto_tree *tree, int hfindex, tvbuff_t *tvb,
81         gint start, gint *length, field_info **pfi);
82
83 static void
84 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap);
85
86 static void
87 proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb);
88 static void
89 proto_tree_set_uint64(field_info *fi, const guint8 *value_ptr, gboolean little_endian);
90 static void
91 proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start, gboolean little_endian);
92 static void
93 proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length);
94 static void
95 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length);
96 static void
97 proto_tree_set_time(field_info *fi, nstime_t *value_ptr);
98 static void
99 proto_tree_set_string(field_info *fi, const char* value);
100 static void
101 proto_tree_set_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
102 static void
103 proto_tree_set_ether(field_info *fi, const guint8* value);
104 static void
105 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start);
106 static void
107 proto_tree_set_ipxnet(field_info *fi, guint32 value);
108 static void
109 proto_tree_set_ipv4(field_info *fi, guint32 value);
110 static void
111 proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr);
112 static void
113 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start);
114 static void
115 proto_tree_set_boolean(field_info *fi, guint32 value);
116 static void
117 proto_tree_set_double(field_info *fi, double value);
118 static void
119 proto_tree_set_uint(field_info *fi, guint32 value);
120 static void
121 proto_tree_set_int(field_info *fi, gint32 value);
122
123 static int proto_register_field_init(header_field_info *hfinfo, int parent);
124
125 /* special-case header field used within proto.c */
126 int hf_text_only = 1;
127
128 /* Structure for information about a protocol */
129 typedef struct {
130         char    *name;          /* long description */
131         char    *short_name;    /* short description */
132         char    *filter_name;   /* name of this protocol in filters */
133         int     proto_id;       /* field ID for this protocol */
134         GList   *fields;        /* fields for this protocol */
135         GList   *last_field;    /* pointer to end of list of fields */
136         gboolean is_enabled;    /* TRUE if protocol is enabled */
137         gboolean can_disable;   /* TRUE if protocol can be disabled */
138 } protocol_t;
139
140 /* List of all protocols */
141 static GList *protocols;
142
143 #define INITIAL_NUM_PROTOCOL_HFINFO     200
144 #define INITIAL_NUM_FIELD_INFO          100
145 #define INITIAL_NUM_PROTO_NODE          100
146 #define INITIAL_NUM_ITEM_LABEL          100
147
148
149 /* Contains information about protocols and header fields. Used when
150  * dissectors register their data */
151 static GMemChunk *gmc_hfinfo = NULL;
152
153 /* Contains information about a field when a dissector calls
154  * proto_tree_add_item.  */
155 static GMemChunk *gmc_field_info = NULL;
156
157 /* Contains the space for proto_nodes. */
158 static GMemChunk *gmc_proto_node = NULL;
159
160 /* String space for protocol and field items for the GUI */
161 static GMemChunk *gmc_item_labels = NULL;
162
163 /* List which stores protocols and fields that have been registered */
164 static GPtrArray *gpa_hfinfo = NULL;
165
166 /* Points to the first element of an array of Booleans, indexed by
167    a subtree item type; that array element is TRUE if subtrees of
168    an item of that type are to be expanded. */
169 gboolean        *tree_is_expanded;
170
171 /* Number of elements in that array. */
172 int             num_tree_types;
173
174 /* initialize data structures and register protocols and fields */
175 void
176 proto_init(const char *plugin_dir,void (register_all_protocols)(void),
177            void (register_all_protocol_handoffs)(void))
178 {
179         static hf_register_info hf[] = {
180                 { &hf_text_only,
181                 { "",   "", FT_NONE, BASE_NONE, NULL, 0x0,
182                         NULL, HFILL }},
183         };
184
185         if (gmc_hfinfo)
186                 g_mem_chunk_destroy(gmc_hfinfo);
187         if (gmc_field_info)
188                 g_mem_chunk_destroy(gmc_field_info);
189         if (gmc_proto_node)
190                 g_mem_chunk_destroy(gmc_proto_node);
191         if (gmc_item_labels)
192                 g_mem_chunk_destroy(gmc_item_labels);
193         if (gpa_hfinfo)
194                 g_ptr_array_free(gpa_hfinfo, TRUE);
195         if (tree_is_expanded != NULL)
196                 g_free(tree_is_expanded);
197
198         gmc_hfinfo = g_mem_chunk_new("gmc_hfinfo",
199                 sizeof(header_field_info),
200         INITIAL_NUM_PROTOCOL_HFINFO * sizeof(header_field_info),
201         G_ALLOC_ONLY);
202
203         gmc_field_info = g_mem_chunk_new("gmc_field_info",
204                 sizeof(field_info),
205         INITIAL_NUM_FIELD_INFO * sizeof(field_info),
206                 G_ALLOC_AND_FREE);
207
208         gmc_proto_node = g_mem_chunk_new("gmc_proto_node",
209                 sizeof(proto_node),
210         INITIAL_NUM_PROTO_NODE * sizeof(proto_node),
211                 G_ALLOC_AND_FREE);
212
213         gmc_item_labels = g_mem_chunk_new("gmc_item_labels",
214                 ITEM_LABEL_LENGTH,
215         INITIAL_NUM_ITEM_LABEL* ITEM_LABEL_LENGTH,
216                 G_ALLOC_AND_FREE);
217
218         gpa_hfinfo = g_ptr_array_new();
219
220         /* Allocate "tree_is_expanded", with one element for ETT_NONE,
221            and initialize that element to FALSE. */
222         tree_is_expanded = g_malloc(sizeof (gint));
223         tree_is_expanded[0] = FALSE;
224         num_tree_types = 1;
225
226         /* Initialize the ftype subsystem */
227         ftypes_initialize();
228
229         /* Have each built-in dissector register its protocols, fields,
230            dissector tables, and dissectors to be called through a
231            handle, and do whatever one-time initialization it needs to
232            do. */
233         register_all_protocols();
234
235 #ifdef HAVE_PLUGINS
236         /* Now scan for plugins and load all the ones we find, calling
237            their register routines to do the stuff described above. */
238         init_plugins(plugin_dir);
239 #endif
240
241         /* Now call the "handoff registration" routines of all built-in
242            dissectors; those routines register the dissector in other
243            dissectors' handoff tables, and fetch any dissector handles
244            they need. */
245         register_all_protocol_handoffs();
246
247 #ifdef HAVE_PLUGINS
248         /* Now do the same with plugins. */
249         register_all_plugin_handoffs();
250 #endif
251
252         /* Register one special-case FT_TEXT_ONLY field for use when
253            converting ethereal to new-style proto_tree. These fields
254            are merely strings on the GUI tree; they are not filterable */
255         proto_register_field_array(-1, hf, array_length(hf));
256
257         /* We've assigned all the subtree type values; allocate the array
258            for them, and zero it out. */
259         tree_is_expanded = g_malloc(num_tree_types*sizeof (gint *));
260         memset(tree_is_expanded, '\0', num_tree_types*sizeof (gint *));
261 }
262
263 void
264 proto_cleanup(void)
265 {
266         if (gmc_hfinfo)
267                 g_mem_chunk_destroy(gmc_hfinfo);
268         if (gmc_field_info)
269                 g_mem_chunk_destroy(gmc_field_info);
270         if (gmc_proto_node)
271                 g_mem_chunk_destroy(gmc_proto_node);
272         if (gmc_item_labels)
273                 g_mem_chunk_destroy(gmc_item_labels);
274         if (gpa_hfinfo)
275                 g_ptr_array_free(gpa_hfinfo, TRUE);
276         if (tree_is_expanded != NULL)
277                 g_free(tree_is_expanded);
278
279         /* Cleanup the ftype subsystem */
280         ftypes_cleanup();
281 }
282
283 /* frees the resources that the dissection a proto_tree uses */
284 void
285 proto_tree_free(proto_tree *tree)
286 {
287     /* Free all the data pointed to by the tree. */
288         g_node_traverse((GNode*)tree, G_IN_ORDER, G_TRAVERSE_ALL, -1,
289                 proto_tree_free_node, NULL);
290
291     /* Then free the tree. */
292         g_node_destroy((GNode*)tree);
293 }
294
295 /* We accept a void* instead of a field_info* to satisfy CLEANUP_POP */
296 static void
297 free_field_info(void *fi)
298 {
299         g_mem_chunk_free(gmc_field_info, (field_info*)fi);
300 }
301
302 static void
303 free_GPtrArray_value(gpointer key, gpointer value, gpointer user_data)
304 {
305     GPtrArray   *ptrs = value;
306
307     g_ptr_array_free(ptrs, TRUE);
308 }
309
310 static void
311 free_node_tree_data(tree_data_t *tree_data)
312 {
313         /* Free all the GPtrArray's in the interesting_hfids hash. */
314         g_hash_table_foreach(tree_data->interesting_hfids,
315             free_GPtrArray_value, NULL);
316
317         /* And then destroy the hash. */
318         g_hash_table_destroy(tree_data->interesting_hfids);
319
320         /* And finally the tree_data_t itself. */
321         g_free(tree_data);
322 }
323
324 static void
325 free_node_field_info(field_info* finfo)
326 {
327                 if (finfo->representation) {
328                         g_mem_chunk_free(gmc_item_labels, finfo->representation);
329                 }
330                 fvalue_free(finfo->value);
331                 free_field_info(finfo);
332 }
333
334 static gboolean
335 proto_tree_free_node(GNode *node, gpointer data)
336 {
337         field_info *finfo = PITEM_FINFO(node);
338
339     if (finfo == NULL) {
340         /* This is the root GNode. Destroy the per-tree data.
341          * There is no field_info to destroy. */
342         free_node_tree_data(PTREE_DATA(node));
343     }
344     else {
345         /* This is a child GNode. Don't free the per-tree data, but
346          * do free the field_info data. */
347         free_node_field_info(finfo);
348         }
349
350     /* Free the proto_node. */
351         g_mem_chunk_free(gmc_proto_node, GNODE_PNODE(node));
352
353         return FALSE; /* FALSE = do not end traversal of GNode tree */
354 }
355
356 /* Is the parsing being done for a visible proto_tree or an invisible one?
357  * By setting this correctly, the proto_tree creation is sped up by not
358  * having to call vsnprintf and copy strings around.
359  */
360 void
361 proto_tree_set_visible(proto_tree *tree, gboolean visible)
362 {
363     PTREE_DATA(tree)->visible = visible;
364 }
365
366 /* Finds a record in the hf_info_records array by id. */
367 header_field_info*
368 proto_registrar_get_nth(int hfindex)
369 {
370         g_assert(hfindex >= 0 && (guint) hfindex < gpa_hfinfo->len);
371         return g_ptr_array_index(gpa_hfinfo, hfindex);
372 }
373
374
375 /* Add a text-only node, leaving it to our caller to fill the text in */
376 static proto_item *
377 proto_tree_add_text_node(proto_tree *tree, tvbuff_t *tvb, gint start, gint length)
378 {
379         proto_item      *pi;
380
381         pi = proto_tree_add_pi(tree, hf_text_only, tvb, start, &length, NULL);
382         if (pi == NULL)
383                 return(NULL);
384
385         return pi;
386 }
387
388 /* Add a text-only node to the proto_tree */
389 proto_item *
390 proto_tree_add_text(proto_tree *tree, tvbuff_t *tvb, gint start, gint length,
391         const char *format, ...)
392 {
393         proto_item      *pi;
394         va_list         ap;
395
396         pi = proto_tree_add_text_node(tree, tvb, start, length);
397         if (pi == NULL)
398                 return(NULL);
399
400         va_start(ap, format);
401         proto_tree_set_representation(pi, format, ap);
402         va_end(ap);
403
404         return pi;
405 }
406
407 /* Add a text-only node to the proto_tree (va_list version) */
408 proto_item *
409 proto_tree_add_text_valist(proto_tree *tree, tvbuff_t *tvb, gint start, 
410         gint length, const char *format, va_list ap)
411 {
412         proto_item      *pi;
413
414         pi = proto_tree_add_text_node(tree, tvb, start, length);
415         if (pi == NULL)
416                 return(NULL);
417
418         proto_tree_set_representation(pi, format, ap);
419
420         return pi;
421 }
422
423 /* Add a text-only node for debugging purposes. The caller doesn't need
424  * to worry about tvbuff, start, or length. Debug message gets sent to
425  * STDOUT, too */
426 proto_item *
427 proto_tree_add_debug_text(proto_tree *tree, const char *format, ...)
428 {
429         proto_item      *pi;
430         va_list         ap;
431
432         pi = proto_tree_add_text_node(tree, NULL, 0, 0);
433         if (pi == NULL)
434                 return(NULL);
435
436         va_start(ap, format);
437         proto_tree_set_representation(pi, format, ap);
438         vprintf(format, ap);
439         va_end(ap);
440         printf("\n");
441
442         return pi;
443 }
444
445
446 static guint32
447 get_uint_value(tvbuff_t *tvb, gint offset, gint length, gboolean little_endian)
448 {
449         guint32 value;
450
451         switch (length) {
452
453         case 1:
454                 value = tvb_get_guint8(tvb, offset);
455                 break;
456
457         case 2:
458                 value = little_endian ? tvb_get_letohs(tvb, offset)
459                                       : tvb_get_ntohs(tvb, offset);
460                 break;
461
462         case 3:
463                 value = little_endian ? tvb_get_letoh24(tvb, offset)
464                                       : tvb_get_ntoh24(tvb, offset);
465                 break;
466
467         case 4:
468                 value = little_endian ? tvb_get_letohl(tvb, offset)
469                                       : tvb_get_ntohl(tvb, offset);
470                 break;
471
472         default:
473                 g_assert_not_reached();
474                 value = 0;
475                 break;
476         }
477         return value;
478 }
479
480 static gint32
481 get_int_value(tvbuff_t *tvb, gint offset, gint length, gboolean little_endian)
482 {
483         gint32 value;
484
485         switch (length) {
486
487         case 1:
488                 value = (gint8)tvb_get_guint8(tvb, offset);
489                 break;
490
491         case 2:
492                 value = (gint16) (little_endian ? tvb_get_letohs(tvb, offset)
493                                                 : tvb_get_ntohs(tvb, offset));
494                 break;
495
496         case 3:
497                 value = little_endian ? tvb_get_letoh24(tvb, offset)
498                                       : tvb_get_ntoh24(tvb, offset);
499                 if (value & 0x00800000) {
500                         /* Sign bit is set; sign-extend it. */
501                         value |= 0xFF000000;
502                 }
503                 break;
504
505         case 4:
506                 value = little_endian ? tvb_get_letohl(tvb, offset)
507                                       : tvb_get_ntohl(tvb, offset);
508                 break;
509
510         default:
511                 g_assert_not_reached();
512                 value = 0;
513                 break;
514         }
515         return value;
516 }
517
518 /* Add an item to a proto_tree, using the text label registered to that item;
519    the item is extracted from the tvbuff handed to it. */
520 proto_item *
521 proto_tree_add_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
522     gint start, gint length, gboolean little_endian)
523 {
524         field_info      *new_fi;
525         proto_item      *pi;
526         guint32         value, n;
527         char            *string;
528         int             found_length;
529         GHashTable      *hash;
530         GPtrArray       *ptrs;
531
532         if (!tree)
533                 return(NULL);
534
535         new_fi = alloc_field_info(tree, hfindex, tvb, start, &length);
536
537         if (new_fi == NULL)
538                 return(NULL);
539
540         /* Register a cleanup function in case on of our tvbuff accesses
541          * throws an exception. We need to clean up new_fi. */
542         CLEANUP_PUSH(free_field_info, new_fi);
543
544         switch(new_fi->hfinfo->type) {
545                 case FT_NONE:
546                         /* no value to set for FT_NONE */
547                         break;
548
549                 case FT_PROTOCOL:
550                         proto_tree_set_protocol_tvb(new_fi, tvb);
551                         break;
552
553                 case FT_BYTES:
554                         proto_tree_set_bytes_tvb(new_fi, tvb, start, length);
555                         break;
556
557                 case FT_BOOLEAN:
558                         proto_tree_set_boolean(new_fi,
559                             get_uint_value(tvb, start, length, little_endian));
560                         break;
561
562                 /* XXX - make these just FT_UINT? */
563                 case FT_UINT8:
564                 case FT_UINT16:
565                 case FT_UINT24:
566                 case FT_UINT32:
567                         proto_tree_set_uint(new_fi,
568                             get_uint_value(tvb, start, length, little_endian));
569                         break;
570
571                 case FT_INT64:
572                 case FT_UINT64:
573                         g_assert(length == 8);
574                         proto_tree_set_uint64_tvb(new_fi, tvb, start, little_endian);
575                         break;
576
577                 /* XXX - make these just FT_INT? */
578                 case FT_INT8:
579                 case FT_INT16:
580                 case FT_INT24:
581                 case FT_INT32:
582                         proto_tree_set_int(new_fi,
583                             get_int_value(tvb, start, length, little_endian));
584                         break;
585
586                 case FT_IPv4:
587                         g_assert(length == 4);
588                         tvb_memcpy(tvb, (guint8 *)&value, start, 4);
589                         proto_tree_set_ipv4(new_fi, value);
590                         break;
591
592                 case FT_IPXNET:
593                         g_assert(length == 4);
594                         proto_tree_set_ipxnet(new_fi,
595                             get_uint_value(tvb, start, 4, FALSE));
596                         break;
597
598                 case FT_IPv6:
599                         g_assert(length == 16);
600                         proto_tree_set_ipv6_tvb(new_fi, tvb, start);
601                         break;
602
603                 case FT_ETHER:
604                         g_assert(length == 6);
605                         proto_tree_set_ether_tvb(new_fi, tvb, start);
606                         break;
607
608                 case FT_STRING:
609                         /* This g_strdup'ed memory is freed in proto_tree_free_node() */
610                         proto_tree_set_string_tvb(new_fi, tvb, start, length);
611                         break;
612
613                 case FT_STRINGZ:
614                         /* This g_strdup'ed memory is freed in proto_tree_free_node() */
615                         string = g_malloc(length);
616
617                         CLEANUP_PUSH(g_free, string);
618
619                         found_length = tvb_get_nstringz(tvb, start, length, string);
620                         if (found_length < 1) {
621                                 found_length = tvb_get_nstringz0(tvb, start, length, string);
622                         }
623
624                         CLEANUP_POP;
625
626                         proto_tree_set_string(new_fi, string);
627                         new_fi->length = found_length + 1;
628
629                         break;
630
631                 case FT_UINT_STRING:
632                         /* This g_strdup'ed memory is freed in proto_tree_free_node() */
633                         n = get_uint_value(tvb, start, length, little_endian);
634                         proto_tree_set_string_tvb(new_fi, tvb, start + length, n);
635
636                         /* Instead of calling proto_item_set_len(), since we don't yet
637                          * have a proto_item, we set the field_info's length ourselves. */
638                         new_fi->length = n + length;
639                         break;
640                 default:
641                         g_error("new_fi->hfinfo->type %d (%s) not handled\n",
642                                         new_fi->hfinfo->type,
643                                         ftype_name(new_fi->hfinfo->type));
644                         g_assert_not_reached();
645                         break;
646
647         }
648         CLEANUP_POP;
649
650         /* Don't add to proto_item to proto_tree until now so that any exceptions
651          * raised by a tvbuff access method doesn't leave junk in the proto_tree. */
652         pi = proto_tree_add_node(tree, new_fi);
653
654     /* If the proto_tree wants to keep a record of this finfo
655      * for quick lookup, then record it. */
656     hash = PTREE_DATA(tree)->interesting_hfids;
657     ptrs = g_hash_table_lookup(hash, GINT_TO_POINTER(hfindex));
658     if (ptrs) {
659         g_ptr_array_add(ptrs, new_fi);
660     }
661
662         return pi;
663 }
664
665 proto_item *
666 proto_tree_add_item_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb,
667     gint start, gint length, gboolean little_endian)
668 {
669         proto_item      *pi;
670         field_info      *fi;
671
672         pi = proto_tree_add_item(tree, hfindex, tvb, start, length, little_endian);
673         if (pi == NULL)
674                 return(NULL);
675
676         fi = PITEM_FINFO(pi);
677         fi->visible = FALSE;
678
679         return pi;
680 }
681
682
683 /* Add a FT_NONE to a proto_tree */
684 proto_item *
685 proto_tree_add_none_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
686                 gint length, const char *format, ...)
687 {
688         proto_item              *pi;
689         va_list                 ap;
690         header_field_info       *hfinfo;
691
692         if (!tree)
693                 return (NULL);
694
695         hfinfo = proto_registrar_get_nth(hfindex);
696         g_assert(hfinfo->type == FT_NONE);
697
698         pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, NULL);
699
700         va_start(ap, format);
701         proto_tree_set_representation(pi, format, ap);
702         va_end(ap);
703
704         /* no value to set for FT_NONE */
705         return pi;
706 }
707
708         
709 static void
710 proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb)
711 {
712         fvalue_set(fi->value, tvb, TRUE);
713 }
714
715 /* Add a FT_PROTOCOL to a proto_tree */
716 proto_item *
717 proto_tree_add_protocol_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
718                 gint length, const char *format, ...)
719 {
720         proto_item              *pi;
721         va_list                 ap;
722         header_field_info       *hfinfo;
723         field_info              *new_fi;
724
725         if (!tree)
726                 return (NULL);
727
728         hfinfo = proto_registrar_get_nth(hfindex);
729         g_assert(hfinfo->type == FT_PROTOCOL);
730
731         pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
732
733         va_start(ap, format);
734         proto_tree_set_representation(pi, format, ap);
735         va_end(ap);
736
737         if (start == 0) {
738                 proto_tree_set_protocol_tvb(new_fi, tvb);
739         }
740         else {
741                 proto_tree_set_protocol_tvb(new_fi, NULL);
742         }
743         return pi;
744 }
745
746
747 /* Add a FT_BYTES to a proto_tree */
748 proto_item *
749 proto_tree_add_bytes(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
750                 gint length, const guint8 *start_ptr)
751 {
752         proto_item              *pi;
753         field_info              *new_fi;
754         header_field_info       *hfinfo;
755
756         if (!tree)
757                 return (NULL);
758
759         hfinfo = proto_registrar_get_nth(hfindex);
760         g_assert(hfinfo->type == FT_BYTES);
761
762         pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
763         proto_tree_set_bytes(new_fi, start_ptr, length);
764
765         return pi;
766 }
767
768 proto_item *
769 proto_tree_add_bytes_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
770                 gint length, const guint8 *start_ptr)
771 {
772         proto_item              *pi;
773         field_info              *fi;
774
775         pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length, start_ptr);
776         if (pi == NULL)
777                 return (NULL);
778
779         fi = PITEM_FINFO(pi);
780         fi->visible = FALSE;
781
782         return pi;
783 }
784
785 proto_item *
786 proto_tree_add_bytes_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
787                 gint length, const guint8 *start_ptr, const char *format, ...)
788 {
789         proto_item              *pi;
790         va_list                 ap;
791
792         pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length, start_ptr);
793         if (pi == NULL)
794                 return (NULL);
795
796         va_start(ap, format);
797         proto_tree_set_representation(pi, format, ap);
798         va_end(ap);
799
800         return pi;
801 }
802
803 static void
804 proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length)
805 {
806         GByteArray              *bytes;
807
808         bytes = g_byte_array_new();
809         if (length > 0) {
810                 g_byte_array_append(bytes, start_ptr, length);
811         }
812         fvalue_set(fi->value, bytes, TRUE);
813 }
814
815
816 static void
817 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length)
818 {
819         proto_tree_set_bytes(fi, tvb_get_ptr(tvb, offset, length), length);
820 }
821
822 /* Add a FT_*TIME to a proto_tree */
823 proto_item *
824 proto_tree_add_time(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
825                 nstime_t *value_ptr)
826 {
827         proto_item              *pi;
828         field_info              *new_fi;
829         header_field_info       *hfinfo;
830
831         if (!tree)
832                 return (NULL);
833
834         hfinfo = proto_registrar_get_nth(hfindex);
835         g_assert(hfinfo->type == FT_ABSOLUTE_TIME ||
836                                 hfinfo->type == FT_RELATIVE_TIME);
837
838         pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
839         proto_tree_set_time(new_fi, value_ptr);
840
841         return pi;
842 }
843
844 proto_item *
845 proto_tree_add_time_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
846                 nstime_t *value_ptr)
847 {
848         proto_item              *pi;
849         field_info              *fi;
850
851         pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
852         if (pi == NULL)
853                 return (NULL);
854
855         fi = PITEM_FINFO(pi);
856         fi->visible = FALSE;
857
858         return pi;
859 }
860
861 proto_item *
862 proto_tree_add_time_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
863                 nstime_t *value_ptr, const char *format, ...)
864 {
865         proto_item              *pi;
866         va_list                 ap;
867
868         pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
869         if (pi == NULL)
870                 return (NULL);
871
872         va_start(ap, format);
873         proto_tree_set_representation(pi, format, ap);
874         va_end(ap);
875
876         return pi;
877 }
878
879 /* Set the FT_*TIME value */
880 static void
881 proto_tree_set_time(field_info *fi, nstime_t *value_ptr)
882 {
883         fvalue_set(fi->value, value_ptr, FALSE);
884 }
885
886 /* Add a FT_IPXNET to a proto_tree */
887 proto_item *
888 proto_tree_add_ipxnet(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
889                 guint32 value)
890 {
891         proto_item              *pi;
892         field_info              *new_fi;
893         header_field_info       *hfinfo;
894
895         if (!tree)
896                 return (NULL);
897
898         hfinfo = proto_registrar_get_nth(hfindex);
899         g_assert(hfinfo->type == FT_IPXNET);
900
901         pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
902         proto_tree_set_ipxnet(new_fi, value);
903
904         return pi;
905 }
906
907 proto_item *
908 proto_tree_add_ipxnet_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
909                 guint32 value)
910 {
911         proto_item              *pi;
912         field_info              *fi;
913
914         pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
915         if (pi == NULL)
916                 return (NULL);
917
918         fi = PITEM_FINFO(pi);
919         fi->visible = FALSE;
920
921         return pi;
922 }
923
924 proto_item *
925 proto_tree_add_ipxnet_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
926                 guint32 value, const char *format, ...)
927 {
928         proto_item              *pi;
929         va_list                 ap;
930
931         pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
932         if (pi == NULL)
933                 return (NULL);
934
935         va_start(ap, format);
936         proto_tree_set_representation(pi, format, ap);
937         va_end(ap);
938
939         return pi;
940 }
941
942 /* Set the FT_IPXNET value */
943 static void
944 proto_tree_set_ipxnet(field_info *fi, guint32 value)
945 {
946         fvalue_set_integer(fi->value, value);
947 }
948
949 /* Add a FT_IPv4 to a proto_tree */
950 proto_item *
951 proto_tree_add_ipv4(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
952                 guint32 value)
953 {
954         proto_item              *pi;
955         field_info              *new_fi;
956         header_field_info       *hfinfo;
957
958         if (!tree)
959                 return (NULL);
960
961         hfinfo = proto_registrar_get_nth(hfindex);
962         g_assert(hfinfo->type == FT_IPv4);
963
964         pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
965         proto_tree_set_ipv4(new_fi, value);
966
967         return pi;
968 }
969
970 proto_item *
971 proto_tree_add_ipv4_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
972                 guint32 value)
973 {
974         proto_item              *pi;
975         field_info              *fi;
976
977         pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
978         if (pi == NULL)
979                 return (NULL);
980
981         fi = PITEM_FINFO(pi);
982         fi->visible = FALSE;
983
984         return pi;
985 }
986
987 proto_item *
988 proto_tree_add_ipv4_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
989                 guint32 value, const char *format, ...)
990 {
991         proto_item              *pi;
992         va_list                 ap;
993
994         pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
995         if (pi == NULL)
996                 return (NULL);
997
998         va_start(ap, format);
999         proto_tree_set_representation(pi, format, ap);
1000         va_end(ap);
1001
1002         return pi;
1003 }
1004
1005 /* Set the FT_IPv4 value */
1006 static void
1007 proto_tree_set_ipv4(field_info *fi, guint32 value)
1008 {
1009         fvalue_set_integer(fi->value, value);
1010 }
1011
1012 /* Add a FT_IPv6 to a proto_tree */
1013 proto_item *
1014 proto_tree_add_ipv6(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1015                 const guint8* value_ptr)
1016 {
1017         proto_item              *pi;
1018         field_info              *new_fi;
1019         header_field_info       *hfinfo;
1020
1021         if (!tree)
1022                 return (NULL);
1023
1024         hfinfo = proto_registrar_get_nth(hfindex);
1025         g_assert(hfinfo->type == FT_IPv6);
1026
1027         pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1028         proto_tree_set_ipv6(new_fi, value_ptr);
1029
1030         return pi;
1031 }
1032
1033 proto_item *
1034 proto_tree_add_ipv6_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1035                 const guint8* value_ptr)
1036 {
1037         proto_item              *pi;
1038         field_info              *fi;
1039
1040         pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
1041         if (pi == NULL)
1042                 return (NULL);
1043
1044         fi = PITEM_FINFO(pi);
1045         fi->visible = FALSE;
1046
1047         return pi;
1048 }
1049
1050 proto_item *
1051 proto_tree_add_ipv6_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1052                 const guint8* value_ptr, const char *format, ...)
1053 {
1054         proto_item              *pi;
1055         va_list                 ap;
1056
1057         pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
1058         if (pi == NULL)
1059                 return (NULL);
1060
1061         va_start(ap, format);
1062         proto_tree_set_representation(pi, format, ap);
1063         va_end(ap);
1064
1065         return pi;
1066 }
1067
1068 /* Set the FT_IPv6 value */
1069 static void
1070 proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr)
1071 {
1072         fvalue_set(fi->value, (gpointer) value_ptr, FALSE);
1073 }
1074
1075 static void
1076 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start)
1077 {
1078         proto_tree_set_ipv6(fi, tvb_get_ptr(tvb, start, 16));
1079 }
1080
1081 static void
1082 proto_tree_set_uint64(field_info *fi, const guint8 *value_ptr, gboolean little_endian)
1083 {
1084         if(little_endian){
1085                 unsigned char buffer[8];
1086                 int i;
1087
1088                 for(i=0;i<8;i++){
1089                         buffer[i]=value_ptr[7-i];
1090                 }
1091                 fvalue_set(fi->value, (gpointer)buffer, FALSE);
1092         } else {
1093                 fvalue_set(fi->value, (gpointer)value_ptr, FALSE);
1094         }
1095 }
1096
1097 static void
1098 proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start, gboolean little_endian)
1099 {
1100         proto_tree_set_uint64(fi, tvb_get_ptr(tvb, start, 8), little_endian);
1101 }
1102
1103 /* Add a FT_STRING to a proto_tree */
1104 proto_item *
1105 proto_tree_add_string(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1106                 gint length, const char* value)
1107 {
1108         proto_item              *pi;
1109         field_info              *new_fi;
1110         header_field_info       *hfinfo;
1111
1112         if (!tree)
1113                 return (NULL);
1114
1115         hfinfo = proto_registrar_get_nth(hfindex);
1116         g_assert(hfinfo->type == FT_STRING);
1117
1118         pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1119         proto_tree_set_string(new_fi, value);
1120
1121         return pi;
1122 }
1123
1124 proto_item *
1125 proto_tree_add_string_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1126                 gint length, const char* value)
1127 {
1128         proto_item              *pi;
1129         field_info              *fi;
1130
1131         pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
1132         if (pi == NULL)
1133                 return (NULL);
1134
1135         fi = PITEM_FINFO(pi);
1136         fi->visible = FALSE;
1137
1138         return pi;
1139 }
1140
1141 proto_item *
1142 proto_tree_add_string_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1143                 gint length, const char* value, const char *format, ...)
1144 {
1145         proto_item              *pi;
1146         va_list                 ap;
1147
1148         pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
1149         if (pi == NULL)
1150                 return (NULL);
1151
1152         va_start(ap, format);
1153         proto_tree_set_representation(pi, format, ap);
1154         va_end(ap);
1155
1156         return pi;
1157 }
1158
1159 /* Set the FT_STRING value */
1160 static void
1161 proto_tree_set_string(field_info *fi, const char* value)
1162 {
1163         fvalue_set(fi->value, (gpointer) value, FALSE);
1164 }
1165
1166 static void
1167 proto_tree_set_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
1168 {
1169         gchar   *string;
1170
1171         if (length == -1) {
1172                 length = tvb_ensure_length_remaining(tvb, start);
1173         }
1174
1175         /* This memory is freed in proto_tree_free_node() */
1176         string = g_malloc(length + 1);
1177         tvb_memcpy(tvb, string, start, length);
1178         string[length] = '\0';
1179         fvalue_set(fi->value, string, TRUE);
1180 }
1181
1182 /* Add a FT_ETHER to a proto_tree */
1183 proto_item *
1184 proto_tree_add_ether(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1185                 const guint8* value)
1186 {
1187         proto_item              *pi;
1188         field_info              *new_fi;
1189         header_field_info       *hfinfo;
1190
1191         if (!tree)
1192                 return (NULL);
1193
1194         hfinfo = proto_registrar_get_nth(hfindex);
1195         g_assert(hfinfo->type == FT_ETHER);
1196
1197         pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1198         proto_tree_set_ether(new_fi, value);
1199
1200         return pi;
1201 }
1202
1203 proto_item *
1204 proto_tree_add_ether_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1205                 const guint8* value)
1206 {
1207         proto_item              *pi;
1208         field_info              *fi;
1209
1210         pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
1211         if (pi == NULL)
1212                 return (NULL);
1213
1214         fi = PITEM_FINFO(pi);
1215         fi->visible = FALSE;
1216
1217         return pi;
1218 }
1219
1220 proto_item *
1221 proto_tree_add_ether_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1222                 const guint8* value, const char *format, ...)
1223 {
1224         proto_item              *pi;
1225         va_list                 ap;
1226
1227         pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
1228         if (pi == NULL)
1229                 return (NULL);
1230
1231         va_start(ap, format);
1232         proto_tree_set_representation(pi, format, ap);
1233         va_end(ap);
1234
1235         return pi;
1236 }
1237
1238 /* Set the FT_ETHER value */
1239 static void
1240 proto_tree_set_ether(field_info *fi, const guint8* value)
1241 {
1242         fvalue_set(fi->value, (gpointer) value, FALSE);
1243 }
1244
1245 static void
1246 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start)
1247 {
1248         proto_tree_set_ether(fi, tvb_get_ptr(tvb, start, 6));
1249 }
1250
1251 /* Add a FT_BOOLEAN to a proto_tree */
1252 proto_item *
1253 proto_tree_add_boolean(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1254                 guint32 value)
1255 {
1256         proto_item              *pi;
1257         field_info              *new_fi;
1258         header_field_info       *hfinfo;
1259
1260         if (!tree)
1261                 return (NULL);
1262
1263         hfinfo = proto_registrar_get_nth(hfindex);
1264         g_assert(hfinfo->type == FT_BOOLEAN);
1265
1266         pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1267         proto_tree_set_boolean(new_fi, value);
1268
1269         return pi;
1270 }
1271
1272 proto_item *
1273 proto_tree_add_boolean_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1274                 guint32 value)
1275 {
1276         proto_item              *pi;
1277         field_info              *fi;
1278
1279         pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
1280         if (pi == NULL)
1281                 return (NULL);
1282
1283         fi = PITEM_FINFO(pi);
1284         fi->visible = FALSE;
1285
1286         return pi;
1287 }
1288
1289 proto_item *
1290 proto_tree_add_boolean_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1291                 guint32 value, const char *format, ...)
1292 {
1293         proto_item              *pi;
1294         va_list                 ap;
1295
1296         pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
1297         if (pi == NULL)
1298                 return (NULL);
1299
1300         va_start(ap, format);
1301         proto_tree_set_representation(pi, format, ap);
1302         va_end(ap);
1303
1304         return pi;
1305 }
1306
1307 /* Set the FT_BOOLEAN value */
1308 static void
1309 proto_tree_set_boolean(field_info *fi, guint32 value)
1310 {
1311         proto_tree_set_uint(fi, value);
1312 }
1313
1314 /* Add a FT_DOUBLE to a proto_tree */
1315 proto_item *
1316 proto_tree_add_double(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1317                 double value)
1318 {
1319         proto_item              *pi;
1320         field_info              *new_fi;
1321         header_field_info       *hfinfo;
1322
1323         if (!tree)
1324                 return (NULL);
1325
1326         hfinfo = proto_registrar_get_nth(hfindex);
1327         g_assert(hfinfo->type == FT_DOUBLE);
1328
1329         pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1330         proto_tree_set_double(new_fi, value);
1331
1332         return pi;
1333 }
1334
1335 proto_item *
1336 proto_tree_add_double_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1337                 double value)
1338 {
1339         proto_item              *pi;
1340         field_info              *fi;
1341
1342         pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
1343         if (pi == NULL)
1344                 return (NULL);
1345
1346         fi = PITEM_FINFO(pi);
1347         fi->visible = FALSE;
1348
1349         return pi;
1350 }
1351
1352 proto_item *
1353 proto_tree_add_double_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1354                 double value, const char *format, ...)
1355 {
1356         proto_item              *pi;
1357         va_list                 ap;
1358
1359         pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
1360         if (pi == NULL)
1361                 return (NULL);
1362
1363         va_start(ap, format);
1364         proto_tree_set_representation(pi, format, ap);
1365         va_end(ap);
1366
1367         return pi;
1368 }
1369
1370 /* Set the FT_DOUBLE value */
1371 static void
1372 proto_tree_set_double(field_info *fi, double value)
1373 {
1374         fvalue_set_floating(fi->value, value);
1375 }
1376
1377 /* Add any FT_UINT* to a proto_tree */
1378 proto_item *
1379 proto_tree_add_uint(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1380                 guint32 value)
1381 {
1382         proto_item              *pi = NULL;
1383         field_info              *new_fi;
1384         header_field_info       *hfinfo;
1385
1386         if (!tree)
1387                 return (NULL);
1388
1389         hfinfo = proto_registrar_get_nth(hfindex);
1390         switch(hfinfo->type) {
1391                 case FT_UINT8:
1392                 case FT_UINT16:
1393                 case FT_UINT24:
1394                 case FT_UINT32:
1395                         pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length,
1396                                         &new_fi);
1397                         proto_tree_set_uint(new_fi, value);
1398                         break;
1399
1400                 default:
1401                         g_assert_not_reached();
1402         }
1403
1404         return pi;
1405 }
1406
1407 proto_item *
1408 proto_tree_add_uint_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1409                 guint32 value)
1410 {
1411         proto_item              *pi;
1412         field_info              *fi;
1413
1414         pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
1415         if (pi == NULL)
1416                 return (NULL);
1417
1418         fi = PITEM_FINFO(pi);
1419         fi->visible = FALSE;
1420
1421         return pi;
1422 }
1423
1424 proto_item *
1425 proto_tree_add_uint_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1426                 guint32 value, const char *format, ...)
1427 {
1428         proto_item              *pi;
1429         va_list                 ap;
1430
1431         pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
1432         if (pi == NULL)
1433                 return (NULL);
1434
1435         va_start(ap, format);
1436         proto_tree_set_representation(pi, format, ap);
1437         va_end(ap);
1438
1439         return pi;
1440 }
1441
1442 /* Set the FT_UINT* value */
1443 static void
1444 proto_tree_set_uint(field_info *fi, guint32 value)
1445 {
1446         header_field_info       *hfinfo;
1447         guint32                 integer;
1448
1449         hfinfo = fi->hfinfo;
1450         integer = value;
1451
1452         if (hfinfo->bitmask) {
1453                 /* Mask out irrelevant portions */
1454                 integer &= hfinfo->bitmask;
1455
1456                 /* Shift bits */
1457                 if (hfinfo->bitshift > 0) {
1458                         integer >>= hfinfo->bitshift;
1459                 }
1460         }
1461         fvalue_set_integer(fi->value, integer);
1462 }
1463
1464 /* Add any FT_INT* to a proto_tree */
1465 proto_item *
1466 proto_tree_add_int(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1467                 gint32 value)
1468 {
1469         proto_item              *pi = NULL;
1470         field_info              *new_fi;
1471         header_field_info       *hfinfo;
1472
1473         if (!tree)
1474                 return (NULL);
1475
1476         hfinfo = proto_registrar_get_nth(hfindex);
1477         switch(hfinfo->type) {
1478                 case FT_INT8:
1479                 case FT_INT16:
1480                 case FT_INT24:
1481                 case FT_INT32:
1482                         pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length,
1483                                         &new_fi);
1484                         proto_tree_set_int(new_fi, value);
1485                         break;
1486
1487                 default:
1488                         g_assert_not_reached();
1489         }
1490
1491         return pi;
1492 }
1493
1494 proto_item *
1495 proto_tree_add_int_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1496                 gint32 value)
1497 {
1498         proto_item              *pi;
1499         field_info              *fi;
1500
1501         pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
1502         if (pi == NULL)
1503                 return (NULL);
1504
1505         fi = PITEM_FINFO(pi);
1506         fi->visible = FALSE;
1507
1508         return pi;
1509 }
1510
1511 proto_item *
1512 proto_tree_add_int_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1513                 gint32 value, const char *format, ...)
1514 {
1515         proto_item              *pi = NULL;
1516         va_list                 ap;
1517
1518         pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
1519         if (pi == NULL)
1520                 return (NULL);
1521
1522         va_start(ap, format);
1523         proto_tree_set_representation(pi, format, ap);
1524         va_end(ap);
1525
1526         return pi;
1527 }
1528
1529 /* Set the FT_INT* value */
1530 static void
1531 proto_tree_set_int(field_info *fi, gint32 value)
1532 {
1533         header_field_info       *hfinfo;
1534         guint32                 integer;
1535
1536         hfinfo = fi->hfinfo;
1537         integer = (guint32) value;
1538
1539         if (hfinfo->bitmask) {
1540                 /* Mask out irrelevant portions */
1541                 integer &= hfinfo->bitmask;
1542
1543                 /* Shift bits */
1544                 if (hfinfo->bitshift > 0) {
1545                         integer >>= hfinfo->bitshift;
1546                 }
1547         }
1548         fvalue_set_integer(fi->value, integer);
1549 }
1550
1551
1552 /* Add a field_info struct to the proto_tree, encapsulating it in a GNode (proto_item) */
1553 static proto_item *
1554 proto_tree_add_node(proto_tree *tree, field_info *fi)
1555 {
1556         GNode *new_gnode;
1557         proto_node *pnode;
1558
1559         pnode = g_mem_chunk_alloc(gmc_proto_node);
1560         pnode->finfo = fi;
1561         pnode->tree_data = PTREE_DATA(tree);
1562
1563         new_gnode = g_node_new(pnode);
1564         g_node_append((GNode*)tree, new_gnode);
1565
1566         return (proto_item*) new_gnode;
1567 }
1568
1569
1570 /* Generic way to allocate field_info and add to proto_tree.
1571  * Sets *pfi to address of newly-allocated field_info struct, if pfi is
1572  * non-NULL. */
1573 static proto_item *
1574 proto_tree_add_pi(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1575     gint *length, field_info **pfi)
1576 {
1577         proto_item      *pi;
1578         field_info      *fi;
1579         GHashTable      *hash;
1580         GPtrArray       *ptrs;
1581
1582         if (!tree)
1583                 return(NULL);
1584
1585         fi = alloc_field_info(tree, hfindex, tvb, start, length);
1586         pi = proto_tree_add_node(tree, fi);
1587
1588         /* If the proto_tree wants to keep a record of this finfo
1589          * for quick lookup, then record it. */
1590         hash = PTREE_DATA(tree)->interesting_hfids;
1591         ptrs = g_hash_table_lookup(hash, GINT_TO_POINTER(hfindex));
1592         if (ptrs) {
1593                 g_ptr_array_add(ptrs, fi);
1594         }
1595
1596         /* Does the caller want to know the fi pointer? */
1597         if (pfi) {
1598                 *pfi = fi;
1599         }
1600
1601         return pi;
1602 }
1603
1604 static field_info *
1605 alloc_field_info(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1606     gint *length)
1607 {
1608         header_field_info       *hfinfo;
1609         field_info              *fi;
1610
1611         /*
1612          * We only allow a null tvbuff if the item has a zero length,
1613          * i.e. if there's no data backing it.
1614          */
1615         g_assert(tvb != NULL || *length == 0);
1616
1617         g_assert(hfindex >= 0 && (guint) hfindex < gpa_hfinfo->len);
1618         hfinfo = proto_registrar_get_nth(hfindex);
1619         g_assert(hfinfo != NULL);
1620
1621         if (*length == -1) {
1622                 /*
1623                  * For FT_NONE, FT_PROTOCOL, FT_BYTES, and FT_STRING fields,
1624                  * a length of -1 means "set the length to what remains in
1625                  * the tvbuff".
1626                  *
1627                  * The assumption is either that
1628                  *
1629                  *      1) the length of the item can only be determined
1630                  *         by dissection (typically true of items with
1631                  *         subitems, which are probably FT_NONE or
1632                  *         FT_PROTOCOL)
1633                  *
1634                  * or
1635                  *
1636                  *      2) if the tvbuff is "short" (either due to a short
1637                  *         snapshot length or due to lack of reassembly of
1638                  *         fragments/segments/whatever), we want to display
1639                  *         what's available in the field (probably FT_BYTES
1640                  *         or FT_STRING) and then throw an exception later
1641                  *
1642                  * or
1643                  *
1644                  *      3) the field is defined to be "what's left in the
1645                  *         packet"
1646                  *
1647                  * so we set the length to what remains in the tvbuff so
1648                  * that, if we throw an exception while dissecting, it
1649                  * has what is probably the right value.
1650                  *
1651                  * It's not valid for any other type of field.
1652                  */
1653                 g_assert(hfinfo->type == FT_PROTOCOL ||
1654                          hfinfo->type == FT_NONE ||
1655                          hfinfo->type == FT_BYTES ||
1656                          hfinfo->type == FT_STRING);
1657                 *length = tvb_ensure_length_remaining(tvb, start);
1658         }
1659
1660         fi = g_mem_chunk_alloc(gmc_field_info);
1661         fi->hfinfo = hfinfo;
1662         fi->start = start;
1663         if (tvb) {
1664                 fi->start += tvb_raw_offset(tvb);
1665         }
1666         fi->length = *length;
1667         fi->tree_type = ETT_NONE;
1668         fi->visible = PTREE_DATA(tree)->visible;
1669         fi->representation = NULL;
1670
1671         fi->value = fvalue_new(fi->hfinfo->type);
1672
1673         /* add the data source tvbuff */
1674         if (tvb) {
1675                 fi->ds_tvb = tvb_get_ds_tvb(tvb);
1676         } else {
1677                 fi->ds_tvb = NULL;
1678         }
1679
1680         return fi;
1681 }
1682
1683 /* Set representation of a proto_tree entry, if the protocol tree is to
1684    be visible. */
1685 static void
1686 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap)
1687 {
1688         field_info *fi = PITEM_FINFO(pi);
1689
1690         if (fi->visible) {
1691                 fi->representation = g_mem_chunk_alloc(gmc_item_labels);
1692                 vsnprintf(fi->representation, ITEM_LABEL_LENGTH, format, ap);
1693         }
1694 }
1695
1696 /* Set text of proto_item after having already been created. */
1697 void
1698 proto_item_set_text(proto_item *pi, const char *format, ...)
1699 {
1700         field_info *fi = NULL;
1701         va_list ap;
1702
1703         if (pi==NULL) {
1704                 return;
1705         }
1706
1707         fi = PITEM_FINFO(pi);
1708
1709         if (fi->representation)
1710                 g_mem_chunk_free(gmc_item_labels, fi->representation);
1711
1712         va_start(ap, format);
1713         proto_tree_set_representation(pi, format, ap);
1714         va_end(ap);
1715 }
1716
1717 /* Append to text of proto_item after having already been created. */
1718 void
1719 proto_item_append_text(proto_item *pi, const char *format, ...)
1720 {
1721         field_info *fi = NULL;
1722         size_t curlen;
1723         va_list ap;
1724
1725         if (pi==NULL) {
1726                 return;
1727         }
1728
1729         fi = PITEM_FINFO(pi);
1730
1731         if (fi->visible) {
1732                 va_start(ap, format);
1733                 /*
1734                  * XXX - this will blow up if we haven't already set
1735                  * "fi->representation"; that seems OK to me - you
1736                  * can't append to something that doesn't exist - but
1737                  * there might be cases where that's not convenient.
1738                  */
1739                 curlen = strlen(fi->representation);
1740                 if (ITEM_LABEL_LENGTH > curlen)
1741                         vsnprintf(fi->representation + curlen,
1742                             ITEM_LABEL_LENGTH - curlen, format, ap);
1743                 va_end(ap);
1744         }
1745 }
1746
1747 void
1748 proto_item_set_len(proto_item *pi, gint length)
1749 {
1750         field_info *fi;
1751         
1752         if (pi == NULL)
1753                 return;
1754         fi = PITEM_FINFO(pi);
1755         fi->length = length;
1756 }
1757
1758 int
1759 proto_item_get_len(proto_item *pi)
1760 {
1761         field_info *fi = PITEM_FINFO(pi);
1762         return fi->length;
1763 }
1764
1765 proto_tree*
1766 proto_tree_create_root(void)
1767 {
1768     proto_node  *pnode;
1769
1770     /* Initialize the proto_node */
1771     pnode = g_mem_chunk_alloc(gmc_proto_node);
1772     pnode->finfo = NULL;
1773     pnode->tree_data = g_new(tree_data_t, 1);
1774
1775     /* Initialize the tree_data_t */
1776     pnode->tree_data->interesting_hfids =
1777         g_hash_table_new(g_direct_hash, g_direct_equal);
1778
1779     /* Set the default to FALSE so it's easier to
1780      * find errors; if we expect to see the protocol tree
1781      * but for some reason the default 'visible' is not
1782      * changed, then we'll find out very quickly. */
1783     pnode->tree_data->visible = FALSE;
1784
1785         return (proto_tree*) g_node_new(pnode);
1786 }
1787
1788 void
1789 proto_tree_prime_hfid(proto_tree *tree, int hfid)
1790 {
1791     g_hash_table_insert(PTREE_DATA(tree)->interesting_hfids,
1792             GINT_TO_POINTER(hfid), g_ptr_array_new());
1793 }
1794
1795 proto_tree*
1796 proto_item_add_subtree(proto_item *pi,  gint idx) {
1797         field_info *fi;
1798
1799         if (!pi)
1800                 return(NULL);
1801
1802         fi = PITEM_FINFO(pi);
1803         g_assert(idx >= 0 && idx < num_tree_types);
1804         fi->tree_type = idx;
1805         return (proto_tree*) pi;
1806 }
1807
1808 static gint
1809 proto_compare_name(gconstpointer p1_arg, gconstpointer p2_arg)
1810 {
1811         const protocol_t *p1 = p1_arg;
1812         const protocol_t *p2 = p2_arg;
1813
1814         return g_strcasecmp(p1->short_name, p2->short_name);
1815 }
1816
1817 int
1818 proto_register_protocol(char *name, char *short_name, char *filter_name)
1819 {
1820         protocol_t *protocol;
1821         header_field_info *hfinfo;
1822         int proto_id;
1823
1824         /* Add this protocol to the list of known protocols; the list
1825            is sorted by protocol short name. */
1826         protocol = g_malloc(sizeof (protocol_t));
1827         protocol->name = name;
1828         protocol->short_name = short_name;
1829         protocol->filter_name = filter_name;
1830         protocol->fields = NULL;
1831         protocol->is_enabled = TRUE; /* protocol is enabled by default */
1832         protocol->can_disable = TRUE;
1833         protocols = g_list_insert_sorted(protocols, protocol,
1834             proto_compare_name);
1835
1836         /* Here we do allocate a new header_field_info struct */
1837         hfinfo = g_mem_chunk_alloc(gmc_hfinfo);
1838         hfinfo->name = name;
1839         hfinfo->abbrev = filter_name;
1840         hfinfo->type = FT_PROTOCOL;
1841         hfinfo->strings = NULL;
1842         hfinfo->bitmask = 0;
1843         hfinfo->bitshift = 0;
1844         hfinfo->blurb = "";
1845         hfinfo->parent = -1; /* this field differentiates protos and fields */
1846
1847         proto_id = proto_register_field_init(hfinfo, hfinfo->parent);
1848         protocol->proto_id = proto_id;
1849         return proto_id;
1850 }
1851
1852 /*
1853  * Routines to use to iterate over the protocols.
1854  * The argument passed to the iterator routines is an opaque cookie to
1855  * their callers; it's the GList pointer for the current element in
1856  * the list.
1857  * The ID of the protocol is returned, or -1 if there is no protocol.
1858  */
1859 int
1860 proto_get_first_protocol(void **cookie)
1861 {
1862         protocol_t *protocol;
1863
1864         if (protocols == NULL)
1865                 return -1;
1866         *cookie = protocols;
1867         protocol = protocols->data;
1868         return protocol->proto_id;
1869 }
1870
1871 int
1872 proto_get_next_protocol(void **cookie)
1873 {
1874         GList *list_item = *cookie;
1875         protocol_t *protocol;
1876
1877         list_item = g_list_next(list_item);
1878         if (list_item == NULL)
1879                 return -1;
1880         *cookie = list_item;
1881         protocol = list_item->data;
1882         return protocol->proto_id;
1883 }
1884
1885 /*
1886  * Find the protocol list entry for a protocol given its field ID.
1887  */
1888 static gint
1889 compare_proto_id(gconstpointer proto_arg, gconstpointer id_arg)
1890 {
1891         const protocol_t *protocol = proto_arg;
1892         const int *id_ptr = id_arg;
1893
1894         return (protocol->proto_id == *id_ptr) ? 0 : 1;
1895 }
1896
1897 static protocol_t *
1898 find_protocol_by_id(int proto_id)
1899 {
1900         GList *list_entry;
1901         
1902         list_entry = g_list_find_custom(protocols, &proto_id, compare_proto_id);
1903         if (list_entry == NULL)
1904                 return NULL;
1905         return list_entry->data;
1906 }
1907
1908 static gint compare_filter_name(gconstpointer proto_arg, 
1909                                 gconstpointer filter_name)
1910 {
1911   const protocol_t *protocol = proto_arg;
1912   const gchar* f_name = filter_name;
1913   return (strcmp(protocol->filter_name, f_name));
1914 }
1915
1916 int proto_get_id_by_filter_name(gchar* filter_name)
1917 {
1918   GList *list_entry;
1919   protocol_t *protocol;
1920   list_entry = g_list_find_custom(protocols,filter_name,compare_filter_name); 
1921   if(list_entry == NULL)
1922     return -1;
1923   protocol = list_entry->data;
1924   return(protocol->proto_id);
1925 }
1926
1927 char *
1928 proto_get_protocol_name(int proto_id)
1929 {
1930         protocol_t *protocol;
1931
1932         protocol = find_protocol_by_id(proto_id);
1933         return protocol->name;
1934 }
1935
1936 char *
1937 proto_get_protocol_short_name(int proto_id)
1938 {
1939         protocol_t *protocol;
1940
1941         if (proto_id == -1)
1942                 return "(none)";
1943         protocol = find_protocol_by_id(proto_id);
1944         return protocol->short_name;
1945 }
1946
1947 char *
1948 proto_get_protocol_filter_name(int proto_id)
1949 {
1950         protocol_t *protocol;
1951
1952         protocol = find_protocol_by_id(proto_id);
1953         return protocol->filter_name;
1954 }
1955
1956 gboolean
1957 proto_is_protocol_enabled(int proto_id)
1958 {
1959         protocol_t *protocol;
1960
1961         protocol = find_protocol_by_id(proto_id);
1962         return protocol->is_enabled;
1963 }
1964
1965 gboolean
1966 proto_can_disable_protocol(int proto_id)
1967 {
1968         protocol_t *protocol;
1969
1970         protocol = find_protocol_by_id(proto_id);
1971         return protocol->can_disable;
1972 }
1973
1974 void 
1975 proto_set_decoding(int proto_id, gboolean enabled)
1976 {
1977         protocol_t *protocol;
1978
1979         protocol = find_protocol_by_id(proto_id);
1980         g_assert(enabled || protocol->can_disable);
1981         protocol->is_enabled = enabled;
1982 }
1983
1984 void 
1985 proto_set_cant_disable(int proto_id)
1986 {
1987         protocol_t *protocol;
1988
1989         protocol = find_protocol_by_id(proto_id);
1990         protocol->can_disable = FALSE;
1991 }
1992
1993 /* for use with static arrays only, since we don't allocate our own copies
1994 of the header_field_info struct contained withing the hf_register_info struct */
1995 void
1996 proto_register_field_array(int parent, hf_register_info *hf, int num_records)
1997 {
1998         int                     field_id, i;
1999         hf_register_info        *ptr = hf;
2000         protocol_t              *proto;
2001
2002         proto = find_protocol_by_id(parent);
2003         for (i = 0; i < num_records; i++, ptr++) {
2004                 if (proto != NULL) {
2005                         if (proto->fields == NULL) {
2006                                 proto->fields = g_list_append(NULL, ptr);
2007                                 proto->last_field = proto->fields;
2008                         } else {
2009                                 proto->last_field =
2010                                     g_list_append(proto->last_field, ptr)->next;
2011                         }
2012                 }
2013                 field_id = proto_register_field_init(&ptr->hfinfo, parent);
2014                 *ptr->p_id = field_id;
2015         }
2016 }
2017
2018 static int
2019 proto_register_field_init(header_field_info *hfinfo, int parent)
2020 {
2021         /* These types of fields are allowed to have value_strings or true_false_strings */
2022         g_assert((hfinfo->strings == NULL) || (
2023                         (hfinfo->type == FT_UINT8) ||
2024                         (hfinfo->type == FT_UINT16) ||
2025                         (hfinfo->type == FT_UINT24) ||
2026                         (hfinfo->type == FT_UINT32) ||
2027                         (hfinfo->type == FT_INT8) ||
2028                         (hfinfo->type == FT_INT16) ||
2029                         (hfinfo->type == FT_INT24) ||
2030                         (hfinfo->type == FT_INT32) ||
2031                         (hfinfo->type == FT_BOOLEAN) ));
2032
2033         /* Require integral types to have a number base */
2034         switch (hfinfo->type) {
2035
2036         case FT_UINT8:
2037         case FT_UINT16:
2038         case FT_UINT24:
2039         case FT_UINT32:
2040         case FT_INT8:
2041         case FT_INT16:
2042         case FT_INT24:
2043         case FT_INT32:
2044                 g_assert(hfinfo->display != BASE_NONE);
2045                 break;
2046
2047         default:
2048                 break;
2049         }
2050         /* if this is a bitfield, compure bitshift */
2051         if (hfinfo->bitmask) {
2052                 while ((hfinfo->bitmask & (1 << hfinfo->bitshift)) == 0)
2053                         hfinfo->bitshift++;
2054         }
2055
2056         hfinfo->parent = parent;
2057         hfinfo->same_name_next = NULL;
2058         hfinfo->same_name_prev = NULL;
2059
2060         /* if we always add and never delete, then id == len - 1 is correct */
2061         g_ptr_array_add(gpa_hfinfo, hfinfo);
2062         hfinfo->id = gpa_hfinfo->len - 1;
2063         return hfinfo->id;
2064 }
2065
2066 void
2067 proto_register_subtree_array(gint **indices, int num_indices)
2068 {
2069         int     i;
2070         gint    **ptr = indices;
2071
2072         /*
2073          * Add "num_indices" elements to "tree_is_expanded".
2074          */
2075         tree_is_expanded = g_realloc(tree_is_expanded,
2076             (num_tree_types + num_indices)*sizeof (gint));
2077
2078         /*
2079          * Assign "num_indices" subtree numbers starting at "num_tree_types",
2080          * returning the indices through the pointers in the array whose
2081          * first element is pointed to by "indices", set to FALSE the
2082          * elements to which those subtree numbers refer, and update
2083          * "num_tree_types" appropriately.
2084          */
2085         for (i = 0; i < num_indices; i++, ptr++, num_tree_types++) {
2086                 tree_is_expanded[num_tree_types] = FALSE;
2087                 **ptr = num_tree_types;
2088         }
2089 }
2090
2091 void
2092 proto_item_fill_label(field_info *fi, gchar *label_str)
2093 {
2094         header_field_info               *hfinfo = fi->hfinfo;
2095
2096         guint8                          *bytes;
2097         guint32                         integer;
2098         ipv4_addr                       *ipv4;
2099         guint32                         n_addr; /* network-order IPv4 address */
2100
2101         switch(hfinfo->type) {
2102                 case FT_NONE:
2103                 case FT_PROTOCOL:
2104                         snprintf(label_str, ITEM_LABEL_LENGTH,
2105                                 "%s", hfinfo->name);
2106                         break;
2107
2108                 case FT_BOOLEAN:
2109                         fill_label_boolean(fi, label_str);
2110                         break;
2111
2112                 case FT_BYTES:
2113                         bytes = fvalue_get(fi->value);
2114                         if (bytes) {
2115                                 snprintf(label_str, ITEM_LABEL_LENGTH,
2116                                         "%s: %s", hfinfo->name, 
2117                                          bytes_to_str(bytes, fi->length));
2118                         }
2119                         else {
2120                                 snprintf(label_str, ITEM_LABEL_LENGTH,
2121                                         "%s: <MISSING>", hfinfo->name);
2122                         }
2123                         break;
2124
2125                 /* Four types of integers to take care of:
2126                  *      Bitfield, with val_string
2127                  *      Bitfield, w/o val_string
2128                  *      Non-bitfield, with val_string
2129                  *      Non-bitfield, w/o val_string
2130                  */
2131                 case FT_UINT8:
2132                 case FT_UINT16:
2133                 case FT_UINT24:
2134                 case FT_UINT32:
2135                         if (hfinfo->bitmask) {
2136                                 if (hfinfo->strings) {
2137                                         fill_label_enumerated_bitfield(fi, label_str);
2138                                 }
2139                                 else {
2140                                         fill_label_numeric_bitfield(fi, label_str);
2141                                 }
2142                         }
2143                         else {
2144                                 if (hfinfo->strings) {
2145                                         fill_label_enumerated_uint(fi, label_str);
2146                                 }
2147                                 else {
2148                                         fill_label_uint(fi, label_str);
2149                                 }
2150                         }
2151                         break;
2152
2153                 case FT_UINT64:
2154                         fill_label_uint64(fi, label_str);
2155                         break;
2156
2157                 case FT_INT8:
2158                 case FT_INT16:
2159                 case FT_INT24:
2160                 case FT_INT32:
2161                         g_assert(!hfinfo->bitmask);
2162                         if (hfinfo->strings) {
2163                                 fill_label_enumerated_int(fi, label_str);
2164                         }
2165                         else {
2166                                 fill_label_int(fi, label_str);
2167                         }
2168                         break;
2169
2170                 case FT_INT64:
2171                         fill_label_int64(fi, label_str);
2172                         break;
2173
2174                 case FT_DOUBLE:
2175                         snprintf(label_str, ITEM_LABEL_LENGTH,
2176                                 "%s: %g", hfinfo->name, fvalue_get_floating(fi->value));
2177                         break;
2178
2179                 case FT_ABSOLUTE_TIME:
2180                         snprintf(label_str, ITEM_LABEL_LENGTH,
2181                                 "%s: %s", hfinfo->name,
2182                                 abs_time_to_str(fvalue_get(fi->value)));
2183                         break;
2184
2185                 case FT_RELATIVE_TIME:
2186                         snprintf(label_str, ITEM_LABEL_LENGTH,
2187                                 "%s: %s seconds", hfinfo->name,
2188                                 rel_time_to_secs_str(fvalue_get(fi->value)));
2189                         break;
2190
2191                 case FT_IPXNET:
2192                         integer = fvalue_get_integer(fi->value);
2193                         snprintf(label_str, ITEM_LABEL_LENGTH,
2194                                 "%s: 0x%08X (%s)", hfinfo->name,
2195                                 integer, get_ipxnet_name(integer));
2196                         break;
2197
2198                 case FT_ETHER:
2199                         bytes = fvalue_get(fi->value);
2200                         snprintf(label_str, ITEM_LABEL_LENGTH,
2201                                 "%s: %s (%s)", hfinfo->name,
2202                                 ether_to_str(bytes),
2203                                 get_ether_name(bytes));
2204                         break;
2205
2206                 case FT_IPv4:
2207                         ipv4 = fvalue_get(fi->value);
2208                         n_addr = ipv4_get_net_order_addr(ipv4);
2209                         snprintf(label_str, ITEM_LABEL_LENGTH,
2210                                 "%s: %s (%s)", hfinfo->name,
2211                                 get_hostname(n_addr),
2212                                 ip_to_str((guint8*)&n_addr));
2213                         break;
2214
2215                 case FT_IPv6:
2216                         bytes = fvalue_get(fi->value);
2217                         snprintf(label_str, ITEM_LABEL_LENGTH,
2218                                 "%s: %s (%s)", hfinfo->name,
2219                                 get_hostname6((struct e_in6_addr *)bytes),
2220                                 ip6_to_str((struct e_in6_addr*)bytes));
2221                         break;
2222         
2223                 case FT_STRING:
2224                 case FT_STRINGZ:
2225                 case FT_UINT_STRING:
2226                         snprintf(label_str, ITEM_LABEL_LENGTH,
2227                                 "%s: %s", hfinfo->name, (char*) fvalue_get(fi->value));
2228                         break;
2229
2230                 default:
2231                         g_error("hfinfo->type %d (%s) not handled\n",
2232                                         hfinfo->type,
2233                                         ftype_name(hfinfo->type));
2234                         g_assert_not_reached();
2235                         break;
2236         }
2237 }
2238
2239 static void
2240 fill_label_uint64(field_info *fi, gchar *label_str)
2241 {
2242         unsigned char *bytes;
2243         header_field_info *hfinfo = fi->hfinfo;
2244
2245         bytes=fvalue_get(fi->value);
2246         switch(hfinfo->display){
2247         case BASE_DEC:
2248                 snprintf(label_str, ITEM_LABEL_LENGTH,
2249                         "%s: %s", hfinfo->name,
2250                         u64toa(bytes));
2251                 break;
2252         case BASE_HEX:
2253                 snprintf(label_str, ITEM_LABEL_LENGTH,
2254                         "%s: %s", hfinfo->name,
2255                         u64toh(bytes));
2256                 break;
2257         default:
2258                 g_assert_not_reached();
2259                 ;
2260         }
2261 }
2262
2263 static void
2264 fill_label_int64(field_info *fi, gchar *label_str)
2265 {
2266         unsigned char *bytes;
2267         header_field_info *hfinfo = fi->hfinfo;
2268
2269         bytes=fvalue_get(fi->value);
2270         switch(hfinfo->display){
2271         case BASE_DEC:
2272                 snprintf(label_str, ITEM_LABEL_LENGTH,
2273                         "%s: %s", hfinfo->name,
2274                         i64toa(bytes));
2275                 break;
2276         case BASE_HEX:
2277                 snprintf(label_str, ITEM_LABEL_LENGTH,
2278                         "%s: %s", hfinfo->name,
2279                         u64toh(bytes));
2280                 break;
2281         default:
2282                 g_assert_not_reached();
2283                 ;
2284         }
2285 }
2286
2287 static void
2288 fill_label_boolean(field_info *fi, gchar *label_str)
2289 {
2290         char    *p = label_str;
2291         int     bitfield_byte_length = 0, bitwidth;
2292         guint32 unshifted_value;
2293         guint32 value;
2294
2295         header_field_info               *hfinfo = fi->hfinfo;
2296         static true_false_string        default_tf = { "True", "False" };
2297         true_false_string               *tfstring = &default_tf;
2298
2299         if (hfinfo->strings) {
2300                 tfstring = (struct true_false_string*) hfinfo->strings;
2301         }
2302
2303         value = fvalue_get_integer(fi->value);
2304         if (hfinfo->bitmask) {
2305                 /* Figure out the bit width */
2306                 bitwidth = hfinfo_bitwidth(hfinfo);
2307
2308                 /* Un-shift bits */
2309                 unshifted_value = value;
2310                 if (hfinfo->bitshift > 0) {
2311                         unshifted_value <<= hfinfo->bitshift;
2312                 }
2313
2314                 /* Create the bitfield first */
2315                 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
2316                 bitfield_byte_length = p - label_str;
2317         }
2318
2319         /* Fill in the textual info */
2320         snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
2321                 "%s: %s",  hfinfo->name,
2322                 value ? tfstring->true_string : tfstring->false_string);
2323 }
2324
2325
2326 /* Fills data for bitfield ints with val_strings */
2327 static void
2328 fill_label_enumerated_bitfield(field_info *fi, gchar *label_str)
2329 {
2330         char *format = NULL, *p;
2331         int bitfield_byte_length, bitwidth;
2332         guint32 unshifted_value;
2333         guint32 value;
2334
2335         header_field_info       *hfinfo = fi->hfinfo;
2336
2337         /* Figure out the bit width */
2338         bitwidth = hfinfo_bitwidth(hfinfo);
2339
2340         /* Pick the proper format string */
2341         format = hfinfo_uint_vals_format(hfinfo);
2342
2343         /* Un-shift bits */
2344         unshifted_value = fvalue_get_integer(fi->value);
2345         value = unshifted_value;
2346         if (hfinfo->bitshift > 0) {
2347                 unshifted_value <<= hfinfo->bitshift;
2348         }
2349
2350         /* Create the bitfield first */
2351         p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
2352         bitfield_byte_length = p - label_str;
2353
2354         /* Fill in the textual info using stored (shifted) value */
2355         snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
2356                         format,  hfinfo->name,
2357                         val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
2358 }
2359
2360 static void
2361 fill_label_numeric_bitfield(field_info *fi, gchar *label_str)
2362 {
2363         char *format = NULL, *p;
2364         int bitfield_byte_length, bitwidth;
2365         guint32 unshifted_value;
2366         guint32 value;
2367
2368         header_field_info       *hfinfo = fi->hfinfo;
2369
2370         /* Figure out the bit width */
2371         bitwidth = hfinfo_bitwidth(hfinfo);
2372
2373         /* Pick the proper format string */
2374         format = hfinfo_uint_format(hfinfo);
2375
2376         /* Un-shift bits */
2377         unshifted_value = fvalue_get_integer(fi->value);
2378         value = unshifted_value;
2379         if (hfinfo->bitshift > 0) {
2380                 unshifted_value <<= hfinfo->bitshift;
2381         }
2382
2383         /* Create the bitfield using */
2384         p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
2385         bitfield_byte_length = p - label_str;
2386
2387         /* Fill in the textual info using stored (shifted) value */
2388         snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
2389                         format,  hfinfo->name, value);
2390 }
2391
2392 static void
2393 fill_label_enumerated_uint(field_info *fi, gchar *label_str)
2394 {
2395         char *format = NULL;
2396         header_field_info       *hfinfo = fi->hfinfo;
2397         guint32 value;
2398
2399         /* Pick the proper format string */
2400         format = hfinfo_uint_vals_format(hfinfo);
2401
2402         value = fvalue_get_integer(fi->value);
2403
2404         /* Fill in the textual info */
2405         snprintf(label_str, ITEM_LABEL_LENGTH,
2406                         format,  hfinfo->name,
2407                         val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
2408 }
2409
2410 static void
2411 fill_label_uint(field_info *fi, gchar *label_str)
2412 {
2413         char *format = NULL;
2414         header_field_info       *hfinfo = fi->hfinfo;
2415         guint32 value;
2416
2417         /* Pick the proper format string */
2418         format = hfinfo_uint_format(hfinfo);
2419         value = fvalue_get_integer(fi->value);
2420
2421         /* Fill in the textual info */
2422         snprintf(label_str, ITEM_LABEL_LENGTH,
2423                         format,  hfinfo->name, value);
2424 }
2425
2426 static void
2427 fill_label_enumerated_int(field_info *fi, gchar *label_str)
2428 {
2429         char *format = NULL;
2430         header_field_info       *hfinfo = fi->hfinfo;
2431         guint32 value;
2432
2433         /* Pick the proper format string */
2434         format = hfinfo_int_vals_format(hfinfo);
2435         value = fvalue_get_integer(fi->value);
2436
2437         /* Fill in the textual info */
2438         snprintf(label_str, ITEM_LABEL_LENGTH,
2439                         format,  hfinfo->name,
2440                         val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
2441 }
2442
2443 static void
2444 fill_label_int(field_info *fi, gchar *label_str)
2445 {
2446         char *format = NULL;
2447         header_field_info       *hfinfo = fi->hfinfo;
2448         guint32 value;
2449
2450         /* Pick the proper format string */
2451         format = hfinfo_int_format(hfinfo);
2452         value = fvalue_get_integer(fi->value);
2453
2454         /* Fill in the textual info */
2455         snprintf(label_str, ITEM_LABEL_LENGTH,
2456                         format,  hfinfo->name, value);
2457 }
2458
2459 int
2460 hfinfo_bitwidth(header_field_info *hfinfo)
2461 {
2462         int bitwidth = 0;
2463
2464         if (!hfinfo->bitmask) {
2465                 return 0;
2466         }
2467
2468         switch(hfinfo->type) {
2469                 case FT_UINT8:
2470                 case FT_INT8:
2471                         bitwidth = 8;
2472                         break;
2473                 case FT_UINT16:
2474                 case FT_INT16:
2475                         bitwidth = 16;
2476                         break;
2477                 case FT_UINT24:
2478                 case FT_INT24:
2479                         bitwidth = 24;
2480                         break;
2481                 case FT_UINT32:
2482                 case FT_INT32:
2483                         bitwidth = 32;
2484                         break;
2485                 case FT_BOOLEAN:
2486                         bitwidth = hfinfo->display; /* hacky? :) */
2487                         break;
2488                 default:
2489                         g_assert_not_reached();
2490                         ;
2491         }
2492         return bitwidth;
2493 }
2494
2495 static char*
2496 hfinfo_uint_vals_format(header_field_info *hfinfo)
2497 {
2498         char *format = NULL;
2499
2500         switch(hfinfo->display) {
2501                 case BASE_DEC:
2502                 case BASE_BIN: /* I'm lazy */
2503                         format = "%s: %s (%u)";
2504                         break;
2505                 case BASE_OCT: /* I'm lazy */
2506                         format = "%s: %s (%o)";
2507                         break;
2508                 case BASE_HEX:
2509                         switch(hfinfo->type) {
2510                                 case FT_UINT8:
2511                                         format = "%s: %s (0x%02x)";
2512                                         break;
2513                                 case FT_UINT16:
2514                                         format = "%s: %s (0x%04x)";
2515                                         break;
2516                                 case FT_UINT24:
2517                                         format = "%s: %s (0x%06x)";
2518                                         break;
2519                                 case FT_UINT32:
2520                                         format = "%s: %s (0x%08x)";
2521                                         break;
2522                                 default:
2523                                         g_assert_not_reached();
2524                                         ;
2525                         }
2526                         break;
2527                 default:
2528                         g_assert_not_reached();
2529                         ;
2530         }
2531         return format;
2532 }
2533
2534 static char*
2535 hfinfo_uint_format(header_field_info *hfinfo)
2536 {
2537         char *format = NULL;
2538
2539         /* Pick the proper format string */
2540         switch(hfinfo->display) {
2541                 case BASE_DEC:
2542                 case BASE_BIN: /* I'm lazy */
2543                         format = "%s: %u";
2544                         break;
2545                 case BASE_OCT: /* I'm lazy */
2546                         format = "%s: %o";
2547                         break;
2548                 case BASE_HEX:
2549                         switch(hfinfo->type) {
2550                                 case FT_UINT8:
2551                                         format = "%s: 0x%02x";
2552                                         break;
2553                                 case FT_UINT16:
2554                                         format = "%s: 0x%04x";
2555                                         break;
2556                                 case FT_UINT24:
2557                                         format = "%s: 0x%06x";
2558                                         break;
2559                                 case FT_UINT32:
2560                                         format = "%s: 0x%08x";
2561                                         break;
2562                                 default:
2563                                         g_assert_not_reached();
2564                                         ;
2565                         }
2566                         break;
2567                 default:
2568                         g_assert_not_reached();
2569                         ;
2570         }
2571         return format;
2572 }
2573
2574 static char*
2575 hfinfo_int_vals_format(header_field_info *hfinfo)
2576 {
2577         char *format = NULL;
2578
2579         switch(hfinfo->display) {
2580                 case BASE_DEC:
2581                 case BASE_BIN: /* I'm lazy */
2582                         format = "%s: %s (%d)";
2583                         break;
2584                 case BASE_OCT: /* I'm lazy */
2585                         format = "%s: %s (%o)";
2586                         break;
2587                 case BASE_HEX:
2588                         switch(hfinfo->type) {
2589                                 case FT_INT8:
2590                                         format = "%s: %s (0x%02x)";
2591                                         break;
2592                                 case FT_INT16:
2593                                         format = "%s: %s (0x%04x)";
2594                                         break;
2595                                 case FT_INT24:
2596                                         format = "%s: %s (0x%06x)";
2597                                         break;
2598                                 case FT_INT32:
2599                                         format = "%s: %s (0x%08x)";
2600                                         break;
2601                                 default:
2602                                         g_assert_not_reached();
2603                                         ;
2604                         }
2605                         break;
2606                 default:
2607                         g_assert_not_reached();
2608                         ;
2609         }
2610         return format;
2611 }
2612
2613 static char*
2614 hfinfo_int_format(header_field_info *hfinfo)
2615 {
2616         char *format = NULL;
2617
2618         /* Pick the proper format string */
2619         switch(hfinfo->display) {
2620                 case BASE_DEC:
2621                 case BASE_BIN: /* I'm lazy */
2622                         format = "%s: %d";
2623                         break;
2624                 case BASE_OCT: /* I'm lazy */
2625                         format = "%s: %o";
2626                         break;
2627                 case BASE_HEX:
2628                         switch(hfinfo->type) {
2629                                 case FT_INT8:
2630                                         format = "%s: 0x%02x";
2631                                         break;
2632                                 case FT_INT16:
2633                                         format = "%s: 0x%04x";
2634                                         break;
2635                                 case FT_INT24:
2636                                         format = "%s: 0x%06x";
2637                                         break;
2638                                 case FT_INT32:
2639                                         format = "%s: 0x%08x";
2640                                         break;
2641                                 default:
2642                                         g_assert_not_reached();
2643                                         ;
2644                         }
2645                         break;
2646                 default:
2647                         g_assert_not_reached();
2648                         ;
2649         }
2650         return format;
2651 }
2652
2653
2654
2655 int
2656 proto_registrar_n(void)
2657 {
2658         return gpa_hfinfo->len;
2659 }
2660
2661 char*
2662 proto_registrar_get_name(int n)
2663 {
2664         header_field_info *hfinfo;
2665
2666         hfinfo = proto_registrar_get_nth(n);
2667         if (hfinfo)
2668                 return hfinfo->name;
2669         else
2670                 return NULL;
2671 }
2672
2673 char*
2674 proto_registrar_get_abbrev(int n)
2675 {
2676         header_field_info *hfinfo;
2677
2678         hfinfo = proto_registrar_get_nth(n);
2679         if (hfinfo)
2680                 return hfinfo->abbrev;
2681         else
2682                 return NULL;
2683 }
2684
2685 int
2686 proto_registrar_get_ftype(int n)
2687 {
2688         header_field_info *hfinfo;
2689
2690         hfinfo = proto_registrar_get_nth(n);
2691         if (hfinfo)
2692                 return hfinfo->type;
2693         else
2694                 return -1;
2695 }
2696
2697 int
2698 proto_registrar_get_parent(int n)
2699 {
2700         header_field_info *hfinfo;
2701
2702         hfinfo = proto_registrar_get_nth(n);
2703         if (hfinfo)
2704                 return hfinfo->parent;
2705         else
2706                 return -2;
2707 }
2708
2709 gboolean
2710 proto_registrar_is_protocol(int n)
2711 {
2712         header_field_info *hfinfo;
2713
2714         hfinfo = proto_registrar_get_nth(n);
2715         if (hfinfo)
2716                 return (hfinfo->parent == -1 ? TRUE : FALSE);
2717         else
2718                 return FALSE;
2719 }
2720
2721 /* Returns length of field in packet (not necessarily the length
2722  * in our internal representation, as in the case of IPv4).
2723  * 0 means undeterminable at time of registration
2724  * -1 means the field is not registered. */
2725 gint
2726 proto_registrar_get_length(int n)
2727 {
2728         header_field_info *hfinfo;
2729
2730         hfinfo = proto_registrar_get_nth(n);
2731         if (!hfinfo)
2732                 return -1;
2733
2734         return ftype_length(hfinfo->type);
2735 }
2736
2737
2738 /* =================================================================== */
2739 /* used when calling proto search functions */
2740 typedef struct {
2741         header_field_info       *target;
2742         const guint8            *packet_data;
2743         guint                   packet_len;
2744         gboolean                halt_on_first_hit;
2745         GNodeTraverseFunc       traverse_func; /* for traverse_subtree_for_field() */
2746         union {
2747                 GPtrArray               *ptr_array;
2748                 GNode                   *node;
2749         }                       result;
2750 } proto_tree_search_info;
2751
2752 /* Looks for a protocol at the top layer of the tree. The protocol can occur
2753  * more than once, for those encapsulated protocols. For each protocol subtree
2754  * that is found, the callback function is called.
2755  */
2756 static void
2757 proto_find_protocol_multi(proto_tree* tree, GNodeTraverseFunc callback,
2758                         proto_tree_search_info *sinfo)
2759 {
2760         g_assert(callback != NULL);
2761         g_node_traverse((GNode*)tree, G_IN_ORDER, G_TRAVERSE_ALL, 2, callback, (gpointer*)sinfo);
2762 }
2763
2764 /* Calls a traversal function for all subtrees.
2765  */
2766 static gboolean
2767 traverse_subtree_for_field(GNode *node, gpointer data)
2768 {
2769         field_info *fi = PITEM_FINFO(node);
2770         proto_tree_search_info  *sinfo = (proto_tree_search_info*) data;
2771
2772         if (fi) { /* !fi == the top most container node which holds nothing */
2773                         g_node_traverse(node, G_IN_ORDER, G_TRAVERSE_ALL, -1,
2774                                         sinfo->traverse_func, sinfo);
2775                         if (sinfo->result.node)
2776                                 return sinfo->halt_on_first_hit; /* halt? continue? */
2777         }
2778         return FALSE; /* keep traversing */
2779 }
2780
2781 /* Looks for a protocol or a field in a proto_tree. Returns TRUE if
2782  * it exists anywhere, or FALSE if it exists nowhere. */
2783 gboolean
2784 proto_check_for_protocol_or_field(proto_tree* tree, int id)
2785 {
2786     GPtrArray *ptrs = proto_get_finfo_ptr_array(tree, id);
2787
2788     if (!ptrs) {
2789         return FALSE;
2790     }
2791     else if (g_ptr_array_len(ptrs) > 0) {
2792         return TRUE;
2793     }
2794     else {
2795         return FALSE;
2796     }
2797 }
2798
2799 /* Return GPtrArray* of field_info pointers for all hfindex that appear in tree.
2800  * This only works if the hfindex was "primed" before the dissection
2801  * took place, as we just pass back the already-created GPtrArray*.
2802  * The caller should *not* free the GPtrArray*; proto_tree_free_node()
2803  * handles that. */
2804 GPtrArray*
2805 proto_get_finfo_ptr_array(proto_tree *tree, int id)
2806 {
2807     return g_hash_table_lookup(PTREE_DATA(tree)->interesting_hfids,
2808             GINT_TO_POINTER(id));
2809 }
2810
2811
2812 typedef struct {
2813         guint           offset;
2814         field_info      *finfo;
2815         tvbuff_t        *tvb;
2816 } offset_search_t;
2817
2818 static gboolean
2819 check_for_offset(GNode *node, gpointer data)
2820 {
2821         field_info          *fi = PITEM_FINFO(node);
2822         offset_search_t         *offsearch = data;
2823
2824         /* !fi == the top most container node which holds nothing */
2825         if (fi && fi->visible && fi->ds_tvb && offsearch->tvb == fi->ds_tvb) {
2826                 if (offsearch->offset >= (guint) fi->start &&
2827                                 offsearch->offset < (guint) (fi->start + fi->length)) {
2828
2829                         offsearch->finfo = fi;
2830                         return FALSE; /* keep traversing */
2831                 }
2832         }
2833         return FALSE; /* keep traversing */
2834 }
2835
2836 /* Search a proto_tree backwards (from leaves to root) looking for the field
2837  * whose start/length occupies 'offset' */
2838 /* XXX - I couldn't find an easy way to search backwards, so I search
2839  * forwards, w/o stopping. Therefore, the last finfo I find will the be
2840  * the one I want to return to the user. This algorithm is inefficient
2841  * and could be re-done, but I'd have to handle all the children and
2842  * siblings of each node myself. When I have more time I'll do that.
2843  * (yeah right) */
2844 field_info*
2845 proto_find_field_from_offset(proto_tree *tree, guint offset, tvbuff_t *tvb)
2846 {
2847         offset_search_t         offsearch;
2848
2849         offsearch.offset = offset;
2850         offsearch.finfo = NULL;
2851         offsearch.tvb = tvb;
2852
2853         g_node_traverse((GNode*)tree, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
2854                         check_for_offset, &offsearch);
2855
2856         return offsearch.finfo;
2857 }
2858
2859
2860
2861         
2862
2863 /* Dumps the contents of the registration database to stdout. An indepedent program can take
2864  * this output and format it into nice tables or HTML or whatever.
2865  *
2866  * There is one record per line. Each record is either a protocol or a header
2867  * field, differentiated by the first field. The fields are tab-delimited.
2868  *
2869  * Protocols
2870  * ---------
2871  * Field 1 = 'P'
2872  * Field 2 = protocol name
2873  * Field 3 = protocol abbreviation
2874  *
2875  * Header Fields
2876  * -------------
2877  * Field 1 = 'F'
2878  * Field 2 = field name
2879  * Field 3 = field abbreviation
2880  * Field 4 = type ( textual representation of the the ftenum type )
2881  * Field 5 = parent protocol abbreviation
2882  */
2883 void
2884 proto_registrar_dump(void)
2885 {
2886         header_field_info       *hfinfo, *parent_hfinfo;
2887         int                     i, len;
2888         const char              *enum_name;
2889
2890         len = gpa_hfinfo->len;
2891         for (i = 0; i < len ; i++) {
2892                 hfinfo = proto_registrar_get_nth(i);
2893
2894                 /*
2895                  * Skip fields with zero-length names or abbreviations;
2896                  * the pseudo-field for "proto_tree_add_text()" is such
2897                  * a field, and we don't want it in the list of filterable
2898                  * fields.
2899                  *
2900                  *
2901                  * XXX - perhaps the name and abbrev field should be null
2902                  * pointers rather than null strings for that pseudo-field,
2903                  * but we'd have to add checks for null pointers in some
2904                  * places if we did that.
2905                  *
2906                  * Or perhaps protocol tree items added with
2907                  * "proto_tree_add_text()" should have -1 as the field index,
2908                  * with no pseudo-field being used, but that might also
2909                  * require special checks for -1 to be added.
2910                  */
2911                 if (strlen(hfinfo->name) == 0 || strlen(hfinfo->abbrev) == 0)
2912                         continue;
2913
2914                 /* format for protocols */
2915                 if (proto_registrar_is_protocol(i)) {
2916                         printf("P\t%s\t%s\n", hfinfo->name, hfinfo->abbrev);
2917                 }
2918                 /* format for header fields */
2919                 else {
2920                         /*
2921                          * If this field isn't at the head of the list of
2922                          * fields with this name, skip this field - all
2923                          * fields with the same name are really just versions
2924                          * of the same field stored in different bits, and
2925                          * should have the same type/radix/value list, and
2926                          * just differ in their bit masks.  (If a field isn't
2927                          * a bitfield, but can be, say, 1 or 2 bytes long,
2928                          * it can just be made FT_UINT16, meaning the
2929                          * *maximum* length is 2 bytes, and be used
2930                          * for all lengths.)
2931                          */
2932                         if (hfinfo->same_name_prev != NULL)
2933                                 continue;
2934
2935                         parent_hfinfo = proto_registrar_get_nth(hfinfo->parent);
2936                         g_assert(parent_hfinfo);
2937
2938                         enum_name = ftype_name(hfinfo->type);
2939                         printf("F\t%s\t%s\t%s\t%s\n", hfinfo->name, hfinfo->abbrev,
2940                                 enum_name,parent_hfinfo->abbrev);
2941                 }
2942         }
2943 }
2944
2945 static char*
2946 hfinfo_numeric_format(header_field_info *hfinfo)
2947 {
2948         char *format = NULL;
2949
2950         /* Pick the proper format string */
2951         switch(hfinfo->display) {
2952                 case BASE_DEC:
2953                 case BASE_OCT: /* I'm lazy */
2954                 case BASE_BIN: /* I'm lazy */
2955                         switch(hfinfo->type) {
2956                                 case FT_UINT8:
2957                                 case FT_UINT16:
2958                                 case FT_UINT24:
2959                                 case FT_UINT32:
2960                                         format = "%s == %u";
2961                                         break;
2962                                 case FT_INT8:
2963                                 case FT_INT16:
2964                                 case FT_INT24:
2965                                 case FT_INT32:
2966                                         format = "%s == %d";
2967                                         break;
2968                                 default:
2969                                         g_assert_not_reached();
2970                                         ;
2971                         }
2972                         break;
2973                 case BASE_HEX:
2974                         switch(hfinfo->type) {
2975                                 case FT_UINT8:
2976                                         format = "%s == 0x%02x";
2977                                         break;
2978                                 case FT_UINT16:
2979                                         format = "%s == 0x%04x";
2980                                         break;
2981                                 case FT_UINT24:
2982                                         format = "%s == 0x%06x";
2983                                         break;
2984                                 case FT_UINT32:
2985                                         format = "%s == 0x%08x";
2986                                         break;
2987                                 default:
2988                                         g_assert_not_reached();
2989                                         ;
2990                         }
2991                         break;
2992                 default:
2993                         g_assert_not_reached();
2994                         ;
2995         }
2996         return format;
2997 }
2998
2999 /*
3000  * Returns TRUE if we can do a "match selected" on the field, FALSE
3001  * otherwise.
3002  */
3003 gboolean
3004 proto_can_match_selected(field_info *finfo)
3005 {
3006         header_field_info       *hfinfo;
3007
3008         hfinfo = finfo->hfinfo;
3009         g_assert(hfinfo);
3010
3011         switch(hfinfo->type) {
3012
3013                 case FT_BOOLEAN:
3014                 case FT_UINT8:
3015                 case FT_UINT16:
3016                 case FT_UINT24:
3017                 case FT_UINT32:
3018                 case FT_UINT64:
3019                 case FT_INT8:
3020                 case FT_INT16:
3021                 case FT_INT24:
3022                 case FT_INT32:
3023                 case FT_INT64:
3024                 case FT_IPv4:
3025                 case FT_IPXNET:
3026                 case FT_IPv6:
3027                 case FT_DOUBLE:
3028                 case FT_ETHER:
3029                 case FT_ABSOLUTE_TIME:
3030                 case FT_RELATIVE_TIME:
3031                 case FT_STRING:
3032                 case FT_BYTES:
3033                         /*
3034                          * These all have values, so we can match.
3035                          */
3036                         return TRUE;
3037
3038                 default:
3039                         /*
3040                          * This doesn't have a value, so we'd match
3041                          * on the raw bytes at this address;
3042                          * however, if the length is 0, there's nothing
3043                          * to match, so we can't match.
3044                          */
3045                         return (finfo->length != 0);
3046         }
3047 }
3048
3049 char*
3050 proto_alloc_dfilter_string(field_info *finfo, guint8 *pd)
3051 {
3052         header_field_info       *hfinfo;
3053         int                     abbrev_len;
3054         char                    *buf, *stringified, *format, *ptr, *value_str;
3055         int                     dfilter_len, i;
3056         guint8                  *c;
3057
3058         hfinfo = finfo->hfinfo;
3059         g_assert(hfinfo);
3060         abbrev_len = strlen(hfinfo->abbrev);
3061
3062         switch(hfinfo->type) {
3063
3064                 case FT_BOOLEAN:
3065                         dfilter_len = abbrev_len + 6;
3066                         buf = g_malloc0(dfilter_len);
3067                         snprintf(buf, dfilter_len, "%s == %s",
3068                                         hfinfo->abbrev,
3069                                         fvalue_get_integer(finfo->value) ? "1" : "0");
3070                         break;
3071
3072                 case FT_UINT8:
3073                 case FT_UINT16:
3074                 case FT_UINT24:
3075                 case FT_UINT32:
3076                 case FT_INT8:
3077                 case FT_INT16:
3078                 case FT_INT24:
3079                 case FT_INT32:
3080                         dfilter_len = abbrev_len + 20;
3081                         buf = g_malloc0(dfilter_len);
3082                         format = hfinfo_numeric_format(hfinfo);
3083                         snprintf(buf, dfilter_len, format, hfinfo->abbrev, fvalue_get_integer(finfo->value));
3084                         break;
3085
3086                 case FT_UINT64:
3087                         stringified = u64toa(fvalue_get(finfo->value));
3088                         dfilter_len = abbrev_len + 4 + strlen(stringified) +1;
3089                         buf = g_malloc0(dfilter_len);
3090                         snprintf(buf, dfilter_len, "%s == %s", hfinfo->abbrev,
3091                                         stringified);
3092                         break;
3093
3094                 case FT_INT64:
3095                         stringified = i64toa(fvalue_get(finfo->value));
3096                         dfilter_len = abbrev_len + 4 + strlen(stringified) +1;
3097                         buf = g_malloc0(dfilter_len);
3098                         snprintf(buf, dfilter_len, "%s == %s", hfinfo->abbrev,
3099                                         stringified);
3100                         break;
3101
3102                 case FT_IPv4:
3103                         dfilter_len = abbrev_len + 4 + 15 + 1;
3104                         buf = g_malloc0(dfilter_len);
3105                         snprintf(buf, dfilter_len, "%s == %s", hfinfo->abbrev,
3106                                         ipv4_addr_str(fvalue_get(finfo->value)));
3107                         break;
3108
3109                 case FT_IPXNET:
3110                         dfilter_len = abbrev_len + 15;
3111                         buf = g_malloc0(dfilter_len);
3112                         snprintf(buf, dfilter_len, "%s == 0x%08x", hfinfo->abbrev,
3113                                         fvalue_get_integer(finfo->value));
3114                         break;
3115
3116                 case FT_IPv6:
3117                         stringified = ip6_to_str((struct e_in6_addr*) fvalue_get(finfo->value));
3118                         dfilter_len = abbrev_len + 4 + strlen(stringified) + 1;
3119                         buf = g_malloc0(dfilter_len);
3120                         snprintf(buf, dfilter_len, "%s == %s", hfinfo->abbrev,
3121                                         stringified);
3122                         break;
3123
3124                 case FT_DOUBLE:
3125                         dfilter_len = abbrev_len + 30;
3126                         buf = g_malloc0(dfilter_len);
3127                         snprintf(buf, dfilter_len, "%s == %f", hfinfo->abbrev,
3128                                         fvalue_get_floating(finfo->value));
3129                         break;
3130
3131                 case FT_ETHER:
3132                         dfilter_len = abbrev_len + 22;
3133                         buf = g_malloc0(dfilter_len);
3134                         snprintf(buf, dfilter_len, "%s == %s",
3135                                         hfinfo->abbrev,
3136                                         ether_to_str(fvalue_get(finfo->value)));
3137                         break;
3138
3139                 case FT_ABSOLUTE_TIME:
3140                         value_str =
3141                             abs_time_to_str((nstime_t *)fvalue_get(finfo->value));
3142                         dfilter_len = abbrev_len + strlen(value_str) + 7;
3143                         buf = g_malloc0(dfilter_len);
3144                         snprintf(buf, dfilter_len, "%s == \"%s\"",
3145                                         hfinfo->abbrev, value_str);
3146                         break;
3147
3148                 case FT_RELATIVE_TIME:
3149                         value_str =
3150                             rel_time_to_secs_str((nstime_t *)fvalue_get(finfo->value));
3151                         dfilter_len = abbrev_len + strlen(value_str) + 4;
3152                         buf = g_malloc0(dfilter_len);
3153                         snprintf(buf, dfilter_len, "%s == %s",
3154                                         hfinfo->abbrev, value_str);
3155                         break;
3156
3157 #if 0
3158                 case FT_TEXT_ONLY:
3159                         ; /* nothing */
3160                         break;
3161 #endif
3162
3163                 case FT_STRING:
3164                         value_str = fvalue_get(finfo->value);
3165                         dfilter_len = abbrev_len + strlen(value_str) + 7;
3166                         buf = g_malloc0(dfilter_len);
3167                         snprintf(buf, dfilter_len, "%s == \"%s\"",
3168                                  hfinfo->abbrev, value_str);
3169                         break;
3170
3171                 case FT_BYTES:
3172                         dfilter_len = finfo->length*3 - 1;
3173                         dfilter_len += abbrev_len + 7;
3174                         buf = g_malloc0(dfilter_len);
3175                         snprintf(buf, dfilter_len, "%s == %s",
3176                                  hfinfo->abbrev,
3177                                  bytes_to_str_punct(fvalue_get(finfo->value), finfo->length,':'));
3178                         break;       
3179
3180                 default:
3181                         c = pd + finfo->start;
3182                         buf = g_malloc0(32 + finfo->length * 3);
3183                         ptr = buf;
3184
3185                         sprintf(ptr, "frame[%d] == ", finfo->start);
3186                         ptr = buf+strlen(buf);
3187
3188                         for (i=0;i<finfo->length; i++) {
3189                                 if (i == 0 ) {
3190                                         sprintf(ptr, "%02x", *c++);
3191                                 }
3192                                 else {
3193                                         sprintf(ptr, ":%02x", *c++);
3194                                 }
3195                                 ptr = buf+strlen(buf);
3196                         }
3197                         break;
3198         }
3199
3200         return buf;
3201 }