From Didier:
[obnox/wireshark/wip.git] / epan / proto.c
1 /* proto.c
2  * Routines for protocol tree
3  *
4  * $Id$
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 #include <stdio.h>
30 #include <string.h>
31 #include <ctype.h>
32 #include <glib.h>
33 #include <float.h>
34
35 #ifdef NEED_SNPRINTF_H
36 # include "snprintf.h"
37 #endif
38
39 #include "packet.h"
40 #include "strutil.h"
41 #include "addr_resolv.h"
42 #include "plugins.h"
43 #include "ipv6-utils.h"
44 #include "proto.h"
45 #include "epan_dissect.h"
46 #include "slab.h"
47 #include "tvbuff.h"
48
49 #define cVALS(x) (const value_string*)(x)
50
51 static gboolean
52 proto_tree_free_node(proto_node *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_enumerated_uint(field_info *fi, gchar *label_str);
58 static void fill_label_enumerated_bitfield(field_info *fi, gchar *label_str);
59 static void fill_label_numeric_bitfield(field_info *fi, gchar *label_str);
60 static void fill_label_int(field_info *fi, gchar *label_str);
61 static void fill_label_int64(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_uint64_format(header_field_info *hfinfo);
68 static char* hfinfo_int_vals_format(header_field_info *hfinfo);
69 static char* hfinfo_int_format(header_field_info *hfinfo);
70 static char* hfinfo_int64_format(header_field_info *hfinfo);
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_bytes(field_info *fi, const guint8* start_ptr, gint length);
90 static void
91 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length);
92 static void
93 proto_tree_set_time(field_info *fi, nstime_t *value_ptr);
94 static void
95 proto_tree_set_string(field_info *fi, const char* value, gboolean);
96 static void
97 proto_tree_set_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
98 static void
99 proto_tree_set_ether(field_info *fi, const guint8* value);
100 static void
101 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start);
102 static void
103 proto_tree_set_ipxnet(field_info *fi, guint32 value);
104 static void
105 proto_tree_set_ipv4(field_info *fi, guint32 value);
106 static void
107 proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr);
108 static void
109 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start);
110 static void
111 proto_tree_set_boolean(field_info *fi, guint32 value);
112 static void
113 proto_tree_set_float(field_info *fi, float value);
114 static void
115 proto_tree_set_double(field_info *fi, double value);
116 static void
117 proto_tree_set_uint(field_info *fi, guint32 value);
118 static void
119 proto_tree_set_int(field_info *fi, gint32 value);
120 static void
121 proto_tree_set_uint64(field_info *fi, guint64 value);
122 static void
123 proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start, gboolean little_endian);
124
125 static int proto_register_field_init(header_field_info *hfinfo, int parent);
126
127 /* Comparision function for tree insertion. A wrapper around strcmp() */
128 static int g_strcmp(gconstpointer a, gconstpointer b);
129
130 /* special-case header field used within proto.c */
131 int hf_text_only = -1;
132
133 /* Structure for information about a protocol */
134 struct _protocol {
135         char    *name;          /* long description */
136         char    *short_name;    /* short description */
137         char    *filter_name;   /* name of this protocol in filters */
138         int     proto_id;       /* field ID for this protocol */
139         GList   *fields;        /* fields for this protocol */
140         GList   *last_field;    /* pointer to end of list of fields */
141         gboolean is_enabled;    /* TRUE if protocol is enabled */
142         gboolean can_toggle;    /* TRUE if is_enabled can be changed */
143 };
144
145 /* List of all protocols */
146 static GList *protocols = NULL;
147
148 #define INITIAL_NUM_PROTOCOL_HFINFO     200
149
150
151 /* Contains information about protocols and header fields. Used when
152  * dissectors register their data */
153 static GMemChunk *gmc_hfinfo = NULL;
154
155 /* Contains information about a field when a dissector calls
156  * proto_tree_add_item.  */
157 SLAB_ITEM_TYPE_DEFINE(field_info)
158 static SLAB_FREE_LIST_DEFINE(field_info)
159 static field_info *field_info_tmp=NULL;
160 #define FIELD_INFO_NEW(fi)                                      \
161         SLAB_ALLOC(fi, field_info)
162 #define FIELD_INFO_FREE(fi)                                     \
163         SLAB_FREE(fi, field_info)
164
165
166
167 /* Contains the space for proto_nodes. */
168 SLAB_ITEM_TYPE_DEFINE(proto_node)
169 static SLAB_FREE_LIST_DEFINE(proto_node)
170 #define PROTO_NODE_NEW(node)                            \
171         SLAB_ALLOC(node, proto_node)                    \
172         node->first_child = NULL;                       \
173         node->last_child = NULL;                        \
174         node->next = NULL;
175
176 #define PROTO_NODE_FREE(node)                           \
177         SLAB_FREE(node, proto_node)
178
179
180
181 /* String space for protocol and field items for the GUI */
182 SLAB_ITEM_TYPE_DEFINE(item_label_t)
183 static SLAB_FREE_LIST_DEFINE(item_label_t)
184 #define ITEM_LABEL_NEW(il)                              \
185         SLAB_ALLOC(il, item_label_t)
186 #define ITEM_LABEL_FREE(il)                             \
187         SLAB_FREE(il, item_label_t)
188
189
190
191 /* List which stores protocols and fields that have been registered */
192 typedef struct _gpa_hfinfo_t {
193         guint32 len;
194         guint32 allocated_len;
195         header_field_info **hfi;
196 } gpa_hfinfo_t;
197 gpa_hfinfo_t gpa_hfinfo;
198
199 /* Balanced tree of abbreviations and IDs */
200 static GTree *gpa_name_tree = NULL;
201
202 /* Points to the first element of an array of Booleans, indexed by
203    a subtree item type; that array element is TRUE if subtrees of
204    an item of that type are to be expanded. */
205 gboolean        *tree_is_expanded;
206
207 /* Number of elements in that array. */
208 int             num_tree_types;
209
210 /* Name hashtables for fast detection of duplicate names */
211 static GHashTable* proto_names = NULL;
212 static GHashTable* proto_short_names = NULL;
213 static GHashTable* proto_filter_names = NULL;
214
215 static gint
216 proto_compare_name(gconstpointer p1_arg, gconstpointer p2_arg)
217 {
218         const protocol_t *p1 = p1_arg;
219         const protocol_t *p2 = p2_arg;
220
221         return g_strcasecmp(p1->short_name, p2->short_name);
222 }
223
224
225 /* initialize data structures and register protocols and fields */
226 void
227 proto_init(const char *plugin_dir
228 #ifndef HAVE_PLUGINS
229                                  _U_
230 #endif
231            ,
232            void (register_all_protocols)(void),
233            void (register_all_protocol_handoffs)(void))
234 {
235         static hf_register_info hf[] = {
236                 { &hf_text_only,
237                 { "",   "", FT_NONE, BASE_NONE, NULL, 0x0,
238                         NULL, HFILL }},
239         };
240
241
242     proto_names = g_hash_table_new(g_int_hash, g_int_equal);
243     proto_short_names = g_hash_table_new(g_int_hash, g_int_equal);
244     proto_filter_names = g_hash_table_new(g_int_hash, g_int_equal);
245
246         proto_cleanup();
247
248         gmc_hfinfo = g_mem_chunk_new("gmc_hfinfo",
249                 sizeof(header_field_info),
250         INITIAL_NUM_PROTOCOL_HFINFO * sizeof(header_field_info),
251         G_ALLOC_ONLY);
252
253         gpa_hfinfo.len=0;
254         gpa_hfinfo.allocated_len=0;
255         gpa_hfinfo.hfi=NULL;
256         gpa_name_tree = g_tree_new(g_strcmp);
257
258         /* Initialize the ftype subsystem */
259         ftypes_initialize();
260
261         /* Register one special-case FT_TEXT_ONLY field for use when
262            converting ethereal to new-style proto_tree. These fields
263            are merely strings on the GUI tree; they are not filterable */
264         proto_register_field_array(-1, hf, array_length(hf));
265
266         /* Have each built-in dissector register its protocols, fields,
267            dissector tables, and dissectors to be called through a
268            handle, and do whatever one-time initialization it needs to
269            do. */
270         register_all_protocols();
271
272 #ifdef HAVE_PLUGINS
273         /* Now scan for plugins and load all the ones we find, calling
274            their register routines to do the stuff described above. */
275         init_plugins(plugin_dir);
276 #endif
277
278         /* Now call the "handoff registration" routines of all built-in
279            dissectors; those routines register the dissector in other
280            dissectors' handoff tables, and fetch any dissector handles
281            they need. */
282         register_all_protocol_handoffs();
283
284 #ifdef HAVE_PLUGINS
285         /* Now do the same with plugins. */
286         register_all_plugin_handoffs();
287 #endif
288
289     /* sort the protocols by protocol name */
290     protocols = g_list_sort(protocols, proto_compare_name);
291
292         /* We've assigned all the subtree type values; allocate the array
293            for them, and zero it out. */
294         tree_is_expanded = g_malloc(num_tree_types*sizeof (gint *));
295         memset(tree_is_expanded, 0, num_tree_types*sizeof (gint *));
296 }
297
298 /* String comparison func for dfilter_token GTree */
299 static int
300 g_strcmp(gconstpointer a, gconstpointer b)
301 {
302         return strcmp((const char*)a, (const char*)b);
303 }
304
305 void
306 proto_cleanup(void)
307 {
308         /* Free the abbrev/ID GTree */
309         if (gpa_name_tree) {
310                 g_tree_destroy(gpa_name_tree);
311                 gpa_name_tree = NULL;
312         }
313
314         if (gmc_hfinfo)
315                 g_mem_chunk_destroy(gmc_hfinfo);
316
317         if(gpa_hfinfo.allocated_len){
318                 gpa_hfinfo.len=0;
319                 gpa_hfinfo.allocated_len=0;
320                 g_free(gpa_hfinfo.hfi);
321                 gpa_hfinfo.hfi=NULL;
322         }
323         if (tree_is_expanded != NULL)
324                 g_free(tree_is_expanded);
325
326 }
327
328 typedef gboolean (*proto_tree_traverse_func)(proto_node *, gpointer);
329
330 static gboolean
331 proto_tree_traverse_pre_order(proto_tree *tree, proto_tree_traverse_func func,
332     gpointer data)
333 {
334         proto_node *pnode = tree;
335         proto_node *child;
336         proto_node *current;
337
338         if (func(pnode, data))
339                 return TRUE;
340
341         child = pnode->first_child;
342         while (child != NULL) {
343                 /*
344                  * The routine we call might modify the child, e.g. by
345                  * freeing it, so we get the child's successor before
346                  * calling that routine.
347                  */
348                 current = child;
349                 child = current->next;
350                 if (proto_tree_traverse_pre_order((proto_tree *)current, func,
351                     data))
352                         return TRUE;
353         }
354
355         return FALSE;
356 }
357
358 static gboolean
359 proto_tree_traverse_in_order(proto_tree *tree, proto_tree_traverse_func func,
360     gpointer data)
361 {
362         proto_node *pnode = tree;
363         proto_node *child;
364         proto_node *current;
365
366         child = pnode->first_child;
367         if (child != NULL) {
368                 /*
369                  * The routine we call might modify the child, e.g. by
370                  * freeing it, so we get the child's successor before
371                  * calling that routine.
372                  */
373                 current = child;
374                 child = current->next;
375
376                 if (proto_tree_traverse_in_order((proto_tree *)current, func,
377                     data))
378                         return TRUE;
379
380                 if (func(pnode, data))
381                         return TRUE;
382
383                 while (child != NULL) {
384                         /*
385                          * The routine we call might modify the child, e.g. by
386                          * freeing it, so we get the child's successor before
387                          * calling that routine.
388                          */
389                         current = child;
390                         child = current->next;
391                         if (proto_tree_traverse_in_order((proto_tree *)current,
392                             func, data))
393                                 return TRUE;
394                 }
395         } else {
396                 if (func(pnode, data))
397                         return TRUE;
398         }
399
400         return FALSE;
401 }
402
403 void
404 proto_tree_children_foreach(proto_tree *tree, proto_tree_foreach_func func,
405     gpointer data)
406 {
407         proto_node *node = tree;
408         proto_node *current;
409
410         node = node->first_child;
411         while (node != NULL) {
412                 current = node;
413                 node = current->next;
414                 func((proto_tree *)current, data);
415         }
416 }
417
418 /* frees the resources that the dissection a proto_tree uses */
419 void
420 proto_tree_free(proto_tree *tree)
421 {
422         proto_tree_traverse_in_order(tree, proto_tree_free_node, NULL);
423 }
424
425 static void
426 free_GPtrArray_value(gpointer key _U_, gpointer value, gpointer user_data _U_)
427 {
428         GPtrArray   *ptrs = value;
429
430         g_ptr_array_free(ptrs, TRUE);
431 }
432
433 static void
434 free_node_tree_data(tree_data_t *tree_data)
435 {
436         /* Free all the GPtrArray's in the interesting_hfids hash. */
437         g_hash_table_foreach(tree_data->interesting_hfids,
438             free_GPtrArray_value, NULL);
439
440         /* And then destroy the hash. */
441         g_hash_table_destroy(tree_data->interesting_hfids);
442
443         /* And finally the tree_data_t itself. */
444         g_free(tree_data);
445 }
446
447 #define FREE_NODE_FIELD_INFO(finfo)     \
448         if(finfo->rep){                 \
449                 ITEM_LABEL_FREE(finfo->rep);    \
450         }                               \
451         FVALUE_CLEANUP(&finfo->value);  \
452         FIELD_INFO_FREE(finfo);
453
454 static gboolean
455 proto_tree_free_node(proto_node *node, gpointer data _U_)
456 {
457         field_info *finfo = PITEM_FINFO(node);
458
459         if (finfo == NULL) {
460                 /* This is the root node. Destroy the per-tree data.
461                  * There is no field_info to destroy. */
462                 free_node_tree_data(PTREE_DATA(node));
463         }
464         else {
465                 /* This is a child node. Don't free the per-tree data, but
466                  * do free the field_info data. */
467                 FREE_NODE_FIELD_INFO(finfo);
468         }
469
470         /* Free the proto_node. */
471         PROTO_NODE_FREE(node);
472
473         return FALSE; /* FALSE = do not end traversal of protocol tree */
474 }
475
476 /* Is the parsing being done for a visible proto_tree or an invisible one?
477  * By setting this correctly, the proto_tree creation is sped up by not
478  * having to call vsnprintf and copy strings around.
479  */
480 void
481 proto_tree_set_visible(proto_tree *tree, gboolean visible)
482 {
483         PTREE_DATA(tree)->visible = visible;
484 }
485
486 #define PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo) \
487         DISSECTOR_ASSERT((guint)hfindex < gpa_hfinfo.len); \
488         hfinfo=gpa_hfinfo.hfi[hfindex];         
489
490 /* Finds a record in the hf_info_records array by id. */
491 header_field_info*
492 proto_registrar_get_nth(guint hfindex)
493 {
494         register header_field_info      *hfinfo;
495
496         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
497         return hfinfo;
498 }
499
500 /* Finds a record in the hf_info_records array by name.
501  */
502 header_field_info*
503 proto_registrar_get_byname(const char *field_name)
504 {
505         DISSECTOR_ASSERT(field_name != NULL);
506         return g_tree_lookup(gpa_name_tree, (gpointer)field_name);
507 }
508
509 /* Add a text-only node, leaving it to our caller to fill the text in */
510 static proto_item *
511 proto_tree_add_text_node(proto_tree *tree, tvbuff_t *tvb, gint start, gint length)
512 {
513         proto_item      *pi;
514
515         pi = proto_tree_add_pi(tree, hf_text_only, tvb, start, &length, NULL);
516         if (pi == NULL)
517                 return(NULL);
518
519         return pi;
520 }
521
522 /* Add a text-only node to the proto_tree */
523 proto_item *
524 proto_tree_add_text(proto_tree *tree, tvbuff_t *tvb, gint start, gint length,
525         const char *format, ...)
526 {
527         proto_item      *pi;
528         va_list         ap;
529
530         pi = proto_tree_add_text_node(tree, tvb, start, length);
531         if (pi == NULL)
532                 return(NULL);
533
534         va_start(ap, format);
535         proto_tree_set_representation(pi, format, ap);
536         va_end(ap);
537
538         return pi;
539 }
540
541 /* Add a text-only node to the proto_tree (va_list version) */
542 proto_item *
543 proto_tree_add_text_valist(proto_tree *tree, tvbuff_t *tvb, gint start,
544         gint length, const char *format, va_list ap)
545 {
546         proto_item      *pi;
547
548         pi = proto_tree_add_text_node(tree, tvb, start, length);
549         if (pi == NULL)
550                 return(NULL);
551
552         proto_tree_set_representation(pi, format, ap);
553
554         return pi;
555 }
556
557 /* Add a text-only node for debugging purposes. The caller doesn't need
558  * to worry about tvbuff, start, or length. Debug message gets sent to
559  * STDOUT, too */
560 proto_item *
561 proto_tree_add_debug_text(proto_tree *tree, const char *format, ...)
562 {
563         proto_item      *pi;
564         va_list         ap;
565
566         pi = proto_tree_add_text_node(tree, NULL, 0, 0);
567         if (pi == NULL)
568                 return(NULL);
569
570         va_start(ap, format);
571         proto_tree_set_representation(pi, format, ap);
572         vprintf(format, ap);
573         va_end(ap);
574         printf("\n");
575
576         return pi;
577 }
578
579
580 static guint32
581 get_uint_value(tvbuff_t *tvb, gint offset, gint length, gboolean little_endian)
582 {
583         guint32 value;
584
585         switch (length) {
586
587         case 1:
588                 value = tvb_get_guint8(tvb, offset);
589                 break;
590
591         case 2:
592                 value = little_endian ? tvb_get_letohs(tvb, offset)
593                                       : tvb_get_ntohs(tvb, offset);
594                 break;
595
596         case 3:
597                 value = little_endian ? tvb_get_letoh24(tvb, offset)
598                                       : tvb_get_ntoh24(tvb, offset);
599                 break;
600
601         case 4:
602                 value = little_endian ? tvb_get_letohl(tvb, offset)
603                                       : tvb_get_ntohl(tvb, offset);
604                 break;
605
606         default:
607                 DISSECTOR_ASSERT_NOT_REACHED();
608                 value = 0;
609                 break;
610         }
611         return value;
612 }
613
614 static gint32
615 get_int_value(tvbuff_t *tvb, gint offset, gint length, gboolean little_endian)
616 {
617         gint32 value;
618
619         switch (length) {
620
621         case 1:
622                 value = (gint8)tvb_get_guint8(tvb, offset);
623                 break;
624
625         case 2:
626                 value = (gint16) (little_endian ? tvb_get_letohs(tvb, offset)
627                                                 : tvb_get_ntohs(tvb, offset));
628                 break;
629
630         case 3:
631                 value = little_endian ? tvb_get_letoh24(tvb, offset)
632                                       : tvb_get_ntoh24(tvb, offset);
633                 if (value & 0x00800000) {
634                         /* Sign bit is set; sign-extend it. */
635                         value |= 0xFF000000;
636                 }
637                 break;
638
639         case 4:
640                 value = little_endian ? tvb_get_letohl(tvb, offset)
641                                       : tvb_get_ntohl(tvb, offset);
642                 break;
643
644         default:
645                 DISSECTOR_ASSERT_NOT_REACHED();
646                 value = 0;
647                 break;
648         }
649         return value;
650 }
651
652 /* Add an item to a proto_tree, using the text label registered to that item;
653    the item is extracted from the tvbuff handed to it. */
654 proto_item *
655 proto_tree_add_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
656     gint start, gint length, gboolean little_endian)
657 {
658         field_info      *new_fi;
659         proto_item      *pi;
660         guint32         value, n;
661         float           floatval;
662         double          doubleval;
663         char            *string;
664         GHashTable      *hash;
665         GPtrArray       *ptrs;
666
667         if (!tree)
668                 return(NULL);
669
670         new_fi = alloc_field_info(tree, hfindex, tvb, start, &length);
671
672         if (new_fi == NULL)
673                 return(NULL);
674
675         /* there is a possibility here that we might raise an exception
676          * and thus would lose track of the field_info.
677          * store it in a temp so that if we come here again we can reclaim
678          * the field_info without leaking memory.
679          */
680         /* XXX this only keeps track of one field_info struct,
681            if we ever go multithreaded for calls to this function
682            we have to change this code to use per thread variable.
683         */
684         if(field_info_tmp){
685                 /* oops, last one we got must have been lost due
686                  * to an exception.
687                  * good thing we saved it, now we can reverse the
688                  * memory leak and reclaim it.
689                  */
690                 SLAB_FREE(field_info_tmp, field_info);
691         }
692         /* we might throw an exception, keep track of this one
693          * across the "dangerous" section below.
694         */
695         field_info_tmp=new_fi;
696
697         switch(new_fi->hfinfo->type) {
698                 case FT_NONE:
699                         /* no value to set for FT_NONE */
700                         break;
701
702                 case FT_PROTOCOL:
703                         proto_tree_set_protocol_tvb(new_fi, tvb);
704                         break;
705
706                 case FT_BYTES:
707                         proto_tree_set_bytes_tvb(new_fi, tvb, start, length);
708                         break;
709
710                 case FT_UINT_BYTES:
711                         n = get_uint_value(tvb, start, length, little_endian);
712                         proto_tree_set_bytes_tvb(new_fi, tvb, start + length, n);
713
714                         /* Instead of calling proto_item_set_len(), since we don't yet
715                          * have a proto_item, we set the field_info's length ourselves. */
716                         new_fi->length = n + length;
717                         break;
718
719                 case FT_BOOLEAN:
720                         proto_tree_set_boolean(new_fi,
721                             get_uint_value(tvb, start, length, little_endian));
722                         break;
723
724                 /* XXX - make these just FT_UINT? */
725                 case FT_UINT8:
726                 case FT_UINT16:
727                 case FT_UINT24:
728                 case FT_UINT32:
729                         proto_tree_set_uint(new_fi,
730                             get_uint_value(tvb, start, length, little_endian));
731                         break;
732
733                 case FT_INT64:
734                 case FT_UINT64:
735                         DISSECTOR_ASSERT(length == 8);
736                         proto_tree_set_uint64_tvb(new_fi, tvb, start, little_endian);
737                         break;
738
739                 /* XXX - make these just FT_INT? */
740                 case FT_INT8:
741                 case FT_INT16:
742                 case FT_INT24:
743                 case FT_INT32:
744                         proto_tree_set_int(new_fi,
745                             get_int_value(tvb, start, length, little_endian));
746                         break;
747
748                 case FT_IPv4:
749                         DISSECTOR_ASSERT(length == 4);
750                         tvb_memcpy(tvb, (guint8 *)&value, start, 4);
751                         proto_tree_set_ipv4(new_fi, little_endian ? GUINT32_SWAP_LE_BE(value) : value);
752                         break;
753
754                 case FT_IPXNET:
755                         DISSECTOR_ASSERT(length == 4);
756                         proto_tree_set_ipxnet(new_fi,
757                             get_uint_value(tvb, start, 4, FALSE));
758                         break;
759
760                 case FT_IPv6:
761                         DISSECTOR_ASSERT(length == 16);
762                         proto_tree_set_ipv6_tvb(new_fi, tvb, start);
763                         break;
764
765                 case FT_ETHER:
766                         DISSECTOR_ASSERT(length == 6);
767                         proto_tree_set_ether_tvb(new_fi, tvb, start);
768                         break;
769
770                 case FT_FLOAT:
771                         DISSECTOR_ASSERT(length == 4);
772                         if (little_endian)
773                                 floatval = tvb_get_letohieee_float(tvb, start);
774                         else
775                                 floatval = tvb_get_ntohieee_float(tvb, start);
776                         proto_tree_set_float(new_fi, floatval);
777                         break;
778
779                 case FT_DOUBLE:
780                         DISSECTOR_ASSERT(length == 8);
781                         if (little_endian)
782                                 doubleval = tvb_get_letohieee_double(tvb, start);
783                         else
784                                 doubleval = tvb_get_ntohieee_double(tvb, start);
785                         proto_tree_set_double(new_fi, doubleval);
786                         break;
787
788                 case FT_STRING:
789                         /* This g_strdup'ed memory is freed in proto_tree_free_node() */
790                         proto_tree_set_string_tvb(new_fi, tvb, start, length);
791                         break;
792
793                 case FT_STRINGZ:
794                         if (length != 0) {  /* XXX - Should we throw an exception instead? */
795                                 /* Instead of calling proto_item_set_len(),
796                                  * since we don't yet have a proto_item, we
797                                  * set the field_info's length ourselves.
798                                  *
799                                  * XXX - our caller can't use that length to
800                                  * advance an offset unless they arrange that
801                                  * there always be a protocol tree into which
802                                  * we're putting this item.
803                                  */
804                                 if (length == -1) {
805                                         /* This can throw an exception */
806                                         length = tvb_strsize(tvb, start);
807
808                                         /* This g_malloc'ed memory is freed
809                                            in proto_tree_free_node() */
810                                         string = g_malloc(length);
811
812                                         tvb_memcpy(tvb, string, start, length);
813                                         new_fi->length = length;
814                                 }
815                                 else {
816                                         /* In this case, length signifies
817                                          * the length of the string.
818                                          *
819                                          * This could either be a null-padded
820                                          * string, which doesn't necessarily
821                                          * have a '\0' at the end, or a
822                                          * null-terminated string, with a
823                                          * trailing '\0'.  (Yes, there are
824                                          * cases where you have a string
825                                          * that's both counted and null-
826                                          * terminated.)
827                                          *
828                                          * In the first case, we must
829                                          * allocate a buffer of length
830                                          * "length+1", to make room for
831                                          * a trailing '\0'.
832                                          *
833                                          * In the second case, we don't
834                                          * assume that there is a trailing
835                                          * '\0' there, as the packet might
836                                          * be malformed.  (XXX - should we
837                                          * throw an exception if there's no
838                                          * trailing '\0'?)  Therefore, we
839                                          * allocate a buffer of length
840                                          * "length+1", and put in a trailing
841                                          * '\0', just to be safe.
842                                          *
843                                          * (XXX - this would change if
844                                          * we made string values counted
845                                          * rather than null-terminated.)
846                                          */
847
848                                         /* This g_malloc'ed memory is freed
849                                          * in proto_tree_free_node() */
850                                         string = tvb_get_string(tvb, start,
851                                             length);
852                                         new_fi->length = length;
853                                 }
854                                 proto_tree_set_string(new_fi, string, TRUE);
855                         }
856                         break;
857
858                 case FT_UINT_STRING:
859                         /* This g_strdup'ed memory is freed in proto_tree_free_node() */
860                         n = get_uint_value(tvb, start, length, little_endian);
861                         proto_tree_set_string_tvb(new_fi, tvb, start + length, n);
862
863                         /* Instead of calling proto_item_set_len(), since we
864                          * don't yet have a proto_item, we set the
865                          * field_info's length ourselves.
866                          *
867                          * XXX - our caller can't use that length to
868                          * advance an offset unless they arrange that
869                          * there always be a protocol tree into which
870                          * we're putting this item.
871                          */
872                         new_fi->length = n + length;
873                         break;
874
875                 default:
876                         g_error("new_fi->hfinfo->type %d (%s) not handled\n",
877                                         new_fi->hfinfo->type,
878                                         ftype_name(new_fi->hfinfo->type));
879                         DISSECTOR_ASSERT_NOT_REACHED();
880                         break;
881         }
882
883         /* Don't add new node to proto_tree until now so that any exceptions
884          * raised by a tvbuff access method doesn't leave junk in the proto_tree. */
885         pi = proto_tree_add_node(tree, new_fi);
886
887         /* we did not raise an exception so we dont have to remember this
888          * field_info struct any more.
889          */
890         field_info_tmp=NULL;
891
892         /* If the proto_tree wants to keep a record of this finfo
893          * for quick lookup, then record it. */
894         hash = PTREE_DATA(tree)->interesting_hfids;
895         ptrs = g_hash_table_lookup(hash, GINT_TO_POINTER(hfindex));
896         if (ptrs) {
897                 g_ptr_array_add(ptrs, new_fi);
898         }
899
900         return pi;
901 }
902
903 proto_item *
904 proto_tree_add_item_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb,
905     gint start, gint length, gboolean little_endian)
906 {
907         proto_item      *pi;
908
909         pi = proto_tree_add_item(tree, hfindex, tvb, start, length, little_endian);
910         if (pi == NULL)
911                 return(NULL);
912
913         PROTO_ITEM_SET_HIDDEN(pi);
914
915         return pi;
916 }
917
918
919 /* Add a FT_NONE to a proto_tree */
920 proto_item *
921 proto_tree_add_none_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
922                 gint length, const char *format, ...)
923 {
924         proto_item              *pi;
925         va_list                 ap;
926         header_field_info       *hfinfo;
927
928         if (!tree)
929                 return (NULL);
930
931         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
932         DISSECTOR_ASSERT(hfinfo->type == FT_NONE);
933
934         pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, NULL);
935
936         va_start(ap, format);
937         proto_tree_set_representation(pi, format, ap);
938         va_end(ap);
939
940         /* no value to set for FT_NONE */
941         return pi;
942 }
943
944
945 static void
946 proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb)
947 {
948         fvalue_set(&fi->value, tvb, TRUE);
949 }
950
951 /* Add a FT_PROTOCOL to a proto_tree */
952 proto_item *
953 proto_tree_add_protocol_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
954                 gint length, const char *format, ...)
955 {
956         proto_item              *pi;
957         va_list                 ap;
958         header_field_info       *hfinfo;
959         field_info              *new_fi;
960
961         if (!tree)
962                 return (NULL);
963
964         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
965         DISSECTOR_ASSERT(hfinfo->type == FT_PROTOCOL);
966
967         pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
968
969         va_start(ap, format);
970         proto_tree_set_representation(pi, format, ap);
971         va_end(ap);
972
973         if (start == 0) {
974                 proto_tree_set_protocol_tvb(new_fi, tvb);
975         }
976         else {
977                 proto_tree_set_protocol_tvb(new_fi, NULL);
978         }
979         return pi;
980 }
981
982
983 /* Add a FT_BYTES to a proto_tree */
984 proto_item *
985 proto_tree_add_bytes(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
986                 gint length, const guint8 *start_ptr)
987 {
988         proto_item              *pi;
989         field_info              *new_fi;
990         header_field_info       *hfinfo;
991
992         if (!tree)
993                 return (NULL);
994
995         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
996         DISSECTOR_ASSERT(hfinfo->type == FT_BYTES);
997
998         pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
999         proto_tree_set_bytes(new_fi, start_ptr, length);
1000
1001         return pi;
1002 }
1003
1004 proto_item *
1005 proto_tree_add_bytes_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1006                 gint length, const guint8 *start_ptr)
1007 {
1008         proto_item              *pi;
1009
1010         pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length, start_ptr);
1011         if (pi == NULL)
1012                 return (NULL);
1013
1014         PROTO_ITEM_SET_HIDDEN(pi);
1015
1016         return pi;
1017 }
1018
1019 proto_item *
1020 proto_tree_add_bytes_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1021                 gint length, const guint8 *start_ptr, const char *format, ...)
1022 {
1023         proto_item              *pi;
1024         va_list                 ap;
1025
1026         pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length, start_ptr);
1027         if (pi == NULL)
1028                 return (NULL);
1029
1030         va_start(ap, format);
1031         proto_tree_set_representation(pi, format, ap);
1032         va_end(ap);
1033
1034         return pi;
1035 }
1036
1037 static void
1038 proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length)
1039 {
1040         GByteArray              *bytes;
1041
1042         bytes = g_byte_array_new();
1043         if (length > 0) {
1044                 g_byte_array_append(bytes, start_ptr, length);
1045         }
1046         fvalue_set(&fi->value, bytes, TRUE);
1047 }
1048
1049
1050 static void
1051 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length)
1052 {
1053         proto_tree_set_bytes(fi, tvb_get_ptr(tvb, offset, length), length);
1054 }
1055
1056 /* Add a FT_*TIME to a proto_tree */
1057 proto_item *
1058 proto_tree_add_time(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1059                 nstime_t *value_ptr)
1060 {
1061         proto_item              *pi;
1062         field_info              *new_fi;
1063         header_field_info       *hfinfo;
1064
1065         if (!tree)
1066                 return (NULL);
1067
1068         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1069         DISSECTOR_ASSERT(hfinfo->type == FT_ABSOLUTE_TIME ||
1070                                 hfinfo->type == FT_RELATIVE_TIME);
1071
1072         pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1073         proto_tree_set_time(new_fi, value_ptr);
1074
1075         return pi;
1076 }
1077
1078 proto_item *
1079 proto_tree_add_time_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1080                 nstime_t *value_ptr)
1081 {
1082         proto_item              *pi;
1083
1084         pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
1085         if (pi == NULL)
1086                 return (NULL);
1087
1088         PROTO_ITEM_SET_HIDDEN(pi);
1089
1090         return pi;
1091 }
1092
1093 proto_item *
1094 proto_tree_add_time_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1095                 nstime_t *value_ptr, const char *format, ...)
1096 {
1097         proto_item              *pi;
1098         va_list                 ap;
1099
1100         pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
1101         if (pi == NULL)
1102                 return (NULL);
1103
1104         va_start(ap, format);
1105         proto_tree_set_representation(pi, format, ap);
1106         va_end(ap);
1107
1108         return pi;
1109 }
1110
1111 /* Set the FT_*TIME value */
1112 static void
1113 proto_tree_set_time(field_info *fi, nstime_t *value_ptr)
1114 {
1115         fvalue_set(&fi->value, value_ptr, FALSE);
1116 }
1117
1118 /* Add a FT_IPXNET to a proto_tree */
1119 proto_item *
1120 proto_tree_add_ipxnet(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1121                 guint32 value)
1122 {
1123         proto_item              *pi;
1124         field_info              *new_fi;
1125         header_field_info       *hfinfo;
1126
1127         if (!tree)
1128                 return (NULL);
1129
1130         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1131         DISSECTOR_ASSERT(hfinfo->type == FT_IPXNET);
1132
1133         pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1134         proto_tree_set_ipxnet(new_fi, value);
1135
1136         return pi;
1137 }
1138
1139 proto_item *
1140 proto_tree_add_ipxnet_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1141                 guint32 value)
1142 {
1143         proto_item              *pi;
1144
1145         pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
1146         if (pi == NULL)
1147                 return (NULL);
1148
1149         PROTO_ITEM_SET_HIDDEN(pi);
1150
1151         return pi;
1152 }
1153
1154 proto_item *
1155 proto_tree_add_ipxnet_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1156                 guint32 value, const char *format, ...)
1157 {
1158         proto_item              *pi;
1159         va_list                 ap;
1160
1161         pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
1162         if (pi == NULL)
1163                 return (NULL);
1164
1165         va_start(ap, format);
1166         proto_tree_set_representation(pi, format, ap);
1167         va_end(ap);
1168
1169         return pi;
1170 }
1171
1172 /* Set the FT_IPXNET value */
1173 static void
1174 proto_tree_set_ipxnet(field_info *fi, guint32 value)
1175 {
1176         fvalue_set_integer(&fi->value, value);
1177 }
1178
1179 /* Add a FT_IPv4 to a proto_tree */
1180 proto_item *
1181 proto_tree_add_ipv4(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1182                 guint32 value)
1183 {
1184         proto_item              *pi;
1185         field_info              *new_fi;
1186         header_field_info       *hfinfo;
1187
1188         if (!tree)
1189                 return (NULL);
1190
1191         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1192         DISSECTOR_ASSERT(hfinfo->type == FT_IPv4);
1193
1194         pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1195         proto_tree_set_ipv4(new_fi, value);
1196
1197         return pi;
1198 }
1199
1200 proto_item *
1201 proto_tree_add_ipv4_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1202                 guint32 value)
1203 {
1204         proto_item              *pi;
1205
1206         pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
1207         if (pi == NULL)
1208                 return (NULL);
1209
1210         PROTO_ITEM_SET_HIDDEN(pi);
1211
1212         return pi;
1213 }
1214
1215 proto_item *
1216 proto_tree_add_ipv4_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1217                 guint32 value, const char *format, ...)
1218 {
1219         proto_item              *pi;
1220         va_list                 ap;
1221
1222         pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
1223         if (pi == NULL)
1224                 return (NULL);
1225
1226         va_start(ap, format);
1227         proto_tree_set_representation(pi, format, ap);
1228         va_end(ap);
1229
1230         return pi;
1231 }
1232
1233 /* Set the FT_IPv4 value */
1234 static void
1235 proto_tree_set_ipv4(field_info *fi, guint32 value)
1236 {
1237         fvalue_set_integer(&fi->value, value);
1238 }
1239
1240 /* Add a FT_IPv6 to a proto_tree */
1241 proto_item *
1242 proto_tree_add_ipv6(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1243                 const guint8* value_ptr)
1244 {
1245         proto_item              *pi;
1246         field_info              *new_fi;
1247         header_field_info       *hfinfo;
1248
1249         if (!tree)
1250                 return (NULL);
1251
1252         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1253         DISSECTOR_ASSERT(hfinfo->type == FT_IPv6);
1254
1255         pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1256         proto_tree_set_ipv6(new_fi, value_ptr);
1257
1258         return pi;
1259 }
1260
1261 proto_item *
1262 proto_tree_add_ipv6_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1263                 const guint8* value_ptr)
1264 {
1265         proto_item              *pi;
1266
1267         pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
1268         if (pi == NULL)
1269                 return (NULL);
1270
1271         PROTO_ITEM_SET_HIDDEN(pi);
1272
1273         return pi;
1274 }
1275
1276 proto_item *
1277 proto_tree_add_ipv6_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1278                 const guint8* value_ptr, const char *format, ...)
1279 {
1280         proto_item              *pi;
1281         va_list                 ap;
1282
1283         pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
1284         if (pi == NULL)
1285                 return (NULL);
1286
1287         va_start(ap, format);
1288         proto_tree_set_representation(pi, format, ap);
1289         va_end(ap);
1290
1291         return pi;
1292 }
1293
1294 /* Set the FT_IPv6 value */
1295 static void
1296 proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr)
1297 {
1298         fvalue_set(&fi->value, (gpointer) value_ptr, FALSE);
1299 }
1300
1301 static void
1302 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start)
1303 {
1304         proto_tree_set_ipv6(fi, tvb_get_ptr(tvb, start, 16));
1305 }
1306
1307 static void
1308 proto_tree_set_uint64(field_info *fi, guint64 value)
1309 {
1310         fvalue_set_integer64(&fi->value, value);
1311 }
1312
1313 static void
1314 proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start, gboolean little_endian)
1315 {
1316         guint64 value;
1317
1318         value = little_endian ? tvb_get_letoh64(tvb, start)
1319                               : tvb_get_ntoh64(tvb, start);
1320
1321         proto_tree_set_uint64(fi, value);
1322 }
1323
1324 /* Add a FT_STRING or FT_STRINGZ to a proto_tree. Creates own copy of string,
1325  * and frees it when the proto_tree is destroyed. */
1326 proto_item *
1327 proto_tree_add_string(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1328                 gint length, const char* value)
1329 {
1330         proto_item              *pi;
1331         field_info              *new_fi;
1332         header_field_info       *hfinfo;
1333
1334         if (!tree)
1335                 return (NULL);
1336
1337         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1338         DISSECTOR_ASSERT(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ);
1339
1340         pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1341         DISSECTOR_ASSERT(length >= 0);
1342         proto_tree_set_string(new_fi, value, FALSE);
1343
1344         return pi;
1345 }
1346
1347 proto_item *
1348 proto_tree_add_string_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1349                 gint length, const char* value)
1350 {
1351         proto_item              *pi;
1352
1353         pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
1354         if (pi == NULL)
1355                 return (NULL);
1356
1357         PROTO_ITEM_SET_HIDDEN(pi);
1358
1359         return pi;
1360 }
1361
1362 proto_item *
1363 proto_tree_add_string_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1364                 gint length, const char* value, const char *format, ...)
1365 {
1366         proto_item              *pi;
1367         va_list                 ap;
1368
1369         pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
1370         if (pi == NULL)
1371                 return (NULL);
1372
1373         va_start(ap, format);
1374         proto_tree_set_representation(pi, format, ap);
1375         va_end(ap);
1376
1377         return pi;
1378 }
1379
1380 /* Appends string data to a FT_STRING or FT_STRINGZ, allowing progressive
1381  * field info update instead of only updating the representation as does
1382  * proto_item_append_text()
1383  */
1384 void
1385 proto_item_append_string(proto_item *pi, const char *str)
1386 {
1387         field_info *fi;
1388         header_field_info *hfinfo;
1389         gchar *old_str, *new_str;
1390
1391         if (!pi)
1392                 return;
1393         if (!*str)
1394                 return;
1395
1396         fi = PITEM_FINFO(pi);
1397         hfinfo = fi->hfinfo;
1398         DISSECTOR_ASSERT(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ);
1399         old_str = fvalue_get(&fi->value);
1400         new_str = g_malloc(strlen(old_str) + strlen(str) + 1);
1401         sprintf(new_str, "%s%s", old_str, str);
1402         fvalue_set(&fi->value, new_str, TRUE);
1403 }
1404
1405 /* Set the FT_STRING value */
1406 static void
1407 proto_tree_set_string(field_info *fi, const char* value,
1408                 gboolean already_allocated)
1409 {
1410         fvalue_set(&fi->value, (gpointer) value, already_allocated);
1411 }
1412
1413 static void
1414 proto_tree_set_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
1415 {
1416         gchar   *string;
1417
1418         if (length == -1) {
1419                 length = tvb_ensure_length_remaining(tvb, start);
1420         }
1421
1422         /* This memory is freed in proto_tree_free_node() */
1423         string = tvb_get_string(tvb, start, length);
1424         proto_tree_set_string(fi, string, TRUE);
1425 }
1426
1427 /* Add a FT_ETHER to a proto_tree */
1428 proto_item *
1429 proto_tree_add_ether(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1430                 const guint8* value)
1431 {
1432         proto_item              *pi;
1433         field_info              *new_fi;
1434         header_field_info       *hfinfo;
1435
1436         if (!tree)
1437                 return (NULL);
1438
1439         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1440         DISSECTOR_ASSERT(hfinfo->type == FT_ETHER);
1441
1442         pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1443         proto_tree_set_ether(new_fi, value);
1444
1445         return pi;
1446 }
1447
1448 proto_item *
1449 proto_tree_add_ether_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1450                 const guint8* value)
1451 {
1452         proto_item              *pi;
1453
1454         pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
1455         if (pi == NULL)
1456                 return (NULL);
1457
1458         PROTO_ITEM_SET_HIDDEN(pi);
1459
1460         return pi;
1461 }
1462
1463 proto_item *
1464 proto_tree_add_ether_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1465                 const guint8* value, const char *format, ...)
1466 {
1467         proto_item              *pi;
1468         va_list                 ap;
1469
1470         pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
1471         if (pi == NULL)
1472                 return (NULL);
1473
1474         va_start(ap, format);
1475         proto_tree_set_representation(pi, format, ap);
1476         va_end(ap);
1477
1478         return pi;
1479 }
1480
1481 /* Set the FT_ETHER value */
1482 static void
1483 proto_tree_set_ether(field_info *fi, const guint8* value)
1484 {
1485         fvalue_set(&fi->value, (gpointer) value, FALSE);
1486 }
1487
1488 static void
1489 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start)
1490 {
1491         proto_tree_set_ether(fi, tvb_get_ptr(tvb, start, 6));
1492 }
1493
1494 /* Add a FT_BOOLEAN to a proto_tree */
1495 proto_item *
1496 proto_tree_add_boolean(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1497                 guint32 value)
1498 {
1499         proto_item              *pi;
1500         field_info              *new_fi;
1501         header_field_info       *hfinfo;
1502
1503         if (!tree)
1504                 return (NULL);
1505
1506         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1507         DISSECTOR_ASSERT(hfinfo->type == FT_BOOLEAN);
1508
1509         pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1510         proto_tree_set_boolean(new_fi, value);
1511
1512         return pi;
1513 }
1514
1515 proto_item *
1516 proto_tree_add_boolean_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1517                 guint32 value)
1518 {
1519         proto_item              *pi;
1520
1521         pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
1522         if (pi == NULL)
1523                 return (NULL);
1524
1525         PROTO_ITEM_SET_HIDDEN(pi);
1526
1527         return pi;
1528 }
1529
1530 proto_item *
1531 proto_tree_add_boolean_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1532                 guint32 value, const char *format, ...)
1533 {
1534         proto_item              *pi;
1535         va_list                 ap;
1536
1537         pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
1538         if (pi == NULL)
1539                 return (NULL);
1540
1541         va_start(ap, format);
1542         proto_tree_set_representation(pi, format, ap);
1543         va_end(ap);
1544
1545         return pi;
1546 }
1547
1548 /* Set the FT_BOOLEAN value */
1549 static void
1550 proto_tree_set_boolean(field_info *fi, guint32 value)
1551 {
1552         proto_tree_set_uint(fi, value);
1553 }
1554
1555 /* Add a FT_FLOAT to a proto_tree */
1556 proto_item *
1557 proto_tree_add_float(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1558                 float value)
1559 {
1560         proto_item              *pi;
1561         field_info              *new_fi;
1562         header_field_info       *hfinfo;
1563
1564         if (!tree)
1565                 return (NULL);
1566
1567         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1568         DISSECTOR_ASSERT(hfinfo->type == FT_FLOAT);
1569
1570         pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1571         proto_tree_set_float(new_fi, value);
1572
1573         return pi;
1574 }
1575
1576 proto_item *
1577 proto_tree_add_float_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1578                 float value)
1579 {
1580         proto_item              *pi;
1581
1582         pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
1583         if (pi == NULL)
1584                 return (NULL);
1585
1586         PROTO_ITEM_SET_HIDDEN(pi);
1587
1588         return pi;
1589 }
1590
1591 proto_item *
1592 proto_tree_add_float_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1593                 float value, const char *format, ...)
1594 {
1595         proto_item              *pi;
1596         va_list                 ap;
1597
1598         pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
1599         if (pi == NULL)
1600                 return (NULL);
1601
1602         va_start(ap, format);
1603         proto_tree_set_representation(pi, format, ap);
1604         va_end(ap);
1605
1606         return pi;
1607 }
1608
1609 /* Set the FT_FLOAT value */
1610 static void
1611 proto_tree_set_float(field_info *fi, float value)
1612 {
1613         fvalue_set_floating(&fi->value, value);
1614 }
1615
1616 /* Add a FT_DOUBLE to a proto_tree */
1617 proto_item *
1618 proto_tree_add_double(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1619                 double value)
1620 {
1621         proto_item              *pi;
1622         field_info              *new_fi;
1623         header_field_info       *hfinfo;
1624
1625         if (!tree)
1626                 return (NULL);
1627
1628         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1629         DISSECTOR_ASSERT(hfinfo->type == FT_DOUBLE);
1630
1631         pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1632         proto_tree_set_double(new_fi, value);
1633
1634         return pi;
1635 }
1636
1637 proto_item *
1638 proto_tree_add_double_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1639                 double value)
1640 {
1641         proto_item              *pi;
1642
1643         pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
1644         if (pi == NULL)
1645                 return (NULL);
1646
1647         PROTO_ITEM_SET_HIDDEN(pi);
1648
1649         return pi;
1650 }
1651
1652 proto_item *
1653 proto_tree_add_double_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1654                 double value, const char *format, ...)
1655 {
1656         proto_item              *pi;
1657         va_list                 ap;
1658
1659         pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
1660         if (pi == NULL)
1661                 return (NULL);
1662
1663         va_start(ap, format);
1664         proto_tree_set_representation(pi, format, ap);
1665         va_end(ap);
1666
1667         return pi;
1668 }
1669
1670 /* Set the FT_DOUBLE value */
1671 static void
1672 proto_tree_set_double(field_info *fi, double value)
1673 {
1674         fvalue_set_floating(&fi->value, value);
1675 }
1676
1677 /* Add FT_UINT{8,16,24,32} to a proto_tree */
1678 proto_item *
1679 proto_tree_add_uint(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1680                 guint32 value)
1681 {
1682         proto_item              *pi = NULL;
1683         field_info              *new_fi;
1684         header_field_info       *hfinfo;
1685
1686         if (!tree)
1687                 return (NULL);
1688
1689         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1690         switch(hfinfo->type) {
1691                 case FT_UINT8:
1692                 case FT_UINT16:
1693                 case FT_UINT24:
1694                 case FT_UINT32:
1695                 case FT_FRAMENUM:
1696                         pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length,
1697                                         &new_fi);
1698                         proto_tree_set_uint(new_fi, value);
1699                         break;
1700
1701                 default:
1702                         DISSECTOR_ASSERT_NOT_REACHED();
1703         }
1704
1705         return pi;
1706 }
1707
1708 proto_item *
1709 proto_tree_add_uint_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1710                 guint32 value)
1711 {
1712         proto_item              *pi;
1713
1714         pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
1715         if (pi == NULL)
1716                 return (NULL);
1717
1718         PROTO_ITEM_SET_HIDDEN(pi);
1719
1720         return pi;
1721 }
1722
1723 proto_item *
1724 proto_tree_add_uint_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1725                 guint32 value, const char *format, ...)
1726 {
1727         proto_item              *pi;
1728         va_list                 ap;
1729
1730         pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
1731         if (pi == NULL)
1732                 return (NULL);
1733
1734         va_start(ap, format);
1735         proto_tree_set_representation(pi, format, ap);
1736         va_end(ap);
1737
1738         return pi;
1739 }
1740
1741 /* Set the FT_UINT{8,16,24,32} value */
1742 static void
1743 proto_tree_set_uint(field_info *fi, guint32 value)
1744 {
1745         header_field_info       *hfinfo;
1746         guint32                 integer;
1747
1748         hfinfo = fi->hfinfo;
1749         integer = value;
1750
1751         if (hfinfo->bitmask) {
1752                 /* Mask out irrelevant portions */
1753                 integer &= hfinfo->bitmask;
1754
1755                 /* Shift bits */
1756                 if (hfinfo->bitshift > 0) {
1757                         integer >>= hfinfo->bitshift;
1758                 }
1759         }
1760         fvalue_set_integer(&fi->value, integer);
1761 }
1762
1763 /* Add FT_UINT64 to a proto_tree */
1764 proto_item *
1765 proto_tree_add_uint64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1766                 guint64 value)
1767 {
1768         proto_item              *pi = NULL;
1769         field_info              *new_fi;
1770         header_field_info       *hfinfo;
1771
1772         if (!tree)
1773                 return (NULL);
1774
1775         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1776         DISSECTOR_ASSERT(hfinfo->type == FT_UINT64);
1777
1778         pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1779         proto_tree_set_uint64(new_fi, value);
1780
1781         return pi;
1782 }
1783
1784 proto_item *
1785 proto_tree_add_uint64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1786                 guint64 value, const char *format, ...)
1787 {
1788         proto_item              *pi;
1789         va_list                 ap;
1790
1791         pi = proto_tree_add_uint64(tree, hfindex, tvb, start, length, value);
1792         if (pi == NULL)
1793                 return (NULL);
1794
1795         va_start(ap, format);
1796         proto_tree_set_representation(pi, format, ap);
1797         va_end(ap);
1798
1799         return pi;
1800 }
1801
1802 /* Add FT_INT{8,16,24,32} to a proto_tree */
1803 proto_item *
1804 proto_tree_add_int(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1805                 gint32 value)
1806 {
1807         proto_item              *pi = NULL;
1808         field_info              *new_fi;
1809         header_field_info       *hfinfo;
1810
1811         if (!tree)
1812                 return (NULL);
1813
1814         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1815         switch(hfinfo->type) {
1816                 case FT_INT8:
1817                 case FT_INT16:
1818                 case FT_INT24:
1819                 case FT_INT32:
1820                         pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length,
1821                                         &new_fi);
1822                         proto_tree_set_int(new_fi, value);
1823                         break;
1824
1825                 default:
1826                         DISSECTOR_ASSERT_NOT_REACHED();
1827         }
1828
1829         return pi;
1830 }
1831
1832 proto_item *
1833 proto_tree_add_int_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1834                 gint32 value)
1835 {
1836         proto_item              *pi;
1837
1838         pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
1839         if (pi == NULL)
1840                 return (NULL);
1841
1842         PROTO_ITEM_SET_HIDDEN(pi);
1843
1844         return pi;
1845 }
1846
1847 proto_item *
1848 proto_tree_add_int_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1849                 gint32 value, const char *format, ...)
1850 {
1851         proto_item              *pi = NULL;
1852         va_list                 ap;
1853
1854         pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
1855         if (pi == NULL)
1856                 return (NULL);
1857
1858         va_start(ap, format);
1859         proto_tree_set_representation(pi, format, ap);
1860         va_end(ap);
1861
1862         return pi;
1863 }
1864
1865 /* Set the FT_INT{8,16,24,32} value */
1866 static void
1867 proto_tree_set_int(field_info *fi, gint32 value)
1868 {
1869         header_field_info       *hfinfo;
1870         guint32                 integer;
1871
1872         hfinfo = fi->hfinfo;
1873         integer = (guint32) value;
1874
1875         if (hfinfo->bitmask) {
1876                 /* Mask out irrelevant portions */
1877                 integer &= hfinfo->bitmask;
1878
1879                 /* Shift bits */
1880                 if (hfinfo->bitshift > 0) {
1881                         integer >>= hfinfo->bitshift;
1882                 }
1883         }
1884         fvalue_set_integer(&fi->value, integer);
1885 }
1886
1887 /* Add FT_INT64 to a proto_tree */
1888 proto_item *
1889 proto_tree_add_int64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1890                 gint64 value)
1891 {
1892         proto_item              *pi = NULL;
1893         field_info              *new_fi;
1894         header_field_info       *hfinfo;
1895
1896         if (!tree)
1897                 return (NULL);
1898
1899         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1900         DISSECTOR_ASSERT(hfinfo->type == FT_INT64);
1901
1902         pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1903         proto_tree_set_uint64(new_fi, (guint64)value);
1904
1905         return pi;
1906 }
1907
1908 proto_item *
1909 proto_tree_add_int64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1910                 gint64 value, const char *format, ...)
1911 {
1912         proto_item              *pi;
1913         va_list                 ap;
1914
1915         pi = proto_tree_add_int64(tree, hfindex, tvb, start, length, value);
1916         if (pi == NULL)
1917                 return (NULL);
1918
1919         va_start(ap, format);
1920         proto_tree_set_representation(pi, format, ap);
1921         va_end(ap);
1922
1923         return pi;
1924 }
1925
1926
1927 /* Add a field_info struct to the proto_tree, encapsulating it in a proto_node */
1928 static proto_item *
1929 proto_tree_add_node(proto_tree *tree, field_info *fi)
1930 {
1931         proto_node *pnode, *tnode, *sibling;
1932         field_info *tfi;
1933
1934         /*
1935          * Make sure "tree" is ready to have subtrees under it, by
1936          * checking whether it's been given an ett_ value.
1937          *
1938          * "tnode->finfo" may be null; that's the case for the root
1939          * node of the protocol tree.  That node is not displayed,
1940          * so it doesn't need an ett_ value to remember whether it
1941          * was expanded.
1942          */
1943         tnode = tree;
1944         tfi = tnode->finfo;
1945         if (tfi != NULL && (tfi->tree_type < 0 || tfi->tree_type >= num_tree_types)) {
1946                 REPORT_DISSECTOR_BUG(g_strdup_printf("\"%s\" - \"%s\" tfi->tree_type: %u invalid (%s:%u)",
1947                         fi->hfinfo->name, fi->hfinfo->abbrev, tfi->tree_type, __FILE__, __LINE__));
1948         /* XXX - is it safe to continue here? */
1949     }
1950
1951         DISSECTOR_ASSERT(tfi == NULL ||
1952             (tfi->tree_type >= 0 && tfi->tree_type < num_tree_types));
1953
1954         PROTO_NODE_NEW(pnode);
1955         pnode->parent = tnode;
1956         pnode->finfo = fi;
1957         pnode->tree_data = PTREE_DATA(tree);
1958
1959         if (tnode->last_child != NULL) {
1960                 sibling = tnode->last_child;
1961                 DISSECTOR_ASSERT(sibling->next == NULL);
1962                 sibling->next = pnode;
1963         } else
1964                 tnode->first_child = pnode;
1965         tnode->last_child = pnode;
1966
1967         return (proto_item*)pnode;
1968 }
1969
1970
1971 /* Generic way to allocate field_info and add to proto_tree.
1972  * Sets *pfi to address of newly-allocated field_info struct, if pfi is
1973  * non-NULL. */
1974 static proto_item *
1975 proto_tree_add_pi(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1976     gint *length, field_info **pfi)
1977 {
1978         proto_item      *pi;
1979         field_info      *fi;
1980         GHashTable      *hash;
1981         GPtrArray       *ptrs;
1982
1983         if (!tree)
1984                 return(NULL);
1985
1986         fi = alloc_field_info(tree, hfindex, tvb, start, length);
1987         pi = proto_tree_add_node(tree, fi);
1988
1989         /* If the proto_tree wants to keep a record of this finfo
1990          * for quick lookup, then record it. */
1991         hash = PTREE_DATA(tree)->interesting_hfids;
1992         ptrs = g_hash_table_lookup(hash, GINT_TO_POINTER(hfindex));
1993         if (ptrs) {
1994                 g_ptr_array_add(ptrs, fi);
1995         }
1996
1997         /* Does the caller want to know the fi pointer? */
1998         if (pfi) {
1999                 *pfi = fi;
2000         }
2001
2002         return pi;
2003 }
2004
2005 static field_info *
2006 alloc_field_info(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2007     gint *length)
2008 {
2009         header_field_info       *hfinfo;
2010         field_info              *fi;
2011         gint                    item_length;
2012         gint                    length_remaining;
2013
2014         /*
2015          * We only allow a null tvbuff if the item has a zero length,
2016          * i.e. if there's no data backing it.
2017          */
2018         DISSECTOR_ASSERT(tvb != NULL || *length == 0);
2019
2020         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2021
2022         /*
2023          * XXX - in some protocols, there are 32-bit unsigned length
2024          * fields, so lengths in protocol tree and tvbuff routines
2025          * should really be unsigned.  We should have, for those
2026          * field types for which "to the end of the tvbuff" makes sense,
2027          * additional routines that take no length argument and
2028          * add fields that run to the end of the tvbuff.
2029          */
2030         if (*length == -1) {
2031                 /*
2032                  * For FT_NONE, FT_PROTOCOL, FT_BYTES, and FT_STRING fields,
2033                  * a length of -1 means "set the length to what remains in
2034                  * the tvbuff".
2035                  *
2036                  * The assumption is either that
2037                  *
2038                  *      1) the length of the item can only be determined
2039                  *         by dissection (typically true of items with
2040                  *         subitems, which are probably FT_NONE or
2041                  *         FT_PROTOCOL)
2042                  *
2043                  * or
2044                  *
2045                  *      2) if the tvbuff is "short" (either due to a short
2046                  *         snapshot length or due to lack of reassembly of
2047                  *         fragments/segments/whatever), we want to display
2048                  *         what's available in the field (probably FT_BYTES
2049                  *         or FT_STRING) and then throw an exception later
2050                  *
2051                  * or
2052                  *
2053                  *      3) the field is defined to be "what's left in the
2054                  *         packet"
2055                  *
2056                  * so we set the length to what remains in the tvbuff so
2057                  * that, if we throw an exception while dissecting, it
2058                  * has what is probably the right value.
2059                  *
2060                  * For FT_STRINGZ, it means "the string is null-terminated,
2061                  * not null-padded; set the length to the actual length
2062                  * of the string", and if the tvbuff if short, we just
2063                  * throw an exception.
2064                  *
2065                  * It's not valid for any other type of field.
2066                  */
2067                 switch (hfinfo->type) {
2068
2069                 case FT_PROTOCOL:
2070                         /*
2071                          * We allow this to be zero-length - for
2072                          * example, an ONC RPC NULL procedure has
2073                          * neither arguments nor reply, so the
2074                          * payload for that protocol is empty.
2075                          *
2076                          * However, if the length is negative, the
2077                          * start offset is *past* the byte past the
2078                          * end of the tvbuff, so we throw an
2079                          * exception.
2080                          */
2081                         *length = tvb_length_remaining(tvb, start);
2082                         if (*length < 0) {
2083                                 /*
2084                                  * Use "tvb_ensure_bytes_exist()"
2085                                  * to force the appropriate exception
2086                                  * to be thrown.
2087                                  */
2088                                 tvb_ensure_bytes_exist(tvb, start, 0);
2089                         }
2090                         DISSECTOR_ASSERT(*length >= 0);
2091                         break;
2092
2093                 case FT_NONE:
2094                 case FT_BYTES:
2095                 case FT_STRING:
2096                         *length = tvb_ensure_length_remaining(tvb, start);
2097                         DISSECTOR_ASSERT(*length >= 0);
2098                         break;
2099
2100                 case FT_STRINGZ:
2101                         /*
2102                          * Leave the length as -1, so our caller knows
2103                          * it was -1.
2104                          */
2105                         break;
2106
2107                 default:
2108                         DISSECTOR_ASSERT_NOT_REACHED();
2109                 }
2110                 item_length = *length;
2111         } else {
2112                 item_length = *length;
2113                 if (hfinfo->type == FT_PROTOCOL || hfinfo->type == FT_NONE) {
2114                         /*
2115                          * These types are for interior nodes of the
2116                          * tree, and don't have data associated with
2117                          * them; if the length is negative (XXX - see
2118                          * above) or goes past the end of the tvbuff,
2119                          * cut it short at the end of the tvbuff.
2120                          * That way, if this field is selected in
2121                          * Ethereal, we don't highlight stuff past
2122                          * the end of the data.
2123                          */
2124             /* XXX - what to do, if we don't have a tvb? */
2125             if(tvb) {
2126                             length_remaining = tvb_length_remaining(tvb, start);
2127                             if (item_length < 0 || (item_length > 0 && (length_remaining < item_length)))
2128                                     item_length = length_remaining;
2129             }
2130                 }
2131                 if (item_length < 0) {
2132                         REPORT_DISSECTOR_BUG(g_strdup_printf("\"%s\" - \"%s\" invalid length: %d (%s:%u)",
2133                             hfinfo->name, hfinfo->abbrev, item_length,
2134                             __FILE__, __LINE__));
2135                 }
2136         }
2137
2138         FIELD_INFO_NEW(fi);
2139
2140         fi->hfinfo = hfinfo;
2141         fi->start = start;
2142         fi->start+=(tvb)?TVB_RAW_OFFSET(tvb):0;
2143         fi->length = item_length;
2144         fi->tree_type = -1;
2145         fi->flags = 0;
2146         if (!PTREE_DATA(tree)->visible)
2147                 FI_SET_FLAG(fi, FI_HIDDEN);
2148         fvalue_init(&fi->value, fi->hfinfo->type);
2149         fi->rep = NULL;
2150
2151         /* add the data source tvbuff */
2152         fi->ds_tvb=tvb?TVB_GET_DS_TVB(tvb):NULL;
2153
2154         return fi;
2155 }
2156
2157 /* Set representation of a proto_tree entry, if the protocol tree is to
2158    be visible. */
2159 static void
2160 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap)
2161 {
2162         int                                     ret;    /*tmp return value */
2163         field_info *fi = PITEM_FINFO(pi);
2164
2165         if (!PROTO_ITEM_IS_HIDDEN(pi)) {
2166                 ITEM_LABEL_NEW(fi->rep);
2167                 ret = vsnprintf(fi->rep->representation, ITEM_LABEL_LENGTH, format, ap);
2168                 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
2169                         fi->rep->representation[ITEM_LABEL_LENGTH - 1] = '\0';
2170         }
2171 }
2172
2173 /* Set text of proto_item after having already been created. */
2174 void
2175 proto_item_set_text(proto_item *pi, const char *format, ...)
2176 {
2177         field_info *fi = NULL;
2178         va_list ap;
2179
2180         if (pi==NULL) {
2181                 return;
2182         }
2183
2184         fi = PITEM_FINFO(pi);
2185
2186         if(fi->rep){
2187                 ITEM_LABEL_FREE(fi->rep);
2188         }
2189
2190         va_start(ap, format);
2191         proto_tree_set_representation(pi, format, ap);
2192         va_end(ap);
2193 }
2194
2195 /* Append to text of proto_item after having already been created. */
2196 void
2197 proto_item_append_text(proto_item *pi, const char *format, ...)
2198 {
2199         field_info *fi = NULL;
2200         size_t curlen;
2201         va_list ap;
2202         int                                     ret;    /*tmp return value */
2203
2204         if (pi==NULL) {
2205                 return;
2206         }
2207
2208         fi = PITEM_FINFO(pi);
2209
2210     if (!PROTO_ITEM_IS_HIDDEN(pi)) {
2211                 va_start(ap, format);
2212
2213                 /*
2214                  * If we don't already have a representation,
2215                  * generate the default representation.
2216                  */
2217                 if (fi->rep == NULL) {
2218                         ITEM_LABEL_NEW(fi->rep);
2219                         proto_item_fill_label(fi, fi->rep->representation);
2220                 }
2221
2222                 curlen = strlen(fi->rep->representation);
2223                 if (ITEM_LABEL_LENGTH > curlen) {
2224                         ret = vsnprintf(fi->rep->representation + curlen,
2225                             ITEM_LABEL_LENGTH - curlen, format, ap);
2226                         if ((ret == -1) || (ret >= (int)(ITEM_LABEL_LENGTH - curlen)))
2227                                 fi->rep->representation[ITEM_LABEL_LENGTH - 1] = '\0';
2228                 }
2229                 va_end(ap);
2230         }
2231 }
2232
2233 void
2234 proto_item_set_len(proto_item *pi, gint length)
2235 {
2236         field_info *fi;
2237
2238         if (pi == NULL)
2239                 return;
2240         fi = PITEM_FINFO(pi);
2241         DISSECTOR_ASSERT(length >= 0);
2242         fi->length = length;
2243 }
2244
2245 /*
2246  * Sets the length of the item based on its start and on the specified
2247  * offset, which is the offset past the end of the item; as the start
2248  * in the item is relative to the beginning of the data source tvbuff,
2249  * we need to pass in a tvbuff - the end offset is relative to the beginning
2250  * of that tvbuff.
2251  */
2252 void
2253 proto_item_set_end(proto_item *pi, tvbuff_t *tvb, gint end)
2254 {
2255         field_info *fi;
2256
2257         if (pi == NULL)
2258                 return;
2259         fi = PITEM_FINFO(pi);
2260         end += TVB_RAW_OFFSET(tvb);
2261         DISSECTOR_ASSERT(end >= fi->start);
2262         fi->length = end - fi->start;
2263 }
2264
2265 int
2266 proto_item_get_len(proto_item *pi)
2267 {
2268         field_info *fi = PITEM_FINFO(pi);
2269         return fi->length;
2270 }
2271
2272 proto_tree*
2273 proto_tree_create_root(void)
2274 {
2275         proto_node  *pnode;
2276
2277         /* Initialize the proto_node */
2278         PROTO_NODE_NEW(pnode);
2279         pnode->parent = NULL;
2280         pnode->finfo = NULL;
2281         pnode->tree_data = g_new(tree_data_t, 1);
2282
2283         /* Initialize the tree_data_t */
2284         pnode->tree_data->interesting_hfids =
2285             g_hash_table_new(g_direct_hash, g_direct_equal);
2286
2287         /* Set the default to FALSE so it's easier to
2288          * find errors; if we expect to see the protocol tree
2289          * but for some reason the default 'visible' is not
2290          * changed, then we'll find out very quickly. */
2291         pnode->tree_data->visible = FALSE;
2292
2293         return (proto_tree*) pnode;
2294 }
2295
2296
2297 /* "prime" a proto_tree with a single hfid that a dfilter
2298  * is interested in. */
2299 void
2300 proto_tree_prime_hfid(proto_tree *tree, gint hfid)
2301 {
2302         g_hash_table_insert(PTREE_DATA(tree)->interesting_hfids,
2303                 GINT_TO_POINTER(hfid), g_ptr_array_new());
2304 }
2305
2306
2307 proto_tree*
2308 proto_item_add_subtree(proto_item *pi,  gint idx) {
2309         field_info *fi;
2310
2311         if (!pi)
2312                 return(NULL);
2313
2314         fi = PITEM_FINFO(pi);
2315         DISSECTOR_ASSERT(idx >= 0 && idx < num_tree_types);
2316         fi->tree_type = idx;
2317         return (proto_tree*) pi;
2318 }
2319
2320 proto_tree*
2321 proto_item_get_subtree(proto_item *pi) {
2322         field_info *fi;
2323
2324         if (!pi)
2325                 return(NULL);
2326         fi = PITEM_FINFO(pi);
2327         if (fi->tree_type == -1)
2328                 return(NULL);
2329         return (proto_tree*) pi;
2330 }
2331
2332 proto_item*
2333 proto_item_get_parent(proto_item *ti) {
2334         if (!ti)
2335                 return (NULL);
2336         return ti->parent;
2337 }
2338
2339 proto_item*
2340 proto_item_get_parent_nth(proto_item *ti, int gen) {
2341         if (!ti)
2342                 return (NULL);
2343         while (gen--) {
2344                 ti = ti->parent;
2345                 if (!ti)
2346                         return (NULL);
2347         }
2348         return ti;
2349 }
2350
2351
2352 proto_item* 
2353 proto_tree_get_parent(proto_tree *tree) {
2354         if (!tree)
2355                 return (NULL);
2356         return (proto_item*) tree;
2357 }
2358
2359
2360 int
2361 proto_register_protocol(char *name, char *short_name, char *filter_name)
2362 {
2363     protocol_t *protocol;
2364     header_field_info *hfinfo;
2365     int proto_id;
2366     char *existing_name;
2367     gint *key;
2368     guint i;
2369     gboolean found_invalid;
2370
2371     /*
2372      * Make sure there's not already a protocol with any of those
2373      * names.  Crash if there is, as that's an error in the code
2374      * or an inappropriate plugin.
2375      * This situation has to be fixed to not register more than one
2376      * protocol with the same name.
2377      *
2378      * This is done by reducing the number of strcmp (and alike) calls as much as possible,
2379      * as this significally slows down startup time.
2380      *
2381      * Drawback: As a hash value is used to reduce insert time, 
2382      * this might lead to a hash collision.
2383      * However, as we have around 500+ protocols and we're using a 32 bit int this is very,
2384      * very unlikely.
2385      */
2386
2387     key = g_malloc (sizeof(gint));
2388     *key = g_str_hash(name);
2389     existing_name = g_hash_table_lookup(proto_names, key);
2390     if (existing_name != NULL) {
2391         /* g_error will terminate the program */
2392         g_error("Duplicate protocol name \"%s\"!"
2393             " This might be caused by an inappropriate plugin or a development error.", name);
2394     }
2395     g_hash_table_insert(proto_names, key, name);
2396
2397     key = g_malloc (sizeof(gint));
2398     *key = g_str_hash(short_name);
2399     existing_name = g_hash_table_lookup(proto_short_names, key);
2400     if (existing_name != NULL) {
2401         g_error("Duplicate protocol short_name \"%s\"!"
2402             " This might be caused by an inappropriate plugin or a development error.", short_name);
2403     }
2404     g_hash_table_insert(proto_short_names, key, short_name);
2405
2406     found_invalid = FALSE;
2407     for (i = 0; i < strlen(filter_name); i++) {
2408         if (! (islower(filter_name[i]) ||
2409                isdigit(filter_name[i]) ||
2410                filter_name[i] == '-'   ||
2411                filter_name[i] == '_'   ||
2412                filter_name[i] == '.'   )) {
2413             found_invalid = TRUE;
2414         }
2415     }
2416     if (found_invalid) {
2417         g_warning("Protocol filter name \"%s\" has one or more invalid characters.", filter_name);
2418     }
2419     key = g_malloc (sizeof(gint));
2420     *key = g_str_hash(filter_name);
2421     existing_name = g_hash_table_lookup(proto_filter_names, key);
2422     if (existing_name != NULL) {
2423         g_error("Duplicate protocol filter_name \"%s\"!"
2424             " This might be caused by an inappropriate plugin or a development error.", filter_name);
2425     }
2426     g_hash_table_insert(proto_filter_names, key, filter_name);
2427
2428     /* Add this protocol to the list of known protocols; the list
2429        is sorted by protocol short name. */
2430     protocol = g_malloc(sizeof (protocol_t));
2431     protocol->name = name;
2432     protocol->short_name = short_name;
2433     protocol->filter_name = filter_name;
2434     protocol->fields = NULL;
2435     protocol->is_enabled = TRUE; /* protocol is enabled by default */
2436     protocol->can_toggle = TRUE;
2437     /* list will be sorted later by name, when all protocols completed registering */
2438     protocols = g_list_append(protocols, protocol);
2439
2440     /* Here we do allocate a new header_field_info struct */
2441     hfinfo = g_mem_chunk_alloc(gmc_hfinfo);
2442     hfinfo->name = name;
2443     hfinfo->abbrev = filter_name;
2444     hfinfo->type = FT_PROTOCOL;
2445     hfinfo->strings = protocol;
2446     hfinfo->bitmask = 0;
2447     hfinfo->bitshift = 0;
2448     hfinfo->blurb = "";
2449     hfinfo->parent = -1; /* this field differentiates protos and fields */
2450
2451     proto_id = proto_register_field_init(hfinfo, hfinfo->parent);
2452     protocol->proto_id = proto_id;
2453     return proto_id;
2454 }
2455
2456 /*
2457  * Routines to use to iterate over the protocols.
2458  * The argument passed to the iterator routines is an opaque cookie to
2459  * their callers; it's the GList pointer for the current element in
2460  * the list.
2461  * The ID of the protocol is returned, or -1 if there is no protocol.
2462  */
2463 int
2464 proto_get_first_protocol(void **cookie)
2465 {
2466         protocol_t *protocol;
2467
2468         if (protocols == NULL)
2469                 return -1;
2470         *cookie = protocols;
2471         protocol = protocols->data;
2472         return protocol->proto_id;
2473 }
2474
2475 int
2476 proto_get_next_protocol(void **cookie)
2477 {
2478         GList *list_item = *cookie;
2479         protocol_t *protocol;
2480
2481         list_item = g_list_next(list_item);
2482         if (list_item == NULL)
2483                 return -1;
2484         *cookie = list_item;
2485         protocol = list_item->data;
2486         return protocol->proto_id;
2487 }
2488
2489 header_field_info *
2490 proto_get_first_protocol_field(int proto_id, void **cookie)
2491 {
2492         protocol_t *protocol = find_protocol_by_id(proto_id);
2493         hf_register_info *ptr;
2494
2495         if ((protocol == NULL) || (protocol->fields == NULL))
2496                 return NULL;
2497
2498         *cookie = protocol->fields;
2499         ptr = protocol->fields->data;
2500         return &ptr->hfinfo;
2501 }
2502
2503 header_field_info *
2504 proto_get_next_protocol_field(void **cookie)
2505 {
2506         GList *list_item = *cookie;
2507         hf_register_info *ptr;
2508
2509         list_item = g_list_next(list_item);
2510         if (list_item == NULL)
2511                 return NULL;
2512
2513         *cookie = list_item;
2514         ptr = list_item->data;
2515         return &ptr->hfinfo;
2516 }
2517
2518 protocol_t *
2519 find_protocol_by_id(int proto_id)
2520 {
2521         header_field_info *hfinfo;
2522
2523         if(proto_id<0)
2524                 return NULL;
2525
2526         PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
2527         DISSECTOR_ASSERT(hfinfo->type==FT_PROTOCOL);
2528         return (protocol_t *)hfinfo->strings;
2529 }
2530
2531 static gint compare_filter_name(gconstpointer proto_arg,
2532                                 gconstpointer filter_name)
2533 {
2534         const protocol_t *protocol = proto_arg;
2535         const gchar* f_name = filter_name;
2536
2537         return (strcmp(protocol->filter_name, f_name));
2538 }
2539
2540 int
2541 proto_get_id(protocol_t *protocol)
2542 {
2543         return protocol->proto_id;
2544 }
2545
2546 int proto_get_id_by_filter_name(gchar* filter_name)
2547 {
2548         GList *list_entry;
2549         protocol_t *protocol;
2550
2551         list_entry = g_list_find_custom(protocols, filter_name,
2552             compare_filter_name);
2553         if (list_entry == NULL)
2554                 return -1;
2555         protocol = list_entry->data;
2556         return protocol->proto_id;
2557 }
2558
2559 char *
2560 proto_get_protocol_name(int proto_id)
2561 {
2562         protocol_t *protocol;
2563
2564         protocol = find_protocol_by_id(proto_id);
2565         return protocol->name;
2566 }
2567
2568 char *
2569 proto_get_protocol_short_name(protocol_t *protocol)
2570 {
2571         if (protocol == NULL)
2572                 return "(none)";
2573         return protocol->short_name;
2574 }
2575
2576 char *
2577 proto_get_protocol_filter_name(int proto_id)
2578 {
2579         protocol_t *protocol;
2580
2581         protocol = find_protocol_by_id(proto_id);
2582         return protocol->filter_name;
2583 }
2584
2585 gboolean
2586 proto_is_protocol_enabled(protocol_t *protocol)
2587 {
2588         return protocol->is_enabled;
2589 }
2590
2591 gboolean
2592 proto_can_toggle_protocol(int proto_id)
2593 {
2594         protocol_t *protocol;
2595
2596         protocol = find_protocol_by_id(proto_id);
2597         return protocol->can_toggle;
2598 }
2599
2600 void
2601 proto_set_decoding(int proto_id, gboolean enabled)
2602 {
2603         protocol_t *protocol;
2604
2605         protocol = find_protocol_by_id(proto_id);
2606         DISSECTOR_ASSERT(protocol->can_toggle);
2607         protocol->is_enabled = enabled;
2608 }
2609
2610 void
2611 proto_set_cant_toggle(int proto_id)
2612 {
2613         protocol_t *protocol;
2614
2615         protocol = find_protocol_by_id(proto_id);
2616         protocol->can_toggle = FALSE;
2617 }
2618
2619 /* for use with static arrays only, since we don't allocate our own copies
2620 of the header_field_info struct contained within the hf_register_info struct */
2621 void
2622 proto_register_field_array(int parent, hf_register_info *hf, int num_records)
2623 {
2624         int                     field_id, i;
2625         hf_register_info        *ptr = hf;
2626         protocol_t              *proto;
2627
2628         proto = find_protocol_by_id(parent);
2629         for (i = 0; i < num_records; i++, ptr++) {
2630                 /*
2631                  * Make sure we haven't registered this yet.
2632                  * Most fields have variables associated with them
2633                  * that are initialized to -1; some have array elements,
2634                  * or possibly uninitialized variables, so we also allow
2635                  * 0 (which is unlikely to be the field ID we get back
2636                  * from "proto_register_field_init()").
2637                  */
2638                 DISSECTOR_ASSERT(*ptr->p_id == -1 || *ptr->p_id == 0);
2639
2640                 if (proto != NULL) {
2641                         if (proto->fields == NULL) {
2642                                 proto->fields = g_list_append(NULL, ptr);
2643                                 proto->last_field = proto->fields;
2644                         } else {
2645                                 proto->last_field =
2646                                     g_list_append(proto->last_field, ptr)->next;
2647                         }
2648                 }
2649                 field_id = proto_register_field_init(&ptr->hfinfo, parent);
2650                 *ptr->p_id = field_id;
2651         }
2652 }
2653
2654 static int
2655 proto_register_field_init(header_field_info *hfinfo, int parent)
2656 {
2657         /* The field must have names */
2658         DISSECTOR_ASSERT(hfinfo->name);
2659         DISSECTOR_ASSERT(hfinfo->abbrev);
2660
2661         /* These types of fields are allowed to have value_strings, true_false_strings or a protocol_t struct*/
2662         DISSECTOR_ASSERT((hfinfo->strings == NULL) || (
2663                         (hfinfo->type == FT_UINT8) ||
2664                         (hfinfo->type == FT_UINT16) ||
2665                         (hfinfo->type == FT_UINT24) ||
2666                         (hfinfo->type == FT_UINT32) ||
2667                         (hfinfo->type == FT_INT8) ||
2668                         (hfinfo->type == FT_INT16) ||
2669                         (hfinfo->type == FT_INT24) ||
2670                         (hfinfo->type == FT_INT32) ||
2671                         (hfinfo->type == FT_BOOLEAN) ||
2672                         (hfinfo->type == FT_PROTOCOL) ||
2673                         (hfinfo->type == FT_FRAMENUM) ));
2674
2675         switch (hfinfo->type) {
2676
2677         case FT_UINT8:
2678         case FT_UINT16:
2679         case FT_UINT24:
2680         case FT_UINT32:
2681         case FT_INT8:
2682         case FT_INT16:
2683         case FT_INT24:
2684         case FT_INT32:
2685                 /* Require integral types (other than frame number, which is
2686                    always displayed in decimal) to have a number base */
2687                 DISSECTOR_ASSERT(hfinfo->display != BASE_NONE);
2688                 break;
2689
2690         case FT_FRAMENUM:
2691                 /* Don't allow bitfields or value strings for frame numbers */
2692                 DISSECTOR_ASSERT(hfinfo->bitmask == 0);
2693                 DISSECTOR_ASSERT(hfinfo->strings == NULL);
2694                 break;
2695
2696         default:
2697                 break;
2698         }
2699         /* if this is a bitfield, compute bitshift */
2700         if (hfinfo->bitmask) {
2701                 while ((hfinfo->bitmask & (1 << hfinfo->bitshift)) == 0)
2702                         hfinfo->bitshift++;
2703         }
2704
2705         hfinfo->parent = parent;
2706         hfinfo->same_name_next = NULL;
2707         hfinfo->same_name_prev = NULL;
2708
2709         /* if we always add and never delete, then id == len - 1 is correct */
2710         if(gpa_hfinfo.len>=gpa_hfinfo.allocated_len){
2711                 if(!gpa_hfinfo.hfi){
2712                         gpa_hfinfo.allocated_len=1000;
2713                         gpa_hfinfo.hfi=g_malloc(sizeof(header_field_info *)*1000);
2714                 } else {
2715                         gpa_hfinfo.allocated_len+=1000;
2716                         gpa_hfinfo.hfi=g_realloc(gpa_hfinfo.hfi, sizeof(header_field_info *)*gpa_hfinfo.allocated_len);
2717                 }
2718         }
2719         gpa_hfinfo.hfi[gpa_hfinfo.len]=hfinfo;
2720         gpa_hfinfo.len++;
2721         hfinfo->id = gpa_hfinfo.len - 1;
2722
2723         /* if we have real names, enter this field in the name tree */
2724         if ((hfinfo->name[0] != 0) && (hfinfo->abbrev[0] != 0 )) {
2725
2726                 header_field_info *same_name_hfinfo, *same_name_next_hfinfo;
2727                 char *p;
2728                 guchar c;
2729
2730                 /* Check that the filter name (abbreviation) is legal;
2731                  * it must contain only alphanumerics, '-', "_", and ".". */
2732                 for (p = hfinfo->abbrev; (c = *p) != '\0'; p++)
2733                         DISSECTOR_ASSERT(isalnum(c) || c == '-' || c == '_' ||
2734                             c == '.');
2735
2736                 /* We allow multiple hfinfo's to be registered under the same
2737                  * abbreviation. This was done for X.25, as, depending
2738                  * on whether it's modulo-8 or modulo-128 operation,
2739                  * some bitfield fields may be in different bits of
2740                  * a byte, and we want to be able to refer to that field
2741                  * with one name regardless of whether the packets
2742                  * are modulo-8 or modulo-128 packets. */
2743                 same_name_hfinfo = g_tree_lookup(gpa_name_tree, hfinfo->abbrev);
2744                 if (same_name_hfinfo) {
2745                         /* There's already a field with this name.
2746                          * Put it after that field in the list of
2747                          * fields with this name, then allow the code
2748                          * after this if{} block to replace the old
2749                          * hfinfo with the new hfinfo in the GTree. Thus,
2750                          * we end up with a linked-list of same-named hfinfo's,
2751                          * with the root of the list being the hfinfo in the GTree */
2752                         same_name_next_hfinfo =
2753                             same_name_hfinfo->same_name_next;
2754
2755                         hfinfo->same_name_next = same_name_next_hfinfo;
2756                         if (same_name_next_hfinfo)
2757                                 same_name_next_hfinfo->same_name_prev = hfinfo;
2758
2759                         same_name_hfinfo->same_name_next = hfinfo;
2760                         hfinfo->same_name_prev = same_name_hfinfo;
2761                 }
2762                 g_tree_insert(gpa_name_tree, hfinfo->abbrev, hfinfo);
2763         }
2764
2765         return hfinfo->id;
2766 }
2767
2768 void
2769 proto_register_subtree_array(gint *const *indices, int num_indices)
2770 {
2771         int     i;
2772         gint    *const *ptr = indices;
2773
2774         /*
2775          * If we've already allocated the array of tree types, expand
2776          * it; this lets plugins such as mate add tree types after
2777          * the initial startup.  (If we haven't already allocated it,
2778          * we don't allocate it; on the first pass, we just assign
2779          * ett values and keep track of how many we've assigned, and
2780          * when we're finished registering all dissectors we allocate
2781          * the array, so that we do only one allocation rather than
2782          * wasting CPU time and memory by growing the array for each
2783          * dissector that registers ett values.)
2784          */
2785         if (tree_is_expanded != NULL) {
2786                 tree_is_expanded =
2787                     g_realloc(tree_is_expanded,
2788                         (num_tree_types+num_indices)*sizeof (gint *));
2789                 memset(tree_is_expanded + num_tree_types, 0,
2790                     num_indices*sizeof (gint *));
2791         }
2792
2793         /*
2794          * Assign "num_indices" subtree numbers starting at "num_tree_types",
2795          * returning the indices through the pointers in the array whose
2796          * first element is pointed to by "indices", and update
2797          * "num_tree_types" appropriately.
2798          */
2799         for (i = 0; i < num_indices; i++, ptr++, num_tree_types++)
2800                 **ptr = num_tree_types;
2801 }
2802
2803 void
2804 proto_item_fill_label(field_info *fi, gchar *label_str)
2805 {
2806         header_field_info               *hfinfo = fi->hfinfo;
2807
2808         guint8                          *bytes;
2809         guint32                         integer;
2810         ipv4_addr                       *ipv4;
2811         guint32                         n_addr; /* network-order IPv4 address */
2812         int                                     ret;    /*tmp return value */
2813
2814         switch(hfinfo->type) {
2815                 case FT_NONE:
2816                 case FT_PROTOCOL:
2817                         ret = snprintf(label_str, ITEM_LABEL_LENGTH,
2818                                 "%s", hfinfo->name);
2819                         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
2820                                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
2821                         break;
2822
2823                 case FT_BOOLEAN:
2824                         fill_label_boolean(fi, label_str);
2825                         break;
2826
2827                 case FT_BYTES:
2828                 case FT_UINT_BYTES:
2829                         bytes = fvalue_get(&fi->value);
2830                         if (bytes) {
2831                                 ret = snprintf(label_str, ITEM_LABEL_LENGTH,
2832                                         "%s: %s", hfinfo->name,
2833                                          bytes_to_str(bytes, fvalue_length(&fi->value)));
2834                                 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
2835                                         label_str[ITEM_LABEL_LENGTH - 1] = '\0';
2836                         }
2837                         else {
2838                                 ret = snprintf(label_str, ITEM_LABEL_LENGTH,
2839                                         "%s: <MISSING>", hfinfo->name);
2840                                 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
2841                                         label_str[ITEM_LABEL_LENGTH - 1] = '\0';
2842                         }
2843                         break;
2844
2845                 /* Four types of integers to take care of:
2846                  *      Bitfield, with val_string
2847                  *      Bitfield, w/o val_string
2848                  *      Non-bitfield, with val_string
2849                  *      Non-bitfield, w/o val_string
2850                  */
2851                 case FT_UINT8:
2852                 case FT_UINT16:
2853                 case FT_UINT24:
2854                 case FT_UINT32:
2855                 case FT_FRAMENUM:
2856                         if (hfinfo->bitmask) {
2857                                 if (hfinfo->strings) {
2858                                         fill_label_enumerated_bitfield(fi, label_str);
2859                                 }
2860                                 else {
2861                                         fill_label_numeric_bitfield(fi, label_str);
2862                                 }
2863                         }
2864                         else {
2865                                 if (hfinfo->strings) {
2866                                         fill_label_enumerated_uint(fi, label_str);
2867                                 }
2868                                 else {
2869                                         fill_label_uint(fi, label_str);
2870                                 }
2871                         }
2872                         break;
2873
2874                 case FT_UINT64:
2875                         fill_label_uint64(fi, label_str);
2876                         break;
2877
2878                 case FT_INT8:
2879                 case FT_INT16:
2880                 case FT_INT24:
2881                 case FT_INT32:
2882                         DISSECTOR_ASSERT(!hfinfo->bitmask);
2883                         if (hfinfo->strings) {
2884                                 fill_label_enumerated_int(fi, label_str);
2885                         }
2886                         else {
2887                                 fill_label_int(fi, label_str);
2888                         }
2889                         break;
2890
2891                 case FT_INT64:
2892                         fill_label_int64(fi, label_str);
2893                         break;
2894
2895                 case FT_FLOAT:
2896                         ret = snprintf(label_str, ITEM_LABEL_LENGTH,
2897                                 "%s: %." STRINGIFY(FLT_DIG) "f",
2898                                 hfinfo->name, fvalue_get_floating(&fi->value));
2899                         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
2900                                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
2901                         break;
2902
2903                 case FT_DOUBLE:
2904                         ret = snprintf(label_str, ITEM_LABEL_LENGTH,
2905                                 "%s: %." STRINGIFY(DBL_DIG) "g",
2906                                 hfinfo->name, fvalue_get_floating(&fi->value));
2907                         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
2908                                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
2909                         break;
2910
2911                 case FT_ABSOLUTE_TIME:
2912                         ret = snprintf(label_str, ITEM_LABEL_LENGTH,
2913                                 "%s: %s", hfinfo->name,
2914                                 abs_time_to_str(fvalue_get(&fi->value)));
2915                         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
2916                                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
2917                         break;
2918
2919                 case FT_RELATIVE_TIME:
2920                         ret = snprintf(label_str, ITEM_LABEL_LENGTH,
2921                                 "%s: %s seconds", hfinfo->name,
2922                                 rel_time_to_secs_str(fvalue_get(&fi->value)));
2923                         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
2924                                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
2925                         break;
2926
2927                 case FT_IPXNET:
2928                         integer = fvalue_get_integer(&fi->value);
2929                         ret = snprintf(label_str, ITEM_LABEL_LENGTH,
2930                                 "%s: 0x%08X (%s)", hfinfo->name,
2931                                 integer, get_ipxnet_name(integer));
2932                         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
2933                                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
2934                         break;
2935
2936                 case FT_ETHER:
2937                         bytes = fvalue_get(&fi->value);
2938                         ret = snprintf(label_str, ITEM_LABEL_LENGTH,
2939                                 "%s: %s (%s)", hfinfo->name,
2940                                 ether_to_str(bytes),
2941                                 get_ether_name(bytes));
2942                         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
2943                                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
2944                         break;
2945
2946                 case FT_IPv4:
2947                         ipv4 = fvalue_get(&fi->value);
2948                         n_addr = ipv4_get_net_order_addr(ipv4);
2949                         ret = snprintf(label_str, ITEM_LABEL_LENGTH,
2950                                 "%s: %s (%s)", hfinfo->name,
2951                                 get_hostname(n_addr),
2952                                 ip_to_str((guint8*)&n_addr));
2953                         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
2954                                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
2955                         break;
2956
2957                 case FT_IPv6:
2958                         bytes = fvalue_get(&fi->value);
2959                         ret = snprintf(label_str, ITEM_LABEL_LENGTH,
2960                                 "%s: %s (%s)", hfinfo->name,
2961                                 get_hostname6((struct e_in6_addr *)bytes),
2962                                 ip6_to_str((struct e_in6_addr*)bytes));
2963                         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
2964                                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
2965                         break;
2966
2967                 case FT_STRING:
2968                 case FT_STRINGZ:
2969                 case FT_UINT_STRING:
2970                         bytes = fvalue_get(&fi->value);
2971                         ret = snprintf(label_str, ITEM_LABEL_LENGTH,
2972                                 "%s: %s", hfinfo->name,
2973                                 format_text(bytes, strlen(bytes)));
2974                         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
2975                                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
2976                         break;
2977
2978                 default:
2979                         g_error("hfinfo->type %d (%s) not handled\n",
2980                                         hfinfo->type,
2981                                         ftype_name(hfinfo->type));
2982                         DISSECTOR_ASSERT_NOT_REACHED();
2983                         break;
2984         }
2985 }
2986
2987 static void
2988 fill_label_boolean(field_info *fi, gchar *label_str)
2989 {
2990         char    *p = label_str;
2991         int     bitfield_byte_length = 0, bitwidth;
2992         guint32 unshifted_value;
2993         guint32 value;
2994         int                                     ret;    /*tmp return value */
2995
2996         header_field_info               *hfinfo = fi->hfinfo;
2997         static const true_false_string  default_tf = { "True", "False" };
2998         const true_false_string         *tfstring = &default_tf;
2999
3000         if (hfinfo->strings) {
3001                 tfstring = (const struct true_false_string*) hfinfo->strings;
3002         }
3003
3004         value = fvalue_get_integer(&fi->value);
3005         if (hfinfo->bitmask) {
3006                 /* Figure out the bit width */
3007                 bitwidth = hfinfo_bitwidth(hfinfo);
3008
3009                 /* Un-shift bits */
3010                 unshifted_value = value;
3011                 if (hfinfo->bitshift > 0) {
3012                         unshifted_value <<= hfinfo->bitshift;
3013                 }
3014
3015                 /* Create the bitfield first */
3016                 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
3017                 bitfield_byte_length = p - label_str;
3018         }
3019
3020         /* Fill in the textual info */
3021         ret = snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
3022                 "%s: %s",  hfinfo->name,
3023                 value ? tfstring->true_string : tfstring->false_string);
3024         if ((ret == -1) || (ret >= (ITEM_LABEL_LENGTH - bitfield_byte_length)))
3025                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3026 }
3027
3028
3029 /* Fills data for bitfield ints with val_strings */
3030 static void
3031 fill_label_enumerated_bitfield(field_info *fi, gchar *label_str)
3032 {
3033         char *format = NULL, *p;
3034         int bitfield_byte_length, bitwidth;
3035         guint32 unshifted_value;
3036         guint32 value;
3037         int                                     ret;    /*tmp return value */
3038
3039         header_field_info       *hfinfo = fi->hfinfo;
3040
3041         /* Figure out the bit width */
3042         bitwidth = hfinfo_bitwidth(hfinfo);
3043
3044         /* Pick the proper format string */
3045         format = hfinfo_uint_vals_format(hfinfo);
3046
3047         /* Un-shift bits */
3048         unshifted_value = fvalue_get_integer(&fi->value);
3049         value = unshifted_value;
3050         if (hfinfo->bitshift > 0) {
3051                 unshifted_value <<= hfinfo->bitshift;
3052         }
3053
3054         /* Create the bitfield first */
3055         p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
3056         bitfield_byte_length = p - label_str;
3057
3058         /* Fill in the textual info using stored (shifted) value */
3059         ret = snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
3060                         format,  hfinfo->name,
3061                         val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
3062         if ((ret == -1) || (ret >= (ITEM_LABEL_LENGTH - bitfield_byte_length)))
3063                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3064 }
3065
3066 static void
3067 fill_label_numeric_bitfield(field_info *fi, gchar *label_str)
3068 {
3069         char *format = NULL, *p;
3070         int bitfield_byte_length, bitwidth;
3071         guint32 unshifted_value;
3072         guint32 value;
3073         int                                     ret;    /*tmp return value */
3074
3075         header_field_info       *hfinfo = fi->hfinfo;
3076
3077         /* Figure out the bit width */
3078         bitwidth = hfinfo_bitwidth(hfinfo);
3079
3080         /* Pick the proper format string */
3081         format = hfinfo_uint_format(hfinfo);
3082
3083         /* Un-shift bits */
3084         unshifted_value = fvalue_get_integer(&fi->value);
3085         value = unshifted_value;
3086         if (hfinfo->bitshift > 0) {
3087                 unshifted_value <<= hfinfo->bitshift;
3088         }
3089
3090         /* Create the bitfield using */
3091         p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
3092         bitfield_byte_length = p - label_str;
3093
3094         /* Fill in the textual info using stored (shifted) value */
3095         ret = snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
3096                         format,  hfinfo->name, value);
3097         if ((ret == -1) || (ret >= (ITEM_LABEL_LENGTH - bitfield_byte_length)))
3098                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3099
3100 }
3101
3102 static void
3103 fill_label_enumerated_uint(field_info *fi, gchar *label_str)
3104 {
3105         char *format = NULL;
3106         header_field_info       *hfinfo = fi->hfinfo;
3107         guint32 value;
3108         int                                     ret;    /*tmp return value */
3109
3110         /* Pick the proper format string */
3111         format = hfinfo_uint_vals_format(hfinfo);
3112
3113         value = fvalue_get_integer(&fi->value);
3114
3115         /* Fill in the textual info */
3116         ret = snprintf(label_str, ITEM_LABEL_LENGTH,
3117                         format,  hfinfo->name,
3118                         val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
3119         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3120                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3121 }
3122
3123 static void
3124 fill_label_uint(field_info *fi, gchar *label_str)
3125 {
3126         char *format = NULL;
3127         header_field_info       *hfinfo = fi->hfinfo;
3128         guint32 value;
3129         int                                     ret;    /*tmp return value */
3130
3131         /* Pick the proper format string */
3132         format = hfinfo_uint_format(hfinfo);
3133         value = fvalue_get_integer(&fi->value);
3134
3135         /* Fill in the textual info */
3136         ret = snprintf(label_str, ITEM_LABEL_LENGTH,
3137                         format,  hfinfo->name, value);
3138         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3139                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3140 }
3141
3142 static void
3143 fill_label_uint64(field_info *fi, gchar *label_str)
3144 {
3145         char *format = NULL;
3146         header_field_info       *hfinfo = fi->hfinfo;
3147         guint64 value;
3148         int                                     ret;    /*tmp return value */
3149
3150         /* Pick the proper format string */
3151         format = hfinfo_uint64_format(hfinfo);
3152         value = fvalue_get_integer64(&fi->value);
3153
3154         /* Fill in the textual info */
3155         ret = snprintf(label_str, ITEM_LABEL_LENGTH,
3156                         format,  hfinfo->name, value);
3157         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3158                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3159 }
3160
3161 static void
3162 fill_label_enumerated_int(field_info *fi, gchar *label_str)
3163 {
3164         char *format = NULL;
3165         header_field_info       *hfinfo = fi->hfinfo;
3166         guint32 value;
3167         int                                     ret;    /*tmp return value */
3168
3169         /* Pick the proper format string */
3170         format = hfinfo_int_vals_format(hfinfo);
3171         value = fvalue_get_integer(&fi->value);
3172
3173         /* Fill in the textual info */
3174         ret = snprintf(label_str, ITEM_LABEL_LENGTH,
3175                         format,  hfinfo->name,
3176                         val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
3177         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3178                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3179 }
3180
3181 static void
3182 fill_label_int(field_info *fi, gchar *label_str)
3183 {
3184         char *format = NULL;
3185         header_field_info       *hfinfo = fi->hfinfo;
3186         guint32 value;
3187         int                                     ret;    /*tmp return value */
3188
3189         /* Pick the proper format string */
3190         format = hfinfo_int_format(hfinfo);
3191         value = fvalue_get_integer(&fi->value);
3192
3193         /* Fill in the textual info */
3194         ret = snprintf(label_str, ITEM_LABEL_LENGTH,
3195                         format,  hfinfo->name, value);
3196         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3197                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3198 }
3199
3200 static void
3201 fill_label_int64(field_info *fi, gchar *label_str)
3202 {
3203         char *format = NULL;
3204         header_field_info       *hfinfo = fi->hfinfo;
3205         guint64 value;
3206         int                                     ret;    /*tmp return value */
3207
3208         /* Pick the proper format string */
3209         format = hfinfo_int64_format(hfinfo);
3210         value = fvalue_get_integer64(&fi->value);
3211
3212         /* Fill in the textual info */
3213         ret = snprintf(label_str, ITEM_LABEL_LENGTH,
3214                         format,  hfinfo->name, value);
3215         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3216                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3217 }
3218
3219 int
3220 hfinfo_bitwidth(header_field_info *hfinfo)
3221 {
3222         int bitwidth = 0;
3223
3224         if (!hfinfo->bitmask) {
3225                 return 0;
3226         }
3227
3228         switch(hfinfo->type) {
3229                 case FT_UINT8:
3230                 case FT_INT8:
3231                         bitwidth = 8;
3232                         break;
3233                 case FT_UINT16:
3234                 case FT_INT16:
3235                         bitwidth = 16;
3236                         break;
3237                 case FT_UINT24:
3238                 case FT_INT24:
3239                         bitwidth = 24;
3240                         break;
3241                 case FT_UINT32:
3242                 case FT_INT32:
3243                         bitwidth = 32;
3244                         break;
3245                 case FT_BOOLEAN:
3246                         bitwidth = hfinfo->display; /* hacky? :) */
3247                         break;
3248                 default:
3249                         DISSECTOR_ASSERT_NOT_REACHED();
3250                         ;
3251         }
3252         return bitwidth;
3253 }
3254
3255 static char*
3256 hfinfo_uint_vals_format(header_field_info *hfinfo)
3257 {
3258         char *format = NULL;
3259
3260         switch(hfinfo->display) {
3261                 case BASE_DEC:
3262                         format = "%s: %s (%u)";
3263                         break;
3264                 case BASE_OCT: /* I'm lazy */
3265                         format = "%s: %s (%o)";
3266                         break;
3267                 case BASE_HEX:
3268                         switch(hfinfo->type) {
3269                                 case FT_UINT8:
3270                                         format = "%s: %s (0x%02x)";
3271                                         break;
3272                                 case FT_UINT16:
3273                                         format = "%s: %s (0x%04x)";
3274                                         break;
3275                                 case FT_UINT24:
3276                                         format = "%s: %s (0x%06x)";
3277                                         break;
3278                                 case FT_UINT32:
3279                                         format = "%s: %s (0x%08x)";
3280                                         break;
3281                                 default:
3282                                         DISSECTOR_ASSERT_NOT_REACHED();
3283                                         ;
3284                         }
3285                         break;
3286                 default:
3287                         DISSECTOR_ASSERT_NOT_REACHED();
3288                         ;
3289         }
3290         return format;
3291 }
3292
3293 static char*
3294 hfinfo_uint_format(header_field_info *hfinfo)
3295 {
3296         char *format = NULL;
3297
3298         /* Pick the proper format string */
3299         if (hfinfo->type == FT_FRAMENUM) {
3300                 /*
3301                  * Frame numbers are always displayed in decimal.
3302                  */
3303                 format = "%s: %u";
3304         } else {
3305                 switch(hfinfo->display) {
3306                         case BASE_DEC:
3307                                 format = "%s: %u";
3308                                 break;
3309                         case BASE_OCT: /* I'm lazy */
3310                                 format = "%s: %o";
3311                                 break;
3312                         case BASE_HEX:
3313                                 switch(hfinfo->type) {
3314                                         case FT_UINT8:
3315                                                 format = "%s: 0x%02x";
3316                                                 break;
3317                                         case FT_UINT16:
3318                                                 format = "%s: 0x%04x";
3319                                                 break;
3320                                         case FT_UINT24:
3321                                                 format = "%s: 0x%06x";
3322                                                 break;
3323                                         case FT_UINT32:
3324                                                 format = "%s: 0x%08x";
3325                                                 break;
3326                                         default:
3327                                                 DISSECTOR_ASSERT_NOT_REACHED();
3328                                                 ;
3329                                 }
3330                                 break;
3331                         default:
3332                                 DISSECTOR_ASSERT_NOT_REACHED();
3333                                 ;
3334                 }
3335         }
3336         return format;
3337 }
3338
3339 static char*
3340 hfinfo_int_vals_format(header_field_info *hfinfo)
3341 {
3342         char *format = NULL;
3343
3344         switch(hfinfo->display) {
3345                 case BASE_DEC:
3346                         format = "%s: %s (%d)";
3347                         break;
3348                 case BASE_OCT: /* I'm lazy */
3349                         format = "%s: %s (%o)";
3350                         break;
3351                 case BASE_HEX:
3352                         switch(hfinfo->type) {
3353                                 case FT_INT8:
3354                                         format = "%s: %s (0x%02x)";
3355                                         break;
3356                                 case FT_INT16:
3357                                         format = "%s: %s (0x%04x)";
3358                                         break;
3359                                 case FT_INT24:
3360                                         format = "%s: %s (0x%06x)";
3361                                         break;
3362                                 case FT_INT32:
3363                                         format = "%s: %s (0x%08x)";
3364                                         break;
3365                                 default:
3366                                         DISSECTOR_ASSERT_NOT_REACHED();
3367                                         ;
3368                         }
3369                         break;
3370                 default:
3371                         DISSECTOR_ASSERT_NOT_REACHED();
3372                         ;
3373         }
3374         return format;
3375 }
3376
3377 static char*
3378 hfinfo_uint64_format(header_field_info *hfinfo)
3379 {
3380         char *format = NULL;
3381
3382         /* Pick the proper format string */
3383         switch(hfinfo->display) {
3384                 case BASE_DEC:
3385                         format = "%s: %" PRIu64;
3386                         break;
3387                 case BASE_OCT: /* I'm lazy */
3388                         format = "%s: %" PRIo64;
3389                         break;
3390                 case BASE_HEX:
3391                         format = "%s: 0x%016" PRIx64;
3392                         break;
3393                 default:
3394                         DISSECTOR_ASSERT_NOT_REACHED();
3395                         ;
3396         }
3397         return format;
3398 }
3399
3400 static char*
3401 hfinfo_int_format(header_field_info *hfinfo)
3402 {
3403         char *format = NULL;
3404
3405         /* Pick the proper format string */
3406         switch(hfinfo->display) {
3407                 case BASE_DEC:
3408                         format = "%s: %d";
3409                         break;
3410                 case BASE_OCT: /* I'm lazy */
3411                         format = "%s: %o";
3412                         break;
3413                 case BASE_HEX:
3414                         switch(hfinfo->type) {
3415                                 case FT_INT8:
3416                                         format = "%s: 0x%02x";
3417                                         break;
3418                                 case FT_INT16:
3419                                         format = "%s: 0x%04x";
3420                                         break;
3421                                 case FT_INT24:
3422                                         format = "%s: 0x%06x";
3423                                         break;
3424                                 case FT_INT32:
3425                                         format = "%s: 0x%08x";
3426                                         break;
3427                                 default:
3428                                         DISSECTOR_ASSERT_NOT_REACHED();
3429                                         ;
3430                         }
3431                         break;
3432                 default:
3433                         DISSECTOR_ASSERT_NOT_REACHED();
3434                         ;
3435         }
3436         return format;
3437 }
3438
3439 static char*
3440 hfinfo_int64_format(header_field_info *hfinfo)
3441 {
3442         char *format = NULL;
3443
3444         /* Pick the proper format string */
3445         switch(hfinfo->display) {
3446                 case BASE_DEC:
3447                         format = "%s: %" PRId64;
3448                         break;
3449                 case BASE_OCT: /* I'm lazy */
3450                         format = "%s: %" PRIo64;
3451                         break;
3452                 case BASE_HEX:
3453                         format = "%s: 0x%016" PRIx64;
3454                         break;
3455                 default:
3456                         DISSECTOR_ASSERT_NOT_REACHED();
3457                         ;
3458         }
3459         return format;
3460 }
3461
3462
3463
3464 int
3465 proto_registrar_n(void)
3466 {
3467         return gpa_hfinfo.len;
3468 }
3469
3470 char*
3471 proto_registrar_get_name(int n)
3472 {
3473         header_field_info *hfinfo;
3474
3475         PROTO_REGISTRAR_GET_NTH(n, hfinfo);
3476         return hfinfo->name;
3477 }
3478
3479 char*
3480 proto_registrar_get_abbrev(int n)
3481 {
3482         header_field_info *hfinfo;
3483
3484         PROTO_REGISTRAR_GET_NTH(n, hfinfo);
3485         return hfinfo->abbrev;
3486 }
3487
3488 int
3489 proto_registrar_get_ftype(int n)
3490 {
3491         header_field_info *hfinfo;
3492
3493         PROTO_REGISTRAR_GET_NTH(n, hfinfo);
3494         return hfinfo->type;
3495 }
3496
3497 int
3498 proto_registrar_get_parent(int n)
3499 {
3500         header_field_info *hfinfo;
3501
3502         PROTO_REGISTRAR_GET_NTH(n, hfinfo);
3503         return hfinfo->parent;
3504 }
3505
3506 gboolean
3507 proto_registrar_is_protocol(int n)
3508 {
3509         header_field_info *hfinfo;
3510
3511         PROTO_REGISTRAR_GET_NTH(n, hfinfo);
3512         return (hfinfo->parent == -1 ? TRUE : FALSE);
3513 }
3514
3515 /* Returns length of field in packet (not necessarily the length
3516  * in our internal representation, as in the case of IPv4).
3517  * 0 means undeterminable at time of registration
3518  * -1 means the field is not registered. */
3519 gint
3520 proto_registrar_get_length(int n)
3521 {
3522         header_field_info *hfinfo;
3523
3524         PROTO_REGISTRAR_GET_NTH(n, hfinfo);
3525         return ftype_length(hfinfo->type);
3526 }
3527
3528
3529
3530 /* Looks for a protocol or a field in a proto_tree. Returns TRUE if
3531  * it exists anywhere, or FALSE if it exists nowhere. */
3532 gboolean
3533 proto_check_for_protocol_or_field(proto_tree* tree, int id)
3534 {
3535         GPtrArray *ptrs = proto_get_finfo_ptr_array(tree, id);
3536
3537         if (!ptrs) {
3538                 return FALSE;
3539         }
3540         else if (g_ptr_array_len(ptrs) > 0) {
3541                 return TRUE;
3542         }
3543         else {
3544                 return FALSE;
3545         }
3546 }
3547
3548 /* Return GPtrArray* of field_info pointers for all hfindex that appear in tree.
3549  * This only works if the hfindex was "primed" before the dissection
3550  * took place, as we just pass back the already-created GPtrArray*.
3551  * The caller should *not* free the GPtrArray*; proto_tree_free_node()
3552  * handles that. */
3553 GPtrArray*
3554 proto_get_finfo_ptr_array(proto_tree *tree, int id)
3555 {
3556         return g_hash_table_lookup(PTREE_DATA(tree)->interesting_hfids,
3557             GINT_TO_POINTER(id));
3558 }
3559
3560
3561 /* Helper struct and function for proto_find_info() */
3562 typedef struct {
3563         GPtrArray       *array;
3564         int             id;
3565 } ffdata_t;
3566
3567 static gboolean
3568 find_finfo(proto_node *node, gpointer data)
3569 {
3570         field_info *fi = PITEM_FINFO(node);
3571         if (fi && fi->hfinfo) {
3572                 if (fi->hfinfo->id == ((ffdata_t*)data)->id) {
3573                         g_ptr_array_add(((ffdata_t*)data)->array, fi);
3574                 }
3575         }
3576
3577         /* Don't stop traversing. */
3578         return FALSE;
3579 }
3580
3581 /* Return GPtrArray* of field_info pointers for all hfindex that appear in a tree.
3582  * This works on any proto_tree, primed or unprimed, but actually searches
3583  * the tree, so it is slower than using proto_get_finfo_ptr_array on a primed tree.
3584  * The caller does need to free the returned GPtrArray with
3585  * g_ptr_array_free(<array>, FALSE).
3586  */
3587 GPtrArray*
3588 proto_find_finfo(proto_tree *tree, int id)
3589 {
3590         ffdata_t        ffdata;
3591
3592         ffdata.array = g_ptr_array_new();
3593         ffdata.id = id;
3594
3595         proto_tree_traverse_pre_order(tree, find_finfo, &ffdata);
3596
3597         return ffdata.array;
3598 }       
3599
3600
3601 typedef struct {
3602         guint           offset;
3603         field_info      *finfo;
3604         tvbuff_t        *tvb;
3605 } offset_search_t;
3606
3607 static gboolean
3608 check_for_offset(proto_node *node, gpointer data)
3609 {
3610         field_info          *fi = PITEM_FINFO(node);
3611         offset_search_t         *offsearch = data;
3612
3613         /* !fi == the top most container node which holds nothing */
3614         if (fi && !PROTO_ITEM_IS_HIDDEN(node) && fi->ds_tvb && offsearch->tvb == fi->ds_tvb) {
3615                 if (offsearch->offset >= (guint) fi->start &&
3616                                 offsearch->offset < (guint) (fi->start + fi->length)) {
3617
3618                         offsearch->finfo = fi;
3619                         return FALSE; /* keep traversing */
3620                 }
3621         }
3622         return FALSE; /* keep traversing */
3623 }
3624
3625 /* Search a proto_tree backwards (from leaves to root) looking for the field
3626  * whose start/length occupies 'offset' */
3627 /* XXX - I couldn't find an easy way to search backwards, so I search
3628  * forwards, w/o stopping. Therefore, the last finfo I find will the be
3629  * the one I want to return to the user. This algorithm is inefficient
3630  * and could be re-done, but I'd have to handle all the children and
3631  * siblings of each node myself. When I have more time I'll do that.
3632  * (yeah right) */
3633 field_info*
3634 proto_find_field_from_offset(proto_tree *tree, guint offset, tvbuff_t *tvb)
3635 {
3636         offset_search_t         offsearch;
3637
3638         offsearch.offset = offset;
3639         offsearch.finfo = NULL;
3640         offsearch.tvb = tvb;
3641
3642         proto_tree_traverse_pre_order(tree, check_for_offset, &offsearch);
3643
3644         return offsearch.finfo;
3645 }
3646
3647 /* Dumps the protocols in the registration database to stdout.  An independent
3648  * program can take this output and format it into nice tables or HTML or
3649  * whatever.
3650  *
3651  * There is one record per line. The fields are tab-delimited.
3652  *
3653  * Field 1 = protocol name
3654  * Field 2 = protocol short name
3655  * Field 3 = protocol filter name
3656  */
3657 void
3658 proto_registrar_dump_protocols(void)
3659 {
3660         protocol_t              *protocol;
3661         int                     i;
3662         void                    *cookie;
3663
3664         for (i = proto_get_first_protocol(&cookie); i != -1;
3665             i = proto_get_next_protocol(&cookie)) {
3666                 protocol = find_protocol_by_id(i);
3667                 printf("%s\t%s\t%s\n", protocol->name, protocol->short_name,
3668                     protocol->filter_name);
3669         }
3670 }
3671
3672 /* Dumps the value_string and true/false strings for fields that have
3673  * them. There is one record per line. Fields are tab-delimited.
3674  * There are two types of records, Value String records and True/False
3675  * String records. The first field, 'V' or 'T', indicates the type
3676  * of record.
3677  *
3678  * Value Strings
3679  * -------------
3680  * Field 1 = 'V'
3681  * Field 2 = field abbreviation to which this value string corresponds
3682  * Field 3 = Integer value
3683  * Field 4 = String
3684  *
3685  * True/False Strings
3686  * ------------------
3687  * Field 1 = 'T'
3688  * Field 2 = field abbreviation to which this true/false string corresponds
3689  * Field 3 = True String
3690  * Field 4 = False String
3691  */
3692 void
3693 proto_registrar_dump_values(void)
3694 {
3695         header_field_info       *hfinfo, *parent_hfinfo;
3696         int                     i, len, vi;
3697         const value_string      *vals;
3698         const true_false_string *tfs;
3699
3700         len = gpa_hfinfo.len;
3701         for (i = 0; i < len ; i++) {
3702                 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
3703
3704                  if (hfinfo->id == hf_text_only) {
3705                          continue;
3706                  }
3707
3708                 /* ignore protocols */
3709                 if (proto_registrar_is_protocol(i)) {
3710                         continue;
3711                 }
3712                 /* process header fields */
3713                 else {
3714                         /*
3715                          * If this field isn't at the head of the list of
3716                          * fields with this name, skip this field - all
3717                          * fields with the same name are really just versions
3718                          * of the same field stored in different bits, and
3719                          * should have the same type/radix/value list, and
3720                          * just differ in their bit masks.  (If a field isn't
3721                          * a bitfield, but can be, say, 1 or 2 bytes long,
3722                          * it can just be made FT_UINT16, meaning the
3723                          * *maximum* length is 2 bytes, and be used
3724                          * for all lengths.)
3725                          */
3726                         if (hfinfo->same_name_prev != NULL)
3727                                 continue;
3728
3729                         PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
3730
3731                         vals = NULL;
3732                         tfs = NULL;
3733
3734                         if (hfinfo->type == FT_UINT8 ||
3735                                 hfinfo->type == FT_UINT16 ||
3736                                 hfinfo->type == FT_UINT24 ||
3737                                 hfinfo->type == FT_UINT32 ||
3738                                 hfinfo->type == FT_UINT64 ||
3739                                 hfinfo->type == FT_INT8 ||
3740                                 hfinfo->type == FT_INT16 ||
3741                                 hfinfo->type == FT_INT24 ||
3742                                 hfinfo->type == FT_INT32 ||
3743                                 hfinfo->type == FT_INT64) {
3744
3745                                 vals = hfinfo->strings;
3746                         }
3747                         else if (hfinfo->type == FT_BOOLEAN) {
3748                                 tfs = hfinfo->strings;
3749                         }
3750
3751                         /* Print value strings? */
3752                         if (vals) {
3753                                 vi = 0;
3754                                 while (vals[vi].strptr) {
3755                                         /* Print in the proper base */
3756                                         if (hfinfo->display == BASE_HEX) {
3757                                                 printf("V\t%s\t0x%x\t%s\n",
3758                                                                 hfinfo->abbrev,
3759                                                                 vals[vi].value,
3760                                                                 vals[vi].strptr);
3761                                         }
3762                                         else {
3763                                                 printf("V\t%s\t%u\t%s\n",
3764                                                                 hfinfo->abbrev,
3765                                                                 vals[vi].value,
3766                                                                 vals[vi].strptr);
3767                                         }
3768                                         vi++;
3769                                 }
3770                         }
3771
3772                         /* Print true/false strings? */
3773                         else if (tfs) {
3774                                 printf("T\t%s\t%s\t%s\n", hfinfo->abbrev,
3775                                                 tfs->true_string, tfs->false_string);
3776                         }
3777                 }
3778         }
3779 }
3780
3781 /* Dumps the contents of the registration database to stdout. An indepedent
3782  * program can take this output and format it into nice tables or HTML or
3783  * whatever.
3784  *
3785  * There is one record per line. Each record is either a protocol or a header
3786  * field, differentiated by the first field. The fields are tab-delimited.
3787  *
3788  * Protocols
3789  * ---------
3790  * Field 1 = 'P'
3791  * Field 2 = descriptive protocol name
3792  * Field 3 = protocol abbreviation
3793  *
3794  * Header Fields
3795  * -------------
3796  * (format 1)
3797  * Field 1 = 'F'
3798  * Field 2 = descriptive field name
3799  * Field 3 = field abbreviation
3800  * Field 4 = type ( textual representation of the the ftenum type )
3801  * Field 5 = parent protocol abbreviation
3802  *
3803  * (format 2 adds these fields:)
3804  * Field 6 = base for display (for integer types)
3805  * Field 7 = blurb describing field
3806  */
3807 void
3808 proto_registrar_dump_fields(int format)
3809 {
3810         header_field_info       *hfinfo, *parent_hfinfo;
3811         int                     i, len;
3812         const char              *enum_name;
3813         const char              *base_name;
3814
3815         len = gpa_hfinfo.len;
3816         for (i = 0; i < len ; i++) {
3817                 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
3818
3819                 /*
3820                  * Skip fields with zero-length names or abbreviations;
3821                  * the pseudo-field for "proto_tree_add_text()" is such
3822                  * a field, and we don't want it in the list of filterable
3823                  * fields.
3824                  *
3825                  *
3826                  * XXX - perhaps the name and abbrev field should be null
3827                  * pointers rather than null strings for that pseudo-field,
3828                  * but we'd have to add checks for null pointers in some
3829                  * places if we did that.
3830                  *
3831                  * Or perhaps protocol tree items added with
3832                  * "proto_tree_add_text()" should have -1 as the field index,
3833                  * with no pseudo-field being used, but that might also
3834                  * require special checks for -1 to be added.
3835                  */
3836                 /* XXX - we could just skip the special text
3837                  * pseudo-field by testing: if (hfinfo->id == hf_text_only)
3838                  * */
3839                 if (hfinfo->name[0] == 0 || hfinfo->abbrev[0] == 0)
3840                         continue;
3841
3842                 /* format for protocols */
3843                 if (proto_registrar_is_protocol(i)) {
3844                         printf("P\t%s\t%s\n", hfinfo->name, hfinfo->abbrev);
3845                 }
3846                 /* format for header fields */
3847                 else {
3848                         /*
3849                          * If this field isn't at the head of the list of
3850                          * fields with this name, skip this field - all
3851                          * fields with the same name are really just versions
3852                          * of the same field stored in different bits, and
3853                          * should have the same type/radix/value list, and
3854                          * just differ in their bit masks.  (If a field isn't
3855                          * a bitfield, but can be, say, 1 or 2 bytes long,
3856                          * it can just be made FT_UINT16, meaning the
3857                          * *maximum* length is 2 bytes, and be used
3858                          * for all lengths.)
3859                          */
3860                         if (hfinfo->same_name_prev != NULL)
3861                                 continue;
3862
3863                         PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
3864
3865                         enum_name = ftype_name(hfinfo->type);
3866                         base_name = "";
3867
3868                         if (format > 1) {
3869                                 if (hfinfo->type == FT_UINT8 ||
3870                                         hfinfo->type == FT_UINT16 ||
3871                                         hfinfo->type == FT_UINT24 ||
3872                                         hfinfo->type == FT_UINT32 ||
3873                                         hfinfo->type == FT_UINT64 ||
3874                                         hfinfo->type == FT_INT8 ||
3875                                         hfinfo->type == FT_INT16 ||
3876                                         hfinfo->type == FT_INT24 ||
3877                                         hfinfo->type == FT_INT32 ||
3878                                         hfinfo->type == FT_INT64) {
3879
3880                                         
3881                                         switch(hfinfo->display) {
3882                                                 case BASE_NONE:
3883                                                         base_name = "BASE_NONE";
3884                                                         break;
3885                                                 case BASE_DEC:
3886                                                         base_name = "BASE_DEC";
3887                                                         break;
3888                                                 case BASE_HEX:
3889                                                         base_name = "BASE_HEX";
3890                                                         break;
3891                                                 case BASE_OCT:
3892                                                         base_name = "BASE_OCT";
3893                                                         break;
3894                                         }
3895                                 }
3896                         }
3897
3898                         if (format == 1) {
3899                                 printf("F\t%s\t%s\t%s\t%s\t%s\n", hfinfo->name, hfinfo->abbrev,
3900                                         enum_name,parent_hfinfo->abbrev, hfinfo->blurb);
3901                         }
3902                         else if (format == 2) {
3903                                 printf("F\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n",
3904                                         hfinfo->name, hfinfo->abbrev,
3905                                         enum_name,parent_hfinfo->abbrev, hfinfo->blurb,
3906                                         base_name, hfinfo->blurb);
3907                         }
3908                 }
3909         }
3910 }
3911
3912 static char*
3913 hfinfo_numeric_format(header_field_info *hfinfo)
3914 {
3915         char *format = NULL;
3916
3917         /* Pick the proper format string */
3918         if (hfinfo->type == FT_FRAMENUM) {
3919                 /*
3920                  * Frame numbers are always displayed in decimal.
3921                  */
3922                 format = "%s == %u";
3923         } else {
3924                 /* Pick the proper format string */
3925                 switch(hfinfo->display) {
3926                         case BASE_DEC:
3927                         case BASE_OCT: /* I'm lazy */
3928                                 switch(hfinfo->type) {
3929                                         case FT_UINT8:
3930                                         case FT_UINT16:
3931                                         case FT_UINT24:
3932                                         case FT_UINT32:
3933                                                 format = "%s == %u";
3934                                                 break;
3935                                         case FT_UINT64:
3936                                                 format = "%s == %" PRIu64;
3937                                                 break;
3938                                         case FT_INT8:
3939                                         case FT_INT16:
3940                                         case FT_INT24:
3941                                         case FT_INT32:
3942                                                 format = "%s == %d";
3943                                                 break;
3944                                         case FT_INT64:
3945                                                 format = "%s == %" PRId64;
3946                                                 break;
3947                                         default:
3948                                                 DISSECTOR_ASSERT_NOT_REACHED();
3949                                                 ;
3950                                 }
3951                                 break;
3952                         case BASE_HEX:
3953                                 switch(hfinfo->type) {
3954                                         case FT_UINT8:
3955                                                 format = "%s == 0x%02x";
3956                                                 break;
3957                                         case FT_UINT16:
3958                                                 format = "%s == 0x%04x";
3959                                                 break;
3960                                         case FT_UINT24:
3961                                                 format = "%s == 0x%06x";
3962                                                 break;
3963                                         case FT_UINT32:
3964                                                 format = "%s == 0x%08x";
3965                                                 break;
3966                                         case FT_UINT64:
3967                                                 format = "%s == 0x%016" PRIx64;
3968                                                 break;
3969                                         default:
3970                                                 DISSECTOR_ASSERT_NOT_REACHED();
3971                                                 ;
3972                                 }
3973                                 break;
3974                         default:
3975                                 DISSECTOR_ASSERT_NOT_REACHED();
3976                                 ;
3977                 }
3978         }
3979         return format;
3980 }
3981
3982 /*
3983  * Returns TRUE if we can do a "match selected" on the field, FALSE
3984  * otherwise.
3985  */
3986 gboolean
3987 proto_can_match_selected(field_info *finfo, epan_dissect_t *edt)
3988 {
3989         header_field_info       *hfinfo;
3990         gint                    length;
3991
3992         hfinfo = finfo->hfinfo;
3993         DISSECTOR_ASSERT(hfinfo);
3994
3995         switch(hfinfo->type) {
3996
3997                 case FT_BOOLEAN:
3998                 case FT_UINT8:
3999                 case FT_UINT16:
4000                 case FT_UINT24:
4001                 case FT_UINT32:
4002                 case FT_INT8:
4003                 case FT_INT16:
4004                 case FT_INT24:
4005                 case FT_INT32:
4006                 case FT_FRAMENUM:
4007                 case FT_UINT64:
4008                 case FT_INT64:
4009                 case FT_IPv4:
4010                 case FT_IPXNET:
4011                 case FT_IPv6:
4012                 case FT_FLOAT:
4013                 case FT_DOUBLE:
4014                 case FT_ABSOLUTE_TIME:
4015                 case FT_RELATIVE_TIME:
4016                 case FT_STRING:
4017                 case FT_STRINGZ:
4018                 case FT_UINT_STRING:
4019                 case FT_ETHER:
4020                 case FT_BYTES:
4021                 case FT_UINT_BYTES:
4022                 case FT_PROTOCOL:
4023                         /*
4024                          * These all have values, so we can match.
4025                          */
4026                         return TRUE;
4027
4028                 default:
4029                         /*
4030                          * This doesn't have a value, so we'd match
4031                          * on the raw bytes at this address.
4032                          *
4033                          * Should we be allowed to access to the raw bytes?
4034                          * If "edt" is NULL, the answer is "no".
4035                          */
4036                         if (edt == NULL)
4037                                 return FALSE;
4038
4039                         /*
4040                          * Is this field part of the raw frame tvbuff?
4041                          * If not, we can't use "frame[N:M]" to match
4042                          * it.
4043                          *
4044                          * XXX - should this be frame-relative, or
4045                          * protocol-relative?
4046                          *
4047                          * XXX - does this fallback for non-registered
4048                          * fields even make sense?
4049                          */
4050                         if (finfo->ds_tvb != edt->tvb)
4051                                 return FALSE;
4052
4053                         /*
4054                          * If the length is 0, there's nothing to match, so
4055                          * we can't match.  (Also check for negative values,
4056                          * just in case, as we'll cast it to an unsigned
4057                          * value later.)
4058                          */
4059                         length = finfo->length;
4060                         if (length <= 0)
4061                                 return FALSE;
4062
4063                         /*
4064                          * Don't go past the end of that tvbuff.
4065                          */
4066                         if ((guint)length > tvb_length(finfo->ds_tvb))
4067                                 length = tvb_length(finfo->ds_tvb);
4068                         if (length <= 0)
4069                                 return FALSE;
4070                         return TRUE;
4071         }
4072 }
4073
4074 char*
4075 proto_construct_dfilter_string(field_info *finfo, epan_dissect_t *edt)
4076 {
4077         header_field_info       *hfinfo;
4078         int                     abbrev_len;
4079         char                    *buf, *stringified, *format, *ptr;
4080         int                     dfilter_len, i;
4081         gint                    start, length, length_remaining;
4082         guint8                  c;
4083
4084         hfinfo = finfo->hfinfo;
4085         DISSECTOR_ASSERT(hfinfo);
4086         abbrev_len = strlen(hfinfo->abbrev);
4087
4088         /*
4089          * XXX - we should add "val_to_string_repr" and "string_repr_len"
4090          * functions for more types, and use them whenever possible.
4091          *
4092          * The FT_UINT and FT_INT types are the only tricky ones, as
4093          * we choose the base in the string expression based on the
4094          * display base of the field.
4095          *
4096          * Note that the base does matter, as this is also used for
4097          * the protocolinfo tap.
4098          *
4099          * It might be nice to use that in "proto_item_fill_label()"
4100          * as well, although, there, you'd have to deal with the base
4101          * *and* with resolved values for addresses.
4102          *
4103          * Perhaps we need two different val_to_string routines, one
4104          * to generate items for display filters and one to generate
4105          * strings for display, and pass to both of them the
4106          * "display" and "strings" values in the header_field_info
4107          * structure for the field, so they can get the base and,
4108          * if the field is Boolean or an enumerated integer type,
4109          * the tables used to generate human-readable values.
4110          */
4111         switch(hfinfo->type) {
4112
4113                 case FT_UINT8:
4114                 case FT_UINT16:
4115                 case FT_UINT24:
4116                 case FT_UINT32:
4117                 case FT_INT8:
4118                 case FT_INT16:
4119                 case FT_INT24:
4120                 case FT_INT32:
4121                 case FT_FRAMENUM:
4122                         /*
4123                          * 4 bytes for " == ".
4124                          * 11 bytes for:
4125                          *
4126                          *      a sign + up to 10 digits of 32-bit integer,
4127                          *      in decimal;
4128                          *
4129                          *      "0x" + 8 digits of 32-bit integer, in hex;
4130                          *
4131                          *      11 digits of 32-bit integer, in octal.
4132                          *      (No, we don't do octal, but this way,
4133                          *      we know that if we do, this will still
4134                          *      work.)
4135                          *
4136                          * 1 byte for the trailing '\0'.
4137                          */
4138                         dfilter_len = abbrev_len + 4 + 11 + 1;
4139                         buf = g_malloc0(dfilter_len);
4140                         format = hfinfo_numeric_format(hfinfo);
4141                         snprintf(buf, dfilter_len, format, hfinfo->abbrev, fvalue_get_integer(&finfo->value));
4142                         break;
4143
4144                 case FT_INT64:
4145                 case FT_UINT64:
4146                         /*
4147                          * 4 bytes for " == ".
4148                          * 22 bytes for:
4149                          *
4150                          *      a sign + up to 20 digits of 32-bit integer,
4151                          *      in decimal;
4152                          *
4153                          *      "0x" + 16 digits of 32-bit integer, in hex;
4154                          *
4155                          *      22 digits of 32-bit integer, in octal.
4156                          *      (No, we don't do octal, but this way,
4157                          *      we know that if we do, this will still
4158                          *      work.)
4159                          *
4160                          * 1 byte for the trailing '\0'.
4161                          */
4162                         dfilter_len = abbrev_len + 4 + 22 + 1;
4163                         buf = g_malloc0(dfilter_len);
4164                         format = hfinfo_numeric_format(hfinfo);
4165                         snprintf(buf, dfilter_len, format, hfinfo->abbrev, fvalue_get_integer64(&finfo->value));
4166                         break;
4167
4168                 case FT_IPXNET:
4169                         /*
4170                          * 4 bytes for " == ".
4171                          * 2 bytes for "0x".
4172                          * 8 bytes for 8 digits of 32-bit hex number.
4173                          * 1 byte for the trailing '\0'.
4174                          */
4175                         dfilter_len = abbrev_len + 4 + 2 + 8 + 1;
4176                         buf = g_malloc0(dfilter_len);
4177                         snprintf(buf, dfilter_len, "%s == 0x%08x", hfinfo->abbrev,
4178                                         fvalue_get_integer(&finfo->value));
4179                         break;
4180
4181                 case FT_IPv6:
4182                         /*
4183                          * 4 bytes for " == ".
4184                          * N bytes for the string for the address.
4185                          * 1 byte for the trailing '\0'.
4186                          */
4187                         stringified = ip6_to_str((struct e_in6_addr*) fvalue_get(&finfo->value));
4188                         dfilter_len = abbrev_len + 4 + strlen(stringified) + 1;
4189                         buf = g_malloc0(dfilter_len);
4190                         snprintf(buf, dfilter_len, "%s == %s", hfinfo->abbrev,
4191                                         stringified);
4192                         break;
4193
4194                 /* These use the fvalue's "to_string_repr" method. */
4195                 case FT_BOOLEAN:
4196                 case FT_STRING:
4197                 case FT_ETHER:
4198                 case FT_BYTES:
4199                 case FT_UINT_BYTES:
4200                 case FT_FLOAT:
4201                 case FT_DOUBLE:
4202                 case FT_ABSOLUTE_TIME:
4203                 case FT_RELATIVE_TIME:
4204                 case FT_IPv4:
4205                         /* Figure out the string length needed.
4206                          *      The ft_repr length.
4207                          *      4 bytes for " == ".
4208                          *      1 byte for trailing NUL.
4209                          */
4210                         dfilter_len = fvalue_string_repr_len(&finfo->value,
4211                                         FTREPR_DFILTER);
4212                         dfilter_len += abbrev_len + 4 + 1;
4213                         buf = g_malloc0(dfilter_len);
4214
4215                         /* Create the string */
4216                         snprintf(buf, dfilter_len, "%s == ", hfinfo->abbrev);
4217                         fvalue_to_string_repr(&finfo->value,
4218                                         FTREPR_DFILTER,
4219                                         &buf[abbrev_len + 4]);
4220                         break;
4221
4222                 case FT_PROTOCOL:
4223                         buf = g_strdup(finfo->hfinfo->abbrev);
4224                         break;
4225
4226                 default:
4227                         /*
4228                          * This doesn't have a value, so we'd match
4229                          * on the raw bytes at this address.
4230                          *
4231                          * Should we be allowed to access to the raw bytes?
4232                          * If "edt" is NULL, the answer is "no".
4233                          */
4234                         if (edt == NULL)
4235                                 return FALSE;
4236
4237                         /*
4238                          * Is this field part of the raw frame tvbuff?
4239                          * If not, we can't use "frame[N:M]" to match
4240                          * it.
4241                          *
4242                          * XXX - should this be frame-relative, or
4243                          * protocol-relative?
4244                          *
4245                          * XXX - does this fallback for non-registered
4246                          * fields even make sense?
4247                          */
4248                         if (finfo->ds_tvb != edt->tvb)
4249                                 return NULL;    /* you lose */
4250
4251                         /*
4252                          * If the length is 0, there's nothing to match, so
4253                          * we can't match.  (Also check for negative values,
4254                          * just in case, as we'll cast it to an unsigned
4255                          * value later.)
4256                          */
4257                         length = finfo->length;
4258                         if (length <= 0)
4259                                 return NULL;
4260
4261                         /*
4262                          * Don't go past the end of that tvbuff.
4263                          */
4264                         length_remaining = tvb_length_remaining(finfo->ds_tvb, finfo->start);
4265                         if (length > length_remaining)
4266                                 length = length_remaining;
4267                         if (length <= 0)
4268                                 return NULL;
4269                         
4270                         start = finfo->start;
4271                         buf = g_malloc0(32 + length * 3);
4272                         ptr = buf;
4273
4274                         sprintf(ptr, "frame[%d:%d] == ", finfo->start, length);
4275                         ptr = buf+strlen(buf);
4276
4277                         for (i=0;i<length; i++) {
4278                                 c = tvb_get_guint8(finfo->ds_tvb, start);
4279                                 start++;
4280                                 if (i == 0 ) {
4281                                         sprintf(ptr, "%02x", c);
4282                                 }
4283                                 else {
4284                                         sprintf(ptr, ":%02x", c);
4285                                 }
4286                                 ptr = buf+strlen(buf);
4287                         }
4288                         break;
4289         }
4290
4291         return buf;
4292 }