ed37f560404e154ee9a33ccd0ff58083efa460cb
[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 #define cVALS(x) (const value_string*)(x)
75
76 /** See inlined comments.
77  @param tree the tree to append this item to
78  @param hfindex field index
79  @param hfinfo header_field
80  @return the header field matching 'hfinfo' */
81 #define TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo) \
82         /* If this item is not referenced we dont have to do much work  \
83            at all but we should still return a node so that field items \
84            below this node (think proto_item_add_subtree()) will still  \
85            have somewhere to attach to or else filtering will not work  \
86            (they would be ignored since tree would be NULL).            \
87            DONT try to fake a node where PTREE_FINFO(tree) is NULL      \
88            since dissectors that want to do proto_item_set_len() or     \
89            other operations that dereference this would crash.          \
90            We fake FT_PROTOCOL unless some clients have requested us    \
91            not to do so. \
92         */                                                              \
93         if (!tree)                                                      \
94                 return NULL;                                            \
95         PTREE_DATA(tree)->count++;                                      \
96         if (PTREE_DATA(tree)->count > MAX_TREE_ITEMS) {                 \
97                 if (getenv("WIRESHARK_ABORT_ON_TOO_MANY_ITEMS") != NULL) \
98                         g_error("More than %d items in the tree -- possible infinite loop", MAX_TREE_ITEMS); \
99                 /* Let the exception handler add items to the tree */   \
100                 PTREE_DATA(tree)->count = 0;                            \
101                 THROW_MESSAGE(DissectorError,                           \
102                         ep_strdup_printf("More than %d items in the tree -- possible infinite loop", MAX_TREE_ITEMS)); \
103         }                                                               \
104         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);                       \
105         if (!(PTREE_DATA(tree)->visible)) {                             \
106                 if (PTREE_FINFO(tree)) {                                \
107                         if ((hfinfo->ref_type != HF_REF_TYPE_DIRECT)    \
108                             && (hfinfo->type != FT_PROTOCOL ||          \
109                                 PTREE_DATA(tree)->fake_protocols)) {    \
110                                 /* just return tree back to the caller */\
111                                 return tree;                            \
112                         }                                               \
113                 }                                                       \
114         }
115
116 /** See inlined comments.
117  @param pi the created protocol item we're about to return */
118 #define TRY_TO_FAKE_THIS_REPR(pi) \
119         g_assert(pi);                   \
120         if (!(PTREE_DATA(pi)->visible)) { \
121                 /* If the tree (GUI) isn't visible it's pointless for us to generate the protocol \
122                  * items string representation */ \
123                 return pi; \
124         }
125
126 static const char *hf_try_val_to_str(guint32 value, const header_field_info *hfinfo);
127
128 static void fill_label_boolean(field_info *fi, gchar *label_str);
129 static void fill_label_bitfield(field_info *fi, gchar *label_str);
130 static void fill_label_number(field_info *fi, gchar *label_str, gboolean is_signed);
131 static void fill_label_number64(field_info *fi, gchar *label_str, gboolean is_signed);
132
133 static const char *hfinfo_number_value_format_display(const header_field_info *hfinfo, int display, char buf[32], guint32 value);
134 static const char *hfinfo_number_vals_format(const header_field_info *hfinfo, char buf[32], guint32 value);
135 static const char *hfinfo_number_value_format(const header_field_info *hfinfo, char buf[32], guint32 value);
136 static const char *hfinfo_numeric_value_format(const header_field_info *hfinfo, char buf[32], guint32 value);
137
138 static const char* hfinfo_uint64_format(const header_field_info *hfinfo);
139 static const char* hfinfo_int64_format(const header_field_info *hfinfo);
140
141 static proto_item *
142 proto_tree_add_node(proto_tree *tree, field_info *fi);
143
144 static void
145 get_hfi_length(header_field_info *hfinfo, tvbuff_t *tvb, const gint start, gint *length,
146                 gint *item_length);
147
148 static field_info *
149 new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
150                const gint start, const gint item_length);
151
152 static field_info *
153 alloc_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
154                  const gint start, gint *length);
155
156 static proto_item *
157 proto_tree_add_pi(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
158                   gint start, gint *length);
159
160 static void
161 proto_tree_set_representation_value(proto_item *pi, const char *format, va_list ap);
162 static void
163 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap);
164
165 static void
166 proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb);
167 static void
168 proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length);
169 static void
170 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length);
171 static void
172 proto_tree_set_time(field_info *fi, nstime_t *value_ptr);
173 static void
174 proto_tree_set_string(field_info *fi, const char* value);
175 static void
176 proto_tree_set_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length, gint encoding);
177 static void
178 proto_tree_set_ax25(field_info *fi, const guint8* value);
179 static void
180 proto_tree_set_ax25_tvb(field_info *fi, tvbuff_t *tvb, gint start);
181 static void
182 proto_tree_set_vines(field_info *fi, const guint8* value);
183 static void
184 proto_tree_set_vines_tvb(field_info *fi, tvbuff_t *tvb, gint start);
185 static void
186 proto_tree_set_ether(field_info *fi, const guint8* value);
187 static void
188 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start);
189 static void
190 proto_tree_set_ipxnet(field_info *fi, guint32 value);
191 static void
192 proto_tree_set_ipv4(field_info *fi, guint32 value);
193 static void
194 proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr);
195 static void
196 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
197 static void
198 proto_tree_set_guid(field_info *fi, const e_guid_t *value_ptr);
199 static void
200 proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, gint start, const guint encoding);
201 static void
202 proto_tree_set_oid(field_info *fi, const guint8* value_ptr, gint length);
203 static void
204 proto_tree_set_oid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
205 static void
206 proto_tree_set_boolean(field_info *fi, guint32 value);
207 static void
208 proto_tree_set_float(field_info *fi, float value);
209 static void
210 proto_tree_set_double(field_info *fi, double value);
211 static void
212 proto_tree_set_uint(field_info *fi, guint32 value);
213 static void
214 proto_tree_set_int(field_info *fi, gint32 value);
215 static void
216 proto_tree_set_uint64(field_info *fi, guint64 value);
217 static void
218 proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start, guint length, const guint encoding);
219 static void
220 proto_tree_set_eui64(field_info *fi, const guint64 value);
221 static void
222 proto_tree_set_eui64_tvb(field_info *fi, tvbuff_t *tvb, gint start, const guint encoding);
223 static gboolean
224 proto_item_add_bitmask_tree(proto_item *item, tvbuff_t *tvb, const int offset,
225                             const int len, const gint ett, const gint **fields,
226                             const guint encoding, const int flags,
227                             gboolean first);
228
229 static int proto_register_field_init(header_field_info *hfinfo, const int parent);
230
231 /* special-case header field used within proto.c */
232 static header_field_info hfi_text_only =
233         { "Text item",  "text", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL };
234 int hf_text_only = -1;
235
236 /* Structure for information about a protocol */
237 struct _protocol {
238         const char *name;         /* long description */
239         const char *short_name;   /* short description */
240         const char *filter_name;  /* name of this protocol in filters */
241         int         proto_id;     /* field ID for this protocol */
242         GSList     *fields;       /* fields for this protocol */
243         GSList     *last_field;   /* pointer to end of list of fields */
244         gboolean    is_enabled;   /* TRUE if protocol is enabled */
245         gboolean    can_toggle;   /* TRUE if is_enabled can be changed */
246         gboolean    is_private;   /* TRUE is protocol is private */
247 };
248
249 /* List of all protocols */
250 static GList *protocols = NULL;
251
252 #define INITIAL_NUM_PROTOCOL_HFINFO     1500
253
254 /* Contains information about a field when a dissector calls
255  * proto_tree_add_item.  */
256 #define FIELD_INFO_NEW(fi)  fi = g_slice_new(field_info)
257 #define FIELD_INFO_FREE(fi) g_slice_free(field_info, fi)
258
259 /* Contains the space for proto_nodes. */
260 #define PROTO_NODE_NEW(node)                            \
261         node = g_slice_new(proto_node);                 \
262         node->first_child = NULL;                       \
263         node->last_child = NULL;                        \
264         node->next = NULL;
265
266 #define PROTO_NODE_FREE(node)                           \
267         g_slice_free(proto_node, node)
268
269 /* String space for protocol and field items for the GUI */
270 #define ITEM_LABEL_NEW(il)                              \
271         il = g_slice_new(item_label_t);
272 #define ITEM_LABEL_FREE(il)                             \
273         g_slice_free(item_label_t, il);
274
275 #define PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo)                                                \
276         if((guint)hfindex >= gpa_hfinfo.len && getenv("WIRESHARK_ABORT_ON_DISSECTOR_BUG"))      \
277                 g_error("Unregistered hf! index=%d", hfindex);                                  \
278         DISSECTOR_ASSERT_HINT((guint)hfindex < gpa_hfinfo.len, "Unregistered hf!");     \
279         hfinfo = gpa_hfinfo.hfi[hfindex];
280
281 /* List which stores protocols and fields that have been registered */
282 typedef struct _gpa_hfinfo_t {
283         guint32             len;
284         guint32             allocated_len;
285         header_field_info **hfi;
286 } gpa_hfinfo_t;
287
288 static gpa_hfinfo_t gpa_hfinfo;
289
290 /* Balanced tree of abbreviations and IDs */
291 static GTree *gpa_name_tree = NULL;
292 static header_field_info *same_name_hfinfo;
293
294 static void save_same_name_hfinfo(gpointer data)
295 {
296         same_name_hfinfo = (header_field_info*)data;
297 }
298
299 /* Points to the first element of an array of bits, indexed by
300    a subtree item type; that array element is TRUE if subtrees of
301    an item of that type are to be expanded. */
302 static guint32 *tree_is_expanded;
303
304 /* Number of elements in that array. */
305 int             num_tree_types;
306
307 /* Name hashtables for fast detection of duplicate names */
308 static GHashTable* proto_names        = NULL;
309 static GHashTable* proto_short_names  = NULL;
310 static GHashTable* proto_filter_names = NULL;
311
312 static gint
313 proto_compare_name(gconstpointer p1_arg, gconstpointer p2_arg)
314 {
315         const protocol_t *p1 = (const protocol_t *)p1_arg;
316         const protocol_t *p2 = (const protocol_t *)p2_arg;
317
318         return g_ascii_strcasecmp(p1->short_name, p2->short_name);
319 }
320
321
322 /* initialize data structures and register protocols and fields */
323 void
324 proto_init(void (register_all_protocols_func)(register_cb cb, gpointer client_data),
325            void (register_all_handoffs_func)(register_cb cb, gpointer client_data),
326            register_cb cb,
327            gpointer client_data)
328 {
329         proto_cleanup();
330
331         proto_names        = g_hash_table_new_full(g_int_hash, g_int_equal, g_free, NULL);
332         proto_short_names  = g_hash_table_new(wrs_str_hash, g_str_equal);
333         proto_filter_names = g_hash_table_new(wrs_str_hash, g_str_equal);
334
335         gpa_hfinfo.len           = 0;
336         gpa_hfinfo.allocated_len = 0;
337         gpa_hfinfo.hfi           = NULL;
338         gpa_name_tree            = g_tree_new_full(wrs_strcmp_with_data, NULL, NULL, save_same_name_hfinfo);
339
340         /* Initialize the ftype subsystem */
341         ftypes_initialize();
342
343         /* Register one special-case FT_TEXT_ONLY field for use when
344            converting wireshark to new-style proto_tree. These fields
345            are merely strings on the GUI tree; they are not filterable */
346         hf_text_only = proto_register_field_init(&hfi_text_only, -1);
347
348         /* Register the pseudo-protocols used for exceptions. */
349         register_show_exception();
350
351         /* Have each built-in dissector register its protocols, fields,
352            dissector tables, and dissectors to be called through a
353            handle, and do whatever one-time initialization it needs to
354            do. */
355         register_all_protocols_func(cb, client_data);
356 #ifdef HAVE_PYTHON
357         /* Now scan for python protocols */
358         if (cb)
359                 (*cb)(RA_PYTHON_REGISTER, NULL, client_data);
360         register_all_py_protocols_func();
361 #endif
362
363 #ifdef HAVE_PLUGINS
364         /* Now scan for plugins and load all the ones we find, calling
365            their register routines to do the stuff described above. */
366         if (cb)
367                 (*cb)(RA_PLUGIN_REGISTER, NULL, client_data);
368         init_plugins();
369         register_all_plugin_registrations();
370 #endif
371
372         /* Now call the "handoff registration" routines of all built-in
373            dissectors; those routines register the dissector in other
374            dissectors' handoff tables, and fetch any dissector handles
375            they need. */
376         register_all_handoffs_func(cb, client_data);
377
378 #ifdef HAVE_PYTHON
379         /* Now do the same with python dissectors */
380         if (cb)
381                 (*cb)(RA_PYTHON_HANDOFF, NULL, client_data);
382         register_all_py_handoffs_func();
383 #endif
384
385 #ifdef HAVE_PLUGINS
386         /* Now do the same with plugins. */
387         if (cb)
388                 (*cb)(RA_PLUGIN_HANDOFF, NULL, client_data);
389         register_all_plugin_handoffs();
390 #endif
391
392         /* sort the protocols by protocol name */
393         protocols = g_list_sort(protocols, proto_compare_name);
394
395         /* We've assigned all the subtree type values; allocate the array
396            for them, and zero it out. */
397         tree_is_expanded = g_new0(guint32, (num_tree_types/32)+1);
398 }
399
400 void
401 proto_cleanup(void)
402 {
403         /* Free the abbrev/ID GTree */
404         if (gpa_name_tree) {
405                 g_tree_destroy(gpa_name_tree);
406                 gpa_name_tree = NULL;
407         }
408
409         while (protocols) {
410                 protocol_t        *protocol = (protocol_t *)protocols->data;
411                 header_field_info *hfinfo;
412                 PROTO_REGISTRAR_GET_NTH(protocol->proto_id, hfinfo);
413                 DISSECTOR_ASSERT(protocol->proto_id == hfinfo->id);
414
415                 g_slice_free(header_field_info, hfinfo);
416                 g_slist_free(protocol->fields);
417                 protocols = g_list_remove(protocols, protocol);
418                 g_free(protocol);
419         }
420
421         if (proto_names) {
422                 g_hash_table_destroy(proto_names);
423                 proto_names = NULL;
424         }
425
426         if (proto_short_names) {
427                 g_hash_table_destroy(proto_short_names);
428                 proto_short_names = NULL;
429         }
430
431         if (proto_filter_names) {
432                 g_hash_table_destroy(proto_filter_names);
433                 proto_filter_names = NULL;
434         }
435
436         if (gpa_hfinfo.allocated_len) {
437                 gpa_hfinfo.len           = 0;
438                 gpa_hfinfo.allocated_len = 0;
439                 g_free(gpa_hfinfo.hfi);
440                 gpa_hfinfo.hfi           = NULL;
441         }
442         g_free(tree_is_expanded);
443         tree_is_expanded = NULL;
444 }
445
446 static gboolean
447 proto_tree_traverse_pre_order(proto_tree *tree, proto_tree_traverse_func func,
448                               gpointer data)
449 {
450         proto_node *pnode = tree;
451         proto_node *child;
452         proto_node *current;
453
454         if (func(pnode, data))
455                 return TRUE;
456
457         child = pnode->first_child;
458         while (child != NULL) {
459                 /*
460                  * The routine we call might modify the child, e.g. by
461                  * freeing it, so we get the child's successor before
462                  * calling that routine.
463                  */
464                 current = child;
465                 child   = current->next;
466                 if (proto_tree_traverse_pre_order((proto_tree *)current, func, data))
467                         return TRUE;
468         }
469
470         return FALSE;
471 }
472
473 gboolean
474 proto_tree_traverse_post_order(proto_tree *tree, proto_tree_traverse_func func,
475                                gpointer data)
476 {
477         proto_node *pnode = tree;
478         proto_node *child;
479         proto_node *current;
480
481         child = pnode->first_child;
482         while (child != NULL) {
483                 /*
484                  * The routine we call might modify the child, e.g. by
485                  * freeing it, so we get the child's successor before
486                  * calling that routine.
487                  */
488                 current = child;
489                 child   = current->next;
490                 if (proto_tree_traverse_post_order((proto_tree *)current, func, data))
491                         return TRUE;
492         }
493         if (func(pnode, data))
494                 return TRUE;
495
496         return FALSE;
497 }
498
499 void
500 proto_tree_children_foreach(proto_tree *tree, proto_tree_foreach_func func,
501                             gpointer data)
502 {
503         proto_node *node = tree;
504         proto_node *current;
505
506         if (!node)
507                 return;
508
509         node = node->first_child;
510         while (node != NULL) {
511                 current = node;
512                 node    = current->next;
513                 func((proto_tree *)current, data);
514         }
515 }
516
517 static void
518 free_GPtrArray_value(gpointer key, gpointer value, gpointer user_data _U_)
519 {
520         GPtrArray         *ptrs = (GPtrArray *)value;
521         gint               hfid = (gint)(long)key;
522         header_field_info *hfinfo;
523
524         PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
525         if (hfinfo->ref_type != HF_REF_TYPE_NONE) {
526                 /* when a field is referenced by a filter this also
527                    affects the refcount for the parent protocol so we need
528                    to adjust the refcount for the parent as well
529                 */
530                 if (hfinfo->parent != -1) {
531                         header_field_info *parent_hfinfo;
532                         PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
533                         parent_hfinfo->ref_type = HF_REF_TYPE_NONE;
534                 }
535                 hfinfo->ref_type = HF_REF_TYPE_NONE;
536         }
537
538         g_ptr_array_free(ptrs, TRUE);
539 }
540
541 static void
542 free_node_tree_data(tree_data_t *tree_data)
543 {
544         if (tree_data->interesting_hfids) {
545                 /* Free all the GPtrArray's in the interesting_hfids hash. */
546                 g_hash_table_foreach(tree_data->interesting_hfids,
547                         free_GPtrArray_value, NULL);
548
549                 /* And then destroy the hash. */
550                 g_hash_table_destroy(tree_data->interesting_hfids);
551         }
552         if (tree_data->fi_tmp)
553                 FIELD_INFO_FREE(tree_data->fi_tmp);
554
555         /* And finally the tree_data_t itself. */
556         g_free(tree_data);
557 }
558
559 #define FREE_NODE_FIELD_INFO(finfo)     \
560         if (finfo->rep) {                       \
561                 ITEM_LABEL_FREE(finfo->rep);    \
562         }                               \
563         FVALUE_CLEANUP(&finfo->value);  \
564         FIELD_INFO_FREE(finfo);
565
566 static void
567 proto_tree_free_node(proto_node *node, gpointer data _U_)
568 {
569         field_info *finfo  = PNODE_FINFO(node);
570
571         proto_tree_children_foreach(node, proto_tree_free_node, NULL);
572
573         /* free the field_info data. */
574         FREE_NODE_FIELD_INFO(finfo);
575         node->finfo = NULL;
576
577         /* Free the proto_node. */
578         PROTO_NODE_FREE(node);
579 }
580
581 /* frees the resources that the dissection a proto_tree uses */
582 void
583 proto_tree_free(proto_tree *tree)
584 {
585         tree_data_t *tree_data = PTREE_DATA(tree);
586
587         proto_tree_children_foreach(tree, proto_tree_free_node, NULL);
588
589         /* free root node */
590         PROTO_NODE_FREE(tree);
591
592         /* free tree data */
593         free_node_tree_data(tree_data);
594 }
595
596 /* Is the parsing being done for a visible proto_tree or an invisible one?
597  * By setting this correctly, the proto_tree creation is sped up by not
598  * having to call g_vsnprintf and copy strings around.
599  */
600 gboolean
601 proto_tree_set_visible(proto_tree *tree, gboolean visible)
602 {
603         gboolean old_visible = PTREE_DATA(tree)->visible;
604
605         PTREE_DATA(tree)->visible = visible;
606
607         return old_visible;
608 }
609
610 void
611 proto_tree_set_fake_protocols(proto_tree *tree, gboolean fake_protocols)
612 {
613         PTREE_DATA(tree)->fake_protocols = fake_protocols;
614 }
615
616 /* Assume dissector set only its protocol fields.
617    This function is called by dissectors and allows the speeding up of filtering
618    in wireshark; if this function returns FALSE it is safe to reset tree to NULL
619    and thus skip calling most of the expensive proto_tree_add_...()
620    functions.
621    If the tree is visible we implicitly assume the field is referenced.
622 */
623 gboolean
624 proto_field_is_referenced(proto_tree *tree, int proto_id)
625 {
626         register header_field_info *hfinfo;
627
628
629         if (!tree)
630                 return FALSE;
631
632         if (PTREE_DATA(tree)->visible)
633                 return TRUE;
634
635         PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
636         if (hfinfo->ref_type != HF_REF_TYPE_NONE)
637                 return TRUE;
638
639         if (hfinfo->type == FT_PROTOCOL && !PTREE_DATA(tree)->fake_protocols)
640                 return TRUE;
641
642         return FALSE;
643 }
644
645
646 /* Finds a record in the hfinfo array by id. */
647 header_field_info *
648 proto_registrar_get_nth(guint hfindex)
649 {
650         register header_field_info *hfinfo;
651
652         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
653         return hfinfo;
654 }
655
656
657 /*      Prefix initialization
658  *        this allows for a dissector to register a display filter name prefix
659  *        so that it can delay the initialization of the hf array as long as
660  *        possible.
661  */
662
663 /* compute a hash for the part before the dot of a display filter */
664 static guint
665 prefix_hash (gconstpointer key) {
666         /* end the string at the dot and compute its hash */
667         gchar* copy = ep_strdup((const gchar *)key);
668         gchar* c    = copy;
669
670         for (; *c; c++) {
671                 if (*c == '.') {
672                         *c = 0;
673                         break;
674                 }
675         }
676
677         return g_str_hash(copy);
678 }
679
680 /* are both strings equal up to the end or the dot? */
681 static gboolean
682 prefix_equal (gconstpointer ap, gconstpointer bp) {
683         const gchar* a = (const gchar *)ap;
684         const gchar* b = (const gchar *)bp;
685
686         do {
687                 gchar ac = *a++;
688                 gchar bc = *b++;
689
690                 if ( (ac == '.' || ac == '\0') &&   (bc == '.' || bc == '\0') ) return TRUE;
691
692                 if ( (ac == '.' || ac == '\0') && ! (bc == '.' || bc == '\0') ) return FALSE;
693                 if ( (bc == '.' || bc == '\0') && ! (ac == '.' || ac == '\0') ) return FALSE;
694
695                 if (ac != bc) return FALSE;
696         } while (1);
697
698         return FALSE;
699 }
700
701
702 /* indexed by prefix, contains initializers */
703 static GHashTable* prefixes = NULL;
704
705
706 /* Register a new prefix for "delayed" initialization of field arrays */
707 void
708 proto_register_prefix(const char *prefix, prefix_initializer_t pi ) {
709         if (! prefixes ) {
710                 prefixes = g_hash_table_new(prefix_hash, prefix_equal);
711         }
712
713         g_hash_table_insert(prefixes, (gpointer)prefix, pi);
714 }
715
716 /* helper to call all prefix initializers */
717 static gboolean
718 initialize_prefix(gpointer k, gpointer v, gpointer u _U_) {
719         ((prefix_initializer_t)v)((const char *)k);
720         return TRUE;
721 }
722
723 /** Initialize every remaining uninitialized prefix. */
724 void
725 proto_initialize_all_prefixes(void) {
726         g_hash_table_foreach_remove(prefixes, initialize_prefix, NULL);
727 }
728
729 /* Finds a record in the hfinfo array by name.
730  * If it fails to find it in the already registered fields,
731  * it tries to find and call an initializer in the prefixes
732  * table and if so it looks again.
733  */
734 header_field_info *
735 proto_registrar_get_byname(const char *field_name)
736 {
737         header_field_info    *hfinfo;
738         prefix_initializer_t  pi;
739
740         if (!field_name)
741                 return NULL;
742
743         hfinfo = (header_field_info *)g_tree_lookup(gpa_name_tree, field_name);
744
745         if (hfinfo)
746                 return hfinfo;
747
748         if (!prefixes)
749                 return NULL;
750
751         if ((pi = (prefix_initializer_t)g_hash_table_lookup(prefixes, field_name) ) != NULL) {
752                 pi(field_name);
753                 g_hash_table_remove(prefixes, field_name);
754         } else {
755                 return NULL;
756         }
757
758         return (header_field_info *)g_tree_lookup(gpa_name_tree, field_name);
759 }
760
761 int
762 proto_registrar_get_id_byname(const char *field_name)
763 {
764         header_field_info *hfinfo;
765
766         hfinfo = proto_registrar_get_byname(field_name);
767
768         if (!hfinfo)
769                 return -1;
770
771         return hfinfo->id;
772 }
773
774
775 static void
776 ptvcursor_new_subtree_levels(ptvcursor_t *ptvc)
777 {
778         subtree_lvl *pushed_tree;
779
780         DISSECTOR_ASSERT(ptvc->pushed_tree_max <= SUBTREE_MAX_LEVELS-SUBTREE_ONCE_ALLOCATION_NUMBER);
781         ptvc->pushed_tree_max += SUBTREE_ONCE_ALLOCATION_NUMBER;
782
783         pushed_tree = (subtree_lvl *)ep_alloc(sizeof(subtree_lvl) * ptvc->pushed_tree_max);
784         DISSECTOR_ASSERT(pushed_tree != NULL);
785         if (ptvc->pushed_tree)
786                 memcpy(pushed_tree, ptvc->pushed_tree, ptvc->pushed_tree_max - SUBTREE_ONCE_ALLOCATION_NUMBER);
787         ptvc->pushed_tree = pushed_tree;
788 }
789
790 static void
791 ptvcursor_free_subtree_levels(ptvcursor_t *ptvc)
792 {
793         ptvc->pushed_tree       = NULL;
794         ptvc->pushed_tree_max   = 0;
795         DISSECTOR_ASSERT(ptvc->pushed_tree_index == 0);
796         ptvc->pushed_tree_index = 0;
797 }
798
799 /* Allocates an initializes a ptvcursor_t with 3 variables:
800  *      proto_tree, tvbuff, and offset. */
801 ptvcursor_t *
802 ptvcursor_new(proto_tree *tree, tvbuff_t *tvb, gint offset)
803 {
804         ptvcursor_t *ptvc;
805
806         ptvc                    = (ptvcursor_t *)ep_alloc(sizeof(ptvcursor_t));
807         ptvc->tree              = tree;
808         ptvc->tvb               = tvb;
809         ptvc->offset            = offset;
810         ptvc->pushed_tree       = NULL;
811         ptvc->pushed_tree_max   = 0;
812         ptvc->pushed_tree_index = 0;
813         return ptvc;
814 }
815
816
817 /* Frees memory for ptvcursor_t, but nothing deeper than that. */
818 void
819 ptvcursor_free(ptvcursor_t *ptvc)
820 {
821         ptvcursor_free_subtree_levels(ptvc);
822         /*g_free(ptvc);*/
823 }
824
825 /* Returns tvbuff. */
826 tvbuff_t *
827 ptvcursor_tvbuff(ptvcursor_t *ptvc)
828 {
829         return ptvc->tvb;
830 }
831
832 /* Returns current offset. */
833 gint
834 ptvcursor_current_offset(ptvcursor_t *ptvc)
835 {
836         return ptvc->offset;
837 }
838
839 proto_tree *
840 ptvcursor_tree(ptvcursor_t *ptvc)
841 {
842         if (!ptvc)
843                 return NULL;
844
845         return ptvc->tree;
846 }
847
848 void
849 ptvcursor_set_tree(ptvcursor_t *ptvc, proto_tree *tree)
850 {
851         ptvc->tree = tree;
852 }
853
854 /* creates a subtree, sets it as the working tree and pushes the old working tree */
855 proto_tree *
856 ptvcursor_push_subtree(ptvcursor_t *ptvc, proto_item *it, gint ett_subtree)
857 {
858         subtree_lvl *subtree;
859         if (ptvc->pushed_tree_index >= ptvc->pushed_tree_max)
860                 ptvcursor_new_subtree_levels(ptvc);
861
862         subtree = ptvc->pushed_tree + ptvc->pushed_tree_index;
863         subtree->tree = ptvc->tree;
864         subtree->it= NULL;
865         ptvc->pushed_tree_index++;
866         return ptvcursor_set_subtree(ptvc, it, ett_subtree);
867 }
868
869 /* pops a subtree */
870 void
871 ptvcursor_pop_subtree(ptvcursor_t *ptvc)
872 {
873         subtree_lvl *subtree;
874
875         if (ptvc->pushed_tree_index <= 0)
876                 return;
877
878         ptvc->pushed_tree_index--;
879         subtree = ptvc->pushed_tree + ptvc->pushed_tree_index;
880         if (subtree->it != NULL)
881                 proto_item_set_len(subtree->it, ptvcursor_current_offset(ptvc) - subtree->cursor_offset);
882
883         ptvc->tree = subtree->tree;
884 }
885
886 /* saves the current tvb offset and the item in the current subtree level */
887 static void
888 ptvcursor_subtree_set_item(ptvcursor_t *ptvc, proto_item *it)
889 {
890         subtree_lvl *subtree;
891
892         DISSECTOR_ASSERT(ptvc->pushed_tree_index > 0);
893
894         subtree                = ptvc->pushed_tree + ptvc->pushed_tree_index - 1;
895         subtree->it            = it;
896         subtree->cursor_offset = ptvcursor_current_offset(ptvc);
897 }
898
899 /* Creates a subtree and adds it to the cursor as the working tree but does not
900  * save the old working tree */
901 proto_tree *
902 ptvcursor_set_subtree(ptvcursor_t *ptvc, proto_item *it, gint ett_subtree)
903 {
904         ptvc->tree = proto_item_add_subtree(it, ett_subtree);
905         return ptvc->tree;
906 }
907
908 static proto_tree *
909 ptvcursor_add_subtree_item(ptvcursor_t *ptvc, proto_item *it, gint ett_subtree, gint length)
910 {
911         ptvcursor_push_subtree(ptvc, it, ett_subtree);
912         if (length == SUBTREE_UNDEFINED_LENGTH)
913                 ptvcursor_subtree_set_item(ptvc, it);
914         return ptvcursor_tree(ptvc);
915 }
916
917 /* Add an item to the tree and create a subtree
918  * If the length is unknown, length may be defined as SUBTREE_UNDEFINED_LENGTH.
919  * In this case, when the subtree will be closed, the parent item length will
920  * be equal to the advancement of the cursor since the creation of the subtree.
921  */
922 proto_tree *
923 ptvcursor_add_with_subtree(ptvcursor_t *ptvc, int hfindex, gint length,
924                            const guint encoding, gint ett_subtree)
925 {
926         proto_item *it;
927
928         it = ptvcursor_add_no_advance(ptvc, hfindex, length, encoding);
929         return ptvcursor_add_subtree_item(ptvc, it, ett_subtree, length);
930 }
931
932 static proto_item *
933 proto_tree_add_text_node(proto_tree *tree, tvbuff_t *tvb, gint start, gint length);
934
935 /* Add a text node to the tree and create a subtree
936  * If the length is unknown, length may be defined as SUBTREE_UNDEFINED_LENGTH.
937  * In this case, when the subtree will be closed, the item length will be equal
938  * to the advancement of the cursor since the creation of the subtree.
939  */
940 proto_tree *
941 ptvcursor_add_text_with_subtree(ptvcursor_t *ptvc, gint length,
942                                 gint ett_subtree, const char *format, ...)
943 {
944         proto_item        *pi;
945         va_list            ap;
946         header_field_info *hfinfo;
947         proto_tree        *tree;
948
949         tree = ptvcursor_tree(ptvc);
950
951         TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
952
953         pi = proto_tree_add_text_node(tree, ptvcursor_tvbuff(ptvc),
954                                       ptvcursor_current_offset(ptvc), length);
955
956         TRY_TO_FAKE_THIS_REPR(pi);
957
958         va_start(ap, format);
959         proto_tree_set_representation(pi, format, ap);
960         va_end(ap);
961
962         return ptvcursor_add_subtree_item(ptvc, pi, ett_subtree, length);
963 }
964
965 /* Add a text-only node, leaving it to our caller to fill the text in */
966 static proto_item *
967 proto_tree_add_text_node(proto_tree *tree, tvbuff_t *tvb, gint start, gint length)
968 {
969         proto_item *pi;
970
971         if (tree == NULL)
972                 return NULL;
973
974         pi = proto_tree_add_pi(tree, &hfi_text_only, tvb, start, &length);
975
976         return pi;
977 }
978
979 /* Add a text-only node to the proto_tree */
980 proto_item *
981 proto_tree_add_text(proto_tree *tree, tvbuff_t *tvb, gint start, gint length,
982                     const char *format, ...)
983 {
984         proto_item        *pi;
985         va_list            ap;
986         header_field_info *hfinfo;
987
988         TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
989
990         pi = proto_tree_add_text_node(tree, tvb, start, length);
991
992         TRY_TO_FAKE_THIS_REPR(pi);
993
994         va_start(ap, format);
995         proto_tree_set_representation(pi, format, ap);
996         va_end(ap);
997
998         return pi;
999 }
1000
1001 /* Add a text-only node to the proto_tree (va_list version) */
1002 proto_item *
1003 proto_tree_add_text_valist(proto_tree *tree, tvbuff_t *tvb, gint start,
1004                            gint length, const char *format, va_list ap)
1005 {
1006         proto_item        *pi;
1007         header_field_info *hfinfo;
1008
1009         TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
1010
1011         pi = proto_tree_add_text_node(tree, tvb, start, length);
1012
1013         TRY_TO_FAKE_THIS_REPR(pi);
1014
1015         proto_tree_set_representation(pi, format, ap);
1016
1017         return pi;
1018 }
1019
1020 /* Add a text-only node for debugging purposes. The caller doesn't need
1021  * to worry about tvbuff, start, or length. Debug message gets sent to
1022  * STDOUT, too */
1023 proto_item *
1024 proto_tree_add_debug_text(proto_tree *tree, const char *format, ...)
1025 {
1026         proto_item *pi;
1027         va_list     ap;
1028
1029         pi = proto_tree_add_text_node(tree, NULL, 0, 0);
1030
1031         if (pi) {
1032                 va_start(ap, format);
1033                 proto_tree_set_representation(pi, format, ap);
1034                 va_end(ap);
1035         }
1036         va_start(ap, format);
1037         vprintf(format, ap);
1038         va_end(ap);
1039         printf("\n");
1040
1041         return pi;
1042 }
1043
1044 /* We could probably get away with changing is_error to a minimum length value. */
1045 static void
1046 report_type_length_mismatch(proto_tree *tree, const gchar *descr, int length, gboolean is_error) {
1047         if (tree) {
1048                 tree_data_t *tree_data = PTREE_DATA(tree);
1049                 field_info *fi_save = tree_data->fi_tmp;
1050
1051                 /* Keep the current item from getting freed by proto_tree_new_item. */
1052                 tree_data->fi_tmp = NULL;
1053
1054                 expert_add_info_format(NULL, tree, PI_MALFORMED, is_error ? PI_ERROR : PI_WARN, "Trying to fetch %s with length %d", descr, length);
1055
1056                 tree_data->fi_tmp = fi_save;
1057         }
1058
1059         if (is_error) {
1060                 THROW(ReportedBoundsError);
1061         }
1062 }
1063
1064 static guint32
1065 get_uint_value(proto_tree *tree, tvbuff_t *tvb, gint offset, gint length, const guint encoding)
1066 {
1067         guint32 value;
1068         gboolean length_error;
1069
1070         switch (length) {
1071
1072         case 1:
1073                 value = tvb_get_guint8(tvb, offset);
1074                 break;
1075
1076         case 2:
1077                 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letohs(tvb, offset)
1078                                                        : tvb_get_ntohs(tvb, offset);
1079                 break;
1080
1081         case 3:
1082                 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letoh24(tvb, offset)
1083                                                        : tvb_get_ntoh24(tvb, offset);
1084                 break;
1085
1086         case 4:
1087                 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letohl(tvb, offset)
1088                                                        : tvb_get_ntohl(tvb, offset);
1089                 break;
1090
1091         default:
1092                 if (length < 1) {
1093                         length_error = TRUE;
1094                         value = 0;
1095                 } else {
1096                         length_error = FALSE;
1097                         value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letohl(tvb, offset)
1098                                                                : tvb_get_ntohl(tvb, offset);
1099                 }
1100                 report_type_length_mismatch(tree, "an unsigned integer", length, length_error);
1101                 break;
1102         }
1103         return value;
1104 }
1105
1106 /*
1107  * NOTE: to support code written when proto_tree_add_item() took a
1108  * gboolean as its last argument, with FALSE meaning "big-endian"
1109  * and TRUE meaning "little-endian", we treat any non-zero value of
1110  * "encoding" as meaning "little-endian".
1111  */
1112 static gint32
1113 get_int_value(proto_tree *tree, tvbuff_t *tvb, gint offset, gint length, const guint encoding)
1114 {
1115         gint32 value;
1116         gboolean length_error;
1117
1118         switch (length) {
1119
1120         case 1:
1121                 value = (gint8)tvb_get_guint8(tvb, offset);
1122                 break;
1123
1124         case 2:
1125                 value = (gint16) (encoding ? tvb_get_letohs(tvb, offset)
1126                                            : tvb_get_ntohs(tvb, offset));
1127                 break;
1128
1129         case 3:
1130                 value = encoding ? tvb_get_letoh24(tvb, offset)
1131                                  : tvb_get_ntoh24(tvb, offset);
1132                 if (value & 0x00800000) {
1133                         /* Sign bit is set; sign-extend it. */
1134                         value |= 0xFF000000;
1135                 }
1136                 break;
1137
1138         case 4:
1139                 value = encoding ? tvb_get_letohl(tvb, offset)
1140                                  : tvb_get_ntohl(tvb, offset);
1141                 break;
1142
1143         default:
1144                 if (length < 1) {
1145                         length_error = TRUE;
1146                         value = 0;
1147                 } else {
1148                         length_error = FALSE;
1149                         value = encoding ? tvb_get_letohl(tvb, offset)
1150                                          : tvb_get_ntohl(tvb, offset);
1151                 }
1152                 report_type_length_mismatch(tree, "a signed integer", length, length_error);
1153                 break;
1154         }
1155         return value;
1156 }
1157
1158 static void
1159 tree_data_add_maybe_interesting_field(tree_data_t *tree_data, field_info *fi)
1160 {
1161         const header_field_info *hfinfo = fi->hfinfo;
1162
1163         if (hfinfo->ref_type == HF_REF_TYPE_DIRECT) {
1164                 GPtrArray *ptrs = NULL;
1165
1166                 if (tree_data->interesting_hfids == NULL) {
1167                         /* Initialize the hash because we now know that it is needed */
1168                         tree_data->interesting_hfids =
1169                                 g_hash_table_new(g_direct_hash, NULL /* g_direct_equal */);
1170                 } else
1171                         ptrs = (GPtrArray *)g_hash_table_lookup(tree_data->interesting_hfids,
1172                                            GINT_TO_POINTER(hfinfo->id));
1173                 if (!ptrs) {
1174                         /* First element triggers the creation of pointer array */
1175                         ptrs = g_ptr_array_new();
1176                         g_hash_table_insert(tree_data->interesting_hfids,
1177                                             GINT_TO_POINTER(hfinfo->id), ptrs);
1178                 }
1179
1180                 g_ptr_array_add(ptrs, fi);
1181         }
1182 }
1183
1184 /* Add an item to a proto_tree, using the text label registered to that item;
1185    the item is extracted from the tvbuff handed to it. */
1186 static proto_item *
1187 proto_tree_new_item(field_info *new_fi, proto_tree *tree,
1188                     tvbuff_t *tvb, gint start, gint length,
1189                     guint encoding)
1190 {
1191         tree_data_t *tree_data = PTREE_DATA(tree);
1192         proto_item *pi;
1193         guint32     value, n;
1194         float       floatval;
1195         double      doubleval;
1196         const char *string;
1197         nstime_t    time_stamp;
1198         guint32     tmpsecs;
1199         gboolean    length_error;
1200
1201         /* there is a possibility here that we might raise an exception
1202          * and thus would lose track of the field_info.
1203          * store it in a temp so that if we come here again we can reclaim
1204          * the field_info without leaking memory.
1205          */
1206         if (tree_data->fi_tmp) {
1207                 /* oops, last one we got must have been lost due
1208                  * to an exception.
1209                  * good thing we saved it, now we can reverse the
1210                  * memory leak and reclaim it.
1211                  */
1212                 FIELD_INFO_FREE(tree_data->fi_tmp);
1213         }
1214         /* we might throw an exception, keep track of this one
1215          * across the "dangerous" section below.
1216         */
1217         tree_data->fi_tmp = new_fi;
1218
1219         switch (new_fi->hfinfo->type) {
1220                 case FT_NONE:
1221                         /* no value to set for FT_NONE */
1222                         break;
1223
1224                 case FT_PROTOCOL:
1225                         proto_tree_set_protocol_tvb(new_fi, tvb);
1226                         break;
1227
1228                 case FT_BYTES:
1229                         proto_tree_set_bytes_tvb(new_fi, tvb, start, length);
1230                         break;
1231
1232                 case FT_UINT_BYTES:
1233                         /*
1234                          * Map all non-zero values to little-endian for
1235                          * backwards compatibility.
1236                          */
1237                         if (encoding)
1238                                 encoding = ENC_LITTLE_ENDIAN;
1239                         n = get_uint_value(tree, tvb, start, length, encoding);
1240                         proto_tree_set_bytes_tvb(new_fi, tvb, start + length, n);
1241
1242                         /* Instead of calling proto_item_set_len(), since we don't yet
1243                          * have a proto_item, we set the field_info's length ourselves. */
1244                         new_fi->length = n + length;
1245                         break;
1246
1247                 case FT_BOOLEAN:
1248                         /*
1249                          * Map all non-zero values to little-endian for
1250                          * backwards compatibility.
1251                          */
1252                         if (encoding)
1253                                 encoding = ENC_LITTLE_ENDIAN;
1254                         proto_tree_set_boolean(new_fi,
1255                                 get_uint_value(tree, tvb, start, length, encoding));
1256                         break;
1257
1258                 /* XXX - make these just FT_UINT? */
1259                 case FT_UINT8:
1260                 case FT_UINT16:
1261                 case FT_UINT24:
1262                 case FT_UINT32:
1263                         /*
1264                          * Map all non-zero values to little-endian for
1265                          * backwards compatibility.
1266                          */
1267                         if (encoding)
1268                                 encoding = ENC_LITTLE_ENDIAN;
1269                         proto_tree_set_uint(new_fi,
1270                                 get_uint_value(tree, tvb, start, length, encoding));
1271                         break;
1272
1273                 case FT_INT64:
1274                 case FT_UINT64:
1275                         /*
1276                          * Map all non-zero values to little-endian for
1277                          * backwards compatibility.
1278                          */
1279                         if (encoding)
1280                                 encoding = ENC_LITTLE_ENDIAN;
1281                         if (length < 1 || length > 8) {
1282                                 length_error = length < 1 ? TRUE : FALSE;
1283                                 report_type_length_mismatch(tree, "a 64-bit integer", length, length_error);
1284                         }
1285                         proto_tree_set_uint64_tvb(new_fi, tvb, start, length, encoding);
1286                         break;
1287
1288                 /* XXX - make these just FT_INT? */
1289                 case FT_INT8:
1290                 case FT_INT16:
1291                 case FT_INT24:
1292                 case FT_INT32:
1293                         /*
1294                          * Map all non-zero values to little-endian for
1295                          * backwards compatibility.
1296                          */
1297                         if (encoding)
1298                                 encoding = ENC_LITTLE_ENDIAN;
1299                         proto_tree_set_int(new_fi,
1300                                 get_int_value(tree, tvb, start, length, encoding));
1301                         break;
1302
1303                 case FT_IPv4:
1304                         /*
1305                          * Map all non-zero values to little-endian for
1306                          * backwards compatibility.
1307                          */
1308                         if (encoding)
1309                                 encoding = ENC_LITTLE_ENDIAN;
1310                         if (length != FT_IPv4_LEN) {
1311                                 length_error = length < FT_IPv4_LEN ? TRUE : FALSE;
1312                                 report_type_length_mismatch(tree, "an IPv4 address", length, length_error);
1313                         }
1314                         value = tvb_get_ipv4(tvb, start);
1315                         /*
1316                          * NOTE: to support code written when
1317                          * proto_tree_add_item() took a gboolean as its
1318                          * last argument, with FALSE meaning "big-endian"
1319                          * and TRUE meaning "little-endian", we treat any
1320                          * non-zero value of "encoding" as meaning
1321                          * "little-endian".
1322                          */
1323                         proto_tree_set_ipv4(new_fi, encoding ? GUINT32_SWAP_LE_BE(value) : value);
1324                         break;
1325
1326                 case FT_IPXNET:
1327                         if (length != FT_IPXNET_LEN) {
1328                                 length_error = length < FT_IPXNET_LEN ? TRUE : FALSE;
1329                                 report_type_length_mismatch(tree, "an IPXNET address", length, length_error);
1330                         }
1331                         proto_tree_set_ipxnet(new_fi,
1332                                 get_uint_value(tree, tvb, start, FT_IPXNET_LEN, ENC_BIG_ENDIAN));
1333                         break;
1334
1335                 case FT_IPv6:
1336                         if (length != FT_IPv6_LEN) {
1337                                 length_error = length < FT_IPv6_LEN ? TRUE : FALSE;
1338                                 report_type_length_mismatch(tree, "an IPv6 address", length, length_error);
1339                         }
1340                         proto_tree_set_ipv6_tvb(new_fi, tvb, start, length);
1341                         break;
1342
1343                 case FT_AX25:
1344                         if (length != 7) {
1345                                 length_error = length < 7 ? TRUE : FALSE;
1346                                 report_type_length_mismatch(tree, "an AX.25 address", length, length_error);
1347                         }
1348                         proto_tree_set_ax25_tvb(new_fi, tvb, start);
1349                         break;
1350
1351                 case FT_VINES:
1352                         if (length != VINES_ADDR_LEN) {
1353                                 length_error = length < VINES_ADDR_LEN ? TRUE : FALSE;
1354                                 report_type_length_mismatch(tree, "a Vines address", length, length_error);
1355                         }
1356                         proto_tree_set_vines_tvb(new_fi, tvb, start);
1357                         break;
1358
1359                 case FT_ETHER:
1360                         if (length != FT_ETHER_LEN) {
1361                                 length_error = length < FT_ETHER_LEN ? TRUE : FALSE;
1362                                 report_type_length_mismatch(tree, "an Ethernet", length, length_error);
1363                         }
1364                         proto_tree_set_ether_tvb(new_fi, tvb, start);
1365                         break;
1366
1367                 case FT_EUI64:
1368                         /*
1369                          * Map all non-zero values to little-endian for
1370                          * backwards compatibility.
1371                          */
1372                         if (encoding)
1373                                 encoding = ENC_LITTLE_ENDIAN;
1374                         if (length != FT_EUI64_LEN) {
1375                                 length_error = length < FT_EUI64_LEN ? TRUE : FALSE;
1376                                 report_type_length_mismatch(tree, "an EUI-64 address", length, length_error);
1377                         }
1378                         proto_tree_set_eui64_tvb(new_fi, tvb, start, encoding);
1379                         break;
1380                 case FT_GUID:
1381                         /*
1382                          * Map all non-zero values to little-endian for
1383                          * backwards compatibility.
1384                          */
1385                         if (encoding)
1386                                 encoding = ENC_LITTLE_ENDIAN;
1387                         if (length != FT_GUID_LEN) {
1388                                 length_error = length < FT_GUID_LEN ? TRUE : FALSE;
1389                                 report_type_length_mismatch(tree, "a GUID", length, length_error);
1390                         }
1391                         proto_tree_set_guid_tvb(new_fi, tvb, start, encoding);
1392                         break;
1393
1394                 case FT_OID:
1395                         proto_tree_set_oid_tvb(new_fi, tvb, start, length);
1396                         break;
1397
1398                 case FT_FLOAT:
1399                         /*
1400                          * NOTE: to support code written when
1401                          * proto_tree_add_item() took a gboolean as its
1402                          * last argument, with FALSE meaning "big-endian"
1403                          * and TRUE meaning "little-endian", we treat any
1404                          * non-zero value of "encoding" as meaning
1405                          * "little-endian".
1406                          *
1407                          * At some point in the future, we might
1408                          * support non-IEEE-binary floating-point
1409                          * formats in the encoding as well
1410                          * (IEEE decimal, System/3x0, VAX).
1411                          */
1412                         if (encoding)
1413                                 encoding = ENC_LITTLE_ENDIAN;
1414                         if (length != 4) {
1415                                 length_error = length < 4 ? TRUE : FALSE;
1416                                 report_type_length_mismatch(tree, "a single-precision floating point number", length, length_error);
1417                         }
1418                         if (encoding)
1419                                 floatval = tvb_get_letohieee_float(tvb, start);
1420                         else
1421                                 floatval = tvb_get_ntohieee_float(tvb, start);
1422                         proto_tree_set_float(new_fi, floatval);
1423                         break;
1424
1425                 case FT_DOUBLE:
1426                         /*
1427                          * NOTE: to support code written when
1428                          * proto_tree_add_item() took a gboolean as its
1429                          * last argument, with FALSE meaning "big-endian"
1430                          * and TRUE meaning "little-endian", we treat any
1431                          * non-zero value of "encoding" as meaning
1432                          * "little-endian".
1433                          *
1434                          * At some point in the future, we might
1435                          * support non-IEEE-binary floating-point
1436                          * formats in the encoding as well
1437                          * (IEEE decimal, System/3x0, VAX).
1438                          */
1439                         if (encoding == TRUE)
1440                                 encoding = ENC_LITTLE_ENDIAN;
1441                         if (length != 8) {
1442                                 length_error = length < 8 ? TRUE : FALSE;
1443                                 report_type_length_mismatch(tree, "a double-precision floating point number", length, length_error);
1444                         }
1445                         if (encoding)
1446                                 doubleval = tvb_get_letohieee_double(tvb, start);
1447                         else
1448                                 doubleval = tvb_get_ntohieee_double(tvb, start);
1449                         proto_tree_set_double(new_fi, doubleval);
1450                         break;
1451
1452                 case FT_STRING:
1453                         proto_tree_set_string_tvb(new_fi, tvb, start, length,
1454                             encoding);
1455                         break;
1456
1457                 case FT_STRINGZ:
1458                         if (length < -1 ) {
1459                                 report_type_length_mismatch(tree, "a string", length, TRUE);
1460                         }
1461                         /* Instead of calling proto_item_set_len(),
1462                          * since we don't yet have a proto_item, we
1463                          * set the field_info's length ourselves.
1464                          *
1465                          * XXX - our caller can't use that length to
1466                          * advance an offset unless they arrange that
1467                          * there always be a protocol tree into which
1468                          * we're putting this item.
1469                          */
1470                         if (length == -1) {
1471                                 /* This can throw an exception */
1472                                 string = tvb_get_stringz_enc(tvb, start, &length, encoding);
1473                         } else if (length == 0) {
1474                                 string = "[Empty]";
1475                         } else {
1476                                 /* In this case, length signifies
1477                                  * the length of the string.
1478                                  *
1479                                  * This could either be a null-padded
1480                                  * string, which doesn't necessarily
1481                                  * have a '\0' at the end, or a
1482                                  * null-terminated string, with a
1483                                  * trailing '\0'.  (Yes, there are
1484                                  * cases where you have a string
1485                                  * that's both counted and null-
1486                                  * terminated.)
1487                                  *
1488                                  * In the first case, we must
1489                                  * allocate a buffer of length
1490                                  * "length+1", to make room for
1491                                  * a trailing '\0'.
1492                                  *
1493                                  * In the second case, we don't
1494                                  * assume that there is a trailing
1495                                  * '\0' there, as the packet might
1496                                  * be malformed.  (XXX - should we
1497                                  * throw an exception if there's no
1498                                  * trailing '\0'?)      Therefore, we
1499                                  * allocate a buffer of length
1500                                  * "length+1", and put in a trailing
1501                                  * '\0', just to be safe.
1502                                  *
1503                                  * (XXX - this would change if
1504                                  * we made string values counted
1505                                  * rather than null-terminated.)
1506                                  */
1507                                 string = tvb_get_ephemeral_string_enc(tvb, start, length, encoding);
1508                         }
1509                         new_fi->length = length;
1510                         proto_tree_set_string(new_fi, string);
1511                         break;
1512
1513                 case FT_UINT_STRING:
1514                         /*
1515                          * NOTE: to support code written when
1516                          * proto_tree_add_item() took a gboolean as its
1517                          * last argument, with FALSE meaning "big-endian"
1518                          * and TRUE meaning "little-endian", if the
1519                          * encoding value is TRUE, treat that as
1520                          * ASCII with a little-endian length.
1521                          *
1522                          * This won't work for code that passes
1523                          * arbitrary non-zero values; that code
1524                          * will need to be fixed.
1525                          */
1526                         if (encoding == TRUE)
1527                                 encoding = ENC_ASCII|ENC_LITTLE_ENDIAN;
1528                         n = get_uint_value(tree, tvb, start, length, encoding & ~ENC_CHARENCODING_MASK);
1529                         proto_tree_set_string_tvb(new_fi, tvb, start + length, n,
1530                             encoding);
1531
1532                         /* Instead of calling proto_item_set_len(), since we
1533                          * don't yet have a proto_item, we set the
1534                          * field_info's length ourselves.
1535                          *
1536                          * XXX - our caller can't use that length to
1537                          * advance an offset unless they arrange that
1538                          * there always be a protocol tree into which
1539                          * we're putting this item.
1540                          */
1541                         new_fi->length = n + length;
1542                         break;
1543
1544                 case FT_ABSOLUTE_TIME:
1545                         /*
1546                          * Absolute times can be in any of a number of
1547                          * formats, and they can be big-endian or
1548                          * little-endian.
1549                          *
1550                          * Historically FT_TIMEs were only timespecs;
1551                          * the only question was whether they were stored
1552                          * in big- or little-endian format.
1553                          *
1554                          * For backwards compatibility, we interpret an
1555                          * encoding of 1 as meaning "little-endian timespec",
1556                          * so that passing TRUE is interpreted as that.
1557                          */
1558                         if (encoding == TRUE)
1559                                 encoding = ENC_TIME_TIMESPEC|ENC_LITTLE_ENDIAN;
1560
1561                         if (length != 8 && length != 4) {
1562                                 length_error = length < 4 ? TRUE : FALSE;
1563                                 report_type_length_mismatch(tree, "an absolute time value", length, length_error);
1564                         }
1565
1566                         switch (encoding) {
1567
1568                         case ENC_TIME_TIMESPEC|ENC_BIG_ENDIAN:
1569                                 /*
1570                                  * 4-byte UNIX epoch, possibly followed by
1571                                  * 4-byte fractional time in nanoseconds,
1572                                  * both big-endian.
1573                                  */
1574                                 time_stamp.secs  = tvb_get_ntohl(tvb, start);
1575                                 if (length == 8)
1576                                         time_stamp.nsecs = tvb_get_ntohl(tvb, start+4);
1577                                 else
1578                                         time_stamp.nsecs = 0;
1579                                 break;
1580
1581                         case ENC_TIME_TIMESPEC|ENC_LITTLE_ENDIAN:
1582                                 /*
1583                                  * 4-byte UNIX epoch, possibly followed by
1584                                  * 4-byte fractional time in nanoseconds,
1585                                  * both little-endian.
1586                                  */
1587                                 time_stamp.secs  = tvb_get_letohl(tvb, start);
1588                                 if (length == 8)
1589                                         time_stamp.nsecs = tvb_get_letohl(tvb, start+4);
1590                                 else
1591                                         time_stamp.nsecs = 0;
1592                                 break;
1593
1594                         case ENC_TIME_NTP|ENC_BIG_ENDIAN:
1595                                 /*
1596                                  * NTP time stamp, big-endian.
1597                                  */
1598
1599 /* XXX - where should this go? */
1600 #define NTP_BASETIME 2208988800ul
1601
1602                                 /* We need a temporary variable here so the unsigned math
1603                                  * works correctly (for years > 2036 according to RFC 2030
1604                                  * chapter 3).
1605                                  */
1606                                 tmpsecs  = tvb_get_ntohl(tvb, start);
1607                                 if (tmpsecs)
1608                                         time_stamp.secs = tmpsecs - (guint32)NTP_BASETIME;
1609                                 else
1610                                         time_stamp.secs = tmpsecs; /* 0 */
1611
1612                                 if (length == 8) {
1613                                         /*
1614                                          * We're using nanoseconds here (and we will
1615                                          * display nanoseconds), but NTP's timestamps
1616                                          * have a precision in microseconds or greater.
1617                                          * Round to 1 microsecond.
1618                                          */
1619                                         time_stamp.nsecs = (int)(1000000*(tvb_get_ntohl(tvb, start+4)/4294967296.0));
1620                                         time_stamp.nsecs *= 1000;
1621                                 } else {
1622                                         time_stamp.nsecs = 0;
1623                                 }
1624                                 break;
1625
1626                         case ENC_TIME_NTP|ENC_LITTLE_ENDIAN:
1627                                 /*
1628                                  * NTP time stamp, big-endian.
1629                                  */
1630                                 tmpsecs  = tvb_get_letohl(tvb, start);
1631                                 if (tmpsecs)
1632                                         time_stamp.secs = tmpsecs - (guint32)NTP_BASETIME;
1633                                 else
1634                                         time_stamp.secs = tmpsecs; /* 0 */
1635
1636                                 if (length == 8) {
1637                                         /*
1638                                          * We're using nanoseconds here (and we will
1639                                          * display nanoseconds), but NTP's timestamps
1640                                          * have a precision in microseconds or greater.
1641                                          * Round to 1 microsecond.
1642                                          */
1643                                         time_stamp.nsecs = (int)(1000000*(tvb_get_letohl(tvb, start+4)/4294967296.0));
1644                                         time_stamp.nsecs *= 1000;
1645                                 } else {
1646                                         time_stamp.nsecs = 0;
1647                                 }
1648                                 break;
1649
1650                         default:
1651                                 DISSECTOR_ASSERT_NOT_REACHED();
1652                                 time_stamp.secs = 0;
1653                                 time_stamp.nsecs = 0;
1654                                 break;
1655                         }
1656                         proto_tree_set_time(new_fi, &time_stamp);
1657                         break;
1658
1659                 case FT_RELATIVE_TIME:
1660                         /*
1661                          * Relative times can be in any of a number of
1662                          * formats, and they can be big-endian or
1663                          * little-endian.
1664                          *
1665                          * Historically FT_TIMEs were only timespecs;
1666                          * the only question was whether they were stored
1667                          * in big- or little-endian format.
1668                          *
1669                          * For backwards compatibility, we interpret an
1670                          * encoding of 1 as meaning "little-endian timespec",
1671                          * so that passing TRUE is interpreted as that.
1672                          */
1673                         if (encoding == TRUE)
1674                                 encoding = ENC_TIME_TIMESPEC|ENC_LITTLE_ENDIAN;
1675                         switch (encoding) {
1676
1677                         if (length != 8 && length != 4) {
1678                                 length_error = length < 4 ? TRUE : FALSE;
1679                                 report_type_length_mismatch(tree, "a relative time value", length, length_error);
1680                         }
1681
1682                         case ENC_TIME_TIMESPEC|ENC_BIG_ENDIAN:
1683                                 /*
1684                                  * 4-byte UNIX epoch, possibly followed by
1685                                  * 4-byte fractional time in nanoseconds,
1686                                  * both big-endian.
1687                                  */
1688                                 time_stamp.secs  = tvb_get_ntohl(tvb, start);
1689                                 if (length == 8)
1690                                         time_stamp.nsecs = tvb_get_ntohl(tvb, start+4);
1691                                 else
1692                                         time_stamp.nsecs = 0;
1693                                 break;
1694
1695                         case ENC_TIME_TIMESPEC|ENC_LITTLE_ENDIAN:
1696                                 /*
1697                                  * 4-byte UNIX epoch, possibly followed by
1698                                  * 4-byte fractional time in nanoseconds,
1699                                  * both little-endian.
1700                                  */
1701                                 time_stamp.secs  = tvb_get_letohl(tvb, start);
1702                                 if (length == 8)
1703                                         time_stamp.nsecs = tvb_get_letohl(tvb, start+4);
1704                                 else
1705                                         time_stamp.nsecs = 0;
1706                                 break;
1707                         }
1708                         proto_tree_set_time(new_fi, &time_stamp);
1709                         break;
1710
1711                 default:
1712                         g_error("new_fi->hfinfo->type %d (%s) not handled\n",
1713                                         new_fi->hfinfo->type,
1714                                         ftype_name(new_fi->hfinfo->type));
1715                         DISSECTOR_ASSERT_NOT_REACHED();
1716                         break;
1717         }
1718         FI_SET_FLAG(new_fi, (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN);
1719
1720         /* Don't add new node to proto_tree until now so that any exceptions
1721          * raised by a tvbuff access method doesn't leave junk in the proto_tree. */
1722         /* XXX. wouldn't be better to add this item to tree, with some special flag (FI_EXCEPTION?)
1723          *      to know which item caused exception? */
1724         pi = proto_tree_add_node(tree, new_fi);
1725
1726         /* we did not raise an exception so we dont have to remember this
1727          * field_info struct any more.
1728          */
1729         tree_data->fi_tmp = NULL;
1730
1731         return pi;
1732 }
1733
1734 /* Gets data from tvbuff, adds it to proto_tree, increments offset,
1735    and returns proto_item* */
1736 proto_item *
1737 ptvcursor_add(ptvcursor_t *ptvc, int hfindex, gint length,
1738               const guint encoding)
1739 {
1740         field_info        *new_fi;
1741         header_field_info *hfinfo;
1742         gint               item_length;
1743         guint32            n;
1744         int                offset;
1745
1746         /* We can't fake it just yet. We have to advance the cursor
1747         TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfindex, hfinfo); */
1748
1749         offset = ptvc->offset;
1750         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1751         get_hfi_length(hfinfo, ptvc->tvb, offset, &length, &item_length);
1752         ptvc->offset += length;
1753         if (hfinfo->type == FT_UINT_BYTES || hfinfo->type == FT_UINT_STRING) {
1754                 /*
1755                  * The length of the rest of the item is in the first N
1756                  * bytes of the item.
1757                  */
1758                 n = get_uint_value(ptvc->tree, ptvc->tvb, offset, length, encoding);
1759                 ptvc->offset += n;
1760         }
1761
1762         /* Coast clear. Try and fake it */
1763         TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfindex, hfinfo);
1764
1765         new_fi = new_field_info(ptvc->tree, hfinfo, ptvc->tvb, offset, item_length);
1766
1767         return proto_tree_new_item(new_fi, ptvc->tree, ptvc->tvb,
1768                 offset, length, encoding);
1769 }
1770
1771 /*
1772  * Validates that field length bytes are available starting from
1773  * start (pos/neg). Throws an exception if they aren't.
1774  */
1775 static void
1776 test_length(header_field_info *hfinfo, proto_tree *tree, tvbuff_t *tvb,
1777             gint start, gint length, const guint encoding)
1778 {
1779         gint size = length;
1780
1781         if (!tvb)
1782                 return;
1783
1784         if (hfinfo->type == FT_UINT_BYTES || hfinfo->type == FT_UINT_STRING) {
1785                 guint32 n;
1786
1787                 n = get_uint_value(tree, tvb, start, length, encoding);
1788                 if (n > size + n) {
1789                         /* If n > size + n then we have an integer overflow, so
1790                          * set size to -1, which will force the
1791                          * tvb_ensure_bytes_exist call below to throw a
1792                          * ReportedBoundsError
1793                          */
1794                         size = -1;
1795                 }
1796                 else {
1797                         size += n;
1798                 }
1799         } else if (hfinfo->type == FT_STRINGZ) {
1800                 /* If we're fetching until the end of the TVB, only validate
1801                  * that the offset is within range.
1802                  */
1803                 if (length == -1)
1804                         size = 0;
1805         }
1806
1807         tvb_ensure_bytes_exist(tvb, start, size);
1808 }
1809
1810 /* Add an item to a proto_tree, using the text label registered to that item;
1811    the item is extracted from the tvbuff handed to it. */
1812 proto_item *
1813 proto_tree_add_item_new(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
1814                     const gint start, gint length, const guint encoding)
1815 {
1816         field_info        *new_fi;
1817         gint              item_length;
1818
1819         DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");
1820
1821         get_hfi_length(hfinfo, tvb, start, &length, &item_length);
1822         test_length(hfinfo, tree, tvb, start, item_length, encoding);
1823
1824         TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
1825
1826         new_fi = new_field_info(tree, hfinfo, tvb, start, item_length);
1827
1828         if (new_fi == NULL)
1829                 return NULL;
1830
1831         return proto_tree_new_item(new_fi, tree, tvb, start, length, encoding);
1832 }
1833
1834 proto_item *
1835 proto_tree_add_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1836                     const gint start, gint length, const guint encoding)
1837 {
1838         return proto_tree_add_item_new(tree, proto_registrar_get_nth(hfindex), tvb, start, length, encoding);
1839 }
1840
1841 /* Add a FT_NONE to a proto_tree */
1842 proto_item *
1843 proto_tree_add_none_format(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
1844                            const gint start, gint length, const char *format,
1845                            ...)
1846 {
1847         proto_item        *pi;
1848         va_list            ap;
1849         header_field_info *hfinfo;
1850
1851         TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1852
1853         DISSECTOR_ASSERT(hfinfo->type == FT_NONE);
1854
1855         pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
1856
1857         TRY_TO_FAKE_THIS_REPR(pi);
1858
1859         va_start(ap, format);
1860         proto_tree_set_representation(pi, format, ap);
1861         va_end(ap);
1862
1863         /* no value to set for FT_NONE */
1864         return pi;
1865 }
1866
1867 /* Gets data from tvbuff, adds it to proto_tree, *DOES NOT* increment
1868  * offset, and returns proto_item* */
1869 proto_item *
1870 ptvcursor_add_no_advance(ptvcursor_t* ptvc, int hf, gint length,
1871                          const guint encoding)
1872 {
1873         proto_item *item;
1874
1875         item = proto_tree_add_item(ptvc->tree, hf, ptvc->tvb, ptvc->offset,
1876                                    length, encoding);
1877
1878         return item;
1879 }
1880
1881 /* Advance the ptvcursor's offset within its tvbuff without
1882  * adding anything to the proto_tree. */
1883 void
1884 ptvcursor_advance(ptvcursor_t* ptvc, gint length)
1885 {
1886         ptvc->offset += length;
1887 }
1888
1889
1890 static void
1891 proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb)
1892 {
1893         fvalue_set(&fi->value, tvb, TRUE);
1894 }
1895
1896 /* Add a FT_PROTOCOL to a proto_tree */
1897 proto_item *
1898 proto_tree_add_protocol_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1899                                gint start, gint length, const char *format, ...)
1900 {
1901         proto_item        *pi;
1902         va_list            ap;
1903         header_field_info *hfinfo;
1904
1905         TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1906
1907         DISSECTOR_ASSERT(hfinfo->type == FT_PROTOCOL);
1908
1909         pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
1910
1911         proto_tree_set_protocol_tvb(PNODE_FINFO(pi), (start == 0 ? tvb : tvb_new_subset(tvb, start, length, length)));
1912
1913         TRY_TO_FAKE_THIS_REPR(pi);
1914
1915         va_start(ap, format);
1916         proto_tree_set_representation(pi, format, ap);
1917         va_end(ap);
1918
1919         return pi;
1920 }
1921
1922
1923 /* Add a FT_BYTES to a proto_tree */
1924 proto_item *
1925 proto_tree_add_bytes(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1926                      gint length, const guint8 *start_ptr)
1927 {
1928         proto_item        *pi;
1929         header_field_info *hfinfo;
1930
1931         TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1932
1933         DISSECTOR_ASSERT(hfinfo->type == FT_BYTES);
1934
1935         pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
1936         proto_tree_set_bytes(PNODE_FINFO(pi), start_ptr, length);
1937
1938         return pi;
1939 }
1940
1941 proto_item *
1942 proto_tree_add_bytes_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1943                                   gint start, gint length,
1944                                   const guint8 *start_ptr,
1945                                   const char *format, ...)
1946 {
1947         proto_item        *pi;
1948         va_list            ap;
1949         header_field_info *hfinfo;
1950
1951         TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1952
1953         if (start_ptr)
1954                 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length,
1955                                           start_ptr);
1956         else
1957                 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length,
1958                                           tvb_get_ptr(tvb, start, length));
1959
1960         va_start(ap, format);
1961         proto_tree_set_representation_value(pi, format, ap);
1962         va_end(ap);
1963
1964         return pi;
1965 }
1966
1967 proto_item *
1968 proto_tree_add_bytes_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1969                             gint start, gint length, const guint8 *start_ptr,
1970                             const char *format, ...)
1971 {
1972         proto_item        *pi;
1973         va_list            ap;
1974         header_field_info *hfinfo;
1975
1976         TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1977
1978         if (start_ptr)
1979                 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length,
1980                                           start_ptr);
1981         else
1982                 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length,
1983                                           tvb_get_ptr(tvb, start, length));
1984
1985         TRY_TO_FAKE_THIS_REPR(pi);
1986
1987         va_start(ap, format);
1988         proto_tree_set_representation(pi, format, ap);
1989         va_end(ap);
1990
1991         return pi;
1992 }
1993
1994 static void
1995 proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length)
1996 {
1997         GByteArray *bytes;
1998
1999         bytes = g_byte_array_new();
2000         if (length > 0) {
2001                 g_byte_array_append(bytes, start_ptr, length);
2002         }
2003         fvalue_set(&fi->value, bytes, TRUE);
2004 }
2005
2006
2007 static void
2008 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length)
2009 {
2010         proto_tree_set_bytes(fi, tvb_get_ptr(tvb, offset, length), length);
2011 }
2012
2013 /* Add a FT_*TIME to a proto_tree */
2014 proto_item *
2015 proto_tree_add_time(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2016                     gint length, nstime_t *value_ptr)
2017 {
2018         proto_item        *pi;
2019         header_field_info *hfinfo;
2020
2021         TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2022
2023         DISSECTOR_ASSERT(hfinfo->type == FT_ABSOLUTE_TIME ||
2024                          hfinfo->type == FT_RELATIVE_TIME);
2025
2026         pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
2027         proto_tree_set_time(PNODE_FINFO(pi), value_ptr);
2028
2029         return pi;
2030 }
2031
2032 proto_item *
2033 proto_tree_add_time_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2034                                  gint start, gint length, nstime_t *value_ptr,
2035                                  const char *format, ...)
2036 {
2037         proto_item        *pi;
2038         va_list            ap;
2039
2040         pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
2041         if (pi != tree) {
2042                 va_start(ap, format);
2043                 proto_tree_set_representation_value(pi, format, ap);
2044                 va_end(ap);
2045         }
2046
2047         return pi;
2048 }
2049
2050 proto_item *
2051 proto_tree_add_time_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2052                            gint start, gint length, nstime_t *value_ptr,
2053                            const char *format, ...)
2054 {
2055         proto_item        *pi;
2056         va_list            ap;
2057
2058         pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
2059         if (pi != tree) {
2060                 TRY_TO_FAKE_THIS_REPR(pi);
2061
2062                 va_start(ap, format);
2063                 proto_tree_set_representation(pi, format, ap);
2064                 va_end(ap);
2065         }
2066
2067         return pi;
2068 }
2069
2070 /* Set the FT_*TIME value */
2071 static void
2072 proto_tree_set_time(field_info *fi, nstime_t *value_ptr)
2073 {
2074         DISSECTOR_ASSERT(value_ptr != NULL);
2075
2076         fvalue_set(&fi->value, value_ptr, FALSE);
2077 }
2078
2079 /* Add a FT_IPXNET to a proto_tree */
2080 proto_item *
2081 proto_tree_add_ipxnet(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2082                       gint length, guint32 value)
2083 {
2084         proto_item        *pi;
2085         header_field_info *hfinfo;
2086
2087         TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2088
2089         DISSECTOR_ASSERT(hfinfo->type == FT_IPXNET);
2090
2091         pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
2092         proto_tree_set_ipxnet(PNODE_FINFO(pi), value);
2093
2094         return pi;
2095 }
2096
2097 proto_item *
2098 proto_tree_add_ipxnet_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2099                                    gint start, gint length, guint32 value,
2100                                    const char *format, ...)
2101 {
2102         proto_item        *pi;
2103         va_list            ap;
2104
2105         pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
2106         if (pi != tree) {
2107                 va_start(ap, format);
2108                 proto_tree_set_representation_value(pi, format, ap);
2109                 va_end(ap);
2110         }
2111
2112         return pi;
2113 }
2114
2115 proto_item *
2116 proto_tree_add_ipxnet_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2117                              gint start, gint length, guint32 value,
2118                              const char *format, ...)
2119 {
2120         proto_item        *pi;
2121         va_list            ap;
2122
2123         pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
2124         if (pi != tree) {
2125                 TRY_TO_FAKE_THIS_REPR(pi);
2126
2127                 va_start(ap, format);
2128                 proto_tree_set_representation(pi, format, ap);
2129                 va_end(ap);
2130         }
2131
2132         return pi;
2133 }
2134
2135 /* Set the FT_IPXNET value */
2136 static void
2137 proto_tree_set_ipxnet(field_info *fi, guint32 value)
2138 {
2139         fvalue_set_uinteger(&fi->value, value);
2140 }
2141
2142 /* Add a FT_IPv4 to a proto_tree */
2143 proto_item *
2144 proto_tree_add_ipv4(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2145                     gint length, guint32 value)
2146 {
2147         proto_item        *pi;
2148         header_field_info *hfinfo;
2149
2150         TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2151
2152         DISSECTOR_ASSERT(hfinfo->type == FT_IPv4);
2153
2154         pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
2155         proto_tree_set_ipv4(PNODE_FINFO(pi), value);
2156
2157         return pi;
2158 }
2159
2160 proto_item *
2161 proto_tree_add_ipv4_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2162                                  gint start, gint length, guint32 value,
2163                                  const char *format, ...)
2164 {
2165         proto_item        *pi;
2166         va_list            ap;
2167
2168         pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
2169         if (pi != tree) {
2170                 va_start(ap, format);
2171                 proto_tree_set_representation_value(pi, format, ap);
2172                 va_end(ap);
2173         }
2174
2175         return pi;
2176 }
2177
2178 proto_item *
2179 proto_tree_add_ipv4_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2180                            gint start, gint length, guint32 value,
2181                            const char *format, ...)
2182 {
2183         proto_item        *pi;
2184         va_list            ap;
2185
2186         pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
2187         if (pi != tree) {
2188                 TRY_TO_FAKE_THIS_REPR(pi);
2189
2190                 va_start(ap, format);
2191                 proto_tree_set_representation(pi, format, ap);
2192                 va_end(ap);
2193         }
2194
2195         return pi;
2196 }
2197
2198 /* Set the FT_IPv4 value */
2199 static void
2200 proto_tree_set_ipv4(field_info *fi, guint32 value)
2201 {
2202         fvalue_set_uinteger(&fi->value, value);
2203 }
2204
2205 /* Add a FT_IPv6 to a proto_tree */
2206 proto_item *
2207 proto_tree_add_ipv6(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2208                     gint length, const guint8* value_ptr)
2209 {
2210         proto_item        *pi;
2211         header_field_info *hfinfo;
2212
2213         TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2214
2215         DISSECTOR_ASSERT(hfinfo->type == FT_IPv6);
2216
2217         pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
2218         proto_tree_set_ipv6(PNODE_FINFO(pi), value_ptr);
2219
2220         return pi;
2221 }
2222
2223 proto_item *
2224 proto_tree_add_ipv6_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2225                                  gint start, gint length,
2226                                  const guint8* value_ptr,
2227                                  const char *format, ...)
2228 {
2229         proto_item        *pi;
2230         va_list            ap;
2231
2232         pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
2233         if (pi != tree) {
2234                 va_start(ap, format);
2235                 proto_tree_set_representation_value(pi, format, ap);
2236                 va_end(ap);
2237         }
2238
2239         return pi;
2240 }
2241
2242 proto_item *
2243 proto_tree_add_ipv6_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2244                            gint start, gint length, const guint8* value_ptr,
2245                            const char *format, ...)
2246 {
2247         proto_item        *pi;
2248         va_list            ap;
2249
2250         pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
2251         if (pi != tree) {
2252                 TRY_TO_FAKE_THIS_REPR(pi);
2253
2254                 va_start(ap, format);
2255                 proto_tree_set_representation(pi, format, ap);
2256                 va_end(ap);
2257         }
2258
2259         return pi;
2260 }
2261
2262 /* Set the FT_IPv6 value */
2263 static void
2264 proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr)
2265 {
2266         DISSECTOR_ASSERT(value_ptr != NULL);
2267         fvalue_set(&fi->value, (gpointer) value_ptr, FALSE);
2268 }
2269
2270 static void
2271 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
2272 {
2273         proto_tree_set_ipv6(fi, tvb_get_ptr(tvb, start, length));
2274 }
2275
2276 /* Add a FT_GUID to a proto_tree */
2277 proto_item *
2278 proto_tree_add_guid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2279                     gint length, const e_guid_t *value_ptr)
2280 {
2281         proto_item        *pi;
2282         header_field_info *hfinfo;
2283
2284         TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2285
2286         DISSECTOR_ASSERT(hfinfo->type == FT_GUID);
2287
2288         pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
2289         proto_tree_set_guid(PNODE_FINFO(pi), value_ptr);
2290
2291         return pi;
2292 }
2293
2294 proto_item *
2295 proto_tree_add_guid_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2296                                  gint start, gint length,
2297                                  const e_guid_t *value_ptr,
2298                                  const char *format, ...)
2299 {
2300         proto_item        *pi;
2301         va_list            ap;
2302
2303         pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
2304         if (pi != tree) {
2305                 va_start(ap, format);
2306                 proto_tree_set_representation_value(pi, format, ap);
2307                 va_end(ap);
2308         }
2309
2310         return pi;
2311 }
2312
2313 proto_item *
2314 proto_tree_add_guid_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2315                            gint start, gint length, const e_guid_t *value_ptr,
2316                            const char *format, ...)
2317 {
2318         proto_item        *pi;
2319         va_list            ap;
2320
2321         pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
2322         if (pi != tree) {
2323                 TRY_TO_FAKE_THIS_REPR(pi);
2324
2325                 va_start(ap, format);
2326                 proto_tree_set_representation(pi, format, ap);
2327                 va_end(ap);
2328         }
2329
2330         return pi;
2331 }
2332
2333 /* Set the FT_GUID value */
2334 static void
2335 proto_tree_set_guid(field_info *fi, const e_guid_t *value_ptr)
2336 {
2337         DISSECTOR_ASSERT(value_ptr != NULL);
2338         fvalue_set(&fi->value, (gpointer) value_ptr, FALSE);
2339 }
2340
2341 static void
2342 proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, gint start,
2343                         const guint encoding)
2344 {
2345         e_guid_t guid;
2346
2347         tvb_get_guid(tvb, start, &guid, encoding);
2348         proto_tree_set_guid(fi, &guid);
2349 }
2350
2351 /* Add a FT_OID to a proto_tree */
2352 proto_item *
2353 proto_tree_add_oid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2354                    gint length, const guint8* value_ptr)
2355 {
2356         proto_item        *pi;
2357         header_field_info *hfinfo;
2358
2359         TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2360
2361         DISSECTOR_ASSERT(hfinfo->type == FT_OID);
2362
2363         pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
2364         proto_tree_set_oid(PNODE_FINFO(pi), value_ptr, length);
2365
2366         return pi;
2367 }
2368
2369 proto_item *
2370 proto_tree_add_oid_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2371                                 gint start, gint length,
2372                                 const guint8* value_ptr,
2373                                 const char *format, ...)
2374 {
2375         proto_item        *pi;
2376         va_list            ap;
2377
2378         pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
2379         if (pi != tree) {
2380                 va_start(ap, format);
2381                 proto_tree_set_representation_value(pi, format, ap);
2382                 va_end(ap);
2383         }
2384
2385         return pi;
2386 }
2387
2388 proto_item *
2389 proto_tree_add_oid_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2390                           gint start, gint length, const guint8* value_ptr,
2391                           const char *format, ...)
2392 {
2393         proto_item        *pi;
2394         va_list            ap;
2395
2396         pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
2397         if (pi != tree) {
2398                 TRY_TO_FAKE_THIS_REPR(pi);
2399
2400                 va_start(ap, format);
2401                 proto_tree_set_representation(pi, format, ap);
2402                 va_end(ap);
2403         }
2404
2405         return pi;
2406 }
2407
2408 /* Set the FT_OID value */
2409 static void
2410 proto_tree_set_oid(field_info *fi, const guint8* value_ptr, gint length)
2411 {
2412         GByteArray *bytes;
2413
2414         DISSECTOR_ASSERT(value_ptr != NULL);
2415
2416         bytes = g_byte_array_new();
2417         if (length > 0) {
2418                 g_byte_array_append(bytes, value_ptr, length);
2419         }
2420         fvalue_set(&fi->value, bytes, TRUE);
2421 }
2422
2423 static void
2424 proto_tree_set_oid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
2425 {
2426         proto_tree_set_oid(fi, tvb_get_ptr(tvb, start, length), length);
2427 }
2428
2429 static void
2430 proto_tree_set_uint64(field_info *fi, guint64 value)
2431 {
2432         fvalue_set_integer64(&fi->value, value);
2433 }
2434
2435 /*
2436  * NOTE: to support code written when proto_tree_add_item() took a
2437  * gboolean as its last argument, with FALSE meaning "big-endian"
2438  * and TRUE meaning "little-endian", we treat any non-zero value of
2439  * "encoding" as meaning "little-endian".
2440  */
2441 static void
2442 proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start,
2443                           guint length, const guint encoding)
2444 {
2445         guint64 value = 0;
2446         guint8* b = (guint8 *)ep_tvb_memdup(tvb, start, length);
2447
2448         if (encoding) {
2449                 b += length;
2450                 switch (length) {
2451                         default: DISSECTOR_ASSERT_NOT_REACHED();
2452                         case 8: value <<= 8; value += *--b;
2453                         case 7: value <<= 8; value += *--b;
2454                         case 6: value <<= 8; value += *--b;
2455                         case 5: value <<= 8; value += *--b;
2456                         case 4: value <<= 8; value += *--b;
2457                         case 3: value <<= 8; value += *--b;
2458                         case 2: value <<= 8; value += *--b;
2459                         case 1: value <<= 8; value += *--b;
2460                                 break;
2461                 }
2462         } else {
2463                 switch (length) {
2464                         default: DISSECTOR_ASSERT_NOT_REACHED();
2465                         case 8: value <<= 8; value += *b++;
2466                         case 7: value <<= 8; value += *b++;
2467                         case 6: value <<= 8; value += *b++;
2468                         case 5: value <<= 8; value += *b++;
2469                         case 4: value <<= 8; value += *b++;
2470                         case 3: value <<= 8; value += *b++;
2471                         case 2: value <<= 8; value += *b++;
2472                         case 1: value <<= 8; value += *b++;
2473                                 break;
2474                 }
2475         }
2476
2477         proto_tree_set_uint64(fi, value);
2478 }
2479
2480 /* Add a FT_STRING or FT_STRINGZ to a proto_tree. Creates own copy of string,
2481  * and frees it when the proto_tree is destroyed. */
2482 proto_item *
2483 proto_tree_add_string(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2484                       gint length, const char* value)
2485 {
2486         proto_item        *pi;
2487         header_field_info *hfinfo;
2488
2489         TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2490
2491         DISSECTOR_ASSERT(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ);
2492
2493         pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
2494         DISSECTOR_ASSERT(length >= 0);
2495         proto_tree_set_string(PNODE_FINFO(pi), value);
2496
2497         return pi;
2498 }
2499
2500 proto_item *
2501 proto_tree_add_unicode_string(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2502                       gint length, const char* value)
2503 {
2504         DISSECTOR_ASSERT(g_utf8_validate(value, -1, NULL));
2505         return proto_tree_add_string_format_value(tree, hfindex, tvb, start, length, value, "%s", value);
2506 }
2507
2508 proto_item *
2509 proto_tree_add_string_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2510                                    gint start, gint length, const char* value,
2511                                    const char *format,
2512                                    ...)
2513 {
2514         proto_item        *pi;
2515         va_list            ap;
2516
2517         pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
2518         if (pi != tree) {
2519                 va_start(ap, format);
2520                 proto_tree_set_representation_value(pi, format, ap);
2521                 va_end(ap);
2522         }
2523
2524         return pi;
2525 }
2526
2527 proto_item *
2528 proto_tree_add_string_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2529                              gint start, gint length, const char* value,
2530                              const char *format, ...)
2531 {
2532         proto_item        *pi;
2533         va_list            ap;
2534
2535         pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
2536         if (pi != tree) {
2537                 TRY_TO_FAKE_THIS_REPR(pi);
2538
2539                 va_start(ap, format);
2540                 proto_tree_set_representation(pi, format, ap);
2541                 va_end(ap);
2542         }
2543
2544         return pi;
2545 }
2546
2547 /* Appends string data to a FT_STRING or FT_STRINGZ, allowing progressive
2548  * field info update instead of only updating the representation as does
2549  * proto_item_append_text()
2550  */
2551 /* NOTE: this function will break with the TRY_TO_FAKE_THIS_ITEM()
2552  * speed optimization.
2553  * Currently only WSP use this function so it is not that bad but try to
2554  * avoid using this one if possible.
2555  * IF you must use this function you MUST also disable the
2556  * TRY_TO_FAKE_THIS_ITEM() optimization for your dissector/function
2557  * using proto_item_append_string().
2558  * Do that by faking that the tree is visible by calling
2559  * proto_tree_set_visible(tree, TRUE) (see packet-wsp.c)
2560  * BEFORE you create the item you are later going to use
2561  * proto_item_append_string() on.
2562  */
2563 void
2564 proto_item_append_string(proto_item *pi, const char *str)
2565 {
2566         field_info        *fi;
2567         header_field_info *hfinfo;
2568         const gchar       *old_str, *new_str;
2569
2570         if (!pi)
2571                 return;
2572         if (!*str)
2573                 return;
2574
2575         fi = PITEM_FINFO(pi);
2576         DISSECTOR_ASSERT_HINT(fi, "proto_tree_set_visible(tree, TRUE) should have been called previously");
2577
2578         hfinfo = fi->hfinfo;
2579         if (hfinfo->type == FT_PROTOCOL) {
2580                 /* TRY_TO_FAKE_THIS_ITEM() speed optimization: silently skip */
2581                 return;
2582         }
2583         DISSECTOR_ASSERT(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ);
2584         old_str = (guint8 *)fvalue_get(&fi->value);
2585         if (old_str && old_str[0])
2586                 new_str = ep_strconcat(old_str, str, NULL);
2587         else
2588                 new_str = str;
2589         fvalue_set(&fi->value, (gpointer) new_str, FALSE);
2590 }
2591
2592 /* Set the FT_STRING value */
2593 static void
2594 proto_tree_set_string(field_info *fi, const char* value)
2595 {
2596         if (value) {
2597                 fvalue_set(&fi->value, (gpointer) value, FALSE);
2598         } else {
2599                 fvalue_set(&fi->value, (gpointer) "[ Null ]", FALSE);
2600         }
2601 }
2602
2603 static void
2604 proto_tree_set_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length, gint encoding)
2605 {
2606         gchar   *string;
2607
2608         if (length == -1) {
2609                 length = tvb_ensure_length_remaining(tvb, start);
2610         }
2611
2612         string = tvb_get_ephemeral_string_enc(tvb, start, length, encoding);
2613         proto_tree_set_string(fi, string);
2614 }
2615
2616
2617 /* Add a FT_AX25 to a proto_tree */
2618 proto_item *
2619 proto_tree_add_ax25(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2620                 const guint8* value)
2621 {
2622         proto_item              *pi;
2623         header_field_info       *hfinfo;
2624
2625         TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2626
2627         DISSECTOR_ASSERT(hfinfo->type == FT_AX25);
2628
2629         pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
2630         proto_tree_set_ax25(PNODE_FINFO(pi), value);
2631
2632         return pi;
2633 }
2634
2635 /* Set the FT_AX25 value */
2636 static void
2637 proto_tree_set_ax25(field_info *fi, const guint8* value)
2638 {
2639         fvalue_set(&fi->value, (gpointer) value, FALSE);
2640 }
2641
2642 static void
2643 proto_tree_set_ax25_tvb(field_info *fi, tvbuff_t *tvb, gint start)
2644 {
2645         proto_tree_set_ax25(fi, tvb_get_ptr(tvb, start, 7));
2646 }
2647
2648 /* Set the FT_VINES value */
2649 static void
2650 proto_tree_set_vines(field_info *fi, const guint8* value)
2651 {
2652         fvalue_set(&fi->value, (gpointer) value, FALSE);
2653 }
2654
2655 static void
2656 proto_tree_set_vines_tvb(field_info *fi, tvbuff_t *tvb, gint start)
2657 {
2658         proto_tree_set_vines(fi, tvb_get_ptr(tvb, start, FT_VINES_ADDR_LEN));
2659 }
2660
2661 /* Add a FT_ETHER to a proto_tree */
2662 proto_item *
2663 proto_tree_add_ether(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2664                      gint length, const guint8* value)
2665 {
2666         proto_item        *pi;
2667         header_field_info *hfinfo;
2668
2669         TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2670
2671         DISSECTOR_ASSERT(hfinfo->type == FT_ETHER);
2672
2673         pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
2674         proto_tree_set_ether(PNODE_FINFO(pi), value);
2675
2676         return pi;
2677 }
2678
2679 proto_item *
2680 proto_tree_add_ether_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2681                                   gint start, gint length, const guint8* value,
2682                                   const char *format, ...)
2683 {
2684         proto_item        *pi;
2685         va_list            ap;
2686
2687         pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
2688         if (pi != tree) {
2689                 va_start(ap, format);
2690                 proto_tree_set_representation_value(pi, format, ap);
2691                 va_end(ap);
2692         }
2693
2694         return pi;
2695 }
2696
2697 proto_item *
2698 proto_tree_add_ether_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2699                             gint start, gint length, const guint8* value,
2700                             const char *format, ...)
2701 {
2702         proto_item        *pi;
2703         va_list            ap;
2704
2705         pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
2706         if (pi != tree) {
2707                 TRY_TO_FAKE_THIS_REPR(pi);
2708
2709                 va_start(ap, format);
2710                 proto_tree_set_representation(pi, format, ap);
2711                 va_end(ap);
2712         }
2713
2714         return pi;
2715 }
2716
2717 /* Set the FT_ETHER value */
2718 static void
2719 proto_tree_set_ether(field_info *fi, const guint8* value)
2720 {
2721         fvalue_set(&fi->value, (gpointer) value, FALSE);
2722 }
2723
2724 static void
2725 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start)
2726 {
2727         proto_tree_set_ether(fi, tvb_get_ptr(tvb, start, FT_ETHER_LEN));
2728 }
2729
2730 /* Add a FT_BOOLEAN to a proto_tree */
2731 proto_item *
2732 proto_tree_add_boolean(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2733                        gint length, guint32 value)
2734 {
2735         proto_item        *pi;
2736         header_field_info *hfinfo;
2737
2738         TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2739
2740         DISSECTOR_ASSERT(hfinfo->type == FT_BOOLEAN);
2741
2742         pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
2743         proto_tree_set_boolean(PNODE_FINFO(pi), value);
2744
2745         return pi;
2746 }
2747
2748 proto_item *
2749 proto_tree_add_boolean_format_value(proto_tree *tree, int hfindex,
2750                                     tvbuff_t *tvb, gint start, gint length,
2751                                     guint32 value, const char *format, ...)
2752 {
2753         proto_item        *pi;
2754         va_list            ap;
2755
2756         pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
2757         if (pi != tree) {
2758                 va_start(ap, format);
2759                 proto_tree_set_representation_value(pi, format, ap);
2760                 va_end(ap);
2761         }
2762
2763         return pi;
2764 }
2765
2766 proto_item *
2767 proto_tree_add_boolean_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2768                               gint start, gint length, guint32 value,
2769                               const char *format, ...)
2770 {
2771         proto_item        *pi;
2772         va_list            ap;
2773
2774         pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
2775         if (pi != tree) {
2776                 TRY_TO_FAKE_THIS_REPR(pi);
2777
2778                 va_start(ap, format);
2779                 proto_tree_set_representation(pi, format, ap);
2780                 va_end(ap);
2781         }
2782
2783         return pi;
2784 }
2785
2786 /* Set the FT_BOOLEAN value */
2787 static void
2788 proto_tree_set_boolean(field_info *fi, guint32 value)
2789 {
2790         proto_tree_set_uint(fi, value);
2791 }
2792
2793 /* Add a FT_FLOAT to a proto_tree */
2794 proto_item *
2795 proto_tree_add_float(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2796                      gint length, float value)
2797 {
2798         proto_item        *pi;
2799         header_field_info *hfinfo;
2800
2801         TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2802
2803         DISSECTOR_ASSERT(hfinfo->type == FT_FLOAT);
2804
2805         pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
2806         proto_tree_set_float(PNODE_FINFO(pi), value);
2807
2808         return pi;
2809 }
2810
2811 proto_item *
2812 proto_tree_add_float_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2813                                   gint start, gint length, float value,
2814                                   const char *format, ...)
2815 {
2816         proto_item        *pi;
2817         va_list            ap;
2818
2819         pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
2820         if (pi != tree) {
2821                 va_start(ap, format);
2822                 proto_tree_set_representation_value(pi, format, ap);
2823                 va_end(ap);
2824         }
2825
2826         return pi;
2827 }
2828
2829 proto_item *
2830 proto_tree_add_float_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2831                             gint start, gint length, float value,
2832                             const char *format, ...)
2833 {
2834         proto_item        *pi;
2835         va_list            ap;
2836
2837         pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
2838         if (pi != tree) {
2839                 TRY_TO_FAKE_THIS_REPR(pi);
2840
2841                 va_start(ap, format);
2842                 proto_tree_set_representation(pi, format, ap);
2843                 va_end(ap);
2844         }
2845
2846         return pi;
2847 }
2848
2849 /* Set the FT_FLOAT value */
2850 static void
2851 proto_tree_set_float(field_info *fi, float value)
2852 {
2853         fvalue_set_floating(&fi->value, value);
2854 }
2855
2856 /* Add a FT_DOUBLE to a proto_tree */
2857 proto_item *
2858 proto_tree_add_double(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2859                       gint length, double value)
2860 {
2861         proto_item        *pi;
2862         header_field_info *hfinfo;
2863
2864         TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2865
2866         DISSECTOR_ASSERT(hfinfo->type == FT_DOUBLE);
2867
2868         pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
2869         proto_tree_set_double(PNODE_FINFO(pi), value);
2870
2871         return pi;
2872 }
2873
2874 proto_item *
2875 proto_tree_add_double_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2876                                    gint start, gint length, double value,
2877                                    const char *format, ...)
2878 {
2879         proto_item        *pi;
2880         va_list            ap;
2881
2882         pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
2883         if (pi != tree) {
2884                 va_start(ap, format);
2885                 proto_tree_set_representation_value(pi, format, ap);
2886                 va_end(ap);
2887         }
2888
2889         return pi;
2890 }
2891
2892 proto_item *
2893 proto_tree_add_double_format(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                 TRY_TO_FAKE_THIS_REPR(pi);
2903
2904                 va_start(ap, format);
2905                 proto_tree_set_representation(pi, format, ap);
2906                 va_end(ap);
2907         }
2908
2909         return pi;
2910 }
2911
2912 /* Set the FT_DOUBLE value */
2913 static void
2914 proto_tree_set_double(field_info *fi, double value)
2915 {
2916         fvalue_set_floating(&fi->value, value);
2917 }
2918
2919 /* Add FT_UINT{8,16,24,32} to a proto_tree */
2920 proto_item *
2921 proto_tree_add_uint(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2922                     gint length, guint32 value)
2923 {
2924         proto_item        *pi = NULL;
2925         header_field_info *hfinfo;
2926
2927         TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2928
2929         switch (hfinfo->type) {
2930                 case FT_UINT8:
2931                 case FT_UINT16:
2932                 case FT_UINT24:
2933                 case FT_UINT32:
2934                 case FT_FRAMENUM:
2935                         pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
2936                         proto_tree_set_uint(PNODE_FINFO(pi), value);
2937                         break;
2938
2939                 default:
2940                         DISSECTOR_ASSERT_NOT_REACHED();
2941         }
2942
2943         return pi;
2944 }
2945
2946 proto_item *
2947 proto_tree_add_uint_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2948                                  gint start, gint length, guint32 value,
2949                                  const char *format, ...)
2950 {
2951         proto_item        *pi;
2952         va_list            ap;
2953
2954         pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
2955         if (pi != tree) {
2956                 va_start(ap, format);
2957                 proto_tree_set_representation_value(pi, format, ap);
2958                 va_end(ap);
2959         }
2960
2961         return pi;
2962 }
2963
2964 proto_item *
2965 proto_tree_add_uint_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2966                            gint start, gint length, guint32 value,
2967                            const char *format, ...)
2968 {
2969         proto_item        *pi;
2970         va_list            ap;
2971
2972         pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
2973         if (pi != tree) {
2974                 TRY_TO_FAKE_THIS_REPR(pi);
2975
2976                 va_start(ap, format);
2977                 proto_tree_set_representation(pi, format, ap);
2978                 va_end(ap);
2979         }
2980
2981         return pi;
2982 }
2983
2984 /* Set the FT_UINT{8,16,24,32} value */
2985 static void
2986 proto_tree_set_uint(field_info *fi, guint32 value)
2987 {
2988         header_field_info *hfinfo;
2989         guint32            integer;
2990
2991         hfinfo = fi->hfinfo;
2992         integer = value;
2993
2994         if (hfinfo->bitmask) {
2995                 /* Mask out irrelevant portions */
2996                 integer &= hfinfo->bitmask;
2997
2998                 /* Shift bits */
2999                 integer >>= hfinfo_bitshift(hfinfo);
3000         }
3001
3002         fvalue_set_uinteger(&fi->value, integer);
3003 }
3004
3005 /* Add FT_UINT64 to a proto_tree */
3006 proto_item *
3007 proto_tree_add_uint64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3008                       gint length, guint64 value)
3009 {
3010         proto_item        *pi;
3011         header_field_info *hfinfo;
3012
3013         TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3014
3015         DISSECTOR_ASSERT(hfinfo->type == FT_UINT64);
3016
3017         pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
3018         proto_tree_set_uint64(PNODE_FINFO(pi), value);
3019
3020         return pi;
3021 }
3022
3023 proto_item *
3024 proto_tree_add_uint64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3025                                    gint start, gint length, guint64 value,
3026                                    const char *format, ...)
3027 {
3028         proto_item        *pi;
3029         va_list            ap;
3030
3031         pi = proto_tree_add_uint64(tree, hfindex, tvb, start, length, value);
3032         if (pi != tree) {
3033                 va_start(ap, format);
3034                 proto_tree_set_representation_value(pi, format, ap);
3035                 va_end(ap);
3036         }
3037
3038         return pi;
3039 }
3040
3041 proto_item *
3042 proto_tree_add_uint64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3043                              gint start, gint length, guint64 value,
3044                              const char *format, ...)
3045 {
3046         proto_item        *pi;
3047         va_list            ap;
3048
3049         pi = proto_tree_add_uint64(tree, hfindex, tvb, start, length, value);
3050         if (pi != tree) {
3051                 TRY_TO_FAKE_THIS_REPR(pi);
3052
3053                 va_start(ap, format);
3054                 proto_tree_set_representation(pi, format, ap);
3055                 va_end(ap);
3056         }
3057
3058         return pi;
3059 }
3060
3061 /* Add FT_INT{8,16,24,32} to a proto_tree */
3062 proto_item *
3063 proto_tree_add_int(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3064                    gint length, gint32 value)
3065 {
3066         proto_item        *pi = NULL;
3067         header_field_info *hfinfo;
3068
3069         TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3070
3071         switch (hfinfo->type) {
3072                 case FT_INT8:
3073                 case FT_INT16:
3074                 case FT_INT24:
3075                 case FT_INT32:
3076                         pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
3077                         proto_tree_set_int(PNODE_FINFO(pi), value);
3078                         break;
3079
3080                 default:
3081                         DISSECTOR_ASSERT_NOT_REACHED();
3082         }
3083
3084         return pi;
3085 }
3086
3087 proto_item *
3088 proto_tree_add_int_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3089                                 gint start, gint length, gint32 value,
3090                                 const char *format, ...)
3091 {
3092         proto_item  *pi;
3093         va_list      ap;
3094
3095         pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
3096         if (pi != tree) {
3097                 va_start(ap, format);
3098                 proto_tree_set_representation_value(pi, format, ap);
3099                 va_end(ap);
3100         }
3101
3102         return pi;
3103 }
3104
3105 proto_item *
3106 proto_tree_add_int_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3107                           gint start, gint length, gint32 value,
3108                           const char *format, ...)
3109 {
3110         proto_item *pi;
3111         va_list     ap;
3112
3113         pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
3114         if (pi != tree) {
3115                 TRY_TO_FAKE_THIS_REPR(pi);
3116
3117                 va_start(ap, format);
3118                 proto_tree_set_representation(pi, format, ap);
3119                 va_end(ap);
3120         }
3121
3122         return pi;
3123 }
3124
3125 /* Set the FT_INT{8,16,24,32} value */
3126 static void
3127 proto_tree_set_int(field_info *fi, gint32 value)
3128 {
3129         header_field_info *hfinfo;
3130         guint32            integer;
3131
3132         hfinfo = fi->hfinfo;
3133         integer = (guint32) value;
3134
3135         if (hfinfo->bitmask) {
3136                 /* Mask out irrelevant portions */
3137                 integer &= hfinfo->bitmask;
3138
3139                 /* Shift bits */
3140                 integer >>= hfinfo_bitshift(hfinfo);
3141         }
3142
3143         fvalue_set_sinteger(&fi->value, integer);
3144 }
3145
3146 /* Add FT_INT64 to a proto_tree */
3147 proto_item *
3148 proto_tree_add_int64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3149                      gint length, gint64 value)
3150 {
3151         proto_item        *pi;
3152         header_field_info *hfinfo;
3153
3154         TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3155
3156         DISSECTOR_ASSERT(hfinfo->type == FT_INT64);
3157
3158         pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
3159         proto_tree_set_uint64(PNODE_FINFO(pi), (guint64)value);
3160
3161         return pi;
3162 }
3163
3164 proto_item *
3165 proto_tree_add_int64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3166                                   gint start, gint length, gint64 value,
3167                                   const char *format, ...)
3168 {
3169         proto_item        *pi;
3170         va_list            ap;
3171
3172         pi = proto_tree_add_int64(tree, hfindex, tvb, start, length, value);
3173         if (pi != tree) {
3174                 va_start(ap, format);
3175                 proto_tree_set_representation_value(pi, format, ap);
3176                 va_end(ap);
3177         }
3178
3179         return pi;
3180 }
3181
3182 proto_item *
3183 proto_tree_add_int64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3184                            gint start, gint length, gint64 value,
3185                            const char *format, ...)
3186 {
3187         proto_item        *pi;
3188         va_list            ap;
3189
3190         pi = proto_tree_add_int64(tree, hfindex, tvb, start, length, value);
3191         if (pi != tree) {
3192                 TRY_TO_FAKE_THIS_REPR(pi);
3193
3194                 va_start(ap, format);
3195                 proto_tree_set_representation(pi, format, ap);
3196                 va_end(ap);
3197         }
3198
3199         return pi;
3200 }
3201 /* Add a FT_EUI64 to a proto_tree */
3202 proto_item *
3203 proto_tree_add_eui64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3204                      gint length, const guint64 value)
3205 {
3206         proto_item        *pi;
3207         header_field_info *hfinfo;
3208
3209         TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3210
3211         DISSECTOR_ASSERT(hfinfo->type == FT_EUI64);
3212
3213         pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
3214         proto_tree_set_eui64(PNODE_FINFO(pi), value);
3215
3216         return pi;
3217 }
3218
3219 proto_item *
3220 proto_tree_add_eui64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3221                                   gint start, gint length, const guint64 value,
3222                                   const char *format, ...)
3223 {
3224         proto_item        *pi;
3225         va_list            ap;
3226
3227         pi = proto_tree_add_eui64(tree, hfindex, tvb, start, length, value);
3228         if (pi != tree) {
3229                 va_start(ap, format);
3230                 proto_tree_set_representation_value(pi, format, ap);
3231                 va_end(ap);
3232         }
3233
3234         return pi;
3235 }
3236
3237 proto_item *
3238 proto_tree_add_eui64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3239                             gint start, gint length, const guint64 value,
3240                             const char *format, ...)
3241 {
3242         proto_item        *pi;
3243         va_list            ap;
3244
3245         pi = proto_tree_add_eui64(tree, hfindex, tvb, start, length, value);
3246         if (pi != tree) {
3247                 TRY_TO_FAKE_THIS_REPR(pi);
3248
3249                 va_start(ap, format);
3250                 proto_tree_set_representation(pi, format, ap);
3251                 va_end(ap);
3252         }
3253
3254         return pi;
3255 }
3256
3257 /* Set the FT_EUI64 value */
3258 static void
3259 proto_tree_set_eui64(field_info *fi, const guint64 value)
3260 {
3261         fvalue_set_integer64(&fi->value, value);
3262 }
3263 static void
3264 proto_tree_set_eui64_tvb(field_info *fi, tvbuff_t *tvb, gint start, const guint encoding)
3265 {
3266         if (encoding)
3267         {
3268                 proto_tree_set_eui64(fi, tvb_get_letoh64(tvb, start));
3269         } else {
3270                 proto_tree_set_eui64(fi, tvb_get_ntoh64(tvb, start));
3271         }
3272 }
3273
3274 /* Add a field_info struct to the proto_tree, encapsulating it in a proto_node */
3275 static proto_item *
3276 proto_tree_add_node(proto_tree *tree, field_info *fi)
3277 {
3278         proto_node *pnode, *tnode, *sibling;
3279         field_info *tfi;
3280
3281         /*
3282          * Make sure "tree" is ready to have subtrees under it, by
3283          * checking whether it's been given an ett_ value.
3284          *
3285          * "PNODE_FINFO(tnode)" may be null; that's the case for the root
3286          * node of the protocol tree.  That node is not displayed,
3287          * so it doesn't need an ett_ value to remember whether it
3288          * was expanded.
3289          */
3290         tnode = tree;
3291         tfi = PNODE_FINFO(tnode);
3292         if (tfi != NULL && (tfi->tree_type < 0 || tfi->tree_type >= num_tree_types)) {
3293                 REPORT_DISSECTOR_BUG(ep_strdup_printf("\"%s\" - \"%s\" tfi->tree_type: %u invalid (%s:%u)",
3294                                      fi->hfinfo->name, fi->hfinfo->abbrev, tfi->tree_type, __FILE__, __LINE__));
3295                 /* XXX - is it safe to continue here? */
3296         }
3297
3298         PROTO_NODE_NEW(pnode);
3299         pnode->parent = tnode;
3300         PNODE_FINFO(pnode) = fi;
3301         pnode->tree_data = PTREE_DATA(tree);
3302
3303         if (tnode->last_child != NULL) {
3304                 sibling = tnode->last_child;
3305                 DISSECTOR_ASSERT(sibling->next == NULL);
3306                 sibling->next = pnode;
3307         } else
3308                 tnode->first_child = pnode;
3309         tnode->last_child = pnode;
3310
3311         tree_data_add_maybe_interesting_field(pnode->tree_data, fi);
3312
3313         return (proto_item *)pnode;
3314 }
3315
3316
3317 /* Generic way to allocate field_info and add to proto_tree.
3318  * Sets *pfi to address of newly-allocated field_info struct */
3319 static proto_item *
3320 proto_tree_add_pi(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb, gint start,
3321                   gint *length)
3322 {
3323         proto_item *pi;
3324         field_info *fi;
3325
3326         fi = alloc_field_info(tree, hfinfo, tvb, start, length);
3327         pi = proto_tree_add_node(tree, fi);
3328
3329         return pi;
3330 }
3331
3332
3333 static void
3334 get_hfi_length(header_field_info *hfinfo, tvbuff_t *tvb, const gint start, gint *length,
3335                    gint *item_length)
3336 {
3337         gint length_remaining;
3338
3339         /*
3340          * We only allow a null tvbuff if the item has a zero length,
3341          * i.e. if there's no data backing it.
3342          */
3343         DISSECTOR_ASSERT(tvb != NULL || *length == 0);
3344
3345         /*
3346          * XXX - in some protocols, there are 32-bit unsigned length
3347          * fields, so lengths in protocol tree and tvbuff routines
3348          * should really be unsigned.  We should have, for those
3349          * field types for which "to the end of the tvbuff" makes sense,
3350          * additional routines that take no length argument and
3351          * add fields that run to the end of the tvbuff.
3352          */
3353         if (*length == -1) {
3354                 /*
3355                  * For FT_NONE, FT_PROTOCOL, FT_BYTES, and FT_STRING fields,
3356                  * a length of -1 means "set the length to what remains in
3357                  * the tvbuff".
3358                  *
3359                  * The assumption is either that
3360                  *
3361                  *      1) the length of the item can only be determined
3362                  *         by dissection (typically true of items with
3363                  *         subitems, which are probably FT_NONE or
3364                  *         FT_PROTOCOL)
3365                  *
3366                  * or
3367                  *
3368                  *      2) if the tvbuff is "short" (either due to a short
3369                  *         snapshot length or due to lack of reassembly of
3370                  *         fragments/segments/whatever), we want to display
3371                  *         what's available in the field (probably FT_BYTES
3372                  *         or FT_STRING) and then throw an exception later
3373                  *
3374                  * or
3375                  *
3376                  *      3) the field is defined to be "what's left in the
3377                  *         packet"
3378                  *
3379                  * so we set the length to what remains in the tvbuff so
3380                  * that, if we throw an exception while dissecting, it
3381                  * has what is probably the right value.
3382                  *
3383                  * For FT_STRINGZ, it means "the string is null-terminated,
3384                  * not null-padded; set the length to the actual length
3385                  * of the string", and if the tvbuff if short, we just
3386                  * throw an exception.
3387                  *
3388                  * It's not valid for any other type of field.
3389                  */
3390                 switch (hfinfo->type) {
3391
3392                 case FT_PROTOCOL:
3393                         /*
3394                          * We allow this to be zero-length - for
3395                          * example, an ONC RPC NULL procedure has
3396                          * neither arguments nor reply, so the
3397                          * payload for that protocol is empty.
3398                          *
3399                          * However, if the length is negative, the
3400                          * start offset is *past* the byte past the
3401                          * end of the tvbuff, so we throw an
3402                          * exception.
3403                          */
3404                         *length = tvb_length_remaining(tvb, start);
3405                         if (*length < 0) {
3406                                 /*
3407                                  * Use "tvb_ensure_bytes_exist()"
3408                                  * to force the appropriate exception
3409                                  * to be thrown.
3410                                  */
3411                                 tvb_ensure_bytes_exist(tvb, start, 0);
3412                         }
3413                         DISSECTOR_ASSERT(*length >= 0);
3414                         break;
3415
3416                 case FT_NONE:
3417                 case FT_BYTES:
3418                 case FT_STRING:
3419                         *length = tvb_ensure_length_remaining(tvb, start);
3420                         DISSECTOR_ASSERT(*length >= 0);
3421                         break;
3422
3423                 case FT_STRINGZ:
3424                         /*
3425                          * Leave the length as -1, so our caller knows
3426                          * it was -1.
3427                          */
3428                         break;
3429
3430                 default:
3431                         DISSECTOR_ASSERT_NOT_REACHED();
3432                 }
3433                 *item_length = *length;
3434         } else {
3435                 *item_length = *length;
3436                 if (hfinfo->type == FT_PROTOCOL || hfinfo->type == FT_NONE) {
3437                         /*
3438                          * These types are for interior nodes of the
3439                          * tree, and don't have data associated with
3440                          * them; if the length is negative (XXX - see
3441                          * above) or goes past the end of the tvbuff,
3442                          * cut it short at the end of the tvbuff.
3443                          * That way, if this field is selected in
3444                          * Wireshark, we don't highlight stuff past
3445                          * the end of the data.
3446                          */
3447                         /* XXX - what to do, if we don't have a tvb? */
3448                         if (tvb) {
3449                                 length_remaining = tvb_length_remaining(tvb, start);
3450                                 if (*item_length < 0 ||
3451                                         (*item_length > 0 &&
3452                                           (length_remaining < *item_length)))
3453                                         *item_length = length_remaining;
3454                         }
3455                 }
3456                 if (*item_length < 0) {
3457                         THROW(ReportedBoundsError);
3458                 }
3459         }
3460 }
3461
3462 static field_info *
3463 new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
3464                const gint start, const gint item_length)
3465 {
3466         field_info *fi;
3467
3468         FIELD_INFO_NEW(fi);
3469
3470         fi->hfinfo     = hfinfo;
3471         fi->start      = start;
3472         fi->start     += (tvb)?tvb_raw_offset(tvb):0;
3473         fi->length     = item_length;
3474         fi->tree_type  = -1;
3475         fi->flags      = 0;
3476         if (!PTREE_DATA(tree)->visible)
3477                 FI_SET_FLAG(fi, FI_HIDDEN);
3478         fvalue_init(&fi->value, fi->hfinfo->type);
3479         fi->rep        = NULL;
3480
3481         /* add the data source tvbuff */
3482         fi->ds_tvb = tvb ? tvb_get_ds_tvb(tvb) : NULL;
3483
3484         fi->appendix_start  = 0;
3485         fi->appendix_length = 0;
3486
3487         return fi;
3488 }
3489
3490 static field_info *
3491 alloc_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb, const gint start,
3492                  gint *length)
3493 {
3494         gint               item_length;
3495
3496         get_hfi_length(hfinfo, tvb, start, length, &item_length);
3497         return new_field_info(tree, hfinfo, tvb, start, item_length);
3498 }
3499
3500 static void
3501 label_mark_truncated_start(char *label_str)
3502 {
3503         static const char trunc_str[] = "[truncated] ";
3504         const size_t trunc_len = sizeof(trunc_str)-1;
3505
3506         memmove(label_str + trunc_len, label_str, ITEM_LABEL_LENGTH - trunc_len);
3507         memcpy(label_str, trunc_str, trunc_len);
3508         label_str[ITEM_LABEL_LENGTH-1] = '\0';
3509 }
3510
3511 /* If the protocol tree is to be visible, set the representation of a
3512    proto_tree entry with the name of the field for the item and with
3513    the value formatted with the supplied printf-style format and
3514    argument list. */
3515 static void
3516 proto_tree_set_representation_value(proto_item *pi, const char *format, va_list ap)
3517 {
3518         g_assert(pi);
3519
3520         /* If the tree (GUI) or item isn't visible it's pointless for us to generate the protocol
3521          * items string representation */
3522         if (PTREE_DATA(pi)->visible && !PROTO_ITEM_IS_HIDDEN(pi)) {
3523                 int               ret = 0;
3524                 field_info        *fi = PITEM_FINFO(pi);
3525                 header_field_info *hf;
3526
3527                 DISSECTOR_ASSERT(fi);
3528
3529                 hf = fi->hfinfo;
3530
3531                 ITEM_LABEL_NEW(fi->rep);
3532                 if (hf->bitmask && (hf->type == FT_BOOLEAN || IS_FT_UINT(hf->type))) {
3533                         guint32 val;
3534                         char *p;
3535
3536                         val = fvalue_get_uinteger(&fi->value);
3537                         val <<= hfinfo_bitshift(hf);
3538
3539                         p = decode_bitfield_value(fi->rep->representation, val, hf->bitmask, hfinfo_bitwidth(hf));
3540                         ret = (int) (p - fi->rep->representation);
3541                 }
3542
3543                 /* put in the hf name */
3544                 ret += g_snprintf(fi->rep->representation + ret, ITEM_LABEL_LENGTH - ret, "%s: ", hf->name);
3545
3546                 /* If possible, Put in the value of the string */
3547                 if (ret < ITEM_LABEL_LENGTH) {
3548                         ret += g_vsnprintf(fi->rep->representation + ret,
3549                                           ITEM_LABEL_LENGTH - ret, format, ap);
3550                 }
3551                 if (ret >= ITEM_LABEL_LENGTH) {
3552                         /* Uh oh, we don't have enough room.  Tell the user
3553                          * that the field is truncated.
3554                          */
3555                         /* XXX, label_mark_truncated() ? */
3556                         label_mark_truncated_start(fi->rep->representation);
3557                 }
3558         }
3559 }
3560
3561 /* If the protocol tree is to be visible, set the representation of a
3562    proto_tree entry with the representation formatted with the supplied
3563    printf-style format and argument list. */
3564 static void
3565 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap)
3566 {
3567         int         ret;        /*tmp return value */
3568         field_info *fi = PITEM_FINFO(pi);
3569
3570         DISSECTOR_ASSERT(fi);
3571
3572         if (!PROTO_ITEM_IS_HIDDEN(pi)) {
3573                 ITEM_LABEL_NEW(fi->rep);
3574                 ret = g_vsnprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
3575                                   format, ap);
3576                 if (ret >= ITEM_LABEL_LENGTH) {
3577                         /* Uh oh, we don't have enough room.  Tell the user
3578                          * that the field is truncated.
3579                          */
3580                         label_mark_truncated_start(fi->rep->representation);
3581                 }
3582         }
3583 }
3584
3585 static int
3586 protoo_strlcpy(gchar *dest, const gchar *src, gsize dest_size)
3587 {
3588         gsize res = g_strlcpy(dest, src, dest_size);
3589
3590         if (res > dest_size)
3591                 res = dest_size;
3592         return (int) res;
3593 }
3594
3595 static header_field_info *
3596 hfinfo_same_name_get_prev(const header_field_info *hfinfo)
3597 {
3598         if (hfinfo->same_name_prev_id == -1)
3599                 return NULL;
3600         return proto_registrar_get_nth(hfinfo->same_name_prev_id);
3601 }
3602
3603 /* -------------------------- */
3604 const gchar *
3605 proto_custom_set(proto_tree* tree, const int field_id, gint occurrence,
3606                  gchar *result, gchar *expr, const int size)
3607 {
3608         guint32            number;
3609         guint8            *bytes;
3610         ipv4_addr         *ipv4;
3611         struct e_in6_addr *ipv6;
3612         address            addr;
3613         guint32            n_addr; /* network-order IPv4 address */
3614
3615         const true_false_string  *tfstring;
3616
3617         int                 len, prev_len = 0, last, i, offset_r = 0, offset_e = 0;
3618         GPtrArray          *finfos;
3619         field_info         *finfo         = NULL;
3620         header_field_info*  hfinfo;
3621         const gchar        *abbrev        = NULL;
3622
3623         const char *hf_str_val;
3624         char number_buf[32];
3625         const char *number_out;
3626
3627         g_assert(field_id >= 0);
3628
3629         hfinfo = proto_registrar_get_nth((guint)field_id);
3630
3631         /* do we need to rewind ? */
3632         if (!hfinfo)
3633                 return "";
3634
3635         if (occurrence < 0) {
3636                 /* Search other direction */
3637                 while (hfinfo->same_name_prev_id != -1) {
3638                         hfinfo = proto_registrar_get_nth(hfinfo->same_name_prev_id);
3639                 }
3640         }
3641
3642         while (hfinfo) {
3643                 finfos = proto_get_finfo_ptr_array(tree, hfinfo->id);
3644
3645                 if (!finfos || !(len = g_ptr_array_len(finfos))) {
3646                         if (occurrence < 0) {
3647                                 hfinfo = hfinfo->same_name_next;
3648                         } else {
3649                                 hfinfo = hfinfo_same_name_get_prev(hfinfo);
3650                         }
3651                         continue;
3652                 }
3653
3654                 /* Are there enough occurrences of the field? */
3655                 if (((occurrence - prev_len) > len) || ((occurrence + prev_len) < -len)) {
3656                         if (occurrence < 0) {
3657                                 hfinfo = hfinfo->same_name_next;
3658                         } else {
3659                                 hfinfo = hfinfo_same_name_get_prev(hfinfo);
3660                         }
3661                         prev_len += len;
3662                         continue;
3663                 }
3664
3665                 /* Calculate single index or set outer bounderies */
3666                 if (occurrence < 0) {
3667                         i = occurrence + len + prev_len;
3668                         last = i;
3669                 } else if (occurrence > 0) {
3670                         i = occurrence - 1 - prev_len;
3671                         last = i;
3672                 } else {
3673                         i = 0;
3674                         last = len - 1;
3675                 }
3676
3677                 prev_len += len; /* Count handled occurrences */
3678
3679                 while (i <= last) {
3680                         finfo = (field_info *)g_ptr_array_index(finfos, i);
3681
3682                         if (offset_r && (offset_r < (size - 2)))
3683                                 result[offset_r++] = ',';
3684
3685                         if (offset_e && (offset_e < (size - 2)))
3686                                 expr[offset_e++] = ',';
3687
3688                         switch (hfinfo->type) {
3689
3690                         case FT_NONE: /* Nothing to add */
3691                                 if (offset_r == 0) {
3692                                         result[0] = '\0';
3693                                 } else if (result[offset_r-1] == ',') {
3694                                         result[offset_r-1] = '\0';
3695                                 }
3696                                 break;
3697
3698                         case FT_PROTOCOL:
3699                                 /* prevent multiple "yes" entries by setting result directly */
3700                                 g_strlcpy(result, "Yes", size);
3701                                 break;
3702
3703                         case FT_UINT_BYTES:
3704                         case FT_BYTES:
3705                                 bytes = (guint8 *)fvalue_get(&finfo->value);
3706                                 offset_r += protoo_strlcpy(result+offset_r,
3707                                                            bytes_to_str(bytes,
3708                                                                         fvalue_length(&finfo->value)),
3709                                                            size-offset_r);
3710                                 break;
3711
3712                         case FT_ABSOLUTE_TIME:
3713                                 offset_r += protoo_strlcpy(result+offset_r,
3714                                                            abs_time_to_str((const nstime_t *)fvalue_get(&finfo->value),
3715                                                                            (absolute_time_display_e)hfinfo->display, TRUE),
3716                                                            size-offset_r);
3717                                 break;
3718
3719                         case FT_RELATIVE_TIME:
3720                                 offset_r += protoo_strlcpy(result+offset_r,
3721                                                            rel_time_to_secs_str((const nstime_t *)fvalue_get(&finfo->value)),
3722                                                            size-offset_r);
3723                                 break;
3724
3725                         case FT_BOOLEAN:
3726                                 number = fvalue_get_uinteger(&finfo->value);
3727                                 tfstring = (const true_false_string *)&tfs_true_false;
3728                                 if (hfinfo->strings) {
3729                                         tfstring = (const struct true_false_string*) hfinfo->strings;
3730                                 }
3731                                 offset_r += protoo_strlcpy(result+offset_r,
3732                                                            number ?
3733                                                              tfstring->true_string :
3734                                                              tfstring->false_string, size-offset_r);
3735
3736                                 offset_e += protoo_strlcpy(expr+offset_e,
3737                                                            number ? "1" : "0", size-offset_e);
3738                                 break;
3739
3740                         /* XXX - make these just FT_NUMBER? */
3741                         case FT_INT8:
3742                         case FT_INT16:
3743                         case FT_INT24:
3744                         case FT_INT32:
3745                         case FT_UINT8:
3746                         case FT_UINT16:
3747                         case FT_UINT24:
3748                         case FT_UINT32:
3749                         case FT_FRAMENUM:
3750                                 hf_str_val = NULL;
3751                                 number = IS_FT_INT(hfinfo->type) ? 
3752                                                 (guint32) fvalue_get_sinteger(&finfo->value) :
3753                                                 fvalue_get_uinteger(&finfo->value);
3754
3755                                 if ((hfinfo->display & BASE_DISPLAY_E_MASK) == BASE_CUSTOM) {
3756                                         gchar tmp[ITEM_LABEL_LENGTH];
3757                                         custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hfinfo->strings;
3758
3759                                         DISSECTOR_ASSERT(fmtfunc);
3760                                         fmtfunc(tmp, number);
3761
3762                                         offset_r += protoo_strlcpy(result+offset_r, tmp, size-offset_r);
3763
3764                                 } else if (hfinfo->strings) {
3765                                         number_out = hf_str_val = hf_try_val_to_str(number, hfinfo);
3766
3767                                         if (!number_out)
3768                                                 number_out = hfinfo_number_value_format_display(hfinfo, BASE_DEC, number_buf, number);
3769
3770                                         offset_r += protoo_strlcpy(result+offset_r, number_out, size-offset_r);
3771
3772                                 } else {
3773                                         number_out = hfinfo_number_value_format(hfinfo, number_buf, number);
3774
3775                                         offset_r += protoo_strlcpy(result+offset_r, number_out, size-offset_r);
3776                                 }
3777
3778                                 if (hf_str_val && (hfinfo->display & BASE_DISPLAY_E_MASK) == BASE_NONE) {
3779                                         g_snprintf(expr+offset_e, size-offset_e, "\"%s\"", hf_str_val);
3780                                 } else {
3781                                         number_out = hfinfo_numeric_value_format(hfinfo, number_buf, number);
3782
3783                                         g_strlcpy(expr+offset_e, number_out, size-offset_e);
3784                                 }
3785
3786                                 offset_e = (int)strlen(expr);
3787                                 break;
3788
3789                         case FT_INT64:
3790                                 /* XXX: Should handle BASE_CUSTOM ? */
3791                                 g_snprintf(result+offset_r, size-offset_r,
3792                                            "%" G_GINT64_MODIFIER "d",
3793                                            fvalue_get_integer64(&finfo->value));
3794                                 offset_r = (int)strlen(result);
3795                                 break;
3796                         case FT_UINT64:
3797                                 g_snprintf(result+offset_r, size-offset_r,
3798                                 /* XXX: Should handle BASE_CUSTOM ? */
3799                                            "%" G_GINT64_MODIFIER "u",
3800                                            fvalue_get_integer64(&finfo->value));
3801                                 offset_r = (int)strlen(result);
3802                                 break;
3803                         case FT_EUI64:
3804                                 offset_r += protoo_strlcpy(result+offset_r,
3805                                                            eui64_to_str(fvalue_get_integer64(&finfo->value)),
3806                                                            size-offset_r);
3807                                 break;
3808
3809                         case FT_IPv4:
3810                                 ipv4 = (ipv4_addr *)fvalue_get(&finfo->value);
3811                                 n_addr = ipv4_get_net_order_addr(ipv4);
3812                                 offset_r += protoo_strlcpy(result+offset_r,
3813                                                            ip_to_str((guint8 *)&n_addr),
3814                                                            size-offset_r);
3815                                 break;
3816
3817                         case FT_IPv6:
3818                                 ipv6 = (struct e_in6_addr *)fvalue_get(&finfo->value);
3819                                 SET_ADDRESS (&addr, AT_IPv6, sizeof(struct e_in6_addr), ipv6);
3820                                 address_to_str_buf(&addr, result+offset_r, size-offset_r);
3821                                 offset_r = (int)strlen(result);
3822                                 break;
3823
3824                         case FT_ETHER:
3825                                 offset_r += protoo_strlcpy(result+offset_r,
3826                                                            bytes_to_str_punct((const guint8 *)fvalue_get(&finfo->value),
3827                                                                               FT_ETHER_LEN, ':'),
3828                                                            size-offset_r);
3829                                 break;
3830
3831                         case FT_GUID:
3832                                 offset_r += protoo_strlcpy(result+offset_r,
3833                                                            guid_to_str((e_guid_t *)fvalue_get(&finfo->value)),
3834                                                            size-offset_r);
3835                                 break;
3836
3837                         case FT_OID:
3838                                 bytes = (guint8 *)fvalue_get(&finfo->value);
3839                                 offset_r += protoo_strlcpy(result+offset_r,
3840                                                            oid_resolved_from_encoded(bytes,
3841                                                                                      fvalue_length(&finfo->value)),
3842                                                            size-offset_r);
3843                                 offset_e += protoo_strlcpy(expr+offset_e,
3844                                                            oid_encoded2string(bytes, fvalue_length(&finfo->value)),
3845                                                            size-offset_e);
3846                                 break;
3847
3848                         case FT_FLOAT:
3849                                 g_snprintf(result+offset_r, size-offset_r,
3850                                            "%." STRINGIFY(FLT_DIG) "g", fvalue_get_floating(&finfo->value));
3851                                 offset_r = (int)strlen(result);
3852                                 break;
3853
3854                         case FT_DOUBLE:
3855                                 g_snprintf(result+offset_r, size-offset_r,
3856                                            "%." STRINGIFY(DBL_DIG) "g", fvalue_get_floating(&finfo->value));
3857                                 offset_r = (int)strlen(result);
3858                                 break;