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