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