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