Have separate proto_construct_match_selected_string() and
[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 /* Throw an exception if we exceed this many tree items. */
2647 /* XXX - This should probably be a preference */
2648 #define MAX_TREE_ITEMS (1 * 1000 * 1000)
2649 /* Add a field_info struct to the proto_tree, encapsulating it in a proto_node */
2650 static proto_item *
2651 proto_tree_add_node(proto_tree *tree, field_info *fi)
2652 {
2653         proto_node *pnode, *tnode, *sibling;
2654         field_info *tfi;
2655
2656         /*
2657          * Make sure "tree" is ready to have subtrees under it, by
2658          * checking whether it's been given an ett_ value.
2659          *
2660          * "tnode->finfo" may be null; that's the case for the root
2661          * node of the protocol tree.  That node is not displayed,
2662          * so it doesn't need an ett_ value to remember whether it
2663          * was expanded.
2664          */
2665         tnode = tree;
2666         tfi = tnode->finfo;
2667         if (tfi != NULL && (tfi->tree_type < 0 || tfi->tree_type >= num_tree_types)) {
2668                 REPORT_DISSECTOR_BUG(ep_strdup_printf("\"%s\" - \"%s\" tfi->tree_type: %u invalid (%s:%u)",
2669                         fi->hfinfo->name, fi->hfinfo->abbrev, tfi->tree_type, __FILE__, __LINE__));
2670                 /* XXX - is it safe to continue here? */
2671         }
2672
2673         DISSECTOR_ASSERT(tfi == NULL ||
2674             (tfi->tree_type >= 0 && tfi->tree_type < num_tree_types));
2675
2676         PTREE_DATA(tree)->count++;
2677         if (PTREE_DATA(tree)->count > MAX_TREE_ITEMS) {
2678                 /* Let the exception handler add items to the tree */
2679                 PTREE_DATA(tree)->count = 0;
2680                 THROW_MESSAGE(DissectorError,
2681                         ep_strdup_printf("More than %d items in the tree -- possible infinite loop", MAX_TREE_ITEMS));
2682         }
2683
2684         PROTO_NODE_NEW(pnode);
2685         pnode->parent = tnode;
2686         pnode->finfo = fi;
2687         pnode->tree_data = PTREE_DATA(tree);
2688
2689         if (tnode->last_child != NULL) {
2690                 sibling = tnode->last_child;
2691                 DISSECTOR_ASSERT(sibling->next == NULL);
2692                 sibling->next = pnode;
2693         } else
2694                 tnode->first_child = pnode;
2695         tnode->last_child = pnode;
2696
2697         return (proto_item*)pnode;
2698 }
2699
2700
2701 /* Generic way to allocate field_info and add to proto_tree.
2702  * Sets *pfi to address of newly-allocated field_info struct, if pfi is
2703  * non-NULL. */
2704 static proto_item *
2705 proto_tree_add_pi(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2706     gint *length, field_info **pfi)
2707 {
2708         proto_item      *pi;
2709         field_info      *fi;
2710         GHashTable      *hash;
2711         GPtrArray       *ptrs;
2712
2713         if (!tree)
2714                 return(NULL);
2715
2716         fi = alloc_field_info(tree, hfindex, tvb, start, length);
2717         pi = proto_tree_add_node(tree, fi);
2718
2719         /* If the proto_tree wants to keep a record of this finfo
2720          * for quick lookup, then record it. */
2721         if (fi->hfinfo->ref_count) {
2722                 /*HERE*/
2723                 hash = PTREE_DATA(tree)->interesting_hfids;
2724                 ptrs = g_hash_table_lookup(hash, GINT_TO_POINTER(hfindex));
2725                 if (ptrs) {
2726                         g_ptr_array_add(ptrs, fi);
2727                 }
2728         }
2729
2730         /* Does the caller want to know the fi pointer? */
2731         if (pfi) {
2732                 *pfi = fi;
2733         }
2734
2735         return pi;
2736 }
2737
2738
2739 static header_field_info *
2740 get_hfi_and_length(int hfindex, tvbuff_t *tvb, gint start, gint *length,
2741     gint *item_length)
2742 {
2743         header_field_info       *hfinfo;
2744         gint                    length_remaining;
2745
2746         /*
2747          * We only allow a null tvbuff if the item has a zero length,
2748          * i.e. if there's no data backing it.
2749          */
2750         DISSECTOR_ASSERT(tvb != NULL || *length == 0);
2751
2752         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2753
2754         /*
2755          * XXX - in some protocols, there are 32-bit unsigned length
2756          * fields, so lengths in protocol tree and tvbuff routines
2757          * should really be unsigned.  We should have, for those
2758          * field types for which "to the end of the tvbuff" makes sense,
2759          * additional routines that take no length argument and
2760          * add fields that run to the end of the tvbuff.
2761          */
2762         if (*length == -1) {
2763                 /*
2764                  * For FT_NONE, FT_PROTOCOL, FT_BYTES, and FT_STRING fields,
2765                  * a length of -1 means "set the length to what remains in
2766                  * the tvbuff".
2767                  *
2768                  * The assumption is either that
2769                  *
2770                  *      1) the length of the item can only be determined
2771                  *         by dissection (typically true of items with
2772                  *         subitems, which are probably FT_NONE or
2773                  *         FT_PROTOCOL)
2774                  *
2775                  * or
2776                  *
2777                  *      2) if the tvbuff is "short" (either due to a short
2778                  *         snapshot length or due to lack of reassembly of
2779                  *         fragments/segments/whatever), we want to display
2780                  *         what's available in the field (probably FT_BYTES
2781                  *         or FT_STRING) and then throw an exception later
2782                  *
2783                  * or
2784                  *
2785                  *      3) the field is defined to be "what's left in the
2786                  *         packet"
2787                  *
2788                  * so we set the length to what remains in the tvbuff so
2789                  * that, if we throw an exception while dissecting, it
2790                  * has what is probably the right value.
2791                  *
2792                  * For FT_STRINGZ, it means "the string is null-terminated,
2793                  * not null-padded; set the length to the actual length
2794                  * of the string", and if the tvbuff if short, we just
2795                  * throw an exception.
2796                  *
2797                  * It's not valid for any other type of field.
2798                  */
2799                 switch (hfinfo->type) {
2800
2801                 case FT_PROTOCOL:
2802                         /*
2803                          * We allow this to be zero-length - for
2804                          * example, an ONC RPC NULL procedure has
2805                          * neither arguments nor reply, so the
2806                          * payload for that protocol is empty.
2807                          *
2808                          * However, if the length is negative, the
2809                          * start offset is *past* the byte past the
2810                          * end of the tvbuff, so we throw an
2811                          * exception.
2812                          */
2813                         *length = tvb_length_remaining(tvb, start);
2814                         if (*length < 0) {
2815                                 /*
2816                                  * Use "tvb_ensure_bytes_exist()"
2817                                  * to force the appropriate exception
2818                                  * to be thrown.
2819                                  */
2820                                 tvb_ensure_bytes_exist(tvb, start, 0);
2821                         }
2822                         DISSECTOR_ASSERT(*length >= 0);
2823                         break;
2824
2825                 case FT_NONE:
2826                 case FT_BYTES:
2827                 case FT_STRING:
2828                         *length = tvb_ensure_length_remaining(tvb, start);
2829                         DISSECTOR_ASSERT(*length >= 0);
2830                         break;
2831
2832                 case FT_STRINGZ:
2833                         /*
2834                          * Leave the length as -1, so our caller knows
2835                          * it was -1.
2836                          */
2837                         break;
2838
2839                 default:
2840                         DISSECTOR_ASSERT_NOT_REACHED();
2841                 }
2842                 *item_length = *length;
2843         } else {
2844                 *item_length = *length;
2845                 if (hfinfo->type == FT_PROTOCOL || hfinfo->type == FT_NONE) {
2846                         /*
2847                          * These types are for interior nodes of the
2848                          * tree, and don't have data associated with
2849                          * them; if the length is negative (XXX - see
2850                          * above) or goes past the end of the tvbuff,
2851                          * cut it short at the end of the tvbuff.
2852                          * That way, if this field is selected in
2853                          * Wireshark, we don't highlight stuff past
2854                          * the end of the data.
2855                          */
2856                         /* XXX - what to do, if we don't have a tvb? */
2857                         if (tvb) {
2858                                 length_remaining = tvb_length_remaining(tvb, start);
2859                                 if (*item_length < 0 ||
2860                                     (*item_length > 0 &&
2861                                       (length_remaining < *item_length)))
2862                                         *item_length = length_remaining;
2863                         }
2864                 }
2865                 if (*item_length < 0) {
2866                         THROW(ReportedBoundsError);
2867                 }
2868         }
2869
2870         return hfinfo;
2871 }
2872
2873 static field_info *
2874 new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
2875     gint start, gint item_length)
2876 {
2877         field_info              *fi;
2878
2879         FIELD_INFO_NEW(fi);
2880
2881         fi->hfinfo = hfinfo;
2882         fi->start = start;
2883         fi->start+=(tvb)?TVB_RAW_OFFSET(tvb):0;
2884         fi->length = item_length;
2885         fi->tree_type = -1;
2886         fi->flags = 0;
2887         if (!PTREE_DATA(tree)->visible)
2888                 FI_SET_FLAG(fi, FI_HIDDEN);
2889         fvalue_init(&fi->value, fi->hfinfo->type);
2890         fi->rep = NULL;
2891
2892         /* add the data source tvbuff */
2893         fi->ds_tvb=tvb?TVB_GET_DS_TVB(tvb):NULL;
2894
2895         return fi;
2896 }
2897
2898 static field_info *
2899 alloc_field_info(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2900     gint *length)
2901 {
2902         header_field_info       *hfinfo;
2903         gint                    item_length;
2904
2905         hfinfo = get_hfi_and_length(hfindex, tvb, start, length, &item_length);
2906         return new_field_info(tree, hfinfo, tvb, start, item_length);
2907 }
2908
2909 /* If the protocol tree is to be visible, set the representation of a
2910    proto_tree entry with the name of the field for the item and with
2911    the value formatted with the supplied printf-style format and
2912    argument list. */
2913 static void
2914 proto_tree_set_representation_value(proto_item *pi, const char *format, va_list ap)
2915 {
2916         int     ret;    /*tmp return value */
2917         int     replen;
2918         field_info *fi = PITEM_FINFO(pi);
2919
2920         if (!PROTO_ITEM_IS_HIDDEN(pi)) {
2921                 ITEM_LABEL_NEW(fi->rep);
2922                 replen = 0;
2923                 ret = g_snprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
2924                     "%s: ", fi->hfinfo->name);
2925                 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH)) {
2926                         /* That's all we can put in the representation. */
2927                         fi->rep->representation[ITEM_LABEL_LENGTH - 1] = '\0';
2928                         return;
2929                 }
2930                 replen = ret;
2931                 ret = g_vsnprintf(fi->rep->representation + replen,
2932                     ITEM_LABEL_LENGTH - replen, format, ap);
2933                 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH - replen))
2934                         fi->rep->representation[ITEM_LABEL_LENGTH - 1] = '\0';
2935         }
2936 }
2937
2938 /* If the protocol tree is to be visible, set the representation of a
2939    proto_tree entry with the representation formatted with the supplied
2940    printf-style format and argument list. */
2941 static void
2942 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap)
2943 {
2944         int                                     ret;    /*tmp return value */
2945         field_info *fi = PITEM_FINFO(pi);
2946
2947         if (!PROTO_ITEM_IS_HIDDEN(pi)) {
2948                 ITEM_LABEL_NEW(fi->rep);
2949                 ret = g_vsnprintf(fi->rep->representation, ITEM_LABEL_LENGTH, format, ap);
2950                 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
2951                         fi->rep->representation[ITEM_LABEL_LENGTH - 1] = '\0';
2952         }
2953 }
2954
2955 /* Set text of proto_item after having already been created. */
2956 void
2957 proto_item_set_text(proto_item *pi, const char *format, ...)
2958 {
2959         field_info *fi = NULL;
2960         va_list ap;
2961
2962         if (pi==NULL) {
2963                 return;
2964         }
2965
2966         fi = PITEM_FINFO(pi);
2967
2968         if(fi->rep){
2969                 ITEM_LABEL_FREE(fi->rep);
2970         }
2971
2972         va_start(ap, format);
2973         proto_tree_set_representation(pi, format, ap);
2974         va_end(ap);
2975 }
2976
2977 /* Append to text of proto_item after having already been created. */
2978 void
2979 proto_item_append_text(proto_item *pi, const char *format, ...)
2980 {
2981         field_info *fi = NULL;
2982         size_t curlen;
2983         va_list ap;
2984         int                                     ret;    /*tmp return value */
2985
2986         if (pi==NULL) {
2987                 return;
2988         }
2989
2990         fi = PITEM_FINFO(pi);
2991
2992         if (!PROTO_ITEM_IS_HIDDEN(pi)) {
2993                 va_start(ap, format);
2994
2995                 /*
2996                  * If we don't already have a representation,
2997                  * generate the default representation.
2998                  */
2999                 if (fi->rep == NULL) {
3000                         ITEM_LABEL_NEW(fi->rep);
3001                         proto_item_fill_label(fi, fi->rep->representation);
3002                 }
3003
3004                 curlen = strlen(fi->rep->representation);
3005                 if (ITEM_LABEL_LENGTH > curlen) {
3006                         ret = g_vsnprintf(fi->rep->representation + curlen,
3007                             ITEM_LABEL_LENGTH - curlen, format, ap);
3008                         if ((ret == -1) || (ret >= (int)(ITEM_LABEL_LENGTH - curlen)))
3009                                 fi->rep->representation[ITEM_LABEL_LENGTH - 1] = '\0';
3010                 }
3011                 va_end(ap);
3012         }
3013 }
3014
3015 void
3016 proto_item_set_len(proto_item *pi, gint length)
3017 {
3018         field_info *fi;
3019
3020         if (pi == NULL)
3021                 return;
3022         fi = PITEM_FINFO(pi);
3023         DISSECTOR_ASSERT(length >= 0);
3024         fi->length = length;
3025 }
3026
3027 /*
3028  * Sets the length of the item based on its start and on the specified
3029  * offset, which is the offset past the end of the item; as the start
3030  * in the item is relative to the beginning of the data source tvbuff,
3031  * we need to pass in a tvbuff - the end offset is relative to the beginning
3032  * of that tvbuff.
3033  */
3034 void
3035 proto_item_set_end(proto_item *pi, tvbuff_t *tvb, gint end)
3036 {
3037         field_info *fi;
3038
3039         if (pi == NULL)
3040                 return;
3041         fi = PITEM_FINFO(pi);
3042         end += TVB_RAW_OFFSET(tvb);
3043         DISSECTOR_ASSERT(end >= fi->start);
3044         fi->length = end - fi->start;
3045 }
3046
3047 int
3048 proto_item_get_len(proto_item *pi)
3049 {
3050         field_info *fi = PITEM_FINFO(pi);
3051         return fi->length;
3052 }
3053
3054
3055 /** clear flags according to the mask and set new flag values */
3056 #define FI_REPLACE_FLAGS(fi, mask, flags_in) { \
3057         (fi->flags = (fi)->flags & ~(mask)); \
3058         (fi->flags = (fi)->flags | (flags_in)); \
3059 }
3060
3061 gboolean
3062 proto_item_set_expert_flags(proto_item *pi, int group, int severity)
3063 {
3064         if(pi == NULL || pi->finfo == NULL)
3065                 return FALSE;
3066
3067         /* only change things if severity is worse or at least equal than before */
3068         if(severity >= FI_GET_FLAG(pi->finfo, PI_SEVERITY_MASK)) {
3069                 FI_REPLACE_FLAGS(pi->finfo, PI_GROUP_MASK, group);
3070                 FI_REPLACE_FLAGS(pi->finfo, PI_SEVERITY_MASK, severity);
3071
3072                 return TRUE;
3073         }
3074
3075         return FALSE;
3076 }
3077
3078
3079
3080 proto_tree*
3081 proto_tree_create_root(void)
3082 {
3083         proto_node  *pnode;
3084
3085         /* Initialize the proto_node */
3086         PROTO_NODE_NEW(pnode);
3087         pnode->parent = NULL;
3088         pnode->finfo = NULL;
3089         pnode->tree_data = g_new(tree_data_t, 1);
3090
3091         /* Initialize the tree_data_t */
3092         pnode->tree_data->interesting_hfids =
3093             g_hash_table_new(g_direct_hash, g_direct_equal);
3094
3095         /* Set the default to FALSE so it's easier to
3096          * find errors; if we expect to see the protocol tree
3097          * but for some reason the default 'visible' is not
3098          * changed, then we'll find out very quickly. */
3099         pnode->tree_data->visible = FALSE;
3100
3101         /* Keep track of the number of children */
3102         pnode->tree_data->count = 0;
3103
3104         return (proto_tree*) pnode;
3105 }
3106
3107
3108 /* "prime" a proto_tree with a single hfid that a dfilter
3109  * is interested in. */
3110 void
3111 proto_tree_prime_hfid(proto_tree *tree, gint hfid)
3112 {
3113         header_field_info *hfinfo;
3114
3115         g_hash_table_insert(PTREE_DATA(tree)->interesting_hfids,
3116                 GINT_TO_POINTER(hfid), g_ptr_array_new());
3117
3118         PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
3119         /* this field is referenced by a filter so increase the refcount.
3120            also increase the refcount for the parent, i.e the protocol.
3121         */
3122         hfinfo->ref_count++;
3123         /* only increase the refcount if there is a parent.
3124            if this is a protocol and not a field then parent will be -1
3125            and there is no parent to add any refcounting for.
3126         */
3127         if (hfinfo->parent != -1) {
3128                 header_field_info *parent_hfinfo;
3129                 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
3130                 parent_hfinfo->ref_count++;
3131         }
3132 }
3133
3134 proto_tree*
3135 proto_item_add_subtree(proto_item *pi,  gint idx) {
3136         field_info *fi;
3137
3138         if (!pi)
3139                 return(NULL);
3140
3141         fi = PITEM_FINFO(pi);
3142         DISSECTOR_ASSERT(idx >= 0 && idx < num_tree_types);
3143         fi->tree_type = idx;
3144
3145         return (proto_tree*) pi;
3146 }
3147
3148 proto_tree*
3149 proto_item_get_subtree(proto_item *pi) {
3150         field_info *fi;
3151
3152         if (!pi)
3153                 return(NULL);
3154         fi = PITEM_FINFO(pi);
3155         if ( (!fi) || (fi->tree_type == -1) )
3156                 return(NULL);
3157         return (proto_tree*) pi;
3158 }
3159
3160 proto_item*
3161 proto_item_get_parent(proto_item *ti) {
3162         /* dont bother if tree is not visible */
3163         if( (!ti) || (!(PTREE_DATA(ti)->visible)) )
3164                 return (NULL);
3165         return ti->parent;
3166 }
3167
3168 proto_item*
3169 proto_item_get_parent_nth(proto_item *ti, int gen) {
3170         /* dont bother if tree is not visible */
3171         if( (!ti) || (!(PTREE_DATA(ti)->visible)) )
3172                 return (NULL);
3173         while (gen--) {
3174                 ti = ti->parent;
3175                 if (!ti)
3176                         return (NULL);
3177         }
3178         return ti;
3179 }
3180
3181
3182 proto_item*
3183 proto_tree_get_parent(proto_tree *tree) {
3184         /* dont bother if tree is not visible */
3185         if( (!tree) || (!(PTREE_DATA(tree)->visible)) )
3186                 return (NULL);
3187         return (proto_item*) tree;
3188 }
3189
3190 proto_tree*
3191 proto_tree_get_root(proto_tree *tree) {
3192         /* dont bother if tree is not visible */
3193         if( (!tree) || (!(PTREE_DATA(tree)->visible)) )
3194                 return (NULL);
3195         while (tree->parent) {
3196                 tree = tree->parent;
3197         }
3198         return tree;
3199 }
3200
3201 void
3202 proto_tree_move_item(proto_tree *tree, proto_item *fixed_item, proto_item *item_to_move)
3203 {
3204     proto_item *curr_item;
3205
3206
3207     /*** cut item_to_move out ***/
3208
3209     /* is item_to_move the first? */
3210     if(tree->first_child == item_to_move) {
3211         /* simply change first child to next */
3212         tree->first_child = item_to_move->next;
3213     } else {
3214         /* find previous and change it's next */
3215         for(curr_item = tree->first_child; curr_item != NULL; curr_item = curr_item->next) {
3216             if(curr_item->next == item_to_move) {
3217                 break;
3218             }
3219         }
3220
3221         DISSECTOR_ASSERT(curr_item);
3222
3223         curr_item->next = item_to_move->next;
3224
3225         /* fix last_child if required */
3226         if(tree->last_child == item_to_move) {
3227             tree->last_child = curr_item;
3228         }
3229     }
3230
3231     /*** insert to_move after fixed ***/
3232     item_to_move->next = fixed_item->next;
3233     fixed_item->next = item_to_move;
3234     if(tree->last_child == fixed_item) {
3235         tree->last_child = item_to_move;
3236     }
3237 }
3238
3239
3240 int
3241 proto_register_protocol(const char *name, const char *short_name, const char *filter_name)
3242 {
3243     protocol_t *protocol;
3244     header_field_info *hfinfo;
3245     int proto_id;
3246     char *existing_name;
3247     gint *key;
3248     guint i;
3249     guchar c;
3250     gboolean found_invalid;
3251
3252     /*
3253      * Make sure there's not already a protocol with any of those
3254      * names.  Crash if there is, as that's an error in the code
3255      * or an inappropriate plugin.
3256      * This situation has to be fixed to not register more than one
3257      * protocol with the same name.
3258      *
3259      * This is done by reducing the number of strcmp (and alike) calls as much as possible,
3260      * as this significally slows down startup time.
3261      *
3262      * Drawback: As a hash value is used to reduce insert time,
3263      * this might lead to a hash collision.
3264      * However, as we have around 500+ protocols and we're using a 32 bit int this is very,
3265      * very unlikely.
3266      */
3267
3268     key = g_malloc (sizeof(gint));
3269     *key = g_str_hash(name);
3270     existing_name = g_hash_table_lookup(proto_names, key);
3271     if (existing_name != NULL) {
3272         /* g_error will terminate the program */
3273         g_error("Duplicate protocol name \"%s\"!"
3274             " This might be caused by an inappropriate plugin or a development error.", name);
3275     }
3276     g_hash_table_insert(proto_names, key, (gpointer)name);
3277
3278     key = g_malloc (sizeof(gint));
3279     *key = g_str_hash(short_name);
3280     existing_name = g_hash_table_lookup(proto_short_names, key);
3281     if (existing_name != NULL) {
3282         g_error("Duplicate protocol short_name \"%s\"!"
3283             " This might be caused by an inappropriate plugin or a development error.", short_name);
3284     }
3285     g_hash_table_insert(proto_short_names, key, (gpointer)short_name);
3286
3287     found_invalid = FALSE;
3288     for (i = 0; i < strlen(filter_name); i++) {
3289         c = filter_name[i];
3290         if (!(islower(c) || isdigit(c) || c == '-' || c == '_' || c == '.')) {
3291             found_invalid = TRUE;
3292         }
3293     }
3294     if (found_invalid) {
3295         g_error("Protocol filter name \"%s\" has one or more invalid characters."
3296             " Allowed are lower characters, digits, '-', '_' and '.'."
3297             " This might be caused by an inappropriate plugin or a development error.", filter_name);
3298     }
3299     key = g_malloc (sizeof(gint));
3300     *key = g_str_hash(filter_name);
3301     existing_name = g_hash_table_lookup(proto_filter_names, key);
3302     if (existing_name != NULL) {
3303         g_error("Duplicate protocol filter_name \"%s\"!"
3304             " This might be caused by an inappropriate plugin or a development error.", filter_name);
3305     }
3306     g_hash_table_insert(proto_filter_names, key, (gpointer)filter_name);
3307
3308     /* Add this protocol to the list of known protocols; the list
3309        is sorted by protocol short name. */
3310     protocol = g_malloc(sizeof (protocol_t));
3311     protocol->name = name;
3312     protocol->short_name = short_name;
3313     protocol->filter_name = filter_name;
3314     protocol->fields = NULL;
3315     protocol->is_enabled = TRUE; /* protocol is enabled by default */
3316     protocol->can_toggle = TRUE;
3317     /* list will be sorted later by name, when all protocols completed registering */
3318     protocols = g_list_append(protocols, protocol);
3319
3320     /* Here we do allocate a new header_field_info struct */
3321     hfinfo = g_mem_chunk_alloc(gmc_hfinfo);
3322     hfinfo->name = name;
3323     hfinfo->abbrev = filter_name;
3324     hfinfo->type = FT_PROTOCOL;
3325     hfinfo->strings = protocol;
3326     hfinfo->bitmask = 0;
3327     hfinfo->bitshift = 0;
3328     hfinfo->ref_count = 0;
3329     hfinfo->blurb = NULL;
3330     hfinfo->parent = -1; /* this field differentiates protos and fields */
3331
3332     proto_id = proto_register_field_init(hfinfo, hfinfo->parent);
3333     protocol->proto_id = proto_id;
3334     return proto_id;
3335 }
3336
3337 /*
3338  * Routines to use to iterate over the protocols.
3339  * The argument passed to the iterator routines is an opaque cookie to
3340  * their callers; it's the GList pointer for the current element in
3341  * the list.
3342  * The ID of the protocol is returned, or -1 if there is no protocol.
3343  */
3344 int
3345 proto_get_first_protocol(void **cookie)
3346 {
3347         protocol_t *protocol;
3348
3349         if (protocols == NULL)
3350                 return -1;
3351         *cookie = protocols;
3352         protocol = protocols->data;
3353         return protocol->proto_id;
3354 }
3355
3356 int
3357 proto_get_next_protocol(void **cookie)
3358 {
3359         GList *list_item = *cookie;
3360         protocol_t *protocol;
3361
3362         list_item = g_list_next(list_item);
3363         if (list_item == NULL)
3364                 return -1;
3365         *cookie = list_item;
3366         protocol = list_item->data;
3367         return protocol->proto_id;
3368 }
3369
3370 header_field_info *
3371 proto_get_first_protocol_field(int proto_id, void **cookie)
3372 {
3373         protocol_t *protocol = find_protocol_by_id(proto_id);
3374         hf_register_info *ptr;
3375
3376         if ((protocol == NULL) || (protocol->fields == NULL))
3377                 return NULL;
3378
3379         *cookie = protocol->fields;
3380         ptr = protocol->fields->data;
3381         return &ptr->hfinfo;
3382 }
3383
3384 header_field_info *
3385 proto_get_next_protocol_field(void **cookie)
3386 {
3387         GList *list_item = *cookie;
3388         hf_register_info *ptr;
3389
3390         list_item = g_list_next(list_item);
3391         if (list_item == NULL)
3392                 return NULL;
3393
3394         *cookie = list_item;
3395         ptr = list_item->data;
3396         return &ptr->hfinfo;
3397 }
3398
3399 protocol_t *
3400 find_protocol_by_id(int proto_id)
3401 {
3402         header_field_info *hfinfo;
3403
3404         if(proto_id<0)
3405                 return NULL;
3406
3407         PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
3408         DISSECTOR_ASSERT(hfinfo->type==FT_PROTOCOL);
3409         return (protocol_t *)hfinfo->strings;
3410 }
3411
3412 static gint compare_filter_name(gconstpointer proto_arg,
3413                                 gconstpointer filter_name)
3414 {
3415         const protocol_t *protocol = proto_arg;
3416         const gchar* f_name = filter_name;
3417
3418         return (strcmp(protocol->filter_name, f_name));
3419 }
3420
3421 int
3422 proto_get_id(protocol_t *protocol)
3423 {
3424         return protocol->proto_id;
3425 }
3426
3427 int proto_get_id_by_filter_name(const gchar* filter_name)
3428 {
3429         GList *list_entry;
3430         protocol_t *protocol;
3431
3432         list_entry = g_list_find_custom(protocols, filter_name,
3433             compare_filter_name);
3434         if (list_entry == NULL)
3435                 return -1;
3436         protocol = list_entry->data;
3437         return protocol->proto_id;
3438 }
3439
3440 const char *
3441 proto_get_protocol_name(int proto_id)
3442 {
3443         protocol_t *protocol;
3444
3445         protocol = find_protocol_by_id(proto_id);
3446         return protocol->name;
3447 }
3448
3449 const char *
3450 proto_get_protocol_short_name(protocol_t *protocol)
3451 {
3452         if (protocol == NULL)
3453                 return "(none)";
3454         return protocol->short_name;
3455 }
3456
3457 const char *
3458 proto_get_protocol_filter_name(int proto_id)
3459 {
3460         protocol_t *protocol;
3461
3462         protocol = find_protocol_by_id(proto_id);
3463         return protocol->filter_name;
3464 }