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