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