Make the "standard" case in proto_can_match_selected() 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 }
3465
3466 gboolean
3467 proto_is_protocol_enabled(protocol_t *protocol)
3468 {
3469         return protocol->is_enabled;
3470 }
3471
3472 gboolean
3473 proto_can_toggle_protocol(int proto_id)
3474 {
3475         protocol_t *protocol;
3476
3477         protocol = find_protocol_by_id(proto_id);
3478         return protocol->can_toggle;
3479 }
3480
3481 void
3482 proto_set_decoding(int proto_id, gboolean enabled)
3483 {
3484         protocol_t *protocol;
3485
3486         protocol = find_protocol_by_id(proto_id);
3487         DISSECTOR_ASSERT(protocol->can_toggle);
3488         protocol->is_enabled = enabled;
3489 }
3490
3491 void
3492 proto_set_cant_toggle(int proto_id)
3493 {
3494         protocol_t *protocol;
3495
3496         protocol = find_protocol_by_id(proto_id);
3497         protocol->can_toggle = FALSE;
3498 }
3499
3500 /* for use with static arrays only, since we don't allocate our own copies
3501 of the header_field_info struct contained within the hf_register_info struct */
3502 void
3503 proto_register_field_array(int parent, hf_register_info *hf, int num_records)
3504 {
3505         int                     field_id, i;
3506         hf_register_info        *ptr = hf;
3507         protocol_t              *proto;
3508
3509         proto = find_protocol_by_id(parent);
3510         for (i = 0; i < num_records; i++, ptr++) {
3511                 /*
3512                  * Make sure we haven't registered this yet.
3513                  * Most fields have variables associated with them
3514                  * that are initialized to -1; some have array elements,
3515                  * or possibly uninitialized variables, so we also allow
3516                  * 0 (which is unlikely to be the field ID we get back
3517                  * from "proto_register_field_init()").
3518                  */
3519                 if (*ptr->p_id != -1 && *ptr->p_id != 0) {
3520                         fprintf(stderr,
3521                             "Duplicate field detected in call to proto_register_field_array: %s is already registered\n",
3522                             ptr->hfinfo.abbrev);
3523                         return;
3524                 }
3525
3526                 if (proto != NULL) {
3527                         if (proto->fields == NULL) {
3528                                 proto->fields = g_list_append(NULL, ptr);
3529                                 proto->last_field = proto->fields;
3530                         } else {
3531                                 proto->last_field =
3532                                     g_list_append(proto->last_field, ptr)->next;
3533                         }
3534                 }
3535                 field_id = proto_register_field_init(&ptr->hfinfo, parent);
3536                 *ptr->p_id = field_id;
3537         }
3538 }
3539
3540 static int
3541 proto_register_field_init(header_field_info *hfinfo, int parent)
3542 {
3543         /* The field must have names */
3544         DISSECTOR_ASSERT(hfinfo->name);
3545         DISSECTOR_ASSERT(hfinfo->abbrev);
3546
3547         /* These types of fields are allowed to have value_strings, true_false_strings or a protocol_t struct*/
3548         DISSECTOR_ASSERT((hfinfo->strings == NULL) || (
3549                         (hfinfo->type == FT_UINT8) ||
3550                         (hfinfo->type == FT_UINT16) ||
3551                         (hfinfo->type == FT_UINT24) ||
3552                         (hfinfo->type == FT_UINT32) ||
3553                         (hfinfo->type == FT_INT8) ||
3554                         (hfinfo->type == FT_INT16) ||
3555                         (hfinfo->type == FT_INT24) ||
3556                         (hfinfo->type == FT_INT32) ||
3557                         (hfinfo->type == FT_BOOLEAN) ||
3558                         (hfinfo->type == FT_PROTOCOL) ||
3559                         (hfinfo->type == FT_FRAMENUM) ));
3560
3561         switch (hfinfo->type) {
3562
3563         case FT_UINT8:
3564         case FT_UINT16:
3565         case FT_UINT24:
3566         case FT_UINT32:
3567         case FT_INT8:
3568         case FT_INT16:
3569         case FT_INT24:
3570         case FT_INT32:
3571                 /* Require integral types (other than frame number, which is
3572                    always displayed in decimal) to have a number base */
3573                 DISSECTOR_ASSERT(hfinfo->display != BASE_NONE);
3574                 break;
3575
3576         case FT_FRAMENUM:
3577                 /* Don't allow bitfields or value strings for frame numbers */
3578                 DISSECTOR_ASSERT(hfinfo->bitmask == 0);
3579                 DISSECTOR_ASSERT(hfinfo->strings == NULL);
3580                 break;
3581
3582         default:
3583                 break;
3584         }
3585         /* if this is a bitfield, compute bitshift */
3586         if (hfinfo->bitmask) {
3587                 while ((hfinfo->bitmask & (1 << hfinfo->bitshift)) == 0)
3588                         hfinfo->bitshift++;
3589         }
3590
3591         hfinfo->parent = parent;
3592         hfinfo->same_name_next = NULL;
3593         hfinfo->same_name_prev = NULL;
3594
3595         /* if we always add and never delete, then id == len - 1 is correct */
3596         if(gpa_hfinfo.len>=gpa_hfinfo.allocated_len){
3597                 if(!gpa_hfinfo.hfi){
3598                         gpa_hfinfo.allocated_len=1000;
3599                         gpa_hfinfo.hfi=g_malloc(sizeof(header_field_info *)*1000);
3600                 } else {
3601                         gpa_hfinfo.allocated_len+=1000;
3602                         gpa_hfinfo.hfi=g_realloc(gpa_hfinfo.hfi, sizeof(header_field_info *)*gpa_hfinfo.allocated_len);
3603                 }
3604         }
3605         gpa_hfinfo.hfi[gpa_hfinfo.len]=hfinfo;
3606         gpa_hfinfo.len++;
3607         hfinfo->id = gpa_hfinfo.len - 1;
3608
3609         /* if we have real names, enter this field in the name tree */
3610         if ((hfinfo->name[0] != 0) && (hfinfo->abbrev[0] != 0 )) {
3611
3612                 header_field_info *same_name_hfinfo, *same_name_next_hfinfo;
3613                 const char *p;
3614                 guchar c;
3615
3616                 /* Check that the filter name (abbreviation) is legal;
3617                  * it must contain only alphanumerics, '-', "_", and ".". */
3618                 for (p = hfinfo->abbrev; (c = *p) != '\0'; p++) {
3619                         if (!(isalnum(c) || c == '-' || c == '_' || c == '.')) {
3620                                 fprintf(stderr, "OOPS: '%c' in '%s'\n", c, hfinfo->abbrev);
3621                                 DISSECTOR_ASSERT(isalnum(c) || c == '-' || c == '_' ||
3622                                         c == '.');
3623                         }
3624                 }
3625                 /* We allow multiple hfinfo's to be registered under the same
3626                  * abbreviation. This was done for X.25, as, depending
3627                  * on whether it's modulo-8 or modulo-128 operation,
3628                  * some bitfield fields may be in different bits of
3629                  * a byte, and we want to be able to refer to that field
3630                  * with one name regardless of whether the packets
3631                  * are modulo-8 or modulo-128 packets. */
3632                 same_name_hfinfo = g_tree_lookup(gpa_name_tree, hfinfo->abbrev);
3633                 if (same_name_hfinfo) {
3634                         /* There's already a field with this name.
3635                          * Put it after that field in the list of
3636                          * fields with this name, then allow the code
3637                          * after this if{} block to replace the old
3638                          * hfinfo with the new hfinfo in the GTree. Thus,
3639                          * we end up with a linked-list of same-named hfinfo's,
3640                          * with the root of the list being the hfinfo in the GTree */
3641                         same_name_next_hfinfo =
3642                             same_name_hfinfo->same_name_next;
3643
3644                         hfinfo->same_name_next = same_name_next_hfinfo;
3645                         if (same_name_next_hfinfo)
3646                                 same_name_next_hfinfo->same_name_prev = hfinfo;
3647
3648                         same_name_hfinfo->same_name_next = hfinfo;
3649                         hfinfo->same_name_prev = same_name_hfinfo;
3650                 }
3651                 g_tree_insert(gpa_name_tree, (gpointer) (hfinfo->abbrev), hfinfo);
3652         }
3653
3654         return hfinfo->id;
3655 }
3656
3657 void
3658 proto_register_subtree_array(gint *const *indices, int num_indices)
3659 {
3660         int     i;
3661         gint    *const *ptr = indices;
3662
3663         /*
3664          * If we've already allocated the array of tree types, expand
3665          * it; this lets plugins such as mate add tree types after
3666          * the initial startup.  (If we haven't already allocated it,
3667          * we don't allocate it; on the first pass, we just assign
3668          * ett values and keep track of how many we've assigned, and
3669          * when we're finished registering all dissectors we allocate
3670          * the array, so that we do only one allocation rather than
3671          * wasting CPU time and memory by growing the array for each
3672          * dissector that registers ett values.)
3673          */
3674         if (tree_is_expanded != NULL) {
3675                 tree_is_expanded =
3676                     g_realloc(tree_is_expanded,
3677                         (num_tree_types+num_indices)*sizeof (gboolean));
3678                 memset(tree_is_expanded + num_tree_types, 0,
3679                     num_indices*sizeof (gboolean));
3680         }
3681
3682         /*
3683          * Assign "num_indices" subtree numbers starting at "num_tree_types",
3684          * returning the indices through the pointers in the array whose
3685          * first element is pointed to by "indices", and update
3686          * "num_tree_types" appropriately.
3687          */
3688         for (i = 0; i < num_indices; i++, ptr++, num_tree_types++)
3689                 **ptr = num_tree_types;
3690 }
3691
3692 void
3693 proto_item_fill_label(field_info *fi, gchar *label_str)
3694 {
3695         header_field_info               *hfinfo = fi->hfinfo;
3696
3697         guint8                          *bytes;
3698         guint32                         integer;
3699         ipv4_addr                       *ipv4;
3700         e_guid_t                        *guid;
3701         guint32                         n_addr; /* network-order IPv4 address */
3702         const gchar                     *name;
3703         int                                     ret;    /*tmp return value */
3704
3705         switch(hfinfo->type) {
3706                 case FT_NONE:
3707                 case FT_PROTOCOL:
3708                         ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3709                                 "%s", hfinfo->name);
3710                         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3711                                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3712                         break;
3713
3714                 case FT_BOOLEAN:
3715                         fill_label_boolean(fi, label_str);
3716                         break;
3717
3718                 case FT_BYTES:
3719                 case FT_UINT_BYTES:
3720                         bytes = fvalue_get(&fi->value);
3721                         if (bytes) {
3722                                 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3723                                         "%s: %s", hfinfo->name,
3724                                          bytes_to_str(bytes, fvalue_length(&fi->value)));
3725                                 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3726                                         label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3727                         }
3728                         else {
3729                                 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3730                                         "%s: <MISSING>", hfinfo->name);
3731                                 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3732                                         label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3733                         }
3734                         break;
3735
3736                 /* Four types of integers to take care of:
3737                  *      Bitfield, with val_string
3738                  *      Bitfield, w/o val_string
3739                  *      Non-bitfield, with val_string
3740                  *      Non-bitfield, w/o val_string
3741                  */
3742                 case FT_UINT8:
3743                 case FT_UINT16:
3744                 case FT_UINT24:
3745                 case FT_UINT32:
3746                 case FT_FRAMENUM:
3747                         if (hfinfo->bitmask) {
3748                                 if (hfinfo->strings) {
3749                                         fill_label_enumerated_bitfield(fi, label_str);
3750                                 }
3751                                 else {
3752                                         fill_label_numeric_bitfield(fi, label_str);
3753                                 }
3754                         }
3755                         else {
3756                                 if (hfinfo->strings) {
3757                                         fill_label_enumerated_uint(fi, label_str);
3758                                 }
3759                                 else {
3760                                         fill_label_uint(fi, label_str);
3761                                 }
3762                         }
3763                         break;
3764
3765                 case FT_UINT64:
3766                         fill_label_uint64(fi, label_str);
3767                         break;
3768
3769                 case FT_INT8:
3770                 case FT_INT16:
3771                 case FT_INT24:
3772                 case FT_INT32:
3773                         DISSECTOR_ASSERT(!hfinfo->bitmask);
3774                         if (hfinfo->strings) {
3775                                 fill_label_enumerated_int(fi, label_str);
3776                         }
3777                         else {
3778                                 fill_label_int(fi, label_str);
3779                         }
3780                         break;
3781
3782                 case FT_INT64:
3783                         fill_label_int64(fi, label_str);
3784                         break;
3785
3786                 case FT_FLOAT:
3787                         ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3788                                 "%s: %." STRINGIFY(FLT_DIG) "f",
3789                                 hfinfo->name, fvalue_get_floating(&fi->value));
3790                         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3791                                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3792                         break;
3793
3794                 case FT_DOUBLE:
3795                         ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3796                                 "%s: %." STRINGIFY(DBL_DIG) "g",
3797                                 hfinfo->name, fvalue_get_floating(&fi->value));
3798                         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3799                                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3800                         break;
3801
3802                 case FT_ABSOLUTE_TIME:
3803                         ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3804                                 "%s: %s", hfinfo->name,
3805                                 abs_time_to_str(fvalue_get(&fi->value)));
3806                         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3807                                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3808                         break;
3809
3810                 case FT_RELATIVE_TIME:
3811                         ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3812                                 "%s: %s seconds", hfinfo->name,
3813                                 rel_time_to_secs_str(fvalue_get(&fi->value)));
3814                         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3815                                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3816                         break;
3817
3818                 case FT_IPXNET:
3819                         integer = fvalue_get_integer(&fi->value);
3820                         ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3821                                 "%s: %s (0x%08X)", hfinfo->name,
3822                                 get_ipxnet_name(integer), integer);
3823                         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3824                                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3825                         break;
3826
3827                 case FT_ETHER:
3828                         bytes = fvalue_get(&fi->value);
3829                         ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3830                                 "%s: %s (%s)", hfinfo->name,
3831                                 get_ether_name(bytes),
3832                                 ether_to_str(bytes));
3833                         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3834                                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3835                         break;
3836
3837                 case FT_IPv4:
3838                         ipv4 = fvalue_get(&fi->value);
3839                         n_addr = ipv4_get_net_order_addr(ipv4);
3840                         ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3841                                 "%s: %s (%s)", hfinfo->name,
3842                                 get_hostname(n_addr),
3843                                 ip_to_str((guint8*)&n_addr));
3844                         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3845                                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3846                         break;
3847
3848                 case FT_IPv6:
3849                         bytes = fvalue_get(&fi->value);
3850                         ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3851                                 "%s: %s (%s)", hfinfo->name,
3852                                 get_hostname6((struct e_in6_addr *)bytes),
3853                                 ip6_to_str((struct e_in6_addr*)bytes));
3854                         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3855                                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3856                         break;
3857
3858                 case FT_GUID:
3859                         guid = fvalue_get(&fi->value);
3860                         ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3861                                 "%s: %s", hfinfo->name,
3862                                  guid_to_str(guid));
3863                         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3864                                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3865                         break;
3866
3867                 case FT_OID:
3868                         bytes = fvalue_get(&fi->value);
3869                         name = (oid_resolv_enabled()) ? get_oid_name(bytes, fvalue_length(&fi->value)) : NULL;
3870                         if (name) {
3871                                 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3872                                         "%s: %s (%s)", hfinfo->name,
3873                                          oid_to_str(bytes, fvalue_length(&fi->value)), name);
3874                         } else {
3875                                 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3876                                         "%s: %s", hfinfo->name,
3877                                          oid_to_str(bytes, fvalue_length(&fi->value)));
3878                         }
3879                         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3880                                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3881                         break;
3882
3883                 case FT_STRING:
3884                 case FT_STRINGZ:
3885                 case FT_UINT_STRING:
3886                         bytes = fvalue_get(&fi->value);
3887             if(strlen(bytes) > ITEM_LABEL_LENGTH) {
3888                             ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3889                                     "%s [truncated]: %s", hfinfo->name,
3890                                     format_text(bytes, strlen(bytes)));
3891             } else {
3892                             ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3893                                     "%s: %s", hfinfo->name,
3894                                     format_text(bytes, strlen(bytes)));
3895             }
3896                         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3897                                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3898                         break;
3899
3900                 default:
3901                         g_error("hfinfo->type %d (%s) not handled\n",
3902                                         hfinfo->type,
3903                                         ftype_name(hfinfo->type));
3904                         DISSECTOR_ASSERT_NOT_REACHED();
3905                         break;
3906         }
3907 }
3908
3909 static void
3910 fill_label_boolean(field_info *fi, gchar *label_str)
3911 {
3912         char    *p = label_str;
3913         int     bitfield_byte_length = 0, bitwidth;
3914         guint32 unshifted_value;
3915         guint32 value;
3916         int                                     ret;    /*tmp return value */
3917
3918         header_field_info               *hfinfo = fi->hfinfo;
3919         static const true_false_string  default_tf = { "True", "False" };
3920         const true_false_string         *tfstring = &default_tf;
3921
3922         if (hfinfo->strings) {
3923                 tfstring = (const struct true_false_string*) hfinfo->strings;
3924         }
3925
3926         value = fvalue_get_integer(&fi->value);
3927         if (hfinfo->bitmask) {
3928                 /* Figure out the bit width */
3929                 bitwidth = hfinfo_bitwidth(hfinfo);
3930
3931                 /* Un-shift bits */
3932                 unshifted_value = value;
3933                 if (hfinfo->bitshift > 0) {
3934                         unshifted_value <<= hfinfo->bitshift;
3935                 }
3936
3937                 /* Create the bitfield first */
3938                 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
3939                 bitfield_byte_length = p - label_str;
3940         }
3941
3942         /* Fill in the textual info */
3943         ret = g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
3944                 "%s: %s",  hfinfo->name,
3945                 value ? tfstring->true_string : tfstring->false_string);
3946         if ((ret == -1) || (ret >= (ITEM_LABEL_LENGTH - bitfield_byte_length)))
3947                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3948 }
3949
3950
3951 /* Fills data for bitfield ints with val_strings */
3952 static void
3953 fill_label_enumerated_bitfield(field_info *fi, gchar *label_str)
3954 {
3955         const char *format = NULL;
3956         char *p;
3957         int bitfield_byte_length, bitwidth;
3958         guint32 unshifted_value;
3959         guint32 value;
3960         int                                     ret;    /*tmp return value */
3961
3962         header_field_info       *hfinfo = fi->hfinfo;
3963
3964         /* Figure out the bit width */
3965         bitwidth = hfinfo_bitwidth(hfinfo);
3966
3967         /* Pick the proper format string */
3968         format = hfinfo_uint_vals_format(hfinfo);
3969
3970         /* Un-shift bits */
3971         unshifted_value = fvalue_get_integer(&fi->value);
3972         value = unshifted_value;
3973         if (hfinfo->bitshift > 0) {
3974                 unshifted_value <<= hfinfo->bitshift;
3975         }
3976
3977         /* Create the bitfield first */
3978         p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
3979         bitfield_byte_length = p - label_str;
3980
3981         /* Fill in the textual info using stored (shifted) value */
3982         ret = g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
3983                         format,  hfinfo->name,
3984                         val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
3985         if ((ret == -1) || (ret >= (ITEM_LABEL_LENGTH - bitfield_byte_length)))
3986                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3987 }
3988
3989 static void
3990 fill_label_numeric_bitfield(field_info *fi, gchar *label_str)
3991 {
3992         const char *format = NULL;
3993         char *p;
3994         int bitfield_byte_length, bitwidth;
3995         guint32 unshifted_value;
3996         guint32 value;
3997         int                                     ret;    /*tmp return value */
3998
3999         header_field_info       *hfinfo = fi->hfinfo;
4000
4001         /* Figure out the bit width */
4002         bitwidth = hfinfo_bitwidth(hfinfo);
4003
4004         /* Pick the proper format string */
4005         format = hfinfo_uint_format(hfinfo);
4006
4007         /* Un-shift bits */
4008         unshifted_value = fvalue_get_integer(&fi->value);
4009         value = unshifted_value;
4010         if (hfinfo->bitshift > 0) {
4011                 unshifted_value <<= hfinfo->bitshift;
4012         }
4013
4014         /* Create the bitfield using */
4015         p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
4016         bitfield_byte_length = p - label_str;
4017
4018         /* Fill in the textual info using stored (shifted) value */
4019         if (IS_BASE_DUAL(hfinfo->display)) {
4020                 ret = g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
4021                                 format,  hfinfo->name, value, value);
4022         } else {
4023                 ret = g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
4024                                 format,  hfinfo->name, value);
4025         }
4026         if ((ret == -1) || (ret >= (ITEM_LABEL_LENGTH - bitfield_byte_length)))
4027                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4028
4029 }
4030
4031 static void
4032 fill_label_enumerated_uint(field_info *fi, gchar *label_str)
4033 {
4034         const char *format = NULL;
4035         header_field_info       *hfinfo = fi->hfinfo;
4036         guint32 value;
4037         int                                     ret;    /*tmp return value */
4038
4039         /* Pick the proper format string */
4040         format = hfinfo_uint_vals_format(hfinfo);
4041
4042         value = fvalue_get_integer(&fi->value);
4043
4044         /* Fill in the textual info */
4045         ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4046                         format,  hfinfo->name,
4047                         val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
4048         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4049                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4050 }
4051
4052 static void
4053 fill_label_uint(field_info *fi, gchar *label_str)
4054 {
4055         const char *format = NULL;
4056         header_field_info       *hfinfo = fi->hfinfo;
4057         guint32 value;
4058         int                                     ret;    /*tmp return value */
4059
4060         /* Pick the proper format string */
4061         format = hfinfo_uint_format(hfinfo);
4062         value = fvalue_get_integer(&fi->value);
4063
4064         /* Fill in the textual info */
4065         if (IS_BASE_DUAL(hfinfo->display)) {
4066                 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4067                                 format,  hfinfo->name, value, value);
4068         } else {
4069                 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4070                                 format,  hfinfo->name, value);
4071         }
4072         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4073                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4074 }
4075
4076 static void
4077 fill_label_uint64(field_info *fi, gchar *label_str)
4078 {
4079         const char *format = NULL;
4080         header_field_info       *hfinfo = fi->hfinfo;
4081         guint64 value;
4082         int                                     ret;    /*tmp return value */
4083
4084         /* Pick the proper format string */
4085         format = hfinfo_uint64_format(hfinfo);
4086         value = fvalue_get_integer64(&fi->value);
4087
4088         /* Fill in the textual info */
4089         if (IS_BASE_DUAL(hfinfo->display)) {
4090                 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4091                                 format,  hfinfo->name, value, value);
4092         } else {
4093                 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4094                                 format,  hfinfo->name, value);
4095         }
4096         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4097                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4098 }
4099
4100 static void
4101 fill_label_enumerated_int(field_info *fi, gchar *label_str)
4102 {
4103         const char *format = NULL;
4104         header_field_info       *hfinfo = fi->hfinfo;
4105         guint32 value;
4106         int                                     ret;    /*tmp return value */
4107
4108         /* Pick the proper format string */
4109         format = hfinfo_int_vals_format(hfinfo);
4110         value = fvalue_get_integer(&fi->value);
4111
4112         /* Fill in the textual info */
4113         ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4114                         format,  hfinfo->name,
4115                         val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
4116         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4117                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4118 }
4119
4120 static void
4121 fill_label_int(field_info *fi, gchar *label_str)
4122 {
4123         const char *format = NULL;
4124         header_field_info       *hfinfo = fi->hfinfo;
4125         guint32 value;
4126         int                                     ret;    /*tmp return value */
4127
4128         /* Pick the proper format string */
4129         format = hfinfo_int_format(hfinfo);
4130         value = fvalue_get_integer(&fi->value);
4131
4132         /* Fill in the textual info */
4133         if (IS_BASE_DUAL(hfinfo->display)) {
4134                 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4135                                 format,  hfinfo->name, value, value);
4136         } else {
4137                 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4138                                 format,  hfinfo->name, value);
4139         }
4140         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4141                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4142 }
4143
4144 static void
4145 fill_label_int64(field_info *fi, gchar *label_str)
4146 {
4147         const char *format = NULL;
4148         header_field_info       *hfinfo = fi->hfinfo;
4149         guint64 value;
4150         int                                     ret;    /*tmp return value */
4151
4152         /* Pick the proper format string */
4153         format = hfinfo_int64_format(hfinfo);
4154         value = fvalue_get_integer64(&fi->value);
4155
4156         /* Fill in the textual info */
4157         if (IS_BASE_DUAL(hfinfo->display)) {
4158                 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4159                                 format,  hfinfo->name, value, value);
4160         } else {
4161                 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4162                                 format,  hfinfo->name, value);
4163         }
4164         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4165                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4166 }
4167
4168 int
4169 hfinfo_bitwidth(header_field_info *hfinfo)
4170 {
4171         int bitwidth = 0;
4172
4173         if (!hfinfo->bitmask) {
4174                 return 0;
4175         }
4176
4177         switch(hfinfo->type) {
4178                 case FT_UINT8:
4179                 case FT_INT8:
4180                         bitwidth = 8;
4181                         break;
4182                 case FT_UINT16:
4183                 case FT_INT16:
4184                         bitwidth = 16;
4185                         break;
4186                 case FT_UINT24:
4187                 case FT_INT24:
4188                         bitwidth = 24;
4189                         break;
4190                 case FT_UINT32:
4191                 case FT_INT32:
4192                         bitwidth = 32;
4193                         break;
4194                 case FT_BOOLEAN:
4195                         bitwidth = hfinfo->display; /* hacky? :) */
4196                         break;
4197                 default:
4198                         DISSECTOR_ASSERT_NOT_REACHED();
4199                         ;
4200         }
4201         return bitwidth;
4202 }
4203
4204 static const char*
4205 hfinfo_uint_vals_format(header_field_info *hfinfo)
4206 {
4207         const char *format = NULL;
4208
4209         switch(hfinfo->display) {
4210                 case BASE_DEC:
4211                 case BASE_DEC_HEX:
4212                         format = "%s: %s (%u)";
4213                         break;
4214                 case BASE_OCT: /* I'm lazy */
4215                         format = "%s: %s (%o)";
4216                         break;
4217                 case BASE_HEX:
4218                 case BASE_HEX_DEC:
4219                         switch(hfinfo->type) {
4220                                 case FT_UINT8:
4221                                         format = "%s: %s (0x%02x)";
4222                                         break;
4223                                 case FT_UINT16:
4224                                         format = "%s: %s (0x%04x)";
4225                                         break;
4226                                 case FT_UINT24:
4227                                         format = "%s: %s (0x%06x)";
4228                                         break;
4229                                 case FT_UINT32:
4230                                         format = "%s: %s (0x%08x)";
4231                                         break;
4232                                 default:
4233                                         DISSECTOR_ASSERT_NOT_REACHED();
4234                                         ;
4235                         }
4236                         break;
4237                 default:
4238                         DISSECTOR_ASSERT_NOT_REACHED();
4239                         ;
4240         }
4241         return format;
4242 }
4243
4244 static const char*
4245 hfinfo_uint_format(header_field_info *hfinfo)
4246 {
4247         const char *format = NULL;
4248
4249         /* Pick the proper format string */
4250         if (hfinfo->type == FT_FRAMENUM) {
4251                 /*
4252                  * Frame numbers are always displayed in decimal.
4253                  */
4254                 format = "%s: %u";
4255         } else {
4256                 switch(hfinfo->display) {
4257                         case BASE_DEC:
4258                                 format = "%s: %u";
4259                                 break;
4260                         case BASE_DEC_HEX:
4261                                 switch(hfinfo->type) {
4262                                         case FT_UINT8:
4263                                                 format = "%s: %u (0x%02x)";
4264                                                 break;
4265                                         case FT_UINT16:
4266                                                 format = "%s: %u (0x%04x)";
4267                                                 break;
4268                                         case FT_UINT24:
4269                                                 format = "%s: %u (0x%06x)";
4270                                                 break;
4271                                         case FT_UINT32:
4272                                                 format = "%s: %u (0x%08x)";
4273                                                 break;
4274                                         default:
4275                                                 DISSECTOR_ASSERT_NOT_REACHED();
4276                                                 ;
4277                                 }
4278                                 break;
4279                         case BASE_OCT: /* I'm lazy */
4280                                 format = "%s: %o";
4281                                 break;
4282                         case BASE_HEX:
4283                                 switch(hfinfo->type) {
4284                                         case FT_UINT8:
4285                                                 format = "%s: 0x%02x";
4286                                                 break;
4287                                         case FT_UINT16:
4288                                                 format = "%s: 0x%04x";
4289                                                 break;
4290                                         case FT_UINT24:
4291                                                 format = "%s: 0x%06x";
4292                                                 break;
4293                                         case FT_UINT32:
4294                                                 format = "%s: 0x%08x";
4295                                                 break;
4296                                         default:
4297                                                 DISSECTOR_ASSERT_NOT_REACHED();
4298                                                 ;
4299                                 }
4300                                 break;
4301                         case BASE_HEX_DEC:
4302                                 switch(hfinfo->type) {
4303                                         case FT_UINT8:
4304                                                 format = "%s: 0x%02x (%u)";
4305                                                 break;
4306                                         case FT_UINT16:
4307                                                 format = "%s: 0x%04x (%u)";
4308                                                 break;
4309                                         case FT_UINT24:
4310                                                 format = "%s: 0x%06x (%u)";
4311                                                 break;
4312                                         case FT_UINT32:
4313                                                 format = "%s: 0x%08x (%u)";
4314                                                 break;
4315                                         default:
4316                                                 DISSECTOR_ASSERT_NOT_REACHED();
4317                                                 ;
4318                                 }
4319                                 break;
4320                         default:
4321                                 DISSECTOR_ASSERT_NOT_REACHED();
4322                                 ;
4323                 }
4324         }
4325         return format;
4326 }
4327
4328 static const char*
4329 hfinfo_int_vals_format(header_field_info *hfinfo)
4330 {
4331         const char *format = NULL;
4332
4333         switch(hfinfo->display) {
4334                 case BASE_DEC:
4335                 case BASE_DEC_HEX:
4336                         format = "%s: %s (%d)";
4337                         break;
4338                 case BASE_OCT: /* I'm lazy */
4339                         format = "%s: %s (%o)";
4340                         break;
4341                 case BASE_HEX:
4342                 case BASE_HEX_DEC:
4343                         switch(hfinfo->type) {
4344                                 case FT_INT8:
4345                                         format = "%s: %s (0x%02x)";
4346                                         break;
4347                                 case FT_INT16:
4348                                         format = "%s: %s (0x%04x)";
4349                                         break;
4350                                 case FT_INT24:
4351                                         format = "%s: %s (0x%06x)";
4352                                         break;
4353                                 case FT_INT32:
4354                                         format = "%s: %s (0x%08x)";
4355                                         break;
4356                                 default:
4357                                         DISSECTOR_ASSERT_NOT_REACHED();
4358                                         ;
4359                         }
4360                         break;
4361                 default:
4362                         DISSECTOR_ASSERT_NOT_REACHED();
4363                         ;
4364         }
4365         return format;
4366 }
4367
4368 static const char*
4369 hfinfo_uint64_format(header_field_info *hfinfo)
4370 {
4371         const char *format = NULL;
4372
4373         /* Pick the proper format string */
4374         switch(hfinfo->display) {
4375                 case BASE_DEC:
4376                         format = "%s: %" PRIu64;
4377                         break;
4378                 case BASE_DEC_HEX:
4379                         format = "%s: %" PRIu64 " (%" PRIx64 ")";
4380                         break;
4381                 case BASE_OCT: /* I'm lazy */
4382                         format = "%s: %" PRIo64;
4383                         break;
4384                 case BASE_HEX:
4385                         format = "%s: 0x%016" PRIx64;
4386                         break;
4387                 case BASE_HEX_DEC:
4388                         format = "%s: 0x%016" PRIx64 " (%" PRIu64 ")";
4389                         break;
4390                 default:
4391                         DISSECTOR_ASSERT_NOT_REACHED();
4392                         ;
4393         }
4394         return format;
4395 }
4396
4397 static const char*
4398 hfinfo_int_format(header_field_info *hfinfo)
4399 {
4400         const char *format = NULL;
4401
4402         /* Pick the proper format string */
4403         switch(hfinfo->display) {
4404                 case BASE_DEC:
4405                         format = "%s: %d";
4406                         break;
4407                 case BASE_DEC_HEX:
4408                         switch(hfinfo->type) {
4409                                 case FT_INT8:
4410                                         format = "%s: %d (0x%02x)";
4411                                         break;
4412                                 case FT_INT16:
4413                                         format = "%s: %d (0x%04x)";
4414                                         break;
4415                                 case FT_INT24:
4416                                         format = "%s: %d (0x%06x)";
4417                                         break;
4418                                 case FT_INT32:
4419                                         format = "%s: %d (0x%08x)";
4420                                         break;
4421                                 default:
4422                                         DISSECTOR_ASSERT_NOT_REACHED();
4423                                         ;
4424                         }
4425                 case BASE_OCT: /* I'm lazy */
4426                         format = "%s: %o";
4427                         break;
4428                 case BASE_HEX:
4429                         switch(hfinfo->type) {
4430                                 case FT_INT8:
4431                                         format = "%s: 0x%02x";
4432                                         break;
4433                                 case FT_INT16:
4434                                         format = "%s: 0x%04x";
4435                                         break;
4436                                 case FT_INT24:
4437                                         format = "%s: 0x%06x";
4438                                         break;
4439                                 case FT_INT32:
4440                                         format = "%s: 0x%08x";
4441                                         break;
4442                                 default:
4443                                         DISSECTOR_ASSERT_NOT_REACHED();
4444                                         ;
4445                         }
4446                         break;
4447                 case BASE_HEX_DEC:
4448                         switch(hfinfo->type) {
4449                                 case FT_INT8:
4450                                         format = "%s: 0x%02x (%d)";
4451                                         break;
4452                                 case FT_INT16:
4453                                         format = "%s: 0x%04x (%d)";
4454                                         break;
4455                                 case FT_INT24:
4456                                         format = "%s: 0x%06x (%d)";
4457                                         break;
4458                                 case FT_INT32:
4459                                         format = "%s: 0x%08x (%d)";
4460                                         break;
4461                                 default:
4462                                         DISSECTOR_ASSERT_NOT_REACHED();
4463                                         ;
4464                         }
4465                         break;
4466                 default:
4467                         DISSECTOR_ASSERT_NOT_REACHED();
4468                         ;
4469         }
4470         return format;
4471 }
4472
4473 static const char*
4474 hfinfo_int64_format(header_field_info *hfinfo)
4475 {
4476         const char *format = NULL;
4477
4478         /* Pick the proper format string */
4479         switch(hfinfo->display) {
4480                 case BASE_DEC:
4481                         format = "%s: %" PRId64;
4482                         break;
4483                 case BASE_DEC_HEX:
4484                         format = "%s: %" PRId64 " (%" PRIx64 ")";
4485                         break;
4486                 case BASE_OCT: /* I'm lazy */
4487                         format = "%s: %" PRIo64;
4488                         break;
4489                 case BASE_HEX:
4490                         format = "%s: 0x%016" PRIx64;
4491                         break;
4492                 case BASE_HEX_DEC:
4493                         format = "%s: 0x%016" PRIx64 " (%" PRId64 ")";
4494                         break;
4495                 default:
4496                         DISSECTOR_ASSERT_NOT_REACHED();
4497                         ;
4498         }
4499         return format;
4500 }
4501
4502
4503
4504 int
4505 proto_registrar_n(void)
4506 {
4507         return gpa_hfinfo.len;
4508 }
4509
4510 const char*
4511 proto_registrar_get_name(int n)
4512 {
4513         header_field_info *hfinfo;
4514
4515         PROTO_REGISTRAR_GET_NTH(n, hfinfo);
4516         return hfinfo->name;
4517 }
4518
4519 const char*
4520 proto_registrar_get_abbrev(int n)
4521 {
4522         header_field_info *hfinfo;
4523
4524         PROTO_REGISTRAR_GET_NTH(n, hfinfo);
4525         return hfinfo->abbrev;
4526 }
4527
4528 int
4529 proto_registrar_get_ftype(int n)
4530 {
4531         header_field_info *hfinfo;
4532
4533         PROTO_REGISTRAR_GET_NTH(n, hfinfo);
4534         return hfinfo->type;
4535 }
4536
4537 int
4538 proto_registrar_get_parent(int n)
4539 {
4540         header_field_info *hfinfo;
4541
4542         PROTO_REGISTRAR_GET_NTH(n, hfinfo);
4543         return hfinfo->parent;
4544 }
4545
4546 gboolean
4547 proto_registrar_is_protocol(int n)
4548 {
4549         header_field_info *hfinfo;
4550
4551         PROTO_REGISTRAR_GET_NTH(n, hfinfo);
4552         return (hfinfo->parent == -1 ? TRUE : FALSE);
4553 }
4554
4555 /* Returns length of field in packet (not necessarily the length
4556  * in our internal representation, as in the case of IPv4).
4557  * 0 means undeterminable at time of registration
4558  * -1 means the field is not registered. */
4559 gint
4560 proto_registrar_get_length(int n)
4561 {
4562         header_field_info *hfinfo;
4563
4564         PROTO_REGISTRAR_GET_NTH(n, hfinfo);
4565         return ftype_length(hfinfo->type);
4566 }
4567
4568
4569
4570 /* Looks for a protocol or a field in a proto_tree. Returns TRUE if
4571  * it exists anywhere, or FALSE if it exists nowhere. */
4572 gboolean
4573 proto_check_for_protocol_or_field(proto_tree* tree, int id)
4574 {
4575         GPtrArray *ptrs = proto_get_finfo_ptr_array(tree, id);
4576
4577         if (!ptrs) {
4578                 return FALSE;
4579         }
4580         else if (g_ptr_array_len(ptrs) > 0) {
4581                 return TRUE;
4582         }
4583         else {
4584                 return FALSE;
4585         }
4586 }
4587
4588 /* Return GPtrArray* of field_info pointers for all hfindex that appear in tree.
4589  * This only works if the hfindex was "primed" before the dissection
4590  * took place, as we just pass back the already-created GPtrArray*.
4591  * The caller should *not* free the GPtrArray*; proto_tree_free_node()
4592  * handles that. */
4593 GPtrArray*
4594 proto_get_finfo_ptr_array(proto_tree *tree, int id)
4595 {
4596         return g_hash_table_lookup(PTREE_DATA(tree)->interesting_hfids,
4597             GINT_TO_POINTER(id));
4598 }
4599
4600
4601 /* Helper struct for proto_find_info() and  proto_all_finfos() */
4602 typedef struct {
4603         GPtrArray       *array;
4604         int             id;
4605 } ffdata_t;
4606
4607 /* Helper function for proto_find_info() */
4608 static gboolean
4609 find_finfo(proto_node *node, gpointer data)
4610 {
4611         field_info *fi = PITEM_FINFO(node);
4612         if (fi && fi->hfinfo) {
4613                 if (fi->hfinfo->id == ((ffdata_t*)data)->id) {
4614                         g_ptr_array_add(((ffdata_t*)data)->array, fi);
4615                 }
4616         }
4617
4618         /* Don't stop traversing. */
4619         return FALSE;
4620 }
4621
4622 /* Return GPtrArray* of field_info pointers for all hfindex that appear in a tree.
4623 * This works on any proto_tree, primed or unprimed, but actually searches
4624 * the tree, so it is slower than using proto_get_finfo_ptr_array on a primed tree.
4625 * The caller does need to free the returned GPtrArray with
4626 * g_ptr_array_free(<array>, FALSE).
4627 */
4628 GPtrArray*
4629 proto_find_finfo(proto_tree *tree, int id)
4630 {
4631         ffdata_t        ffdata;
4632
4633         ffdata.array = g_ptr_array_new();
4634         ffdata.id = id;
4635
4636         proto_tree_traverse_pre_order(tree, find_finfo, &ffdata);
4637
4638         return ffdata.array;
4639 }
4640
4641 /* Helper function for proto_all_finfos() */
4642 static gboolean
4643 every_finfo(proto_node *node, gpointer data)
4644 {
4645         field_info *fi = PITEM_FINFO(node);
4646         if (fi && fi->hfinfo) {
4647                 g_ptr_array_add(((ffdata_t*)data)->array, fi);
4648         }
4649
4650         /* Don't stop traversing. */
4651         return FALSE;
4652 }
4653
4654 /* Return GPtrArray* of field_info pointers containing all hfindexes that appear in a tree. */
4655 GPtrArray*
4656 proto_all_finfos(proto_tree *tree)
4657 {
4658         ffdata_t        ffdata;
4659
4660         ffdata.array = g_ptr_array_new();
4661         ffdata.id = 0;
4662
4663         proto_tree_traverse_pre_order(tree, every_finfo, &ffdata);
4664
4665         return ffdata.array;
4666 }
4667
4668
4669 typedef struct {
4670         guint           offset;
4671         field_info      *finfo;
4672         tvbuff_t        *tvb;
4673 } offset_search_t;
4674
4675 static gboolean
4676 check_for_offset(proto_node *node, gpointer data)
4677 {
4678         field_info          *fi = PITEM_FINFO(node);
4679         offset_search_t         *offsearch = data;
4680
4681         /* !fi == the top most container node which holds nothing */
4682         if (fi && !PROTO_ITEM_IS_HIDDEN(node) && fi->ds_tvb && offsearch->tvb == fi->ds_tvb) {
4683                 if (offsearch->offset >= (guint) fi->start &&
4684                                 offsearch->offset < (guint) (fi->start + fi->length)) {
4685
4686                         offsearch->finfo = fi;
4687                         return FALSE; /* keep traversing */
4688                 }
4689         }
4690         return FALSE; /* keep traversing */
4691 }
4692
4693 /* Search a proto_tree backwards (from leaves to root) looking for the field
4694  * whose start/length occupies 'offset' */
4695 /* XXX - I couldn't find an easy way to search backwards, so I search
4696  * forwards, w/o stopping. Therefore, the last finfo I find will the be
4697  * the one I want to return to the user. This algorithm is inefficient
4698  * and could be re-done, but I'd have to handle all the children and
4699  * siblings of each node myself. When I have more time I'll do that.
4700  * (yeah right) */
4701 field_info*
4702 proto_find_field_from_offset(proto_tree *tree, guint offset, tvbuff_t *tvb)
4703 {
4704         offset_search_t         offsearch;
4705
4706         offsearch.offset = offset;
4707         offsearch.finfo = NULL;
4708         offsearch.tvb = tvb;
4709
4710         proto_tree_traverse_pre_order(tree, check_for_offset, &offsearch);
4711
4712         return offsearch.finfo;
4713 }
4714
4715 /* Dumps the protocols in the registration database to stdout.  An independent
4716  * program can take this output and format it into nice tables or HTML or
4717  * whatever.
4718  *
4719  * There is one record per line. The fields are tab-delimited.
4720  *
4721  * Field 1 = protocol name
4722  * Field 2 = protocol short name
4723  * Field 3 = protocol filter name
4724  */
4725 void
4726 proto_registrar_dump_protocols(void)
4727 {
4728         protocol_t              *protocol;
4729         int                     i;
4730         void                    *cookie = NULL;
4731
4732         for (i = proto_get_first_protocol(&cookie); i != -1;
4733             i = proto_get_next_protocol(&cookie)) {
4734                 protocol = find_protocol_by_id(i);
4735                 printf("%s\t%s\t%s\n", protocol->name, protocol->short_name,
4736                     protocol->filter_name);
4737         }
4738 }
4739
4740 /* Dumps the value_string and true/false strings for fields that have
4741  * them. There is one record per line. Fields are tab-delimited.
4742  * There are two types of records, Value String records and True/False
4743  * String records. The first field, 'V' or 'T', indicates the type
4744  * of record.
4745  *
4746  * Value Strings
4747  * -------------
4748  * Field 1 = 'V'
4749  * Field 2 = field abbreviation to which this value string corresponds
4750  * Field 3 = Integer value
4751  * Field 4 = String
4752  *
4753  * True/False Strings
4754  * ------------------
4755  * Field 1 = 'T'
4756  * Field 2 = field abbreviation to which this true/false string corresponds
4757  * Field 3 = True String
4758  * Field 4 = False String
4759  */
4760 void
4761 proto_registrar_dump_values(void)
4762 {
4763         header_field_info       *hfinfo, *parent_hfinfo;
4764         int                     i, len, vi;
4765         const value_string      *vals;
4766         const true_false_string *tfs;
4767
4768         len = gpa_hfinfo.len;
4769         for (i = 0; i < len ; i++) {
4770                 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
4771
4772                  if (hfinfo->id == hf_text_only) {
4773                          continue;
4774                  }
4775
4776                 /* ignore protocols */
4777                 if (proto_registrar_is_protocol(i)) {
4778                         continue;
4779                 }
4780                 /* process header fields */
4781                 else {
4782                         /*
4783                          * If this field isn't at the head of the list of
4784                          * fields with this name, skip this field - all
4785                          * fields with the same name are really just versions
4786                          * of the same field stored in different bits, and
4787                          * should have the same type/radix/value list, and
4788                          * just differ in their bit masks.  (If a field isn't
4789                          * a bitfield, but can be, say, 1 or 2 bytes long,
4790                          * it can just be made FT_UINT16, meaning the
4791                          * *maximum* length is 2 bytes, and be used
4792                          * for all lengths.)
4793                          */
4794                         if (hfinfo->same_name_prev != NULL)
4795                                 continue;
4796
4797                         PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
4798
4799                         vals = NULL;
4800                         tfs = NULL;
4801
4802                         if (hfinfo->type == FT_UINT8 ||
4803                                 hfinfo->type == FT_UINT16 ||
4804                                 hfinfo->type == FT_UINT24 ||
4805                                 hfinfo->type == FT_UINT32 ||
4806                                 hfinfo->type == FT_UINT64 ||
4807                                 hfinfo->type == FT_INT8 ||
4808                                 hfinfo->type == FT_INT16 ||
4809                                 hfinfo->type == FT_INT24 ||
4810                                 hfinfo->type == FT_INT32 ||
4811                                 hfinfo->type == FT_INT64) {
4812
4813                                 vals = hfinfo->strings;
4814                         }
4815                         else if (hfinfo->type == FT_BOOLEAN) {
4816                                 tfs = hfinfo->strings;
4817                         }
4818
4819                         /* Print value strings? */
4820                         if (vals) {
4821                                 vi = 0;
4822                                 while (vals[vi].strptr) {
4823                                         /* Print in the proper base */
4824                                         if (hfinfo->display == BASE_HEX) {
4825                                                 printf("V\t%s\t0x%x\t%s\n",
4826                                                                 hfinfo->abbrev,
4827                                                                 vals[vi].value,
4828                                                                 vals[vi].strptr);
4829                                         }
4830                                         else {
4831                                                 printf("V\t%s\t%u\t%s\n",
4832                                                                 hfinfo->abbrev,
4833                                                                 vals[vi].value,
4834                                                                 vals[vi].strptr);
4835                                         }
4836                                         vi++;
4837                                 }
4838                         }
4839
4840                         /* Print true/false strings? */
4841                         else if (tfs) {
4842                                 printf("T\t%s\t%s\t%s\n", hfinfo->abbrev,
4843                                                 tfs->true_string, tfs->false_string);
4844                         }
4845                 }
4846         }
4847 }
4848
4849 /* Dumps the contents of the registration database to stdout. An indepedent
4850  * program can take this output and format it into nice tables or HTML or
4851  * whatever.
4852  *
4853  * There is one record per line. Each record is either a protocol or a header
4854  * field, differentiated by the first field. The fields are tab-delimited.
4855  *
4856  * Protocols
4857  * ---------
4858  * Field 1 = 'P'
4859  * Field 2 = descriptive protocol name
4860  * Field 3 = protocol abbreviation
4861  *
4862  * Header Fields
4863  * -------------
4864  * (format 1)
4865  * Field 1 = 'F'
4866  * Field 2 = descriptive field name
4867  * Field 3 = field abbreviation
4868  * Field 4 = type ( textual representation of the the ftenum type )
4869  * Field 5 = parent protocol abbreviation
4870  * Field 6 = blurb describing field
4871  *
4872  * (format 2)
4873  * Field 1 = 'F'
4874  * Field 2 = descriptive field name
4875  * Field 3 = field abbreviation
4876  * Field 4 = type ( textual representation of the the ftenum type )
4877  * Field 5 = parent protocol abbreviation
4878  * Field 6 = blurb describing field
4879  * Field 7 = base for display (for integer types)
4880  * Field 8 = blurb describing field (yes, apparently we repeated this accidentally)
4881  *
4882  * (format 3)
4883  * Field 1 = 'F'
4884  * Field 2 = descriptive field name
4885  * Field 3 = field abbreviation
4886  * Field 4 = type ( textual representation of the the ftenum type )
4887  * Field 5 = parent protocol abbreviation
4888  * Field 6 = blurb describing field
4889  * Field 7 = base for display (for integer types)
4890  * Field 8 = bitmask
4891  */
4892 void
4893 proto_registrar_dump_fields(int format)
4894 {
4895         header_field_info       *hfinfo, *parent_hfinfo;
4896         int                     i, len;
4897         const char              *enum_name;
4898         const char              *base_name;
4899         const char              *blurb;
4900
4901         len = gpa_hfinfo.len;
4902         for (i = 0; i < len ; i++) {
4903                 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
4904
4905                 /*
4906                  * Skip the pseudo-field for "proto_tree_add_text()" since
4907                  * we don't want it in the list of filterable fields.
4908          */
4909         if (hfinfo->id == hf_text_only)
4910                         continue;
4911
4912                 /* format for protocols */
4913                 if (proto_registrar_is_protocol(i)) {
4914                         printf("P\t%s\t%s\n", hfinfo->name, hfinfo->abbrev);
4915                 }
4916                 /* format for header fields */
4917                 else {
4918                         /*
4919                          * If this field isn't at the head of the list of
4920                          * fields with this name, skip this field - all
4921                          * fields with the same name are really just versions
4922                          * of the same field stored in different bits, and
4923                          * should have the same type/radix/value list, and
4924                          * just differ in their bit masks.  (If a field isn't
4925                          * a bitfield, but can be, say, 1 or 2 bytes long,
4926                          * it can just be made FT_UINT16, meaning the
4927                          * *maximum* length is 2 bytes, and be used
4928                          * for all lengths.)
4929                          */
4930                         if (hfinfo->same_name_prev != NULL)
4931                                 continue;
4932
4933                         PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
4934
4935                         enum_name = ftype_name(hfinfo->type);
4936                         base_name = "";
4937
4938                         if (format > 1) {
4939                                 if (hfinfo->type == FT_UINT8 ||
4940                                         hfinfo->type == FT_UINT16 ||
4941                                         hfinfo->type == FT_UINT24 ||
4942                                         hfinfo->type == FT_UINT32 ||
4943                                         hfinfo->type == FT_UINT64 ||
4944                                         hfinfo->type == FT_INT8 ||
4945                                         hfinfo->type == FT_INT16 ||
4946                                         hfinfo->type == FT_INT24 ||
4947                                         hfinfo->type == FT_INT32 ||
4948                                         hfinfo->type == FT_INT64) {
4949
4950
4951                                         switch(hfinfo->display) {
4952                                                 case BASE_NONE:
4953                                                         base_name = "BASE_NONE";
4954                                                         break;
4955                                                 case BASE_DEC:
4956                                                         base_name = "BASE_DEC";
4957                                                         break;
4958                                                 case BASE_HEX:
4959                                                         base_name = "BASE_HEX";
4960                                                         break;
4961                                                 case BASE_OCT:
4962                                                         base_name = "BASE_OCT";
4963                                                         break;
4964                                                 case BASE_DEC_HEX:
4965                                                         base_name = "BASE_DEC_HEX";
4966                                                         break;
4967                                                 case BASE_HEX_DEC:
4968                                                         base_name = "BASE_HEX_DEC";
4969                                                         break;
4970                                         }
4971                                 }
4972                         }
4973
4974                         blurb = hfinfo->blurb;
4975                         if (blurb == NULL)
4976                                 blurb = "";
4977                         if (format == 1) {
4978                                 printf("F\t%s\t%s\t%s\t%s\t%s\n",
4979                                         hfinfo->name, hfinfo->abbrev, enum_name,
4980                                         parent_hfinfo->abbrev, blurb);
4981                         }
4982                         else if (format == 2) {
4983                                 printf("F\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n",
4984                                         hfinfo->name, hfinfo->abbrev, enum_name,
4985                                         parent_hfinfo->abbrev, blurb,
4986                                         base_name, blurb);
4987                         }
4988                         else if (format == 3) {
4989                                 printf("F\t%s\t%s\t%s\t%s\t%s\t%s\t%u\n",
4990                                         hfinfo->name, hfinfo->abbrev, enum_name,
4991                                         parent_hfinfo->abbrev, blurb,
4992                                         base_name, hfinfo->bitmask);
4993                         }
4994                         else {
4995                                 g_assert_not_reached();
4996                         }
4997                 }
4998         }
4999 }
5000
5001 static const char*
5002 hfinfo_numeric_format(header_field_info *hfinfo)
5003 {
5004         const char *format = NULL;
5005
5006         /* Pick the proper format string */
5007         if (hfinfo->type == FT_FRAMENUM) {
5008                 /*
5009                  * Frame numbers are always displayed in decimal.
5010                  */
5011                 format = "%s == %u";
5012         } else {
5013                 /* Pick the proper format string */
5014                 switch(hfinfo->display) {
5015                         case BASE_DEC:
5016                         case BASE_DEC_HEX:
5017                         case BASE_OCT: /* I'm lazy */
5018                                 switch(hfinfo->type) {
5019                                         case FT_UINT8:
5020                                         case FT_UINT16:
5021                                         case FT_UINT24:
5022                                         case FT_UINT32:
5023                                                 format = "%s == %u";
5024                                                 break;
5025                                         case FT_UINT64:
5026                                                 format = "%s == %" PRIu64;
5027                                                 break;
5028                                         case FT_INT8:
5029                                         case FT_INT16:
5030                                         case FT_INT24:
5031                                         case FT_INT32:
5032                                                 format = "%s == %d";
5033                                                 break;
5034                                         case FT_INT64:
5035                                                 format = "%s == %" PRId64;
5036                                                 break;
5037                                         default:
5038                                                 DISSECTOR_ASSERT_NOT_REACHED();
5039                                                 ;
5040                                 }
5041                                 break;
5042                         case BASE_HEX:
5043                         case BASE_HEX_DEC:
5044                                 switch(hfinfo->type) {
5045                                         case FT_UINT8:
5046                                                 format = "%s == 0x%02x";
5047                                                 break;
5048                                         case FT_UINT16:
5049                                                 format = "%s == 0x%04x";
5050                                                 break;
5051                                         case FT_UINT24:
5052                                                 format = "%s == 0x%06x";
5053                                                 break;
5054                                         case FT_UINT32:
5055                                                 format = "%s == 0x%08x";
5056                                                 break;
5057                                         case FT_UINT64:
5058                                                 format = "%s == 0x%016" PRIx64;
5059                                                 break;
5060                                         default:
5061                                                 DISSECTOR_ASSERT_NOT_REACHED();
5062                                                 ;
5063                                 }
5064                                 break;
5065                         default:
5066                                 DISSECTOR_ASSERT_NOT_REACHED();
5067                                 ;
5068                 }
5069         }
5070         return format;
5071 }
5072
5073 /*
5074  * Returns TRUE if we can do a "match selected" on the field, FALSE
5075  * otherwise.
5076  */
5077 gboolean
5078 proto_can_match_selected(field_info *finfo, epan_dissect_t *edt)
5079 {
5080         header_field_info       *hfinfo;
5081         gint                    length;
5082
5083         hfinfo = finfo->hfinfo;
5084         DISSECTOR_ASSERT(hfinfo);
5085
5086         switch(hfinfo->type) {
5087
5088                 case FT_NONE:
5089                         /*
5090                          * Doesn't have a value, but may still want to test
5091                          * for its presence in a trace
5092                          */
5093                         return TRUE;
5094
5095                 case FT_PCRE:
5096                         /*
5097                          * This doesn't have a value, so we'd match
5098                          * on the raw bytes at this address.
5099                          *
5100                          * Should we be allowed to access to the raw bytes?
5101                          * If "edt" is NULL, the answer is "no".
5102                          */
5103                         if (edt == NULL)
5104                                 return FALSE;
5105
5106                         /*
5107                          * Is this field part of the raw frame tvbuff?
5108                          * If not, we can't use "frame[N:M]" to match
5109                          * it.
5110                          *
5111                          * XXX - should this be frame-relative, or
5112                          * protocol-relative?
5113                          *
5114                          * XXX - does this fallback for non-registered
5115                          * fields even make sense?
5116                          */
5117                         if (finfo->ds_tvb != edt->tvb)
5118                                 return FALSE;
5119
5120                         /*
5121                          * If the length is 0, there's nothing to match, so
5122                          * we can't match.  (Also check for negative values,
5123                          * just in case, as we'll cast it to an unsigned
5124                          * value later.)
5125                          */
5126                         length = finfo->length;
5127                         if (length <= 0)
5128                                 return FALSE;
5129
5130                         /*
5131                          * Don't go past the end of that tvbuff.
5132                          */
5133                         if ((guint)length > tvb_length(finfo->ds_tvb))
5134                                 length = tvb_length(finfo->ds_tvb);
5135                         if (length <= 0)
5136                                 return FALSE;
5137                         return TRUE;
5138
5139                 default:
5140                         /*
5141                          * By default, assume the type has a value, so
5142                          * we can match.
5143                          */
5144                         return TRUE;
5145         }
5146 }
5147
5148 /* This function returns a string allocated with packet lifetime scope.
5149  * You do not need to [g_]free() this string since it will be automatically
5150  * freed once the next packet is dissected.
5151  */
5152 char*
5153 proto_construct_dfilter_string(field_info *finfo, epan_dissect_t *edt)
5154 {
5155         header_field_info       *hfinfo;
5156         int                     abbrev_len;
5157         char                    *buf, *ptr;
5158         int                     buf_len;
5159         const char              *format;
5160         int                     dfilter_len, i;
5161         gint                    start, length, length_remaining;
5162         guint8                  c;
5163
5164         hfinfo = finfo->hfinfo;
5165         DISSECTOR_ASSERT(hfinfo);
5166         abbrev_len = strlen(hfinfo->abbrev);
5167
5168         /*
5169          * XXX - we can't use the "val_to_string_repr" and "string_repr_len"
5170          * functions for FT_UINT and FT_INT types, as we choose the base in
5171          * the string expression based on the display base of the field.
5172          *
5173          * Note that the base does matter, as this is also used for
5174          * the protocolinfo tap.
5175          *
5176          * It might be nice to use them in "proto_item_fill_label()"
5177          * as well, although, there, you'd have to deal with the base
5178          * *and* with resolved values for addresses.
5179          *
5180          * Perhaps we need two different val_to_string routines, one
5181          * to generate items for display filters and one to generate
5182          * strings for display, and pass to both of them the
5183          * "display" and "strings" values in the header_field_info
5184          * structure for the field, so they can get the base and,
5185          * if the field is Boolean or an enumerated integer type,
5186          * the tables used to generate human-readable values.
5187          */
5188         switch(hfinfo->type) {
5189
5190                 case FT_UINT8:
5191                 case FT_UINT16:
5192                 case FT_UINT24:
5193                 case FT_UINT32:
5194                 case FT_INT8:
5195                 case FT_INT16:
5196                 case FT_INT24:
5197                 case FT_INT32:
5198                 case FT_FRAMENUM:
5199                         /*
5200                          * 4 bytes for " == ".
5201                          * 11 bytes for:
5202                          *
5203                          *      a sign + up to 10 digits of 32-bit integer,
5204                          *      in decimal;
5205                          *
5206                          *      "0x" + 8 digits of 32-bit integer, in hex;
5207                          *
5208                          *      11 digits of 32-bit integer, in octal.
5209                          *      (No, we don't do octal, but this way,
5210                          *      we know that if we do, this will still
5211                          *      work.)
5212                          *
5213                          * 1 byte for the trailing '\0'.
5214                          */
5215                         dfilter_len = abbrev_len + 4 + 11 + 1;
5216                         buf = ep_alloc0(dfilter_len);
5217                         format = hfinfo_numeric_format(hfinfo);
5218                         g_snprintf(buf, dfilter_len, format, hfinfo->abbrev, fvalue_get_integer(&finfo->value));
5219                         break;
5220
5221                 case FT_INT64:
5222                 case FT_UINT64:
5223                         /*
5224                          * 4 bytes for " == ".
5225                          * 22 bytes for:
5226                          *
5227                          *      a sign + up to 20 digits of 32-bit integer,
5228                          *      in decimal;
5229                          *
5230                          *      "0x" + 16 digits of 32-bit integer, in hex;
5231                          *
5232                          *      22 digits of 32-bit integer, in octal.
5233                          *      (No, we don't do octal, but this way,
5234                          *      we know that if we do, this will still
5235                          *      work.)
5236                          *
5237                          * 1 byte for the trailing '\0'.
5238                          */
5239                         dfilter_len = abbrev_len + 4 + 22 + 1;
5240                         buf = ep_alloc0(dfilter_len);
5241                         format = hfinfo_numeric_format(hfinfo);
5242                         g_snprintf(buf, dfilter_len, format, hfinfo->abbrev, fvalue_get_integer64(&finfo->value));
5243                         break;
5244
5245                 case FT_PROTOCOL:
5246                         buf = ep_strdup(finfo->hfinfo->abbrev);
5247                         break;
5248
5249                 case FT_NONE:
5250                 case FT_PCRE:
5251                         /*
5252                          * This doesn't have a value, so we'd match
5253                          * on the raw bytes at this address.
5254                          *
5255                          * Should we be allowed to access to the raw bytes?
5256                          * If "edt" is NULL, the answer is "no".
5257                          */
5258                         if (edt == NULL)
5259                                 return NULL;
5260
5261                         /*
5262                          * Is this field part of the raw frame tvbuff?
5263                          * If not, we can't use "frame[N:M]" to match
5264                          * it.
5265                          *
5266                          * XXX - should this be frame-relative, or
5267                          * protocol-relative?
5268                          *
5269                          * XXX - does this fallback for non-registered
5270                          * fields even make sense?
5271                          */
5272                         if (finfo->ds_tvb != edt->tvb)
5273                                 return NULL;    /* you lose */
5274
5275                         /*
5276                          * If the length is 0, just match the name of the field
5277                          * (Also check for negative values,
5278                          * just in case, as we'll cast it to an unsigned
5279                          * value later.)
5280                          */
5281                         length = finfo->length;
5282                         if (length == 0)
5283                         {
5284                                 buf = ep_strdup(finfo->hfinfo->abbrev);
5285                                 break;
5286                         }
5287                         if (length < 0)
5288                                 return NULL;
5289
5290                         /*
5291                          * Don't go past the end of that tvbuff.
5292                          */
5293                         length_remaining = tvb_length_remaining(finfo->ds_tvb, finfo->start);
5294                         if (length > length_remaining)
5295                                 length = length_remaining;
5296                         if (length <= 0)
5297                                 return NULL;
5298
5299                         start = finfo->start;
5300                         buf_len = 32 + length * 3;
5301                         buf = ep_alloc0(buf_len);
5302                         ptr = buf;
5303
5304                         ptr += g_snprintf(ptr, buf_len-(ptr-buf), "frame[%d:%d] == ", finfo->start, length);
5305                         for (i=0;i<length; i++) {
5306                                 c = tvb_get_guint8(finfo->ds_tvb, start);
5307                                 start++;
5308                                 if (i == 0 ) {
5309                                         ptr += g_snprintf(ptr, buf_len-(ptr-buf), "%02x", c);
5310                                 }
5311                                 else {
5312                                         ptr += g_snprintf(ptr, buf_len-(ptr-buf), ":%02x", c);
5313                                 }
5314                         }
5315                         break;
5316
5317                 /* By default, use the fvalue's "to_string_repr" method. */
5318                 default:
5319                         /* Figure out the string length needed.
5320                          *      The ft_repr length.
5321                          *      4 bytes for " == ".
5322                          *      1 byte for trailing NUL.
5323                          */
5324                         dfilter_len = fvalue_string_repr_len(&finfo->value,
5325                                         FTREPR_DFILTER);
5326                         dfilter_len += abbrev_len + 4 + 1;
5327                         buf = ep_alloc0(dfilter_len);
5328
5329                         /* Create the string */
5330                         g_snprintf(buf, dfilter_len, "%s == ", hfinfo->abbrev);
5331                         fvalue_to_string_repr(&finfo->value,
5332                                         FTREPR_DFILTER,
5333                                         &buf[abbrev_len + 4]);
5334                         break;
5335         }
5336
5337         return buf;
5338 }