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