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