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