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