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