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