proto_tree_add_bytes_format[_value] can handle NULL trees
[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 <glib.h>
28 #include <float.h>
29 #include <errno.h>
30
31 #include <wsutil/bits_ctz.h>
32 #include <wsutil/bits_count_ones.h>
33 #include <wsutil/sign_ext.h>
34
35 #include <ftypes/ftypes-int.h>
36
37 #include "packet.h"
38 #include "exceptions.h"
39 #include "ptvcursor.h"
40 #include "strutil.h"
41 #include "addr_resolv.h"
42 #include "address_types.h"
43 #include "oids.h"
44 #include "proto.h"
45 #include "epan_dissect.h"
46 #include "tvbuff.h"
47 #include "wmem/wmem.h"
48 #include "charsets.h"
49 #include "asm_utils.h"
50 #include "column-utils.h"
51 #include "to_str-int.h"
52 #include "to_str.h"
53 #include "osi-utils.h"
54 #include "expert.h"
55 #include "show_exception.h"
56 #include "in_cksum.h"
57
58 #include <wsutil/plugins.h>
59 #include <wsutil/ws_printf.h> /* ws_debug_printf/ws_g_warning */
60 #include <wsutil/glib-compat.h>
61
62 /* Ptvcursor limits */
63 #define SUBTREE_ONCE_ALLOCATION_NUMBER 8
64 #define SUBTREE_MAX_LEVELS 256
65
66 /* Throw an exception if our tree exceeds these. */
67 /* XXX - These should probably be preferences */
68 #define MAX_TREE_ITEMS (1 * 1000 * 1000)
69 #define MAX_TREE_LEVELS (5 * 100)
70
71 typedef struct __subtree_lvl {
72         gint        cursor_offset;
73         proto_item *it;
74         proto_tree *tree;
75 } subtree_lvl;
76
77 struct ptvcursor {
78         subtree_lvl *pushed_tree;
79         guint8       pushed_tree_index;
80         guint8       pushed_tree_max;
81         proto_tree  *tree;
82         tvbuff_t    *tvb;
83         gint         offset;
84 };
85
86 #define cVALS(x) (const value_string*)(x)
87
88 /** See inlined comments.
89  @param tree the tree to append this item to
90  @param free_block a code block to call to free resources if this returns
91  @return NULL if 'tree' is null */
92 #define CHECK_FOR_NULL_TREE_AND_FREE(tree, free_block)                  \
93         if (!tree) {                                                    \
94                 free_block;                                             \
95                 return NULL;                                            \
96         }
97
98 /** See inlined comments.
99  @param tree the tree to append this item to
100  @param free_block a code block to call to free resources if this returns
101  @return NULL if 'tree' is null */
102 #define CHECK_FOR_NULL_TREE(tree) \
103         CHECK_FOR_NULL_TREE_AND_FREE(tree, ((void)0))
104
105 /** See inlined comments.
106  @param tree the tree to append this item to
107  @param hfindex field index
108  @param hfinfo header_field
109  @param free_block a code block to call to free resources if this returns
110  @return the header field matching 'hfinfo' */
111 #define TRY_TO_FAKE_THIS_ITEM_OR_FREE(tree, hfindex, hfinfo, free_block) \
112         /* If this item is not referenced we don't have to do much work \
113            at all but we should still return a node so that field items \
114            below this node (think proto_item_add_subtree()) will still  \
115            have somewhere to attach to or else filtering will not work  \
116            (they would be ignored since tree would be NULL).            \
117            DON'T try to fake a node where PTREE_FINFO(tree) is NULL     \
118            since dissectors that want to do proto_item_set_len() or     \
119            other operations that dereference this would crash.          \
120            We fake FT_PROTOCOL unless some clients have requested us    \
121            not to do so.                                                \
122         */                                                              \
123         PTREE_DATA(tree)->count++;                                      \
124         if (PTREE_DATA(tree)->count > MAX_TREE_ITEMS) {                 \
125                 free_block;                                             \
126                 if (getenv("WIRESHARK_ABORT_ON_TOO_MANY_ITEMS") != NULL) \
127                         g_error("More than %d items in the tree -- possible infinite loop", MAX_TREE_ITEMS); \
128                 /* Let the exception handler add items to the tree */   \
129                 PTREE_DATA(tree)->count = 0;                            \
130                 THROW_MESSAGE(DissectorError,                           \
131                         wmem_strdup_printf(wmem_packet_scope(), "More than %d items in the tree -- possible infinite loop", MAX_TREE_ITEMS)); \
132         }                                                               \
133         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);                       \
134         if (!(PTREE_DATA(tree)->visible)) {                             \
135                 if (PTREE_FINFO(tree)) {                                \
136                         if ((hfinfo->ref_type != HF_REF_TYPE_DIRECT)    \
137                             && (hfinfo->type != FT_PROTOCOL ||          \
138                                 PTREE_DATA(tree)->fake_protocols)) {    \
139                                 free_block;                             \
140                                 /* just return tree back to the caller */\
141                                 return tree;                            \
142                         }                                               \
143                 }                                                       \
144         }
145
146 /** See inlined comments.
147  @param tree the tree to append this item to
148  @param hfindex field index
149  @param hfinfo header_field
150  @return the header field matching 'hfinfo' */
151 #define TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo) \
152         TRY_TO_FAKE_THIS_ITEM_OR_FREE(tree, hfindex, hfinfo, ((void)0))
153
154
155 /** See inlined comments.
156  @param pi the created protocol item we're about to return */
157 #define TRY_TO_FAKE_THIS_REPR(pi)       \
158         g_assert(pi);                   \
159         if (!(PTREE_DATA(pi)->visible)) { \
160                 /* If the tree (GUI) isn't visible it's pointless for us to generate the protocol \
161                  * items string representation */ \
162                 return pi; \
163         }
164 /* Same as above but returning void */
165 #define TRY_TO_FAKE_THIS_REPR_VOID(pi)  \
166         if (!pi)                        \
167                 return;                 \
168         if (!(PTREE_DATA(pi)->visible)) { \
169                 /* If the tree (GUI) isn't visible it's pointless for us to generate the protocol \
170                  * items string representation */ \
171                 return; \
172         }
173 /* Similar to above, but allows a NULL tree */
174 #define TRY_TO_FAKE_THIS_REPR_NESTED(pi)        \
175         if ((pi == NULL) || (!(PTREE_DATA(pi)->visible))) { \
176                 /* If the tree (GUI) isn't visible it's pointless for us to generate the protocol \
177                  * items string representation */ \
178                 return pi; \
179         }
180
181 static const char *hf_try_val_to_str(guint32 value, const header_field_info *hfinfo);
182 static const char *hf_try_val64_to_str(guint64 value, const header_field_info *hfinfo);
183 static int hfinfo_container_bitwidth(const header_field_info *hfinfo);
184
185 static void label_mark_truncated(char *label_str, gsize name_pos);
186 #define LABEL_MARK_TRUNCATED_START(label_str) label_mark_truncated(label_str, 0)
187
188 static void fill_label_boolean(field_info *fi, gchar *label_str);
189 static void fill_label_bitfield_char(field_info *fi, gchar *label_str);
190 static void fill_label_bitfield(field_info *fi, gchar *label_str, gboolean is_signed);
191 static void fill_label_bitfield64(field_info *fi, gchar *label_str, gboolean is_signed);
192 static void fill_label_char(field_info *fi, gchar *label_str);
193 static void fill_label_number(field_info *fi, gchar *label_str, gboolean is_signed);
194 static void fill_label_number64(field_info *fi, gchar *label_str, gboolean is_signed);
195
196 static const char *hfinfo_char_value_format_display(int display, char buf[7], guint32 value);
197 static const char *hfinfo_number_value_format_display(const header_field_info *hfinfo, int display, char buf[32], guint32 value);
198 static const char *hfinfo_number_value_format_display64(const header_field_info *hfinfo, int display, char buf[48], guint64 value);
199 static const char *hfinfo_char_vals_format(const header_field_info *hfinfo, char buf[32], guint32 value);
200 static const char *hfinfo_number_vals_format(const header_field_info *hfinfo, char buf[32], guint32 value);
201 static const char *hfinfo_number_vals_format64(const header_field_info *hfinfo, char buf[48], guint64 value);
202 static const char *hfinfo_number_value_format(const header_field_info *hfinfo, char buf[32], guint32 value);
203 static const char *hfinfo_number_value_format64(const header_field_info *hfinfo, char buf[48], guint64 value);
204 static const char *hfinfo_char_value_format(const header_field_info *hfinfo, char buf[32], guint32 value);
205 static const char *hfinfo_numeric_value_format(const header_field_info *hfinfo, char buf[32], guint32 value);
206 static const char *hfinfo_numeric_value_format64(const header_field_info *hfinfo, char buf[48], guint64 value);
207
208 static void proto_cleanup_base(void);
209
210 static proto_item *
211 proto_tree_add_node(proto_tree *tree, field_info *fi);
212
213 static void
214 get_hfi_length(header_field_info *hfinfo, tvbuff_t *tvb, const gint start, gint *length,
215                 gint *item_length);
216
217 static gint
218 get_full_length(header_field_info *hfinfo, tvbuff_t *tvb, const gint start,
219                 gint length, guint item_length, const gint encoding);
220
221 static field_info *
222 new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
223                const gint start, const gint item_length);
224
225 static proto_item *
226 proto_tree_add_pi(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
227                   gint start, gint *length);
228
229 static void
230 proto_tree_set_representation_value(proto_item *pi, const char *format, va_list ap);
231 static void
232 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap);
233
234 static void
235 proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb, const char* field_data);
236 static void
237 proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length);
238 static void
239 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length);
240 static void
241 proto_tree_set_bytes_gbytearray(field_info *fi, const GByteArray *value);
242 static void
243 proto_tree_set_time(field_info *fi, const nstime_t *value_ptr);
244 static void
245 proto_tree_set_string(field_info *fi, const char* value);
246 static void
247 proto_tree_set_ax25(field_info *fi, const guint8* value);
248 static void
249 proto_tree_set_ax25_tvb(field_info *fi, tvbuff_t *tvb, gint start);
250 static void
251 proto_tree_set_vines(field_info *fi, const guint8* value);
252 static void
253 proto_tree_set_vines_tvb(field_info *fi, tvbuff_t *tvb, gint start);
254 static void
255 proto_tree_set_ether(field_info *fi, const guint8* value);
256 static void
257 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start);
258 static void
259 proto_tree_set_ipxnet(field_info *fi, guint32 value);
260 static void
261 proto_tree_set_ipv4(field_info *fi, guint32 value);
262 static void
263 proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr);
264 static void
265 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
266 static void
267 proto_tree_set_fcwwn_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
268 static void
269 proto_tree_set_guid(field_info *fi, const e_guid_t *value_ptr);
270 static void
271 proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, gint start, const guint encoding);
272 static void
273 proto_tree_set_oid(field_info *fi, const guint8* value_ptr, gint length);
274 static void
275 proto_tree_set_oid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
276 static void
277 proto_tree_set_system_id(field_info *fi, const guint8* value_ptr, gint length);
278 static void
279 proto_tree_set_system_id_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
280 static void
281 proto_tree_set_boolean(field_info *fi, guint64 value);
282 static void
283 proto_tree_set_float(field_info *fi, float value);
284 static void
285 proto_tree_set_double(field_info *fi, double value);
286 static void
287 proto_tree_set_uint(field_info *fi, guint32 value);
288 static void
289 proto_tree_set_int(field_info *fi, gint32 value);
290 static void
291 proto_tree_set_uint64(field_info *fi, guint64 value);
292 static void
293 proto_tree_set_int64(field_info *fi, gint64 value);
294 static void
295 proto_tree_set_eui64(field_info *fi, const guint64 value);
296 static void
297 proto_tree_set_eui64_tvb(field_info *fi, tvbuff_t *tvb, gint start, const guint encoding);
298
299 /* Handle type length mismatch (now filterable) expert info */
300 static int proto_type_length_mismatch = -1;
301 static expert_field ei_type_length_mismatch_error = EI_INIT;
302 static expert_field ei_type_length_mismatch_warn = EI_INIT;
303 static void register_type_length_mismatch(void);
304
305 /* Handle number string decoding errors with expert info */
306 static int proto_number_string_decoding_error = -1;
307 static expert_field ei_number_string_decoding_failed_error = EI_INIT;
308 static expert_field ei_number_string_decoding_erange_error = EI_INIT;
309 static void register_number_string_decoding_error(void);
310
311 static int proto_register_field_init(header_field_info *hfinfo, const int parent);
312
313 /* special-case header field used within proto.c */
314 static header_field_info hfi_text_only =
315         { "Text item",  "text", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL };
316 int hf_text_only = -1;
317
318 /* Structure for information about a protocol */
319 struct _protocol {
320         const char *name;               /* long description */
321         const char *short_name;         /* short description */
322         const char *filter_name;        /* name of this protocol in filters */
323         GPtrArray  *fields;             /* fields for this protocol */
324         int         proto_id;           /* field ID for this protocol */
325         gboolean    is_enabled;         /* TRUE if protocol is enabled */
326         gboolean    enabled_by_default; /* TRUE if protocol is enabled by default */
327         gboolean    can_toggle;         /* TRUE if is_enabled can be changed */
328         int         parent_proto_id;    /* Used to identify "pino"s (Protocol In Name Only).
329                                        For dissectors that need a protocol name so they
330                                        can be added to a dissector table, but use the
331                                        parent_proto_id for things like enable/disable */
332         GList      *heur_list;          /* Heuristic dissectors associated with this protocol */
333 };
334
335 /* List of all protocols */
336 static GList *protocols = NULL;
337 static GList *pino_protocols = NULL;
338
339 /* Deregistered fields */
340 static GPtrArray *deregistered_fields = NULL;
341 static GPtrArray *deregistered_data = NULL;
342
343 /* indexed by prefix, contains initializers */
344 static GHashTable* prefixes = NULL;
345
346 /* Contains information about a field when a dissector calls
347  * proto_tree_add_item.  */
348 #define FIELD_INFO_NEW(pool, fi)  fi = wmem_new(pool, field_info)
349 #define FIELD_INFO_FREE(pool, fi) wmem_free(pool, fi)
350
351 /* Contains the space for proto_nodes. */
352 #define PROTO_NODE_INIT(node)                   \
353         node->first_child = NULL;               \
354         node->last_child = NULL;                \
355         node->next = NULL;
356
357 #define PROTO_NODE_FREE(pool, node)                     \
358         wmem_free(pool, node)
359
360 /* String space for protocol and field items for the GUI */
361 #define ITEM_LABEL_NEW(pool, il)                        \
362         il = wmem_new(pool, item_label_t);
363 #define ITEM_LABEL_FREE(pool, il)                       \
364         wmem_free(pool, il);
365
366 #define PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo)                                                \
367         if((guint)hfindex >= gpa_hfinfo.len && getenv("WIRESHARK_ABORT_ON_DISSECTOR_BUG"))      \
368                 g_error("Unregistered hf! index=%d", hfindex);                                  \
369         DISSECTOR_ASSERT_HINT((guint)hfindex < gpa_hfinfo.len, "Unregistered hf!");     \
370         DISSECTOR_ASSERT_HINT(gpa_hfinfo.hfi[hfindex] != NULL, "Unregistered hf!");     \
371         hfinfo = gpa_hfinfo.hfi[hfindex];
372
373 /* List which stores protocols and fields that have been registered */
374 typedef struct _gpa_hfinfo_t {
375         guint32             len;
376         guint32             allocated_len;
377         header_field_info **hfi;
378 } gpa_hfinfo_t;
379
380 static gpa_hfinfo_t gpa_hfinfo;
381
382 /* Hash table of abbreviations and IDs */
383 static GHashTable *gpa_name_map = NULL;
384 static header_field_info *same_name_hfinfo;
385 /*
386  * We're called repeatedly with the same field name when sorting a column.
387  * Cache our last gpa_name_map hit for faster lookups.
388  */
389 static char *last_field_name = NULL;
390 static header_field_info *last_hfinfo;
391
392 static void save_same_name_hfinfo(gpointer data)
393 {
394         same_name_hfinfo = (header_field_info*)data;
395 }
396
397 /* Cached value for VINES address type (used for FT_VINES) */
398 static int vines_address_type = -1;
399
400 /* Points to the first element of an array of bits, indexed by
401    a subtree item type; that array element is TRUE if subtrees of
402    an item of that type are to be expanded. */
403 static guint32 *tree_is_expanded;
404
405 /* Number of elements in that array. */
406 int             num_tree_types;
407
408 /* Name hashtables for fast detection of duplicate names */
409 static GHashTable* proto_names        = NULL;
410 static GHashTable* proto_short_names  = NULL;
411 static GHashTable* proto_filter_names = NULL;
412
413 static gint
414 proto_compare_name(gconstpointer p1_arg, gconstpointer p2_arg)
415 {
416         const protocol_t *p1 = (const protocol_t *)p1_arg;
417         const protocol_t *p2 = (const protocol_t *)p2_arg;
418
419         return g_ascii_strcasecmp(p1->short_name, p2->short_name);
420 }
421
422 #ifdef HAVE_PLUGINS
423 /*
424  * List of dissector plugins.
425  */
426 typedef struct {
427         void (*register_protoinfo)(void);       /* routine to call to register protocol information */
428         void (*reg_handoff)(void);              /* routine to call to register dissector handoff */
429 } dissector_plugin;
430
431 static GSList *dissector_plugins = NULL;
432
433 /*
434  * Callback for each plugin found.
435  */
436 static gboolean
437 check_for_dissector_plugin(GModule *handle)
438 {
439         gpointer gp;
440         void (*register_protoinfo)(void);
441         void (*reg_handoff)(void);
442         dissector_plugin *plugin;
443
444         /*
445          * Do we have a register routine?
446          */
447         if (g_module_symbol(handle, "plugin_register", &gp)) {
448 DIAG_OFF(pedantic)
449                 register_protoinfo = (void (*)(void))gp;
450 DIAG_ON(pedantic)
451         }
452         else {
453                 register_protoinfo = NULL;
454         }
455
456         /*
457          * Do we have a reg_handoff routine?
458          */
459         if (g_module_symbol(handle, "plugin_reg_handoff", &gp)) {
460 DIAG_OFF(pedantic)
461                 reg_handoff = (void (*)(void))gp;
462 DIAG_ON(pedantic)
463         }
464         else {
465                 reg_handoff = NULL;
466         }
467
468         /*
469          * If we have neither, we're not a dissector plugin.
470          */
471         if (register_protoinfo == NULL && reg_handoff == NULL)
472                 return FALSE;
473
474         /*
475          * Add this one to the list of dissector plugins.
476          */
477         plugin = (dissector_plugin *)g_malloc(sizeof (dissector_plugin));
478         plugin->register_protoinfo = register_protoinfo;
479         plugin->reg_handoff = reg_handoff;
480         dissector_plugins = g_slist_prepend(dissector_plugins, plugin);
481         return TRUE;
482 }
483
484 static void
485 register_dissector_plugin(gpointer data, gpointer user_data _U_)
486 {
487         dissector_plugin *plugin = (dissector_plugin *)data;
488
489         if (plugin->register_protoinfo)
490                 (plugin->register_protoinfo)();
491 }
492
493 static void
494 reg_handoff_dissector_plugin(gpointer data, gpointer user_data _U_)
495 {
496         dissector_plugin *plugin = (dissector_plugin *)data;
497
498         if (plugin->reg_handoff)
499                 (plugin->reg_handoff)();
500 }
501
502 /*
503  * Register dissector plugin type.
504  */
505 void
506 register_dissector_plugin_type(void)
507 {
508         add_plugin_type("dissector", check_for_dissector_plugin);
509 }
510
511 static void
512 dissector_plugin_destroy(gpointer p)
513 {
514         g_free(p);
515 }
516
517 #endif /* HAVE_PLUGINS */
518
519 /* initialize data structures and register protocols and fields */
520 void
521 proto_init(void (register_all_protocols_func)(register_cb cb, gpointer client_data),
522            void (register_all_handoffs_func)(register_cb cb, gpointer client_data),
523            register_cb cb,
524            gpointer client_data)
525 {
526         proto_cleanup_base();
527
528         proto_names        = g_hash_table_new_full(g_int_hash, g_int_equal, g_free, NULL);
529         proto_short_names  = g_hash_table_new(wrs_str_hash, g_str_equal);
530         proto_filter_names = g_hash_table_new(wrs_str_hash, g_str_equal);
531
532         gpa_hfinfo.len           = 0;
533         gpa_hfinfo.allocated_len = 0;
534         gpa_hfinfo.hfi           = NULL;
535         gpa_name_map             = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, save_same_name_hfinfo);
536         deregistered_fields      = g_ptr_array_new();
537         deregistered_data        = g_ptr_array_new();
538
539         /* Initialize the ftype subsystem */
540         ftypes_initialize();
541
542         /* Initialize the addres type subsystem */
543         address_types_initialize();
544
545         /* Register one special-case FT_TEXT_ONLY field for use when
546            converting wireshark to new-style proto_tree. These fields
547            are merely strings on the GUI tree; they are not filterable */
548         hf_text_only = proto_register_field_init(&hfi_text_only, -1);
549
550         /* Register the pseudo-protocols used for exceptions. */
551         register_show_exception();
552         register_type_length_mismatch();
553         register_number_string_decoding_error();
554
555         /* Have each built-in dissector register its protocols, fields,
556            dissector tables, and dissectors to be called through a
557            handle, and do whatever one-time initialization it needs to
558            do. */
559         register_all_protocols_func(cb, client_data);
560
561         /* Now that the VINES dissector has registered it's address
562            type, grab the value for the field type */
563         vines_address_type = address_type_get_by_name("AT_VINES");
564 #ifdef HAVE_PLUGINS
565         /* Now call the registration routines for all disssector
566            plugins. */
567         if (cb)
568                 (*cb)(RA_PLUGIN_REGISTER, NULL, client_data);
569         g_slist_foreach(dissector_plugins, register_dissector_plugin, NULL);
570 #endif
571
572         /* Now call the "handoff registration" routines of all built-in
573            dissectors; those routines register the dissector in other
574            dissectors' handoff tables, and fetch any dissector handles
575            they need. */
576         register_all_handoffs_func(cb, client_data);
577
578 #ifdef HAVE_PLUGINS
579         /* Now do the same with plugins. */
580         if (cb)
581                 (*cb)(RA_PLUGIN_HANDOFF, NULL, client_data);
582         g_slist_foreach(dissector_plugins, reg_handoff_dissector_plugin, NULL);
583 #endif
584
585         /* sort the protocols by protocol name */
586         protocols = g_list_sort(protocols, proto_compare_name);
587
588         /* We've assigned all the subtree type values; allocate the array
589            for them, and zero it out. */
590         tree_is_expanded = g_new0(guint32, (num_tree_types/32)+1);
591 }
592
593 static void
594 proto_cleanup_base(void)
595 {
596         protocol_t *protocol;
597         header_field_info *hfinfo;
598
599         /* Free the abbrev/ID hash table */
600         if (gpa_name_map) {
601                 g_hash_table_destroy(gpa_name_map);
602                 gpa_name_map = NULL;
603         }
604         g_free(last_field_name);
605         last_field_name = NULL;
606
607         while (protocols) {
608                 protocol = (protocol_t *)protocols->data;
609                 PROTO_REGISTRAR_GET_NTH(protocol->proto_id, hfinfo);
610                 DISSECTOR_ASSERT(protocol->proto_id == hfinfo->id);
611
612                 g_slice_free(header_field_info, hfinfo);
613                 if (protocol->fields) {
614                         g_ptr_array_free(protocol->fields, TRUE);
615                 }
616                 g_list_free(protocol->heur_list);
617                 protocols = g_list_remove(protocols, protocol);
618                 g_free(protocol);
619         }
620
621         while (pino_protocols) {
622                 protocol = (protocol_t *)pino_protocols->data;
623                 PROTO_REGISTRAR_GET_NTH(protocol->proto_id, hfinfo);
624                 DISSECTOR_ASSERT(protocol->proto_id == hfinfo->id);
625                 DISSECTOR_ASSERT(protocol->fields == NULL); //helpers should not have any registered fields
626                 g_slice_free(header_field_info, hfinfo);
627                 DISSECTOR_ASSERT(protocol->heur_list == NULL); //helpers should not have a heuristic list
628                 pino_protocols = g_list_remove(pino_protocols, protocol);
629                 g_free(protocol);
630         }
631
632         if (proto_names) {
633                 g_hash_table_destroy(proto_names);
634                 proto_names = NULL;
635         }
636
637         if (proto_short_names) {
638                 g_hash_table_destroy(proto_short_names);
639                 proto_short_names = NULL;
640         }
641
642         if (proto_filter_names) {
643                 g_hash_table_destroy(proto_filter_names);
644                 proto_filter_names = NULL;
645         }
646
647         if (gpa_hfinfo.allocated_len) {
648                 gpa_hfinfo.len           = 0;
649                 gpa_hfinfo.allocated_len = 0;
650                 g_free(gpa_hfinfo.hfi);
651                 gpa_hfinfo.hfi           = NULL;
652         }
653
654         if (deregistered_fields) {
655                 g_ptr_array_free(deregistered_fields, FALSE);
656                 deregistered_fields = NULL;
657         }
658
659         if (deregistered_data) {
660                 g_ptr_array_free(deregistered_data, FALSE);
661                 deregistered_data = NULL;
662         }
663
664         g_free(tree_is_expanded);
665         tree_is_expanded = NULL;
666
667         if (prefixes)
668                 g_hash_table_destroy(prefixes);
669 }
670
671 void
672 proto_cleanup(void)
673 {
674         proto_cleanup_base();
675
676 #ifdef HAVE_PLUGINS
677         if (dissector_plugins) {
678                 g_slist_free_full(dissector_plugins, dissector_plugin_destroy);
679                 dissector_plugins = NULL;
680         }
681 #endif
682 }
683
684 static gboolean
685 proto_tree_traverse_pre_order(proto_tree *tree, proto_tree_traverse_func func,
686                               gpointer data)
687 {
688         proto_node *pnode = tree;
689         proto_node *child;
690         proto_node *current;
691
692         if (func(pnode, data))
693                 return TRUE;
694
695         child = pnode->first_child;
696         while (child != NULL) {
697                 /*
698                  * The routine we call might modify the child, e.g. by
699                  * freeing it, so we get the child's successor before
700                  * calling that routine.
701                  */
702                 current = child;
703                 child   = current->next;
704                 if (proto_tree_traverse_pre_order((proto_tree *)current, func, data))
705                         return TRUE;
706         }
707
708         return FALSE;
709 }
710
711 gboolean
712 proto_tree_traverse_post_order(proto_tree *tree, proto_tree_traverse_func func,
713                                gpointer data)
714 {
715         proto_node *pnode = tree;
716         proto_node *child;
717         proto_node *current;
718
719         child = pnode->first_child;
720         while (child != NULL) {
721                 /*
722                  * The routine we call might modify the child, e.g. by
723                  * freeing it, so we get the child's successor before
724                  * calling that routine.
725                  */
726                 current = child;
727                 child   = current->next;
728                 if (proto_tree_traverse_post_order((proto_tree *)current, func, data))
729                         return TRUE;
730         }
731         if (func(pnode, data))
732                 return TRUE;
733
734         return FALSE;
735 }
736
737 void
738 proto_tree_children_foreach(proto_tree *tree, proto_tree_foreach_func func,
739                             gpointer data)
740 {
741         proto_node *node = tree;
742         proto_node *current;
743
744         if (!node)
745                 return;
746
747         node = node->first_child;
748         while (node != NULL) {
749                 current = node;
750                 node    = current->next;
751                 func((proto_tree *)current, data);
752         }
753 }
754
755 static void
756 free_GPtrArray_value(gpointer key, gpointer value, gpointer user_data _U_)
757 {
758         GPtrArray         *ptrs = (GPtrArray *)value;
759         gint               hfid = GPOINTER_TO_UINT(key);
760         header_field_info *hfinfo;
761
762         PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
763         if (hfinfo->ref_type != HF_REF_TYPE_NONE) {
764                 /* when a field is referenced by a filter this also
765                    affects the refcount for the parent protocol so we need
766                    to adjust the refcount for the parent as well
767                 */
768                 if (hfinfo->parent != -1) {
769                         header_field_info *parent_hfinfo;
770                         PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
771                         parent_hfinfo->ref_type = HF_REF_TYPE_NONE;
772                 }
773                 hfinfo->ref_type = HF_REF_TYPE_NONE;
774         }
775
776         g_ptr_array_free(ptrs, TRUE);
777 }
778
779 static void
780 proto_tree_free_node(proto_node *node, gpointer data _U_)
781 {
782         field_info *finfo  = PNODE_FINFO(node);
783
784         proto_tree_children_foreach(node, proto_tree_free_node, NULL);
785
786         FVALUE_CLEANUP(&finfo->value);
787 }
788
789 void
790 proto_tree_reset(proto_tree *tree)
791 {
792         tree_data_t *tree_data = PTREE_DATA(tree);
793
794         proto_tree_children_foreach(tree, proto_tree_free_node, NULL);
795
796         /* free tree data */
797         if (tree_data->interesting_hfids) {
798                 /* Free all the GPtrArray's in the interesting_hfids hash. */
799                 g_hash_table_foreach(tree_data->interesting_hfids,
800                         free_GPtrArray_value, NULL);
801
802                 /* And then remove all values. */
803                 g_hash_table_remove_all(tree_data->interesting_hfids);
804         }
805
806         /* Reset track of the number of children */
807         tree_data->count = 0;
808
809         PROTO_NODE_INIT(tree);
810 }
811
812 /* frees the resources that the dissection a proto_tree uses */
813 void
814 proto_tree_free(proto_tree *tree)
815 {
816         tree_data_t *tree_data = PTREE_DATA(tree);
817
818         proto_tree_children_foreach(tree, proto_tree_free_node, NULL);
819
820         /* free tree data */
821         if (tree_data->interesting_hfids) {
822                 /* Free all the GPtrArray's in the interesting_hfids hash. */
823                 g_hash_table_foreach(tree_data->interesting_hfids,
824                         free_GPtrArray_value, NULL);
825
826                 /* And then destroy the hash. */
827                 g_hash_table_destroy(tree_data->interesting_hfids);
828         }
829
830         g_slice_free(tree_data_t, tree_data);
831
832         g_slice_free(proto_tree, tree);
833 }
834
835 /* Is the parsing being done for a visible proto_tree or an invisible one?
836  * By setting this correctly, the proto_tree creation is sped up by not
837  * having to call g_vsnprintf and copy strings around.
838  */
839 gboolean
840 proto_tree_set_visible(proto_tree *tree, gboolean visible)
841 {
842         gboolean old_visible = PTREE_DATA(tree)->visible;
843
844         PTREE_DATA(tree)->visible = visible;
845
846         return old_visible;
847 }
848
849 void
850 proto_tree_set_fake_protocols(proto_tree *tree, gboolean fake_protocols)
851 {
852         PTREE_DATA(tree)->fake_protocols = fake_protocols;
853 }
854
855 /* Assume dissector set only its protocol fields.
856    This function is called by dissectors and allows the speeding up of filtering
857    in wireshark; if this function returns FALSE it is safe to reset tree to NULL
858    and thus skip calling most of the expensive proto_tree_add_...()
859    functions.
860    If the tree is visible we implicitly assume the field is referenced.
861 */
862 gboolean
863 proto_field_is_referenced(proto_tree *tree, int proto_id)
864 {
865         register header_field_info *hfinfo;
866
867
868         if (!tree)
869                 return FALSE;
870
871         if (PTREE_DATA(tree)->visible)
872                 return TRUE;
873
874         PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
875         if (hfinfo->ref_type != HF_REF_TYPE_NONE)
876                 return TRUE;
877
878         if (hfinfo->type == FT_PROTOCOL && !PTREE_DATA(tree)->fake_protocols)
879                 return TRUE;
880
881         return FALSE;
882 }
883
884
885 /* Finds a record in the hfinfo array by id. */
886 header_field_info *
887 proto_registrar_get_nth(guint hfindex)
888 {
889         register header_field_info *hfinfo;
890
891         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
892         return hfinfo;
893 }
894
895
896 /*      Prefix initialization
897  *        this allows for a dissector to register a display filter name prefix
898  *        so that it can delay the initialization of the hf array as long as
899  *        possible.
900  */
901
902 /* compute a hash for the part before the dot of a display filter */
903 static guint
904 prefix_hash (gconstpointer key) {
905         /* end the string at the dot and compute its hash */
906         gchar* copy = g_strdup((const gchar *)key);
907         gchar* c    = copy;
908         guint tmp;
909
910         for (; *c; c++) {
911                 if (*c == '.') {
912                         *c = 0;
913                         break;
914                 }
915         }
916
917         tmp = g_str_hash(copy);
918         g_free(copy);
919         return tmp;
920 }
921
922 /* are both strings equal up to the end or the dot? */
923 static gboolean
924 prefix_equal (gconstpointer ap, gconstpointer bp) {
925         const gchar* a = (const gchar *)ap;
926         const gchar* b = (const gchar *)bp;
927
928         do {
929                 gchar ac = *a++;
930                 gchar bc = *b++;
931
932                 if ( (ac == '.' || ac == '\0') &&   (bc == '.' || bc == '\0') ) return TRUE;
933
934                 if ( (ac == '.' || ac == '\0') && ! (bc == '.' || bc == '\0') ) return FALSE;
935                 if ( (bc == '.' || bc == '\0') && ! (ac == '.' || ac == '\0') ) return FALSE;
936
937                 if (ac != bc) return FALSE;
938         } while (1);
939
940         return FALSE;
941 }
942
943 /* Register a new prefix for "delayed" initialization of field arrays */
944 void
945 proto_register_prefix(const char *prefix, prefix_initializer_t pi ) {
946         if (! prefixes ) {
947                 prefixes = g_hash_table_new(prefix_hash, prefix_equal);
948         }
949
950         g_hash_table_insert(prefixes, (gpointer)prefix, (gpointer)pi);
951 }
952
953 /* helper to call all prefix initializers */
954 static gboolean
955 initialize_prefix(gpointer k, gpointer v, gpointer u _U_) {
956         ((prefix_initializer_t)v)((const char *)k);
957         return TRUE;
958 }
959
960 /** Initialize every remaining uninitialized prefix. */
961 void
962 proto_initialize_all_prefixes(void) {
963         g_hash_table_foreach_remove(prefixes, initialize_prefix, NULL);
964 }
965
966 /* Finds a record in the hfinfo array by name.
967  * If it fails to find it in the already registered fields,
968  * it tries to find and call an initializer in the prefixes
969  * table and if so it looks again.
970  */
971
972 header_field_info *
973 proto_registrar_get_byname(const char *field_name)
974 {
975         header_field_info    *hfinfo;
976         prefix_initializer_t  pi;
977
978         if (!field_name)
979                 return NULL;
980
981         if (g_strcmp0(field_name, last_field_name) == 0) {
982                 return last_hfinfo;
983         }
984
985         hfinfo = (header_field_info *)g_hash_table_lookup(gpa_name_map, field_name);
986
987         if (hfinfo) {
988                 g_free(last_field_name);
989                 last_field_name = g_strdup(field_name);
990                 last_hfinfo = hfinfo;
991                 return hfinfo;
992         }
993
994         if (!prefixes)
995                 return NULL;
996
997         if ((pi = (prefix_initializer_t)g_hash_table_lookup(prefixes, field_name) ) != NULL) {
998                 pi(field_name);
999                 g_hash_table_remove(prefixes, field_name);
1000         } else {
1001                 return NULL;
1002         }
1003
1004         hfinfo = (header_field_info *)g_hash_table_lookup(gpa_name_map, field_name);
1005
1006         if (hfinfo) {
1007                 g_free(last_field_name);
1008                 last_field_name = g_strdup(field_name);
1009                 last_hfinfo = hfinfo;
1010         }
1011         return hfinfo;
1012 }
1013
1014 int
1015 proto_registrar_get_id_byname(const char *field_name)
1016 {
1017         header_field_info *hfinfo;
1018
1019         hfinfo = proto_registrar_get_byname(field_name);
1020
1021         if (!hfinfo)
1022                 return -1;
1023
1024         return hfinfo->id;
1025 }
1026
1027
1028 static void
1029 ptvcursor_new_subtree_levels(ptvcursor_t *ptvc)
1030 {
1031         subtree_lvl *pushed_tree;
1032
1033         DISSECTOR_ASSERT(ptvc->pushed_tree_max <= SUBTREE_MAX_LEVELS-SUBTREE_ONCE_ALLOCATION_NUMBER);
1034         ptvc->pushed_tree_max += SUBTREE_ONCE_ALLOCATION_NUMBER;
1035
1036         pushed_tree = (subtree_lvl *)wmem_alloc(wmem_packet_scope(), sizeof(subtree_lvl) * ptvc->pushed_tree_max);
1037         DISSECTOR_ASSERT(pushed_tree != NULL);
1038         if (ptvc->pushed_tree)
1039                 memcpy(pushed_tree, ptvc->pushed_tree, ptvc->pushed_tree_max - SUBTREE_ONCE_ALLOCATION_NUMBER);
1040         ptvc->pushed_tree = pushed_tree;
1041 }
1042
1043 static void
1044 ptvcursor_free_subtree_levels(ptvcursor_t *ptvc)
1045 {
1046         ptvc->pushed_tree       = NULL;
1047         ptvc->pushed_tree_max   = 0;
1048         DISSECTOR_ASSERT(ptvc->pushed_tree_index == 0);
1049         ptvc->pushed_tree_index = 0;
1050 }
1051
1052 /* Allocates an initializes a ptvcursor_t with 3 variables:
1053  *      proto_tree, tvbuff, and offset. */
1054 ptvcursor_t *
1055 ptvcursor_new(proto_tree *tree, tvbuff_t *tvb, gint offset)
1056 {
1057         ptvcursor_t *ptvc;
1058
1059         ptvc                    = (ptvcursor_t *)wmem_alloc(wmem_packet_scope(), sizeof(ptvcursor_t));
1060         ptvc->tree              = tree;
1061         ptvc->tvb               = tvb;
1062         ptvc->offset            = offset;
1063         ptvc->pushed_tree       = NULL;
1064         ptvc->pushed_tree_max   = 0;
1065         ptvc->pushed_tree_index = 0;
1066         return ptvc;
1067 }
1068
1069
1070 /* Frees memory for ptvcursor_t, but nothing deeper than that. */
1071 void
1072 ptvcursor_free(ptvcursor_t *ptvc)
1073 {
1074         ptvcursor_free_subtree_levels(ptvc);
1075         /*g_free(ptvc);*/
1076 }
1077
1078 /* Returns tvbuff. */
1079 tvbuff_t *
1080 ptvcursor_tvbuff(ptvcursor_t *ptvc)
1081 {
1082         return ptvc->tvb;
1083 }
1084
1085 /* Returns current offset. */
1086 gint
1087 ptvcursor_current_offset(ptvcursor_t *ptvc)
1088 {
1089         return ptvc->offset;
1090 }
1091
1092 proto_tree *
1093 ptvcursor_tree(ptvcursor_t *ptvc)
1094 {
1095         if (!ptvc)
1096                 return NULL;
1097
1098         return ptvc->tree;
1099 }
1100
1101 void
1102 ptvcursor_set_tree(ptvcursor_t *ptvc, proto_tree *tree)
1103 {
1104         ptvc->tree = tree;
1105 }
1106
1107 /* creates a subtree, sets it as the working tree and pushes the old working tree */
1108 proto_tree *
1109 ptvcursor_push_subtree(ptvcursor_t *ptvc, proto_item *it, gint ett_subtree)
1110 {
1111         subtree_lvl *subtree;
1112         if (ptvc->pushed_tree_index >= ptvc->pushed_tree_max)
1113                 ptvcursor_new_subtree_levels(ptvc);
1114
1115         subtree = ptvc->pushed_tree + ptvc->pushed_tree_index;
1116         subtree->tree = ptvc->tree;
1117         subtree->it= NULL;
1118         ptvc->pushed_tree_index++;
1119         return ptvcursor_set_subtree(ptvc, it, ett_subtree);
1120 }
1121
1122 /* pops a subtree */
1123 void
1124 ptvcursor_pop_subtree(ptvcursor_t *ptvc)
1125 {
1126         subtree_lvl *subtree;
1127
1128         if (ptvc->pushed_tree_index <= 0)
1129                 return;
1130
1131         ptvc->pushed_tree_index--;
1132         subtree = ptvc->pushed_tree + ptvc->pushed_tree_index;
1133         if (subtree->it != NULL)
1134                 proto_item_set_len(subtree->it, ptvcursor_current_offset(ptvc) - subtree->cursor_offset);
1135
1136         ptvc->tree = subtree->tree;
1137 }
1138
1139 /* saves the current tvb offset and the item in the current subtree level */
1140 static void
1141 ptvcursor_subtree_set_item(ptvcursor_t *ptvc, proto_item *it)
1142 {
1143         subtree_lvl *subtree;
1144
1145         DISSECTOR_ASSERT(ptvc->pushed_tree_index > 0);
1146
1147         subtree                = ptvc->pushed_tree + ptvc->pushed_tree_index - 1;
1148         subtree->it            = it;
1149         subtree->cursor_offset = ptvcursor_current_offset(ptvc);
1150 }
1151
1152 /* Creates a subtree and adds it to the cursor as the working tree but does not
1153  * save the old working tree */
1154 proto_tree *
1155 ptvcursor_set_subtree(ptvcursor_t *ptvc, proto_item *it, gint ett_subtree)
1156 {
1157         ptvc->tree = proto_item_add_subtree(it, ett_subtree);
1158         return ptvc->tree;
1159 }
1160
1161 static proto_tree *
1162 ptvcursor_add_subtree_item(ptvcursor_t *ptvc, proto_item *it, gint ett_subtree, gint length)
1163 {
1164         ptvcursor_push_subtree(ptvc, it, ett_subtree);
1165         if (length == SUBTREE_UNDEFINED_LENGTH)
1166                 ptvcursor_subtree_set_item(ptvc, it);
1167         return ptvcursor_tree(ptvc);
1168 }
1169
1170 /* Add an item to the tree and create a subtree
1171  * If the length is unknown, length may be defined as SUBTREE_UNDEFINED_LENGTH.
1172  * In this case, when the subtree will be closed, the parent item length will
1173  * be equal to the advancement of the cursor since the creation of the subtree.
1174  */
1175 proto_tree *
1176 ptvcursor_add_with_subtree(ptvcursor_t *ptvc, int hfindex, gint length,
1177                            const guint encoding, gint ett_subtree)
1178 {
1179         proto_item *it;
1180
1181         it = ptvcursor_add_no_advance(ptvc, hfindex, length, encoding);
1182         return ptvcursor_add_subtree_item(ptvc, it, ett_subtree, length);
1183 }
1184
1185 static proto_item *
1186 proto_tree_add_text_node(proto_tree *tree, tvbuff_t *tvb, gint start, gint length);
1187
1188 /* Add a text node to the tree and create a subtree
1189  * If the length is unknown, length may be defined as SUBTREE_UNDEFINED_LENGTH.
1190  * In this case, when the subtree will be closed, the item length will be equal
1191  * to the advancement of the cursor since the creation of the subtree.
1192  */
1193 proto_tree *
1194 ptvcursor_add_text_with_subtree(ptvcursor_t *ptvc, gint length,
1195                                 gint ett_subtree, const char *format, ...)
1196 {
1197         proto_item        *pi;
1198         va_list            ap;
1199         header_field_info *hfinfo;
1200         proto_tree        *tree;
1201
1202         tree = ptvcursor_tree(ptvc);
1203
1204         CHECK_FOR_NULL_TREE(tree);
1205
1206         TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
1207
1208         pi = proto_tree_add_text_node(tree, ptvcursor_tvbuff(ptvc),
1209                                       ptvcursor_current_offset(ptvc), length);
1210
1211         TRY_TO_FAKE_THIS_REPR(pi);
1212
1213         va_start(ap, format);
1214         proto_tree_set_representation(pi, format, ap);
1215         va_end(ap);
1216
1217         return ptvcursor_add_subtree_item(ptvc, pi, ett_subtree, length);
1218 }
1219
1220 /* Add a text-only node, leaving it to our caller to fill the text in */
1221 static proto_item *
1222 proto_tree_add_text_node(proto_tree *tree, tvbuff_t *tvb, gint start, gint length)
1223 {
1224         proto_item *pi;
1225
1226         if (tree == NULL)
1227                 return NULL;
1228
1229         pi = proto_tree_add_pi(tree, &hfi_text_only, tvb, start, &length);
1230
1231         return pi;
1232 }
1233
1234 /* (INTERNAL USE ONLY) Add a text-only node to the proto_tree */
1235 proto_item *
1236 proto_tree_add_text_internal(proto_tree *tree, tvbuff_t *tvb, gint start, gint length,
1237                     const char *format, ...)
1238 {
1239         proto_item        *pi;
1240         va_list            ap;
1241         header_field_info *hfinfo;
1242
1243         if (length == -1) {
1244                 /* If we're fetching until the end of the TVB, only validate
1245                  * that the offset is within range.
1246                  */
1247                 length = 0;
1248         }
1249         tvb_ensure_bytes_exist(tvb, start, length);
1250
1251         CHECK_FOR_NULL_TREE(tree);
1252
1253         TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
1254
1255         pi = proto_tree_add_text_node(tree, tvb, start, length);
1256
1257         TRY_TO_FAKE_THIS_REPR(pi);
1258
1259         va_start(ap, format);
1260         proto_tree_set_representation(pi, format, ap);
1261         va_end(ap);
1262
1263         return pi;
1264 }
1265
1266 /* (INTERNAL USE ONLY) Add a text-only node to the proto_tree (va_list version) */
1267 proto_item *
1268 proto_tree_add_text_valist_internal(proto_tree *tree, tvbuff_t *tvb, gint start,
1269                            gint length, const char *format, va_list ap)
1270 {
1271         proto_item        *pi;
1272         header_field_info *hfinfo;
1273
1274         if (length == -1) {
1275                 /* If we're fetching until the end of the TVB, only validate
1276                  * that the offset is within range.
1277                  */
1278                 length = 0;
1279         }
1280         tvb_ensure_bytes_exist(tvb, start, length);
1281
1282         CHECK_FOR_NULL_TREE(tree);
1283
1284         TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
1285
1286         pi = proto_tree_add_text_node(tree, tvb, start, length);
1287
1288         TRY_TO_FAKE_THIS_REPR(pi);
1289
1290         proto_tree_set_representation(pi, format, ap);
1291
1292         return pi;
1293 }
1294
1295 /* Add a text-only node that creates a subtree underneath.
1296  */
1297 proto_tree *
1298 proto_tree_add_subtree(proto_tree *tree, tvbuff_t *tvb, gint start, gint length, gint idx, proto_item **tree_item, const char *text)
1299 {
1300         return proto_tree_add_subtree_format(tree, tvb, start, length, idx, tree_item, "%s", text);
1301 }
1302
1303 /* Add a text-only node that creates a subtree underneath.
1304  */
1305 proto_tree *
1306 proto_tree_add_subtree_format(proto_tree *tree, tvbuff_t *tvb, gint start, gint length, gint idx, proto_item **tree_item, const char *format, ...)
1307 {
1308         proto_tree *pt;
1309         proto_item *pi;
1310         va_list     ap;
1311
1312         va_start(ap, format);
1313         pi = proto_tree_add_text_valist_internal(tree, tvb, start, length, format, ap);
1314         va_end(ap);
1315
1316         if (tree_item != NULL)
1317                 *tree_item = pi;
1318
1319         pt = proto_item_add_subtree(pi, idx);
1320
1321         return pt;
1322 }
1323
1324 /* Add a text-only node for debugging purposes. The caller doesn't need
1325  * to worry about tvbuff, start, or length. Debug message gets sent to
1326  * STDOUT, too */
1327 proto_item *
1328 proto_tree_add_debug_text(proto_tree *tree, const char *format, ...)
1329 {
1330         proto_item *pi;
1331         va_list     ap;
1332
1333         pi = proto_tree_add_text_node(tree, NULL, 0, 0);
1334
1335         if (pi) {
1336                 va_start(ap, format);
1337                 proto_tree_set_representation(pi, format, ap);
1338                 va_end(ap);
1339         }
1340         va_start(ap, format);
1341         vprintf(format, ap);
1342         va_end(ap);
1343         ws_debug_printf("\n");
1344
1345         return pi;
1346 }
1347
1348 proto_item *
1349 proto_tree_add_format_text(proto_tree *tree, tvbuff_t *tvb, gint start, gint length)
1350 {
1351         proto_item        *pi;
1352         header_field_info *hfinfo;
1353
1354         CHECK_FOR_NULL_TREE(tree);
1355
1356         TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
1357
1358         pi = proto_tree_add_text_node(tree, tvb, start, length);
1359
1360         TRY_TO_FAKE_THIS_REPR(pi);
1361
1362         proto_item_set_text(pi, "%s", tvb_format_text(tvb, start, length));
1363
1364         return pi;
1365 }
1366
1367 proto_item *
1368 proto_tree_add_format_wsp_text(proto_tree *tree, tvbuff_t *tvb, gint start, gint length)
1369 {
1370         proto_item        *pi;
1371         header_field_info *hfinfo;
1372     gchar* str;
1373
1374         CHECK_FOR_NULL_TREE(tree);
1375
1376         TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
1377
1378         pi = proto_tree_add_text_node(tree, tvb, start, length);
1379
1380         TRY_TO_FAKE_THIS_REPR(pi);
1381
1382         str = tvb_format_text_wsp(NULL, tvb, start, length);
1383         proto_item_set_text(pi, "%s", str);
1384         wmem_free(NULL, str);
1385
1386         return pi;
1387 }
1388
1389 void proto_report_dissector_bug(const char *message)
1390 {
1391         if (getenv("WIRESHARK_ABORT_ON_DISSECTOR_BUG") != NULL)
1392                 abort();
1393         else
1394                 THROW_MESSAGE(DissectorError, message);
1395 }
1396
1397 /* We could probably get away with changing is_error to a minimum length value. */
1398 static void
1399 report_type_length_mismatch(proto_tree *tree, const gchar *descr, int length, gboolean is_error) {
1400
1401         if (is_error) {
1402                 expert_add_info_format(NULL, tree, &ei_type_length_mismatch_error, "Trying to fetch %s with length %d", descr, length);
1403         } else {
1404                 expert_add_info_format(NULL, tree, &ei_type_length_mismatch_warn, "Trying to fetch %s with length %d", descr, length);
1405         }
1406
1407         if (is_error) {
1408                 THROW(ReportedBoundsError);
1409         }
1410 }
1411
1412 static guint32
1413 get_uint_value(proto_tree *tree, tvbuff_t *tvb, gint offset, gint length, const guint encoding)
1414 {
1415         guint32 value;
1416         gboolean length_error;
1417
1418         switch (length) {
1419
1420         case 1:
1421                 value = tvb_get_guint8(tvb, offset);
1422                 break;
1423
1424         case 2:
1425                 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letohs(tvb, offset)
1426                                                        : tvb_get_ntohs(tvb, offset);
1427                 break;
1428
1429         case 3:
1430                 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letoh24(tvb, offset)
1431                                                        : tvb_get_ntoh24(tvb, offset);
1432                 break;
1433
1434         case 4:
1435                 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letohl(tvb, offset)
1436                                                        : tvb_get_ntohl(tvb, offset);
1437                 break;
1438
1439         default:
1440                 if (length < 1) {
1441                         length_error = TRUE;
1442                         value = 0;
1443                 } else {
1444                         length_error = FALSE;
1445                         value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letohl(tvb, offset)
1446                                                                : tvb_get_ntohl(tvb, offset);
1447                 }
1448                 report_type_length_mismatch(tree, "an unsigned integer", length, length_error);
1449                 break;
1450         }
1451         return value;
1452 }
1453
1454 static inline guint64
1455 get_uint64_value(proto_tree *tree, tvbuff_t *tvb, gint offset, guint length, const guint encoding)
1456 {
1457         guint64 value;
1458         gboolean length_error;
1459
1460         switch (length) {
1461
1462         case 1:
1463                 value = tvb_get_guint8(tvb, offset);
1464                 break;
1465
1466         case 2:
1467                 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letohs(tvb, offset)
1468                                                        : tvb_get_ntohs(tvb, offset);
1469                 break;
1470
1471         case 3:
1472                 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letoh24(tvb, offset)
1473                                                        : tvb_get_ntoh24(tvb, offset);
1474                 break;
1475
1476         case 4:
1477                 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letohl(tvb, offset)
1478                                                        : tvb_get_ntohl(tvb, offset);
1479                 break;
1480
1481         case 5:
1482                 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letoh40(tvb, offset)
1483                                                        : tvb_get_ntoh40(tvb, offset);
1484                 break;
1485
1486         case 6:
1487                 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letoh48(tvb, offset)
1488                                                        : tvb_get_ntoh48(tvb, offset);
1489                 break;
1490
1491         case 7:
1492                 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letoh56(tvb, offset)
1493                                                        : tvb_get_ntoh56(tvb, offset);
1494                 break;
1495
1496         case 8:
1497                 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letoh64(tvb, offset)
1498                                                        : tvb_get_ntoh64(tvb, offset);
1499                 break;
1500
1501         default:
1502                 if (length < 1) {
1503                         length_error = TRUE;
1504                         value = 0;
1505                 } else {
1506                         length_error = FALSE;
1507                         value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letoh64(tvb, offset)
1508                                                                : tvb_get_ntoh64(tvb, offset);
1509                 }
1510                 report_type_length_mismatch(tree, "an unsigned integer", length, length_error);
1511                 break;
1512         }
1513         return value;
1514 }
1515
1516 static gint32
1517 get_int_value(proto_tree *tree, tvbuff_t *tvb, gint offset, gint length, const guint encoding)
1518 {
1519         gint32 value;
1520         gboolean length_error;
1521
1522         switch (length) {
1523
1524         case 1:
1525                 value = (gint8)tvb_get_guint8(tvb, offset);
1526                 break;
1527
1528         case 2:
1529                 value = (gint16) (encoding ? tvb_get_letohs(tvb, offset)
1530                                            : tvb_get_ntohs(tvb, offset));
1531                 break;
1532
1533         case 3:
1534                 value = encoding ? tvb_get_letoh24(tvb, offset)
1535                                  : tvb_get_ntoh24(tvb, offset);
1536                 if (value & 0x00800000) {
1537                         /* Sign bit is set; sign-extend it. */
1538                         value |= 0xFF000000;
1539                 }
1540                 break;
1541
1542         case 4:
1543                 value = encoding ? tvb_get_letohl(tvb, offset)
1544                                  : tvb_get_ntohl(tvb, offset);
1545                 break;
1546
1547         default:
1548                 if (length < 1) {
1549                         length_error = TRUE;
1550                         value = 0;
1551                 } else {
1552                         length_error = FALSE;
1553                         value = encoding ? tvb_get_letohl(tvb, offset)
1554                                          : tvb_get_ntohl(tvb, offset);
1555                 }
1556                 report_type_length_mismatch(tree, "a signed integer", length, length_error);
1557                 break;
1558         }
1559         return value;
1560 }
1561
1562 /* Note: this returns an unsigned int64, but with the appropriate bit(s) set to
1563  * be cast-able as a gint64. This is weird, but what the code has always done.
1564  */
1565 static inline guint64
1566 get_int64_value(proto_tree *tree, tvbuff_t *tvb, gint start, guint length, const guint encoding)
1567 {
1568         guint64 value = get_uint64_value(tree, tvb, start, length, encoding);
1569
1570         switch(length)
1571         {
1572                 case 7:
1573                         value = ws_sign_ext64(value, 56);
1574                         break;
1575                 case 6:
1576                         value = ws_sign_ext64(value, 48);
1577                         break;
1578                 case 5:
1579                         value = ws_sign_ext64(value, 40);
1580                         break;
1581                 case 4:
1582                         value = ws_sign_ext64(value, 32);
1583                         break;
1584                 case 3:
1585                         value = ws_sign_ext64(value, 24);
1586                         break;
1587                 case 2:
1588                         value = ws_sign_ext64(value, 16);
1589                         break;
1590                 case 1:
1591                         value = ws_sign_ext64(value, 8);
1592                         break;
1593         }
1594
1595         return value;
1596 }
1597
1598 /* For FT_STRING */
1599 static inline const guint8 *
1600 get_string_value(wmem_allocator_t *scope, tvbuff_t *tvb, gint start,
1601     gint length, gint *ret_length, const guint encoding)
1602 {
1603         if (length == -1) {
1604                 length = tvb_ensure_captured_length_remaining(tvb, start);
1605         }
1606         *ret_length = length;
1607         return tvb_get_string_enc(scope, tvb, start, length, encoding);
1608 }
1609
1610 /* For FT_STRINGZ */
1611 static inline const guint8 *
1612 get_stringz_value(wmem_allocator_t *scope, proto_tree *tree, tvbuff_t *tvb,
1613     gint start, gint length, gint *ret_length, const guint encoding)
1614 {
1615         const guint8 *value;
1616
1617         if (length < -1) {
1618                 report_type_length_mismatch(tree, "a string", length, TRUE);
1619         }
1620         if (length == -1) {
1621                 /* This can throw an exception */
1622                 value = tvb_get_stringz_enc(scope, tvb, start, &length, encoding);
1623         } else if (length == 0) {
1624                 value = "[Empty]";
1625         } else {
1626                 /* In this case, length signifies the length of the string.
1627                  *
1628                  * This could either be a null-padded string, which doesn't
1629                  * necessarily have a '\0' at the end, or a null-terminated
1630                  * string, with a trailing '\0'.  (Yes, there are cases
1631                  * where you have a string that's both counted and null-
1632                  * terminated.)
1633                  *
1634                  * In the first case, we must allocate a buffer of length
1635                  * "length+1", to make room for a trailing '\0'.
1636                  *
1637                  * In the second case, we don't assume that there is a
1638                  * trailing '\0' there, as the packet might be malformed.
1639                  * (XXX - should we throw an exception if there's no
1640                  * trailing '\0'?)  Therefore, we allocate a buffer of
1641                  * length "length+1", and put in a trailing '\0', just to
1642                  * be safe.
1643                  *
1644                  * (XXX - this would change if we made string values counted
1645                  * rather than null-terminated.)
1646                  */
1647                 value = tvb_get_string_enc(scope, tvb, start, length, encoding);
1648         }
1649         *ret_length = length;
1650         return value;
1651 }
1652
1653 /* For FT_UINT_STRING */
1654 static inline const guint8 *
1655 get_uint_string_value(wmem_allocator_t *scope, proto_tree *tree,
1656     tvbuff_t *tvb, gint start, gint length, gint *ret_length,
1657     const guint encoding)
1658 {
1659         guint32 n;
1660         const guint8 *value;
1661
1662         /* I believe it's ok if this is called with a NULL tree */
1663         n = get_uint_value(tree, tvb, start, length, encoding & ~ENC_CHARENCODING_MASK);
1664         value = tvb_get_string_enc(scope, tvb, start + length, n, encoding);
1665         length += n;
1666         *ret_length = length;
1667         return value;
1668 }
1669
1670 /* For FT_STRINGZPAD */
1671 static inline const guint8 *
1672 get_stringzpad_value(wmem_allocator_t *scope, tvbuff_t *tvb, gint start,
1673     gint length, gint *ret_length, const guint encoding)
1674 {
1675         /*
1676          * XXX - currently, string values are null-
1677          * terminated, so a "zero-padded" string
1678          * isn't special.  If we represent string
1679          * values as something that includes a counted
1680          * array of bytes, we'll need to strip
1681          * trailing NULs.
1682          */
1683         if (length == -1) {
1684                 length = tvb_ensure_captured_length_remaining(tvb, start);
1685         }
1686         *ret_length = length;
1687         return tvb_get_string_enc(scope, tvb, start, length, encoding);
1688 }
1689
1690 /*
1691  * Epochs for various non-UN*X time stamp formats.
1692  */
1693 #define NTP_BASETIME G_GUINT64_CONSTANT(2208988800)     /* NTP */
1694 #define TOD_BASETIME G_GUINT64_CONSTANT(2208988800)     /* System/3x0 and z/Architecture TOD clock */
1695
1696 /* this can be called when there is no tree, so tree may be null */
1697 static void
1698 get_time_value(proto_tree *tree, tvbuff_t *tvb, const gint start,
1699                const gint length, const guint encoding, nstime_t *time_stamp,
1700                const gboolean is_relative)
1701 {
1702         guint32     tmpsecs;
1703         guint64     todsecs;
1704
1705         switch (encoding) {
1706
1707                 case ENC_TIME_TIMESPEC|ENC_BIG_ENDIAN:
1708                         /*
1709                          * 4-byte seconds, followed by 4-byte fractional
1710                          * time in nanoseconds, both big-endian.
1711                          * For absolute times, the seconds are seconds
1712                          * since the UN*X epoch.
1713                          */
1714                         time_stamp->secs  = (time_t)tvb_get_ntohl(tvb, start);
1715                         if (length == 8)
1716                                 time_stamp->nsecs = tvb_get_ntohl(tvb, start+4);
1717                         else if (length == 4) {
1718                                 /*
1719                                  * Backwards compatibility.
1720                                  */
1721                                 time_stamp->nsecs = 0;
1722                         } else
1723                                 report_type_length_mismatch(tree, "a timespec", length, TRUE);
1724                         break;
1725
1726                 case ENC_TIME_TIMESPEC|ENC_LITTLE_ENDIAN:
1727                         /*
1728                          * 4-byte UNIX epoch, possibly followed by
1729                          * 4-byte fractional time in nanoseconds,
1730                          * both little-endian.
1731                          * For absolute times, the seconds are seconds
1732                          * since the UN*X epoch.
1733                          */
1734                         time_stamp->secs  = (time_t)tvb_get_letohl(tvb, start);
1735                         if (length == 8)
1736                                 time_stamp->nsecs = tvb_get_letohl(tvb, start+4);
1737                         else if (length == 4) {
1738                                 /*
1739                                  * Backwards compatibility.
1740                                  */
1741                                 time_stamp->nsecs = 0;
1742                         } else
1743                                 report_type_length_mismatch(tree, "a timespec", length, TRUE);
1744                         break;
1745
1746                 case ENC_TIME_NTP|ENC_BIG_ENDIAN:
1747                         /*
1748                          * NTP time stamp, big-endian.
1749                          * Only supported for absolute times.
1750                          */
1751                         DISSECTOR_ASSERT(!is_relative);
1752
1753                         /* We need a temporary variable here so the unsigned math
1754                          * works correctly (for years > 2036 according to RFC 2030
1755                          * chapter 3).
1756                          */
1757                         tmpsecs  = tvb_get_ntohl(tvb, start);
1758                         if (tmpsecs)
1759                                 time_stamp->secs = (time_t)(tmpsecs - (guint32)NTP_BASETIME);
1760                         else
1761                                 time_stamp->secs = tmpsecs; /* 0 */
1762
1763                         if (length == 8) {
1764                                 /*
1765                                  * Convert 1/2^32s of a second to nanoseconds.
1766                                  */
1767                                 time_stamp->nsecs = (int)(1000000000*(tvb_get_ntohl(tvb, start+4)/4294967296.0));
1768                         } else if (length == 4) {
1769                                 /*
1770                                  * Backwards compatibility.
1771                                  */
1772                                 time_stamp->nsecs = 0;
1773                         } else
1774                                 report_type_length_mismatch(tree, "an NTP time stamp", length, TRUE);
1775                         break;
1776
1777                 case ENC_TIME_NTP|ENC_LITTLE_ENDIAN:
1778                         /*
1779                          * NTP time stamp, little-endian.
1780                          * Only supported for absolute times.
1781                          */
1782                         DISSECTOR_ASSERT(!is_relative);
1783
1784                         tmpsecs  = tvb_get_letohl(tvb, start);
1785                         if (tmpsecs)
1786                                 time_stamp->secs = (time_t)(tmpsecs - (guint32)NTP_BASETIME);
1787                         else
1788                                 time_stamp->secs = tmpsecs; /* 0 */
1789
1790                         if (length == 8) {
1791                                 /*
1792                                  * Convert 1/2^32s of a second to nanoseconds.
1793                                  */
1794                                 time_stamp->nsecs = (int)(1000000000*(tvb_get_letohl(tvb, start+4)/4294967296.0));
1795                         } else if (length == 4) {
1796                                 /*
1797                                  * Backwards compatibility.
1798                                  */
1799                                 time_stamp->nsecs = 0;
1800                         } else
1801                                 report_type_length_mismatch(tree, "an NTP time stamp", length, TRUE);
1802                         break;
1803
1804                 case ENC_TIME_TOD|ENC_BIG_ENDIAN:
1805                         /*
1806                          * S/3x0 and z/Architecture TOD clock time stamp,
1807                          * big-endian.
1808                          * Only supported for absolute times.
1809                          */
1810                         DISSECTOR_ASSERT(!is_relative);
1811                         DISSECTOR_ASSERT(length == 8);
1812
1813                         if (length == 8) {
1814                                 todsecs  = tvb_get_ntoh64(tvb, start) >> 12;
1815                                 time_stamp->secs = (time_t)((todsecs  / 1000000) - TOD_BASETIME);
1816                                 time_stamp->nsecs = (int)((todsecs  % 1000000) * 1000);
1817                         } else
1818                                 report_type_length_mismatch(tree, "a TOD clock time stamp", length, TRUE);
1819                         break;
1820
1821                 case ENC_TIME_TOD|ENC_LITTLE_ENDIAN:
1822                         /*
1823                          * S/3x0 and z/Architecture TOD clock time stamp,
1824                          * little-endian.
1825                          * Only supported for absolute times.
1826                          */
1827                         DISSECTOR_ASSERT(!is_relative);
1828
1829                         if (length == 8) {
1830                                 todsecs  = tvb_get_letoh64(tvb, start) >> 12 ;
1831                                 time_stamp->secs = (time_t)((todsecs  / 1000000) - TOD_BASETIME);
1832                                 time_stamp->nsecs = (int)((todsecs  % 1000000) * 1000);
1833                         } else
1834                                 report_type_length_mismatch(tree, "a TOD clock time stamp", length, TRUE);
1835                         break;
1836
1837                 case ENC_TIME_RTPS|ENC_BIG_ENDIAN:
1838                         /*
1839                          * Time stamp using the same seconds/fraction format
1840                          * as NTP, but with the origin of the time stamp being
1841                          * the UNIX epoch rather than the NTP epoch; big-
1842                          * endian.
1843                          *
1844                          * Only supported for absolute times.
1845                          */
1846                         DISSECTOR_ASSERT(!is_relative);
1847
1848                         if (length == 8) {
1849                                 time_stamp->secs = (time_t)tvb_get_ntohl(tvb, start);
1850                                 /*
1851                                  * Convert 1/2^32s of a second to nanoseconds.
1852                                  */
1853                                 time_stamp->nsecs = (int)(1000000000*(tvb_get_ntohl(tvb, start+4)/4294967296.0));
1854                         } else
1855                                 report_type_length_mismatch(tree, "an RTPS time stamp", length, TRUE);
1856                         break;
1857
1858                 case ENC_TIME_RTPS|ENC_LITTLE_ENDIAN:
1859                         /*
1860                          * Time stamp using the same seconds/fraction format
1861                          * as NTP, but with the origin of the time stamp being
1862                          * the UNIX epoch rather than the NTP epoch; little-
1863                          * endian.
1864                          *
1865                          * Only supported for absolute times.
1866                          */
1867                         DISSECTOR_ASSERT(!is_relative);
1868
1869                         if (length == 8) {
1870                                 time_stamp->secs = (time_t)tvb_get_letohl(tvb, start);
1871                                 /*
1872                                  * Convert 1/2^32s of a second to nanoseconds.
1873                                  */
1874                                 time_stamp->nsecs = (int)(1000000000*(tvb_get_letohl(tvb, start+4)/4294967296.0));
1875                         } else
1876                                 report_type_length_mismatch(tree, "an RTPS time stamp", length, TRUE);
1877                         break;
1878
1879                 case ENC_TIME_TIMEVAL|ENC_BIG_ENDIAN:
1880                         /*
1881                          * 4-byte seconds, followed by 4-byte fractional
1882                          * time in microseconds, both big-endian.
1883                          * For absolute times, the seconds are seconds
1884                          * since the UN*X epoch.
1885                          */
1886                         if (length == 8) {
1887                                 time_stamp->secs  = (time_t)tvb_get_ntohl(tvb, start);
1888                                 time_stamp->nsecs = tvb_get_ntohl(tvb, start+4)*1000;
1889                         } else
1890                                 report_type_length_mismatch(tree, "a timeval", length, TRUE);
1891                         break;
1892
1893                 case ENC_TIME_TIMEVAL|ENC_LITTLE_ENDIAN:
1894                         /*
1895                          * 4-byte seconds, followed by 4-byte fractional
1896                          * time in microseconds, both little-endian.
1897                          * For absolute times, the seconds are seconds
1898                          * since the UN*X epoch.
1899                          */
1900                         if (length == 8) {
1901                                 time_stamp->secs  = (time_t)tvb_get_letohl(tvb, start);
1902                                 time_stamp->nsecs = tvb_get_letohl(tvb, start+4)*1000;
1903                         } else
1904                                 report_type_length_mismatch(tree, "a timeval", length, TRUE);
1905                         break;
1906
1907                 case ENC_TIME_SECS|ENC_BIG_ENDIAN:
1908                 case ENC_TIME_SECS|ENC_LITTLE_ENDIAN:
1909                         /*
1910                          * Seconds, 1 to 8 bytes.
1911                          * For absolute times, it's seconds since the
1912                          * UN*X epoch.
1913                          */
1914                         if (length >= 1 && length <= 8) {
1915                                 time_stamp->secs  = (time_t)get_uint64_value(tree, tvb, start, length, encoding);
1916                                 time_stamp->nsecs = 0;
1917                         } else
1918                                 report_type_length_mismatch(tree, "a time-in-seconds time stamp", length, TRUE);
1919                         break;
1920
1921                 case ENC_TIME_MSECS|ENC_BIG_ENDIAN:
1922                         /*
1923                          * Milliseconds, 1 to 8 bytes.
1924                          * For absolute times, it's milliseconds since the
1925                          * UN*X epoch.
1926                          */
1927                         if (length >= 1 && length <= 8) {
1928                                 guint64 msecs;
1929
1930                                 msecs = get_uint64_value(tree, tvb, start, length, encoding);
1931                                 time_stamp->secs  = (time_t)(msecs / 1000);
1932                                 time_stamp->nsecs = (int)(msecs % 1000)*1000000;
1933                         } else
1934                                 report_type_length_mismatch(tree, "a time-in-milliseconds time stamp", length, TRUE);
1935                         break;
1936
1937                 case ENC_TIME_RFC_3971|ENC_BIG_ENDIAN:
1938                         /*
1939                          * 1/64ths of a second since the UN*X epoch,
1940                          * big-endian.
1941                          *
1942                          * Only supported for absolute times.
1943                          */
1944                         DISSECTOR_ASSERT(!is_relative);
1945
1946                         if (length == 8) {
1947                                 /*
1948                                  * The upper 48 bits are seconds since the
1949                                  * UN*X epoch.
1950                                  */
1951                                 time_stamp->secs  = tvb_get_ntoh48(tvb, start);
1952                                 /*
1953                                  * The lower 16 bits are 1/2^16s of a second;
1954                                  * convert them to nanoseconds.
1955                                  *
1956                                  * XXX - this may give the impression of higher
1957                                  * precision than you actually get.
1958                                  */
1959                                 time_stamp->nsecs = (int)(1000000000*(tvb_get_ntohs(tvb, start+6)/65536.0));
1960                         } else
1961                                 report_type_length_mismatch(tree, "an RFC 3971-style time stamp", length, TRUE);
1962                         break;
1963
1964                 case ENC_TIME_RFC_3971|ENC_LITTLE_ENDIAN:
1965                         /*
1966                          * 1/64ths of a second since the UN*X epoch,
1967                          * little-endian.
1968                          *
1969                          * Only supported for absolute times.
1970                          */
1971                         DISSECTOR_ASSERT(!is_relative);
1972
1973                         if (length == 8) {
1974                                 /*
1975                                  * XXX - this is assuming that, if anybody
1976                                  * were ever to use this format - RFC 3971
1977                                  * doesn't, because that's an Internet
1978                                  * protocol, and those use network byte
1979                                  * order, i.e. big-endian - they'd treat it
1980                                  * as a 64-bit count of 1/2^16s of a second,
1981                                  * putting the upper 48 bits at the end.
1982                                  *
1983                                  * The lower 48 bits are seconds since the
1984                                  * UN*X epoch.
1985                                  */
1986                                 time_stamp->secs  = tvb_get_letoh48(tvb, start+2);
1987                                 /*
1988                                  * The upper 16 bits are 1/2^16s of a second;
1989                                  * convert them to nanoseconds.
1990                                  *
1991                                  * XXX - this may give the impression of higher
1992                                  * precision than you actually get.
1993                                  */
1994                                 time_stamp->nsecs = (int)(1000000000*(tvb_get_letohs(tvb, start)/65536.0));
1995                         } else
1996                                 report_type_length_mismatch(tree, "an RFC 3971-style time stamp", length, TRUE);
1997                         break;
1998
1999                 case ENC_TIME_SECS_NTP|ENC_BIG_ENDIAN:
2000                         /*
2001                          * NTP time stamp, with 1-second resolution (i.e.,
2002                          * seconds since the NTP epoch), big-endian.
2003                          * Only supported for absolute times.
2004                          */
2005                         DISSECTOR_ASSERT(!is_relative);
2006
2007                         if (length == 4) {
2008                                 /*
2009                                  * We need a temporary variable here so the
2010                                  * unsigned math works correctly (for
2011                                  * years > 2036 according to RFC 2030
2012                                  * chapter 3).
2013                                  */
2014                                 tmpsecs  = tvb_get_ntohl(tvb, start);
2015                                 if (tmpsecs)
2016                                         time_stamp->secs = (time_t)(tmpsecs - (guint32)NTP_BASETIME);
2017                                 else
2018                                         time_stamp->secs = tmpsecs; /* 0 */
2019                                 time_stamp->nsecs = 0;
2020                         } else
2021                                 report_type_length_mismatch(tree, "an NTP seconds-only time stamp", length, TRUE);
2022                         break;
2023
2024                 case ENC_TIME_SECS_NTP|ENC_LITTLE_ENDIAN:
2025                         /*
2026                          * NTP time stamp, with 1-second resolution (i.e.,
2027                          * seconds since the NTP epoch), little-endian.
2028                          * Only supported for absolute times.
2029                          */
2030                         DISSECTOR_ASSERT(!is_relative);
2031
2032                         if (length == 4) {
2033                                 tmpsecs  = tvb_get_letohl(tvb, start);
2034                                 if (tmpsecs)
2035                                         time_stamp->secs = (time_t)(tmpsecs - (guint32)NTP_BASETIME);
2036                                 else
2037                                         time_stamp->secs = tmpsecs; /* 0 */
2038                                 time_stamp->nsecs = 0;
2039                         } else
2040                                 report_type_length_mismatch(tree, "an NTP seconds-only time stamp", length, TRUE);
2041                         break;
2042                 case ENC_TIME_MSEC_NTP | ENC_BIG_ENDIAN:
2043                         /*
2044                         * Milliseconds, 1 to 8 bytes.
2045                         * For absolute times, it's milliseconds since the
2046                         * NTP epoch.
2047                         */
2048                         if (length >= 1 && length <= 8) {
2049                                 guint64 msecs;
2050
2051                                 msecs = get_uint64_value(tree, tvb, start, length, encoding);
2052                                 tmpsecs = (guint32)(msecs / 1000);
2053                                 time_stamp->secs = (time_t)(tmpsecs - (guint32)NTP_BASETIME);
2054                                 time_stamp->nsecs = (int)(msecs % 1000)*1000000;
2055                         }
2056                         else
2057                                 report_type_length_mismatch(tree, "a time-in-milliseconds NTP time stamp", length, TRUE);
2058                         break;
2059                 default:
2060                         DISSECTOR_ASSERT_NOT_REACHED();
2061                         break;
2062         }
2063 }
2064
2065 static void
2066 tree_data_add_maybe_interesting_field(tree_data_t *tree_data, field_info *fi)
2067 {
2068         const header_field_info *hfinfo = fi->hfinfo;
2069
2070         if (hfinfo->ref_type == HF_REF_TYPE_DIRECT) {
2071                 GPtrArray *ptrs = NULL;
2072
2073                 if (tree_data->interesting_hfids == NULL) {
2074                         /* Initialize the hash because we now know that it is needed */
2075                         tree_data->interesting_hfids =
2076                                 g_hash_table_new(g_direct_hash, NULL /* g_direct_equal */);
2077                 } else if (g_hash_table_size(tree_data->interesting_hfids)) {
2078                         ptrs = (GPtrArray *)g_hash_table_lookup(tree_data->interesting_hfids,
2079                                            GINT_TO_POINTER(hfinfo->id));
2080                 }
2081
2082                 if (!ptrs) {
2083                         /* First element triggers the creation of pointer array */
2084                         ptrs = g_ptr_array_new();
2085                         g_hash_table_insert(tree_data->interesting_hfids,
2086                                             GINT_TO_POINTER(hfinfo->id), ptrs);
2087                 }
2088
2089                 g_ptr_array_add(ptrs, fi);
2090         }
2091 }
2092
2093 /* Add an item to a proto_tree, using the text label registered to that item;
2094    the item is extracted from the tvbuff handed to it. */
2095 static proto_item *
2096 proto_tree_new_item(field_info *new_fi, proto_tree *tree,
2097                     tvbuff_t *tvb, gint start, gint length,
2098                     guint encoding)
2099 {
2100         proto_item *pi;
2101         guint32     value, n;
2102         float       floatval;
2103         double      doubleval;
2104         const char *stringval;
2105         nstime_t    time_stamp;
2106         gboolean    length_error;
2107
2108         switch (new_fi->hfinfo->type) {
2109                 case FT_NONE:
2110                         /* no value to set for FT_NONE */
2111                         break;
2112
2113                 case FT_PROTOCOL:
2114                         proto_tree_set_protocol_tvb(new_fi, tvb, new_fi->hfinfo->name);
2115                         break;
2116
2117                 case FT_BYTES:
2118                         proto_tree_set_bytes_tvb(new_fi, tvb, start, length);
2119                         break;
2120
2121                 case FT_UINT_BYTES:
2122                         /*
2123                          * Map all non-zero values to little-endian for
2124                          * backwards compatibility.
2125                          */
2126                         if (encoding)
2127                                 encoding = ENC_LITTLE_ENDIAN;
2128                         n = get_uint_value(tree, tvb, start, length, encoding);
2129                         proto_tree_set_bytes_tvb(new_fi, tvb, start + length, n);
2130
2131                         /* Instead of calling proto_item_set_len(), since we don't yet
2132                          * have a proto_item, we set the field_info's length ourselves. */
2133                         new_fi->length = n + length;
2134                         break;
2135
2136                 case FT_BOOLEAN:
2137                         /*
2138                          * Map all non-zero values to little-endian for
2139                          * backwards compatibility.
2140                          */
2141                         if (encoding)
2142                                 encoding = ENC_LITTLE_ENDIAN;
2143                         proto_tree_set_boolean(new_fi,
2144                                 get_uint64_value(tree, tvb, start, length, encoding));
2145                         break;
2146
2147                 case FT_CHAR:
2148                 /* XXX - make these just FT_UINT? */
2149                 case FT_UINT8:
2150                 case FT_UINT16:
2151                 case FT_UINT24:
2152                 case FT_UINT32:
2153                         /*
2154                          * Map all non-zero values to little-endian for
2155                          * backwards compatibility.
2156                          */
2157                         if (encoding)
2158                                 encoding = ENC_LITTLE_ENDIAN;
2159                         proto_tree_set_uint(new_fi,
2160                                 get_uint_value(tree, tvb, start, length, encoding));
2161                         break;
2162
2163                 case FT_UINT40:
2164                 case FT_UINT48:
2165                 case FT_UINT56:
2166                 case FT_UINT64:
2167                         /*
2168                          * Map all non-zero values to little-endian for
2169                          * backwards compatibility.
2170                          */
2171                         if (encoding)
2172                                 encoding = ENC_LITTLE_ENDIAN;
2173                         proto_tree_set_uint64(new_fi,
2174                                 get_uint64_value(tree, tvb, start, length, encoding));
2175                         break;
2176
2177                 /* XXX - make these just FT_INT? */
2178                 case FT_INT8:
2179                 case FT_INT16:
2180                 case FT_INT24:
2181                 case FT_INT32:
2182                         /*
2183                          * Map all non-zero values to little-endian for
2184                          * backwards compatibility.
2185                          */
2186                         if (encoding)
2187                                 encoding = ENC_LITTLE_ENDIAN;
2188                         proto_tree_set_int(new_fi,
2189                                 get_int_value(tree, tvb, start, length, encoding));
2190                         break;
2191
2192                 case FT_INT40:
2193                 case FT_INT48:
2194                 case FT_INT56:
2195                 case FT_INT64:
2196                         /*
2197                          * Map all non-zero values to little-endian for
2198                          * backwards compatibility.
2199                          */
2200                         if (encoding)
2201                                 encoding = ENC_LITTLE_ENDIAN;
2202                         proto_tree_set_int64(new_fi,
2203                                 get_int64_value(tree, tvb, start, length, encoding));
2204                         break;
2205
2206                 case FT_IPv4:
2207                         /*
2208                          * Map all non-zero values to little-endian for
2209                          * backwards compatibility.
2210                          */
2211                         if (encoding)
2212                                 encoding = ENC_LITTLE_ENDIAN;
2213                         if (length != FT_IPv4_LEN) {
2214                                 length_error = length < FT_IPv4_LEN ? TRUE : FALSE;
2215                                 report_type_length_mismatch(tree, "an IPv4 address", length, length_error);
2216                         }
2217                         value = tvb_get_ipv4(tvb, start);
2218                         /*
2219                          * NOTE: to support code written when
2220                          * proto_tree_add_item() took a gboolean as its
2221                          * last argument, with FALSE meaning "big-endian"
2222                          * and TRUE meaning "little-endian", we treat any
2223                          * non-zero value of "encoding" as meaning
2224                          * "little-endian".
2225                          */
2226                         proto_tree_set_ipv4(new_fi, encoding ? GUINT32_SWAP_LE_BE(value) : value);
2227                         break;
2228
2229                 case FT_IPXNET:
2230                         if (length != FT_IPXNET_LEN) {
2231                                 length_error = length < FT_IPXNET_LEN ? TRUE : FALSE;
2232                                 report_type_length_mismatch(tree, "an IPXNET address", length, length_error);
2233                         }
2234                         proto_tree_set_ipxnet(new_fi,
2235                                 get_uint_value(tree, tvb, start, FT_IPXNET_LEN, ENC_BIG_ENDIAN));
2236                         break;
2237
2238                 case FT_IPv6:
2239                         if (length != FT_IPv6_LEN) {
2240                                 length_error = length < FT_IPv6_LEN ? TRUE : FALSE;
2241                                 report_type_length_mismatch(tree, "an IPv6 address", length, length_error);
2242                         }
2243                         proto_tree_set_ipv6_tvb(new_fi, tvb, start, length);
2244                         break;
2245
2246                 case FT_FCWWN:
2247                         if (length != FT_FCWWN_LEN) {
2248                                 length_error = length < FT_FCWWN_LEN ? TRUE : FALSE;
2249                                 report_type_length_mismatch(tree, "an FCWWN address", length, length_error);
2250                         }
2251                         proto_tree_set_fcwwn_tvb(new_fi, tvb, start, length);
2252                         break;
2253
2254                 case FT_AX25:
2255                         if (length != 7) {
2256                                 length_error = length < 7 ? TRUE : FALSE;
2257                                 report_type_length_mismatch(tree, "an AX.25 address", length, length_error);
2258                         }
2259                         proto_tree_set_ax25_tvb(new_fi, tvb, start);
2260                         break;
2261
2262                 case FT_VINES:
2263                         if (length != VINES_ADDR_LEN) {
2264                                 length_error = length < VINES_ADDR_LEN ? TRUE : FALSE;
2265                                 report_type_length_mismatch(tree, "a Vines address", length, length_error);
2266                         }
2267                         proto_tree_set_vines_tvb(new_fi, tvb, start);
2268                         break;
2269
2270                 case FT_ETHER:
2271                         if (length != FT_ETHER_LEN) {
2272                                 length_error = length < FT_ETHER_LEN ? TRUE : FALSE;
2273                                 report_type_length_mismatch(tree, "a MAC address", length, length_error);
2274                         }
2275                         proto_tree_set_ether_tvb(new_fi, tvb, start);
2276                         break;
2277
2278                 case FT_EUI64:
2279                         /*
2280                          * Map all non-zero values to little-endian for
2281                          * backwards compatibility.
2282                          */
2283                         if (encoding)
2284                                 encoding = ENC_LITTLE_ENDIAN;
2285                         if (length != FT_EUI64_LEN) {
2286                                 length_error = length < FT_EUI64_LEN ? TRUE : FALSE;
2287                                 report_type_length_mismatch(tree, "an EUI-64 address", length, length_error);
2288                         }
2289                         proto_tree_set_eui64_tvb(new_fi, tvb, start, encoding);
2290                         break;
2291                 case FT_GUID:
2292                         /*
2293                          * Map all non-zero values to little-endian for
2294                          * backwards compatibility.
2295                          */
2296                         if (encoding)
2297                                 encoding = ENC_LITTLE_ENDIAN;
2298                         if (length != FT_GUID_LEN) {
2299                                 length_error = length < FT_GUID_LEN ? TRUE : FALSE;
2300                                 report_type_length_mismatch(tree, "a GUID", length, length_error);
2301                         }
2302                         proto_tree_set_guid_tvb(new_fi, tvb, start, encoding);
2303                         break;
2304
2305                 case FT_OID:
2306                 case FT_REL_OID:
2307                         proto_tree_set_oid_tvb(new_fi, tvb, start, length);
2308                         break;
2309
2310                 case FT_SYSTEM_ID:
2311                         proto_tree_set_system_id_tvb(new_fi, tvb, start, length);
2312                         break;
2313
2314                 case FT_FLOAT:
2315                         /*
2316                          * NOTE: to support code written when
2317                          * proto_tree_add_item() took a gboolean as its
2318                          * last argument, with FALSE meaning "big-endian"
2319                          * and TRUE meaning "little-endian", we treat any
2320                          * non-zero value of "encoding" as meaning
2321                          * "little-endian".
2322                          *
2323                          * At some point in the future, we might
2324                          * support non-IEEE-binary floating-point
2325                          * formats in the encoding as well
2326                          * (IEEE decimal, System/3x0, VAX).
2327                          */
2328                         if (encoding)
2329                                 encoding = ENC_LITTLE_ENDIAN;
2330                         if (length != 4) {
2331                                 length_error = length < 4 ? TRUE : FALSE;
2332                                 report_type_length_mismatch(tree, "a single-precision floating point number", length, length_error);
2333                         }
2334                         if (encoding)
2335                                 floatval = tvb_get_letohieee_float(tvb, start);
2336                         else
2337                                 floatval = tvb_get_ntohieee_float(tvb, start);
2338                         proto_tree_set_float(new_fi, floatval);
2339                         break;
2340
2341                 case FT_DOUBLE:
2342                         /*
2343                          * NOTE: to support code written when
2344                          * proto_tree_add_item() took a gboolean as its
2345                          * last argument, with FALSE meaning "big-endian"
2346                          * and TRUE meaning "little-endian", we treat any
2347                          * non-zero value of "encoding" as meaning
2348                          * "little-endian".
2349                          *
2350                          * At some point in the future, we might
2351                          * support non-IEEE-binary floating-point
2352                          * formats in the encoding as well
2353                          * (IEEE decimal, System/3x0, VAX).
2354                          */
2355                         if (encoding == TRUE)
2356                                 encoding = ENC_LITTLE_ENDIAN;
2357                         if (length != 8) {
2358                                 length_error = length < 8 ? TRUE : FALSE;
2359                                 report_type_length_mismatch(tree, "a double-precision floating point number", length, length_error);
2360                         }
2361                         if (encoding)
2362                                 doubleval = tvb_get_letohieee_double(tvb, start);
2363                         else
2364                                 doubleval = tvb_get_ntohieee_double(tvb, start);
2365                         proto_tree_set_double(new_fi, doubleval);
2366                         break;
2367
2368                 case FT_STRING:
2369                         stringval = get_string_value(wmem_packet_scope(),
2370                             tvb, start, length, &length, encoding);
2371                         proto_tree_set_string(new_fi, stringval);
2372
2373                         /* Instead of calling proto_item_set_len(), since we
2374                          * don't yet have a proto_item, we set the
2375                          * field_info's length ourselves.
2376                          *
2377                          * XXX - our caller can't use that length to
2378                          * advance an offset unless they arrange that
2379                          * there always be a protocol tree into which
2380                          * we're putting this item.
2381                          */
2382                         new_fi->length = length;
2383                         break;
2384
2385                 case FT_STRINGZ:
2386                         stringval = get_stringz_value(wmem_packet_scope(),
2387                             tree, tvb, start, length, &length, encoding);
2388                         proto_tree_set_string(new_fi, stringval);
2389
2390                         /* Instead of calling proto_item_set_len(),
2391                          * since we don't yet have a proto_item, we
2392                          * set the field_info's length ourselves.
2393                          *
2394                          * XXX - our caller can't use that length to
2395                          * advance an offset unless they arrange that
2396                          * there always be a protocol tree into which
2397                          * we're putting this item.
2398                          */
2399                         new_fi->length = length;
2400                         break;
2401
2402                 case FT_UINT_STRING:
2403                         /*
2404                          * NOTE: to support code written when
2405                          * proto_tree_add_item() took a gboolean as its
2406                          * last argument, with FALSE meaning "big-endian"
2407                          * and TRUE meaning "little-endian", if the
2408                          * encoding value is TRUE, treat that as
2409                          * ASCII with a little-endian length.
2410                          *
2411                          * This won't work for code that passes
2412                          * arbitrary non-zero values; that code
2413                          * will need to be fixed.
2414                          */
2415                         if (encoding == TRUE)
2416                                 encoding = ENC_ASCII|ENC_LITTLE_ENDIAN;
2417                         stringval = get_uint_string_value(wmem_packet_scope(),
2418                             tree, tvb, start, length, &length, encoding);
2419                         proto_tree_set_string(new_fi, stringval);
2420
2421                         /* Instead of calling proto_item_set_len(), since we
2422                          * don't yet have a proto_item, we set the
2423                          * field_info's length ourselves.
2424                          *
2425                          * XXX - our caller can't use that length to
2426                          * advance an offset unless they arrange that
2427                          * there always be a protocol tree into which
2428                          * we're putting this item.
2429                          */
2430                         new_fi->length = length;
2431                         break;
2432
2433                 case FT_STRINGZPAD:
2434                         stringval = get_stringzpad_value(wmem_packet_scope(),
2435                             tvb, start, length, &length, encoding);
2436                         proto_tree_set_string(new_fi, stringval);
2437
2438                         /* Instead of calling proto_item_set_len(), since we
2439                          * don't yet have a proto_item, we set the
2440                          * field_info's length ourselves.
2441                          *
2442                          * XXX - our caller can't use that length to
2443                          * advance an offset unless they arrange that
2444                          * there always be a protocol tree into which
2445                          * we're putting this item.
2446                          */
2447                         new_fi->length = length;
2448                         break;
2449
2450                 case FT_ABSOLUTE_TIME:
2451                         /*
2452                          * Absolute times can be in any of a number of
2453                          * formats, and they can be big-endian or
2454                          * little-endian.
2455                          *
2456                          * Historically FT_TIMEs were only timespecs;
2457                          * the only question was whether they were stored
2458                          * in big- or little-endian format.
2459                          *
2460                          * For backwards compatibility, we interpret an
2461                          * encoding of 1 as meaning "little-endian timespec",
2462                          * so that passing TRUE is interpreted as that.
2463                          */
2464                         if (encoding == TRUE)
2465                                 encoding = ENC_TIME_TIMESPEC|ENC_LITTLE_ENDIAN;
2466
2467                         if (length > 8 || length < 4) {
2468                                 length_error = length < 4 ? TRUE : FALSE;
2469                                 report_type_length_mismatch(tree, "an absolute time value", length, length_error);
2470                         }
2471
2472                         get_time_value(tree, tvb, start, length, encoding, &time_stamp, FALSE);
2473
2474                         proto_tree_set_time(new_fi, &time_stamp);
2475                         break;
2476
2477                 case FT_RELATIVE_TIME:
2478                         /*
2479                          * Relative times can be in any of a number of
2480                          * formats, and they can be big-endian or
2481                          * little-endian.
2482                          *
2483                          * Historically FT_TIMEs were only timespecs;
2484                          * the only question was whether they were stored
2485                          * in big- or little-endian format.
2486                          *
2487                          * For backwards compatibility, we interpret an
2488                          * encoding of 1 as meaning "little-endian timespec",
2489                          * so that passing TRUE is interpreted as that.
2490                          */
2491                         if (encoding == TRUE)
2492                                 encoding = ENC_TIME_TIMESPEC|ENC_LITTLE_ENDIAN;
2493
2494                         if (length != 8 && length != 4) {
2495                                 length_error = length < 4 ? TRUE : FALSE;
2496                                 report_type_length_mismatch(tree, "a relative time value", length, length_error);
2497                         }
2498
2499                         get_time_value(tree, tvb, start, length, encoding, &time_stamp, TRUE);
2500
2501                         proto_tree_set_time(new_fi, &time_stamp);
2502                         break;
2503                 case FT_IEEE_11073_SFLOAT:
2504                         if (encoding)
2505                                 encoding = ENC_LITTLE_ENDIAN;
2506                         if (length != 2) {
2507                                 length_error = length < 2 ? TRUE : FALSE;
2508                                 report_type_length_mismatch(tree, "a IEEE 11073 SFLOAT", length, length_error);
2509                         }
2510
2511                         fvalue_set_uinteger(&new_fi->value, tvb_get_guint16(tvb, start, encoding));
2512
2513                         break;
2514                 case FT_IEEE_11073_FLOAT:
2515                         if (encoding)
2516                                 encoding = ENC_LITTLE_ENDIAN;
2517                         if (length != 4) {
2518                                 length_error = length < 4 ? TRUE : FALSE;
2519                                 report_type_length_mismatch(tree, "a IEEE 11073 FLOAT", length, length_error);
2520                         }
2521
2522                         break;
2523                 default:
2524                         g_error("new_fi->hfinfo->type %d (%s) not handled\n",
2525                                         new_fi->hfinfo->type,
2526                                         ftype_name(new_fi->hfinfo->type));
2527                         DISSECTOR_ASSERT_NOT_REACHED();
2528                         break;
2529         }
2530         FI_SET_FLAG(new_fi, (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN);
2531
2532         /* Don't add new node to proto_tree until now so that any exceptions
2533          * raised by a tvbuff access method doesn't leave junk in the proto_tree. */
2534         /* XXX. wouldn't be better to add this item to tree, with some special flag (FI_EXCEPTION?)
2535          *      to know which item caused exception? */
2536         pi = proto_tree_add_node(tree, new_fi);
2537
2538         return pi;
2539 }
2540
2541 proto_item *
2542 proto_tree_add_item_ret_int(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2543                             const gint start, gint length,
2544                             const guint encoding, gint32 *retval)
2545 {
2546         header_field_info *hfinfo = proto_registrar_get_nth(hfindex);
2547         field_info        *new_fi;
2548         gint32             value;
2549
2550         DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");
2551
2552         switch (hfinfo->type){
2553         case FT_INT8:
2554         case FT_INT16:
2555         case FT_INT24:
2556         case FT_INT32:
2557                 break;
2558         default:
2559                 DISSECTOR_ASSERT_NOT_REACHED();
2560         }
2561
2562         /* length validation for native number encoding caught by get_uint_value() */
2563         /* length has to be -1 or > 0 regardless of encoding */
2564         if (length < -1 || length == 0)
2565                 REPORT_DISSECTOR_BUG(wmem_strdup_printf(wmem_packet_scope(),
2566                         "Invalid length %d passed to proto_tree_add_item_ret_int",
2567                         length));
2568
2569         if (encoding & ENC_STRING) {
2570                 REPORT_DISSECTOR_BUG("wrong encoding");
2571         }
2572         /* I believe it's ok if this is called with a NULL tree */
2573         value = get_int_value(tree, tvb, start, length, encoding);
2574
2575         if (retval) {
2576                 gint no_of_bits;
2577                 *retval = value;
2578                 if (hfinfo->bitmask) {
2579                         /* Mask out irrelevant portions */
2580                         *retval &= (guint32)(hfinfo->bitmask);
2581                         /* Shift bits */
2582                         *retval >>= hfinfo_bitshift(hfinfo);
2583                 }
2584                 no_of_bits = ws_count_ones(hfinfo->bitmask);
2585                 *retval = ws_sign_ext32(*retval, no_of_bits);
2586         }
2587
2588         CHECK_FOR_NULL_TREE(tree);
2589
2590         TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
2591
2592         new_fi = new_field_info(tree, hfinfo, tvb, start, length);
2593
2594         proto_tree_set_int(new_fi, value);
2595
2596         new_fi->flags |= (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN;
2597
2598         return proto_tree_add_node(tree, new_fi);
2599 }
2600
2601 proto_item *
2602 proto_tree_add_item_ret_uint(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2603                              const gint start, gint length,
2604                              const guint encoding, guint32 *retval)
2605 {
2606         header_field_info *hfinfo = proto_registrar_get_nth(hfindex);
2607         field_info        *new_fi;
2608         guint32            value;
2609
2610         DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");
2611
2612         switch (hfinfo->type){
2613         case FT_CHAR:
2614         case FT_UINT8:
2615         case FT_UINT16:
2616         case FT_UINT24:
2617         case FT_UINT32:
2618                 break;
2619         default:
2620                 REPORT_DISSECTOR_BUG(wmem_strdup_printf(wmem_packet_scope(),
2621                     "field %s is not of type FT_CHAR, FT_UINT8, FT_UINT16, FT_UINT24, or FT_UINT32",
2622                     hfinfo->abbrev));
2623         }
2624
2625         /* length validation for native number encoding caught by get_uint_value() */
2626         /* length has to be -1 or > 0 regardless of encoding */
2627         if (length < -1 || length == 0)
2628                 REPORT_DISSECTOR_BUG(wmem_strdup_printf(wmem_packet_scope(),
2629                         "Invalid length %d passed to proto_tree_add_item_ret_uint",
2630                         length));
2631
2632         if (encoding & ENC_STRING) {
2633                 REPORT_DISSECTOR_BUG("wrong encoding");
2634         }
2635         /* I believe it's ok if this is called with a NULL tree */
2636         /* XXX - modify if we ever support EBCDIC FT_CHAR */
2637         value = get_uint_value(tree, tvb, start, length, encoding);
2638
2639         if (retval) {
2640                 *retval = value;
2641                 if (hfinfo->bitmask) {
2642                         /* Mask out irrelevant portions */
2643                         *retval &= (guint32)(hfinfo->bitmask);
2644                         /* Shift bits */
2645                         *retval >>= hfinfo_bitshift(hfinfo);
2646                 }
2647         }
2648
2649         CHECK_FOR_NULL_TREE(tree);
2650
2651         TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
2652
2653         new_fi = new_field_info(tree, hfinfo, tvb, start, length);
2654
2655         proto_tree_set_uint(new_fi, value);
2656
2657         new_fi->flags |= (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN;
2658
2659         return proto_tree_add_node(tree, new_fi);
2660 }
2661
2662 proto_item *
2663 proto_tree_add_item_ret_uint64(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2664     const gint start, gint length, const guint encoding, guint64 *retval)
2665 {
2666         header_field_info *hfinfo = proto_registrar_get_nth(hfindex);
2667         field_info        *new_fi;
2668         guint64            value;
2669
2670         DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");
2671
2672         if (hfinfo->type != FT_UINT64) {
2673                 REPORT_DISSECTOR_BUG(wmem_strdup_printf(wmem_packet_scope(),
2674                     "field %s is not of type FT_UINT64", hfinfo->abbrev));
2675         }
2676
2677         /* length validation for native number encoding caught by get_uint64_value() */
2678         /* length has to be -1 or > 0 regardless of encoding */
2679         if (length < -1 || length == 0)
2680                 REPORT_DISSECTOR_BUG(wmem_strdup_printf(wmem_packet_scope(),
2681                         "Invalid length %d passed to proto_tree_add_item_ret_uint",
2682                         length));
2683
2684         if (encoding & ENC_STRING) {
2685                 REPORT_DISSECTOR_BUG("wrong encoding");
2686         }
2687         /* I believe it's ok if this is called with a NULL tree */
2688         value = get_uint64_value(tree, tvb, start, length, encoding);
2689
2690         if (retval) {
2691                 *retval = value;
2692                 if (hfinfo->bitmask) {
2693                         /* Mask out irrelevant portions */
2694                         *retval &= hfinfo->bitmask;
2695                         /* Shift bits */
2696                         *retval >>= hfinfo_bitshift(hfinfo);
2697                 }
2698         }
2699
2700         CHECK_FOR_NULL_TREE(tree);
2701
2702         TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
2703
2704         new_fi = new_field_info(tree, hfinfo, tvb, start, length);
2705
2706         proto_tree_set_uint64(new_fi, value);
2707
2708         new_fi->flags |= (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN;
2709
2710         return proto_tree_add_node(tree, new_fi);
2711 }
2712
2713 proto_item *
2714 proto_tree_add_item_ret_boolean(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2715                                 const gint start, gint length,
2716                                 const guint encoding, gboolean *retval)
2717 {
2718         header_field_info *hfinfo = proto_registrar_get_nth(hfindex);
2719         field_info        *new_fi;
2720         guint64            value, bitval;
2721
2722         DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");
2723
2724         if (hfinfo->type != FT_BOOLEAN) {
2725                 REPORT_DISSECTOR_BUG(wmem_strdup_printf(wmem_packet_scope(),
2726                     "field %s is not of type FT_BOOLEAN", hfinfo->abbrev));
2727         }
2728
2729         /* length validation for native number encoding caught by get_uint64_value() */
2730         /* length has to be -1 or > 0 regardless of encoding */
2731         if (length < -1 || length == 0)
2732                 REPORT_DISSECTOR_BUG(wmem_strdup_printf(wmem_packet_scope(),
2733                         "Invalid length %d passed to proto_tree_add_item_ret_uint",
2734                         length));
2735
2736         if (encoding & ENC_STRING) {
2737                 REPORT_DISSECTOR_BUG("wrong encoding");
2738         }
2739         /* I believe it's ok if this is called with a NULL tree */
2740         value = get_uint64_value(tree, tvb, start, length, encoding);
2741
2742         if (retval) {
2743                 bitval = value;
2744                 if (hfinfo->bitmask) {
2745                         /* Mask out irrelevant portions */
2746                         bitval &= hfinfo->bitmask;
2747                 }
2748                 *retval = (bitval != 0);
2749         }
2750
2751         CHECK_FOR_NULL_TREE(tree);
2752
2753         TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
2754
2755         new_fi = new_field_info(tree, hfinfo, tvb, start, length);
2756
2757         proto_tree_set_boolean(new_fi, value);
2758
2759         new_fi->flags |= (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN;
2760
2761         return proto_tree_add_node(tree, new_fi);
2762 }
2763
2764 proto_item *
2765 proto_tree_add_item_ret_string_and_length(proto_tree *tree, int hfindex,
2766                                           tvbuff_t *tvb,
2767                                           const gint start, gint length,
2768                                           const guint encoding,
2769                                           wmem_allocator_t *scope,
2770                                           const guint8 **retval,
2771                                           gint *lenretval)
2772 {
2773         header_field_info *hfinfo = proto_registrar_get_nth(hfindex);
2774         field_info        *new_fi;
2775         const guint8      *value;
2776
2777         DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");
2778
2779         switch (hfinfo->type){
2780         case FT_STRING:
2781                 value = get_string_value(scope, tvb, start, length, lenretval, encoding);
2782                 break;
2783         case FT_STRINGZ:
2784                 value = get_stringz_value(scope, tree, tvb, start, length, lenretval, encoding);
2785                 break;
2786         case FT_UINT_STRING:
2787                 value = get_uint_string_value(scope, tree, tvb, start, length, lenretval, encoding);
2788                 break;
2789         case FT_STRINGZPAD:
2790                 value = get_stringzpad_value(scope, tvb, start, length, lenretval, encoding);
2791                 break;
2792         default:
2793                 REPORT_DISSECTOR_BUG(wmem_strdup_printf(wmem_packet_scope(),
2794                     "field %s is not of type FT_STRING, FT_STRINGZ, FT_UINT_STRING, or FT_STRINGZPAD",
2795                     hfinfo->abbrev));
2796         }
2797
2798         if (retval)
2799                 *retval = value;
2800
2801         CHECK_FOR_NULL_TREE(tree);
2802
2803         TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
2804
2805         new_fi = new_field_info(tree, hfinfo, tvb, start, *lenretval);
2806
2807         proto_tree_set_string(new_fi, value);
2808
2809         new_fi->flags |= (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN;
2810
2811         return proto_tree_add_node(tree, new_fi);
2812 }
2813
2814 proto_item *
2815 proto_tree_add_item_ret_string(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2816                                const gint start, gint length,
2817                                const guint encoding, wmem_allocator_t *scope,
2818                                const guint8 **retval)
2819 {
2820         return proto_tree_add_item_ret_string_and_length(tree, hfindex,
2821             tvb, start, length, encoding, scope, retval, &length);
2822 }
2823
2824 /*
2825  * Validates that field length bytes are available starting from
2826  * start (pos/neg). Throws an exception if they aren't.
2827  */
2828 static void
2829 test_length(header_field_info *hfinfo, tvbuff_t *tvb,
2830             gint start, gint length)
2831 {
2832         gint size = length;
2833
2834         if (!tvb)
2835                 return;
2836
2837         if (hfinfo->type == FT_STRINGZ) {
2838                 /* If we're fetching until the end of the TVB, only validate
2839                  * that the offset is within range.
2840                  */
2841                 if (length == -1)
2842                         size = 0;
2843         }
2844
2845         tvb_ensure_bytes_exist(tvb, start, size);
2846 }
2847
2848 /* Gets data from tvbuff, adds it to proto_tree, increments offset,
2849    and returns proto_item* */
2850 proto_item *
2851 ptvcursor_add(ptvcursor_t *ptvc, int hfindex, gint length,
2852               const guint encoding)
2853 {
2854         field_info        *new_fi;
2855         header_field_info *hfinfo;
2856         gint               item_length;
2857         int                offset;
2858
2859         offset = ptvc->offset;
2860         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2861         get_hfi_length(hfinfo, ptvc->tvb, offset, &length, &item_length);
2862         test_length(hfinfo, ptvc->tvb, offset, item_length);
2863
2864         ptvc->offset += get_full_length(hfinfo, ptvc->tvb, offset, length,
2865             item_length, encoding);
2866
2867         CHECK_FOR_NULL_TREE(ptvc->tree);
2868
2869         /* Coast clear. Try and fake it */
2870         TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfindex, hfinfo);
2871
2872         new_fi = new_field_info(ptvc->tree, hfinfo, ptvc->tvb, offset, item_length);
2873
2874         return proto_tree_new_item(new_fi, ptvc->tree, ptvc->tvb,
2875                 offset, length, encoding);
2876 }
2877
2878 /* Add an item to a proto_tree, using the text label registered to that item;
2879    the item is extracted from the tvbuff handed to it. */
2880 proto_item *
2881 proto_tree_add_item_new(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
2882                         const gint start, gint length, const guint encoding)
2883 {
2884         field_info        *new_fi;
2885         gint              item_length;
2886
2887         DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");
2888
2889         get_hfi_length(hfinfo, tvb, start, &length, &item_length);
2890         test_length(hfinfo, tvb, start, item_length);
2891
2892         CHECK_FOR_NULL_TREE(tree);
2893
2894         TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
2895
2896         new_fi = new_field_info(tree, hfinfo, tvb, start, item_length);
2897
2898         return proto_tree_new_item(new_fi, tree, tvb, start, length, encoding);
2899 }
2900
2901 proto_item *
2902 proto_tree_add_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2903                     const gint start, gint length, const guint encoding)
2904 {
2905         register header_field_info *hfinfo;
2906
2907         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2908         return proto_tree_add_item_new(tree, hfinfo, tvb, start, length, encoding);
2909 }
2910
2911 /* Add an item to a proto_tree, using the text label registered to that item;
2912    the item is extracted from the tvbuff handed to it.
2913
2914    Return the length of the item through the pointer. */
2915 proto_item *
2916 proto_tree_add_item_new_ret_length(proto_tree *tree, header_field_info *hfinfo,
2917                                    tvbuff_t *tvb, const gint start,
2918                                    gint length, const guint encoding,
2919                                    gint *lenretval)
2920 {
2921         field_info        *new_fi;
2922         gint              item_length;
2923         proto_item       *item;
2924
2925         DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");
2926
2927         get_hfi_length(hfinfo, tvb, start, &length, &item_length);
2928         test_length(hfinfo, tvb, start, item_length);
2929
2930         if (!tree) {
2931                 /*
2932                  * We need to get the correct item length here.
2933                  * That's normally done by proto_tree_new_item(),
2934                  * but we won't be calling it.
2935                  */
2936                 *lenretval = get_full_length(hfinfo, tvb, start, length,
2937                     item_length, encoding);
2938                 return NULL;
2939         }
2940
2941         TRY_TO_FAKE_THIS_ITEM_OR_FREE(tree, hfinfo->id, hfinfo, {
2942                 /*
2943                  * Even if the tree item is not referenced (and thus faked),
2944                  * the caller must still be informed of the actual length.
2945                  */
2946                 *lenretval = get_full_length(hfinfo, tvb, start, length,
2947                     item_length, encoding);
2948         });
2949
2950         new_fi = new_field_info(tree, hfinfo, tvb, start, item_length);
2951
2952         item = proto_tree_new_item(new_fi, tree, tvb, start, length, encoding);
2953         *lenretval = new_fi->length;
2954         return item;
2955 }
2956
2957 proto_item *
2958 proto_tree_add_item_ret_length(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2959                                const gint start, gint length,
2960                                const guint encoding, gint *lenretval)
2961 {
2962         register header_field_info *hfinfo;
2963
2964         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2965         return proto_tree_add_item_new_ret_length(tree, hfinfo, tvb, start, length, encoding, lenretval);
2966 }
2967
2968 /* which FT_ types can use proto_tree_add_bytes_item() */
2969 static inline gboolean
2970 validate_proto_tree_add_bytes_ftype(const enum ftenum type)
2971 {
2972         return (type == FT_BYTES      ||
2973                 type == FT_UINT_BYTES ||
2974                 type == FT_OID        ||
2975                 type == FT_REL_OID    ||
2976                 type == FT_SYSTEM_ID  );
2977 }
2978
2979 /* Note: this does no validation that the byte array of an FT_OID or
2980    FT_REL_OID is actually valid; and neither does proto_tree_add_item(),
2981    so I think it's ok to continue not validating it?
2982  */
2983 proto_item *
2984 proto_tree_add_bytes_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2985                            const gint start, gint length, const guint encoding,
2986                            GByteArray *retval, gint *endoff, gint *err)
2987 {
2988         field_info        *new_fi;
2989         GByteArray        *bytes = retval;
2990         GByteArray        *created_bytes = NULL;
2991         gint               saved_err = 0;
2992         guint32            n = 0;
2993         header_field_info *hfinfo;
2994         gboolean           generate = (bytes || tree) ? TRUE : FALSE;
2995
2996         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2997
2998         DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");
2999
3000         DISSECTOR_ASSERT_HINT(validate_proto_tree_add_bytes_ftype(hfinfo->type),
3001                 "Called proto_tree_add_bytes_item but not a bytes-based FT_XXX type");
3002
3003         /* length has to be -1 or > 0 regardless of encoding */
3004         /* invalid FT_UINT_BYTES length is caught in get_uint_value() */
3005         if (length < -1 || length == 0) {
3006                 REPORT_DISSECTOR_BUG(wmem_strdup_printf(wmem_packet_scope(),
3007                     "Invalid length %d passed to proto_tree_add_bytes_item for %s",
3008                     length, ftype_name(hfinfo->type)));
3009         }
3010
3011         if (encoding & ENC_STR_NUM) {
3012                 REPORT_DISSECTOR_BUG("Decoding number strings for byte arrays is not supported");
3013         }
3014
3015         if (generate && (encoding & ENC_STR_HEX)) {
3016                 if (hfinfo->type == FT_UINT_BYTES) {
3017                         /* can't decode FT_UINT_BYTES from strings */
3018                         REPORT_DISSECTOR_BUG("proto_tree_add_bytes_item called for "
3019                             "FT_UINT_BYTES type, but as ENC_STR_HEX");
3020                 }
3021
3022                 if (!bytes) {
3023                         /* caller doesn't care about return value, but we need it to
3024                            call tvb_get_string_bytes() and set the tree later */
3025                         bytes = created_bytes = g_byte_array_new();
3026                 }
3027
3028                 /* bytes might be NULL after this, but can't add expert error until later */
3029                 bytes = tvb_get_string_bytes(tvb, start, length, encoding, bytes, endoff);
3030
3031                 /* grab the errno now before it gets overwritten */
3032                 saved_err = errno;
3033         }
3034         else if (generate) {
3035                 tvb_ensure_bytes_exist(tvb, start, length);
3036
3037                 if (!bytes) {
3038                         /* caller doesn't care about return value, but we need it to
3039                            call tvb_get_string_bytes() and set the tree later */
3040                         bytes = created_bytes = g_byte_array_new();
3041                 }
3042
3043                 if (hfinfo->type == FT_UINT_BYTES) {
3044                         n = length; /* n is now the "header" length */
3045                         length = get_uint_value(tree, tvb, start, n, encoding);
3046                         /* length is now the value's length; only store the value in the array */
3047                         g_byte_array_append(bytes, tvb_get_ptr(tvb, start + n, length), length);
3048                 }
3049                 else if (length > 0) {
3050                         g_byte_array_append(bytes, tvb_get_ptr(tvb, start, length), length);
3051                 }
3052
3053                 if (endoff)
3054                     *endoff = start + n + length;
3055         }
3056
3057         if (err) *err = saved_err;
3058
3059         CHECK_FOR_NULL_TREE_AND_FREE(tree,
3060                 {
3061                     if (created_bytes)
3062                         g_byte_array_free(created_bytes, TRUE);
3063                     created_bytes = NULL;
3064                     bytes = NULL;
3065                 } );
3066
3067         TRY_TO_FAKE_THIS_ITEM_OR_FREE(tree, hfinfo->id, hfinfo,
3068                 {
3069                     if (created_bytes)
3070                         g_byte_array_free(created_bytes, TRUE);
3071                     created_bytes = NULL;
3072                     bytes = NULL;
3073                 } );
3074
3075         /* n will be zero except when it's a FT_UINT_BYTES */
3076         new_fi = new_field_info(tree, hfinfo, tvb, start, n + length);
3077
3078         if (encoding & ENC_STRING) {
3079                 if (saved_err == ERANGE)
3080                     expert_add_info(NULL, tree, &ei_number_string_decoding_erange_error);
3081                 else if (!bytes || saved_err != 0)
3082                     expert_add_info(NULL, tree, &ei_number_string_decoding_failed_error);
3083
3084                 if (bytes)
3085                     proto_tree_set_bytes_gbytearray(new_fi, bytes);
3086                 else
3087                     proto_tree_set_bytes(new_fi, NULL, 0);
3088
3089                 if (created_bytes)
3090                     g_byte_array_free(created_bytes, TRUE);
3091         }
3092         else {
3093                 /* n will be zero except when it's a FT_UINT_BYTES */
3094                 proto_tree_set_bytes_tvb(new_fi, tvb, start + n, length);
3095
3096                 FI_SET_FLAG(new_fi,
3097                         (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN);
3098         }
3099
3100         return proto_tree_add_node(tree, new_fi);
3101 }
3102
3103
3104 proto_item *
3105 proto_tree_add_time_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3106                            const gint start, gint length, const guint encoding,
3107                            nstime_t *retval, gint *endoff, gint *err)
3108 {
3109         field_info        *new_fi;
3110         nstime_t           time_stamp;
3111         gint               saved_err = 0;
3112         header_field_info *hfinfo;
3113
3114         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
3115
3116         DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");
3117
3118         DISSECTOR_ASSERT_FIELD_TYPE_IS_TIME(hfinfo);
3119
3120         /* length has to be -1 or > 0 regardless of encoding */
3121         if (length < -1 || length == 0) {
3122                 REPORT_DISSECTOR_BUG(wmem_strdup_printf(wmem_packet_scope(),
3123                     "Invalid length %d passed to proto_tree_add_time_item", length));
3124         }
3125
3126         time_stamp.secs  = 0;
3127         time_stamp.nsecs = 0;
3128
3129         if (encoding & ENC_STR_TIME_MASK) {
3130                 tvb_get_string_time(tvb, start, length, encoding, &time_stamp, endoff);
3131                 /* grab the errno now before it gets overwritten */
3132                 saved_err = errno;
3133         }
3134         else {
3135                 const gboolean is_relative = (hfinfo->type == FT_RELATIVE_TIME) ? TRUE : FALSE;
3136                 const gboolean length_error = length < 4 ? TRUE : FALSE;
3137
3138                 if (length > 8 || length < 4) {
3139                         if (is_relative)
3140                             report_type_length_mismatch(tree, "a relative time value", length, length_error);
3141                         else
3142                             report_type_length_mismatch(tree, "an absolute time value", length, length_error);
3143                 }
3144
3145                 tvb_ensure_bytes_exist(tvb, start, length);
3146                 get_time_value(tree, tvb, start, length, encoding, &time_stamp, is_relative);
3147                 if (endoff) *endoff = length;
3148         }
3149
3150         if (err) *err = saved_err;
3151
3152         if (retval) {
3153                 retval->secs  = time_stamp.secs;
3154                 retval->nsecs = time_stamp.nsecs;
3155         }
3156
3157         CHECK_FOR_NULL_TREE(tree);
3158
3159         TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
3160
3161         new_fi = new_field_info(tree, hfinfo, tvb, start, length);
3162
3163         proto_tree_set_time(new_fi, &time_stamp);
3164
3165         if (encoding & ENC_STRING) {
3166                 if (saved_err == ERANGE)
3167                     expert_add_info(NULL, tree, &ei_number_string_decoding_erange_error);
3168                 else if (saved_err == EDOM)
3169                     expert_add_info(NULL, tree, &ei_number_string_decoding_failed_error);
3170         }
3171         else {
3172                 FI_SET_FLAG(new_fi,
3173                         (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN);
3174         }
3175
3176         return proto_tree_add_node(tree, new_fi);
3177 }
3178
3179 /* Add a FT_NONE to a proto_tree */
3180 proto_item *
3181 proto_tree_add_none_format(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
3182                            const gint start, gint length, const char *format,
3183                            ...)
3184 {
3185         proto_item        *pi;
3186         va_list            ap;
3187         header_field_info *hfinfo;
3188
3189         CHECK_FOR_NULL_TREE(tree);
3190
3191         TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3192
3193         DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_NONE);
3194
3195         pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
3196
3197         TRY_TO_FAKE_THIS_REPR(pi);
3198
3199         va_start(ap, format);
3200         proto_tree_set_representation(pi, format, ap);
3201         va_end(ap);
3202
3203         /* no value to set for FT_NONE */
3204         return pi;
3205 }
3206
3207 /* Gets data from tvbuff, adds it to proto_tree, *DOES NOT* increment
3208  * offset, and returns proto_item* */
3209 proto_item *
3210 ptvcursor_add_no_advance(ptvcursor_t* ptvc, int hf, gint length,
3211                          const guint encoding)
3212 {
3213         proto_item *item;
3214
3215         item = proto_tree_add_item(ptvc->tree, hf, ptvc->tvb, ptvc->offset,
3216                                    length, encoding);
3217
3218         return item;
3219 }
3220
3221 /* Advance the ptvcursor's offset within its tvbuff without
3222  * adding anything to the proto_tree. */
3223 void
3224 ptvcursor_advance(ptvcursor_t* ptvc, gint length)
3225 {
3226         ptvc->offset += length;
3227 }
3228
3229
3230 static void
3231 proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb, const char* field_data)
3232 {
3233         fvalue_set_protocol(&fi->value, tvb, field_data);
3234 }
3235
3236 /* Add a FT_PROTOCOL to a proto_tree */
3237 proto_item *
3238 proto_tree_add_protocol_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3239                                gint start, gint length, const char *format, ...)
3240 {
3241         proto_item        *pi;
3242         va_list            ap;
3243         header_field_info *hfinfo;
3244         gchar* protocol_rep;
3245
3246         CHECK_FOR_NULL_TREE(tree);
3247
3248         TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3249
3250         DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_PROTOCOL);
3251
3252         pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
3253
3254         va_start(ap, format);
3255         protocol_rep = g_strdup_vprintf(format, ap);
3256         proto_tree_set_protocol_tvb(PNODE_FINFO(pi), (start == 0 ? tvb : tvb_new_subset_length(tvb, start, length)), protocol_rep);
3257         g_free(protocol_rep);
3258         va_end(ap);
3259
3260         TRY_TO_FAKE_THIS_REPR(pi);
3261
3262         va_start(ap, format);
3263         proto_tree_set_representation(pi, format, ap);
3264         va_end(ap);
3265
3266         return pi;
3267 }
3268
3269 /* Add a FT_BYTES to a proto_tree */
3270 proto_item *
3271 proto_tree_add_bytes(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3272                      gint length, const guint8 *start_ptr)
3273 {
3274         proto_item        *pi;
3275         header_field_info *hfinfo;
3276         gint              item_length;
3277
3278         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
3279         get_hfi_length(hfinfo, tvb, start, &length, &item_length);
3280         test_length(hfinfo, tvb, start, item_length);
3281
3282         CHECK_FOR_NULL_TREE(tree);
3283
3284         TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3285
3286         DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_BYTES);
3287
3288         pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
3289         proto_tree_set_bytes(PNODE_FINFO(pi), start_ptr, length);
3290
3291         return pi;
3292 }
3293
3294 /* Add a FT_BYTES to a proto_tree */
3295 proto_item *
3296 proto_tree_add_bytes_with_length(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3297              gint tvbuff_length, const guint8 *start_ptr, gint ptr_length)
3298 {
3299         proto_item    *pi;
3300         header_field_info *hfinfo;
3301         gint          item_length;
3302
3303         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
3304         get_hfi_length(hfinfo, tvb, start, &tvbuff_length, &item_length);
3305         test_length(hfinfo, tvb, start, item_length);
3306
3307         CHECK_FOR_NULL_TREE(tree);
3308
3309         TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3310
3311         DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_BYTES);
3312
3313         pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &tvbuff_length);
3314         proto_tree_set_bytes(PNODE_FINFO(pi), start_ptr, ptr_length);
3315
3316         return pi;
3317 }
3318
3319 proto_item *
3320 proto_tree_add_bytes_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3321                                   gint start, gint length,
3322                                   const guint8 *start_ptr,
3323                                   const char *format, ...)
3324 {
3325         proto_item        *pi;
3326         va_list            ap;
3327
3328         if (start_ptr == NULL)
3329                 start_ptr = tvb_get_ptr(tvb, start, length);
3330
3331         pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length, start_ptr);
3332
3333         TRY_TO_FAKE_THIS_REPR_NESTED(pi);
3334
3335         va_start(ap, format);
3336         proto_tree_set_representation_value(pi, format, ap);
3337         va_end(ap);
3338
3339         return pi;
3340 }
3341
3342 proto_item *
3343 proto_tree_add_bytes_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3344                             gint start, gint length, const guint8 *start_ptr,
3345                             const char *format, ...)
3346 {
3347         proto_item        *pi;
3348         va_list            ap;
3349
3350         if (start_ptr == NULL)
3351                 start_ptr = tvb_get_ptr(tvb, start, length);
3352
3353         pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length, start_ptr);
3354
3355         TRY_TO_FAKE_THIS_REPR_NESTED(pi);
3356
3357         va_start(ap, format);
3358         proto_tree_set_representation(pi, format, ap);
3359         va_end(ap);
3360
3361         return pi;
3362 }
3363
3364 static void
3365 proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length)
3366 {
3367         GByteArray *bytes;
3368
3369         DISSECTOR_ASSERT(start_ptr != NULL || length == 0);
3370
3371         bytes = g_byte_array_new();
3372         if (length > 0) {
3373                 g_byte_array_append(bytes, start_ptr, length);
3374         }
3375         fvalue_set_byte_array(&fi->value, bytes);
3376 }
3377
3378
3379 static void
3380 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length)
3381 {
3382         proto_tree_set_bytes(fi, tvb_get_ptr(tvb, offset, length), length);
3383 }
3384
3385 static void
3386 proto_tree_set_bytes_gbytearray(field_info *fi, const GByteArray *value)
3387 {
3388         GByteArray *bytes;
3389
3390         DISSECTOR_ASSERT(value != NULL);
3391
3392         bytes = byte_array_dup(value);
3393
3394         fvalue_set_byte_array(&fi->value, bytes);
3395 }
3396
3397 /* Add a FT_*TIME to a proto_tree */
3398 proto_item *
3399 proto_tree_add_time(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3400                     gint length, const nstime_t *value_ptr)
3401 {
3402         proto_item        *pi;
3403         header_field_info *hfinfo;
3404
3405         CHECK_FOR_NULL_TREE(tree);
3406
3407         TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3408
3409         DISSECTOR_ASSERT_FIELD_TYPE_IS_TIME(hfinfo);
3410
3411         pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
3412         proto_tree_set_time(PNODE_FINFO(pi), value_ptr);
3413
3414         return pi;
3415 }
3416
3417 proto_item *
3418 proto_tree_add_time_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3419                                  gint start, gint length, nstime_t *value_ptr,
3420                                  const char *format, ...)
3421 {
3422         proto_item        *pi;
3423         va_list            ap;
3424
3425         pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
3426         if (pi != tree) {
3427                 va_start(ap, format);
3428                 proto_tree_set_representation_value(pi, format, ap);
3429                 va_end(ap);
3430         }
3431
3432         return pi;
3433 }
3434
3435 proto_item *
3436 proto_tree_add_time_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3437                            gint start, gint length, nstime_t *value_ptr,
3438                            const char *format, ...)
3439 {
3440         proto_item        *pi;
3441         va_list            ap;
3442
3443         pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
3444         if (pi != tree) {
3445                 TRY_TO_FAKE_THIS_REPR(pi);
3446
3447                 va_start(ap, format);
3448                 proto_tree_set_representation(pi, format, ap);
3449                 va_end(ap);
3450         }
3451
3452         return pi;
3453 }
3454
3455 /* Set the FT_*TIME value */
3456 static void
3457 proto_tree_set_time(field_info *fi, const nstime_t *value_ptr)
3458 {
3459         DISSECTOR_ASSERT(value_ptr != NULL);
3460
3461         fvalue_set_time(&fi->value, value_ptr);
3462 }
3463
3464 /* Add a FT_IPXNET to a proto_tree */
3465 proto_item *
3466 proto_tree_add_ipxnet(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3467                       gint length, guint32 value)
3468 {
3469         proto_item        *pi;
3470         header_field_info *hfinfo;
3471
3472         CHECK_FOR_NULL_TREE(tree);
3473
3474         TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3475
3476         DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_IPXNET);
3477
3478         pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
3479         proto_tree_set_ipxnet(PNODE_FINFO(pi), value);
3480
3481         return pi;
3482 }
3483
3484 proto_item *
3485 proto_tree_add_ipxnet_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3486                                    gint start, gint length, guint32 value,
3487                                    const char *format, ...)
3488 {
3489         proto_item        *pi;
3490         va_list            ap;
3491
3492         pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
3493         if (pi != tree) {
3494                 va_start(ap, format);
3495                 proto_tree_set_representation_value(pi, format, ap);
3496                 va_end(ap);
3497         }
3498
3499         return pi;
3500 }
3501
3502 proto_item *
3503 proto_tree_add_ipxnet_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3504                              gint start, gint length, guint32 value,
3505                              const char *format, ...)
3506 {
3507         proto_item        *pi;
3508         va_list            ap;
3509
3510         pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
3511         if (pi != tree) {
3512                 TRY_TO_FAKE_THIS_REPR(pi);
3513
3514                 va_start(ap, format);
3515                 proto_tree_set_representation(pi, format, ap);
3516                 va_end(ap);
3517         }
3518
3519         return pi;
3520 }
3521
3522 /* Set the FT_IPXNET value */
3523 static void
3524 proto_tree_set_ipxnet(field_info *fi, guint32 value)
3525 {
3526         fvalue_set_uinteger(&fi->value, value);
3527 }
3528
3529 /* Add a FT_IPv4 to a proto_tree */
3530 proto_item *
3531 proto_tree_add_ipv4(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3532                     gint length, guint32 value)
3533 {
3534         proto_item        *pi;
3535         header_field_info *hfinfo;
3536
3537         CHECK_FOR_NULL_TREE(tree);
3538
3539         TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3540
3541         DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_IPv4);
3542
3543         pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
3544         proto_tree_set_ipv4(PNODE_FINFO(pi), value);
3545
3546         return pi;
3547 }
3548
3549 proto_item *
3550 proto_tree_add_ipv4_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3551                                  gint start, gint length, guint32 value,
3552                                  const char *format, ...)
3553 {
3554         proto_item        *pi;
3555         va_list            ap;
3556
3557         pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
3558         if (pi != tree) {
3559                 va_start(ap, format);
3560                 proto_tree_set_representation_value(pi, format, ap);
3561                 va_end(ap);
3562         }
3563
3564         return pi;
3565 }
3566
3567 proto_item *
3568 proto_tree_add_ipv4_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3569                            gint start, gint length, guint32 value,
3570                            const char *format, ...)
3571 {
3572         proto_item        *pi;
3573         va_list            ap;
3574
3575         pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
3576         if (pi != tree) {
3577                 TRY_TO_FAKE_THIS_REPR(pi);
3578
3579                 va_start(ap, format);
3580                 proto_tree_set_representation(pi, format, ap);
3581                 va_end(ap);
3582         }
3583
3584         return pi;
3585 }
3586
3587 /* Set the FT_IPv4 value */
3588 static void
3589 proto_tree_set_ipv4(field_info *fi, guint32 value)
3590 {
3591         fvalue_set_uinteger(&fi->value, value);
3592 }
3593
3594 /* Add a FT_IPv6 to a proto_tree */
3595 proto_item *
3596 proto_tree_add_ipv6(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3597                     gint length, const struct e_in6_addr *value_ptr)
3598 {
3599         proto_item        *pi;
3600         header_field_info *hfinfo;
3601
3602         CHECK_FOR_NULL_TREE(tree);
3603
3604         TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3605
3606         DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_IPv6);
3607
3608         pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
3609         proto_tree_set_ipv6(PNODE_FINFO(pi), value_ptr->bytes);
3610
3611         return pi;
3612 }
3613
3614 proto_item *
3615 proto_tree_add_ipv6_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3616                                  gint start, gint length,
3617                                  const struct e_in6_addr *value_ptr,
3618                                  const char *format, ...)
3619 {
3620         proto_item        *pi;
3621         va_list            ap;
3622
3623         pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
3624         if (pi != tree) {
3625                 va_start(ap, format);
3626                 proto_tree_set_representation_value(pi, format, ap);
3627                 va_end(ap);
3628         }
3629
3630         return pi;
3631 }
3632
3633 proto_item *
3634 proto_tree_add_ipv6_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3635                            gint start, gint length,
3636                            const struct e_in6_addr *value_ptr,
3637                            const char *format, ...)
3638 {
3639         proto_item        *pi;
3640         va_list            ap;
3641
3642         pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
3643         if (pi != tree) {
3644                 TRY_TO_FAKE_THIS_REPR(pi);
3645
3646                 va_start(ap, format);
3647                 proto_tree_set_representation(pi, format, ap);
3648                 va_end(ap);
3649         }
3650
3651         return pi;
3652 }
3653
3654 /* Set the FT_IPv6 value */
3655 static void
3656 proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr)
3657 {
3658         DISSECTOR_ASSERT(value_ptr != NULL);
3659         fvalue_set_bytes(&fi->value, value_ptr);
3660 }
3661
3662 static void
3663 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
3664 {
3665         proto_tree_set_ipv6(fi, tvb_get_ptr(tvb, start, length));
3666 }
3667
3668 /* Set the FT_FCWWN value */
3669 static void
3670 proto_tree_set_fcwwn(field_info *fi, const guint8* value_ptr)
3671 {
3672         DISSECTOR_ASSERT(value_ptr != NULL);
3673         fvalue_set_bytes(&fi->value, value_ptr);
3674 }
3675
3676 static void
3677 proto_tree_set_fcwwn_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
3678 {
3679         proto_tree_set_fcwwn(fi, tvb_get_ptr(tvb, start, length));
3680 }
3681
3682 /* Add a FT_GUID to a proto_tree */
3683 proto_item *
3684 proto_tree_add_guid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3685                     gint length, const e_guid_t *value_ptr)
3686 {
3687         proto_item        *pi;
3688         header_field_info *hfinfo;
3689
3690         CHECK_FOR_NULL_TREE(tree);
3691
3692         TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3693
3694         DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_GUID);
3695
3696         pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
3697         proto_tree_set_guid(PNODE_FINFO(pi), value_ptr);
3698
3699         return pi;
3700 }
3701
3702 proto_item *
3703 proto_tree_add_guid_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3704                                  gint start, gint length,
3705                                  const e_guid_t *value_ptr,
3706                                  const char *format, ...)
3707 {
3708         proto_item        *pi;
3709         va_list            ap;
3710
3711         pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
3712         if (pi != tree) {
3713                 va_start(ap, format);
3714                 proto_tree_set_representation_value(pi, format, ap);
3715                 va_end(ap);
3716         }
3717
3718         return pi;
3719 }
3720
3721 proto_item *
3722 proto_tree_add_guid_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3723                            gint start, gint length, const e_guid_t *value_ptr,
3724                            const char *format, ...)
3725 {
3726         proto_item        *pi;
3727         va_list            ap;
3728
3729         pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
3730         if (pi != tree) {
3731                 TRY_TO_FAKE_THIS_REPR(pi);
3732
3733                 va_start(ap, format);
3734                 proto_tree_set_representation(pi, format, ap);
3735                 va_end(ap);
3736         }
3737
3738         return pi;
3739 }
3740
3741 /* Set the FT_GUID value */
3742 static void
3743 proto_tree_set_guid(field_info *fi, const e_guid_t *value_ptr)
3744 {
3745         DISSECTOR_ASSERT(value_ptr != NULL);
3746         fvalue_set_guid(&fi->value, value_ptr);
3747 }
3748
3749 static void
3750 proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, gint start,
3751                         const guint encoding)
3752 {
3753         e_guid_t guid;
3754
3755         tvb_get_guid(tvb, start, &guid, encoding);
3756         proto_tree_set_guid(fi, &guid);
3757 }
3758
3759 /* Add a FT_OID to a proto_tree */
3760 proto_item *
3761 proto_tree_add_oid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3762                    gint length, const guint8* value_ptr)
3763 {
3764         proto_item        *pi;
3765         header_field_info *hfinfo;
3766
3767         CHECK_FOR_NULL_TREE(tree);
3768
3769         TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3770
3771         DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_OID);
3772
3773         pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
3774         proto_tree_set_oid(PNODE_FINFO(pi), value_ptr, length);
3775
3776         return pi;
3777 }
3778
3779 proto_item *
3780 proto_tree_add_oid_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3781                                 gint start, gint length,
3782                                 const guint8* value_ptr,
3783                                 const char *format, ...)
3784 {
3785         proto_item        *pi;
3786         va_list            ap;
3787
3788         pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
3789         if (pi != tree) {
3790                 va_start(ap, format);
3791                 proto_tree_set_representation_value(pi, format, ap);
3792                 va_end(ap);
3793         }
3794
3795         return pi;
3796 }
3797
3798 proto_item *
3799 proto_tree_add_oid_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3800                           gint start, gint length, const guint8* value_ptr,
3801                           const char *format, ...)
3802 {
3803         proto_item        *pi;
3804         va_list            ap;
3805
3806         pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
3807         if (pi != tree) {
3808                 TRY_TO_FAKE_THIS_REPR(pi);
3809
3810                 va_start(ap, format);
3811                 proto_tree_set_representation(pi, format, ap);
3812                 va_end(ap);
3813         }
3814
3815         return pi;
3816 }
3817
3818 /* Set the FT_OID value */
3819 static void
3820 proto_tree_set_oid(field_info *fi, const guint8* value_ptr, gint length)
3821 {
3822         GByteArray *bytes;
3823
3824         DISSECTOR_ASSERT(value_ptr != NULL || length == 0);
3825
3826         bytes = g_byte_array_new();
3827         if (length > 0) {
3828                 g_byte_array_append(bytes, value_ptr, length);
3829         }
3830         fvalue_set_byte_array(&fi->value, bytes);
3831 }
3832
3833 static void
3834 proto_tree_set_oid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
3835 {
3836         proto_tree_set_oid(fi, tvb_get_ptr(tvb, start, length), length);
3837 }
3838
3839 /* Set the FT_SYSTEM_ID value */
3840 static void
3841 proto_tree_set_system_id(field_info *fi, const guint8* value_ptr, gint length)
3842 {
3843         GByteArray *bytes;
3844
3845         DISSECTOR_ASSERT(value_ptr != NULL || length == 0);
3846
3847         bytes = g_byte_array_new();
3848         if (length > 0) {
3849                 g_byte_array_append(bytes, value_ptr, length);
3850         }
3851         fvalue_set_byte_array(&fi->value, bytes);
3852 }
3853
3854 static void
3855 proto_tree_set_system_id_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
3856 {
3857         proto_tree_set_system_id(fi, tvb_get_ptr(tvb, start, length), length);
3858 }
3859
3860 /* Add a FT_STRING, FT_STRINGZ, or FT_STRINGZPAD to a proto_tree. Creates
3861  * own copy of string, and frees it when the proto_tree is destroyed. */
3862 proto_item *
3863 proto_tree_add_string(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3864                       gint length, const char* value)
3865 {
3866         proto_item        *pi;
3867         header_field_info *hfinfo;
3868
3869         CHECK_FOR_NULL_TREE(tree);
3870
3871         TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3872
3873         DISSECTOR_ASSERT_FIELD_TYPE_IS_STRING(hfinfo);
3874
3875         if (hfinfo->display == STR_UNICODE) {
3876                 DISSECTOR_ASSERT(g_utf8_validate(value, -1, NULL));
3877         }
3878
3879         pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
3880         DISSECTOR_ASSERT(length >= 0);
3881         proto_tree_set_string(PNODE_FINFO(pi), value);
3882
3883         return pi;
3884 }
3885
3886 proto_item *
3887 proto_tree_add_string_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3888                                    gint start, gint length, const char* value,
3889                                    const char *format,
3890                                    ...)
3891 {
3892         proto_item        *pi;
3893         va_list            ap;
3894
3895         pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
3896         if (pi != tree) {
3897                 va_start(ap, format);
3898                 proto_tree_set_representation_value(pi, format, ap);
3899                 va_end(ap);
3900         }
3901
3902         return pi;
3903 }
3904
3905 proto_item *
3906 proto_tree_add_string_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3907                              gint start, gint length, const char* value,
3908                              const char *format, ...)
3909 {
3910         proto_item        *pi;
3911         va_list            ap;
3912
3913         pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
3914         if (pi != tree) {
3915                 TRY_TO_FAKE_THIS_REPR(pi);
3916
3917                 va_start(ap, format);
3918                 proto_tree_set_representation(pi, format, ap);
3919                 va_end(ap);
3920         }
3921
3922         return pi;
3923 }
3924
3925 /* Set the FT_STRING value */
3926 static void
3927 proto_tree_set_string(field_info *fi, const char* value)
3928 {
3929         if (value) {
3930                 fvalue_set_string(&fi->value, value);
3931         } else {
3932                 fvalue_set_string(&fi->value, "[ Null ]");
3933         }
3934 }
3935
3936 /* Set the FT_AX25 value */
3937 static void
3938 proto_tree_set_ax25(field_info *fi, const guint8* value)
3939 {
3940         fvalue_set_bytes(&fi->value, value);
3941 }
3942
3943 static void
3944 proto_tree_set_ax25_tvb(field_info *fi, tvbuff_t *tvb, gint start)
3945 {
3946         proto_tree_set_ax25(fi, tvb_get_ptr(tvb, start, 7));
3947 }
3948
3949 /* Set the FT_VINES value */
3950 static void
3951 proto_tree_set_vines(field_info *fi, const guint8* value)
3952 {
3953         fvalue_set_bytes(&fi->value, value);
3954 }
3955
3956 static void
3957 proto_tree_set_vines_tvb(field_info *fi, tvbuff_t *tvb, gint start)
3958 {
3959         proto_tree_set_vines(fi, tvb_get_ptr(tvb, start, FT_VINES_ADDR_LEN));
3960 }
3961
3962 /* Add a FT_ETHER to a proto_tree */
3963 proto_item *
3964 proto_tree_add_ether(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3965                      gint length, const guint8* value)
3966 {
3967         proto_item        *pi;
3968         header_field_info *hfinfo;
3969
3970         CHECK_FOR_NULL_TREE(tree);
3971
3972         TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3973
3974         DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_ETHER);
3975
3976         pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
3977         proto_tree_set_ether(PNODE_FINFO(pi), value);
3978
3979         return pi;
3980 }
3981
3982 proto_item *
3983 proto_tree_add_ether_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3984                                   gint start, gint length, const guint8* value,
3985                                   const char *format, ...)
3986 {
3987         proto_item        *pi;
3988         va_list            ap;
3989
3990         pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
3991         if (pi != tree) {
3992                 va_start(ap, format);
3993                 proto_tree_set_representation_value(pi, format, ap);
3994                 va_end(ap);
3995         }
3996
3997         return pi;
3998 }
3999
4000 proto_item *
4001 proto_tree_add_ether_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4002                             gint start, gint length, const guint8* value,
4003                             const char *format, ...)
4004 {
4005         proto_item        *pi;
4006         va_list            ap;
4007
4008         pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
4009         if (pi != tree) {
4010                 TRY_TO_FAKE_THIS_REPR(pi);
4011
4012                 va_start(ap, format);
4013                 proto_tree_set_representation(pi, format, ap);
4014                 va_end(ap);
4015         }
4016
4017         return pi;
4018 }
4019
4020 /* Set the FT_ETHER value */
4021 static void
4022 proto_tree_set_ether(field_info *fi, const guint8* value)
4023 {
4024         fvalue_set_bytes(&fi->value, value);
4025 }
4026
4027 static void
4028 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start)
4029 {
4030         proto_tree_set_ether(fi, tvb_get_ptr(tvb, start, FT_ETHER_LEN));
4031 }
4032
4033 /* Add a FT_BOOLEAN to a proto_tree */
4034 proto_item *
4035 proto_tree_add_boolean(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
4036                        gint length, guint32 value)
4037 {
4038         proto_item        *pi;
4039         header_field_info *hfinfo;
4040
4041         CHECK_FOR_NULL_TREE(tree);
4042
4043         TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
4044
4045         DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_BOOLEAN);
4046
4047         pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
4048         proto_tree_set_boolean(PNODE_FINFO(pi), value);
4049
4050         return pi;
4051 }
4052
4053 proto_item *
4054 proto_tree_add_boolean_format_value(proto_tree *tree, int hfindex,
4055                                     tvbuff_t *tvb, gint start, gint length,
4056                                     guint32 value, const char *format, ...)
4057 {
4058         proto_item        *pi;
4059         va_list            ap;
4060
4061         pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
4062         if (pi != tree) {
4063                 va_start(ap, format);
4064                 proto_tree_set_representation_value(pi, format, ap);
4065                 va_end(ap);
4066         }
4067
4068         return pi;
4069 }
4070
4071 proto_item *
4072 proto_tree_add_boolean_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4073                               gint start, gint length, guint32 value,
4074                               const char *format, ...)
4075 {
4076         proto_item        *pi;
4077         va_list            ap;
4078
4079         pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
4080         if (pi != tree) {
4081                 TRY_TO_FAKE_THIS_REPR(pi);
4082
4083                 va_start(ap, format);
4084                 proto_tree_set_representation(pi, format, ap);
4085                 va_end(ap);
4086         }
4087
4088         return pi;
4089 }
4090
4091 static proto_item *
4092 proto_tree_add_boolean64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
4093                          gint length, guint64 value)
4094 {
4095         proto_item        *pi;
4096         header_field_info *hfinfo;
4097
4098         CHECK_FOR_NULL_TREE(tree);
4099
4100         TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
4101
4102         DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_BOOLEAN);
4103
4104         pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
4105         proto_tree_set_boolean(PNODE_FINFO(pi), value);
4106
4107         return pi;
4108 }
4109
4110 /* Set the FT_BOOLEAN value */
4111 static void
4112 proto_tree_set_boolean(field_info *fi, guint64 value)
4113 {
4114         proto_tree_set_uint64(fi, value);
4115 }
4116
4117 /* Generate, into "buf", a string showing the bits of a bitfield.
4118    Return a pointer to the character after that string. */
4119 /*XXX this needs a buf_len check */
4120 static char *
4121 other_decode_bitfield_value(char *buf, const guint64 val, const guint64 mask, const int width)
4122 {
4123         int i;
4124         guint64 bit;
4125         char *p;
4126
4127         i = 0;
4128         p = buf;
4129         bit = G_GUINT64_CONSTANT(1) << (width - 1);
4130         for (;;) {
4131                 if (mask & bit) {
4132                         /* This bit is part of the field.  Show its value. */
4133                         if (val & bit)
4134                                 *p++ = '1';
4135                         else
4136                                 *p++ = '0';
4137                 } else {
4138                         /* This bit is not part of the field. */
4139                         *p++ = '.';
4140                 }
4141                 bit >>= 1;
4142                 i++;
4143                 if (i >= width)
4144                         break;
4145                 if (i % 4 == 0)
4146                         *p++ = ' ';
4147         }
4148         *p = '\0';
4149         return p;
4150 }
4151
4152 static char *
4153 decode_bitfield_value(char *buf, const guint64 val, const guint64 mask, const int width)
4154 {
4155         char *p;
4156
4157         p = other_decode_bitfield_value(buf, val, mask, width);
4158         p = g_stpcpy(p, " = ");
4159
4160         return p;
4161 }
4162
4163 /* Add a FT_FLOAT to a proto_tree */
4164 proto_item *
4165 proto_tree_add_float(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
4166                      gint length, float value)
4167 {
4168         proto_item        *pi;
4169         header_field_info *hfinfo;
4170
4171         CHECK_FOR_NULL_TREE(tree);
4172
4173         TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
4174
4175         DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_FLOAT);
4176
4177         pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
4178         proto_tree_set_float(PNODE_FINFO(pi), value);
4179
4180         return pi;
4181 }
4182
4183 proto_item *
4184 proto_tree_add_float_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4185                                   gint start, gint length, float value,
4186                                   const char *format, ...)
4187 {
4188         proto_item        *pi;
4189         va_list            ap;
4190
4191         pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
4192         if (pi != tree) {
4193                 va_start(ap, format);
4194                 proto_tree_set_representation_value(pi, format, ap);
4195                 va_end(ap);
4196         }
4197
4198         return pi;
4199 }
4200
4201 proto_item *
4202 proto_tree_add_float_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4203                             gint start, gint length, float value,
4204                             const char *format, ...)
4205 {
4206         proto_item        *pi;
4207         va_list            ap;
4208
4209         pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
4210         if (pi != tree) {
4211                 TRY_TO_FAKE_THIS_REPR(pi);
4212
4213                 va_start(ap, format);
4214                 proto_tree_set_representation(pi, format, ap);
4215                 va_end(ap);
4216         }
4217
4218         return pi;
4219 }
4220
4221 /* Set the FT_FLOAT value */
4222 static void
4223 proto_tree_set_float(field_info *fi, float value)
4224 {
4225         fvalue_set_floating(&fi->value, value);
4226 }
4227
4228 /* Add a FT_DOUBLE to a proto_tree */
4229 proto_item *
4230 proto_tree_add_double(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
4231                       gint length, double value)
4232 {
4233         proto_item        *pi;
4234         header_field_info *hfinfo;
4235
4236         CHECK_FOR_NULL_TREE(tree);
4237
4238         TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
4239
4240         DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_DOUBLE);
4241
4242         pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
4243         proto_tree_set_double(PNODE_FINFO(pi), value);
4244
4245         return pi;
4246 }
4247
4248 proto_item *
4249 proto_tree_add_double_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4250                                    gint start, gint length, double value,
4251                                    const char *format, ...)
4252 {
4253         proto_item        *pi;
4254         va_list            ap;
4255
4256         pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
4257         if (pi != tree) {
4258                 va_start(ap, format);
4259                 proto_tree_set_representation_value(pi, format, ap);
4260                 va_end(ap);
4261         }
4262
4263         return pi;
4264 }
4265
4266 proto_item *
4267 proto_tree_add_double_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4268                              gint start, gint length, double value,
4269                              const char *format, ...)
4270 {
4271         proto_item        *pi;
4272         va_list            ap;
4273
4274         pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
4275         if (pi != tree) {
4276                 TRY_TO_FAKE_THIS_REPR(pi);
4277
4278                 va_start(ap, format);
4279                 proto_tree_set_representation(pi, format, ap);
4280                 va_end(ap);
4281         }
4282
4283         return pi;
4284 }
4285
4286 /* Set the FT_DOUBLE value */
4287 static void
4288 proto_tree_set_double(field_info *fi, double value)
4289 {
4290         fvalue_set_floating(&fi->value, value);
4291 }
4292
4293 /* Add FT_CHAR or FT_UINT{8,16,24,32} to a proto_tree */
4294 proto_item *
4295 proto_tree_add_uint(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
4296                     gint length, guint32 value)
4297 {
4298         proto_item        *pi = NULL;
4299         header_field_info *hfinfo;
4300
4301         CHECK_FOR_NULL_TREE(tree);
4302
4303         TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
4304
4305         switch (hfinfo->type) {
4306                 case FT_CHAR:
4307                 case FT_UINT8:
4308                 case FT_UINT16:
4309                 case FT_UINT24:
4310                 case FT_UINT32:
4311                 case FT_FRAMENUM:
4312                         pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
4313                         proto_tree_set_uint(PNODE_FINFO(pi), value);
4314                         break;
4315
4316                 default:
4317                         REPORT_DISSECTOR_BUG(wmem_strdup_printf(wmem_packet_scope(),
4318                             "field %s is not of type FT_CHAR, FT_UINT8, FT_UINT16, FT_UINT24, FT_UINT32, or FT_FRAMENUM",
4319                             hfinfo->abbrev));
4320         }
4321
4322         return pi;
4323 }
4324
4325 proto_item *
4326 proto_tree_add_uint_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4327                                  gint start, gint length, guint32 value,
4328                                  const char *format, ...)
4329 {
4330         proto_item        *pi;
4331         va_list            ap;
4332
4333         pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
4334         if (pi != tree) {
4335                 va_start(ap, format);
4336                 proto_tree_set_representation_value(pi, format, ap);
4337                 va_end(ap);
4338         }
4339
4340         return pi;
4341 }
4342
4343 proto_item *
4344 proto_tree_add_uint_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4345                            gint start, gint length, guint32 value,
4346                            const char *format, ...)
4347 {
4348         proto_item        *pi;
4349         va_list            ap;
4350
4351         pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
4352         if (pi != tree) {
4353                 TRY_TO_FAKE_THIS_REPR(pi);
4354
4355                 va_start(ap, format);
4356                 proto_tree_set_representation(pi, format, ap);
4357                 va_end(ap);
4358         }
4359
4360         return pi;
4361 }
4362
4363 /* Set the FT_UINT{8,16,24,32} value */
4364 static void
4365 proto_tree_set_uint(field_info *fi, guint32 value)
4366 {
4367         header_field_info *hfinfo;
4368         guint32            integer;
4369
4370         hfinfo = fi->hfinfo;
4371         integer = value;
4372
4373         if (hfinfo->bitmask) {
4374                 /* Mask out irrelevant portions */
4375                 integer &= (guint32)(hfinfo->bitmask);
4376
4377                 /* Shift bits */
4378                 integer >>= hfinfo_bitshift(hfinfo);
4379         }
4380
4381         fvalue_set_uinteger(&fi->value, integer);
4382 }
4383
4384 /* Add FT_UINT{40,48,56,64} to a proto_tree */
4385 proto_item *
4386 proto_tree_add_uint64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
4387                       gint length, guint64 value)
4388 {
4389         proto_item        *pi = NULL;
4390         header_field_info *hfinfo;
4391
4392         CHECK_FOR_NULL_TREE(tree);
4393
4394         TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
4395
4396         switch (hfinfo->type) {
4397                 case FT_UINT40:
4398                 case FT_UINT48:
4399                 case FT_UINT56:
4400                 case FT_UINT64:
4401                 case FT_FRAMENUM:
4402                         pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
4403                         proto_tree_set_uint64(PNODE_FINFO(pi), value);
4404                         break;
4405
4406                 default:
4407                         REPORT_DISSECTOR_BUG(wmem_strdup_printf(wmem_packet_scope(),
4408                             "field %s is not of type FT_UINT40, FT_UINT48, FT_UINT56, FT_UINT64, or FT_FRAMENUM",
4409                             hfinfo->abbrev));
4410         }
4411
4412         return pi;
4413 }
4414
4415 proto_item *
4416 proto_tree_add_uint64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4417                                    gint start, gint length, guint64 value,
4418                                    const char *format, ...)
4419 {
4420         proto_item        *pi;
4421         va_list            ap;
4422
4423         pi = proto_tree_add_uint64(tree, hfindex, tvb, start, length, value);
4424         if (pi != tree) {
4425                 va_start(ap, format);
4426                 proto_tree_set_representation_value(pi, format, ap);
4427                 va_end(ap);
4428         }
4429
4430         return pi;
4431 }
4432
4433 proto_item *
4434 proto_tree_add_uint64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4435                              gint start, gint length, guint64 value,
4436                              const char *format, ...)
4437 {
4438         proto_item        *pi;
4439         va_list            ap;
4440
4441         pi = proto_tree_add_uint64(tree, hfindex, tvb, start, length, value);
4442         if (pi != tree) {
4443                 TRY_TO_FAKE_THIS_REPR(pi);
4444
4445                 va_start(ap, format);
4446                 proto_tree_set_representation(pi, format, ap);
4447                 va_end(ap);
4448         }
4449
4450         return pi;
4451 }
4452
4453 /* Set the FT_UINT{40,48,56,64} value */
4454 static void
4455 proto_tree_set_uint64(field_info *fi, guint64 value)
4456 {
4457         header_field_info *hfinfo;
4458         guint64            integer;
4459
4460         hfinfo = fi->hfinfo;
4461         integer = value;
4462
4463         if (hfinfo->bitmask) {
4464                 /* Mask out irrelevant portions */
4465                 integer &= hfinfo->bitmask;
4466
4467                 /* Shift bits */
4468                 integer >>= hfinfo_bitshift(hfinfo);
4469         }
4470
4471         fvalue_set_uinteger64(&fi->value, integer);
4472 }
4473
4474 /* Add FT_INT{8,16,24,32} to a proto_tree */
4475 proto_item *
4476 proto_tree_add_int(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
4477                    gint length, gint32 value)
4478 {
4479         proto_item        *pi = NULL;
4480         header_field_info *hfinfo;
4481
4482         CHECK_FOR_NULL_TREE(tree);
4483
4484         TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
4485
4486         switch (hfinfo->type) {
4487                 case FT_INT8:
4488                 case FT_INT16:
4489                 case FT_INT24:
4490                 case FT_INT32:
4491                         pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
4492                         proto_tree_set_int(PNODE_FINFO(pi), value);
4493                         break;
4494
4495                 default:
4496                         REPORT_DISSECTOR_BUG(wmem_strdup_printf(wmem_packet_scope(),
4497                             "field %s is not of type FT_INT8, FT_INT16, FT_INT24, or FT_INT32",
4498                             hfinfo->abbrev));
4499         }
4500
4501         return pi;
4502 }
4503
4504 proto_item *
4505 proto_tree_add_int_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4506                                 gint start, gint length, gint32 value,
4507                                 const char *format, ...)
4508 {
4509         proto_item  *pi;
4510         va_list      ap;
4511
4512         pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
4513         if (pi != tree) {
4514                 va_start(ap, format);
4515                 proto_tree_set_representation_value(pi, format, ap);
4516                 va_end(ap);
4517         }
4518
4519         return pi;
4520 }
4521
4522 proto_item *
4523 proto_tree_add_int_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4524                           gint start, gint length, gint32 value,
4525                           const char *format, ...)
4526 {
4527         proto_item *pi;
4528         va_list     ap;
4529
4530         pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
4531         if (pi != tree) {
4532                 TRY_TO_FAKE_THIS_REPR(pi);
4533
4534                 va_start(ap, format);
4535                 proto_tree_set_representation(pi, format, ap);
4536                 va_end(ap);
4537         }
4538
4539         return pi;
4540 }
4541
4542 /* Set the FT_INT{8,16,24,32} value */
4543 static void
4544 proto_tree_set_int(field_info *fi, gint32 value)
4545 {
4546         header_field_info *hfinfo;
4547         guint32            integer;
4548         gint               no_of_bits;
4549
4550         hfinfo = fi->hfinfo;
4551         integer = (guint32) value;
4552
4553         if (hfinfo->bitmask) {
4554                 /* Mask out irrelevant portions */
4555                 integer &= (guint32)(hfinfo->bitmask);
4556
4557                 /* Shift bits */
4558                 integer >>= hfinfo_bitshift(hfinfo);
4559
4560                 no_of_bits = ws_count_ones(hfinfo->bitmask);
4561                 integer = ws_sign_ext32(integer, no_of_bits);
4562         }
4563
4564         fvalue_set_sinteger(&fi->value, integer);
4565 }
4566
4567 /* Add FT_INT{40,48,56,64} to a proto_tree */
4568 proto_item *
4569 proto_tree_add_int64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
4570                      gint length, gint64 value)
4571 {
4572         proto_item        *pi = NULL;
4573         header_field_info *hfinfo;
4574
4575         CHECK_FOR_NULL_TREE(tree);
4576
4577         TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
4578
4579         switch (hfinfo->type) {
4580                 case FT_INT40:
4581                 case FT_INT48:
4582                 case FT_INT56:
4583                 case FT_INT64:
4584                         pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
4585                         proto_tree_set_int64(PNODE_FINFO(pi), value);
4586                         break;
4587
4588                 default:
4589                         REPORT_DISSECTOR_BUG(wmem_strdup_printf(wmem_packet_scope(),
4590                             "field %s is not of type FT_INT40, FT_INT48, FT_INT56, or FT_INT64",
4591                             hfinfo->abbrev));
4592         }
4593
4594         return pi;
4595 }
4596
4597 proto_item *
4598 proto_tree_add_int64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4599                                   gint start, gint length, gint64 value,
4600                                   const char *format, ...)
4601 {
4602         proto_item        *pi;
4603         va_list            ap;
4604
4605         pi = proto_tree_add_int64(tree, hfindex, tvb, start, length, value);
4606         if (pi != tree) {
4607                 va_start(ap, format);
4608                 proto_tree_set_representation_value(pi, format, ap);
4609                 va_end(ap);
4610         }
4611
4612         return pi;
4613 }
4614
4615 /* Set the FT_INT{40,48,56,64} value */
4616 static void
4617 proto_tree_set_int64(field_info *fi, gint64 value)
4618 {
4619         header_field_info *hfinfo;
4620         guint64            integer;
4621         gint               no_of_bits;
4622
4623         hfinfo = fi->hfinfo;
4624         integer = value;
4625
4626         if (hfinfo->bitmask) {
4627                 /* Mask out irrelevant portions */
4628                 integer &= hfinfo->bitmask;
4629
4630                 /* Shift bits */
4631                 integer >>= hfinfo_bitshift(hfinfo);
4632
4633                 no_of_bits = ws_count_ones(hfinfo->bitmask);
4634                 integer = ws_sign_ext64(integer, no_of_bits);
4635         }
4636
4637         fvalue_set_sinteger64(&fi->value, integer);
4638 }
4639
4640 proto_item *
4641 proto_tree_add_int64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4642                            gint start, gint length, gint64 value,
4643                            const char *format, ...)
4644 {
4645         proto_item        *pi;
4646         va_list            ap;
4647
4648         pi = proto_tree_add_int64(tree, hfindex, tvb, start, length, value);
4649         if (pi != tree) {
4650                 TRY_TO_FAKE_THIS_REPR(pi);
4651
4652                 va_start(ap, format);
4653                 proto_tree_set_representation(pi, format, ap);
4654                 va_end(ap);
4655         }
4656
4657         return pi;
4658 }
4659
4660 /* Add a FT_EUI64 to a proto_tree */
4661 proto_item *
4662 proto_tree_add_eui64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
4663                      gint length, const guint64 value)
4664 {
4665         proto_item        *pi;
4666         header_field_info *hfinfo;
4667
4668         CHECK_FOR_NULL_TREE(tree);
4669
4670         TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
4671
4672         DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_EUI64);
4673
4674         pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
4675         proto_tree_set_eui64(PNODE_FINFO(pi), value);
4676
4677         return pi;
4678 }
4679
4680 proto_item *
4681 proto_tree_add_eui64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4682                                   gint start, gint length, const guint64 value,
4683                                   const char *format, ...)
4684 {
4685         proto_item        *pi;
4686         va_list            ap;
4687
4688         pi = proto_tree_add_eui64(tree, hfindex, tvb, start, length, value);
4689         if (pi != tree) {
4690                 va_start(ap, format);
4691                 proto_tree_set_representation_value(pi, format, ap);
4692                 va_end(ap);
4693         }
4694
4695         return pi;
4696 }
4697
4698 proto_item *
4699 proto_tree_add_eui64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4700                             gint start, gint length, const guint64 value,
4701                             const char *format, ...)
4702 {
4703         proto_item        *pi;
4704         va_list            ap;
4705
4706         pi = proto_tree_add_eui64(tree, hfindex, tvb, start, length, value);
4707         if (pi != tree) {
4708                 TRY_TO_FAKE_THIS_REPR(pi);
4709
4710                 va_start(ap, format);
4711                 proto_tree_set_representation(pi, format, ap);
4712                 va_end(ap);
4713         }
4714
4715         return pi;
4716 }
4717
4718 /* Set the FT_EUI64 value */
4719 static void
4720 proto_tree_set_eui64(field_info *fi, const guint64 value)
4721 {
4722         fvalue_set_uinteger64(&fi->value, value);
4723 }
4724 static void
4725 proto_tree_set_eui64_tvb(field_info *fi, tvbuff_t *tvb, gint start, const guint encoding)
4726 {
4727         if (encoding)
4728         {
4729                 proto_tree_set_eui64(fi, tvb_get_letoh64(tvb, start));
4730         } else {
4731                 proto_tree_set_eui64(fi, tvb_get_ntoh64(tvb, start));
4732         }
4733 }
4734
4735 /* Add a field_info struct to the proto_tree, encapsulating it in a proto_node */
4736 static proto_item *
4737 proto_tree_add_node(proto_tree *tree, field_info *fi)
4738 {
4739         proto_node *pnode, *tnode, *sibling;
4740         field_info *tfi;
4741         int depth = 1;
4742
4743         /*
4744          * Restrict our depth. proto_tree_traverse_pre_order and
4745          * proto_tree_traverse_post_order (and possibly others) are recursive
4746          * so we need to be mindful of our stack size.
4747          */
4748         if (tree->first_child == NULL) {
4749                 for (tnode = tree; tnode != NULL; tnode = tnode->parent) {
4750                         depth++;
4751                         if (G_UNLIKELY(depth > MAX_TREE_LEVELS)) {
4752                                 THROW_MESSAGE(DissectorError, wmem_strdup_printf(wmem_packet_scope(),
4753                                                      "Maximum tree depth %d exceeded for \"%s\" - \"%s\" (%s:%u)",
4754                                                      MAX_TREE_LEVELS,
4755                                                      fi->hfinfo->name, fi->hfinfo->abbrev, G_STRFUNC, __LINE__));
4756                         }
4757                 }
4758         }
4759
4760         /*
4761          * Make sure "tree" is ready to have subtrees under it, by
4762          * checking whether it's been given an ett_ value.
4763          *
4764          * "PNODE_FINFO(tnode)" may be null; that's the case for the root
4765          * node of the protocol tree.  That node is not displayed,
4766          * so it doesn't need an ett_ value to remember whether it
4767          * was expanded.
4768          */
4769         tnode = tree;
4770         tfi = PNODE_FINFO(tnode);
4771         if (tfi != NULL && (tfi->tree_type < 0 || tfi->tree_type >= num_tree_types)) {
4772                 REPORT_DISSECTOR_BUG(wmem_strdup_printf(wmem_packet_scope(),
4773                                      "\"%s\" - \"%s\" tfi->tree_type: %d invalid (%s:%u)",
4774                                      fi->hfinfo->name, fi->hfinfo->abbrev, tfi->tree_type, __FILE__, __LINE__));
4775                 /* XXX - is it safe to continue here? */
4776         }
4777
4778         pnode = wmem_new(PNODE_POOL(tree), proto_node);
4779         PROTO_NODE_INIT(pnode);
4780         pnode->parent = tnode;
4781         PNODE_FINFO(pnode) = fi;
4782         pnode->tree_data = PTREE_DATA(tree);
4783
4784         if (tnode->last_child != NULL) {
4785                 sibling = tnode->last_child;
4786                 DISSECTOR_ASSERT(sibling->next == NULL);
4787                 sibling->next = pnode;
4788         } else
4789                 tnode->first_child = pnode;
4790         tnode->last_child = pnode;
4791
4792         tree_data_add_maybe_interesting_field(pnode->tree_data, fi);
4793
4794         return (proto_item *)pnode;
4795 }
4796
4797
4798 /* Generic way to allocate field_info and add to proto_tree.
4799  * Sets *pfi to address of newly-allocated field_info struct */
4800 static proto_item *
4801 proto_tree_add_pi(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb, gint start,
4802                   gint *length)
4803 {
4804         proto_item *pi;
4805         field_info *fi;
4806         gint            item_length;
4807
4808         get_hfi_length(hfinfo, tvb, start, length, &item_length);
4809         fi = new_field_info(tree, hfinfo, tvb, start, item_length);
4810         pi = proto_tree_add_node(tree, fi);
4811
4812         return pi;
4813 }
4814
4815
4816 static void
4817 get_hfi_length(header_field_info *hfinfo, tvbuff_t *tvb, const gint start, gint *length,
4818                    gint *item_length)
4819 {
4820         gint length_remaining;
4821
4822         /*
4823          * We only allow a null tvbuff if the item has a zero length,
4824          * i.e. if there's no data backing it.
4825          */
4826         DISSECTOR_ASSERT(tvb != NULL || *length == 0);
4827
4828         /*
4829          * XXX - in some protocols, there are 32-bit unsigned length
4830          * fields, so lengths in protocol tree and tvbuff routines
4831          * should really be unsigned.  We should have, for those
4832          * field types for which "to the end of the tvbuff" makes sense,
4833          * additional routines that take no length argument and
4834          * add fields that run to the end of the tvbuff.
4835          */
4836         if (*length == -1) {
4837                 /*
4838                  * For FT_NONE, FT_PROTOCOL, FT_BYTES, FT_STRING, and
4839                  * FT_STRINGZPAD fields, a length of -1 means "set the
4840                  * length to what remains in the tvbuff".
4841                  *
4842                  * The assumption is either that
4843                  *
4844                  *      1) the length of the item can only be determined
4845                  *         by dissection (typically true of items with
4846                  *         subitems, which are probably FT_NONE or
4847                  *         FT_PROTOCOL)
4848                  *
4849                  * or
4850                  *
4851                  *      2) if the tvbuff is "short" (either due to a short
4852                  *         snapshot length or due to lack of reassembly of
4853                  *         fragments/segments/whatever), we want to display
4854                  *         what's available in the field (probably FT_BYTES
4855                  *         or FT_STRING) and then throw an exception later
4856                  *
4857                  * or
4858                  *
4859                  *      3) the field is defined to be "what's left in the
4860                  *         packet"
4861                  *
4862                  * so we set the length to what remains in the tvbuff so
4863                  * that, if we throw an exception while dissecting, it
4864                  * has what is probably the right value.
4865                  *
4866                  * For FT_STRINGZ, it means "the string is null-terminated,
4867                  * not null-padded; set the length to the actual length
4868                  * of the string", and if the tvbuff if short, we just
4869                  * throw an exception.
4870                  *
4871                  * It's not valid for any other type of field.  For those
4872                  * fields, we treat -1 the same way we treat other
4873                  * negative values - we assume the length is a Really
4874                  * Big Positive Number, and throw a ReportedBoundsError
4875                  * exception, under the assumption that the Really Big
4876                  * Length would run past the end of the packet.
4877                  */
4878                 switch (hfinfo->type) {
4879
4880                 case FT_PROTOCOL:
4881                 case FT_NONE:
4882                 case FT_BYTES:
4883                 case FT_STRING:
4884                 case FT_STRINGZPAD:
4885                         /*
4886                          * We allow FT_PROTOCOLs to be zero-length -
4887                          * for example, an ONC RPC NULL procedure has
4888                          * neither arguments nor reply, so the
4889                          * payload for that protocol is empty.
4890                          *
4891                          * We also allow the others to be zero-length -
4892                          * because that's the way the code has been for a
4893                          * long, long time.
4894                          *
4895                          * However, we want to ensure that the start
4896                          * offset is not *past* the byte past the end
4897                          * of the tvbuff: we throw an exception in that
4898                          * case.
4899                          */
4900                         *length = tvb_captured_length(tvb) ? tvb_ensure_captured_length_remaining(tvb, start) : 0;
4901                         DISSECTOR_ASSERT(*length >= 0);
4902                         break;
4903
4904                 case FT_STRINGZ:
4905                         /*
4906                          * Leave the length as -1, so our caller knows
4907                          * it was -1.
4908                          */
4909                         break;
4910
4911                 default:
4912                         THROW(ReportedBoundsError);
4913                         DISSECTOR_ASSERT_NOT_REACHED();
4914                 }
4915                 *item_length = *length;
4916         } else {
4917                 *item_length = *length;
4918                 if (hfinfo->type == FT_PROTOCOL || hfinfo->type == FT_NONE) {
4919                         /*
4920                          * These types are for interior nodes of the
4921                          * tree, and don't have data associated with
4922                          * them; if the length is negative (XXX - see
4923                          * above) or goes past the end of the tvbuff,
4924                          * cut it short at the end of the tvbuff.
4925                          * That way, if this field is selected in
4926                          * Wireshark, we don't highlight stuff past
4927                          * the end of the data.
4928                          */
4929                         /* XXX - what to do, if we don't have a tvb? */
4930                         if (tvb) {
4931                                 length_remaining = tvb_captured_length_remaining(tvb, start);
4932                                 if (*item_length < 0 ||
4933                                         (*item_length > 0 &&
4934                                           (length_remaining < *item_length)))
4935                                         *item_length = length_remaining;
4936                         }
4937                 }
4938                 if (*item_length < 0) {
4939                         THROW(ReportedBoundsError);
4940                 }
4941         }
4942 }
4943
4944 static gint
4945 get_full_length(header_field_info *hfinfo, tvbuff_t *tvb, const gint start,
4946                 gint length, guint item_length, const gint encoding)
4947 {
4948         guint32 n;
4949
4950         /*
4951          * We need to get the correct item length here.
4952          * That's normally done by proto_tree_new_item(),
4953          * but we won't be calling it.
4954          */
4955         switch (hfinfo->type) {
4956
4957         case FT_NONE:
4958         case FT_PROTOCOL:
4959         case FT_BYTES:
4960                 /*
4961                  * The length is the specified length.
4962                  */
4963                 break;
4964
4965         case FT_UINT_BYTES:
4966                 /*
4967                  * Map all non-zero values to little-endian for
4968                  * backwards compatibility.
4969                  */
4970                 n = get_uint_value(NULL, tvb, start, length,
4971                     encoding ? ENC_LITTLE_ENDIAN : ENC_BIG_ENDIAN);
4972                 item_length += n;
4973                 break;
4974
4975         case FT_BOOLEAN:
4976         case FT_CHAR:
4977         /* XXX - make these just FT_UINT? */
4978         case FT_UINT8:
4979         case FT_UINT16:
4980         case FT_UINT24:
4981         case FT_UINT32:
4982         case FT_UINT40:
4983         case FT_UINT48:
4984         case FT_UINT56:
4985         case FT_UINT64:
4986         /* XXX - make these just FT_INT? */
4987         case FT_INT8:
4988         case FT_INT16:
4989         case FT_INT24:
4990         case FT_INT32:
4991         case FT_INT40:
4992         case FT_INT48:
4993         case FT_INT56:
4994         case FT_INT64:
4995         case FT_IPv4:
4996         case FT_IPXNET:
4997         case FT_IPv6:
4998         case FT_FCWWN:
4999         case FT_AX25:
5000         case FT_VINES:
5001         case FT_ETHER:
5002         case FT_EUI64:
5003         case FT_GUID:
5004         case FT_OID:
5005         case FT_REL_OID:
5006         case FT_SYSTEM_ID:
5007         case FT_FLOAT:
5008         case FT_DOUBLE:
5009         case FT_STRING:
5010                 /*
5011                  * The length is the specified length.
5012                  */
5013                 break;
5014
5015         case FT_STRINGZ:
5016                 if (length < -1) {
5017                         report_type_length_mismatch(NULL, "a string", length, TRUE);
5018                 }
5019                 if (length == -1) {
5020                         /* This can throw an exception */
5021                         /* XXX - do this without fetching the string? */
5022                         tvb_get_stringz_enc(wmem_packet_scope(), tvb, start, &length, encoding);
5023                 }
5024                 item_length = length;
5025                 break;
5026
5027         case FT_UINT_STRING:
5028                 n = get_uint_value(NULL, tvb, start, length, encoding & ~ENC_CHARENCODING_MASK);
5029                 item_length += n;
5030                 break;
5031
5032         case FT_STRINGZPAD:
5033         case FT_ABSOLUTE_TIME:
5034         case FT_RELATIVE_TIME:
5035         case FT_IEEE_11073_SFLOAT:
5036         case FT_IEEE_11073_FLOAT:
5037                 /*
5038                  * The length is the specified length.
5039                  */
5040                 break;
5041
5042         default:
5043                 g_error("hfinfo->type %d (%s) not handled\n",
5044                                 hfinfo->type,
5045                                 ftype_name(hfinfo->type));
5046                 DISSECTOR_ASSERT_NOT_REACHED();
5047                 break;
5048         }
5049         return item_length;
5050 }
5051
5052 static field_info *
5053 new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
5054                const gint start, const gint item_length)
5055 {
5056         field_info *fi;
5057
5058         FIELD_INFO_NEW(PNODE_POOL(tree), fi);
5059
5060         fi->hfinfo     = hfinfo;
5061         fi->start      = start;
5062         fi->start     += (tvb)?tvb_raw_offset(tvb):0;
5063         fi->length     = item_length;
5064         fi->tree_type  = -1;
5065         fi->flags      = 0;
5066         if (!PTREE_DATA(tree)->visible)
5067                 FI_SET_FLAG(fi, FI_HIDDEN);
5068         fvalue_init(&fi->value, fi->hfinfo->type);
5069         fi->rep        = NULL;
5070
5071         /* add the data source tvbuff */
5072         fi->ds_tvb = tvb ? tvb_get_ds_tvb(tvb) : NULL;
5073
5074         fi->appendix_start  = 0;
5075         fi->appendix_length = 0;
5076
5077         return fi;
5078 }
5079
5080 /* If the protocol tree is to be visible, set the representation of a
5081    proto_tree entry with the name of the field for the item and with
5082    the value formatted with the supplied printf-style format and
5083    argument list. */
5084 static void
5085 proto_tree_set_representation_value(proto_item *pi, const char *format, va_list ap)
5086 {
5087         g_assert(pi);
5088
5089         /* If the tree (GUI) or item isn't visible it's pointless for us to generate the protocol
5090          * items string representation */
5091         if (PTREE_DATA(pi)->visible && !PROTO_ITEM_IS_HIDDEN(pi)) {
5092                 int               ret = 0;
5093                 field_info        *fi = PITEM_FINFO(pi);
5094                 header_field_info *hf;
5095
5096                 DISSECTOR_ASSERT(fi);
5097
5098                 hf = fi->hfinfo;
5099
5100                 ITEM_LABEL_NEW(PNODE_POOL(pi), fi->rep);
5101                 if (hf->bitmask && (hf->type == FT_BOOLEAN || IS_FT_UINT(hf->type))) {
5102                         guint64 val;
5103                         char *p;
5104
5105                         if (IS_FT_UINT(hf->type))
5106                                 val = fvalue_get_uinteger(&fi->value);
5107                         else
5108                                 val = fvalue_get_uinteger64(&fi->value);
5109
5110                         val <<= hfinfo_bitshift(hf);
5111
5112                         p = decode_bitfield_value(fi->rep->representation, val, hf->bitmask, hfinfo_container_bitwidth(hf));
5113                         ret = (int) (p - fi->rep->representation);
5114                 }
5115
5116                 /* put in the hf name */
5117                 ret += g_snprintf(fi->rep->representation + ret, ITEM_LABEL_LENGTH - ret, "%s: ", hf->name);
5118
5119                 /* If possible, Put in the value of the string */
5120                 if (ret < ITEM_LABEL_LENGTH) {
5121                         ret += g_vsnprintf(fi->rep->representation + ret,
5122                                           ITEM_LABEL_LENGTH - ret, format, ap);
5123                 }
5124                 if (ret >= ITEM_LABEL_LENGTH) {
5125                         /* Uh oh, we don't have enough room.  Tell the user
5126                          * that the field is truncated.
5127                          */
5128                         LABEL_MARK_TRUNCATED_START(fi->rep->representation);
5129                 }
5130         }
5131 }
5132
5133 /* If the protocol tree is to be visible, set the representation of a
5134    proto_tree entry with the representation formatted with the supplied
5135    printf-style format and argument list. */
5136 static void
5137 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap)
5138 {
5139         int         ret;        /*tmp return value */
5140         field_info *fi = PITEM_FINFO(pi);
5141
5142         DISSECTOR_ASSERT(fi);
5143
5144         if (!PROTO_ITEM_IS_HIDDEN(pi)) {
5145                 ITEM_LABEL_NEW(PNODE_POOL(pi), fi->rep);
5146                 ret = g_vsnprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
5147                                   format, ap);
5148                 if (ret >= ITEM_LABEL_LENGTH) {
5149                         /* Uh oh, we don't have enough room.  Tell the user
5150                          * that the field is truncated.
5151                          */
5152                         LABEL_MARK_TRUNCATED_START(fi->rep->representation);
5153                 }
5154         }
5155 }
5156
5157 static char *
5158 hfinfo_format_text(const header_field_info *hfinfo, const guchar *string)
5159 {
5160         switch (hfinfo->display) {
5161                 case STR_ASCII:
5162                         return format_text(NULL, string, strlen(string));
5163 /*
5164                 case STR_ASCII_WSP
5165                         return format_text_wsp(string, strlen(string));
5166  */
5167                 case STR_UNICODE:
5168                         /* XXX, format_unicode_text() */
5169                         return wmem_strdup(NULL, string);
5170         }
5171
5172         return format_text(NULL, string, strlen(string));
5173 }
5174
5175 static int
5176 protoo_strlcpy(gchar *dest, const gchar *src, gsize dest_size)
5177 {
5178         gsize res = g_strlcpy(dest, src, dest_size);
5179
5180         if (res > dest_size)
5181                 res = dest_size;
5182         return (int) res;
5183 }
5184
5185 static header_field_info *
5186 hfinfo_same_name_get_prev(const header_field_info *hfinfo)
5187 {
5188         header_field_info *dup_hfinfo;
5189
5190         if (hfinfo->same_name_prev_id == -1)
5191                 return NULL;
5192         PROTO_REGISTRAR_GET_NTH(hfinfo->same_name_prev_id, dup_hfinfo);
5193         return dup_hfinfo;
5194 }
5195
5196 static void
5197 hfinfo_remove_from_gpa_name_map(const header_field_info *hfinfo)
5198 {
5199         g_free(last_field_name);
5200         last_field_name = NULL;
5201
5202         if (!hfinfo->same_name_next && hfinfo->same_name_prev_id == -1) {
5203                 /* No hfinfo with the same name */
5204                 g_hash_table_steal(gpa_name_map, hfinfo->abbrev);
5205                 return;
5206         }
5207
5208         if (hfinfo->same_name_next) {
5209                 hfinfo->same_name_next->same_name_prev_id = hfinfo->same_name_prev_id;
5210         }
5211
5212         if (hfinfo->same_name_prev_id != -1) {
5213                 header_field_info *same_name_prev = hfinfo_same_name_get_prev(hfinfo);
5214                 same_name_prev->same_name_next = hfinfo->same_name_next;
5215                 if (!hfinfo->same_name_next) {
5216                         /* It's always the latest added hfinfo which is stored in gpa_name_map */
5217                         g_hash_table_insert(gpa_name_map, (gpointer) (same_name_prev->abbrev), same_name_prev);
5218                 }
5219         }
5220 }
5221
5222 /* -------------------------- */
5223 const gchar *
5224 proto_custom_set(proto_tree* tree, GSList *field_ids, gint occurrence,
5225                  gchar *result, gchar *expr, const int size)
5226 {
5227         guint32             number;
5228         guint64             number64;
5229         guint8             *bytes;
5230         ipv4_addr_and_mask *ipv4;
5231         struct e_in6_addr  *ipv6;
5232         address             addr;
5233         guint32             n_addr; /* network-order IPv4 address */
5234
5235         const true_false_string  *tfstring;
5236
5237         int                 len, prev_len = 0, last, i, offset_r = 0, offset_e = 0;
5238         GPtrArray          *finfos;
5239         field_info         *finfo         = NULL;
5240         header_field_info*  hfinfo;
5241         const gchar        *abbrev        = NULL;
5242
5243         const char *hf_str_val;
5244         char number_buf[48];
5245         const char *number_out;
5246         char *tmpbuf, *str;
5247         int *field_idx;
5248         int field_id;
5249         int ii = 0;
5250
5251         g_assert(field_ids != NULL);
5252         while ((field_idx = (int *) g_slist_nth_data(field_ids, ii++))) {
5253                 field_id = *field_idx;
5254                 PROTO_REGISTRAR_GET_NTH((guint)field_id, hfinfo);
5255
5256                 /* do we need to rewind ? */
5257                 if (!hfinfo)
5258                         return "";
5259
5260                 if (occurrence < 0) {
5261                         /* Search other direction */
5262                         while (hfinfo->same_name_prev_id != -1) {
5263                                 PROTO_REGISTRAR_GET_NTH(hfinfo->same_name_prev_id, hfinfo);
5264                         }
5265                 }
5266
5267                 while (hfinfo) {
5268                         finfos = proto_get_finfo_ptr_array(tree, hfinfo->id);
5269
5270                         if (!finfos || !(len = g_ptr_array_len(finfos))) {
5271                                 if (occurrence < 0) {
5272                                         hfinfo = hfinfo->same_name_next;
5273                                 } else {
5274                                         hfinfo = hfinfo_same_name_get_prev(hfinfo);
5275                                 }
5276                                 continue;
5277                         }
5278
5279                         /* Are there enough occurrences of the field? */
5280                         if (((occurrence - prev_len) > len) || ((occurrence + prev_len) < -len)) {
5281                                 if (occurrence < 0) {
5282                                         hfinfo = hfinfo->same_name_next;
5283                                 } else {
5284                                         hfinfo = hfinfo_same_name_get_prev(hfinfo);
5285                                 }
5286                                 prev_len += len;
5287                                 continue;
5288                         }
5289
5290                         /* Calculate single index or set outer bounderies */
5291                         if (occurrence < 0) {
5292                                 i = occurrence + len + prev_len;
5293                                 last = i;
5294                         } else if (occurrence > 0) {
5295                                 i = occurrence - 1 - prev_len;
5296                                 last = i;
5297                         } else {
5298                                 i = 0;
5299                                 last = len - 1;
5300                         }
5301
5302                         prev_len += len; /* Count handled occurrences */
5303
5304                         while (i <= last) {
5305                                 finfo = (field_info *)g_ptr_array_index(finfos, i);
5306
5307                                 if (offset_r && (offset_r < (size - 2)))
5308                                         result[offset_r++] = ',';
5309
5310                                 if (offset_e && (offset_e < (size - 2)))
5311                                         expr[offset_e++] = ',';
5312
5313                                 switch (hfinfo->type) {
5314
5315                                         case FT_NONE: /* Nothing to add */
5316                                                 if (offset_r == 0) {
5317                                                         result[0] = '\0';
5318                                                 } else if (result[offset_r-1] == ',') {
5319                                                         result[offset_r-1] = '\0';
5320                                                 }
5321                                                 break;
5322
5323                                         case FT_PROTOCOL:
5324                                                 /* prevent multiple "yes" entries by setting result directly */
5325                                                 g_strlcpy(result, "Yes", size);
5326                                                 break;
5327
5328                                         case FT_UINT_BYTES:
5329                                         case FT_BYTES:
5330                                                 bytes = (guint8 *)fvalue_get(&finfo->value);
5331                                                 if (bytes) {
5332                                                         switch(hfinfo->display)
5333                                                         {
5334                                                         case SEP_DOT:
5335                                                                 str = bytestring_to_str(NULL, bytes, fvalue_length(&finfo->value), '.');
5336                                                                 break;
5337                                                         case SEP_DASH:
5338                                                                 str = bytestring_to_str(NULL, bytes, fvalue_length(&finfo->value), '-');
5339                                                                 break;
5340                                                         case SEP_COLON:
5341                                                                 str = bytestring_to_str(NULL, bytes, fvalue_length(&finfo->value), ':');
5342                                                                 break;
5343                                                         case SEP_SPACE:
5344                                                                 str = bytestring_to_str(NULL, bytes, fvalue_length(&finfo->value), ' ');
5345                                                                 break;
5346                                                         case BASE_NONE:
5347                                                         default:
5348                                                                 if (prefs.display_byte_fields_with_spaces)
5349                                                                 {
5350                                                                         str = bytestring_to_str(NULL, bytes, fvalue_length(&finfo->value), ' ');
5351                                                                 }
5352                                                                 else
5353                                                                 {
5354                                                                         str = bytes_to_str(NULL, bytes, fvalue_length(&finfo->value));
5355                                                                 }
5356                                                                 break;
5357                                                         }
5358                                                         offset_r += protoo_strlcpy(result+offset_r, str, size-offset_r);
5359                                                         wmem_free(NULL, str);
5360                                                 }
5361                                                 else {
5362                                                         if (hfinfo->display & BASE_ALLOW_ZERO) {
5363                                                                 offset_r += protoo_strlcpy(result+offset_r, "<none>", size-offset_r);
5364                                                         } else {
5365                                                                 offset_r += protoo_strlcpy(result+offset_r, "<MISSING>", size-offset_r);
5366                                                         }
5367                                                 }
5368                                                 break;
5369
5370                                         case FT_ABSOLUTE_TIME:
5371                                                 tmpbuf = abs_time_to_str(NULL, (const nstime_t *)fvalue_get(&finfo->value), (absolute_time_display_e)hfinfo->display, TRUE);
5372                                                 offset_r += protoo_strlcpy(result+offset_r,
5373                                                                 tmpbuf,
5374                                                                 size-offset_r);
5375                                                 wmem_free(NULL, tmpbuf);
5376                                                 break;
5377
5378                                         case FT_RELATIVE_TIME:
5379                                                 tmpbuf = rel_time_to_secs_str(NULL, (const nstime_t *)fvalue_get(&finfo->value));
5380                                                 offset_r += protoo_strlcpy(result+offset_r,
5381                                                                 tmpbuf,
5382                                                                 size-offset_r);
5383                                                 wmem_free(NULL, tmpbuf);
5384                                                 break;
5385
5386                                         case FT_BOOLEAN:
5387                                                 number64 = fvalue_get_uinteger64(&finfo->value);
5388                                                 tfstring = (const true_false_string *)&tfs_true_false;
5389                                                 if (hfinfo->strings) {
5390                                                         tfstring = (const struct true_false_string*) hfinfo->strings;
5391                                                 }
5392                                                 offset_r += protoo_strlcpy(result+offset_r,
5393                                                                 number64 ?
5394                                                                 tfstring->true_string :
5395                                                                 tfstring->false_string, size-offset_r);
5396
5397                                                 offset_e += protoo_strlcpy(expr+offset_e,
5398                                                                 number64 ? "1" : "0", size-offset_e);
5399                                                 break;
5400
5401                                         case FT_CHAR:
5402                                                 hf_str_val = NULL;
5403                                                 number = fvalue_get_uinteger(&finfo->value);
5404
5405                                                 if ((hfinfo->display & FIELD_DISPLAY_E_MASK) == BASE_CUSTOM) {
5406                                                         gchar tmp[ITEM_LABEL_LENGTH];
5407                                                         custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hfinfo->strings;
5408
5409                                                         DISSECTOR_ASSERT(fmtfunc);
5410                                                         fmtfunc(tmp, number);
5411
5412                                                         offset_r += protoo_strlcpy(result+offset_r, tmp, size-offset_r);
5413
5414                                                 } else if (hfinfo->strings) {
5415                                                         number_out = hf_str_val = hf_try_val_to_str(number, hfinfo);
5416
5417                                                         if (!number_out)
5418                                                                 number_out = hfinfo_char_value_format_display(BASE_HEX, number_buf, number);
5419
5420                                                         offset_r += protoo_strlcpy(result+offset_r, number_out, size-offset_r);
5421
5422                                                 } else {
5423                                                         number_out = hfinfo_char_value_format(hfinfo, number_buf, number);
5424
5425                                                         offset_r += protoo_strlcpy(result+offset_r, number_out, size-offset_r);
5426                                                 }
5427
5428                                                 if (hf_str_val && (hfinfo->display & FIELD_DISPLAY_E_MASK) == BASE_NONE) {
5429                                                         g_snprintf(expr+offset_e, size-offset_e, "\"%s\"", hf_str_val);
5430                                                 } else {
5431                                                         number_out = hfinfo_char_value_format(hfinfo, number_buf, number);
5432
5433                                                         g_strlcpy(expr+offset_e, number_out, size-offset_e);
5434                                                 }
5435
5436                                                 offset_e = (int)strlen(expr);
5437                                                 break;
5438
5439                                                 /* XXX - make these just FT_NUMBER? */
5440                                         case FT_INT8:
5441                                         case FT_INT16:
5442                                         case FT_INT24:
5443                                         case FT_INT32:
5444                                         case FT_UINT8:
5445                                         case FT_UINT16:
5446                                         case FT_UINT24:
5447                                         case FT_UINT32:
5448                                         case FT_FRAMENUM:
5449                                                 hf_str_val = NULL;
5450                                                 number = IS_FT_INT(hfinfo->type) ?
5451                                                         (guint32) fvalue_get_sinteger(&finfo->value) :
5452                                                         fvalue_get_uinteger(&finfo->value);
5453
5454                                                 if ((hfinfo->display & FIELD_DISPLAY_E_MASK) == BASE_CUSTOM) {
5455                                                         gchar tmp[ITEM_LABEL_LENGTH];
5456                                                         custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hfinfo->strings;
5457
5458                                                         DISSECTOR_ASSERT(fmtfunc);
5459                                                         fmtfunc(tmp, number);
5460
5461                                                         offset_r += protoo_strlcpy(result+offset_r, tmp, size-offset_r);
5462
5463                                                 } else if (hfinfo->strings && hfinfo->type != FT_FRAMENUM) {
5464                                                         if (hfinfo->display & BASE_UNIT_STRING) {
5465                                                                 number_out = hfinfo_numeric_value_format(hfinfo, number_buf, number);
5466                                                                 offset_r += protoo_strlcpy(result+offset_r, number_out, size-offset_r);
5467                                                                 hf_str_val = hf_try_val_to_str(number, hfinfo);
5468                                                                 offset_r += protoo_strlcpy(result+offset_r, hf_str_val, size-offset_r);
5469                                                         } else {
5470                                                                 number_out = hf_str_val = hf_try_val_to_str(number, hfinfo);
5471
5472                                                                 if (!number_out)
5473                                                                         number_out = hfinfo_number_value_format_display(hfinfo, hfinfo->display, number_buf, number);
5474
5475                                                                 offset_r += protoo_strlcpy(result+offset_r, number_out, size-offset_r);
5476                                                         }
5477                                                 } else {
5478                                                         number_out = hfinfo_number_value_format(hfinfo, number_buf, number);
5479
5480                                                         offset_r += protoo_strlcpy(result+offset_r, number_out, size-offset_r);
5481                                                 }
5482
5483                                                 if (hf_str_val && (hfinfo->display & FIELD_DISPLAY_E_MASK) == BASE_NONE) {
5484                                                         g_snprintf(expr+offset_e, size-offset_e, "\"%s\"", hf_str_val);
5485                                                 } else {
5486                                                         number_out = hfinfo_numeric_value_format(hfinfo, number_buf, number);
5487
5488                                                         g_strlcpy(expr+offset_e, number_out, size-offset_e);
5489                                                 }
5490
5491                                                 offset_e = (int)strlen(expr);
5492                                                 break;
5493
5494                                         case FT_INT40:
5495                                         case FT_INT48:
5496                                         case FT_INT56:
5497                                         case FT_INT64:
5498                                         case FT_UINT40:
5499                                         case FT_UINT48:
5500                                         case FT_UINT56:
5501                                         case FT_UINT64:
5502                                                 hf_str_val = NULL;
5503                                                 number64 = IS_FT_INT(hfinfo->type) ?
5504                                                         (guint64) fvalue_get_sinteger64(&finfo->value) :
5505                                                         fvalue_get_uinteger64(&finfo->value);
5506
5507                                                 if ((hfinfo->display & FIELD_DISPLAY_E_MASK) == BASE_CUSTOM) {
5508                                                         gchar tmp[ITEM_LABEL_LENGTH];
5509                                                         custom_fmt_func_64_t fmtfunc64 = (custom_fmt_func_64_t)hfinfo->strings;
5510
5511                                                         DISSECTOR_ASSERT(fmtfunc64);
5512                                                         fmtfunc64(tmp, number64);
5513                                                         offset_r += protoo_strlcpy(result+offset_r, tmp, size-offset_r);
5514                                                 } else if (hfinfo->strings) {
5515                                                         number_out = hf_str_val = hf_try_val64_to_str(number64, hfinfo);
5516
5517                                                         if (!number_out)
5518                                                                 number_out = hfinfo_number_value_format_display64(hfinfo, hfinfo->display, number_buf, number64);
5519
5520                                                         offset_r += protoo_strlcpy(result+offset_r, number_out, size-offset_r);
5521
5522                                                 } else {
5523                                                         number_out = hfinfo_number_value_format64(hfinfo, number_buf, number64);
5524
5525                                                         offset_r += protoo_strlcpy(result+offset_r, number_out, size-offset_r);
5526                                                 }
5527
5528                                                 if (hf_str_val && (hfinfo->display & FIELD_DISPLAY_E_MASK) == BASE_NONE) {
5529                                                         g_snprintf(expr+offset_e, size-offset_e, "\"%s\"", hf_str_val);
5530                                                 } else {
5531                                                         number_out = hfinfo_numeric_value_format64(hfinfo, number_buf, number64);
5532
5533                                                         g_strlcpy(expr+offset_e, number_out, size-offset_e);
5534                                                 }
5535
5536                                                 offset_e = (int)strlen(expr);
5537                                                 break;
5538
5539                                         case FT_EUI64:
5540                                                 str = eui64_to_str(NULL, fvalue_get_uinteger64(&finfo->value));
5541                                                 offset_r += protoo_strlcpy(result+offset_r, str, size-offset_r);
5542                                                 wmem_free(NULL, str);
5543                                                 break;
5544
5545                                         case FT_IPv4:
5546                                                 ipv4 = (ipv4_addr_and_mask *)fvalue_get(&finfo->value);
5547                                                 n_addr = ipv4_get_net_order_addr(ipv4);
5548                                                 set_address (&addr, AT_IPv4, 4, &n_addr);
5549                                                 address_to_str_buf(&addr, result+offset_r, size-offset_r);
5550                                                 offset_r = (int)strlen(result);
5551                                                 break;
5552
5553                                         case FT_IPv6:
5554                                                 ipv6 = (struct e_in6_addr *)fvalue_get(&finfo->value);
5555                                                 set_address (&addr, AT_IPv6, sizeof(struct e_in6_addr), ipv6);
5556                                                 address_to_str_buf(&addr, result+offset_r, size-offset_r);
5557                                                 offset_r = (int)strlen(result);
5558                                                 break;
5559
5560                                         case FT_FCWWN:
5561                                                 set_address (&addr, AT_FCWWN, FCWWN_ADDR_LEN, fvalue_get(&finfo->value));
5562                                                 address_to_str_buf(&addr, result+offset_r, size-offset_r);
5563                                                 offset_r = (int)strlen(result);
5564                                                 break;
5565
5566                                         case FT_ETHER:
5567                                                 set_address (&addr, AT_ETHER, FT_ETHER_LEN, fvalue_get(&finfo->value));
5568                                                 address_to_str_buf(&addr, result+offset_r, size-offset_r);
5569                                                 offset_r = (int)strlen(result);
5570                                                 break;
5571
5572                                         case FT_GUID:
5573                                                 str = guid_to_str(NULL, (e_guid_t *)fvalue_get(&finfo->value));
5574                                                 offset_r += protoo_strlcpy(result+offset_r, str, size-offset_r);
5575                                                 wmem_free(NULL, str);
5576                                                 break;
5577
5578                                         case FT_REL_OID:
5579                                                 bytes = (guint8 *)fvalue_get(&finfo->value);
5580                                                 str = rel_oid_resolved_from_encoded(NULL, bytes, fvalue_length(&finfo->value));
5581                                                 offset_r += protoo_strlcpy(result+offset_r, str, size-offset_r);
5582                                                 wmem_free(NULL, str);
5583
5584                                                 str = rel_oid_encoded2string(NULL, bytes, fvalue_length(&finfo->value));
5585                                                 offset_e += protoo_strlcpy(expr+offset_e, str, size-offset_e);
5586                                                 wmem_free(NULL, str);
5587                                                 break;
5588
5589                                         case FT_OID:
5590                                                 bytes = (guint8 *)fvalue_get(&finfo->value);
5591                                                 str = oid_resolved_from_encoded(NULL, bytes, fvalue_length(&finfo->value));
5592                                                 offset_r += protoo_strlcpy(result+offset_r, str, size-offset_r);
5593                                                 wmem_free(NULL, str);
5594
5595                                                 str = oid_encoded2string(NULL, bytes, fvalue_length(&finfo->value));
5596                                                 offset_e += protoo_strlcpy(expr+offset_e, str, size-offset_e);
5597                                                 wmem_free(NULL, str);
5598                                                 break;
5599
5600                                         case FT_SYSTEM_ID:
5601                                                 bytes = (guint8 *)fvalue_get(&finfo->value);
5602                                                 str = print_system_id(NULL, bytes, fvalue_length(&finfo->value));
5603                                                 offset_r += protoo_strlcpy(result+offset_r, str, size-offset_r);
5604                                                 offset_e += protoo_strlcpy(expr+offset_e, str, size-offset_e);
5605                                                 wmem_free(NULL, str);
5606                                                 break;
5607
5608                                         case FT_FLOAT:
5609                                                 if (hfinfo->display & BASE_UNIT_STRING) {
5610                                                         double d_value = fvalue_get_floating(&finfo->value);
5611                                                         g_snprintf(result+offset_r, size-offset_r,
5612                                                                         "%." G_STRINGIFY(FLT_DIG) "g%s", d_value,
5613                                                                         unit_name_string_get_double(d_value, (unit_name_string*)hfinfo->strings));
5614                                                 } else {
5615                                                         g_snprintf(result+offset_r, size-offset_r,
5616                                                                         "%." G_STRINGIFY(FLT_DIG) "g", fvalue_get_floating(&finfo->value));
5617                                                 }
5618                                                 offset_r = (int)strlen(result);
5619                                                 break;
5620
5621                                         case FT_DOUBLE:
5622                                                 if (hfinfo->display & BASE_UNIT_STRING) {
5623                                                         double d_value = fvalue_get_floating(&finfo->value);
5624                                                         g_snprintf(result+offset_r, size-offset_r,
5625                                                                         "%." G_STRINGIFY(DBL_DIG) "g%s", d_value,
5626                                                                         unit_name_string_get_double(d_value, (unit_name_string*)hfinfo->strings));
5627                                                 } else {
5628                                                         g_snprintf(result+offset_r, size-offset_r,
5629                                                                         "%." G_STRINGIFY(DBL_DIG) "g", fvalue_get_floating(&finfo->value));
5630                                                 }
5631                                                 offset_r = (int)strlen(result);
5632                                                 break;
5633
5634                                         case FT_STRING:
5635                                         case FT_STRINGZ:
5636                                         case FT_UINT_STRING:
5637                                         case FT_STRINGZPAD:
5638                                                 bytes = (guint8 *)fvalue_get(&finfo->value);
5639                                                 str = hfinfo_format_text(hfinfo, bytes);
5640                                                 offset_r += protoo_strlcpy(result+offset_r,
5641                                                                 str, size-offset_r);
5642                                                 wmem_free(NULL, str);
5643                                                 break;
5644
5645                                         case FT_IEEE_11073_SFLOAT:
5646                                                 str = fvalue_to_string_repr(NULL, &finfo->value, FTREPR_DISPLAY, hfinfo->display);
5647                                                 g_snprintf(result+offset_r, size-offset_r,
5648                                                                                 "%s: %s",
5649                                                                                 hfinfo->name, str);
5650                                                 wmem_free(NULL, str);
5651                                                 offset_r = (int)strlen(result);
5652                                                 break;
5653
5654                                         case FT_IEEE_11073_FLOAT:
5655                                                 str = fvalue_to_string_repr(NULL, &finfo->value, FTREPR_DISPLAY, hfinfo->display);
5656                                                 g_snprintf(result+offset_r, size-offset_r,
5657                                                                                 "%s: %s",
5658                                                                                 hfinfo->name, str);
5659                                                 offset_r = (int)strlen(result);
5660                                                 wmem_free(NULL, str);
5661                                                 break;
5662
5663                                         case FT_IPXNET: /*XXX really No column custom ?*/
5664                                         case FT_PCRE:
5665                                         default:
5666                                                 g_error("hfinfo->type %d (%s) not handled\n",
5667                                                                 hfinfo->type,
5668                                                                 ftype_name(hfinfo->type));
5669                                                 DISSECTOR_ASSERT_NOT_REACHED();
5670                                                 break;
5671                                 }
5672                                 i++;
5673                         }
5674
5675                         switch (hfinfo->type) {
5676
5677                                 case FT_BOOLEAN:
5678                                 case FT_CHAR:
5679                                 case FT_UINT8:
5680                                 case FT_UINT16:
5681                                 case FT_UINT24:
5682                                 case FT_UINT32:
5683                                 case FT_UINT40:
5684                                 case FT_UINT48:
5685                                 case FT_UINT56:
5686                                 case FT_UINT64:
5687                                 case FT_FRAMENUM:
5688                                 case FT_INT8:
5689                                 case FT_INT16:
5690                                 case FT_INT24:
5691                                 case FT_INT32:
5692                                 case FT_INT40:
5693                                 case FT_INT48:
5694                                 case FT_INT56:
5695                                 case FT_INT64:
5696                                 case FT_OID:
5697                                 case FT_REL_OID:
5698                                 case FT_SYSTEM_ID:
5699                                         /* for these types, "expr" is filled in the loop above */
5700                                         break;
5701
5702                                 default:
5703                                         /* for all others, just copy "result" to "expr" */
5704                                         g_strlcpy(expr, result, size);
5705                                         break;
5706                         }
5707
5708                         if (!abbrev) {
5709                                 /* Store abbrev for return value */
5710                                 abbrev = hfinfo->abbrev;
5711                         }
5712
5713                         if (occurrence == 0) {
5714                                 /* Fetch next hfinfo with same name (abbrev) */
5715                                 hfinfo = hfinfo_same_name_get_prev(hfinfo);
5716                         } else {
5717                                 hfinfo = NULL;
5718                         }
5719                 }
5720         }
5721
5722         return abbrev ? abbrev : "";
5723 }
5724
5725
5726 /* Set text of proto_item after having already been created. */
5727 void
5728 proto_item_set_text(proto_item *pi, const char *format, ...)
5729 {
5730         field_info *fi = NULL;
5731         va_list     ap;
5732
5733         TRY_TO_FAKE_THIS_REPR_VOID(pi);
5734
5735         fi = PITEM_FINFO(pi);
5736         if (fi == NULL)
5737                 return;
5738
5739         if (fi->rep) {
5740                 ITEM_LABEL_FREE(PNODE_POOL(pi), fi->rep);
5741                 fi->rep = NULL;
5742         }
5743
5744         va_start(ap, format);
5745         proto_tree_set_representation(pi, format, ap);
5746         va_end(ap);
5747 }
5748
5749 /* Append to text of proto_item after having already been created. */
5750 void
5751 proto_item_append_text(proto_item *pi, const char *format, ...)
5752 {
5753         field_info *fi = NULL;
5754         size_t      curlen;
5755         va_list     ap;
5756
5757         TRY_TO_FAKE_THIS_REPR_VOID(pi);
5758
5759         fi = PITEM_FINFO(pi);
5760         if (fi == NULL) {
5761                 return;
5762         }
5763
5764         if (!PROTO_ITEM_IS_HIDDEN(pi)) {
5765                 /*
5766                  * If we don't already have a representation,
5767                  * generate the default representation.
5768                  */
5769                 if (fi->rep == NULL) {
5770                         ITEM_LABEL_NEW(PNODE_POOL(pi), fi->rep);
5771                         proto_item_fill_label(fi, fi->rep->representation);
5772                 }
5773
5774                 curlen = strlen(fi->rep->representation);
5775                 if (ITEM_LABEL_LENGTH > curlen) {
5776                         va_start(ap, format);
5777                         g_vsnprintf(fi->rep->representation + curlen,
5778                                 ITEM_LABEL_LENGTH - (gulong) curlen, format, ap);
5779                         va_end(ap);
5780                 }
5781         }
5782 }
5783
5784 /* Prepend to text of proto_item after having already been created. */
5785 void
5786 proto_item_prepend_text(proto_item *pi, const char *format, ...)
5787 {
5788         field_info *fi = NULL;
5789         char        representation[ITEM_LABEL_LENGTH];
5790         va_list     ap;
5791
5792         TRY_TO_FAKE_THIS_REPR_VOID(pi);
5793
5794         fi = PITEM_FINFO(pi);
5795         if (fi == NULL) {
5796                 return;
5797         }
5798
5799         if (!PROTO_ITEM_IS_HIDDEN(pi)) {
5800                 /*
5801                  * If we don't already have a representation,
5802                  * generate the default representation.
5803                  */
5804                 if (fi->rep == NULL) {
5805                         ITEM_LABEL_NEW(PNODE_POOL(pi), fi->rep);
5806                         proto_item_fill_label(fi, representation);
5807                 } else
5808                         g_strlcpy(representation, fi->rep->representation, ITEM_LABEL_LENGTH);
5809
5810                 va_start(ap, format);
5811                 g_vsnprintf(fi->rep->representation,
5812                         ITEM_LABEL_LENGTH, format, ap);
5813                 va_end(ap);
5814                 g_strlcat(fi->rep->representation, representation, ITEM_LABEL_LENGTH);
5815         }
5816 }
5817
5818 static void
5819 finfo_set_len(field_info *fi, const gint length)
5820 {
5821         DISSECTOR_ASSERT(length >= 0);
5822         fi->length = length;
5823
5824         /*
5825          * You cannot just make the "len" field of a GByteArray
5826          * larger, if there's no data to back that length;
5827          * you can only make it smaller.
5828          */
5829         if (fi->value.ftype->ftype == FT_BYTES && length <= (gint)fi->value.value.bytes->len)
5830                 fi->value.value.bytes->len = length;
5831 }
5832
5833 void
5834 proto_item_set_len(proto_item *pi, const gint length)
5835 {
5836         field_info *fi;
5837
5838         TRY_TO_FAKE_THIS_REPR_VOID(pi);
5839
5840         fi = PITEM_FINFO(pi);
5841         if (fi == NULL)
5842                 return;
5843
5844         finfo_set_len(fi, length);
5845 }
5846
5847 /*
5848  * Sets the length of the item based on its start and on the specified
5849  * offset, which is the offset past the end of the item; as the start
5850  * in the item is relative to the beginning of the data source tvbuff,
5851  * we need to pass in a tvbuff - the end offset is relative to the beginning
5852  * of that tvbuff.
5853  */
5854 void
5855 proto_item_set_end(proto_item *pi, tvbuff_t *tvb, gint end)
5856 {
5857         field_info *fi;
5858         gint length;
5859
5860         TRY_TO_FAKE_THIS_REPR_VOID(pi);
5861
5862         fi = PITEM_FINFO(pi);
5863         if (fi == NULL)
5864                 return;
5865
5866         end += tvb_raw_offset(tvb);
5867         DISSECTOR_ASSERT(end >= fi->start);
5868         length = end - fi->start;
5869
5870         finfo_set_len(fi, length);
5871 }
5872
5873 int
5874 proto_item_get_len(const proto_item *pi)
5875 {
5876         field_info *fi = PITEM_FINFO(pi);
5877         return fi ? fi->length : -1;
5878 }
5879
5880 proto_tree *
5881 proto_tree_create_root(packet_info *pinfo)
5882 {
5883         proto_node *pnode;
5884
5885         /* Initialize the proto_node */
5886         pnode = g_slice_new(proto_tree);
5887         PROTO_NODE_INIT(pnode);
5888         pnode->parent = NULL;
5889         PNODE_FINFO(pnode) = NULL;
5890         pnode->tree_data = g_slice_new(tree_data_t);
5891
5892         /* Make sure we can access pinfo everywhere */
5893         pnode->tree_data->pinfo = pinfo;
5894
5895         /* Don't initialize the tree_data_t. Wait until we know we need it */
5896         pnode->tree_data->interesting_hfids = NULL;
5897
5898         /* Set the default to FALSE so it's easier to
5899          * find errors; if we expect to see the protocol tree
5900          * but for some reason the default 'visible' is not
5901          * changed, then we'll find out very quickly. */
5902         pnode->tree_data->visible = FALSE;
5903
5904         /* Make sure that we fake protocols (if possible) */
5905         pnode->tree_data->fake_protocols = TRUE;
5906
5907         /* Keep track of the number of children */
5908         pnode->tree_data->count = 0;
5909
5910         return (proto_tree *)pnode;
5911 }
5912
5913
5914 /* "prime" a proto_tree with a single hfid that a dfilter
5915  * is interested in. */
5916 void
5917 proto_tree_prime_with_hfid(proto_tree *tree _U_, const gint hfid)
5918 {
5919         header_field_info *hfinfo;
5920
5921         PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
5922         /* this field is referenced by a filter so increase the refcount.
5923            also increase the refcount for the parent, i.e the protocol.
5924         */
5925         hfinfo->ref_type = HF_REF_TYPE_DIRECT;
5926         /* only increase the refcount if there is a parent.
5927            if this is a protocol and not a field then parent will be -1
5928            and there is no parent to add any refcounting for.
5929         */
5930         if (hfinfo->parent != -1) {
5931                 header_field_info *parent_hfinfo;
5932                 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
5933
5934                 /* Mark parent as indirectly referenced unless it is already directly
5935                  * referenced, i.e. the user has specified the parent in a filter.
5936                  */
5937                 if (parent_hfinfo->ref_type != HF_REF_TYPE_DIRECT)
5938                         parent_hfinfo->ref_type = HF_REF_TYPE_INDIRECT;
5939         }
5940 }
5941
5942 proto_tree *
5943 proto_item_add_subtree(proto_item *pi,  const gint idx) {
5944         field_info *fi;
5945
5946         if (!pi)
5947                 return NULL;
5948
5949         DISSECTOR_ASSERT(idx >= 0 && idx < num_tree_types);
5950
5951         fi = PITEM_FINFO(pi);
5952         if (!fi)
5953                 return (proto_tree *)pi;
5954
5955         fi->tree_type = idx;
5956
5957         return (proto_tree *)pi;
5958 }
5959
5960 proto_tree *
5961 proto_item_get_subtree(proto_item *pi) {
5962         field_info *fi;
5963
5964         if (!pi)
5965                 return NULL;
5966         fi = PITEM_FINFO(pi);
5967         if ( (!fi) || (fi->tree_type == -1) )
5968                 return NULL;
5969         return (proto_tree *)pi;
5970 }
5971
5972 proto_item *
5973 proto_item_get_parent(const proto_item *ti) {
5974         if (!ti)
5975                 return NULL;
5976         return ti->parent;
5977 }
5978
5979 proto_item *
5980 proto_item_get_parent_nth(proto_item *ti, int gen) {
5981         if (!ti)
5982                 return NULL;
5983         while (gen--) {
5984                 ti = ti->parent;
5985                 if (!ti)
5986                         return NULL;
5987         }
5988         return ti;
5989 }
5990
5991
5992 proto_item *
5993 proto_tree_get_parent(proto_tree *tree) {
5994         if (!tree)
5995                 return NULL;
5996         return (proto_item *)tree;
5997 }
5998
5999 proto_tree *
6000 proto_tree_get_parent_tree(proto_tree *tree) {
6001         if (!tree)
6002                 return NULL;
6003
6004         /* we're the root tree, there's no parent
6005            return ourselves so the caller has at least a tree to attach to */
6006         if (!tree->parent)
6007                 return tree;
6008
6009         return (proto_tree *)tree->parent;
6010 }
6011
6012 proto_tree *
6013 proto_tree_get_root(proto_tree *tree) {
6014         if (!tree)
6015                 return NULL;
6016         while (tree->parent) {
6017                 tree = tree->parent;
6018         }
6019         return tree;
6020 }
6021
6022 void
6023 proto_tree_move_item(proto_tree *tree, proto_item *fixed_item,
6024                      proto_item *item_to_move)
6025 {
6026
6027         /* Revert part of: https://code.wireshark.org/review/gitweb?p=wireshark.git;a=commit;h=00c05ed3fdfa9287422e6e1fc9bd6ea8b31ca4ee
6028          * See https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=5500
6029          */
6030         /* This function doesn't generate any values. It only reorganizes the prococol tree
6031          * so we can bail out immediately if it isn't visible. */
6032         if (!tree || !PTREE_DATA(tree)->visible)
6033                 return;
6034
6035         DISSECTOR_ASSERT(item_to_move->parent == tree);
6036         DISSECTOR_ASSERT(fixed_item->parent == tree);
6037
6038         /*** cut item_to_move out ***/
6039
6040         /* is item_to_move the first? */
6041         if (tree->first_child == item_to_move) {
6042                 /* simply change first child to next */
6043                 tree->first_child = item_to_move->next;
6044
6045                 DISSECTOR_ASSERT(tree->last_child != item_to_move);
6046         } else {
6047                 proto_item *curr_item;
6048                 /* find previous and change it's next */
6049                 for(curr_item = tree->first_child; curr_item != NULL; curr_item = curr_item->next) {
6050                         if (curr_item->next == item_to_move) {
6051                                 break;
6052                         }
6053                 }
6054
6055                 DISSECTOR_ASSERT(curr_item);
6056
6057                 curr_item->next = item_to_move->next;
6058
6059                 /* fix last_child if required */
6060                 if (tree->last_child == item_to_move) {
6061                         tree->last_child = curr_item;
6062                 }
6063         }
6064
6065         /*** insert to_move after fixed ***/
6066         item_to_move->next = fixed_item->next;
6067         fixed_item->next = item_to_move;
6068         if (tree->last_child == fixed_item) {
6069                 tree->last_child = item_to_move;
6070         }
6071 }
6072
6073 void
6074 proto_tree_set_appendix(proto_tree *tree, tvbuff_t *tvb, gint start,
6075                         const gint length)
6076 {
6077         field_info *fi;
6078
6079         if (tree == NULL)
6080                 return;
6081
6082         fi = PTREE_FINFO(tree);
6083         if (fi == NULL)
6084                 return;
6085
6086         start += tvb_raw_offset(tvb);
6087         DISSECTOR_ASSERT(start >= 0);
6088         DISSECTOR_ASSERT(length >= 0);
6089
6090         fi->appendix_start = start;
6091         fi->appendix_length = length;
6092 }
6093
6094 int
6095 proto_register_protocol(const char *name, const char *short_name,
6096                         const char *filter_name)
6097 {
6098         protocol_t *protocol;
6099         const protocol_t *existing_protocol = NULL;
6100         header_field_info *hfinfo;
6101         int proto_id;
6102         const char *existing_name;
6103         gint *key;
6104         guint i;
6105         gchar c;
6106         gboolean found_invalid;
6107
6108         /*
6109          * Make sure there's not already a protocol with any of those
6110          * names.  Crash if there is, as that's an error in the code
6111          * or an inappropriate plugin.
6112          * This situation has to be fixed to not register more than one
6113          * protocol with the same name.
6114          *
6115          * This is done by reducing the number of strcmp (and alike) calls
6116          * as much as possible, as this significally slows down startup time.
6117          *
6118          * Drawback: As a hash value is used to reduce insert time,
6119          * this might lead to a hash collision.
6120          * However, although we have somewhat over 1000 protocols, we're using
6121          * a 32 bit int so this is very, very unlikely.
6122          */
6123
6124         key  = (gint *)g_malloc (sizeof(gint));
6125         *key = wrs_str_hash(name);
6126
6127         existing_name = (const char *)g_hash_table_lookup(proto_names, key);
6128         if (existing_name != NULL) {
6129                 /* g_error will terminate the program */
6130                 g_error("Duplicate protocol name \"%s\"!"
6131                         " This might be caused by an inappropriate plugin or a development error.", name);
6132         }
6133         g_hash_table_insert(proto_names, key, (gpointer)name);
6134
6135         existing_protocol = (const protocol_t *)g_hash_table_lookup(proto_short_names, short_name);
6136         if (existing_protocol != NULL) {
6137                 g_error("Duplicate protocol short_name \"%s\"!"
6138                         " This might be caused by an inappropriate plugin or a development error.", short_name);
6139         }
6140
6141         found_invalid = FALSE;
6142         for (i = 0; filter_name[i]; i++) {
6143                 c = filter_name[i];
6144                 if (!(g_ascii_islower(c) || g_ascii_isdigit(c) || c == '-' || c == '_' || c == '.')) {
6145                         found_invalid = TRUE;
6146                 }
6147         }
6148         if (found_invalid) {
6149                 g_error("Protocol filter name \"%s\" has one or more invalid characters."
6150                         " Allowed are lower characters, digits, '-', '_' and '.'."
6151                         " This might be caused by an inappropriate plugin or a development error.", filter_name);
6152         }
6153         existing_protocol = (const protocol_t *)g_hash_table_lookup(proto_filter_names, filter_name);
6154         if (existing_protocol != NULL) {
6155                 g_error("Duplicate protocol filter_name \"%s\"!"
6156                         " This might be caused by an inappropriate plugin or a development error.", filter_name);
6157         }
6158
6159         /* Add this protocol to the list of known protocols; the list
6160            is sorted by protocol short name. */
6161         protocol = g_new(protocol_t, 1);
6162         protocol->name = name;
6163         protocol->short_name = short_name;
6164         protocol->filter_name = filter_name;
6165         /*protocol->fields = g_ptr_array_new();*/
6166         /* Delegate until actually needed and use g_ptr_array_sized_new*/
6167         protocol->fields = NULL;
6168         protocol->is_enabled = TRUE; /* protocol is enabled by default */
6169         protocol->enabled_by_default = TRUE; /* see previous comment */
6170         protocol->can_toggle = TRUE;
6171         protocol->parent_proto_id = -1;
6172         protocol->heur_list = NULL;
6173         /* list will be sorted later by name, when all protocols completed registering */
6174         protocols = g_list_prepend(protocols, protocol);
6175         g_hash_table_insert(proto_filter_names, (gpointer)filter_name, protocol);
6176         g_hash_table_insert(proto_short_names, (gpointer)short_name, protocol);
6177
6178         /* Here we allocate a new header_field_info struct */
6179         hfinfo = g_slice_new(header_field_info);
6180         hfinfo->name = name;
6181         hfinfo->abbrev = filter_name;
6182         hfinfo->type = FT_PROTOCOL;
6183         hfinfo->display = BASE_NONE;
6184         hfinfo->strings = protocol;
6185         hfinfo->bitmask = 0;
6186         hfinfo->ref_type = HF_REF_TYPE_NONE;
6187         hfinfo->blurb = NULL;
6188         hfinfo->parent = -1; /* this field differentiates protos and fields */
6189
6190         proto_id = proto_register_field_init(hfinfo, hfinfo->parent);
6191         protocol->proto_id = proto_id;
6192         return proto_id;
6193 }
6194
6195 int
6196 proto_register_protocol_in_name_only(const char *name, const char *short_name, const char *filter_name, int parent_proto, enum ftenum field_type)
6197 {
6198         protocol_t *protocol;
6199         header_field_info *hfinfo;
6200         guint i;
6201         gchar c;
6202         gboolean found_invalid = FALSE;
6203
6204         /*
6205          * Helper protocols don't need the strict rules as a "regular" protocol
6206          * Just register it in a list and make a hf_ field from it
6207          */
6208         if ((field_type != FT_PROTOCOL) && (field_type != FT_BYTES)) {
6209                 g_error("Pino \"%s\" must be of type FT_PROTOCOL or FT_BYTES.", name);
6210         }
6211
6212         if (parent_proto < 0) {
6213                 g_error("Must have a valid parent protocol for helper protocol \"%s\"!"
6214                         " This might be caused by an inappropriate plugin or a development error.", name);
6215         }
6216
6217         for (i = 0; filter_name[i]; i++) {
6218                 c = filter_name[i];
6219                 if (!(g_ascii_islower(c) || g_ascii_isdigit(c) || c == '-' || c == '_' || c == '.')) {
6220                         found_invalid = TRUE;
6221                 }
6222         }
6223         if (found_invalid) {
6224                 g_error("Protocol filter name \"%s\" has one or more invalid characters."
6225                         " Allowed are lower characters, digits, '-', '_' and '.'."
6226                         " This might be caused by an inappropriate plugin or a development error.", filter_name);
6227         }
6228
6229         /* Add this protocol to the list of helper protocols (just so it can be properly freed) */
6230         protocol = g_new(protocol_t, 1);
6231         protocol->name = name;
6232         protocol->short_name = short_name;
6233         protocol->filter_name = filter_name;
6234         protocol->fields = NULL;
6235
6236         /* Enabling and toggling is really determined by parent protocol,
6237            but provide default values here */
6238         protocol->is_enabled = TRUE;
6239         protocol->enabled_by_default = TRUE;
6240         protocol->can_toggle = TRUE;
6241
6242         protocol->parent_proto_id = parent_proto;
6243         protocol->heur_list = NULL;
6244         /* list will be sorted later by name, when all protocols completed registering */
6245         pino_protocols = g_list_prepend(pino_protocols, protocol);
6246
6247         /* Here we allocate a new header_field_info struct */
6248         hfinfo = g_slice_new(header_field_info);
6249         hfinfo->name = name;
6250         hfinfo->abbrev = filter_name;
6251         hfinfo->type = field_type;
6252         hfinfo->display = BASE_NONE;
6253         if (field_type == FT_BYTES) {
6254                 hfinfo->display |= (BASE_NO_DISPLAY_VALUE|BASE_PROTOCOL_INFO);
6255         }
6256         hfinfo->strings = protocol;
6257         hfinfo->bitmask = 0;
6258         hfinfo->ref_type = HF_REF_TYPE_NONE;
6259         hfinfo->blurb = NULL;
6260         hfinfo->parent = -1; /* this field differentiates protos and fields */
6261
6262         protocol->proto_id = proto_register_field_init(hfinfo, hfinfo->parent);
6263         return protocol->proto_id;
6264 }
6265
6266 gboolean
6267 proto_deregister_protocol(const char *short_name)
6268 {
6269         protocol_t *protocol;
6270         header_field_info *hfinfo;
6271         int proto_id;
6272         gint key;
6273         guint i;
6274
6275         proto_id = proto_get_id_by_short_name(short_name);
6276         protocol = find_protocol_by_id(proto_id);
6277         if (protocol == NULL)
6278                 return FALSE;
6279
6280         key = wrs_str_hash(protocol->name);
6281         g_hash_table_remove(proto_names, &key);
6282
6283         g_hash_table_remove(proto_short_names, (gpointer)short_name);
6284         g_hash_table_remove(proto_filter_names, (gpointer)protocol->filter_name);
6285
6286         if (protocol->fields) {
6287                 for (i = 0; i < protocol->fields->len; i++) {
6288                         hfinfo = (header_field_info *)g_ptr_array_index(protocol->fields, i);
6289                         hfinfo_remove_from_gpa_name_map(hfinfo);
6290                         expert_deregister_expertinfo(hfinfo->abbrev);
6291                         g_ptr_array_add(deregistered_fields, gpa_hfinfo.hfi[hfinfo->id]);
6292                 }
6293                 g_ptr_array_free(protocol->fields, TRUE);
6294                 protocol->fields = NULL;
6295         }
6296
6297         /* Remove this protocol from the list of known protocols */
6298         protocols = g_list_remove(protocols, protocol);
6299
6300         g_ptr_array_add(deregistered_fields, gpa_hfinfo.hfi[proto_id]);
6301         g_hash_table_steal(gpa_name_map, protocol->filter_name);
6302
6303         g_free(last_field_name);
6304         last_field_name = NULL;
6305
6306         return TRUE;
6307 }
6308
6309 /*
6310  * Routines to use to iterate over the protocols.
6311  * The argument passed to the iterator routines is an opaque cookie to
6312  * their callers; it's the GList pointer for the current element in
6313  * the list.
6314  * The ID of the protocol is returned, or -1 if there is no protocol.
6315  */
6316 int
6317 proto_get_first_protocol(void **cookie)
6318 {
6319         protocol_t *protocol;
6320
6321         if (protocols == NULL)
6322                 return -1;
6323         *cookie = protocols;
6324         protocol = (protocol_t *)protocols->data;
6325         return protocol->proto_id;
6326 }
6327
6328 int
6329 proto_get_data_protocol(void *cookie)
6330 {
6331         GList *list_item = (GList *)cookie;
6332
6333         protocol_t *protocol = (protocol_t *)list_item->data;
6334         return protocol->proto_id;
6335 }
6336
6337 int
6338 proto_get_next_protocol(void **cookie)
6339 {
6340         GList      *list_item = (GList *)*cookie;
6341         protocol_t *protocol;
6342
6343         list_item = g_list_next(list_item);
6344         if (list_item == NULL)
6345                 return -1;
6346         *cookie = list_item;
6347         protocol = (protocol_t *)list_item->data;
6348         return protocol->proto_id;
6349 }
6350
6351 /* XXX: Unfortunately certain functions in proto_hier_tree_model.c
6352         assume that the cookie stored by
6353         proto_get_(first|next)_protocol_field() will never have a
6354         value of NULL. So, to preserve this semantic, the cookie value
6355         below is adjusted so that the cookie value stored is 1 + the
6356         current (zero-based) array index.
6357 */
6358 header_field_info *
6359 proto_get_first_protocol_field(const int proto_id, void **cookie)
6360 {
6361         protocol_t *protocol = find_protocol_by_id(proto_id);
6362
6363         if ((protocol == NULL) || (protocol->fields == NULL) || (protocol->fields->len == 0))
6364                 return NULL;
6365
6366         *cookie = GUINT_TO_POINTER(0 + 1);
6367         return (header_field_info *)g_ptr_array_index(protocol->fields, 0);
6368 }
6369
6370 header_field_info *
6371 proto_get_next_protocol_field(const int proto_id, void **cookie)
6372 {
6373         protocol_t *protocol = find_protocol_by_id(proto_id);
6374         guint       i        = GPOINTER_TO_UINT(*cookie) - 1;
6375
6376         i++;
6377
6378         if ((protocol->fields == NULL) || (i >= protocol->fields->len))
6379                 return NULL;
6380
6381         *cookie = GUINT_TO_POINTER(i + 1);
6382         return (header_field_info *)g_ptr_array_index(protocol->fields, i);
6383 }
6384
6385 protocol_t *
6386 find_protocol_by_id(const int proto_id)
6387 {
6388         header_field_info *hfinfo;
6389
6390         if (proto_id < 0)
6391                 return NULL;
6392
6393         PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
6394         if (hfinfo->type != FT_PROTOCOL) {
6395                 DISSECTOR_ASSERT(hfinfo->display & BASE_PROTOCOL_INFO);
6396         }
6397         return (protocol_t *)hfinfo->strings;
6398 }
6399
6400 int
6401 proto_get_id(const protocol_t *protocol)
6402 {
6403         return protocol->proto_id;
6404 }
6405
6406 gboolean
6407 proto_name_already_registered(const gchar *name)
6408 {
6409         gint key;
6410
6411         DISSECTOR_ASSERT_HINT(name, "No name present");
6412
6413         key = wrs_str_hash(name);
6414         if (g_hash_table_lookup(proto_names, &key) != NULL)
6415                 return TRUE;
6416         return FALSE;
6417 }
6418
6419 int
6420 proto_get_id_by_filter_name(const gchar *filter_name)
6421 {
6422         const protocol_t *protocol = NULL;
6423
6424         DISSECTOR_ASSERT_HINT(filter_name, "No filter name present");
6425
6426         protocol = (const protocol_t *)g_hash_table_lookup(proto_filter_names, filter_name);
6427
6428         if (protocol == NULL)
6429                 return -1;
6430         return protocol->proto_id;
6431 }
6432
6433 int
6434 proto_get_id_by_short_name(const gchar *short_name)
6435 {
6436         const protocol_t *protocol = NULL;
6437
6438         DISSECTOR_ASSERT_HINT(short_name, "No short name present");
6439
6440         protocol = (const protocol_t *)g_hash_table_lookup(proto_short_names, short_name);
6441
6442         if (protocol == NULL)
6443                 return -1;
6444         return protocol->proto_id;
6445 }
6446
6447 const char *
6448 proto_get_protocol_name(const int proto_id)
6449 {
6450         protocol_t *protocol;
6451
6452         protocol = find_protocol_by_id(proto_id);
6453
6454         if (protocol == NULL)
6455                 return NULL;
6456         return protocol->name;
6457 }
6458
6459 const char *
6460 proto_get_protocol_short_name(const protocol_t *protocol)
6461 {
6462         if (protocol == NULL)
6463                 return "(none)";
6464         return protocol->short_name;
6465 }
6466
6467 const char *
6468 proto_get_protocol_long_name(const protocol_t *protocol)
6469 {
6470         if (protocol == NULL)
6471                 return "(none)";
6472         return protocol->name;
6473 }
6474
6475 const char *
6476 proto_get_protocol_filter_name(const int proto_id)
6477 {
6478         protocol_t *protocol;
6479
6480         protocol = find_protocol_by_id(proto_id);
6481         if (protocol == NULL)
6482                 return "(none)";
6483         return protocol->filter_name;
6484 }
6485
6486 void proto_add_heuristic_dissector(protocol_t *protocol, const char *short_name)
6487 {
6488         heur_dtbl_entry_t* heuristic_dissector;
6489
6490         if (protocol == NULL)
6491                 return;
6492
6493         heuristic_dissector = find_heur_dissector_by_unique_short_name(short_name);
6494         if (heuristic_dissector != NULL)
6495         {
6496                 protocol->heur_list = g_list_prepend (protocol->heur_list, heuristic_dissector);
6497         }
6498 }
6499
6500 void proto_heuristic_dissector_foreach(const protocol_t *protocol, GFunc func, gpointer user_data)
6501 {
6502         if (protocol == NULL)
6503                 return;
6504
6505         g_list_foreach(protocol->heur_list, func, user_data);
6506 }
6507
6508 void
6509 proto_get_frame_protocols(const wmem_list_t *layers, gboolean *is_ip,
6510                           gboolean *is_tcp, gboolean *is_udp,
6511                           gboolean *is_sctp, gboolean *is_ssl,
6512                           gboolean *is_rtp,
6513                           gboolean *is_lte_rlc)
6514 {
6515         wmem_list_frame_t *protos = wmem_list_head(layers);
6516         int         proto_id;
6517         const char *proto_name;
6518
6519         /* Walk the list of a available protocols in the packet and
6520            find "major" ones. */
6521         /* It might make more sense to assemble and return a bitfield. */
6522         while (protos != NULL)
6523         {
6524                 proto_id = GPOINTER_TO_INT(wmem_list_frame_data(protos));
6525                 proto_name = proto_get_protocol_filter_name(proto_id);
6526
6527                 if (is_ip && ((!strcmp(proto_name, "ip")) ||
6528                               (!strcmp(proto_name, "ipv6")))) {
6529                         *is_ip = TRUE;
6530                 } else if (is_tcp && !strcmp(proto_name, "tcp")) {
6531                         *is_tcp = TRUE;
6532                 } else if (is_udp && !strcmp(proto_name, "udp")) {
6533                         *is_udp = TRUE;
6534                 } else if (is_sctp && !strcmp(proto_name, "sctp")) {
6535                         *is_sctp = TRUE;
6536                 } else if (is_ssl && !strcmp(proto_name, "ssl")) {
6537                         *is_ssl = TRUE;
6538                 } else if (is_rtp && !strcmp(proto_name, "rtp")) {
6539                         *is_rtp = TRUE;
6540                 } else if (is_lte_rlc && !strcmp(proto_name, "rlc-lte")) {
6541                         *is_lte_rlc = TRUE;
6542                 }
6543
6544                 protos = wmem_list_frame_next(protos);
6545         }
6546 }
6547
6548 gboolean
6549 proto_is_frame_protocol(const wmem_list_t *layers, const char* proto_name)
6550 {
6551         wmem_list_frame_t *protos = wmem_list_head(layers);
6552         int         proto_id;
6553         const char *name;
6554
6555         /* Walk the list of a available protocols in the packet and
6556            find "major" ones. */
6557         /* It might make more sense to assemble and return a bitfield. */
6558         while (protos != NULL)
6559         {
6560                 proto_id = GPOINTER_TO_INT(wmem_list_frame_data(protos));
6561                 name = proto_get_protocol_filter_name(proto_id);
6562
6563                 if (!strcmp(name, proto_name))
6564                 {
6565                         return TRUE;
6566                 }
6567
6568                 protos = wmem_list_frame_next(protos);
6569         }
6570
6571         return FALSE;
6572 }
6573
6574 gboolean
6575 proto_is_pino(const protocol_t *protocol)
6576 {
6577         return (protocol->parent_proto_id != -1);
6578 }
6579
6580 gboolean
6581 proto_is_protocol_enabled(const protocol_t *protocol)
6582 {
6583         //parent protocol determines enable/disable for helper dissectors
6584         if (proto_is_pino(protocol))
6585                 return proto_is_protocol_enabled(find_protocol_by_id(protocol->parent_proto_id));
6586
6587         return protocol->is_enabled;
6588 }
6589
6590 gboolean
6591 proto_is_protocol_enabled_by_default(const protocol_t *protocol)
6592 {
6593         //parent protocol determines enable/disable for helper dissectors
6594         if (proto_is_pino(protocol))
6595                 return proto_is_protocol_enabled_by_default(find_protocol_by_id(protocol->parent_proto_id));
6596
6597         return protocol->enabled_by_default;
6598 }
6599
6600 gboolean
6601 proto_can_toggle_protocol(const int proto_id)
6602 {
6603         protocol_t *protocol;
6604
6605         protocol = find_protocol_by_id(proto_id);
6606         //parent protocol determines toggling for helper dissectors
6607         if (proto_is_pino(protocol))
6608                 return proto_can_toggle_protocol(protocol->parent_proto_id);
6609
6610         return protocol->can_toggle;
6611 }
6612
6613 void
6614 proto_disable_by_default(const int proto_id)
6615 {
6616         protocol_t *protocol;
6617
6618         protocol = find_protocol_by_id(proto_id);
6619         DISSECTOR_ASSERT(protocol->can_toggle);
6620         DISSECTOR_ASSERT(proto_is_pino(protocol) == FALSE);
6621         protocol->is_enabled = FALSE;
6622         protocol->enabled_by_default = FALSE;
6623 }
6624
6625 void
6626 proto_set_decoding(const int proto_id, const gboolean enabled)
6627 {
6628         protocol_t *protocol;
6629
6630         protocol = find_protocol_by_id(proto_id);
6631         DISSECTOR_ASSERT(protocol->can_toggle);
6632         DISSECTOR_ASSERT(proto_is_pino(protocol) == FALSE);
6633         protocol->is_enabled = enabled;
6634 }
6635
6636 void
6637 proto_reenable_all(void)
6638 {
6639         protocol_t *protocol;
6640         GList      *list_item = protocols;
6641
6642         if (protocols == NULL)
6643                 return;
6644
6645         while (list_item) {
6646                 protocol = (protocol_t *)list_item->data;
6647                 if (protocol->can_toggle && protocol->enabled_by_default)
6648                         protocol->is_enabled = TRUE;
6649                 list_item = g_list_next(list_item);
6650         }
6651 }
6652
6653 void
6654 proto_set_cant_toggle(const int proto_id)
6655 {
6656         protocol_t *protocol;
6657
6658         protocol = find_protocol_by_id(proto_id);
6659         protocol->can_toggle = FALSE;
6660 }
6661
6662 static int
6663 proto_register_field_common(protocol_t *proto, header_field_info *hfi, const int parent)
6664 {
6665         if (proto != NULL) {
6666                 g_ptr_array_add(proto->fields, hfi);
6667         }
6668
6669         return proto_register_field_init(hfi, parent);
6670 }
6671
6672 /* for use with static arrays only, since we don't allocate our own copies
6673 of the header_field_info struct contained within the hf_register_info struct */
6674 void
6675 proto_register_field_array(const int parent, hf_register_info *hf, const int num_records)
6676 {
6677         hf_register_info *ptr = hf;
6678         protocol_t       *proto;
6679         int               i;
6680
6681         proto = find_protocol_by_id(parent);
6682
6683         if (proto->fields == NULL) {
6684                 proto->fields = g_ptr_array_sized_new(num_records);
6685         }
6686
6687         for (i = 0; i < num_records; i++, ptr++) {
6688                 /*
6689                  * Make sure we haven't registered this yet.
6690                  * Most fields have variables associated with them
6691                  * that are initialized to -1; some have array elements,
6692                  * or possibly uninitialized variables, so we also allow
6693                  * 0 (which is unlikely to be the field ID we get back
6694                  * from "proto_register_field_init()").
6695                  */
6696                 if (*ptr->p_id != -1 && *ptr->p_id != 0) {
6697                         fprintf(stderr,
6698                                 "Duplicate field detected in call to proto_register_field_array: %s is already registered\n",
6699                                 ptr->hfinfo.abbrev);
6700                         return;
6701                 }
6702
6703                 *ptr->p_id = proto_register_field_common(proto, &ptr->hfinfo, parent);
6704         }
6705 }
6706
6707 void
6708 proto_register_fields_section(const int parent, header_field_info *hfi, const int num_records)
6709 {
6710         int               i;
6711         protocol_t       *proto;
6712
6713         proto = find_protocol_by_id(parent);
6714
6715         if (proto->fields == NULL) {
6716                 proto->fields = g_ptr_array_sized_new(num_records);
6717         }
6718
6719     for (i = 0; i < num_records; i++) {
6720                 /*
6721                  * Make sure we haven't registered this yet.
6722                  */
6723                 if (hfi[i].id != -1) {
6724                         fprintf(stderr,
6725                                 "Duplicate field detected in call to proto_register_fields: %s is already registered\n",
6726                                 hfi[i].abbrev);
6727                         return;
6728                 }
6729
6730                 proto_register_field_common(proto, &hfi[i], parent);
6731         }
6732 }
6733
6734 void
6735 proto_register_fields_manual(const int parent, header_field_info **hfi, const int num_records)
6736 {
6737         int               i;
6738         protocol_t       *proto;
6739
6740         proto = find_protocol_by_id(parent);
6741
6742         if (proto->fields == NULL) {
6743                 proto->fields = g_ptr_array_sized_new(num_records);
6744         }
6745
6746
6747         for (i = 0; i < num_records; i++) {
6748                 /*
6749                  * Make sure we haven't registered this yet.
6750                  */
6751                 if (hfi[i]->id != -1) {
6752                         fprintf(stderr,
6753                                 "Duplicate field detected in call to proto_register_fields: %s is already registered\n",
6754                                 hfi[i]->abbrev);
6755                         return;
6756                 }
6757
6758                 proto_register_field_common(proto, hfi[i], parent);
6759         }
6760 }
6761
6762 /* deregister already registered fields */
6763 void
6764 proto_deregister_field (const int parent, gint hf_id)
6765 {
6766         header_field_info *hfi;
6767         protocol_t       *proto;
6768         guint             i;
6769
6770         g_free(last_field_name);
6771         last_field_name = NULL;
6772
6773         if (hf_id == -1 || hf_id == 0)
6774                 return;
6775
6776         proto = find_protocol_by_id (parent);
6777         if (!proto || proto->fields == NULL) {
6778                 return;
6779         }
6780
6781         for (i = 0; i < proto->fields->len; i++) {
6782                 hfi = (header_field_info *)g_ptr_array_index(proto->fields, i);
6783                 if (hfi->id == hf_id) {
6784                         /* Found the hf_id in this protocol */
6785                         g_hash_table_steal(gpa_name_map, hfi->abbrev);
6786                         g_ptr_array_remove_index_fast(proto->fields, i);
6787                         g_ptr_array_add(deregistered_fields, gpa_hfinfo.hfi[hf_id]);
6788                         return;
6789                 }
6790         }
6791 }
6792
6793 void
6794 proto_add_deregistered_data (void *data)
6795 {
6796         g_ptr_array_add(deregistered_data, data);
6797 }
6798
6799 static void
6800 free_deregistered_field (gpointer data, gpointer user_data _U_)
6801 {
6802         header_field_info *hfi = (header_field_info *) data;
6803         gint hf_id = hfi->id;
6804
6805         g_free((char *)hfi->name);
6806         g_free((char *)hfi->abbrev);
6807         g_free((char *)hfi->blurb);
6808
6809         if (hfi->strings) {
6810                 switch (hfi->type) {
6811                         case FT_FRAMENUM:
6812                                 /* This is just an integer represented as a pointer */
6813                                 break;
6814                         case FT_PROTOCOL: {
6815                                 protocol_t *protocol = (protocol_t *)hfi->strings;
6816                                 g_free((gchar *)protocol->short_name);
6817                                 break;
6818                         }
6819                         case FT_BOOLEAN: {
6820                                 true_false_string *tf = (true_false_string *)hfi->strings;
6821                                 g_free ((gchar *)tf->true_string);
6822                                 g_free ((gchar *)tf->false_string);
6823                                 break;
6824                         }
6825                         case FT_UINT64:
6826                         case FT_INT64: {
6827                                 if (hfi->display & BASE_UNIT_STRING) {
6828                                         unit_name_string *unit = (unit_name_string*)hfi->strings;
6829                                         g_free ((gchar *)unit->singular);
6830                                         g_free ((gchar *)unit->plural);
6831                                 } else {
6832                                         val64_string *vs64 = (val64_string *)hfi->strings;
6833                                         while (vs64->strptr) {
6834                                                 g_free((gchar *)vs64->strptr);
6835                                                 vs64++;
6836                                         }
6837                                 }
6838                                 break;
6839                         }
6840                         default: {
6841                                 /* Other Integer types */
6842                                 if (hfi->display & BASE_UNIT_STRING) {
6843                                         unit_name_string *unit = (unit_name_string*)hfi->strings;
6844                                         g_free ((gchar *)unit->singular);
6845                                         g_free ((gchar *)unit->plural);
6846                                 } else {
6847                                         value_string *vs = (value_string *)hfi->strings;
6848                                         while (vs->strptr) {
6849                                                 g_free((gchar *)vs->strptr);
6850                                                 vs++;
6851                                         }
6852                                 }
6853                                 break;
6854                         }
6855                 }
6856                 if (hfi->type != FT_FRAMENUM) {
6857                         g_free((void *)hfi->strings);
6858                 }
6859         }
6860
6861         if (hfi->parent == -1)
6862                 g_slice_free(header_field_info, hfi);
6863
6864         gpa_hfinfo.hfi[hf_id] = NULL; /* Invalidate this hf_id / proto_id */
6865 }
6866
6867 static void
6868 free_deregistered_data (gpointer data, gpointer user_data _U_)
6869 {
6870         g_free (data);
6871 }
6872
6873 /* free deregistered fields and data */
6874 void
6875 proto_free_deregistered_fields (void)
6876 {
6877         expert_free_deregistered_expertinfos();
6878
6879         g_ptr_array_foreach(deregistered_fields, free_deregistered_field, NULL);
6880         g_ptr_array_free(deregistered_fields, TRUE);
6881         deregistered_fields = g_ptr_array_new();
6882
6883         g_ptr_array_foreach(deregistered_data, free_deregistered_data, NULL);
6884         g_ptr_array_free(deregistered_data, TRUE);
6885         deregistered_data = g_ptr_array_new();
6886 }
6887
6888 /* chars allowed in field abbrev */
6889 static
6890 const guint8 fld_abbrev_chars[256] = {
6891         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00-0x0F */
6892         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10-0x1F */
6893         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, /* 0x20-0x2F '-', '.'      */
6894         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 0x30-0x3F '0'-'9'       */
6895         0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x40-0x4F 'A'-'O'       */
6896         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 0x50-0x5F 'P'-'Z', '_' */
6897         0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x60-0x6F 'a'-'o'       */
6898         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 0x70-0x7F 'p'-'z'       */
6899         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80-0x8F */
6900         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90-0x9F */
6901         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xA0-0xAF */
6902         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xB0-0xBF */
6903         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xC0-0xCF */
6904         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xD0-0xDF */
6905         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xE0-0xEF */
6906         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xF0-0xFF */
6907 };
6908
6909 static const value_string hf_display[] = {
6910         { BASE_NONE,                      "BASE_NONE"                      },
6911         { BASE_DEC,                       "BASE_DEC"                       },
6912         { BASE_HEX,                       "BASE_HEX"                       },
6913         { BASE_OCT,                       "BASE_OCT"                       },
6914         { BASE_DEC_HEX,                   "BASE_DEC_HEX"                   },
6915         { BASE_HEX_DEC,                   "BASE_HEX_DEC"                   },
6916         { BASE_CUSTOM,                    "BASE_CUSTOM"                    },
6917         { BASE_NONE|BASE_RANGE_STRING,    "BASE_NONE|BASE_RANGE_STRING"    },
6918         { BASE_DEC|BASE_RANGE_STRING,     "BASE_DEC|BASE_RANGE_STRING"     },
6919         { BASE_HEX|BASE_RANGE_STRING,     "BASE_HEX|BASE_RANGE_STRING"     },
6920         { BASE_OCT|BASE_RANGE_STRING,     "BASE_OCT|BASE_RANGE_STRING"     },
6921         { BASE_DEC_HEX|BASE_RANGE_STRING, "BASE_DEC_HEX|BASE_RANGE_STRING" },
6922         { BASE_HEX_DEC|BASE_RANGE_STRING, "BASE_HEX_DEC|BASE_RANGE_STRING" },
6923         { BASE_CUSTOM|BASE_RANGE_STRING,  "BASE_CUSTOM|BASE_RANGE_STRING"  },
6924         { BASE_NONE|BASE_VAL64_STRING,    "BASE_NONE|BASE_VAL64_STRING"    },
6925         { BASE_DEC|BASE_VAL64_STRING,     "BASE_DEC|BASE_VAL64_STRING"     },
6926         { BASE_HEX|BASE_VAL64_STRING,     "BASE_HEX|BASE_VAL64_STRING"     },
6927         { BASE_OCT|BASE_VAL64_STRING,     "BASE_OCT|BASE_VAL64_STRING"     },
6928         { BASE_DEC_HEX|BASE_VAL64_STRING, "BASE_DEC_HEX|BASE_VAL64_STRING" },
6929         { BASE_HEX_DEC|BASE_VAL64_STRING, "BASE_HEX_DEC|BASE_VAL64_STRING" },
6930         { BASE_CUSTOM|BASE_VAL64_STRING,  "BASE_CUSTOM|BASE_VAL64_STRING"  },
6931         /* Alias: BASE_NONE { BASE_FLOAT,                       "BASE_FLOAT" }, */
6932         /* Alias: BASE_NONE { STR_ASCII,                          "STR_ASCII" }, */
6933         { STR_UNICODE,                    "STR_UNICODE" },
6934         { ABSOLUTE_TIME_LOCAL,            "ABSOLUTE_TIME_LOCAL"            },
6935         { ABSOLUTE_TIME_UTC,              "ABSOLUTE_TIME_UTC"              },
6936         { ABSOLUTE_TIME_DOY_UTC,          "ABSOLUTE_TIME_DOY_UTC"          },
6937         { BASE_PT_UDP,                    "BASE_PT_UDP"                    },
6938         { BASE_PT_TCP,                    "BASE_PT_TCP"                    },
6939         { BASE_PT_DCCP,                   "BASE_PT_DCCP"                   },
6940         { BASE_PT_SCTP,                   "BASE_PT_SCTP"                   },
6941         { 0,                              NULL } };
6942
6943 const char* proto_field_display_to_string(int field_display)
6944 {
6945     return val_to_str_const(field_display, hf_display, "Unknown");
6946 }
6947
6948 static inline port_type
6949 display_to_port_type(field_display_e e)
6950 {
6951         switch (e) {
6952         case BASE_PT_UDP:
6953                 return PT_UDP;
6954         case BASE_PT_TCP:
6955                 return PT_TCP;
6956         case BASE_PT_DCCP:
6957                 return PT_DCCP;
6958         case BASE_PT_SCTP:
6959                 return PT_SCTP;
6960         default:
6961                 break;
6962         }
6963         return PT_NONE;
6964 }
6965
6966 /* temporary function containing assert part for easier profiling */
6967 static void
6968 tmp_fld_check_assert(header_field_info *hfinfo)
6969 {
6970         gchar* tmp_str;
6971
6972         /* The field must have a name (with length > 0) */
6973         if (!hfinfo->name || !hfinfo->name[0]) {
6974                 if (hfinfo->abbrev)
6975                         /* Try to identify the field */
6976                         g_error("Field (abbrev='%s') does not have a name\n",
6977                                 hfinfo->abbrev);
6978                 else
6979                         /* Hum, no luck */
6980                         g_error("Field does not have a name (nor an abbreviation)\n");
6981         }
6982
6983         /* fields with an empty string for an abbreviation aren't filterable */
6984         if (!hfinfo->abbrev || !hfinfo->abbrev[0])
6985                 g_error("Field '%s' does not have an abbreviation\n", hfinfo->name);
6986
6987         /*  These types of fields are allowed to have value_strings,
6988          *  true_false_strings or a protocol_t struct
6989          */
6990         if (hfinfo->strings != NULL) {
6991                 switch(hfinfo->type) {
6992                 case FT_CHAR:
6993                 case FT_UINT8:
6994                 case FT_UINT16:
6995                 case FT_UINT24:
6996                 case FT_UINT32:
6997                 case FT_UINT40:
6998                 case FT_UINT48:
6999                 case FT_UINT56:
7000                 case FT_UINT64:
7001                 case FT_INT8:
7002                 case FT_INT16:
7003                 case FT_INT24:
7004                 case FT_INT32:
7005                 case FT_INT40:
7006                 case FT_INT48:
7007                 case FT_INT56:
7008                 case FT_INT64:
7009                 case FT_BOOLEAN:
7010                 case FT_PROTOCOL:
7011                 case FT_FRAMENUM:
7012                         break;
7013                 case FT_FLOAT:
7014                 case FT_DOUBLE:
7015                         //allowed to support string if its a unit decsription
7016                         if (hfinfo->display & BASE_UNIT_STRING)
7017                                 break;
7018
7019                         //fallthrough
7020                 case FT_BYTES:
7021                         //allowed to support string if its a protocol (for pinos)
7022                         if (hfinfo->display & BASE_PROTOCOL_INFO)
7023                                 break;
7024
7025                         //fallthrough
7026                 default:
7027                         g_error("Field '%s' (%s) has a 'strings' value but is of type %s"
7028                                 " (which is not allowed to have strings)\n",
7029                                 hfinfo->name, hfinfo->abbrev, ftype_name(hfinfo->type));
7030                 }
7031         }
7032
7033         /* TODO: This check may slow down startup, and output quite a few warnings.
7034            It would be good to be able to enable this (and possibly other checks?)
7035            in non-release builds.   */
7036 #if 0
7037         /* Check for duplicate value_string values.
7038            There are lots that have the same value *and* string, so for now only
7039            report those that have same value but different string. */
7040         if ((hfinfo->strings != NULL) &&
7041             !(hfinfo->display & BASE_RANGE_STRING) &&
7042             !((hfinfo->display & FIELD_DISPLAY_E_MASK) == BASE_CUSTOM) &&
7043             (
7044                     (hfinfo->type == FT_CHAR)  ||
7045                     (hfinfo->type == FT_UINT8)  ||
7046                     (hfinfo->type == FT_UINT16) ||
7047                     (hfinfo->type == FT_UINT24) ||
7048                     (hfinfo->type == FT_UINT32) ||
7049                     (hfinfo->type == FT_INT8)   ||
7050                     (hfinfo->type == FT_INT16)  ||
7051                     (hfinfo->type == FT_INT24)  ||
7052                     (hfinfo->type == FT_INT32)  ||
7053                     (hfinfo->type == FT_FRAMENUM) )) {
7054
7055                 int n, m;
7056                 const value_string *start_values;
7057                 const value_string *current;
7058
7059                 if (hfinfo->display & BASE_EXT_STRING)
7060                         start_values = VALUE_STRING_EXT_VS_P(((const value_string_ext*)hfinfo->strings));
7061                 else
7062                         start_values = (const value_string*)hfinfo->strings;
7063                 current = start_values;
7064
7065                 for (n=0; current; n++, current++) {
7066                         /* Drop out if we reached the end. */
7067                         if ((current->value == 0) && (current->strptr == NULL)) {
7068                                 break;
7069                         }
7070
7071                         /* Check value against all previous */
7072                         for (m=0; m < n; m++) {
7073                                 /* There are lots of duplicates with the same string,
7074                                    so only report if different... */
7075                                 if ((start_values[m].value == current->value) &&
7076                                     (strcmp(start_values[m].strptr, current->strptr) != 0)) {
7077                                         ws_g_warning("Field '%s' (%s) has a conflicting entry in its"
7078                                                   " value_string: %u is at indices %u (%s) and %u (%s))\n",
7079                                                   hfinfo->name, hfinfo->abbrev,
7080                                                   current->value, m, start_values[m].strptr, n, current->strptr);
7081                                 }
7082                         }
7083                 }
7084         }
7085 #endif
7086
7087
7088         switch (hfinfo->type) {
7089
7090                 case FT_CHAR:
7091                         /*  Require the char type to have BASE_HEX, BASE_OCT,
7092                          *  BASE_CUSTOM, or BASE_NONE as its base.
7093                          *
7094                          *  If the display value is BASE_NONE and there is a
7095                          *  strings conversion then the dissector writer is
7096                          *  telling us that the field's numerical value is
7097                          *  meaningless; we'll avoid showing the value to the
7098                          *  user.
7099                          */
7100                         switch (FIELD_DISPLAY(hfinfo->display)) {
7101                                 case BASE_HEX:
7102                                 case BASE_OCT:
7103                                 case BASE_CUSTOM: /* hfinfo_numeric_value_format() treats this as decimal */
7104                                         break;
7105                                 case BASE_NONE:
7106                                         if (hfinfo->strings == NULL)
7107                                                 g_error("Field '%s' (%s) is an integral value (%s)"
7108                                                         " but is being displayed as BASE_NONE but"
7109                                                         " without a strings conversion",
7110                                                         hfinfo->name, hfinfo->abbrev,
7111                                                         ftype_name(hfinfo->type));
7112                                         break;
7113                                 default:
7114                                         tmp_str = val_to_str_wmem(NULL, hfinfo->display, hf_display, "(Unknown: 0x%x)");
7115                                         g_error("Field '%s' (%s) is a character value (%s)"
7116                                                 " but is being displayed as %s\n",
7117                                                 hfinfo->name, hfinfo->abbrev,
7118                                                 ftype_name(hfinfo->type), tmp_str);
7119                                         wmem_free(NULL, tmp_str);
7120                         }
7121                         if (hfinfo->display & BASE_UNIT_STRING) {
7122                                 g_error("Field '%s' (%s) is a character value (%s) but has a unit string\n",
7123                                         hfinfo->name, hfinfo->abbrev,
7124                                         ftype_name(hfinfo->type));
7125                         }
7126                         break;
7127                 case FT_INT8:
7128                 case FT_INT16:
7129                 case FT_INT24:
7130                 case FT_INT32:
7131                 case FT_INT40:
7132                 case FT_INT48:
7133                 case FT_INT56:
7134                 case FT_INT64:
7135                         /*      Hexadecimal and octal are, in printf() and everywhere
7136                          *      else, unsigned so don't allow dissectors to register a
7137                          *      signed field to be displayed unsigned.  (Else how would
7138                          *      we display negative values?)
7139                          */
7140                         switch (hfinfo->display & FIELD_DISPLAY_E_MASK) {
7141                                 case BASE_HEX:
7142                                 case BASE_OCT:
7143                                 case BASE_DEC_HEX:
7144                                 case BASE_HEX_DEC:
7145                                         tmp_str = val_to_str_wmem(NULL, hfinfo->display, hf_display, "(Bit count: %d)");
7146                                         g_error("Field '%s' (%s) is signed (%s) but is being displayed unsigned (%s)\n",
7147                                                 hfinfo->name, hfinfo->abbrev,
7148                                                 ftype_name(hfinfo->type), tmp_str);
7149                                         wmem_free(NULL, tmp_str);
7150                         }
7151                         /* FALL THROUGH */
7152                 case FT_UINT8:
7153                 case FT_UINT16:
7154                 case FT_UINT24:
7155                 case FT_UINT32:
7156                 case FT_UINT40:
7157                 case FT_UINT48:
7158                 case FT_UINT56:
7159                 case FT_UINT64:
7160                         if (IS_BASE_PORT(hfinfo->display)) {
7161                                 tmp_str = val_to_str_wmem(NULL, hfinfo->display, hf_display, "(Unknown: 0x%x)");
7162                                 if (hfinfo->type != FT_UINT16) {
7163                                         g_error("Field '%s' (%s) has 'display' value %s but it can only be used with FT_UINT16, not %s\n",
7164                                                 hfinfo->name, hfinfo->abbrev,
7165                                                 tmp_str, ftype_name(hfinfo->type));
7166                                 }
7167                                 if (hfinfo->strings != NULL) {
7168                                         g_error("Field '%s' (%s) is an %s (%s) but has a strings value\n",
7169                                                 hfinfo->name, hfinfo->abbrev,
7170                                                 ftype_name(hfinfo->type), tmp_str);
7171                                 }
7172                                 if (hfinfo->bitmask != 0) {
7173                                         g_error("Field '%s' (%s) is an %s (%s) but has a bitmask\n",
7174                                                 hfinfo->name, hfinfo->abbrev,
7175                                                 ftype_name(hfinfo->type), tmp_str);
7176                                 }
7177                                 wmem_free(NULL, tmp_str);
7178                                 break;
7179                         }
7180
7181                         /*  Require integral types (other than frame number,
7182                          *  which is always displayed in decimal) to have a
7183                          *  number base.
7184                          *
7185                          *  If the display value is BASE_NONE and there is a
7186                          *  strings conversion then the dissector writer is
7187                          *  telling us that the field's numerical value is
7188                          *  meaningless; we'll avoid showing the value to the
7189                          *  user.
7190                          */
7191                         switch (hfinfo->display & FIELD_DISPLAY_E_MASK) {
7192                                 case BASE_DEC:
7193                                 case BASE_HEX:
7194                                 case BASE_OCT:
7195                                 case BASE_DEC_HEX:
7196                                 case BASE_HEX_DEC:
7197                                 case BASE_CUSTOM: /* hfinfo_numeric_value_format() treats this as decimal */
7198                                         break;
7199                                 case BASE_NONE:
7200                                         if (hfinfo->strings == NULL) {
7201                                                 g_error("Field '%s' (%s) is an integral value (%s)"
7202                                                         " but is being displayed as BASE_NONE but"
7203                                                         " without a strings conversion",
7204                                                         hfinfo->name, hfinfo->abbrev,
7205                                                         ftype_name(hfinfo->type));
7206                                         }
7207                                         if (hfinfo->display & BASE_SPECIAL_VALS) {
7208                                                 g_error("Field '%s' (%s) is an integral value (%s)"
7209                                                         " that is being displayed as BASE_NONE but"
7210                                                         " with BASE_SPECIAL_VALS",
7211                                                         hfinfo->name, hfinfo->abbrev,
7212                                                         ftype_name(hfinfo->type));
7213                                         }
7214                                         break;
7215
7216                                 default:
7217                                         tmp_str = val_to_str_wmem(NULL, hfinfo->display, hf_display, "(Unknown: 0x%x)");
7218                                         g_error("Field '%s' (%s) is an integral value (%s)"
7219                                                 " but is being displayed as %s\n",
7220                                                 hfinfo->name, hfinfo->abbrev,
7221                                                 ftype_name(hfinfo->type), tmp_str);
7222                                         wmem_free(NULL, tmp_str);
7223                         }
7224                         break;
7225                 case FT_BYTES:
7226                 case FT_UINT_BYTES:
7227                         /*  Require bytes to have a "display type" that could
7228                          *  add a character between displayed bytes.
7229                          */
7230                         switch (FIELD_DISPLAY(hfinfo->display)) {
7231                                 case BASE_NONE:
7232                                 case SEP_DOT:
7233                                 case SEP_DASH:
7234                                 case SEP_COLON:
7235                                 case SEP_SPACE:
7236                                         break;
7237                                 default:
7238                                         tmp_str = val_to_str_wmem(NULL, hfinfo->display, hf_display, "(Bit count: %d)");
7239                                         g_error("Field '%s' (%s) is an byte array but is being displayed as %s instead of BASE_NONE, SEP_DOT, SEP_DASH, SEP_COLON, or SEP_SPACE\n",
7240                                                 hfinfo->name, hfinfo->abbrev, tmp_str);
7241                                         wmem_free(NULL, tmp_str);
7242                         }
7243                         if (hfinfo->bitmask != 0)
7244                                 g_error("Field '%s' (%s) is an %s but has a bitmask\n",
7245                                         hfinfo->name, hfinfo->abbrev,
7246                                         ftype_name(hfinfo->type));
7247                         //allowed to support string if its a protocol (for pinos)
7248                         if ((hfinfo->strings != NULL) && (!(hfinfo->display & BASE_PROTOCOL_INFO)))
7249                                 g_error("Field '%s' (%s) is an %s but has a strings value\n",
7250                                         hfinfo->name, hfinfo->abbrev,
7251                                         ftype_name(hfinfo->type));
7252                         break;
7253
7254                 case FT_PROTOCOL:
7255                 case FT_FRAMENUM:
7256                         if (hfinfo->display != BASE_NONE) {
7257                                 tmp_str = val_to_str_wmem(NULL, hfinfo->display, hf_display, "(Bit count: %d)");
7258                                 g_error("Field '%s' (%s) is an %s but is being displayed as %s instead of BASE_NONE\n",
7259                                         hfinfo->name, hfinfo->abbrev,
7260                                         ftype_name(hfinfo->type), tmp_str);
7261                                 wmem_free(NULL, tmp_str);
7262                         }
7263                         if (hfinfo->bitmask != 0)
7264                                 g_error("Field '%s' (%s) is an %s but has a bitmask\n",
7265                                         hfinfo->name, hfinfo->abbrev,
7266                                         ftype_name(hfinfo->type));
7267                         break;
7268
7269                 case FT_BOOLEAN:
7270                         break;
7271
7272                 case FT_ABSOLUTE_TIME:
7273                         if (!(hfinfo->display == ABSOLUTE_TIME_LOCAL ||
7274                               hfinfo->display == ABSOLUTE_TIME_UTC   ||
7275                               hfinfo->display == ABSOLUTE_TIME_DOY_UTC)) {
7276                                 tmp_str = val_to_str_wmem(NULL, hfinfo->display, hf_display, "(Bit count: %d)");
7277                                 g_error("Field '%s' (%s) is a %s but is being displayed as %s instead of as a time\n",
7278                                         hfinfo->name, hfinfo->abbrev, ftype_name(hfinfo->type), tmp_str);
7279                                 wmem_free(NULL, tmp_str);
7280                         }
7281                         if (hfinfo->bitmask != 0)
7282                                 g_error("Field '%s' (%s) is an %s but has a bitmask\n",
7283                                         hfinfo->name, hfinfo->abbrev,
7284                                         ftype_name(hfinfo->type));
7285                         break;
7286
7287                 case FT_STRING:
7288                 case FT_STRINGZ:
7289                 case FT_UINT_STRING:
7290                 case FT_STRINGZPAD:
7291                         switch (hfinfo->display) {
7292                                 case STR_ASCII:
7293                                 case STR_UNICODE:
7294                                         break;
7295
7296                                 default:
7297                                         tmp_str = val_to_str_wmem(NULL, hfinfo->display, hf_display, "(Unknown: 0x%x)");
7298                                         g_error("Field '%s' (%s) is an string value (%s)"
7299                                                 " but is being displayed as %s\n",
7300                                                 hfinfo->name, hfinfo->abbrev,
7301                                                 ftype_name(hfinfo->type), tmp_str);
7302                                         wmem_free(NULL, tmp_str);
7303                         }
7304
7305                         if (hfinfo->bitmask != 0)
7306                                 g_error("Field '%s' (%s) is an %s but has a bitmask\n",
7307                                         hfinfo->name, hfinfo->abbrev,
7308                                         ftype_name(hfinfo->type));
7309                         if (hfinfo->strings != NULL)
7310                                 g_error("Field '%s' (%s) is an %s but has a strings value\n",
7311                                         hfinfo->name, hfinfo->abbrev,
7312                                         ftype_name(hfinfo->type));
7313                         break;
7314
7315                 case FT_IPv4:
7316                         switch (hfinfo->display) {
7317                                 case BASE_NONE:
7318                                 case BASE_NETMASK:
7319                                         break;
7320
7321                                 default:
7322                                         tmp_str = val_to_str_wmem(NULL, hfinfo->display, hf_display, "(Unknown: 0x%x)");
7323                                         g_error("Field '%s' (%s) is an IPv4 value (%s)"
7324                                                 " but is being displayed as %s\n",
7325                                                 hfinfo->name, hfinfo->abbrev,
7326                                                 ftype_name(hfinfo->type), tmp_str);
7327                                         wmem_free(NULL, tmp_str);
7328                                         break;
7329                         }
7330                         break;
7331                 case FT_FLOAT:
7332                 case FT_DOUBLE:
7333                         if (FIELD_DISPLAY(hfinfo->display) != BASE_NONE) {
7334                                 tmp_str = val_to_str_wmem(NULL, hfinfo->display, hf_display, "(Bit count: %d)");
7335                                 g_error("Field '%s' (%s) is an %s but is being displayed as %s instead of BASE_NONE\n",
7336                                         hfinfo->name, hfinfo->abbrev,
7337                                         ftype_name(hfinfo->type),
7338                                         tmp_str);
7339                                 wmem_free(NULL, tmp_str);
7340                         }
7341                         if (hfinfo->bitmask != 0)
7342                                 g_error("Field '%s' (%s) is an %s but has a bitmask\n",
7343                                         hfinfo->name, hfinfo->abbrev,
7344                                         ftype_name(hfinfo->type));
7345                         if ((hfinfo->strings != NULL) && (!(hfinfo->display & BASE_UNIT_STRING)))
7346                                 g_error("Field '%s' (%s) is an %s but has a strings value\n",
7347                                         hfinfo->name, hfinfo->abbrev,
7348                                         ftype_name(hfinfo->type));
7349                         break;
7350                 default:
7351                         if (hfinfo->display != BASE_NONE) {
7352                                 tmp_str = val_to_str_wmem(NULL, hfinfo->display, hf_display, "(Bit count: %d)");
7353                                 g_error("Field '%s' (%s) is an %s but is being displayed as %s instead of BASE_NONE\n",
7354                                         hfinfo->name, hfinfo->abbrev,
7355                                         ftype_name(hfinfo->type),
7356                                         tmp_str);
7357                                 wmem_free(NULL, tmp_str);
7358                         }
7359                         if (hfinfo->bitmask != 0)
7360                                 g_error("Field '%s' (%s) is an %s but has a bitmask\n",
7361                                         hfinfo->name, hfinfo->abbrev,
7362                                         ftype_name(hfinfo->type));
7363                         if (hfinfo->strings != NULL)
7364                                 g_error("Field '%s' (%s) is an %s but has a strings value\n",
7365                                         hfinfo->name, hfinfo->abbrev,
7366                                         ftype_name(hfinfo->type));
7367                         break;
7368         }
7369 }
7370
7371 #ifdef ENABLE_CHECK_FILTER
7372 static enum ftenum
7373 _ftype_common(enum ftenum type)
7374 {
7375         switch (type) {
7376                 case FT_INT8:
7377                 case FT_INT16:
7378                 case FT_INT24:
7379                 case FT_INT32:
7380                         return FT_INT32;
7381
7382                 case FT_CHAR:
7383                 case FT_UINT8:
7384                 case FT_UINT16:
7385                 case FT_UINT24:
7386                 case FT_UINT32:
7387                 case FT_IPXNET:
7388                 case FT_FRAMENUM:
7389                         return FT_UINT32;
7390
7391                 case FT_UINT64:
7392                 case FT_EUI64:
7393                         return FT_UINT64;
7394
7395                 case FT_STRING:
7396                 case FT_STRINGZ:
7397                 case FT_UINT_STRING:
7398                         return FT_STRING;
7399
7400                 case FT_FLOAT:
7401                 case FT_DOUBLE:
7402                         return FT_DOUBLE;
7403
7404                 case FT_BYTES:
7405                 case FT_UINT_BYTES:
7406                 case FT_ETHER:
7407                 case FT_OID:
7408                         return FT_BYTES;
7409
7410                 case FT_ABSOLUTE_TIME:
7411                 case FT_RELATIVE_TIME:
7412                         return FT_ABSOLUTE_TIME;
7413
7414                 default:
7415                         return type;
7416         }
7417 }
7418 #endif
7419
7420 static void
7421 register_type_length_mismatch(void)
7422 {
7423         static ei_register_info ei[] = {
7424                 { &ei_type_length_mismatch_error, { "_ws.type_length.mismatch", PI_MALFORMED, PI_ERROR, "Trying to fetch X with length Y", EXPFILL }},
7425                 { &ei_type_length_mismatch_warn, { "_ws.type_length.mismatch", PI_MALFORMED, PI_WARN, "Trying to fetch X with length Y", EXPFILL }},
7426         };
7427
7428         expert_module_t* expert_type_length_mismatch;
7429
7430         proto_type_length_mismatch = proto_register_protocol("Type Length Mismatch", "Type length mismatch", "_ws.type_length");
7431
7432         expert_type_length_mismatch = expert_register_protocol(proto_type_length_mismatch);
7433         expert_register_field_array(expert_type_length_mismatch, ei, array_length(ei));
7434
7435         /* "Type Length Mismatch" isn't really a protocol, it's an error indication;
7436            disabling them makes no sense. */
7437         proto_set_cant_toggle(proto_type_length_mismatch);
7438 }
7439
7440 static void
7441 register_number_string_decoding_error(void)
7442 {
7443         static ei_register_info ei[] = {
7444                 { &ei_number_string_decoding_failed_error,
7445                         { "_ws.number_string.decoding_error.failed", PI_MALFORMED, PI_ERROR,
7446                           "Failed to decode number from string", EXPFILL
7447                         }
7448                 },
7449                 { &ei_number_string_decoding_erange_error,
7450                         { "_ws.number_string.decoding_error.erange", PI_MALFORMED, PI_ERROR,
7451                           "Decoded number from string is out of valid range", EXPFILL
7452                         }
7453                 },
7454         };
7455
7456         expert_module_t* expert_number_string_decoding_error;
7457
7458         proto_number_string_decoding_error =
7459                 proto_register_protocol("Number-String Decoding Error",
7460                                         "Number-string decoding error",
7461                                         "_ws.number_string.decoding_error");
7462
7463         expert_number_string_decoding_error =
7464                 expert_register_protocol(proto_number_string_decoding_error);
7465         expert_register_field_array(expert_number_string_decoding_error, ei, array_length(ei));
7466
7467         /* "Number-String Decoding Error" isn't really a protocol, it's an error indication;
7468            disabling them makes no sense. */
7469         proto_set_cant_toggle(proto_number_string_decoding_error);
7470 }
7471
7472 #define PROTO_PRE_ALLOC_HF_FIELDS_MEM (188000+PRE_ALLOC_EXPERT_FIELDS_MEM)
7473 static int
7474 proto_register_field_init(header_field_info *hfinfo, const int parent)
7475 {
7476
7477         tmp_fld_check_assert(hfinfo);
7478
7479         hfinfo->parent         = parent;
7480         hfinfo->same_name_next = NULL;
7481         hfinfo->same_name_prev_id = -1;
7482
7483         /* if we always add and never delete, then id == len - 1 is correct */
7484         if (gpa_hfinfo.len >= gpa_hfinfo.allocated_len) {
7485                 if (!gpa_hfinfo.hfi) {
7486                         gpa_hfinfo.allocated_len = PROTO_PRE_ALLOC_HF_FIELDS_MEM;
7487                         gpa_hfinfo.hfi = (header_field_info **)g_malloc(sizeof(header_field_info *)*PROTO_PRE_ALLOC_HF_FIELDS_MEM);
7488                 } else {
7489                         gpa_hfinfo.allocated_len += 1000;
7490                         gpa_hfinfo.hfi = (header_field_info **)g_realloc(gpa_hfinfo.hfi,
7491                                                    sizeof(header_field_info *)*gpa_hfinfo.allocated_len);
7492                         /*g_warning("gpa_hfinfo.allocated_len %u", gpa_hfinfo.allocated_len);*/
7493                 }
7494         }
7495         gpa_hfinfo.hfi[gpa_hfinfo.len] = hfinfo;
7496         gpa_hfinfo.len++;
7497         hfinfo->id = gpa_hfinfo.len - 1;
7498
7499         /* if we have real names, enter this field in the name tree */
7500         if ((hfinfo->name[0] != 0) && (hfinfo->abbrev[0] != 0 )) {
7501
7502                 header_field_info *same_name_next_hfinfo;
7503                 guchar c;
7504
7505                 /* Check that the filter name (abbreviation) is legal;
7506                  * it must contain only alphanumerics, '-', "_", and ".". */
7507                 c = wrs_check_charset(fld_abbrev_chars, hfinfo->abbrev);
7508                 if (c) {
7509                         if (g_ascii_isprint(c))
7510                                 fprintf(stderr, "Invalid character '%c' in filter name '%s'\n", c, hfinfo->abbrev);
7511                         else
7512                                 fprintf(stderr, "Invalid byte \\%03o in filter name '%s'\n", c, hfinfo->abbrev);
7513                         DISSECTOR_ASSERT_NOT_REACHED();
7514                 }
7515
7516                 /* We allow multiple hfinfo's to be registered under the same
7517                  * abbreviation. This was done for X.25, as, depending
7518                  * on whether it's modulo-8 or modulo-128 operation,
7519                  * some bitfield fields may be in different bits of
7520                  * a byte, and we want to be able to refer to that field
7521                  * with one name regardless of whether the packets
7522                  * are modulo-8 or modulo-128 packets. */
7523
7524                 same_name_hfinfo = NULL;
7525
7526                 g_hash_table_insert(gpa_name_map, (gpointer) (hfinfo->abbrev), hfinfo);
7527                 /* GLIB 2.x - if it is already present
7528                  * the previous hfinfo with the same name is saved
7529                  * to same_name_hfinfo by value destroy callback */
7530                 if (same_name_hfinfo) {
7531                         /* There's already a field with this name.
7532                          * Put the current field *before* that field
7533                          * in the list of fields with this name, Thus,
7534                          * we end up with an effectively
7535                          * doubly-linked-list of same-named hfinfo's,
7536                          * with the head of the list (stored in the
7537                          * hash) being the last seen hfinfo.
7538                          */
7539                         same_name_next_hfinfo =
7540                                 same_name_hfinfo->same_name_next;
7541
7542                         hfinfo->same_name_next = same_name_next_hfinfo;
7543                         if (same_name_next_hfinfo)
7544                                 same_name_next_hfinfo->same_name_prev_id = hfinfo->id;
7545
7546                         same_name_hfinfo->same_name_next = hfinfo;
7547                         hfinfo->same_name_prev_id = same_name_hfinfo->id;
7548 #ifdef ENABLE_CHECK_FILTER
7549                         while (same_name_hfinfo) {
7550                                 if (_ftype_common(hfinfo->type) != _ftype_common(same_name_hfinfo->type))
7551                                         fprintf(stderr, "'%s' exists multiple times with NOT compatible types: %s and %s\n", hfinfo->abbrev, ftype_name(hfinfo->type), ftype_name(same_name_hfinfo->type));
7552                                 same_name_hfinfo = same_name_hfinfo->same_name_next;
7553                         }
7554 #endif
7555                 }
7556         }
7557
7558         return hfinfo->id;
7559 }
7560
7561 void
7562 proto_register_subtree_array(gint *const *indices, const int num_indices)
7563 {
7564         int     i;
7565         gint    *const *ptr = indices;
7566
7567         /*
7568          * If we've already allocated the array of tree types, expand
7569          * it; this lets plugins such as mate add tree types after
7570          * the initial startup.  (If we haven't already allocated it,
7571          * we don't allocate it; on the first pass, we just assign
7572          * ett values and keep track of how many we've assigned, and
7573          * when we're finished registering all dissectors we allocate
7574          * the array, so that we do only one allocation rather than
7575          * wasting CPU time and memory by growing the array for each
7576          * dissector that registers ett values.)
7577          */
7578         if (tree_is_expanded != NULL) {
7579                 tree_is_expanded = (guint32 *)g_realloc(tree_is_expanded, (1+((num_tree_types + num_indices)/32)) * sizeof(guint32));
7580
7581                 /* set new items to 0 */
7582                 /* XXX, slow!!! optimize when needed (align 'i' to 32, and set rest of guint32 to 0) */
7583                 for (i = num_tree_types; i < num_tree_types + num_indices; i++)
7584                         tree_is_expanded[i >> 5] &= ~(1U << (i & 31));
7585         }
7586
7587         /*
7588          * Assign "num_indices" subtree numbers starting at "num_tree_types",
7589          * returning the indices through the pointers in the array whose
7590          * first element is pointed to by "indices", and update
7591          * "num_tree_types" appropriately.
7592          */
7593         for (i = 0; i < num_indices; i++, ptr++, num_tree_types++) {
7594                 if (**ptr != -1) {
7595                         /* g_error will terminate the program */
7596                         g_error("register_subtree_array: subtree item type (ett_...) not -1 !"
7597                                 " This is a development error:"
7598                                 " Either the subtree item type has already been assigned or"
7599                                 " was not initialized to -1.");
7600                 }
7601                 **ptr = num_tree_types;
7602         }
7603 }
7604
7605 static inline gsize
7606 label_concat(char *label_str, gsize pos, const char *str)
7607 {
7608         if (pos < ITEM_LABEL_LENGTH)
7609                 pos += g_strlcpy(label_str + pos, str, ITEM_LABEL_LENGTH - pos);
7610
7611         return pos;
7612 }
7613
7614 static void
7615 label_mark_truncated(char *label_str, gsize name_pos)
7616 {
7617         static const char  trunc_str[] = " [truncated]";
7618         const size_t       trunc_len = sizeof(trunc_str)-1;
7619         gchar             *last_char;
7620
7621         /* ..... field_name: dataaaaaaaaaaaaa
7622          *                 |
7623          *                 ^^^^^ name_pos
7624          *
7625          * ..... field_name [truncated]: dataaaaaaaaaaaaa
7626          *
7627          * name_pos==0 means that we have only data or only a field_name
7628          */
7629
7630         if (name_pos < ITEM_LABEL_LENGTH - trunc_len) {
7631                 memmove(label_str + name_pos + trunc_len, label_str + name_pos, ITEM_LABEL_LENGTH - name_pos - trunc_len);
7632                 memcpy(label_str + name_pos, trunc_str, trunc_len);
7633
7634                 /* in general, label_str is UTF-8
7635                    we can truncate it only at the beginning of a new character
7636                    we go backwards from the byte right after our buffer and
7637                     find the next starting byte of a UTF-8 character, this is
7638                     where we cut
7639                    there's no need to use g_utf8_find_prev_char(), the search
7640                     will always succeed since we copied trunc_str into the
7641                     buffer */
7642                 last_char = g_utf8_prev_char(&label_str[ITEM_LABEL_LENGTH]);
7643                 *last_char = '\0';
7644
7645         } else if (name_pos < ITEM_LABEL_LENGTH)
7646                 g_strlcpy(label_str + name_pos, trunc_str, ITEM_LABEL_LENGTH - name_pos);
7647 }
7648
7649 static gsize
7650 label_fill(char *label_str, gsize pos, const header_field_info *hfinfo, const char *text)
7651 {
7652         gsize name_pos;
7653
7654         /* "%s: %s", hfinfo->name, text */
7655         name_pos = pos = label_concat(label_str, pos, hfinfo->name);
7656         if (!(hfinfo->display & BASE_NO_DISPLAY_VALUE)) {
7657                 pos = label_concat(label_str, pos, ": ");
7658                 pos = label_concat(label_str, pos, text ? text : "(null)");
7659         }
7660
7661         if (pos >= ITEM_LABEL_LENGTH) {
7662                 /* Uh oh, we don't have enough room. Tell the user that the field is truncated. */
7663                 label_mark_truncated(label_str, name_pos);
7664         }
7665
7666         return pos;
7667 }
7668
7669 static gsize
7670 label_fill_descr(char *label_str, gsize pos, const header_field_info *hfinfo, const char *text, const char *descr)
7671 {
7672         gsize name_pos;
7673
7674         /* "%s: %s (%s)", hfinfo->name, text, descr */
7675         name_pos = pos = label_concat(label_str, pos, hfinfo->name);
7676         if (!(hfinfo->display & BASE_NO_DISPLAY_VALUE)) {
7677                 pos = label_concat(label_str, pos, ": ");
7678                 if (hfinfo->display & BASE_UNIT_STRING) {
7679                         pos = label_concat(label_str, pos, descr ? descr : "(null)");
7680                         pos = label_concat(label_str, pos, text ? text : "(null)");
7681                 } else {
7682                         pos = label_concat(label_str, pos, text ? text : "(null)");
7683                         pos = label_concat(label_str, pos, " (");
7684                         pos = label_concat(label_str, pos, descr ? descr : "(null)");
7685                         pos = label_concat(label_str, pos, ")");
7686                 }
7687         }
7688
7689         if (pos >= ITEM_LABEL_LENGTH) {
7690                 /* Uh oh, we don't have enough room. Tell the user that the field is truncated. */
7691                 label_mark_truncated(label_str, name_pos);
7692         }
7693
7694         return pos;
7695 }
7696
7697 void
7698 proto_item_fill_label(field_info *fi, gchar *label_str)
7699 {
7700         header_field_info  *hfinfo;
7701         guint8             *bytes;
7702         guint32             integer;
7703         guint64             integer64;
7704         ipv4_addr_and_mask *ipv4;
7705         e_guid_t           *guid;
7706         guint32             n_addr; /* network-order IPv4 address */
7707         gchar              *name;
7708         address             addr;
7709         char               *addr_str;
7710         char               *tmp;
7711
7712         if (!fi) {
7713                 if (label_str)
7714                         label_str[0]= '\0';
7715                 /* XXX: Check validity of hfinfo->type */
7716                 return;
7717         }
7718
7719         hfinfo = fi->hfinfo;
7720
7721         switch (hfinfo->type) {
7722                 case FT_NONE:
7723                 case FT_PROTOCOL:
7724                         g_strlcpy(label_str, hfinfo->name, ITEM_LABEL_LENGTH);
7725                         break;
7726
7727                 case FT_BOOLEAN:
7728                         fill_label_boolean(fi, label_str);
7729                         break;
7730
7731                 case FT_BYTES:
7732                 case FT_UINT_BYTES:
7733                         bytes = (guint8 *)fvalue_get(&fi->value);
7734                         if (bytes) {
7735                                 char* str = NULL;
7736                                 switch(hfinfo->display)
7737                                 {
7738                                 case SEP_DOT:
7739                                         str = bytestring_to_str(NULL, bytes, fvalue_length(&fi->value), '.');
7740                                         break;
7741                                 case SEP_DASH:
7742                                         str = bytestring_to_str(NULL, bytes, fvalue_length(&fi->value), '-');
7743                                         break;
7744                                 case SEP_COLON:
7745                                         str = bytestring_to_str(NULL, bytes, fvalue_length(&fi->value), ':');
7746                                         break;
7747                                 case SEP_SPACE:
7748                                         str = bytestring_to_str(NULL, bytes, fvalue_length(&fi->value), ' ');
7749                                         break;
7750                                 case BASE_NONE:
7751                                 default:
7752                                         if (prefs.display_byte_fields_with_spaces)
7753                                         {
7754                                                 str = bytestring_to_str(NULL, bytes, fvalue_length(&fi->value), ' ');
7755                                         }
7756                                         else
7757                                         {
7758                                                 str = bytes_to_str(NULL, bytes, fvalue_length(&fi->value));
7759                                         }
7760                                         break;
7761                                 }
7762                                 label_fill(label_str, 0, hfinfo, str);
7763                                 wmem_free(NULL, str);
7764                         } else {
7765                                 if (hfinfo->display & BASE_ALLOW_ZERO) {
7766                                         label_fill(label_str, 0, hfinfo, "<none>");
7767                                 } else {
7768                                         label_fill(label_str, 0, hfinfo, "<MISSING>");
7769                                 }
7770                         }
7771                         break;
7772
7773                 case FT_CHAR:
7774                         if (hfinfo->bitmask) {
7775                                 fill_label_bitfield_char(fi, label_str);
7776                         } else {
7777                                 fill_label_char(fi, label_str);
7778                         }
7779                         break;
7780
7781                 /* Four types of integers to take care of:
7782                  *      Bitfield, with val_string
7783                  *      Bitfield, w/o val_string
7784                  *      Non-bitfield, with val_string
7785                  *      Non-bitfield, w/o val_string
7786                  */
7787                 case FT_UINT8:
7788                 case FT_UINT16:
7789                 case FT_UINT24:
7790                 case FT_UINT32:
7791                         if (hfinfo->bitmask) {
7792                                 fill_label_bitfield(fi, label_str, FALSE);
7793                         } else {
7794                                 fill_label_number(fi, label_str, FALSE);
7795                         }
7796                         break;
7797
7798                 case FT_FRAMENUM:
7799                         fill_label_number(fi, label_str, FALSE);
7800                         break;
7801
7802                 case FT_UINT40:
7803                 case FT_UINT48:
7804                 case FT_UINT56:
7805                 case FT_UINT64:
7806                         if (hfinfo->bitmask) {
7807                                 fill_label_bitfield64(fi, label_str, FALSE);
7808                         } else {
7809                                 fill_label_number64(fi, label_str, FALSE);
7810                         }
7811                         break;
7812
7813                 case FT_INT8:
7814                 case FT_INT16:
7815                 case FT_INT24:
7816                 case FT_INT32:
7817                         if (hfinfo->bitmask) {
7818                                 fill_label_bitfield(fi, label_str, TRUE);
7819                         } else {
7820                                 fill_label_number(fi, label_str, TRUE);
7821                         }
7822                         break;
7823
7824                 case FT_INT40:
7825                 case FT_INT48:
7826                 case FT_INT56:
7827                 case FT_INT64:
7828                         if (hfinfo->bitmask) {
7829                                 fill_label_bitfield64(fi, label_str, TRUE);
7830                         } else {
7831                                 fill_label_number64(fi, label_str, TRUE);
7832                         }
7833                         break;
7834
7835                 case FT_FLOAT: {
7836                         double d_value = fvalue_get_floating(&fi->value);
7837                         if (hfinfo->display & BASE_UNIT_STRING) {
7838                                 g_snprintf(label_str, ITEM_LABEL_LENGTH,
7839                                            "%s: %." G_STRINGIFY(FLT_DIG) "g%s",
7840                                            hfinfo->name, d_value,
7841                                            unit_name_string_get_double(d_value, (unit_name_string*)hfinfo->strings));
7842                         } else {
7843                                 g_snprintf(label_str, ITEM_LABEL_LENGTH,
7844                                            "%s: %." G_STRINGIFY(FLT_DIG) "g",
7845                                            hfinfo->name, d_value);
7846                         }
7847                         }
7848                         break;
7849
7850                 case FT_DOUBLE: {
7851                         double d_value = fvalue_get_floating(&fi->value);
7852                         if (hfinfo->display & BASE_UNIT_STRING) {
7853                                 g_snprintf(label_str, ITEM_LABEL_LENGTH,
7854                                            "%s: %." G_STRINGIFY(DBL_DIG) "g%s",
7855                                            hfinfo->name, d_value,
7856                                            unit_name_string_get_double(d_value, (unit_name_string*)hfinfo->strings));
7857                         } else {
7858                                 g_snprintf(label_str, ITEM_LABEL_LENGTH,
7859                                            "%s: %." G_STRINGIFY(DBL_DIG) "g",
7860                                            hfinfo->name, d_value);
7861                         }
7862                         }
7863                         break;
7864
7865                 case FT_ABSOLUTE_TIME:
7866                         tmp = abs_time_to_str(NULL, (const nstime_t *)fvalue_get(&fi->value), (absolute_time_display_e)hfinfo->display, TRUE);
7867                         label_fill(label_str, 0, hfinfo, tmp);
7868                         wmem_free(NULL, tmp);
7869                         break;
7870
7871                 case FT_RELATIVE_TIME:
7872                         tmp = rel_time_to_secs_str(NULL, (const nstime_t *)fvalue_get(&fi->value));
7873                         g_snprintf(label_str, ITEM_LABEL_LENGTH,
7874                                    "%s: %s seconds", hfinfo->name, tmp);
7875                         wmem_free(NULL, tmp);
7876                         break;
7877
7878                 case FT_IPXNET:
7879                         integer = fvalue_get_uinteger(&fi->value);
7880                         tmp = get_ipxnet_name(NULL, integer);
7881                         g_snprintf(label_str, ITEM_LABEL_LENGTH,
7882                                    "%s: %s (0x%08X)", hfinfo->name,
7883                                    tmp, integer);
7884                         wmem_free(NULL, tmp);
7885                         break;
7886
7887                 case FT_AX25:
7888                         addr.type = AT_AX25;
7889                         addr.len  = AX25_ADDR_LEN;
7890                         addr.data = (guint8 *)fvalue_get(&fi->value);
7891
7892                         addr_str = (char*)address_to_str(NULL, &addr);
7893                         g_snprintf(label_str, ITEM_LABEL_LENGTH,
7894                                    "%s: %s", hfinfo->name, addr_str);
7895                         wmem_free(NULL, addr_str);
7896                         break;
7897
7898                 case FT_VINES:
7899                         addr.type = vines_address_type;
7900                         addr.len  = VINES_ADDR_LEN;
7901                         addr.data = (guint8 *)fvalue_get(&fi->value);
7902
7903                         addr_str = (char*)address_to_str(NULL, &addr);
7904                         g_snprintf(label_str, ITEM_LABEL_LENGTH,
7905                                    "%s: %s", hfinfo->name, addr_str);
7906                         wmem_free(NULL, addr_str);
7907                         break;
7908
7909                 case FT_ETHER:
7910                         bytes = (guint8 *)fvalue_get(&fi->value);
7911
7912                         addr.type = AT_ETHER;
7913                         addr.len  = 6;
7914                         addr.data = bytes;
7915
7916                         addr_str = (char*)address_with_resolution_to_str(NULL, &addr);
7917                         g_snprintf(label_str, ITEM_LABEL_LENGTH,
7918                                    "%s: %s", hfinfo->name, addr_str);
7919                         wmem_free(NULL, addr_str);
7920                         break;
7921
7922                 case FT_IPv4:
7923                         ipv4 = (ipv4_addr_and_mask *)fvalue_get(&fi->value);
7924                         n_addr = ipv4_get_net_order_addr(ipv4);
7925
7926                         addr.type = AT_IPv4;
7927                         addr.len  = 4;
7928                         addr.data = &n_addr;
7929
7930                         if (hfinfo->display == BASE_NETMASK)
7931                         {
7932                                 addr_str = (char*)address_to_str(NULL, &addr);
7933                         }
7934                         else
7935                         {
7936                                 addr_str = (char*)address_with_resolution_to_str(NULL, &addr);
7937                         }
7938                         g_snprintf(label_str, ITEM_LABEL_LENGTH,
7939                                    "%s: %s", hfinfo->name, addr_str);
7940                         wmem_free(NULL, addr_str);
7941                         break;
7942
7943                 case FT_IPv6:
7944                         bytes = (guint8 *)fvalue_get(&fi->value);
7945
7946                         addr.type = AT_IPv6;
7947                         addr.len  = 16;
7948                         addr.data = bytes;
7949
7950                         addr_str = (char*)address_with_resolution_to_str(NULL, &addr);
7951                         g_snprintf(label_str, ITEM_LABEL_LENGTH,
7952                                    "%s: %s", hfinfo->name, addr_str);
7953                         wmem_free(NULL, addr_str);
7954                         break;
7955
7956                 case FT_FCWWN:
7957                         addr.type = AT_FCWWN;
7958                         addr.len  = FCWWN_ADDR_LEN;
7959                         addr.data = (guint8 *)fvalue_get(&fi->value);
7960
7961                         addr_str = (char*)address_with_resolution_to_str(NULL, &addr);
7962                         g_snprintf(label_str, ITEM_LABEL_LENGTH,
7963                                    "%s: %s", hfinfo->name, addr_str);
7964                         wmem_free(NULL, addr_str);
7965                         break;
7966
7967                 case FT_GUID:
7968                         guid = (e_guid_t *)fvalue_get(&fi->value);
7969                         tmp = guid_to_str(NULL, guid);
7970                         label_fill(label_str, 0, hfinfo, tmp);
7971                         wmem_free(NULL, tmp);
7972                         break;
7973
7974                 case FT_OID:
7975                         bytes = (guint8 *)fvalue_get(&fi->value);
7976                         name = oid_resolved_from_encoded(NULL, bytes, fvalue_length(&fi->value));
7977                         tmp = oid_encoded2string(NULL, bytes, fvalue_length(&fi->value));
7978                         if (name) {
7979                                 label_fill_descr(label_str, 0, hfinfo, tmp, name);
7980                                 wmem_free(NULL, name);
7981                         } else {
7982                                 label_fill(label_str, 0, hfinfo, tmp);
7983                         }
7984                         wmem_free(NULL, tmp);
7985                         break;
7986
7987                 case FT_REL_OID:
7988                         bytes = (guint8 *)fvalue_get(&fi->value);
7989                         name = rel_oid_resolved_from_encoded(NULL, bytes, fvalue_length(&fi->value));
7990                         tmp = rel_oid_encoded2string(NULL, bytes, fvalue_length(&fi->value));
7991                         if (name) {
7992                                 label_fill_descr(label_str, 0, hfinfo, tmp, name);
7993                                 wmem_free(NULL, name);
7994                         } else {
7995                                 label_fill(label_str, 0, hfinfo, tmp);
7996                         }
7997                         wmem_free(NULL, tmp);
7998                         break;
7999
8000                 case FT_SYSTEM_ID:
8001                         bytes = (guint8 *)fvalue_get(&fi->value);
8002                         tmp = print_system_id(NULL, bytes, fvalue_length(&fi->value));
8003                         label_fill(label_str, 0, hfinfo, tmp);
8004                         wmem_free(NULL, tmp);
8005                         break;
8006
8007                 case FT_EUI64:
8008                         integer64 = fvalue_get_uinteger64(&fi->value);
8009                         addr_str = eui64_to_str(NULL, integer64);
8010                         tmp = (char*)eui64_to_display(NULL, integer64);
8011                         label_fill_descr(label_str, 0, hfinfo, tmp, addr_str);
8012                         wmem_free(NULL, tmp);
8013                         wmem_free(NULL, addr_str);
8014                         break;
8015                 case FT_STRING:
8016                 case FT_STRINGZ:
8017                 case FT_UINT_STRING:
8018                 case FT_STRINGZPAD:
8019                         bytes = (guint8 *)fvalue_get(&fi->value);
8020                         tmp = hfinfo_format_text(hfinfo, bytes);
8021                         label_fill(label_str, 0, hfinfo, tmp);
8022                         wmem_free(NULL, tmp);
8023                         break;
8024
8025                 case FT_IEEE_11073_SFLOAT:
8026                         tmp = fvalue_to_string_repr(NULL, &fi->value, FTREPR_DISPLAY, hfinfo->display);
8027                         g_snprintf(label_str, ITEM_LABEL_LENGTH,
8028                                                 "%s: %s",
8029                                                 hfinfo->name, tmp);
8030                         wmem_free(NULL, tmp);
8031                         break;
8032                 case FT_IEEE_11073_FLOAT:
8033                         tmp = fvalue_to_string_repr(NULL, &fi->value, FTREPR_DISPLAY, hfinfo->display);
8034                         g_snprintf(label_str, ITEM_LABEL_LENGTH,
8035                                                 "%s: %s",
8036                                                 hfinfo->name, tmp);
8037                         wmem_free(NULL, tmp);
8038                         break;
8039
8040                 default:
8041                         g_error("hfinfo->type %d (%s) not handled\n",
8042                                 hfinfo->type, ftype_name(hfinfo->type));
8043                         DISSECTOR_ASSERT_NOT_REACHED();
8044                         break;
8045         }
8046 }
8047
8048 static void
8049 fill_label_boolean(field_info *fi, gchar *label_str)
8050 {
8051         char    *p                    = label_str;
8052         int      bitfield_byte_length = 0, bitwidth;
8053         guint64  unshifted_value;
8054         guint64  value;
8055
8056         header_field_info       *hfinfo   = fi->hfinfo;
8057         const true_false_string *tfstring = (const true_false_string *)&tfs_true_false;
8058
8059         if (hfinfo->strings) {
8060                 tfstring = (const struct true_false_string*) hfinfo->strings;
8061         }
8062
8063         value = fvalue_get_uinteger64(&fi->value);
8064         if (hfinfo->bitmask) {
8065                 /* Figure out the bit width */
8066                 bitwidth = hfinfo_container_bitwidth(hfinfo);
8067
8068                 /* Un-shift bits */
8069                 unshifted_value = value;
8070                 unshifted_value <<= hfinfo_bitshift(hfinfo);
8071
8072                 /* Create the bitfield first */
8073                 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
8074                 bitfield_byte_length = (int) (p - label_str);
8075         }
8076
8077         /* Fill in the textual info */
8078         label_fill(label_str, bitfield_byte_length, hfinfo, value ? tfstring->true_string : tfstring->false_string);
8079 }
8080
8081 static const char *
8082 hf_try_val_to_str(guint32 value, const header_field_info *hfinfo)
8083 {
8084         if (hfinfo->display & BASE_RANGE_STRING)
8085                 return try_rval_to_str(value, (const range_string *) hfinfo->strings);
8086
8087         if (hfinfo->display & BASE_EXT_STRING)
8088                 return try_val_to_str_ext(value, (value_string_ext *) hfinfo->strings);
8089
8090         if (hfinfo->display & BASE_VAL64_STRING)
8091                 return try_val64_to_str(value, (const val64_string *) hfinfo->strings);
8092
8093         if (hfinfo->display & BASE_UNIT_STRING)
8094                 return unit_name_string_get_value(value, (struct unit_name_string*) hfinfo->strings);
8095
8096         return try_val_to_str(value, (const value_string *) hfinfo->strings);
8097 }
8098
8099 static const char *
8100 hf_try_val64_to_str(guint64 value, const header_field_info *hfinfo)
8101 {
8102         if (hfinfo->display & BASE_VAL64_STRING)
8103                 return try_val64_to_str(value, (const val64_string *) hfinfo->strings);
8104
8105         if (hfinfo->display & BASE_RANGE_STRING)
8106                 return try_rval64_to_str(value, (const range_string *) hfinfo->strings);
8107
8108         if (hfinfo->display & BASE_UNIT_STRING)
8109                 return unit_name_string_get_value64(value, (struct unit_name_string*) hfinfo->strings);
8110
8111         /* If this is reached somebody registered a 64-bit field with a 32-bit
8112          * value-string, which isn't right. */
8113         DISSECTOR_ASSERT_NOT_REACHED();
8114
8115         /* This is necessary to squelch MSVC errors; is there
8116            any way to tell it that DISSECTOR_ASSERT_NOT_REACHED()
8117            never returns? */
8118         return NULL;
8119 }
8120
8121 static const char *
8122 hf_try_val_to_str_const(guint32 value, const header_field_info *hfinfo, const char *unknown_str)
8123 {
8124         const char *str = hf_try_val_to_str(value, hfinfo);
8125
8126         return (str) ? str : unknown_str;
8127 }
8128
8129 static const char *
8130 hf_try_val64_to_str_const(guint64 value, const header_field_info *hfinfo, const char *unknown_str)
8131 {
8132         const char *str = hf_try_val64_to_str(value, hfinfo);
8133
8134         return (str) ? str : unknown_str;
8135 }
8136
8137 /* Fills data for bitfield chars with val_strings */
8138 static void
8139 fill_label_bitfield_char(field_info *fi, gchar *label_str)
8140 {
8141         char       *p;
8142         int         bitfield_byte_length, bitwidth;
8143         guint32     unshifted_value;
8144         guint32     value;
8145
8146         char        buf[32];
8147         const char *out;
8148
8149         header_field_info *hfinfo = fi->hfinfo;
8150
8151         /* Figure out the bit width */
8152         bitwidth = hfinfo_container_bitwidth(hfinfo);
8153
8154         /* Un-shift bits */
8155         value = fvalue_get_uinteger(&fi->value);
8156
8157         unshifted_value = value;
8158         if (hfinfo->bitmask) {
8159                 unshifted_value <<= hfinfo_bitshift(hfinfo);
8160         }
8161
8162         /* Create the bitfield first */
8163         p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
8164         bitfield_byte_length = (int) (p - label_str);
8165
8166         /* Fill in the textual info using stored (shifted) value */
8167         if (hfinfo->display == BASE_CUSTOM) {
8168                 gchar tmp[ITEM_LABEL_LENGTH];
8169                 const custom_fmt_func_t fmtfunc = (const custom_fmt_func_t)hfinfo->strings;
8170
8171                 DISSECTOR_ASSERT(fmtfunc);
8172                 fmtfunc(tmp, value);
8173                 label_fill(label_str, bitfield_byte_length, hfinfo, tmp);
8174         }
8175         else if (hfinfo->strings) {
8176                 const char *val_str = hf_try_val_to_str_const(value, hfinfo, "Unknown");
8177
8178                 out = hfinfo_char_vals_format(hfinfo, buf, value);
8179                 if (out == NULL) /* BASE_NONE so don't put integer in descr */
8180                         label_fill(label_str, bitfield_byte_length, hfinfo, val_str);
8181                 else
8182                         label_fill_descr(label_str, bitfield_byte_length, hfinfo, val_str, out);
8183         }
8184         else {
8185                 out = hfinfo_char_value_format(hfinfo, buf, value);
8186
8187                 label_fill(label_str, bitfield_byte_length, hfinfo, out);
8188         }
8189 }
8190
8191 /* Fills data for bitfield ints with val_strings */
8192 static void
8193 fill_label_bitfield(field_info *fi, gchar *label_str, gboolean is_signed)
8194 {
8195         char       *p;
8196         int         bitfield_byte_length, bitwidth;
8197         guint32     unshifted_value;
8198         guint32     value;
8199
8200         char        buf[32];
8201         const char *out;
8202
8203         header_field_info *hfinfo = fi->hfinfo;
8204
8205         /* Figure out the bit width */
8206         bitwidth = hfinfo_container_bitwidth(hfinfo);
8207
8208         /* Un-shift bits */
8209         if (is_signed)
8210                 value = fvalue_get_sinteger(&fi->value);
8211         else
8212                 value = fvalue_get_uinteger(&fi->value);
8213
8214         unshifted_value = value;
8215         if (hfinfo->bitmask) {
8216                 unshifted_value <<= hfinfo_bitshift(hfinfo);
8217         }
8218
8219         /* Create the bitfield first */
8220         p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
8221         bitfield_byte_length = (int) (p - label_str);
8222
8223         /* Fill in the textual info using stored (shifted) value */
8224         if (hfinfo->display == BASE_CUSTOM) {
8225                 gchar tmp[ITEM_LABEL_LENGTH];
8226                 const custom_fmt_func_t fmtfunc = (const custom_fmt_func_t)hfinfo->strings;
8227
8228                 DISSECTOR_ASSERT(fmtfunc);
8229                 fmtfunc(tmp, value);
8230                 label_fill(label_str, bitfield_byte_length, hfinfo, tmp);
8231         }
8232         else if (hfinfo->strings) {
8233                 const char *val_str = hf_try_val_to_str_const(value, hfinfo, "Unknown");
8234
8235                 out = hfinfo_number_vals_format(hfinfo, buf, value);
8236                 if (out == NULL) /* BASE_NONE so don't put integer in descr */
8237                         label_fill(label_str, bitfield_byte_length, hfinfo, val_str);
8238                 else
8239                         label_fill_descr(label_str, bitfield_byte_length, hfinfo, val_str, out);
8240         }
8241         else {
8242                 out = hfinfo_number_value_format(hfinfo, buf, value);
8243
8244                 label_fill(label_str, bitfield_byte_length, hfinfo, out);
8245         }
8246 }
8247
8248 static void
8249 fill_label_bitfield64(field_info *fi, gchar *label_str, gboolean is_signed)
8250 {
8251         char       *p;
8252         int         bitfield_byte_length, bitwidth;
8253         guint64     unshifted_value;
8254         guint64     value;
8255
8256         char        buf[48];
8257         const char *out;
8258
8259         header_field_info *hfinfo = fi->hfinfo;
8260
8261         /* Figure out the bit width */
8262         bitwidth = hfinfo_container_bitwidth(hfinfo);
8263
8264         /* Un-shift bits */
8265         if (is_signed)
8266                 value = fvalue_get_sinteger64(&fi->value);
8267         else
8268                 value = fvalue_get_uinteger64(&fi->value);
8269
8270         unshifted_value = value;
8271         if (hfinfo->bitmask) {
8272                 unshifted_value <<= hfinfo_bitshift(hfinfo);
8273         }
8274
8275         /* Create the bitfield first */
8276         p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
8277         bitfield_byte_length = (int) (p - label_str);
8278
8279         /* Fill in the textual info using stored (shifted) value */
8280         if (hfinfo->display == BASE_CUSTOM) {
8281                 gchar tmp[ITEM_LABEL_LENGTH];
8282                 const custom_fmt_func_64_t fmtfunc64 = (const custom_fmt_func_64_t)hfinfo->strings;
8283
8284                 DISSECTOR_ASSERT(fmtfunc64);
8285                 fmtfunc64(tmp, value);
8286                 label_fill(label_str, bitfield_byte_length, hfinfo, tmp);
8287         }
8288         else if (hfinfo->strings) {
8289                 const char *val_str = hf_try_val64_to_str_const(value, hfinfo, "Unknown");
8290
8291                 out = hfinfo_number_vals_format64(hfinfo, buf, value);
8292                 if (out == NULL) /* BASE_NONE so don't put integer in descr */
8293                         label_fill(label_str, bitfield_byte_length, hfinfo, val_str);
8294                 else
8295                         label_fill_descr(label_str, bitfield_byte_length, hfinfo, val_str, out);
8296         }
8297         else {
8298                 out = hfinfo_number_value_format64(hfinfo, buf, value);
8299
8300                 label_fill(label_str, bitfield_byte_length, hfinfo, out);
8301         }
8302 }
8303
8304 static void
8305 fill_label_char(field_info *fi, gchar *label_str)
8306 {
8307         header_field_info *hfinfo = fi->hfinfo;
8308         guint32            value;
8309
8310         char               buf[32];
8311         const char        *out;
8312
8313         value = fvalue_get_uinteger(&fi->value);
8314
8315         /* Fill in the textual info */
8316         if (hfinfo->display == BASE_CUSTOM) {
8317                 gchar tmp[ITEM_LABEL_LENGTH];
8318                 const custom_fmt_func_t fmtfunc = (const custom_fmt_func_t)hfinfo->strings;
8319
8320                 DISSECTOR_ASSERT(fmtfunc);
8321                 fmtfunc(tmp, value);
8322                 label_fill(label_str, 0, hfinfo, tmp);
8323         }
8324         else if (hfinfo->strings) {
8325                 const char *val_str = hf_try_val_to_str_const(value, hfinfo, "Unknown");
8326
8327                 out = hfinfo_char_vals_format(hfinfo, buf, value);
8328                 label_fill_descr(label_str, 0, hfinfo, val_str, out);
8329         }
8330         else {
8331                 out = hfinfo_char_value_format(hfinfo, buf, value);
8332
8333                 label_fill(label_str, 0, hfinfo, out);
8334         }
8335 }
8336
8337 static void
8338 fill_label_number(field_info *fi, gchar *label_str, gboolean is_signed)
8339 {
8340         header_field_info *hfinfo = fi->hfinfo;
8341         guint32            value;
8342
8343         char               buf[32];
8344         const char        *out;
8345
8346         if (is_signed)
8347                 value = fvalue_get_sinteger(&fi->value);
8348         else
8349                 value = fvalue_get_uinteger(&fi->value);
8350
8351         /* Fill in the textual info */
8352         if (hfinfo->display == BASE_CUSTOM) {
8353                 gchar tmp[ITEM_LABEL_LENGTH];
8354                 const custom_fmt_func_t fmtfunc = (const custom_fmt_func_t)hfinfo->strings;
8355
8356                 DISSECTOR_ASSERT(fmtfunc);
8357                 fmtfunc(tmp, value);
8358                 label_fill(label_str, 0, hfinfo, tmp);
8359         }
8360         else if (hfinfo->strings && hfinfo->type != FT_FRAMENUM) {
8361                 /*
8362                  * It makes no sense to have a value-string table for a
8363                  * frame-number field - they're just integers giving
8364                  * the ordinal frame number.
8365                  */
8366                 const char *val_str = hf_try_val_to_str(value, hfinfo);
8367
8368                 out = hfinfo_number_vals_format(hfinfo, buf, value);
8369                 if (hfinfo->display & BASE_SPECIAL_VALS) {
8370                         /*
8371                          * Unique values only display value_string string
8372                          * if there is a match.  Otherwise it's just a number
8373                          */
8374                         if (val_str) {
8375                                 label_fill_descr(label_str, 0, hfinfo, val_str, out);
8376                         } else {
8377                                 label_fill(label_str, 0, hfinfo, out);
8378                         }
8379                 } else {
8380                         if (val_str == NULL)
8381                                 val_str = "Unknown";
8382
8383                         if (out == NULL) /* BASE_NONE so don't put integer in descr */
8384                                 label_fill(label_str, 0, hfinfo, val_str);
8385                         else
8386                                 label_fill_descr(label_str, 0, hfinfo, val_str, out);
8387                 }
8388         }
8389         else if (IS_BASE_PORT(hfinfo->display)) {
8390                 gchar tmp[ITEM_LABEL_LENGTH];
8391
8392                 port_with_resolution_to_str_buf(tmp, sizeof(tmp),
8393                         display_to_port_type((field_display_e)hfinfo->display), value);
8394                 label_fill(label_str, 0, hfinfo, tmp);
8395         }
8396         else {
8397                 out = hfinfo_number_value_format(hfinfo, buf, value);
8398
8399                 label_fill(label_str, 0, hfinfo, out);
8400         }
8401 }
8402
8403 static void
8404 fill_label_number64(field_info *fi, gchar *label_str, gboolean is_signed)
8405 {
8406         header_field_info *hfinfo = fi->hfinfo;
8407         guint64            value;
8408
8409         char               buf[48];
8410         const char        *out;
8411
8412         if (is_signed)
8413                 value = fvalue_get_sinteger64(&fi->value);
8414         else
8415                 value = fvalue_get_uinteger64(&fi->value);
8416
8417         /* Fill in the textual info */
8418         if (hfinfo->display == BASE_CUSTOM) {
8419                 gchar tmp[ITEM_LABEL_LENGTH];
8420                 const custom_fmt_func_64_t fmtfunc64 = (const custom_fmt_func_64_t)hfinfo->strings;
8421
8422                 DISSECTOR_ASSERT(fmtfunc64);
8423                 fmtfunc64(tmp, value);
8424                 label_fill(label_str, 0, hfinfo, tmp);
8425         }
8426         else if (hfinfo->strings) {
8427                 const char *val_str = hf_try_val64_to_str_const(value, hfinfo, "Unknown");
8428
8429                 out = hfinfo_number_vals_format64(hfinfo, buf, value);
8430                 if (out == NULL) /* BASE_NONE so don't put integer in descr */
8431                         label_fill(label_str, 0, hfinfo, val_str);
8432                 else
8433                         label_fill_descr(label_str, 0, hfinfo, val_str, out);
8434         }
8435         else {
8436                 out = hfinfo_number_value_format64(hfinfo, buf, value);
8437
8438                 label_fill(label_str, 0, hfinfo, out);
8439         }
8440 }
8441
8442 int
8443 hfinfo_bitshift(const header_field_info *hfinfo)
8444 {
8445         return ws_ctz(hfinfo->bitmask);
8446 }
8447
8448 static int
8449 hfinfo_mask_bitwidth(const header_field_info *hfinfo)
8450 {
8451         if (!hfinfo->bitmask) {
8452                 return 0;
8453         }
8454
8455         /* ilog2 = first set bit, ctz = last set bit */
8456         return ws_ilog2(hfinfo->bitmask) - ws_ctz(hfinfo->bitmask) + 1;
8457 }
8458
8459 static int
8460 hfinfo_type_bitwidth(enum ftenum type)
8461 {
8462         int bitwidth = 0;
8463
8464         switch (type) {
8465                 case FT_CHAR:
8466                 case FT_UINT8:
8467                 case FT_INT8:
8468                         bitwidth = 8;
8469                         break;
8470                 case FT_UINT16:
8471                 case FT_INT16:
8472                         bitwidth = 16;
8473                         break;
8474                 case FT_UINT24:
8475                 case FT_INT24:
8476                         bitwidth = 24;
8477                         break;
8478                 case FT_UINT32:
8479                 case FT_INT32:
8480                         bitwidth = 32;
8481                         break;
8482                 case FT_UINT40:
8483                 case FT_INT40:
8484                         bitwidth = 40;
8485                         break;
8486                 case FT_UINT48:
8487                 case FT_INT48:
8488                         bitwidth = 48;
8489                         break;
8490                 case FT_UINT56:
8491                 case FT_INT56:
8492                         bitwidth = 56;
8493                         break;
8494                 case FT_UINT64:
8495                 case FT_INT64:
8496                         bitwidth = 64;
8497                         break;
8498                 default:
8499                         DISSECTOR_ASSERT_NOT_REACHED();
8500                         ;
8501         }
8502         return bitwidth;
8503 }
8504
8505
8506 static int
8507 hfinfo_container_bitwidth(const header_field_info *hfinfo)
8508 {
8509         if (!hfinfo->bitmask) {
8510                 return 0;
8511         }
8512
8513         if (hfinfo->type == FT_BOOLEAN) {
8514                 return hfinfo->display; /* hacky? :) */
8515         }
8516
8517         return hfinfo_type_bitwidth(hfinfo->type);
8518 }
8519
8520 static int
8521 hfinfo_hex_digits(const header_field_info *hfinfo)
8522 {
8523         int bitwidth;
8524
8525         /* If we have a bitmask, hfinfo->type is the width of the container, so not
8526          * appropriate to determine the number of hex digits for the field.
8527          * So instead, we compute it from the bitmask.
8528          */
8529         if (hfinfo->bitmask != 0) {
8530                 bitwidth = hfinfo_mask_bitwidth(hfinfo);
8531         } else {
8532                 bitwidth = hfinfo_type_bitwidth(hfinfo->type);
8533         }
8534
8535         /* Divide by 4, rounding up, to get number of hex digits. */
8536         return (bitwidth + 3) / 4;
8537 }
8538
8539 static const char *
8540 hfinfo_char_value_format_display(int display, char buf[7], guint32 value)
8541 {
8542         char *ptr = &buf[6];
8543         static const gchar hex_digits[16] =
8544         { '0', '1', '2', '3', '4', '5', '6', '7',
8545           '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
8546
8547         *ptr = '\0';
8548         *(--ptr) = '\'';
8549         /* Properly format value */
8550         if (g_ascii_isprint(value)) {
8551                 /*
8552                  * Printable, so just show the character, and, if it needs
8553                  * to be escaped, escape it.
8554                  */
8555                 *(--ptr) = value;
8556                 if (value == '\\' || value == '\'')
8557                         *(--ptr) = '\\';
8558         } else {
8559                 /*
8560                  * Non-printable; show it as an escape sequence.
8561                  */
8562                 switch (value) {
8563
8564                 case '\0':
8565                         /*
8566                          * Show a NUL with only one digit.
8567                          */
8568                         *(--ptr) = '0';
8569                         break;
8570
8571                 case '\a':
8572                         *(--ptr) = 'a';
8573                         break;
8574
8575                 case '\b':
8576                         *(--ptr) = 'b';
8577                         break;
8578
8579                 case '\f':
8580                         *(--ptr) = 'f';
8581                         break;
8582
8583                 case '\n':
8584                         *(--ptr) = 'n';
8585                         break;
8586
8587                 case '\r':
8588                         *(--ptr) = 'r';
8589                         break;
8590
8591                 case '\t':
8592                         *(--ptr) = 't';
8593                         break;
8594
8595                 case '\v':
8596                         *(--ptr) = 'v';
8597                         break;
8598
8599                 default:
8600                         switch (display & FIELD_DISPLAY_E_MASK) {
8601
8602                         case BASE_OCT:
8603                                 *(--ptr) = (value & 0x7) + '0';
8604                                 value >>= 3;
8605                                 *(--ptr) = (value & 0x7) + '0';
8606                                 value >>= 3;
8607                                 *(--ptr) = (value & 0x7) + '0';
8608                                 break;
8609
8610                         case BASE_HEX:
8611                                 *(--ptr) = hex_digits[value & 0x0F];
8612                                 value >>= 4;
8613                                 *(--ptr) = hex_digits[value & 0x0F];
8614                                 *(--ptr) = 'x';
8615                                 break;
8616
8617                         default:
8618                                 g_assert_not_reached();
8619                         }
8620                 }
8621                 *(--ptr) = '\\';
8622         }
8623         *(--ptr) = '\'';
8624         return ptr;
8625 }
8626
8627 static const char *
8628 hfinfo_number_value_format_display(const header_field_info *hfinfo, int display, char buf[32], guint32 value)
8629 {
8630         char *ptr = &buf[31];
8631         gboolean isint = IS_FT_INT(hfinfo->type);
8632
8633         *ptr = '\0';
8634         /* Properly format value */
8635         switch (display & FIELD_DISPLAY_E_MASK) {
8636                 case BASE_DEC:
8637                         return isint ? int_to_str_back(ptr, (gint32) value) : uint_to_str_back(ptr, value);
8638
8639                 case BASE_DEC_HEX:
8640                         *(--ptr) = ')';
8641                         ptr = hex_to_str_back(ptr, hfinfo_hex_digits(hfinfo), value);
8642                         *(--ptr) = '(';
8643                         *(--ptr) = ' ';
8644                         ptr = isint ? int_to_str_back(ptr, (gint32) value) : uint_to_str_back(ptr, value);
8645                         return ptr;
8646
8647                 case BASE_OCT:
8648                         return oct_to_str_back(ptr, value);
8649
8650                 case BASE_HEX:
8651                         return hex_to_str_back(ptr, hfinfo_hex_digits(hfinfo), value);
8652
8653                 case BASE_HEX_DEC:
8654                         *(--ptr) = ')';
8655                         ptr = isint ? int_to_str_back(ptr, (gint32) value) : uint_to_str_back(ptr, value);
8656                         *(--ptr) = '(';
8657                         *(--ptr) = ' ';
8658                         ptr = hex_to_str_back(ptr, hfinfo_hex_digits(hfinfo), value);
8659                         return ptr;
8660
8661                 case BASE_PT_UDP:
8662                 case BASE_PT_TCP:
8663                 case BASE_PT_DCCP:
8664                 case BASE_PT_SCTP:
8665                         port_with_resolution_to_str_buf(buf, 32,
8666                                         display_to_port_type((field_display_e)display), value);
8667                         return buf;
8668
8669                 default:
8670                         g_assert_not_reached();
8671         }
8672         return ptr;
8673 }
8674
8675 static const char *
8676 hfinfo_number_value_format_display64(const header_field_info *hfinfo, int display, char buf[48], guint64 value)
8677 {
8678         char *ptr = &buf[47];
8679         gboolean isint = IS_FT_INT(hfinfo->type);
8680
8681         *ptr = '\0';
8682         /* Properly format value */
8683                 switch (display) {
8684                         case BASE_DEC:
8685                                 return isint ? int64_to_str_back(ptr, (gint64) value) : uint64_to_str_back(ptr, value);
8686
8687                         case BASE_DEC_HEX:
8688                                 *(--ptr) = ')';
8689                                 ptr = hex64_to_str_back(ptr, hfinfo_hex_digits(hfinfo), value);
8690                                 *(--ptr) = '(';
8691                                 *(--ptr) = ' ';
8692                                 ptr = isint ? int64_to_str_back(ptr, (gint64) value) : uint64_to_str_back(ptr, value);
8693                                 return ptr;
8694
8695                         case BASE_OCT:
8696                                 return oct64_to_str_back(ptr, value);
8697
8698                         case BASE_HEX:
8699                                 return hex64_to_str_back(ptr, hfinfo_hex_digits(hfinfo), value);
8700
8701                         case BASE_HEX_DEC:
8702                                 *(--ptr) = ')';
8703                                 ptr = isint ? int64_to_str_back(ptr, (gint64) value) : uint64_to_str_back(ptr, value);
8704                                 *(--ptr) = '(';
8705                                 *(--ptr) = ' ';
8706                                 ptr = hex64_to_str_back(ptr, hfinfo_hex_digits(hfinfo), value);
8707                                 return ptr;
8708
8709                         default:
8710                                 g_assert_not_reached();
8711                 }
8712         return ptr;
8713 }
8714
8715 static const char *
8716 hfinfo_number_value_format(const header_field_info *hfinfo, char buf[32], guint32 value)
8717 {
8718         int display = hfinfo->display;
8719
8720         if (hfinfo->type == FT_FRAMENUM) {
8721                 /*
8722                  * Frame numbers are always displayed in decimal.
8723                  */
8724                 display = BASE_DEC;
8725         }
8726
8727         return hfinfo_number_value_format_display(hfinfo, display, buf, value);
8728 }
8729
8730 static const char *
8731 hfinfo_number_value_format64(const header_field_info *hfinfo, char buf[64], guint64 value)
8732 {
8733         int display = hfinfo->display;
8734
8735         if (hfinfo->type == FT_FRAMENUM) {
8736                 /*
8737                  * Frame numbers are always displayed in decimal.
8738                  */
8739                 display = BASE_DEC;
8740         }
8741
8742         return hfinfo_number_value_format_display64(hfinfo, display, buf, value);
8743 }
8744
8745 static const char *
8746 hfinfo_char_value_format(const header_field_info *hfinfo, char buf[32], guint32 value)
8747 {
8748         /* Get the underlying BASE_ value */
8749         int display = hfinfo->display & FIELD_DISPLAY_E_MASK;
8750
8751         return hfinfo_char_value_format_display(display, buf, value);
8752 }
8753
8754 static const char *
8755 hfinfo_numeric_value_format(const header_field_info *hfinfo, char buf[32], guint32 value)
8756 {
8757         /* Get the underlying BASE_ value */
8758         int display = hfinfo->display & FIELD_DISPLAY_E_MASK;
8759
8760         if (hfinfo->type == FT_FRAMENUM) {
8761                 /*
8762                  * Frame numbers are always displayed in decimal.
8763                  */
8764                 display = BASE_DEC;
8765         }
8766
8767         if (IS_BASE_PORT(display)) {
8768                 display = BASE_DEC;
8769         }
8770
8771         switch (display) {
8772                 case BASE_NONE:
8773                 /* case BASE_DEC: */
8774                 case BASE_DEC_HEX:
8775                 case BASE_OCT: /* XXX, why we're changing BASE_OCT to BASE_DEC? */
8776                 case BASE_CUSTOM:
8777                         display = BASE_DEC;
8778                         break;
8779
8780                 /* case BASE_HEX: */
8781                 case BASE_HEX_DEC:
8782                         display = BASE_HEX;
8783                         break;
8784         }
8785
8786         return hfinfo_number_value_format_display(hfinfo, display, buf, value);
8787 }
8788
8789 static const char *
8790 hfinfo_numeric_value_format64(const header_field_info *hfinfo, char buf[64], guint64 value)
8791 {
8792         /* Get the underlying BASE_ value */
8793         int display = hfinfo->display & FIELD_DISPLAY_E_MASK;
8794
8795         if (hfinfo->type == FT_FRAMENUM) {
8796                 /*
8797                  * Frame numbers are always displayed in decimal.
8798                  */
8799                 display = BASE_DEC;
8800         }
8801
8802         switch (display) {
8803                 case BASE_NONE:
8804                 /* case BASE_DEC: */
8805                 case BASE_DEC_HEX:
8806                 case BASE_OCT: /* XXX, why we're changing BASE_OCT to BASE_DEC? */
8807                 case BASE_CUSTOM:
8808                         display = BASE_DEC;
8809                         break;
8810
8811                 /* case BASE_HEX: */
8812                 case BASE_HEX_DEC:
8813                         display = BASE_HEX;
8814                         break;
8815         }
8816
8817         return hfinfo_number_value_format_display64(hfinfo, display, buf, value);
8818 }
8819
8820 static const char *
8821 hfinfo_char_vals_format(const header_field_info *hfinfo, char buf[32], guint32 value)
8822 {
8823         /* Get the underlying BASE_ value */
8824         int display = hfinfo->display & FIELD_DISPLAY_E_MASK;
8825
8826         return hfinfo_char_value_format_display(display, buf, value);
8827 }
8828
8829 static const char *
8830 hfinfo_number_vals_format(const header_field_info *hfinfo, char buf[32], guint32 value)
8831 {
8832         /* Get the underlying BASE_ value */
8833         int display = hfinfo->display & FIELD_DISPLAY_E_MASK;
8834
8835         if (display == BASE_NONE)
8836                 return NULL;
8837
8838         if (display == BASE_DEC_HEX)
8839                 display = BASE_DEC;
8840         if (display == BASE_HEX_DEC)
8841                 display = BASE_HEX;
8842
8843         return hfinfo_number_value_format_display(hfinfo, display, buf, value);
8844 }
8845
8846 static const char *
8847 hfinfo_number_vals_format64(const header_field_info *hfinfo, char buf[64], guint64 value)
8848 {
8849         /* Get the underlying BASE_ value */
8850         int display = hfinfo->display & FIELD_DISPLAY_E_MASK;
8851
8852         if (display == BASE_NONE)
8853                 return NULL;
8854
8855         if (display == BASE_DEC_HEX)
8856                 display = BASE_DEC;
8857         if (display == BASE_HEX_DEC)
8858                 display = BASE_HEX;
8859
8860         return hfinfo_number_value_format_display64(hfinfo, display, buf, value);
8861 }
8862
8863 const char *
8864 proto_registrar_get_name(const int n)
8865 {
8866         header_field_info *hfinfo;
8867
8868         PROTO_REGISTRAR_GET_NTH(n, hfinfo);
8869         return hfinfo->name;
8870 }
8871
8872 const char *
8873 proto_registrar_get_abbrev(const int n)
8874 {
8875         header_field_info *hfinfo;
8876
8877         PROTO_REGISTRAR_GET_NTH(n, hfinfo);
8878         return hfinfo->abbrev;
8879 }
8880
8881 enum ftenum
8882 proto_registrar_get_ftype(const int n)
8883 {
8884         header_field_info *hfinfo;
8885
8886         PROTO_REGISTRAR_GET_NTH(n, hfinfo);
8887         return hfinfo->type;
8888 }
8889
8890 int
8891 proto_registrar_get_parent(const int n)
8892 {
8893         header_field_info *hfinfo;
8894
8895         PROTO_REGISTRAR_GET_NTH(n, hfinfo);
8896         return hfinfo->parent;
8897 }
8898
8899 gboolean
8900 proto_registrar_is_protocol(const int n)
8901 {
8902         header_field_info *hfinfo;
8903
8904         PROTO_REGISTRAR_GET_NTH(n, hfinfo);
8905         return (((hfinfo->id != hf_text_only) && (hfinfo->parent == -1)) ? TRUE : FALSE);
8906 }
8907
8908 /* Returns length of field in packet (not necessarily the length
8909  * in our internal representation, as in the case of IPv4).
8910  * 0 means undeterminable at time of registration
8911  * -1 means the field is not registered. */
8912 gint
8913 proto_registrar_get_length(const int n)
8914 {
8915         header_field_info *hfinfo;
8916
8917         PROTO_REGISTRAR_GET_NTH(n, hfinfo);
8918         return ftype_length(hfinfo->type);
8919 }
8920
8921 /* Looks for a protocol or a field in a proto_tree. Returns TRUE if
8922  * it exists anywhere, or FALSE if it exists nowhere. */
8923 gboolean
8924 proto_check_for_protocol_or_field(const proto_tree* tree, const int id)
8925 {
8926         GPtrArray *ptrs = proto_get_finfo_ptr_array(tree, id);
8927
8928         if (g_ptr_array_len(ptrs) > 0) {
8929                 return TRUE;
8930         }
8931         else {
8932                 return FALSE;
8933         }
8934 }
8935
8936 /* Return GPtrArray* of field_info pointers for all hfindex that appear in tree.
8937  * This only works if the hfindex was "primed" before the dissection
8938  * took place, as we just pass back the already-created GPtrArray*.
8939  * The caller should *not* free the GPtrArray*; proto_tree_free_node()
8940  * handles that. */
8941 GPtrArray *
8942 proto_get_finfo_ptr_array(const proto_tree *tree, const int id)
8943 {
8944         if (!tree)
8945                 return NULL;
8946
8947         if (PTREE_DATA(tree)->interesting_hfids != NULL)
8948                 return (GPtrArray *)g_hash_table_lookup(PTREE_DATA(tree)->interesting_hfids,
8949                                            GINT_TO_POINTER(id));
8950         else
8951                 return NULL;
8952 }
8953
8954 gboolean
8955 proto_tracking_interesting_fields(const proto_tree *tree)
8956 {
8957         GHashTable *interesting_hfids;
8958
8959         if (!tree)
8960                 return FALSE;
8961
8962         interesting_hfids = PTREE_DATA(tree)->interesting_hfids;
8963
8964         return (interesting_hfids != NULL) && g_hash_table_size(interesting_hfids);
8965 }
8966
8967 /* Helper struct for proto_find_info() and      proto_all_finfos() */
8968 typedef struct {
8969         GPtrArray *array;
8970         int        id;
8971 } ffdata_t;
8972
8973 /* Helper function for proto_find_info() */
8974 static gboolean
8975 find_finfo(proto_node *node, gpointer data)
8976 {
8977         field_info *fi = PNODE_FINFO(node);
8978         if (fi && fi->hfinfo) {
8979                 if (fi->hfinfo->id == ((ffdata_t*)data)->id) {
8980                         g_ptr_array_add(((ffdata_t*)data)->array, fi);
8981                 }
8982         }
8983
8984         /* Don't stop traversing. */
8985         return FALSE;
8986 }
8987
8988 /* Helper function for proto_find_first_info() */
8989 static gboolean
8990 find_first_finfo(proto_node *node, gpointer data)
8991 {
8992         field_info *fi = PNODE_FINFO(node);
8993         if (fi && fi->hfinfo) {
8994                 if (fi->hfinfo->id == ((ffdata_t*)data)->id) {
8995                         g_ptr_array_add(((ffdata_t*)data)->array, fi);
8996                 }
8997         }
8998
8999         /* Stop traversing. */
9000         return TRUE;
9001 }
9002
9003 /* Return GPtrArray* of field_info pointers for all hfindex that appear in a tree.
9004 * This works on any proto_tree, primed or unprimed, but actually searches
9005 * the tree, so it is slower than using proto_get_finfo_ptr_array on a primed tree.
9006 * The caller does need to free the returned GPtrArray with
9007 * g_ptr_array_free(<array>, TRUE).
9008 */
9009 GPtrArray *
9010 proto_find_finfo(proto_tree *tree, const int id)
9011 {
9012         ffdata_t ffdata;
9013
9014         ffdata.array = g_ptr_array_new();
9015         ffdata.id = id;
9016
9017         proto_tree_traverse_pre_order(tree, find_finfo, &ffdata);
9018
9019         return ffdata.array;
9020 }
9021
9022 /* Return GPtrArray* of first field_info pointers for the searched hfindex that appear in a tree.
9023 * This works on any proto_tree, primed or unprimed, but actually searches
9024 * the tree, so it is slower than using proto_get_finfo_ptr_array on a primed tree.
9025 * The caller does need to free the returned GPtrArray with
9026 * g_ptr_array_free(<array>, TRUE).
9027 */
9028 GPtrArray *
9029 proto_find_first_finfo(proto_tree *tree, const int id)
9030 {
9031         ffdata_t ffdata;
9032
9033         ffdata.array = g_ptr_array_new();
9034         ffdata.id = id;
9035
9036         proto_tree_traverse_pre_order(tree, find_first_finfo, &ffdata);
9037
9038         return ffdata.array;
9039 }
9040
9041 /* Helper function for proto_all_finfos() */
9042 static gboolean
9043 every_finfo(proto_node *node, gpointer data)
9044 {
9045         field_info *fi = PNODE_FINFO(node);
9046         if (fi && fi->hfinfo) {
9047                 g_ptr_array_add(((ffdata_t*)data)->array, fi);
9048         }
9049
9050         /* Don't stop traversing. */
9051         return FALSE;
9052 }
9053
9054 /* Return GPtrArray* of field_info pointers containing all hfindexes that appear in a tree. */
9055 GPtrArray *
9056 proto_all_finfos(proto_tree *tree)
9057 {
9058         ffdata_t ffdata;
9059
9060         /* Pre allocate enough space to hold all fields in most cases */
9061         ffdata.array = g_ptr_array_sized_new(512);
9062         ffdata.id = 0;
9063
9064         proto_tree_traverse_pre_order(tree, every_finfo, &ffdata);
9065
9066         return ffdata.array;
9067 }
9068
9069
9070 typedef struct {
9071         guint       offset;
9072         field_info *finfo;
9073         tvbuff_t   *tvb;
9074 } offset_search_t;
9075
9076 static gboolean
9077 check_for_offset(proto_node *node, gpointer data)
9078 {
9079         field_info      *fi        = PNODE_FINFO(node);
9080         offset_search_t *offsearch = (offset_search_t *)data;
9081
9082         /* !fi == the top most container node which holds nothing */
9083         if (fi && !PROTO_ITEM_IS_HIDDEN(node) && !PROTO_ITEM_IS_GENERATED(node) && fi->ds_tvb && offsearch->tvb == fi->ds_tvb) {
9084                 if (offsearch->offset >= (guint) fi->start &&
9085                                 offsearch->offset < (guint) (fi->start + fi->length)) {
9086
9087                         offsearch->finfo = fi;
9088                         return FALSE; /* keep traversing */
9089                 }
9090         }
9091         return FALSE; /* keep traversing */
9092 }
9093
9094 /* Search a proto_tree backwards (from leaves to root) looking for the field
9095  * whose start/length occupies 'offset' */
9096 /* XXX - I couldn't find an easy way to search backwards, so I search
9097  * forwards, w/o stopping. Therefore, the last finfo I find will the be
9098  * the one I want to return to the user. This algorithm is inefficient
9099  * and could be re-done, but I'd have to handle all the children and
9100  * siblings of each node myself. When I have more time I'll do that.
9101  * (yeah right) */
9102 field_info *
9103 proto_find_field_from_offset(proto_tree *tree, guint offset, tvbuff_t *tvb)
9104 {
9105         offset_search_t offsearch;
9106
9107         offsearch.offset = offset;
9108         offsearch.finfo  = NULL;
9109         offsearch.tvb    = tvb;
9110
9111         proto_tree_traverse_pre_order(tree, check_for_offset, &offsearch);
9112
9113         return offsearch.finfo;
9114 }
9115
9116
9117 static gboolean
9118 check_for_undecoded(proto_node *node, gpointer data)
9119 {
9120         field_info *fi = PNODE_FINFO(node);
9121         gchar* decoded = (gchar*)data;
9122         gint i;
9123         guint byte;
9124         guint bit;
9125
9126         if (fi && fi->hfinfo->type != FT_PROTOCOL) {
9127                 for (i = fi->start; i < fi->start + fi->length; i++) {
9128                         byte = i / 8;
9129                         bit = i % 8;
9130                         decoded[byte] |= (1 << bit);
9131                 }
9132         }
9133
9134         return FALSE;
9135 }
9136
9137 gchar*
9138 proto_find_undecoded_data(proto_tree *tree, guint length)
9139 {
9140         gchar* decoded = (gchar*)wmem_alloc0(wmem_packet_scope(), length / 8 + 1);
9141
9142         proto_tree_traverse_pre_order(tree, check_for_undecoded, decoded);
9143         return decoded;
9144 }
9145
9146 /* Dumps the protocols in the registration database to stdout.  An independent
9147  * program can take this output and format it into nice tables or HTML or
9148  * whatever.
9149  *
9150  * There is one record per line. The fields are tab-delimited.
9151  *
9152  * Field 1 = protocol name
9153  * Field 2 = protocol short name
9154  * Field 3 = protocol filter name
9155  */
9156 void
9157 proto_registrar_dump_protocols(void)
9158 {
9159         protocol_t *protocol;
9160         int         i;
9161         void       *cookie = NULL;
9162
9163
9164         i = proto_get_first_protocol(&cookie);
9165         while (i != -1) {
9166                 protocol = find_protocol_by_id(i);
9167                 ws_debug_printf("%s\t%s\t%s\n", protocol->name, protocol->short_name,
9168                         protocol->filter_name);
9169                 i = proto_get_next_protocol(&cookie);
9170         }
9171 }
9172
9173 /* Dumps the value_strings, extended value string headers, range_strings
9174  * or true/false strings for fields that have them.
9175  * There is one record per line. Fields are tab-delimited.
9176  * There are four types of records: Value String, Extended Value String Header,
9177  * Range String and True/False String. The first field, 'V', 'E', 'R' or 'T', indicates
9178  * the type of record.
9179  *
9180  * Note that a record will be generated only if the value_string,... is referenced
9181  * in a registered hfinfo entry.
9182  *
9183  *
9184  * Value Strings
9185  * -------------
9186  * Field 1 = 'V'
9187  * Field 2 = Field abbreviation to which this value string corresponds
9188  * Field 3 = Integer value
9189  * Field 4 = String
9190  *
9191  * Extended Value String Headers
9192  * -----------------------------
9193  * Field 1 = 'E'
9194  * Field 2 = Field abbreviation to which this extended value string header corresponds
9195  * Field 3 = Extended Value String "Name"
9196  * Field 4 = Number of entries in the associated value_string array
9197  * Field 5 = Access Type: "Linear Search", "Binary Search", "Direct (indexed) Access"
9198  *
9199  * Range Strings
9200  * -------------
9201  * Field 1 = 'R'
9202  * Field 2 = Field abbreviation to which this range string corresponds
9203  * Field 3 = Integer value: lower bound
9204  * Field 4 = Integer value: upper bound
9205  * Field 5 = String
9206  *
9207  * True/False Strings
9208  * ------------------
9209  * Field 1 = 'T'
9210  * Field 2 = Field abbreviation to which this true/false string corresponds
9211  * Field 3 = True String
9212  * Field 4 = False String
9213  */
9214 void
9215 proto_registrar_dump_values(void)
9216 {
9217         header_field_info       *hfinfo;
9218         int                     i, len, vi;
9219         const value_string      *vals;
9220         const val64_string      *vals64;
9221         const range_string      *range;
9222         const true_false_string *tfs;
9223         const unit_name_string  *units;
9224
9225         len = gpa_hfinfo.len;
9226         for (i = 0; i < len ; i++) {
9227                 if (gpa_hfinfo.hfi[i] == NULL)
9228                         continue; /* This is a deregistered protocol or field */
9229
9230                 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
9231
9232                  if (hfinfo->id == hf_text_only) {
9233                          continue;
9234                  }
9235
9236                 /* ignore protocols */
9237                 if (proto_registrar_is_protocol(i)) {
9238                         continue;
9239                 }
9240                 /* process header fields */
9241 #if 0 /* XXX: We apparently allow fields with the same name but with differing "strings" content */
9242                 /*
9243                  * If this field isn't at the head of the list of
9244                  * fields with this name, skip this field - all
9245                  * fields with the same name are really just versions
9246                  * of the same field stored in different bits, and
9247                  * should have the same type/radix/value list, and
9248                  * just differ in their bit masks.      (If a field isn't
9249                  * a bitfield, but can be, say, 1 or 2 bytes long,
9250                  * it can just be made FT_UINT16, meaning the
9251                  * *maximum* length is 2 bytes, and be used
9252                  * for all lengths.)
9253                  */
9254                 if (hfinfo->same_name_prev_id != -1)
9255                         continue;
9256 #endif
9257                 vals   = NULL;
9258                 vals64 = NULL;
9259                 range  = NULL;
9260                 tfs    = NULL;
9261                 units  = NULL;
9262
9263                 if (hfinfo->strings != NULL) {
9264                         if ((hfinfo->display & FIELD_DISPLAY_E_MASK) != BASE_CUSTOM &&
9265                             (hfinfo->type == FT_CHAR  ||
9266                              hfinfo->type == FT_UINT8  ||
9267                              hfinfo->type == FT_UINT16 ||
9268                              hfinfo->type == FT_UINT24 ||
9269                              hfinfo->type == FT_UINT32 ||
9270                              hfinfo->type == FT_UINT40 ||
9271                              hfinfo->type == FT_UINT48 ||
9272                              hfinfo->type == FT_UINT56 ||
9273                              hfinfo->type == FT_UINT64 ||
9274                              hfinfo->type == FT_INT8   ||
9275                              hfinfo->type == FT_INT16  ||
9276                              hfinfo->type == FT_INT24  ||
9277                              hfinfo->type == FT_INT32  ||
9278                              hfinfo->type == FT_INT40  ||
9279                              hfinfo->type == FT_INT48  ||
9280                              hfinfo->type == FT_INT56  ||
9281                              hfinfo->type == FT_INT64)) {
9282
9283                                 if (hfinfo->display & BASE_RANGE_STRING) {
9284                                         range = (const range_string *)hfinfo->strings;
9285                                 } else if (hfinfo->display & BASE_EXT_STRING) {
9286                                         vals = VALUE_STRING_EXT_VS_P((value_string_ext *)hfinfo->strings);
9287                                 } else if (hfinfo->display & BASE_VAL64_STRING) {
9288                                         vals64 = (const val64_string *)hfinfo->strings;
9289                                 } else if (hfinfo->display & BASE_UNIT_STRING) {
9290                                         units = (const unit_name_string *)hfinfo->strings;
9291                                 } else {
9292                                         vals = (const value_string *)hfinfo->strings;
9293                                 }
9294                         }
9295                         else if (hfinfo->type == FT_BOOLEAN) {
9296                                 tfs = (const struct true_false_string *)hfinfo->strings;
9297                         }
9298                 }
9299
9300                 /* Print value strings? */
9301                 if (vals) {
9302                         if (hfinfo->display & BASE_EXT_STRING) {
9303                                 value_string_ext *vse_p = (value_string_ext *)hfinfo->strings;
9304                                 if (!value_string_ext_validate(vse_p)) {
9305                                         ws_g_warning("Invalid value_string_ext ptr for: %s", hfinfo->abbrev);
9306                                         continue;
9307                                 }
9308                                 try_val_to_str_ext(0, vse_p); /* "prime" the extended value_string */
9309                                 ws_debug_printf("E\t%s\t%u\t%s\t%s\n",
9310                                        hfinfo->abbrev,
9311                                        VALUE_STRING_EXT_VS_NUM_ENTRIES(vse_p),
9312                                        VALUE_STRING_EXT_VS_NAME(vse_p),
9313                                        value_string_ext_match_type_str(vse_p));
9314                         }
9315                         vi = 0;
9316                         while (vals[vi].strptr) {
9317                                 /* Print in the proper base */
9318                                 if (hfinfo->type == FT_CHAR) {
9319                                         if (g_ascii_isprint(vals[vi].value)) {
9320                                                 ws_debug_printf("V\t%s\t'%c'\t%s\n",
9321                                                        hfinfo->abbrev,
9322                                                        vals[vi].value,
9323                                                        vals[vi].strptr);
9324                                         } else {
9325                                                 if (hfinfo->display == BASE_HEX) {
9326                                                         ws_debug_printf("V\t%s\t'\\x%02x'\t%s\n",
9327                                                                hfinfo->abbrev,
9328                                                                vals[vi].value,
9329                                                                vals[vi].strptr);
9330                                                 }
9331                                                 else {
9332                                                         ws_debug_printf("V\t%s\t'\\%03o'\t%s\n",
9333                                                                hfinfo->abbrev,
9334                                                                vals[vi].value,
9335                                                                vals[vi].strptr);
9336                                                 }
9337                                         }
9338                                 } else {
9339                                         if (hfinfo->display == BASE_HEX) {
9340                                                 ws_debug_printf("V\t%s\t0x%x\t%s\n",
9341                                                        hfinfo->abbrev,
9342                                                        vals[vi].value,
9343                                                        vals[vi].strptr);
9344                                         }
9345                                         else {
9346                                                 ws_debug_printf("V\t%s\t%u\t%s\n",
9347                                                        hfinfo->abbrev,
9348                                                        vals[vi].value,
9349                                                        vals[vi].strptr);
9350                                         }
9351                                 }
9352                                 vi++;
9353                         }
9354                 }
9355                 else if (vals64) {
9356                         vi = 0;
9357                         while (vals64[vi].strptr) {
9358                                 ws_debug_printf("V64\t%s\t%" G_GINT64_MODIFIER "u\t%s\n",
9359                                        hfinfo->abbrev,
9360                                        vals64[vi].value,
9361                                        vals64[vi].strptr);
9362                                 vi++;
9363                         }
9364                 }
9365
9366                 /* print range strings? */
9367                 else if (range) {
9368                         vi = 0;
9369                         while (range[vi].strptr) {
9370                                 /* Print in the proper base */
9371                                 if ((hfinfo->display & FIELD_DISPLAY_E_MASK) == BASE_HEX) {
9372                                         ws_debug_printf("R\t%s\t0x%x\t0x%x\t%s\n",
9373                                                hfinfo->abbrev,
9374                                                range[vi].value_min,
9375                                                range[vi].value_max,
9376                                                range[vi].strptr);
9377                                 }
9378                                 else {
9379                                         ws_debug_printf("R\t%s\t%u\t%u\t%s\n",
9380                                                hfinfo->abbrev,
9381                                                range[vi].value_min,
9382                                                range[vi].value_max,
9383                                                range[vi].strptr);
9384                                 }
9385                                 vi++;
9386                         }
9387                 }
9388
9389                 /* Print true/false strings? */
9390                 else if (tfs) {
9391                         ws_debug_printf("T\t%s\t%s\t%s\n", hfinfo->abbrev,
9392                                tfs->true_string, tfs->false_string);
9393                 }
9394                 /* Print unit strings? */
9395                 else if (units) {
9396                         ws_debug_printf("U\t%s\t%s\t%s\n", hfinfo->abbrev,
9397                                units->singular, units->plural ? units->plural : "(no plural)");
9398                 }
9399         }
9400 }
9401
9402 /* Prints the number of registered fields.
9403  * Useful for determining an appropriate value for
9404  * PROTO_PRE_ALLOC_HF_FIELDS_MEM.
9405  *
9406  * Returns FALSE if PROTO_PRE_ALLOC_HF_FIELDS_MEM is larger than or equal to
9407  * the number of fields, TRUE otherwise.
9408  */
9409 gboolean
9410 proto_registrar_dump_fieldcount(void)
9411 {
9412         guint32                 i;
9413         header_field_info       *hfinfo;
9414         guint32                 deregistered_count = 0;
9415         guint32                 same_name_count = 0;
9416         guint32                 protocol_count = 0;
9417
9418         for (i = 0; i < gpa_hfinfo.len; i++) {
9419                 if (gpa_hfinfo.hfi[i] == NULL) {
9420                         deregistered_count++;
9421                         continue; /* This is a deregistered protocol or header field */
9422                 }
9423
9424                 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
9425
9426                 if (proto_registrar_is_protocol(i))
9427                         protocol_count++;
9428
9429                 if (hfinfo->same_name_prev_id != -1)
9430                         same_name_count++;
9431         }
9432
9433         ws_debug_printf("There are %u header fields registered, of which:\n"
9434                 "\t%u are deregistered\n"
9435                 "\t%u are protocols\n"
9436                 "\t%u have the same name as another field\n\n",
9437                 gpa_hfinfo.len, deregistered_count, protocol_count,
9438                 same_name_count);
9439
9440         ws_debug_printf("%d fields were pre-allocated.\n%s", PROTO_PRE_ALLOC_HF_FIELDS_MEM,
9441                 (gpa_hfinfo.allocated_len > PROTO_PRE_ALLOC_HF_FIELDS_MEM) ?
9442                     "* * Please increase PROTO_PRE_ALLOC_HF_FIELDS_MEM (in epan/proto.c)! * *\n\n" :
9443                     "\n");
9444
9445         ws_debug_printf("The header field table consumes %u KiB of memory.\n",
9446                 (unsigned int)(gpa_hfinfo.allocated_len * sizeof(header_field_info *) / 1024));
9447         ws_debug_printf("The fields themselves consume %u KiB of memory.\n",
9448                 (unsigned int)(gpa_hfinfo.len * sizeof(header_field_info) / 1024));
9449
9450         return (gpa_hfinfo.allocated_len > PROTO_PRE_ALLOC_HF_FIELDS_MEM);
9451 }
9452
9453
9454 /* Dumps the contents of the registration database to stdout. An independent
9455  * program can take this output and format it into nice tables or HTML or
9456  * whatever.
9457  *
9458  * There is one record per line. Each record is either a protocol or a header
9459  * field, differentiated by the first field. The fields are tab-delimited.
9460  *
9461  * Protocols
9462  * ---------
9463  * Field 1 = 'P'
9464  * Field 2 = descriptive protocol name
9465  * Field 3 = protocol abbreviation
9466  *
9467  * Header Fields
9468  * -------------
9469  * Field 1 = 'F'
9470  * Field 2 = descriptive field name
9471  * Field 3 = field abbreviation
9472  * Field 4 = type ( textual representation of the the ftenum type )
9473  * Field 5 = parent protocol abbreviation
9474  * Field 6 = base for display (for integer types); "parent bitfield width" for FT_BOOLEAN
9475  * Field 7 = bitmask: format: hex: 0x....
9476  * Field 8 = blurb describing field
9477  */
9478 void
9479 proto_registrar_dump_fields(void)
9480 {
9481         header_field_info *hfinfo, *parent_hfinfo;
9482         int                i, len;
9483         const char        *enum_name;
9484         const char        *base_name;
9485         const char        *blurb;
9486         char               width[5];
9487
9488         len = gpa_hfinfo.len;
9489         for (i = 0; i < len ; i++) {
9490                 if (gpa_hfinfo.hfi[i] == NULL)
9491                         continue; /* This is a deregistered protocol or header field */
9492
9493                 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
9494
9495                 /*
9496                  * Skip the pseudo-field for "proto_tree_add_text()" since
9497                  * we don't want it in the list of filterable fields.
9498                  */
9499                 if (hfinfo->id == hf_text_only)
9500                         continue;
9501
9502                 /* format for protocols */
9503                 if (proto_registrar_is_protocol(i)) {
9504                         ws_debug_printf("P\t%s\t%s\n", hfinfo->name, hfinfo->abbrev);
9505                 }
9506                 /* format for header fields */
9507                 else {
9508                         /*
9509                          * If this field isn't at the head of the list of
9510                          * fields with this name, skip this field - all
9511                          * fields with the same name are really just versions
9512                          * of the same field stored in different bits, and
9513                          * should have the same type/radix/value list, and
9514                          * just differ in their bit masks.      (If a field isn't
9515                          * a bitfield, but can be, say, 1 or 2 bytes long,
9516                          * it can just be made FT_UINT16, meaning the
9517                          * *maximum* length is 2 bytes, and be used
9518                          * for all lengths.)
9519                          */
9520                         if (hfinfo->same_name_prev_id != -1)
9521                                 continue;
9522
9523                         PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
9524
9525                         enum_name = ftype_name(hfinfo->type);
9526                         base_name = "";
9527
9528                         if (hfinfo->type == FT_CHAR  ||
9529                             hfinfo->type == FT_UINT8  ||
9530                             hfinfo->type == FT_UINT16 ||
9531                             hfinfo->type == FT_UINT24 ||
9532                             hfinfo->type == FT_UINT32 ||
9533                             hfinfo->type == FT_UINT40 ||
9534                             hfinfo->type == FT_UINT48 ||
9535                             hfinfo->type == FT_UINT56 ||
9536                             hfinfo->type == FT_UINT64 ||
9537                             hfinfo->type == FT_INT8   ||
9538                             hfinfo->type == FT_INT16  ||
9539                             hfinfo->type == FT_INT24  ||
9540                             hfinfo->type == FT_INT32  ||
9541                             hfinfo->type == FT_INT40 ||
9542                             hfinfo->type == FT_INT48 ||
9543                             hfinfo->type == FT_INT56 ||
9544                             hfinfo->type == FT_INT64) {
9545
9546                                 switch (FIELD_DISPLAY(hfinfo->display)) {
9547                                         case BASE_NONE:
9548                                         case BASE_DEC:
9549                                         case BASE_HEX:
9550                                         case BASE_OCT:
9551                                         case BASE_DEC_HEX:
9552                                         case BASE_HEX_DEC:
9553                                         case BASE_CUSTOM:
9554                                         case BASE_PT_UDP:
9555                                         case BASE_PT_TCP:
9556                                         case BASE_PT_DCCP:
9557                                         case BASE_PT_SCTP:
9558                                                 base_name = val_to_str_const(FIELD_DISPLAY(hfinfo->display), hf_display, "????");
9559                                                 break;
9560                                         default:
9561                                                 base_name = "????";
9562                                                 break;
9563                                 }
9564                         } else if (hfinfo->type == FT_BOOLEAN) {
9565                                 /* For FT_BOOLEAN: 'display' can be "parent bitfield width" */
9566                                 g_snprintf(width, sizeof(width), "%d", hfinfo->display);
9567                                 base_name = width;
9568                         }
9569
9570                         blurb = hfinfo->blurb;
9571                         if (blurb == NULL)
9572                                 blurb = "";
9573                         else if (strlen(blurb) == 0)
9574                                 blurb = "\"\"";
9575
9576                         ws_debug_printf("F\t%s\t%s\t%s\t%s\t%s\t0x%" G_GINT64_MODIFIER "x\t%s\n",
9577                                 hfinfo->name, hfinfo->abbrev, enum_name,
9578                                 parent_hfinfo->abbrev, base_name,
9579                                 hfinfo->bitmask, blurb);
9580                 }
9581         }
9582 }
9583
9584 /* Dumps field types and descriptive names to stdout. An independent
9585  * program can take this output and format it into nice tables or HTML or
9586  * whatever.
9587  *
9588  * There is one record per line. The fields are tab-delimited.
9589  *
9590  * Field 1 = field type name, e.g. FT_UINT8
9591  * Field 2 = descriptive name, e.g. "Unsigned, 1 byte"
9592  */
9593 void
9594 proto_registrar_dump_ftypes(void)
9595 {
9596         int fte;
9597
9598         for (fte = 0; fte < FT_NUM_TYPES; fte++) {
9599                 ws_debug_printf("%s\t%s\n", ftype_name((ftenum_t)fte), ftype_pretty_name((ftenum_t)fte));
9600         }
9601 }
9602
9603 /* This function indicates whether it's possible to construct a
9604  * "match selected" display filter string for the specified field,
9605  * returns an indication of whether it's possible, and, if it's
9606  * possible and "filter" is non-null, constructs the filter and
9607  * sets "*filter" to point to it.
9608  * You do not need to [g_]free() this string since it will be automatically
9609  * freed once the next packet is dissected.
9610  */
9611 static gboolean
9612 construct_match_selected_string(field_info *finfo, epan_dissect_t *edt,
9613                                 char **filter)
9614 {
9615         header_field_info *hfinfo;
9616         int                abbrev_len;
9617         char              *ptr;
9618         int                buf_len;
9619         int                dfilter_len, i;
9620         gint               start, length, length_remaining;
9621         guint8             c;
9622         gchar              is_signed_num = FALSE;
9623
9624         if (!finfo)
9625                 return FALSE;
9626
9627         hfinfo     = finfo->hfinfo;
9628         DISSECTOR_ASSERT(hfinfo);
9629         abbrev_len = (int) strlen(hfinfo->abbrev);
9630
9631         if (hfinfo->strings && (hfinfo->display & FIELD_DISPLAY_E_MASK) == BASE_NONE) {
9632                 const gchar *str = NULL;
9633
9634                 switch (hfinfo->type) {
9635
9636                 case FT_INT8:
9637                 case FT_INT16:
9638                 case FT_INT24:
9639                 case FT_INT32:
9640                         str = hf_try_val_to_str(fvalue_get_sinteger(&finfo->value), hfinfo);
9641                         break;
9642
9643                 case FT_CHAR:
9644                 case FT_UINT8:
9645                 case FT_UINT16:
9646                 case FT_UINT24:
9647                 case FT_UINT32:
9648                         str = hf_try_val_to_str(fvalue_get_uinteger(&finfo->value), hfinfo);
9649                         break;
9650
9651                 default:
9652                         break;
9653                 }
9654
9655                 if (str != NULL && filter != NULL) {
9656                         *filter = wmem_strdup_printf(NULL, "%s == \"%s\"", hfinfo->abbrev, str);
9657                         return TRUE;
9658                 }
9659         }
9660
9661         /*
9662          * XXX - we can't use the "val_to_string_repr" and "string_repr_len"
9663          * functions for FT_UINT and FT_INT types, as we choose the base in
9664          * the string expression based on the display base of the field.
9665          *
9666          * Note that the base does matter, as this is also used for
9667          * the protocolinfo tap.
9668          *
9669          * It might be nice to use them in "proto_item_fill_label()"
9670          * as well, although, there, you'd have to deal with the base
9671          * *and* with resolved values for addresses.
9672          *
9673          * Perhaps we need two different val_to_string routines, one
9674          * to generate items for display filters and one to generate
9675          * strings for display, and pass to both of them the
9676          * "display" and "strings" values in the header_field_info
9677          * structure for the field, so they can get the base and,
9678          * if the field is Boolean or an enumerated integer type,
9679          * the tables used to generate human-readable values.
9680          */
9681         switch (hfinfo->type) {
9682
9683                 case FT_CHAR:
9684                         if (filter != NULL) {
9685                                 guint32 number;
9686
9687                                 char buf [48];
9688                                 const char *out;
9689
9690                                 number = fvalue_get_uinteger(&finfo->value);
9691
9692                                 out = hfinfo_char_value_format(hfinfo, buf, number);
9693
9694                                 *filter = wmem_strdup_printf(NULL, "%s == %s", hfinfo->abbrev, out);
9695                         }
9696                         break;
9697
9698                 case FT_INT8:
9699                 case FT_INT16:
9700                 case FT_INT24:
9701                 case FT_INT32:
9702                         is_signed_num = TRUE;
9703                         /* FALLTHRU */
9704                 case FT_UINT8:
9705                 case FT_UINT16:
9706                 case FT_UINT24:
9707                 case FT_UINT32:
9708                 case FT_FRAMENUM:
9709                         if (filter != NULL) {
9710                                 guint32 number;
9711
9712                                 char buf[32];
9713                                 const char *out;
9714
9715                                 if (is_signed_num)
9716                                         number = fvalue_get_sinteger(&finfo->value);
9717                                 else
9718                                         number = fvalue_get_uinteger(&finfo->value);
9719
9720                                 out = hfinfo_numeric_value_format(hfinfo, buf, number);
9721
9722                                 *filter = wmem_strdup_printf(NULL, "%s == %s", hfinfo->abbrev, out);
9723                         }
9724                         break;
9725
9726                 case FT_INT40:
9727                 case FT_INT48:
9728                 case FT_INT56:
9729                 case FT_INT64:
9730                         is_signed_num = TRUE;
9731                         /* FALLTHRU */
9732                 case FT_UINT40:
9733                 case FT_UINT48:
9734                 case FT_UINT56:
9735                 case FT_UINT64:
9736                         if (filter != NULL) {
9737                                 guint64 number;
9738
9739                                 char buf [48];
9740                                 const char *out;
9741
9742                                 if (is_signed_num)
9743                                         number = fvalue_get_sinteger64(&finfo->value);
9744                                 else
9745                                         number = fvalue_get_uinteger64(&finfo->value);
9746
9747                                 out = hfinfo_numeric_value_format64(hfinfo, buf, number);
9748
9749                                 *filter = wmem_strdup_printf(NULL, "%s == %s", hfinfo->abbrev, out);
9750                         }
9751                         break;
9752
9753                 case FT_PROTOCOL:
9754                         if (filter != NULL)
9755                                 *filter = wmem_strdup(NULL, finfo->hfinfo->abbrev);
9756                         break;
9757
9758                 case FT_NONE:
9759                         /*
9760                          * If the length is 0, just match the name of the
9761                          * field.
9762                          *
9763                          * (Also check for negative values, just in case,
9764                          * as we'll cast it to an unsigned value later.)
9765                          */
9766                         length = finfo->length;
9767                         if (length == 0) {
9768                                 if (filter != NULL)
9769                                         *filter = wmem_strdup(NULL, finfo->hfinfo->abbrev);
9770                                 break;
9771                         }
9772                         if (length < 0)
9773                                 return FALSE;
9774
9775                         /*
9776                          * This doesn't have a value, so we'd match
9777                          * on the raw bytes at this address.
9778                          *
9779                          * Should we be allowed to access to the raw bytes?
9780                          * If "edt" is NULL, the answer is "no".
9781                          */
9782                         if (edt == NULL)
9783                                 return FALSE;
9784
9785                         /*
9786                          * Is this field part of the raw frame tvbuff?
9787                          * If not, we can't use "frame[N:M]" to match
9788                          * it.
9789                          *
9790                          * XXX - should this be frame-relative, or
9791                          * protocol-relative?
9792                          *
9793                          * XXX - does this fallback for non-registered
9794                          * fields even make sense?
9795                          */
9796                         if (finfo->ds_tvb != edt->tvb)
9797                                 return FALSE;   /* you lose */
9798
9799                         /*
9800                          * Don't go past the end of that tvbuff.
9801                          */
9802                         length_remaining = tvb_captured_length_remaining(finfo->ds_tvb, finfo->start);
9803                         if (length > length_remaining)
9804                                 length = length_remaining;
9805                         if (length <= 0)
9806                                 return FALSE;
9807
9808                         if (filter != NULL) {
9809                                 start = finfo->start;
9810                                 buf_len = 32 + length * 3;
9811                                 *filter = (char *)wmem_alloc0(NULL, buf_len);
9812                                 ptr = *filter;
9813
9814                                 ptr += g_snprintf(ptr, (gulong) (buf_len-(ptr-*filter)),
9815                                         "frame[%d:%d] == ", finfo->start, length);
9816                                 for (i=0; i<length; i++) {
9817                                         c = tvb_get_guint8(finfo->ds_tvb, start);
9818                                         start++;
9819                                         if (i == 0 ) {
9820                                                 ptr += g_snprintf(ptr, (gulong) (buf_len-(ptr-*filter)), "%02x", c);
9821                                         }
9822                                         else {
9823                                                 ptr += g_snprintf(ptr, (gulong) (buf_len-(ptr-*filter)), ":%02x", c);
9824                                         }
9825                                 }
9826                         }
9827                         break;
9828
9829                 case FT_PCRE:
9830                         /* FT_PCRE never appears as a type for a registered field. It is
9831                          * only used internally. */
9832                         DISSECTOR_ASSERT_NOT_REACHED();
9833                         break;
9834
9835                 /* By default, use the fvalue's "to_string_repr" method. */
9836                 default:
9837                         /* Figure out the string length needed.
9838                          *      The ft_repr length.
9839                          *      4 bytes for " == ".
9840                          *      1 byte for trailing NUL.
9841                          */
9842                         if (filter != NULL) {
9843                                 char* str;
9844                                 dfilter_len = fvalue_string_repr_len(&finfo->value,
9845                                                 FTREPR_DFILTER, finfo->hfinfo->display);
9846                                 dfilter_len += abbrev_len + 4 + 1;
9847                                 *filter = (char *)wmem_alloc0(NULL, dfilter_len);
9848
9849                                 /* Create the string */
9850                                 str = fvalue_to_string_repr(NULL, &finfo->value, FTREPR_DFILTER, finfo->hfinfo->display);
9851                                 g_snprintf(*filter, dfilter_len, "%s == %s", hfinfo->abbrev, str);
9852                                 wmem_free(NULL, str);
9853                         }
9854                         break;
9855         }
9856
9857         return TRUE;
9858 }
9859
9860 /*
9861  * Returns TRUE if we can do a "match selected" on the field, FALSE
9862  * otherwise.
9863  */
9864 gboolean
9865 proto_can_match_selected(field_info *finfo, epan_dissect_t *edt)
9866 {
9867         return construct_match_selected_string(finfo, edt, NULL);
9868 }
9869
9870 /* This function attempts to construct a "match selected" display filter
9871  * string for the specified field; if it can do so, it returns a pointer
9872  * to the string, otherwise it returns NULL.
9873  *
9874  * The string is allocated with packet lifetime scope.
9875  * You do not need to [g_]free() this string since it will be automatically
9876  * freed once the next packet is dissected.
9877  */
9878 char *
9879 proto_construct_match_selected_string(field_info *finfo, epan_dissect_t *edt)
9880 {
9881         char *filter = NULL;
9882
9883         if (!construct_match_selected_string(finfo, edt, &filter))
9884         {
9885                 wmem_free(NULL, filter);
9886                 return NULL;
9887         }
9888         return filter;
9889 }
9890
9891 /* This function is common code for all proto_tree_add_bitmask... functions.
9892  */
9893
9894 static gboolean
9895 proto_item_add_bitmask_tree(proto_item *item, tvbuff_t *tvb, const int offset,
9896                             const int len, const gint ett, const int **fields,
9897                             const int flags, gboolean first,
9898                             gboolean use_parent_tree,
9899                             proto_tree* tree, guint64 value)
9900 {
9901         guint              bitshift;
9902         guint64            available_bits = 0;
9903         guint64            tmpval;
9904         header_field_info *hf;
9905         guint32            integer32;
9906         gint               no_of_bits;
9907
9908         if (len < 0 || len > 8)
9909                 g_assert_not_reached();
9910         bitshift = (8 - (guint)len)*8;
9911         available_bits = G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF) >> bitshift;
9912
9913         if (use_parent_tree == FALSE)
9914                 tree = proto_item_add_subtree(item, ett);
9915
9916         while (*fields) {
9917                 guint64 present_bits;
9918                 PROTO_REGISTRAR_GET_NTH(**fields,hf);
9919                 DISSECTOR_ASSERT_HINT(hf->bitmask != 0, hf->abbrev);
9920
9921                 /* Skip fields that aren't fully present */
9922                 present_bits = available_bits & hf->bitmask;
9923                 if (present_bits != hf->bitmask) {
9924                         fields++;
9925                         continue;
9926                 }
9927
9928                 switch (hf->type) {
9929                 case FT_CHAR:
9930                 case FT_UINT8:
9931                 case FT_UINT16:
9932                 case FT_UINT24:
9933                 case FT_UINT32:
9934                         proto_tree_add_uint(tree, **fields, tvb, offset, len, (guint32)value);
9935                         break;
9936
9937                 case FT_INT8:
9938                 case FT_INT16:
9939                 case FT_INT24:
9940                 case FT_INT32:
9941                         proto_tree_add_int(tree, **fields, tvb, offset, len, (gint32)value);
9942                         break;
9943
9944                 case FT_UINT40:
9945                 case FT_UINT48:
9946                 case FT_UINT56:
9947                 case FT_UINT64:
9948                         proto_tree_add_uint64(tree, **fields, tvb, offset, len, value);
9949                         break;
9950
9951                 case FT_INT40:
9952                 case FT_INT48:
9953                 case FT_INT56:
9954                 case FT_INT64:
9955                         proto_tree_add_int64(tree, **fields, tvb, offset, len, (gint64)value);
9956                         break;
9957
9958                 case FT_BOOLEAN:
9959                         proto_tree_add_boolean64(tree, **fields, tvb, offset, len, value);
9960                         break;
9961
9962                 default:
9963                         DISSECTOR_ASSERT_NOT_REACHED();
9964                         break;
9965                 }
9966                 if (flags & BMT_NO_APPEND) {
9967                         fields++;
9968                         continue;
9969                 }
9970                 tmpval = (value & hf->bitmask) >> hfinfo_bitshift(hf);
9971
9972                 switch (hf->type) {
9973                 case FT_CHAR:
9974                         if (hf->display == BASE_CUSTOM) {
9975                                 gchar lbl[ITEM_LABEL_LENGTH];
9976                                 const custom_fmt_func_t fmtfunc = (const custom_fmt_func_t)hf->strings;
9977
9978                                 DISSECTOR_ASSERT(fmtfunc);
9979                                 fmtfunc(lbl, (guint32) tmpval);
9980                                 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
9981                                                 hf->name, lbl);
9982                                 first = FALSE;
9983                         }
9984                         else if (hf->strings) {
9985                                 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
9986                                                        hf->name, hf_try_val_to_str_const((guint32) tmpval, hf, "Unknown"));
9987                                 first = FALSE;
9988                         }
9989                         else if (!(flags & BMT_NO_INT)) {
9990                                 char buf[32];
9991                                 const char *out;
9992
9993                                 if (!first) {
9994                                         proto_item_append_text(item, ", ");
9995                                 }
9996
9997                                 out = hfinfo_char_value_format(hf, buf, (guint32) tmpval);
9998                                 proto_item_append_text(item, "%s: %s", hf->name, out);
9999                                 first = FALSE;
10000                         }
10001
10002                         break;
10003
10004                 case FT_UINT8:
10005                 case FT_UINT16:
10006                 case FT_UINT24:
10007                 case FT_UINT32:
10008                         if (hf->display == BASE_CUSTOM) {
10009                                 gchar lbl[ITEM_LABEL_LENGTH];
10010                                 const custom_fmt_func_t fmtfunc = (const custom_fmt_func_t)hf->strings;
10011
10012                                 DISSECTOR_ASSERT(fmtfunc);
10013                                 fmtfunc(lbl, (guint32) tmpval);
10014                                 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
10015                                                 hf->name, lbl);
10016                                 first = FALSE;
10017                         }
10018                         else if ((hf->strings) &&(!(hf->display & BASE_UNIT_STRING))) {
10019                                 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
10020                                                                                 hf->name, hf_try_val_to_str_const((guint32) tmpval, hf, "Unknown"));
10021                                 first = FALSE;
10022                         }
10023                         else if (!(flags & BMT_NO_INT)) {
10024                                 char buf[32];
10025                                 const char *out;
10026
10027                                 if (!first) {
10028                                         proto_item_append_text(item, ", ");
10029                                 }
10030
10031                                 out = hfinfo_number_value_format(hf, buf, (guint32) tmpval);
10032                                 if (hf->display & BASE_UNIT_STRING) {
10033                                         proto_item_append_text(item, "%s: %s%s", hf->name, out, unit_name_string_get_value((guint32) tmpval, (unit_name_string*)hf->strings));
10034                                 } else {
10035                                         proto_item_append_text(item, "%s: %s", hf->name, out);
10036                                 }
10037                                 first = FALSE;
10038                         }
10039
10040                         break;
10041
10042                 case FT_INT8:
10043                 case FT_INT16:
10044                 case FT_INT24:
10045                 case FT_INT32:
10046                         integer32 = (guint32) tmpval;
10047                         if (hf->bitmask) {
10048                                 no_of_bits = ws_count_ones(hf->bitmask);
10049                                 integer32 = ws_sign_ext32(integer32, no_of_bits);
10050                         }
10051                         if (hf->display == BASE_CUSTOM) {
10052                                 gchar lbl[ITEM_LABEL_LENGTH];
10053                                 const custom_fmt_func_t fmtfunc = (const custom_fmt_func_t)hf->strings;
10054
10055                                 DISSECTOR_ASSERT(fmtfunc);
10056                                 fmtfunc(lbl, (gint32) integer32);
10057                                 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
10058                                                 hf->name, lbl);
10059                                 first = FALSE;
10060                         }
10061                         else if ((hf->strings) &&(!(hf->display & BASE_UNIT_STRING))) {
10062                                 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
10063                                                 hf->name, hf_try_val_to_str_const((gint32) integer32, hf, "Unknown"));
10064                                 first = FALSE;
10065                         }
10066                         else if (!(flags & BMT_NO_INT)) {
10067                                 char buf[32];
10068                                 const char *out;
10069
10070                                 if (!first) {
10071                                         proto_item_append_text(item, ", ");
10072                                 }
10073
10074                                 out = hfinfo_number_value_format(hf, buf, (gint32) integer32);
10075                                 if ((hf->strings) &&(!(hf->display & BASE_UNIT_STRING))) {
10076                                         proto_item_append_text(item, "%s: %s%s", hf->name, out, unit_name_string_get_value((guint32) tmpval, (unit_name_string*)hf->strings));
10077                                 } else {
10078                                         proto_item_append_text(item, "%s: %s", hf->name, out);
10079                                 }
10080                                 first = FALSE;
10081                         }
10082
10083                         break;
10084
10085                 case FT_UINT40:
10086                 case FT_UINT48:
10087                 case FT_UINT56:
10088                 case FT_UINT64:
10089                         if (hf->display == BASE_CUSTOM) {
10090                                 gchar lbl[ITEM_LABEL_LENGTH];
10091                                 const custom_fmt_func_64_t fmtfunc = (const custom_fmt_func_64_t)hf->strings;
10092
10093                                 DISSECTOR_ASSERT(fmtfunc);
10094                                 fmtfunc(lbl, tmpval);
10095                                 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
10096                                                 hf->name, lbl);
10097                                 first = FALSE;
10098                         }
10099                         else if (hf->strings) {
10100                                 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
10101                                                 hf->name, hf_try_val64_to_str_const(tmpval, hf, "Unknown"));
10102                                 first = FALSE;
10103                         }
10104                         else if (!(flags & BMT_NO_INT)) {
10105                                 char buf[48];
10106                                 const char *out;
10107
10108                                 if (!first) {
10109                                         proto_item_append_text(item, ", ");
10110                                 }
10111
10112                                 out = hfinfo_number_value_format64(hf, buf, tmpval);
10113                                 proto_item_append_text(item, "%s: %s", hf->name, out);
10114                                 first = FALSE;
10115                         }
10116
10117                         break;
10118
10119                 case FT_INT40:
10120                 case FT_INT48:
10121                 case FT_INT56:
10122                 case FT_INT64:
10123                         if (hf->bitmask) {
10124                                 no_of_bits = ws_count_ones(hf->bitmask);
10125                                 tmpval = ws_sign_ext64(tmpval, no_of_bits);
10126                         }
10127                         if (hf->display == BASE_CUSTOM) {
10128                                 gchar lbl[ITEM_LABEL_LENGTH];
10129                                 const custom_fmt_func_64_t fmtfunc = (const custom_fmt_func_64_t)hf->strings;
10130
10131                                 DISSECTOR_ASSERT(fmtfunc);
10132                                 fmtfunc(lbl, (gint64) tmpval);
10133                                 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
10134                                                 hf->name, lbl);
10135                                 first = FALSE;
10136                         }
10137                         else if (hf->strings) {
10138                                 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
10139                                                 hf->name, hf_try_val64_to_str_const((gint64) tmpval, hf, "Unknown"));
10140                                 first = FALSE;
10141                         }
10142                         else if (!(flags & BMT_NO_INT)) {
10143                                 char buf[48];
10144                                 const char *out;
10145
10146                                 if (!first) {
10147                                         proto_item_append_text(item, ", ");
10148                                 }
10149
10150                                 out = hfinfo_number_value_format64(hf, buf, (gint64) tmpval);
10151                                 proto_item_append_text(item, "%s: %s", hf->name, out);
10152                                 first = FALSE;
10153                         }
10154
10155                         break;
10156
10157                 case FT_BOOLEAN:
10158                         if (hf->strings && !(flags & BMT_NO_TFS)) {
10159                                 /* If we have true/false strings, emit full - otherwise messages
10160                                    might look weird */
10161                                 const struct true_false_string *tfs =
10162                                         (const struct true_false_string *)hf->strings;
10163
10164                                 if (tmpval) {
10165                                         proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
10166                                                         hf->name, tfs->true_string);
10167                                         first = FALSE;
10168                                 } else if (!(flags & BMT_NO_FALSE)) {
10169                                         proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
10170                                                         hf->name, tfs->false_string);
10171                                         first = FALSE;
10172                                 }
10173                         } else if (hf->bitmask & value) {
10174                                 /* If the flag is set, show the name */
10175                                 proto_item_append_text(item, "%s%s", first ? "" : ", ", hf->name);
10176                                 first = FALSE;
10177                         }
10178                         break;
10179                 default:
10180                         DISSECTOR_ASSERT_NOT_REACHED();
10181                         break;
10182                 }
10183
10184                 fields++;
10185         }
10186
10187         return first;
10188 }
10189
10190 /* This function will dissect a sequence of bytes that describe a
10191  * bitmask and supply the value of that sequence through a pointer.
10192  * hf_hdr is a 8/16/24/32/40/48/56/64 bit integer that describes the bitmask
10193  * to be dissected.
10194  * This field will form an expansion under which the individual fields of the
10195  * bitmask is dissected and displayed.
10196  * This field must be of the type FT_[U]INT{8|16|24|32|40|48|56|64}.
10197  *
10198  * fields is an array of pointers to int that lists all the fields of the
10199  * bitmask. These fields can be either of the type FT_BOOLEAN for flags
10200  * or another integer of the same type/size as hf_hdr with a mask specified.
10201  * This array is terminated by a NULL entry.
10202  *
10203  * FT_BOOLEAN bits that are set to 1 will have the name added to the expansion.
10204  * FT_integer fields that have a value_string attached will have the
10205  * matched string displayed on the expansion line.
10206  */
10207 proto_item *
10208 proto_tree_add_bitmask_ret_uint64(proto_tree *parent_tree, tvbuff_t *tvb,
10209                        const guint offset, const int hf_hdr,
10210                        const gint ett, const int **fields,
10211                        const guint encoding, guint64 *retval)
10212 {
10213         return proto_tree_add_bitmask_with_flags_ret_uint64(parent_tree, tvb, offset, hf_hdr, ett, fields, encoding, BMT_NO_INT|BMT_NO_TFS, retval);
10214 }
10215
10216 /* This function will dissect a sequence of bytes that describe a
10217  * bitmask.
10218  * hf_hdr is a 8/16/24/32/40/48/56/64 bit integer that describes the bitmask
10219  * to be dissected.
10220  * This field will form an expansion under which the individual fields of the
10221  * bitmask is dissected and displayed.
10222  * This field must be of the type FT_[U]INT{8|16|24|32|40|48|56|64}.
10223  *
10224  * fields is an array of pointers to int that lists all the fields of the
10225  * bitmask. These fields can be either of the type FT_BOOLEAN for flags
10226  * or another integer of the same type/size as hf_hdr with a mask specified.
10227  * This array is terminated by a NULL entry.
10228  *
10229  * FT_BOOLEAN bits that are set to 1 will have the name added to the expansion.
10230  * FT_integer fields that have a value_string attached will have the
10231  * matched string displayed on the expansion line.
10232  */
10233 proto_item *
10234 proto_tree_add_bitmask(proto_tree *parent_tree, tvbuff_t *tvb,
10235                        const guint offset, const int hf_hdr,
10236                        const gint ett, const int **fields,
10237                        const guint encoding)
10238 {
10239         return proto_tree_add_bitmask_with_flags(parent_tree, tvb, offset, hf_hdr, ett, fields, encoding, BMT_NO_INT|BMT_NO_TFS);
10240 }
10241
10242 /* The same as proto_tree_add_bitmask_ret_uint64(), but uses user-supplied flags to determine
10243  * what data is appended to the header.
10244  */
10245 proto_item *
10246 proto_tree_add_bitmask_with_flags_ret_uint64(proto_tree *parent_tree, tvbuff_t *tvb, const guint offset,
10247                 const int hf_hdr, const gint ett, const int **fields, const guint encoding, const int flags,
10248                 guint64 *retval)
10249 {
10250         proto_item        *item = NULL;
10251         header_field_info *hf;
10252         int                len;
10253         guint64            value;
10254
10255         PROTO_REGISTRAR_GET_NTH(hf_hdr,hf);
10256         DISSECTOR_ASSERT_FIELD_TYPE_IS_INTEGRAL(hf);
10257         len = ftype_length(hf->type);
10258         value = get_uint64_value(parent_tree, tvb, offset, len, encoding);
10259
10260         if (parent_tree) {
10261                 item = proto_tree_add_item(parent_tree, hf_hdr, tvb, offset, len, encoding);
10262                 proto_item_add_bitmask_tree(item, tvb, offset, len, ett, fields,
10263                     flags, FALSE, FALSE, NULL, value);
10264         }
10265
10266         *retval = value;
10267         if (hf->bitmask) {
10268                 /* Mask out irrelevant portions */
10269                 *retval &= hf->bitmask;
10270                 /* Shift bits */
10271                 *retval >>= hfinfo_bitshift(hf);
10272         }
10273
10274         return item;
10275 }
10276
10277 /* The same as proto_tree_add_bitmask_ret_uint64(), but uses user-supplied flags to determine
10278  * what data is appended to the header.
10279  */
10280 proto_item *
10281 proto_tree_add_bitmask_with_flags(proto_tree *parent_tree, tvbuff_t *tvb, const guint offset,
10282                 const int hf_hdr, const gint ett, const int **fields, const guint encoding, const int flags)
10283 {
10284         proto_item        *item = NULL;
10285         header_field_info *hf;
10286         int                len;
10287         guint64            value;
10288
10289         PROTO_REGISTRAR_GET_NTH(hf_hdr,hf);
10290         DISSECTOR_ASSERT_FIELD_TYPE_IS_INTEGRAL(hf);
10291
10292         if (parent_tree) {
10293                 len = ftype_length(hf->type);
10294                 item = proto_tree_add_item(parent_tree, hf_hdr, tvb, offset, len, encoding);
10295                 value = get_uint64_value(parent_tree, tvb, offset, len, encoding);
10296                 proto_item_add_bitmask_tree(item, tvb, offset, len, ett, fields,
10297                     flags, FALSE, FALSE, NULL, value);
10298         }
10299
10300         return item;
10301 }
10302
10303 /* Similar to proto_tree_add_bitmask(), but with a passed in value (presumably because it
10304    can't be retrieved directly from tvb) */
10305 proto_item *
10306 proto_tree_add_bitmask_value(proto_tree *parent_tree, tvbuff_t *tvb, const guint offset,
10307                 const int hf_hdr, const gint ett, const int **fields, const guint64 value)
10308 {
10309         return proto_tree_add_bitmask_value_with_flags(parent_tree, tvb, offset,
10310                                                 hf_hdr, ett, fields, value, BMT_NO_INT|BMT_NO_TFS);
10311 }
10312
10313 /* Similar to proto_tree_add_bitmask_value(), but with control of flag values */
10314 WS_DLL_PUBLIC proto_item *
10315 proto_tree_add_bitmask_value_with_flags(proto_tree *parent_tree, tvbuff_t *tvb, const guint offset,
10316                 const int hf_hdr, const gint ett, const int **fields, const guint64 value, const int flags)
10317 {
10318         proto_item        *item = NULL;
10319         header_field_info *hf;
10320         int                len;
10321
10322         PROTO_REGISTRAR_GET_NTH(hf_hdr,hf);
10323         DISSECTOR_ASSERT_FIELD_TYPE_IS_INTEGRAL(hf);
10324         /* the proto_tree_add_uint/_uint64() calls below
10325            will fail if tvb==NULL and len!=0 */
10326         len = tvb ? ftype_length(hf->type) : 0;
10327
10328         if (parent_tree) {
10329                 if (len <= 4)
10330                         item = proto_tree_add_uint(parent_tree, hf_hdr, tvb, offset, len, (guint32)value);
10331                 else
10332                         item = proto_tree_add_uint64(parent_tree, hf_hdr, tvb, offset, len, value);
10333
10334                 proto_item_add_bitmask_tree(item, tvb, offset, len, ett, fields,
10335                     flags, FALSE, FALSE, NULL, value);
10336         }
10337
10338         return item;
10339 }
10340
10341 /* Similar to proto_tree_add_bitmask(), but with no "header" item to group all of the fields */
10342 void
10343 proto_tree_add_bitmask_list(proto_tree *tree, tvbuff_t *tvb, const guint offset,
10344                                                                 const int len, const int **fields, const guint encoding)
10345 {
10346         guint64 value;
10347
10348         if (tree) {
10349                 value = get_uint64_value(tree, tvb, offset, len, encoding);
10350                 proto_item_add_bitmask_tree(NULL, tvb, offset, len, -1, fields,
10351                     BMT_NO_APPEND, FALSE, TRUE, tree, value);
10352         }
10353 }
10354
10355 WS_DLL_PUBLIC void
10356 proto_tree_add_bitmask_list_value(proto_tree *tree, tvbuff_t *tvb, const guint offset,
10357                                                                 const int len, const int **fields, const guint64 value)
10358 {
10359         if (tree) {
10360                 proto_item_add_bitmask_tree(NULL, tvb, offset, len, -1, fields,
10361                     BMT_NO_APPEND, FALSE, TRUE, tree, value);
10362         }
10363 }
10364
10365
10366 /* The same as proto_tree_add_bitmask(), but using a caller-supplied length.
10367  * This is intended to support bitmask fields whose lengths can vary, perhaps
10368  * as the underlying standard evolves over time.
10369  * With this API there is the possibility of being called to display more or
10370  * less data than the dissector was coded to support.
10371  * In such cases, it is assumed that bitmasks are extended on the MSb end.
10372  * Thus when presented with "too much" or "too little" data, MSbits will be
10373  * ignored or MSfields sacrificed.
10374  *
10375  * Only fields for which all defined bits are available are displayed.
10376  */
10377 proto_item *
10378 proto_tree_add_bitmask_len(proto_tree *parent_tree, tvbuff_t *tvb,
10379                        const guint offset,  const guint len, const int hf_hdr,
10380                        const gint ett, const int **fields, struct expert_field* exp,
10381                        const guint encoding)
10382 {
10383         proto_item        *item = NULL;
10384         header_field_info *hf;
10385         guint   decodable_len;
10386         guint   decodable_offset;
10387         guint32 decodable_value;
10388         guint64 value;
10389
10390         PROTO_REGISTRAR_GET_NTH(hf_hdr, hf);
10391         DISSECTOR_ASSERT_FIELD_TYPE_IS_INTEGRAL(hf);
10392
10393         decodable_offset = offset;
10394         decodable_len = MIN(len, (guint) ftype_length(hf->type));
10395
10396         /* If we are ftype_length-limited,
10397          * make sure we decode as many LSBs as possible.
10398          */
10399         if (encoding == ENC_BIG_ENDIAN) {
10400                 decodable_offset += (len - decodable_len);
10401         }
10402
10403         if (parent_tree) {
10404                 decodable_value = get_uint_value(parent_tree, tvb, decodable_offset,
10405                                                  decodable_len, encoding);
10406
10407                 /* The root item covers all the bytes even if we can't decode them all */
10408                 item = proto_tree_add_uint(parent_tree, hf_hdr, tvb, offset, len,
10409                                            decodable_value);
10410         }
10411
10412         if (decodable_len < len) {
10413                 /* Dissector likely requires updating for new protocol revision */
10414                 expert_add_info_format(NULL, item, exp,
10415                                        "Only least-significant %d of %d bytes decoded",
10416                                        decodable_len, len);
10417         }
10418
10419         if (item) {
10420                 value = get_uint64_value(parent_tree, tvb, decodable_offset, decodable_len, encoding);
10421                 proto_item_add_bitmask_tree(item, tvb, decodable_offset, decodable_len,
10422                     ett, fields, BMT_NO_INT|BMT_NO_TFS, FALSE, FALSE, NULL, value);
10423         }
10424
10425         return item;
10426 }
10427
10428 /* The same as proto_tree_add_bitmask(), but using an arbitrary text as a top-level item */
10429 proto_item *
10430 proto_tree_add_bitmask_text(proto_tree *parent_tree, tvbuff_t *tvb,
10431                             const guint offset, const guint len,
10432                             const char *name, const char *fallback,
10433                             const gint ett, const int **fields,
10434                             const guint encoding, const int flags)
10435 {
10436         proto_item *item = NULL;
10437         guint64     value;
10438
10439         if (parent_tree) {
10440                 item = proto_tree_add_text_internal(parent_tree, tvb, offset, len, "%s", name ? name : "");
10441                 value = get_uint64_value(parent_tree, tvb, offset, len, encoding);
10442                 if (proto_item_add_bitmask_tree(item, tvb, offset, len, ett, fields,
10443                     flags, TRUE, FALSE, NULL, value) && fallback) {
10444                         /* Still at first item - append 'fallback' text if any */
10445                         proto_item_append_text(item, "%s", fallback);
10446                 }
10447         }
10448
10449         return item;
10450 }
10451
10452 proto_item *
10453 proto_tree_add_bits_item(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
10454                          const guint bit_offset, const gint no_of_bits,
10455                          const guint encoding)
10456 {
10457         header_field_info *hfinfo;
10458         gint               octet_length;
10459         gint               octet_offset;
10460
10461         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
10462
10463         octet_length = (no_of_bits + 7) >> 3;
10464         octet_offset = bit_offset >> 3;
10465         test_length(hfinfo, tvb, octet_offset, octet_length);
10466
10467         /* Yes, we try to fake this item again in proto_tree_add_bits_ret_val()
10468          * but only after doing a bunch more work (which we can, in the common
10469          * case, shortcut here).
10470          */
10471         CHECK_FOR_NULL_TREE(tree);
10472         TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
10473
10474         return proto_tree_add_bits_ret_val(tree, hfindex, tvb, bit_offset, no_of_bits, NULL, encoding);
10475 }
10476
10477 /*
10478  * This function will dissect a sequence of bits that does not need to be byte aligned; the bits
10479  * set will be shown in the tree as ..10 10.. and the integer value returned if return_value is set.
10480  * Offset should be given in bits from the start of the tvb.
10481  */
10482
10483 static proto_item *
10484 _proto_tree_add_bits_ret_val(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
10485                             const guint bit_offset, const gint no_of_bits,
10486                             guint64 *return_value, const guint encoding)
10487 {
10488         gint     offset;
10489         guint    length;
10490         guint8   tot_no_bits;
10491         char    *bf_str;
10492         char     lbl_str[ITEM_LABEL_LENGTH];
10493         guint64  value = 0;
10494
10495         proto_item        *pi;
10496         header_field_info *hf_field;
10497
10498         const true_false_string *tfstring;
10499
10500         /* We can't fake it just yet. We have to fill in the 'return_value' parameter */
10501         PROTO_REGISTRAR_GET_NTH(hfindex, hf_field);
10502
10503         if (hf_field->bitmask != 0) {
10504                 REPORT_DISSECTOR_BUG(wmem_strdup_printf(wmem_packet_scope(),
10505                                         "Incompatible use of proto_tree_add_bits_ret_val"
10506                                         " with field '%s' (%s) with bitmask != 0",
10507                                         hf_field->abbrev, hf_field->name));
10508         }
10509
10510         DISSECTOR_ASSERT(no_of_bits >  0);
10511
10512         /* Byte align offset */
10513         offset = bit_offset>>3;
10514
10515         /*
10516          * Calculate the number of octets used to hold the bits
10517          */
10518         tot_no_bits = ((bit_offset&0x7) + no_of_bits);
10519         length = (tot_no_bits + 7) >> 3;
10520
10521         if (no_of_bits < 65) {
10522                 value = tvb_get_bits64(tvb, bit_offset, no_of_bits, encoding);
10523         } else {
10524                 DISSECTOR_ASSERT_NOT_REACHED();
10525                 return NULL;
10526         }
10527
10528         /* Sign extend for signed types */
10529         switch (hf_field->type) {
10530                 case FT_INT8:
10531                 case FT_INT16:
10532                 case FT_INT24:
10533                 case FT_INT32:
10534                 case FT_INT40:
10535                 case FT_INT48:
10536                 case FT_INT56:
10537                 case FT_INT64:
10538                         value = ws_sign_ext64(value, no_of_bits);
10539                         break;
10540
10541                 default:
10542                         break;
10543         }
10544
10545         if (return_value) {
10546                 *return_value = value;
10547         }
10548
10549         /* Coast clear. Try and fake it */
10550         CHECK_FOR_NULL_TREE(tree);
10551         TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
10552
10553         bf_str = decode_bits_in_field(bit_offset, no_of_bits, value);
10554
10555         switch (hf_field->type) {
10556         case FT_BOOLEAN:
10557                 /* Boolean field */
10558                 tfstring = (const true_false_string *) &tfs_true_false;
10559                 if (hf_field->strings)
10560                         tfstring = (const true_false_string *)hf_field->strings;
10561                 return proto_tree_add_boolean_format(tree, hfindex, tvb, offset, length, (guint32)value,
10562                         "%s = %s: %s",
10563                         bf_str, hf_field->name,
10564                         (guint64)value ? tfstring->true_string : tfstring->false_string);
10565                 break;
10566
10567         case FT_CHAR:
10568                 pi = proto_tree_add_uint(tree, hfindex, tvb, offset, length, (guint32)value);
10569                 fill_label_char(PITEM_FINFO(pi), lbl_str);
10570                 break;
10571
10572         case FT_UINT8:
10573         case FT_UINT16:
10574         case FT_UINT24:
10575         case FT_UINT32:
10576                 pi = proto_tree_add_uint(tree, hfindex, tvb, offset, length, (guint32)value);
10577                 fill_label_number(PITEM_FINFO(pi), lbl_str, FALSE);
10578                 break;
10579
10580         case FT_INT8:
10581         case FT_INT16:
10582         case FT_INT24:
10583         case FT_INT32:
10584                 pi = proto_tree_add_int(tree, hfindex, tvb, offset, length, (gint32)value);
10585                 fill_label_number(PITEM_FINFO(pi), lbl_str, TRUE);
10586                 break;
10587
10588         case FT_UINT40:
10589         case FT_UINT48:
10590         case FT_UINT56:
10591         case FT_UINT64:
10592                 pi = proto_tree_add_uint64(tree, hfindex, tvb, offset, length, value);
10593                 fill_label_number64(PITEM_FINFO(pi), lbl_str, FALSE);
10594                 break;
10595
10596         case FT_INT40:
10597         case FT_INT48:
10598         case FT_INT56:
10599         case FT_INT64:
10600                 pi = proto_tree_add_int64(tree, hfindex, tvb, offset, length, (gint64)value);
10601                 fill_label_number64(PITEM_FINFO(pi), lbl_str, TRUE);
10602                 break;
10603
10604         default:
10605                 DISSECTOR_ASSERT_NOT_REACHED();
10606                 return NULL;
10607                 break;
10608         }
10609
10610         proto_item_set_text(pi, "%s = %s", bf_str, lbl_str);
10611         return pi;
10612 }
10613
10614 proto_item *
10615 proto_tree_add_split_bits_item_ret_val(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
10616                                        const guint bit_offset, const crumb_spec_t *crumb_spec,
10617                                        guint64 *return_value)
10618 {
10619         proto_item *pi;
10620         gint        no_of_bits;
10621         gint        octet_offset;
10622         guint       mask_initial_bit_offset;
10623         guint       mask_greatest_bit_offset;
10624         guint       octet_length;
10625         guint8      i;
10626         char        bf_str[256];
10627         char        lbl_str[ITEM_LABEL_LENGTH];
10628         guint64     value;
10629         guint64     composite_bitmask;
10630         guint64     composite_bitmap;
10631
10632         header_field_info       *hf_field;
10633         const true_false_string *tfstring;
10634
10635         /* We can't fake it just yet. We have to fill in the 'return_value' parameter */
10636         PROTO_REGISTRAR_GET_NTH(hfindex, hf_field);
10637
10638         if (hf_field->bitmask != 0) {
10639                 REPORT_DISSECTOR_BUG(wmem_strdup_printf(wmem_packet_scope(),
10640                                         "Incompatible use of proto_tree_add_split_bits_item_ret_val"
10641                                         " with field '%s' (%s) with bitmask != 0",
10642                                         hf_field->abbrev, hf_field->name));
10643         }
10644
10645         mask_initial_bit_offset = bit_offset % 8;
10646
10647         no_of_bits = 0;
10648         value      = 0;
10649         i          = 0;
10650         mask_greatest_bit_offset = 0;
10651         composite_bitmask        = 0;
10652         composite_bitmap         = 0;
10653
10654         while (crumb_spec[i].crumb_bit_length != 0) {
10655                 guint64 crumb_mask, crumb_value;
10656                 guint8  crumb_end_bit_offset;
10657
10658                 DISSECTOR_ASSERT(i < 64);
10659                 crumb_value = tvb_get_bits64(tvb,
10660                                              bit_offset + crumb_spec[i].crumb_bit_offset,
10661                                              crumb_spec[i].crumb_bit_length,
10662                                              ENC_BIG_ENDIAN);
10663                 value      += crumb_value;
10664                 no_of_bits += crumb_spec[i].crumb_bit_length;
10665
10666                 /* The bitmask is 64 bit, left-aligned, starting at the first bit of the
10667                    octet containing the initial offset.
10668                    If the mask is beyond 32 bits, then give up on bit map display.
10669                    This could be improved in future, probably showing a table
10670                    of 32 or 64 bits per row */
10671                 if (mask_greatest_bit_offset < 32) {
10672                         crumb_end_bit_offset = mask_initial_bit_offset
10673                                 + crumb_spec[i].crumb_bit_offset
10674                                 + crumb_spec[i].crumb_bit_length;
10675                         crumb_mask = (G_GUINT64_CONSTANT(1) << crumb_spec[i].crumb_bit_length) - 1;
10676
10677                         if (crumb_end_bit_offset > mask_greatest_bit_offset) {
10678                                 mask_greatest_bit_offset = crumb_end_bit_offset;
10679                         }
10680                         composite_bitmask |= (crumb_mask  << (64 - crumb_end_bit_offset));
10681                         composite_bitmap  |= (crumb_value << (64 - crumb_end_bit_offset));
10682                 }
10683                 /* Shift left for the next segment */
10684                 value <<= crumb_spec[++i].crumb_bit_length;
10685         }
10686
10687         /* Sign extend for signed types */
10688         switch (hf_field->type) {
10689                 case FT_INT8:
10690                 case FT_INT16:
10691                 case FT_INT24:
10692                 case FT_INT32:
10693                 case FT_INT40:
10694                 case FT_INT48:
10695                 case FT_INT56:
10696                 case FT_INT64:
10697                         value = ws_sign_ext64(value, no_of_bits);
10698                         break;
10699                 default:
10700                         break;
10701         }
10702
10703         if (return_value) {
10704                 *return_value = value;
10705         }
10706
10707         /* Coast clear. Try and fake it */
10708         CHECK_FOR_NULL_TREE(tree);
10709         TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
10710
10711         /* initialise the format string */
10712         bf_str[0] = '\0';
10713
10714         octet_offset = bit_offset >> 3;
10715
10716         /* Round up mask length to nearest octet */
10717         octet_length = ((mask_greatest_bit_offset + 7) >> 3);
10718         mask_greatest_bit_offset = octet_length << 3;
10719
10720         /* As noted above, we currently only produce a bitmap if the crumbs span less than 4 octets of the tvb.
10721            It would be a useful enhancement to eliminate this restriction. */
10722         if (mask_greatest_bit_offset > 0 && mask_greatest_bit_offset <= 32) {
10723                 other_decode_bitfield_value(bf_str,
10724                                             (guint32)(composite_bitmap  >> (64 - mask_greatest_bit_offset)),
10725                                             (guint32)(composite_bitmask >> (64 - mask_greatest_bit_offset)),
10726                                             mask_greatest_bit_offset);
10727         }
10728
10729         switch (hf_field->type) {
10730         case FT_BOOLEAN: /* it is a bit odd to have a boolean encoded as split-bits, but possible, I suppose? */
10731                 /* Boolean field */
10732                 tfstring = (const true_false_string *) &tfs_true_false;
10733                 if (hf_field->strings)
10734                         tfstring = (const true_false_string *) hf_field->strings;
10735                 return proto_tree_add_boolean_format(tree, hfindex,
10736                                                      tvb, octet_offset, octet_length, (guint32)value,
10737                                                      "%s = %s: %s",
10738                                                      bf_str, hf_field->name,
10739                                                      (guint64)value ? tfstring->true_string : tfstring->false_string);
10740                 break;
10741
10742         case FT_CHAR:
10743                 pi = proto_tree_add_uint(tree, hfindex, tvb, octet_offset, octet_length, (guint32)value);
10744                 fill_label_char(PITEM_FINFO(pi), lbl_str);
10745                 break;
10746
10747         case FT_UINT8:
10748         case FT_UINT16:
10749         case FT_UINT24:
10750         case FT_UINT32:
10751                 pi = proto_tree_add_uint(tree, hfindex, tvb, octet_offset, octet_length, (guint32)value);
10752                 fill_label_number(PITEM_FINFO(pi), lbl_str, FALSE);
10753                 break;
10754
10755         case FT_INT8:
10756         case FT_INT16:
10757         case FT_INT24:
10758         case FT_INT32:
10759                 pi = proto_tree_add_int(tree, hfindex, tvb, octet_offset, octet_length, (gint32)value);
10760                 fill_label_number(PITEM_FINFO(pi), lbl_str, TRUE);
10761                 break;
10762
10763         case FT_UINT40:
10764         case FT_UINT48:
10765         case FT_UINT56:
10766         case FT_UINT64:
10767                 pi = proto_tree_add_uint64(tree, hfindex, tvb, octet_offset, octet_length, value);
10768                 fill_label_number64(PITEM_FINFO(pi), lbl_str, FALSE);
10769                 break;
10770
10771         case FT_INT40:
10772         case FT_INT48:
10773         case FT_INT56:
10774         case FT_INT64:
10775                 pi = proto_tree_add_int64(tree, hfindex, tvb, octet_offset, octet_length, (gint64)value);
10776                 fill_label_number64(PITEM_FINFO(pi), lbl_str, TRUE);
10777                 break;
10778
10779         default:
10780                 DISSECTOR_ASSERT_NOT_REACHED();
10781                 return NULL;
10782                 break;
10783         }
10784         proto_item_set_text(pi, "%s = %s", bf_str, lbl_str);
10785         return pi;
10786 }
10787
10788 void
10789 proto_tree_add_split_bits_crumb(proto_tree *tree, const int hfindex, tvbuff_t *tvb, const guint bit_offset,
10790                                 const crumb_spec_t *crumb_spec, guint16 crumb_index)
10791 {
10792         header_field_info *hfinfo;
10793
10794         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
10795         proto_tree_add_text_internal(tree, tvb,
10796                             bit_offset >> 3,
10797                             ((bit_offset + crumb_spec[crumb_index].crumb_bit_length - 1) >> 3) - (bit_offset >> 3) + 1,
10798                             "%s crumb %d of %s (decoded above)",
10799                             decode_bits_in_field(bit_offset, crumb_spec[crumb_index].crumb_bit_length,
10800                                                  tvb_get_bits(tvb,
10801                                                               bit_offset,
10802                                                               crumb_spec[crumb_index].crumb_bit_length,
10803                                                               ENC_BIG_ENDIAN)),
10804                             crumb_index,
10805                             hfinfo->name);
10806 }
10807
10808 proto_item *
10809 proto_tree_add_bits_ret_val(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
10810                             const guint bit_offset, const gint no_of_bits,
10811                             guint64 *return_value, const guint encoding)
10812 {
10813         proto_item *item;
10814
10815         if ((item = _proto_tree_add_bits_ret_val(tree, hfindex, tvb,
10816                                                  bit_offset, no_of_bits,
10817                                                  return_value, encoding))) {
10818                 FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_OFFSET(bit_offset));
10819                 FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_SIZE(no_of_bits));
10820         }
10821         return item;
10822 }
10823
10824 static proto_item *
10825 _proto_tree_add_bits_format_value(proto_tree *tree, const int hfindex,
10826                                  tvbuff_t *tvb, const guint bit_offset,
10827                                  const gint no_of_bits, void *value_ptr,
10828                                  gchar *value_str)
10829 {
10830         gint     offset;
10831         guint    length;
10832         guint8   tot_no_bits;
10833         char    *str;
10834         guint64  value = 0;
10835         header_field_info *hf_field;
10836
10837         /* We do not have to return a value, try to fake it as soon as possible */
10838         CHECK_FOR_NULL_TREE(tree);
10839         TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
10840
10841         if (hf_field->bitmask != 0) {
10842                 REPORT_DISSECTOR_BUG(wmem_strdup_printf(wmem_packet_scope(),
10843                                         "Incompatible use of proto_tree_add_bits_format_value"
10844                                         " with field '%s' (%s) with bitmask != 0",
10845                                         hf_field->abbrev, hf_field->name));
10846         }
10847
10848         DISSECTOR_ASSERT(no_of_bits > 0);
10849
10850         /* Byte align offset */
10851         offset = bit_offset>>3;
10852
10853         /*
10854          * Calculate the number of octets used to hold the bits
10855          */
10856         tot_no_bits = ((bit_offset&0x7) + no_of_bits);
10857         length      = tot_no_bits>>3;
10858         /* If we are using part of the next octet, increase length by 1 */
10859         if (tot_no_bits & 0x07)
10860                 length++;
10861
10862         if (no_of_bits < 65) {
10863                 value = tvb_get_bits64(tvb, bit_offset, no_of_bits, ENC_BIG_ENDIAN);
10864         } else {
10865                 DISSECTOR_ASSERT_NOT_REACHED();
10866                 return NULL;
10867         }
10868
10869         str = decode_bits_in_field(bit_offset, no_of_bits, value);
10870
10871         g_strlcat(str, " = ", 256+64);
10872         g_strlcat(str, hf_field->name, 256+64);
10873
10874         /*
10875          * This function does not receive an actual value but a dimensionless pointer to that value.
10876          * For this reason, the type of the header field is examined in order to determine
10877          * what kind of value we should read from this address.
10878          * The caller of this function must make sure that for the specific header field type the address of
10879          * a compatible value is provided.
10880          */
10881         switch (hf_field->type) {
10882         case FT_BOOLEAN:
10883                 return proto_tree_add_boolean_format(tree, hfindex, tvb, offset, length, *(guint32 *)value_ptr,
10884                                                      "%s: %s", str, value_str);
10885                 break;
10886
10887         case FT_CHAR:
10888         case FT_UINT8:
10889         case FT_UINT16:
10890         case FT_UINT24:
10891         case FT_UINT32:
10892                 return proto_tree_add_uint_format(tree, hfindex, tvb, offset, length, *(guint32 *)value_ptr,
10893                                                   "%s: %s", str, value_str);
10894                 break;
10895
10896         case FT_UINT40:
10897         case FT_UINT48:
10898         case FT_UINT56:
10899         case FT_UINT64:
10900                 return proto_tree_add_uint64_format(tree, hfindex, tvb, offset, length, *(guint64 *)value_ptr,
10901                                                     "%s: %s", str, value_str);
10902                 break;
10903
10904         case FT_INT8:
10905         case FT_INT16:
10906         case FT_INT24:
10907         case FT_INT32:
10908                 return proto_tree_add_int_format(tree, hfindex, tvb, offset, length, *(gint32 *)value_ptr,
10909                                                  "%s: %s", str, value_str);
10910                 break;
10911
10912         case FT_INT40:
10913         case FT_INT48:
10914         case FT_INT56:
10915         case FT_INT64:
10916                 return proto_tree_add_int64_format(tree, hfindex, tvb, offset, length, *(gint64 *)value_ptr,
10917                                                    "%s: %s", str, value_str);
10918                 break;
10919
10920         case FT_FLOAT:
10921                 return proto_tree_add_float_format(tree, hfindex, tvb, offset, length, *(float *)value_ptr,
10922                                                    "%s: %s", str, value_str);
10923                 break;
10924
10925         default:
10926                 DISSECTOR_ASSERT_NOT_REACHED();
10927                 return NULL;
10928                 break;
10929         }
10930 }
10931
10932 static proto_item *
10933 proto_tree_add_bits_format_value(proto_tree *tree, const int hfindex,
10934                                  tvbuff_t *tvb, const guint bit_offset,
10935                                  const gint no_of_bits, void *value_ptr,
10936                                  gchar *value_str)
10937 {
10938         proto_item *item;
10939
10940         if ((item = _proto_tree_add_bits_format_value(tree, hfindex,
10941                                                       tvb, bit_offset, no_of_bits,
10942                                                       value_ptr, value_str))) {
10943                 FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_OFFSET(bit_offset));
10944                 FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_SIZE(no_of_bits));
10945         }
10946         return item;
10947 }
10948
10949 #define CREATE_VALUE_STRING(dst,format,ap) \
10950         va_start(ap, format); \
10951         dst = wmem_strdup_vprintf(wmem_packet_scope(), format, ap); \
10952         va_end(ap);
10953
10954 proto_item *
10955 proto_tree_add_uint_bits_format_value(proto_tree *tree, const int hfindex,
10956                                       tvbuff_t *tvb, const guint bit_offset,
10957                                       const gint no_of_bits, guint32 value,
10958                                       const char *format, ...)
10959 {
10960         va_list ap;
10961         gchar  *dst;
10962         header_field_info *hf_field;
10963
10964         CHECK_FOR_NULL_TREE(tree);
10965
10966         TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
10967
10968         switch (hf_field->type) {
10969                 case FT_UINT8:
10970                 case FT_UINT16:
10971                 case FT_UINT24:
10972                 case FT_UINT32:
10973                         break;
10974
10975                 default:
10976                         DISSECTOR_ASSERT_NOT_REACHED();
10977                         return NULL;
10978                         break;
10979         }
10980
10981         CREATE_VALUE_STRING(dst, format, ap);
10982
10983         return proto_tree_add_bits_format_value(tree, hfindex, tvb, bit_offset, no_of_bits, &value, dst);
10984 }
10985
10986 proto_item *
10987 proto_tree_add_uint64_bits_format_value(proto_tree *tree, const int hfindex,
10988                                       tvbuff_t *tvb, const guint bit_offset,
10989                                       const gint no_of_bits, guint64 value,
10990                                       const char *format, ...)
10991 {
10992         va_list ap;
10993         gchar  *dst;
10994         header_field_info *hf_field;
10995
10996         CHECK_FOR_NULL_TREE(tree);
10997
10998         TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
10999
11000         switch (hf_field->type) {
11001                 case FT_UINT40:
11002                 case FT_UINT48:
11003                 case FT_UINT56:
11004                 case FT_UINT64:
11005                         break;
11006
11007                 default:
11008                         DISSECTOR_ASSERT_NOT_REACHED();
11009                         return NULL;
11010                         break;
11011         }
11012
11013         CREATE_VALUE_STRING(dst, format, ap);
11014
11015         return proto_tree_add_bits_format_value(tree, hfindex, tvb, bit_offset, no_of_bits, &value, dst);
11016 }
11017
11018 proto_item *
11019 proto_tree_add_float_bits_format_value(proto_tree *tree, const int hfindex,
11020                                        tvbuff_t *tvb, const guint bit_offset,
11021                                        const gint no_of_bits, float value,
11022                                        const char *format, ...)
11023 {
11024         va_list ap;
11025         gchar  *dst;
11026         header_field_info *hf_field;
11027
11028         CHECK_FOR_NULL_TREE(tree);
11029
11030         TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
11031
11032         DISSECTOR_ASSERT_FIELD_TYPE(hf_field, FT_FLOAT);
11033
11034         CREATE_VALUE_STRING(dst, format, ap);
11035
11036         return proto_tree_add_bits_format_value(tree, hfindex, tvb, bit_offset, no_of_bits, &value, dst);
11037 }
11038
11039 proto_item *
11040 proto_tree_add_int_bits_format_value(proto_tree *tree, const int hfindex,
11041                                      tvbuff_t *tvb, const guint bit_offset,
11042                                      const gint no_of_bits, gint32 value,
11043                                      const char *format, ...)
11044 {
11045         va_list ap;
11046         gchar  *dst;
11047         header_field_info *hf_field;
11048
11049         CHECK_FOR_NULL_TREE(tree);
11050
11051         TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
11052
11053         switch (hf_field->type) {
11054                 case FT_INT8:
11055                 case FT_INT16:
11056                 case FT_INT24:
11057                 case FT_INT32:
11058                         break;
11059
11060                 default:
11061                         DISSECTOR_ASSERT_NOT_REACHED();
11062                         return NULL;
11063                         break;
11064         }
11065
11066         CREATE_VALUE_STRING(dst, format, ap);
11067
11068         return proto_tree_add_bits_format_value(tree, hfindex, tvb, bit_offset, no_of_bits, &value, dst);
11069 }
11070
11071 proto_item *
11072 proto_tree_add_int64_bits_format_value(proto_tree *tree, const int hfindex,
11073                                      tvbuff_t *tvb, const guint bit_offset,
11074                                      const gint no_of_bits, gint64 value,
11075                                      const char *format, ...)
11076 {
11077         va_list ap;
11078         gchar  *dst;
11079         header_field_info *hf_field;
11080
11081         CHECK_FOR_NULL_TREE(tree);
11082
11083         TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
11084
11085         switch (hf_field->type) {
11086                 case FT_INT40:
11087                 case FT_INT48:
11088                 case FT_INT56:
11089                 case FT_INT64:
11090                         break;
11091
11092                 default:
11093                         DISSECTOR_ASSERT_NOT_REACHED();
11094                         return NULL;
11095                         break;
11096         }
11097
11098         CREATE_VALUE_STRING(dst, format, ap);
11099
11100         return proto_tree_add_bits_format_value(tree, hfindex, tvb, bit_offset, no_of_bits, &value, dst);
11101 }
11102
11103 proto_item *
11104 proto_tree_add_boolean_bits_format_value(proto_tree *tree, const int hfindex,
11105                                          tvbuff_t *tvb, const guint bit_offset,
11106                                          const gint no_of_bits, guint32 value,
11107                                          const char *format, ...)
11108 {
11109         va_list ap;
11110         gchar  *dst;
11111         header_field_info *hf_field;
11112
11113         CHECK_FOR_NULL_TREE(tree);
11114
11115         TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
11116
11117         DISSECTOR_ASSERT_FIELD_TYPE(hf_field, FT_BOOLEAN);
11118
11119         CREATE_VALUE_STRING(dst, format, ap);
11120
11121         return proto_tree_add_bits_format_value(tree, hfindex, tvb, bit_offset, no_of_bits, &value, dst);
11122 }
11123
11124 proto_item *
11125 proto_tree_add_boolean_bits_format_value64(proto_tree *tree, const int hfindex,
11126                                          tvbuff_t *tvb, const guint bit_offset,
11127                                          const gint no_of_bits, guint64 value,
11128                                          const char *format, ...)
11129 {
11130         va_list ap;
11131         gchar  *dst;
11132         header_field_info *hf_field;
11133
11134         CHECK_FOR_NULL_TREE(tree);
11135
11136         TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
11137
11138         DISSECTOR_ASSERT(hf_field->type == FT_BOOLEAN);
11139
11140         CREATE_VALUE_STRING(dst, format, ap);
11141
11142         return proto_tree_add_bits_format_value(tree, hfindex, tvb, bit_offset, no_of_bits, &value, dst);
11143 }
11144
11145 proto_item *
11146 proto_tree_add_ts_23_038_7bits_item(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
11147         const guint bit_offset, const gint no_of_chars)
11148 {
11149         proto_item        *pi;
11150         header_field_info *hfinfo;
11151         gint               byte_length;
11152         gint               byte_offset;
11153         gchar             *string;
11154
11155         CHECK_FOR_NULL_TREE(tree);
11156
11157         TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
11158
11159         DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_STRING);
11160
11161         byte_length = (((no_of_chars + 1) * 7) + (bit_offset & 0x07)) >> 3;
11162         byte_offset = bit_offset >> 3;
11163
11164         string = tvb_get_ts_23_038_7bits_string(wmem_packet_scope(), tvb, bit_offset, no_of_chars);
11165
11166         if (hfinfo->display == STR_UNICODE) {
11167                 DISSECTOR_ASSERT(g_utf8_validate(string, -1, NULL));
11168         }
11169
11170         pi = proto_tree_add_pi(tree, hfinfo, tvb, byte_offset, &byte_length);
11171         DISSECTOR_ASSERT(byte_length >= 0);
11172         proto_tree_set_string(PNODE_FINFO(pi), string);
11173
11174         return pi;
11175 }
11176
11177 proto_item *
11178 proto_tree_add_ascii_7bits_item(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
11179         const guint bit_offset, const gint no_of_chars)
11180 {
11181         proto_item        *pi;
11182         header_field_info *hfinfo;
11183         gint               byte_length;
11184         gint               byte_offset;
11185         gchar             *string;
11186
11187         CHECK_FOR_NULL_TREE(tree);
11188
11189         TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
11190
11191         DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_STRING);
11192
11193         byte_length = (((no_of_chars + 1) * 7) + (bit_offset & 0x07)) >> 3;
11194         byte_offset = bit_offset >> 3;
11195
11196         string = tvb_get_ascii_7bits_string(wmem_packet_scope(), tvb, bit_offset, no_of_chars);
11197
11198         if (hfinfo->display == STR_UNICODE) {
11199                 DISSECTOR_ASSERT(g_utf8_validate(string, -1, NULL));
11200         }
11201
11202         pi = proto_tree_add_pi(tree, hfinfo, tvb, byte_offset, &byte_length);
11203         DISSECTOR_ASSERT(byte_length >= 0);
11204         proto_tree_set_string(PNODE_FINFO(pi), string);
11205
11206         return pi;
11207 }
11208
11209 const value_string proto_checksum_vals[] = {
11210         { PROTO_CHECKSUM_E_BAD,        "Bad"  },
11211         { PROTO_CHECKSUM_E_GOOD,       "Good" },
11212         { PROTO_CHECKSUM_E_UNVERIFIED, "Unverified" },
11213         { PROTO_CHECKSUM_E_NOT_PRESENT, "Not present" },
11214
11215         { 0,        NULL }
11216 };
11217
11218 proto_item *
11219 proto_tree_add_checksum(proto_tree *tree, tvbuff_t *tvb, const guint offset,
11220                 const int hf_checksum, const int hf_checksum_status, struct expert_field* bad_checksum_expert,
11221                 packet_info *pinfo, guint32 computed_checksum, const guint encoding, const guint flags)
11222 {
11223         header_field_info *hfinfo = proto_registrar_get_nth(hf_checksum);
11224         guint32 checksum;
11225         guint32 len;
11226         proto_item* ti = NULL;
11227         proto_item* ti2;
11228         gboolean incorrect_checksum = TRUE;
11229
11230         DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");
11231
11232         if (flags & PROTO_CHECKSUM_NOT_PRESENT) {
11233                 ti = proto_tree_add_uint_format_value(tree, hf_checksum, tvb, offset, 0, 0, "[missing]");
11234                 PROTO_ITEM_SET_GENERATED(ti);
11235                 if (hf_checksum_status != -1) {
11236                         ti2 = proto_tree_add_uint(tree, hf_checksum_status, tvb, offset, 0, PROTO_CHECKSUM_E_NOT_PRESENT);
11237                         PROTO_ITEM_SET_GENERATED(ti2);
11238                 }
11239                 return ti;
11240         }
11241
11242         switch (hfinfo->type){
11243         case FT_UINT8:
11244                 len = 1;
11245                 break;
11246         case FT_UINT16:
11247                 len = 2;
11248                 break;
11249         case FT_UINT24:
11250                 len = 3;
11251                 break;
11252         case FT_UINT32:
11253                 len = 4;
11254                 break;
11255         default:
11256                 DISSECTOR_ASSERT_NOT_REACHED();
11257         }
11258
11259         if (flags & PROTO_CHECKSUM_GENERATED) {
11260                 ti = proto_tree_add_uint(tree, hf_checksum, tvb, offset, 0, computed_checksum);
11261                 PROTO_ITEM_SET_GENERATED(ti);
11262         } else {
11263                 ti = proto_tree_add_item_ret_uint(tree, hf_checksum, tvb, offset, len, encoding, &checksum);
11264                 if (flags & PROTO_CHECKSUM_VERIFY) {
11265                         if (flags & (PROTO_CHECKSUM_IN_CKSUM|PROTO_CHECKSUM_ZERO)) {
11266                                 if (computed_checksum == 0) {
11267                                         proto_item_append_text(ti, " [correct]");
11268                                         if (hf_checksum_status != -1) {
11269                                                 ti2 = proto_tree_add_uint(tree, hf_checksum_status, tvb, offset, 0, PROTO_CHECKSUM_E_GOOD);
11270                                                 PROTO_ITEM_SET_GENERATED(ti2);
11271                                         }
11272                                         incorrect_checksum = FALSE;
11273                                 } else if (flags & PROTO_CHECKSUM_IN_CKSUM) {
11274                                         computed_checksum = in_cksum_shouldbe(checksum, computed_checksum);
11275                                 }
11276                         } else {
11277                                 if (checksum == computed_checksum) {
11278                                         proto_item_append_text(ti, " [correct]");
11279                                         if (hf_checksum_status != -1) {
11280                                                 ti2 = proto_tree_add_uint(tree, hf_checksum_status, tvb, offset, 0, PROTO_CHECKSUM_E_GOOD);
11281                                                 PROTO_ITEM_SET_GENERATED(ti2);
11282                                         }
11283                                         incorrect_checksum = FALSE;
11284                                 }
11285                         }
11286
11287                         if (incorrect_checksum) {
11288                                 if (hf_checksum_status != -1) {
11289                                         ti2 = proto_tree_add_uint(tree, hf_checksum_status, tvb, offset, 0, PROTO_CHECKSUM_E_BAD);
11290                                         PROTO_ITEM_SET_GENERATED(ti2);
11291                                 }
11292                                 if (flags & PROTO_CHECKSUM_ZERO) {
11293                                         proto_item_append_text(ti, " [incorrect]");
11294                                         if (bad_checksum_expert != NULL)
11295                                                 expert_add_info_format(pinfo, ti, bad_checksum_expert, "Bad checksum");
11296                                 } else {
11297                                         proto_item_append_text(ti, " incorrect, should be 0x%0*x", len*2, computed_checksum);
11298                                         if (bad_checksum_expert != NULL)
11299                                                 expert_add_info_format(pinfo, ti, bad_checksum_expert, "Bad checksum [should be 0x%0*x]", len*2, computed_checksum);
11300                                 }
11301                         }
11302                 } else {
11303                         if (hf_checksum_status != -1) {
11304                                 proto_item_append_text(ti, " [unverified]");
11305                                 ti2 = proto_tree_add_uint(tree, hf_checksum_status, tvb, offset, 0, PROTO_CHECKSUM_E_UNVERIFIED);
11306                                 PROTO_ITEM_SET_GENERATED(ti2);
11307                         }
11308                 }
11309         }
11310
11311         return ti;
11312 }
11313
11314 guchar
11315 proto_check_field_name(const gchar *field_name)
11316 {
11317         return wrs_check_charset(fld_abbrev_chars, field_name);
11318 }
11319
11320 gboolean
11321 tree_expanded(int tree_type)
11322 {
11323         g_assert(tree_type >= 0 && tree_type < num_tree_types);
11324         return tree_is_expanded[tree_type >> 5] & (1U << (tree_type & 31));
11325 }
11326
11327 void
11328 tree_expanded_set(int tree_type, gboolean value)
11329 {
11330         g_assert(tree_type >= 0 && tree_type < num_tree_types);
11331
11332         if (value)
11333                 tree_is_expanded[tree_type >> 5] |= (1U << (tree_type & 31));
11334         else
11335                 tree_is_expanded[tree_type >> 5] &= ~(1U << (tree_type & 31));
11336 }
11337
11338 /*
11339  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
11340  *
11341  * Local variables:
11342  * c-basic-offset: 8
11343  * tab-width: 8
11344  * indent-tabs-mode: t
11345  * End:
11346  *
11347  * vi: set shiftwidth=8 tabstop=8 noexpandtab:
11348  * :indentSize=8:tabSize=8:noTabs=false:
11349  */