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