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