e04807e533ade3c8ecb138448655beab01662bfd
[metze/wireshark/wip.git] / epan / proto.c
1 /* proto.c
2  * Routines for protocol tree
3  *
4  * $Id$
5  *
6  * Wireshark - Network traffic analyzer
7  * By Gerald Combs <gerald@wireshark.org>
8  * Copyright 1998 Gerald Combs
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
23  */
24
25 #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
49 #ifdef NEED_G_ASCII_STRCASECMP_H
50 #include "g_ascii_strcasecmp.h"
51 #endif
52
53 #define SUBTREE_ONCE_ALLOCATION_NUMBER 8
54 #define SUBTREE_MAX_LEVELS 256
55
56
57 typedef struct __subtree_lvl {
58   gint cursor_offset;
59   proto_item * it;
60   proto_tree * tree;
61 }subtree_lvl;
62
63 struct ptvcursor {
64         subtree_lvl     *pushed_tree;
65         guint8          pushed_tree_index;
66         guint8          pushed_tree_max;
67         proto_tree      *tree;
68         tvbuff_t        *tvb;
69         gint            offset;
70 };
71
72 /* Candidates for assembler */
73 int
74 wrs_count_bitshift(guint32 bitmask)
75 {
76         int bitshift = 0;
77
78         while ((bitmask & (1 << bitshift)) == 0)
79                 bitshift++;
80         return bitshift;
81 }
82
83
84
85 #if GLIB_MAJOR_VERSION < 2
86 static void *discard_const(const void *const_ptr)
87 {
88         union {
89                 const void *const_ptr;
90                 void *ptr;
91         } stupid_const;
92
93         stupid_const.const_ptr = const_ptr;
94
95         return stupid_const.ptr;
96 }
97 #endif
98
99 #define cVALS(x) (const value_string*)(x)
100
101 #if 1
102 #define TRY_TO_FAKE_THIS_ITEM(tree, hfindex) \
103         /* If this item is not referenced we dont have to do much work  \
104            at all but we should still return a node so that             \
105            field items below this node ( think proto_item_add_subtree() )\
106            will still have somewhere to attach to                       \
107            or else filtering will not work (they would be ignored since tree\
108            would be NULL).                                              \
109            DONT try to fake a node where PITEM_FINFO(pi) is NULL        \
110            since dissectors that want to do proto_item_set_len() or     \
111            other operations that dereference this would crash.          \
112            We dont fake FT_PROTOCOL either since these are cheap and    \
113            some stuff (proto hier stat) assumes they always exist.      \
114         */                                                              \
115         if(!(PTREE_DATA(tree)->visible)){                               \
116                 if(PITEM_FINFO(tree)){                                  \
117                         register header_field_info *hfinfo;             \
118                         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);       \
119                         if((hfinfo->ref_count == 0)                     \
120                         && (hfinfo->type!=FT_PROTOCOL)){                \
121                                 /* just return tree back to the caller */\
122                                 return tree;                            \
123                         }                                               \
124                 }                                                       \
125         }
126 #else
127 #define TRY_TO_FAKE_THIS_ITEM(tree, hfindex) ;
128 #endif
129
130 static gboolean
131 proto_tree_free_node(proto_node *node, gpointer data);
132
133 static void fill_label_boolean(field_info *fi, gchar *label_str);
134 static void fill_label_uint(field_info *fi, gchar *label_str);
135 static void fill_label_uint64(field_info *fi, gchar *label_str);
136 static void fill_label_enumerated_uint(field_info *fi, gchar *label_str);
137 static void fill_label_enumerated_bitfield(field_info *fi, gchar *label_str);
138 static void fill_label_numeric_bitfield(field_info *fi, gchar *label_str);
139 static void fill_label_int(field_info *fi, gchar *label_str);
140 static void fill_label_int64(field_info *fi, gchar *label_str);
141 static void fill_label_enumerated_int(field_info *fi, gchar *label_str);
142
143 int hfinfo_bitwidth(header_field_info *hfinfo);
144 static const char* hfinfo_uint_vals_format(header_field_info *hfinfo);
145 static const char* hfinfo_uint_format(header_field_info *hfinfo);
146 static const char* hfinfo_uint64_format(header_field_info *hfinfo);
147 static const char* hfinfo_int_vals_format(header_field_info *hfinfo);
148 static const char* hfinfo_int_format(header_field_info *hfinfo);
149 static const char* hfinfo_int64_format(header_field_info *hfinfo);
150
151 static proto_item*
152 proto_tree_add_node(proto_tree *tree, field_info *fi);
153
154 static header_field_info *
155 get_hfi_and_length(int hfindex, tvbuff_t *tvb, gint start, gint *length,
156     gint *item_length);
157
158 static field_info *
159 new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
160     gint start, gint item_length);
161
162 static field_info *
163 alloc_field_info(proto_tree *tree, int hfindex, tvbuff_t *tvb,
164         gint start, gint *length);
165
166 static proto_item *
167 proto_tree_add_pi(proto_tree *tree, int hfindex, tvbuff_t *tvb,
168         gint start, gint *length, field_info **pfi);
169
170 static void
171 proto_tree_set_representation_value(proto_item *pi, const char *format, va_list ap);
172 static void
173 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap);
174
175 static void
176 proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb);
177 static void
178 proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length);
179 static void
180 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length);
181 static void
182 proto_tree_set_time(field_info *fi, nstime_t *value_ptr);
183 static void
184 proto_tree_set_string(field_info *fi, const char* value);
185 static void
186 proto_tree_set_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
187 static void
188 proto_tree_set_ebcdic_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
189 static void
190 proto_tree_set_ether(field_info *fi, const guint8* value);
191 static void
192 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start);
193 static void
194 proto_tree_set_ipxnet(field_info *fi, guint32 value);
195 static void
196 proto_tree_set_ipv4(field_info *fi, guint32 value);
197 static void
198 proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr);
199 static void
200 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start);
201 static void
202 proto_tree_set_guid(field_info *fi, const e_guid_t *value_ptr);
203 static void
204 proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gboolean little_endian);
205 static void
206 proto_tree_set_oid(field_info *fi, const guint8* value_ptr, gint length);
207 static void
208 proto_tree_set_oid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
209 static void
210 proto_tree_set_boolean(field_info *fi, guint32 value);
211 static void
212 proto_tree_set_float(field_info *fi, float value);
213 static void
214 proto_tree_set_double(field_info *fi, double value);
215 static void
216 proto_tree_set_uint(field_info *fi, guint32 value);
217 static void
218 proto_tree_set_int(field_info *fi, gint32 value);
219 static void
220 proto_tree_set_uint64(field_info *fi, guint64 value);
221 static void
222 proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start, guint length, gboolean little_endian);
223
224 static int proto_register_field_init(header_field_info *hfinfo, int parent);
225
226 /* special-case header field used within proto.c */
227 int hf_text_only = -1;
228
229 /* Structure for information about a protocol */
230 struct _protocol {
231         const char *name;               /* long description */
232         const char *short_name;         /* short description */
233         const char *filter_name;        /* name of this protocol in filters */
234         int     proto_id;               /* field ID for this protocol */
235         GList   *fields;                /* fields for this protocol */
236         GList   *last_field;            /* pointer to end of list of fields */
237         gboolean is_enabled;            /* TRUE if protocol is enabled */
238         gboolean can_toggle;            /* TRUE if is_enabled can be changed */
239 };
240
241 /* List of all protocols */
242 static GList *protocols = NULL;
243
244 #define INITIAL_NUM_PROTOCOL_HFINFO     200
245
246
247 /* Contains information about protocols and header fields. Used when
248  * dissectors register their data */
249 static GMemChunk *gmc_hfinfo = NULL;
250
251 /* Contains information about a field when a dissector calls
252  * proto_tree_add_item.  */
253 SLAB_ITEM_TYPE_DEFINE(field_info)
254 static SLAB_FREE_LIST_DEFINE(field_info)
255 static field_info *field_info_tmp=NULL;
256 #define FIELD_INFO_NEW(fi)                                      \
257         SLAB_ALLOC(fi, field_info)
258 #define FIELD_INFO_FREE(fi)                                     \
259         SLAB_FREE(fi, field_info)
260
261
262
263 /* Contains the space for proto_nodes. */
264 SLAB_ITEM_TYPE_DEFINE(proto_node)
265 static SLAB_FREE_LIST_DEFINE(proto_node)
266 #define PROTO_NODE_NEW(node)                            \
267         SLAB_ALLOC(node, proto_node)                    \
268         node->first_child = NULL;                       \
269         node->last_child = NULL;                        \
270         node->next = NULL;
271
272 #define PROTO_NODE_FREE(node)                           \
273         SLAB_FREE(node, proto_node)
274
275
276
277 /* String space for protocol and field items for the GUI */
278 SLAB_ITEM_TYPE_DEFINE(item_label_t)
279 static SLAB_FREE_LIST_DEFINE(item_label_t)
280 #define ITEM_LABEL_NEW(il)                              \
281         SLAB_ALLOC(il, item_label_t)
282 #define ITEM_LABEL_FREE(il)                             \
283         SLAB_FREE(il, item_label_t)
284
285
286 #define PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo) \
287         DISSECTOR_ASSERT((guint)hfindex < gpa_hfinfo.len); \
288         hfinfo=gpa_hfinfo.hfi[hfindex];
289
290
291 /* List which stores protocols and fields that have been registered */
292 typedef struct _gpa_hfinfo_t {
293         guint32 len;
294         guint32 allocated_len;
295         header_field_info **hfi;
296 } gpa_hfinfo_t;
297 gpa_hfinfo_t gpa_hfinfo;
298
299 /* Balanced tree of abbreviations and IDs */
300 static GTree *gpa_name_tree = NULL;
301 static header_field_info *same_name_hfinfo;
302
303 #if GLIB_MAJOR_VERSION >= 2
304 static void save_same_name_hfinfo(gpointer data)
305 {
306   same_name_hfinfo = (header_field_info*)data;
307 }
308 #endif
309
310 /* Points to the first element of an array of Booleans, indexed by
311    a subtree item type; that array element is TRUE if subtrees of
312    an item of that type are to be expanded. */
313 gboolean        *tree_is_expanded;
314
315 /* Number of elements in that array. */
316 int             num_tree_types;
317
318 /* Name hashtables for fast detection of duplicate names */
319 static GHashTable* proto_names = NULL;
320 static GHashTable* proto_short_names = NULL;
321 static GHashTable* proto_filter_names = NULL;
322
323 static gint
324 proto_compare_name(gconstpointer p1_arg, gconstpointer p2_arg)
325 {
326         const protocol_t *p1 = p1_arg;
327         const protocol_t *p2 = p2_arg;
328
329         return g_ascii_strcasecmp(p1->short_name, p2->short_name);
330 }
331
332
333 /* initialize data structures and register protocols and fields */
334 void
335 proto_init(void (register_all_protocols)(register_cb cb, gpointer client_data),
336            void (register_all_protocol_handoffs)(register_cb cb, gpointer client_data),
337            register_cb cb,
338            gpointer client_data)
339 {
340         static hf_register_info hf[] = {
341                 { &hf_text_only,
342                 { "Text item",  "", FT_NONE, BASE_NONE, NULL, 0x0,
343                         NULL, HFILL }},
344         };
345
346
347         proto_names = g_hash_table_new(g_int_hash, g_int_equal);
348         proto_short_names = g_hash_table_new(wrs_str_hash, g_str_equal);
349         proto_filter_names = g_hash_table_new(wrs_str_hash, g_str_equal);
350
351         proto_cleanup();
352
353         gmc_hfinfo = g_mem_chunk_new("gmc_hfinfo",
354                 sizeof(header_field_info),
355                 INITIAL_NUM_PROTOCOL_HFINFO * sizeof(header_field_info),
356                 G_ALLOC_ONLY);
357
358         gpa_hfinfo.len=0;
359         gpa_hfinfo.allocated_len=0;
360         gpa_hfinfo.hfi=NULL;
361 #if GLIB_MAJOR_VERSION < 2
362         gpa_name_tree = g_tree_new(wrs_strcmp);
363 #else
364         gpa_name_tree = g_tree_new_full(wrs_strcmp_with_data, NULL, NULL, save_same_name_hfinfo);
365 #endif
366
367         /* Initialize the ftype subsystem */
368         ftypes_initialize();
369
370         /* Register one special-case FT_TEXT_ONLY field for use when
371            converting wireshark to new-style proto_tree. These fields
372            are merely strings on the GUI tree; they are not filterable */
373         proto_register_field_array(-1, hf, array_length(hf));
374
375         /* Have each built-in dissector register its protocols, fields,
376            dissector tables, and dissectors to be called through a
377            handle, and do whatever one-time initialization it needs to
378            do. */
379         register_all_protocols(cb, client_data);
380
381 #ifdef HAVE_PLUGINS
382         /* Now scan for plugins and load all the ones we find, calling
383            their register routines to do the stuff described above. */
384         if(cb)
385           (*cb)(RA_PLUGIN_REGISTER, NULL, client_data);
386         init_plugins();
387         register_all_plugin_registrations();
388 #endif
389
390         /* Now call the "handoff registration" routines of all built-in
391            dissectors; those routines register the dissector in other
392            dissectors' handoff tables, and fetch any dissector handles
393            they need. */
394         register_all_protocol_handoffs(cb, client_data);
395
396 #ifdef HAVE_PLUGINS
397         /* Now do the same with plugins. */
398         if(cb)
399           (*cb)(RA_PLUGIN_HANDOFF, NULL, client_data);
400         register_all_plugin_handoffs();
401 #endif
402
403         /* sort the protocols by protocol name */
404         protocols = g_list_sort(protocols, proto_compare_name);
405
406         /* We've assigned all the subtree type values; allocate the array
407            for them, and zero it out. */
408         tree_is_expanded = g_malloc(num_tree_types*sizeof (gboolean));
409         memset(tree_is_expanded, 0, num_tree_types*sizeof (gboolean));
410 }
411
412 void
413 proto_cleanup(void)
414 {
415         /* Free the abbrev/ID GTree */
416         if (gpa_name_tree) {
417                 g_tree_destroy(gpa_name_tree);
418                 gpa_name_tree = NULL;
419         }
420
421         if (gmc_hfinfo)
422                 g_mem_chunk_destroy(gmc_hfinfo);
423
424         if(gpa_hfinfo.allocated_len){
425                 gpa_hfinfo.len=0;
426                 gpa_hfinfo.allocated_len=0;
427                 g_free(gpa_hfinfo.hfi);
428                 gpa_hfinfo.hfi=NULL;
429         }
430         if (tree_is_expanded != NULL)
431                 g_free(tree_is_expanded);
432
433 }
434
435 static gboolean
436 proto_tree_traverse_pre_order(proto_tree *tree, proto_tree_traverse_func func,
437     gpointer data)
438 {
439         proto_node *pnode = tree;
440         proto_node *child;
441         proto_node *current;
442
443         if (func(pnode, data))
444                 return TRUE;
445
446         child = pnode->first_child;
447         while (child != NULL) {
448                 /*
449                  * The routine we call might modify the child, e.g. by
450                  * freeing it, so we get the child's successor before
451                  * calling that routine.
452                  */
453                 current = child;
454                 child = current->next;
455                 if (proto_tree_traverse_pre_order((proto_tree *)current, func,
456                     data))
457                         return TRUE;
458         }
459
460         return FALSE;
461 }
462
463 gboolean
464 proto_tree_traverse_in_order(proto_tree *tree, proto_tree_traverse_func func,
465     gpointer data)
466 {
467         proto_node *pnode = tree;
468         proto_node *child;
469         proto_node *current;
470
471         child = pnode->first_child;
472         if (child != NULL) {
473                 /*
474                  * The routine we call might modify the child, e.g. by
475                  * freeing it, so we get the child's successor before
476                  * calling that routine.
477                  */
478                 current = child;
479                 child = current->next;
480
481                 if (proto_tree_traverse_in_order((proto_tree *)current, func,
482                     data))
483                         return TRUE;
484
485                 if (func(pnode, data))
486                         return TRUE;
487
488                 while (child != NULL) {
489                         /*
490                          * The routine we call might modify the child, e.g. by
491                          * freeing it, so we get the child's successor before
492                          * calling that routine.
493                          */
494                         current = child;
495                         child = current->next;
496                         if (proto_tree_traverse_in_order((proto_tree *)current,
497                             func, data))
498                                 return TRUE;
499                 }
500         } else {
501                 if (func(pnode, data))
502                         return TRUE;
503         }
504
505         return FALSE;
506 }
507
508 void
509 proto_tree_children_foreach(proto_tree *tree, proto_tree_foreach_func func,
510     gpointer data)
511 {
512         proto_node *node = tree;
513         proto_node *current;
514
515         node = node->first_child;
516         while (node != NULL) {
517                 current = node;
518                 node = current->next;
519                 func((proto_tree *)current, data);
520         }
521 }
522
523 /* frees the resources that the dissection a proto_tree uses */
524 void
525 proto_tree_free(proto_tree *tree)
526 {
527         proto_tree_traverse_in_order(tree, proto_tree_free_node, NULL);
528 }
529
530 static void
531 free_GPtrArray_value(gpointer key, gpointer value, gpointer user_data _U_)
532 {
533         GPtrArray   *ptrs = value;
534         gint hfid = (gint)(long)key;
535         header_field_info *hfinfo;
536
537
538         PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
539         if(hfinfo->ref_count){
540                 /* when a field is referenced by a filter this also
541                    affects the refcount for the parent protocol so we need
542                    to adjust the refcount for the parent as well
543                 */
544                 if( (hfinfo->parent != -1) && (hfinfo->ref_count) ){
545                         header_field_info *parent_hfinfo;
546                         PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
547                         parent_hfinfo->ref_count -= hfinfo->ref_count;
548                 }
549                 hfinfo->ref_count = 0;
550         }
551
552         g_ptr_array_free(ptrs, TRUE);
553 }
554
555 static void
556 free_node_tree_data(tree_data_t *tree_data)
557 {
558         /* Free all the GPtrArray's in the interesting_hfids hash. */
559         g_hash_table_foreach(tree_data->interesting_hfids,
560             free_GPtrArray_value, NULL);
561
562         /* And then destroy the hash. */
563         g_hash_table_destroy(tree_data->interesting_hfids);
564
565         /* And finally the tree_data_t itself. */
566         g_free(tree_data);
567 }
568
569 #define FREE_NODE_FIELD_INFO(finfo)     \
570         if(finfo->rep){                 \
571                 ITEM_LABEL_FREE(finfo->rep);    \
572         }                               \
573         FVALUE_CLEANUP(&finfo->value);  \
574         FIELD_INFO_FREE(finfo);
575
576 static gboolean
577 proto_tree_free_node(proto_node *node, gpointer data _U_)
578 {
579         field_info *finfo = PITEM_FINFO(node);
580
581         if (finfo == NULL) {
582                 /* This is the root node. Destroy the per-tree data.
583                  * There is no field_info to destroy. */
584                 free_node_tree_data(PTREE_DATA(node));
585         }
586         else {
587                 /* This is a child node. Don't free the per-tree data, but
588                  * do free the field_info data. */
589                 FREE_NODE_FIELD_INFO(finfo);
590         }
591
592         /* Free the proto_node. */
593         PROTO_NODE_FREE(node);
594
595         return FALSE; /* FALSE = do not end traversal of protocol tree */
596 }
597
598 /* Is the parsing being done for a visible proto_tree or an invisible one?
599  * By setting this correctly, the proto_tree creation is sped up by not
600  * having to call g_vsnprintf and copy strings around.
601  */
602 void
603 proto_tree_set_visible(proto_tree *tree, gboolean visible)
604 {
605         PTREE_DATA(tree)->visible = visible;
606 }
607
608 /* Assume dissector set only its protocol fields.
609    This function is called by dissectors and allowes to speed up filtering
610    in wireshark, if this function returns FALSE it is safe to reset tree to NULL
611    and thus skip calling most of the expensive proto_tree_add_...()
612    functions.
613    If the tree is visible we implicitely assume the field is referenced.
614 */
615 gboolean
616 proto_field_is_referenced(proto_tree *tree, int proto_id)
617 {
618         register header_field_info *hfinfo;
619
620
621         if (!tree)
622                 return FALSE;
623
624         if (PTREE_DATA(tree)->visible)
625                 return TRUE;
626
627         PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
628         if (hfinfo->ref_count != 0)
629                 return TRUE;
630
631         return FALSE;
632 }
633
634
635 /* Finds a record in the hf_info_records array by id. */
636 header_field_info*
637 proto_registrar_get_nth(guint hfindex)
638 {
639         register header_field_info      *hfinfo;
640
641         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
642         return hfinfo;
643 }
644
645 /* Finds a record in the hf_info_records array by name.
646  */
647 header_field_info*
648 proto_registrar_get_byname(const char *field_name)
649 {
650         DISSECTOR_ASSERT(field_name != NULL);
651 #if GLIB_MAJOR_VERSION < 2
652         return g_tree_lookup(gpa_name_tree, discard_const(field_name));
653 #else
654         return g_tree_lookup(gpa_name_tree, field_name);
655 #endif
656 }
657
658
659 void ptvcursor_new_subtree_levels(ptvcursor_t * ptvc)
660 {
661   subtree_lvl * pushed_tree;
662
663   DISSECTOR_ASSERT(ptvc->pushed_tree_max <= SUBTREE_MAX_LEVELS-SUBTREE_ONCE_ALLOCATION_NUMBER);
664   ptvc->pushed_tree_max += SUBTREE_ONCE_ALLOCATION_NUMBER;
665
666   pushed_tree = ep_alloc(sizeof(subtree_lvl) * ptvc->pushed_tree_max);
667   DISSECTOR_ASSERT(pushed_tree != NULL);
668   if (ptvc->pushed_tree)
669     memcpy(pushed_tree, ptvc->pushed_tree, ptvc->pushed_tree_max - SUBTREE_ONCE_ALLOCATION_NUMBER);
670   ptvc->pushed_tree = pushed_tree;
671 }
672
673 void ptvcursor_free_subtree_levels(ptvcursor_t * ptvc)
674 {
675   ptvc->pushed_tree = NULL;
676   ptvc->pushed_tree_max = 0;
677   DISSECTOR_ASSERT(ptvc->pushed_tree_index ==0);
678   ptvc->pushed_tree_index = 0;
679 }
680
681 /* Allocates an initializes a ptvcursor_t with 3 variables:
682  *      proto_tree, tvbuff, and offset. */
683 ptvcursor_t*
684 ptvcursor_new(proto_tree *tree, tvbuff_t *tvb, gint offset)
685 {
686         ptvcursor_t     *ptvc;
687
688         ptvc = ep_alloc(sizeof(ptvcursor_t));
689         ptvc->tree      = tree;
690         ptvc->tvb       = tvb;
691         ptvc->offset    = offset;
692         ptvc->pushed_tree= NULL;
693         ptvc->pushed_tree_max= 0;
694         ptvc->pushed_tree_index= 0;
695         return ptvc;
696 }
697
698
699 /* Frees memory for ptvcursor_t, but nothing deeper than that. */
700 void
701 ptvcursor_free(ptvcursor_t *ptvc)
702 {
703         ptvcursor_free_subtree_levels(ptvc);
704         /*g_free(ptvc);*/
705 }
706
707 /* Returns tvbuff. */
708 tvbuff_t*
709 ptvcursor_tvbuff(ptvcursor_t* ptvc)
710 {
711         return ptvc->tvb;
712 }
713
714 /* Returns current offset. */
715 gint
716 ptvcursor_current_offset(ptvcursor_t* ptvc)
717 {
718         return ptvc->offset;
719 }
720
721 proto_tree*
722 ptvcursor_tree(ptvcursor_t* ptvc)
723 {
724   if (!ptvc)
725     return NULL;
726
727   return ptvc->tree;
728 }
729
730 void
731 ptvcursor_set_tree(ptvcursor_t* ptvc, proto_tree *tree)
732 {
733         ptvc->tree = tree;
734 }
735
736 /* creates a subtree, sets it as the working tree and pushes the old working tree */
737 proto_tree*
738 ptvcursor_push_subtree(ptvcursor_t *ptvc, proto_item *it, gint ett_subtree)
739 {
740   subtree_lvl * subtree;
741   if (ptvc->pushed_tree_index >= ptvc->pushed_tree_max)
742     ptvcursor_new_subtree_levels(ptvc);
743
744   subtree = ptvc->pushed_tree+ptvc->pushed_tree_index;
745   subtree->tree = ptvc->tree;
746   subtree->it= NULL;
747   ptvc->pushed_tree_index++;
748   return ptvcursor_set_subtree(ptvc, it, ett_subtree);
749 }
750
751 /* pops a subtree */
752 void
753 ptvcursor_pop_subtree(ptvcursor_t *ptvc)
754 {
755   subtree_lvl * subtree;
756   if (ptvc->pushed_tree_index <= 0)
757     return;
758
759   ptvc->pushed_tree_index--;
760   subtree = ptvc->pushed_tree+ptvc->pushed_tree_index;
761   if (subtree->it != NULL)
762     proto_item_set_len(subtree->it, ptvcursor_current_offset(ptvc) - subtree->cursor_offset);
763   ptvc->tree = subtree->tree;
764 }
765
766 /* saves the current tvb offset and the item in the current subtree level */
767 void ptvcursor_subtree_set_item(ptvcursor_t * ptvc, proto_item * it)
768 {
769   subtree_lvl * subtree;
770
771   DISSECTOR_ASSERT(ptvc->pushed_tree_index > 0);
772
773   subtree = ptvc->pushed_tree+ptvc->pushed_tree_index-1;
774   subtree->it = it;
775   subtree->cursor_offset = ptvcursor_current_offset(ptvc);
776 }
777
778 /* Creates a subtree and adds it to the cursor as the working tree but does not
779  * save the old working tree */
780 proto_tree*
781 ptvcursor_set_subtree(ptvcursor_t *ptvc, proto_item *it, gint ett_subtree)
782 {
783   ptvc->tree = proto_item_add_subtree(it, ett_subtree);
784   return ptvc->tree;
785 }
786
787 proto_tree* ptvcursor_add_subtree_item(ptvcursor_t * ptvc, proto_item * it, gint ett_subtree, gint length)
788 {
789   ptvcursor_push_subtree(ptvc, it, ett_subtree);
790   if (length == SUBTREE_UNDEFINED_LENGTH)
791     ptvcursor_subtree_set_item(ptvc, it);
792   return ptvcursor_tree(ptvc);
793 }
794
795 /* Add an item to the tree and create a subtree
796  * If the length is unknown, length may be defined as SUBTREE_UNDEFINED_LENGTH.
797  * In this case, when the subtree will be closed, the parent item length will
798  * be equal to the advancement of the cursor since the creation of the subtree.
799  */
800 proto_tree* ptvcursor_add_with_subtree(ptvcursor_t * ptvc, int hfindex, gint length,
801 gboolean little_endian, gint ett_subtree)
802 {
803   proto_item * it;
804   it = ptvcursor_add_no_advance(ptvc, hfindex, length, little_endian);
805   return ptvcursor_add_subtree_item(ptvc, it, ett_subtree, length);
806 }
807
808 static proto_item *
809 proto_tree_add_text_node(proto_tree *tree, tvbuff_t *tvb, gint start, gint length);
810
811 /* Add a text node to the tree and create a subtree
812  * If the length is unknown, length may be defined as SUBTREE_UNDEFINED_LENGTH.
813  * In this case, when the subtree will be closed, the item length will be equal
814  * to the advancement of the cursor since the creation of the subtree.
815  */
816 proto_tree * ptvcursor_add_text_with_subtree(ptvcursor_t * ptvc, gint length,
817     gint ett_subtree, const char *format, ...)
818 {
819   proto_item *  it;
820   va_list       ap;
821
822   it = proto_tree_add_text_node(ptvcursor_tree(ptvc), ptvcursor_tvbuff(ptvc),
823       ptvcursor_current_offset(ptvc), length);
824
825   va_start(ap, format);
826   proto_tree_set_representation(it, format, ap);
827   va_end(ap);
828
829   return ptvcursor_add_subtree_item(ptvc, it, ett_subtree, length);
830 }
831
832 /* Add a text-only node, leaving it to our caller to fill the text in */
833 static proto_item *
834 proto_tree_add_text_node(proto_tree *tree, tvbuff_t *tvb, gint start, gint length)
835 {
836         proto_item      *pi;
837
838         pi = proto_tree_add_pi(tree, hf_text_only, tvb, start, &length, NULL);
839         if (pi == NULL)
840                 return(NULL);
841
842         return pi;
843 }
844
845 /* Add a text-only node to the proto_tree */
846 proto_item *
847 proto_tree_add_text(proto_tree *tree, tvbuff_t *tvb, gint start, gint length,
848         const char *format, ...)
849 {
850         proto_item      *pi;
851         va_list         ap;
852
853         pi = proto_tree_add_text_node(tree, tvb, start, length);
854         if (pi == NULL)
855                 return(NULL);
856
857         va_start(ap, format);
858         proto_tree_set_representation(pi, format, ap);
859         va_end(ap);
860
861         return pi;
862 }
863
864 /* Add a text-only node to the proto_tree (va_list version) */
865 proto_item *
866 proto_tree_add_text_valist(proto_tree *tree, tvbuff_t *tvb, gint start,
867         gint length, const char *format, va_list ap)
868 {
869         proto_item      *pi;
870
871         pi = proto_tree_add_text_node(tree, tvb, start, length);
872         if (pi == NULL)
873                 return(NULL);
874
875         proto_tree_set_representation(pi, format, ap);
876
877         return pi;
878 }
879
880 /* Add a text-only node for debugging purposes. The caller doesn't need
881  * to worry about tvbuff, start, or length. Debug message gets sent to
882  * STDOUT, too */
883 proto_item *
884 proto_tree_add_debug_text(proto_tree *tree, const char *format, ...)
885 {
886         proto_item      *pi;
887         va_list         ap;
888
889         pi = proto_tree_add_text_node(tree, NULL, 0, 0);
890         if (pi == NULL)
891                 return(NULL);
892
893         va_start(ap, format);
894         proto_tree_set_representation(pi, format, ap);
895         vprintf(format, ap);
896         va_end(ap);
897         printf("\n");
898
899         return pi;
900 }
901
902
903 static guint32
904 get_uint_value(tvbuff_t *tvb, gint offset, gint length, gboolean little_endian)
905 {
906         guint32 value;
907
908         switch (length) {
909
910         case 1:
911                 value = tvb_get_guint8(tvb, offset);
912                 break;
913
914         case 2:
915                 value = little_endian ? tvb_get_letohs(tvb, offset)
916                                       : tvb_get_ntohs(tvb, offset);
917                 break;
918
919         case 3:
920                 value = little_endian ? tvb_get_letoh24(tvb, offset)
921                                       : tvb_get_ntoh24(tvb, offset);
922                 break;
923
924         case 4:
925                 value = little_endian ? tvb_get_letohl(tvb, offset)
926                                       : tvb_get_ntohl(tvb, offset);
927                 break;
928
929         default:
930                 DISSECTOR_ASSERT_NOT_REACHED();
931                 value = 0;
932                 break;
933         }
934         return value;
935 }
936
937 static gint32
938 get_int_value(tvbuff_t *tvb, gint offset, gint length, gboolean little_endian)
939 {
940         gint32 value;
941
942         switch (length) {
943
944         case 1:
945                 value = (gint8)tvb_get_guint8(tvb, offset);
946                 break;
947
948         case 2:
949                 value = (gint16) (little_endian ? tvb_get_letohs(tvb, offset)
950                                                 : tvb_get_ntohs(tvb, offset));
951                 break;
952
953         case 3:
954                 value = little_endian ? tvb_get_letoh24(tvb, offset)
955                                       : tvb_get_ntoh24(tvb, offset);
956                 if (value & 0x00800000) {
957                         /* Sign bit is set; sign-extend it. */
958                         value |= 0xFF000000;
959                 }
960                 break;
961
962         case 4:
963                 value = little_endian ? tvb_get_letohl(tvb, offset)
964                                       : tvb_get_ntohl(tvb, offset);
965                 break;
966
967         default:
968                 DISSECTOR_ASSERT_NOT_REACHED();
969                 value = 0;
970                 break;
971         }
972         return value;
973 }
974
975 /* Add an item to a proto_tree, using the text label registered to that item;
976    the item is extracted from the tvbuff handed to it. */
977 static proto_item *
978 proto_tree_new_item(field_info *new_fi, proto_tree *tree, int hfindex,
979     tvbuff_t *tvb, gint start, gint length, gboolean little_endian)
980 {
981         proto_item      *pi;
982         guint32         value, n;
983         float           floatval;
984         double          doubleval;
985         char            *string;
986         GHashTable      *hash;
987         GPtrArray       *ptrs;
988
989         /* there is a possibility here that we might raise an exception
990          * and thus would lose track of the field_info.
991          * store it in a temp so that if we come here again we can reclaim
992          * the field_info without leaking memory.
993          */
994         /* XXX this only keeps track of one field_info struct,
995            if we ever go multithreaded for calls to this function
996            we have to change this code to use per thread variable.
997         */
998         if(field_info_tmp){
999                 /* oops, last one we got must have been lost due
1000                  * to an exception.
1001                  * good thing we saved it, now we can reverse the
1002                  * memory leak and reclaim it.
1003                  */
1004                 SLAB_FREE(field_info_tmp, field_info);
1005         }
1006         /* we might throw an exception, keep track of this one
1007          * across the "dangerous" section below.
1008         */
1009         field_info_tmp=new_fi;
1010
1011         switch(new_fi->hfinfo->type) {
1012                 case FT_NONE:
1013                         /* no value to set for FT_NONE */
1014                         break;
1015
1016                 case FT_PROTOCOL:
1017                         proto_tree_set_protocol_tvb(new_fi, tvb);
1018                         break;
1019
1020                 case FT_BYTES:
1021                         proto_tree_set_bytes_tvb(new_fi, tvb, start, length);
1022                         break;
1023
1024                 case FT_UINT_BYTES:
1025                         n = get_uint_value(tvb, start, length, little_endian);
1026                         proto_tree_set_bytes_tvb(new_fi, tvb, start + length, n);
1027
1028                         /* Instead of calling proto_item_set_len(), since we don't yet
1029                          * have a proto_item, we set the field_info's length ourselves. */
1030                         new_fi->length = n + length;
1031                         break;
1032
1033                 case FT_BOOLEAN:
1034                         proto_tree_set_boolean(new_fi,
1035                             get_uint_value(tvb, start, length, little_endian));
1036                         break;
1037
1038                 /* XXX - make these just FT_UINT? */
1039                 case FT_UINT8:
1040                 case FT_UINT16:
1041                 case FT_UINT24:
1042                 case FT_UINT32:
1043                         proto_tree_set_uint(new_fi,
1044                             get_uint_value(tvb, start, length, little_endian));
1045                         break;
1046
1047                 case FT_INT64:
1048                 case FT_UINT64:
1049                         DISSECTOR_ASSERT( length <= 8 && length >= 1);
1050                         proto_tree_set_uint64_tvb(new_fi, tvb, start, length, little_endian);
1051                         break;
1052
1053                 /* XXX - make these just FT_INT? */
1054                 case FT_INT8:
1055                 case FT_INT16:
1056                 case FT_INT24:
1057                 case FT_INT32:
1058                         proto_tree_set_int(new_fi,
1059                             get_int_value(tvb, start, length, little_endian));
1060                         break;
1061
1062                 case FT_IPv4:
1063                         DISSECTOR_ASSERT(length == 4);
1064                         value = tvb_get_ipv4(tvb, start);
1065                         proto_tree_set_ipv4(new_fi, little_endian ? GUINT32_SWAP_LE_BE(value) : value);
1066                         break;
1067
1068                 case FT_IPXNET:
1069                         DISSECTOR_ASSERT(length == 4);
1070                         proto_tree_set_ipxnet(new_fi,
1071                             get_uint_value(tvb, start, 4, FALSE));
1072                         break;
1073
1074                 case FT_IPv6:
1075                         DISSECTOR_ASSERT(length == 16);
1076                         proto_tree_set_ipv6_tvb(new_fi, tvb, start);
1077                         break;
1078
1079                 case FT_ETHER:
1080                         DISSECTOR_ASSERT(length == 6);
1081                         proto_tree_set_ether_tvb(new_fi, tvb, start);
1082                         break;
1083
1084                 case FT_GUID:
1085                         DISSECTOR_ASSERT(length == 16);
1086                         proto_tree_set_guid_tvb(new_fi, tvb, start, little_endian);
1087                         break;
1088
1089                 case FT_OID:
1090                         proto_tree_set_oid_tvb(new_fi, tvb, start, length);
1091                         break;
1092
1093                 case FT_FLOAT:
1094                         DISSECTOR_ASSERT(length == 4);
1095                         if (little_endian)
1096                                 floatval = tvb_get_letohieee_float(tvb, start);
1097                         else
1098                                 floatval = tvb_get_ntohieee_float(tvb, start);
1099                         proto_tree_set_float(new_fi, floatval);
1100                         break;
1101
1102                 case FT_DOUBLE:
1103                         DISSECTOR_ASSERT(length == 8);
1104                         if (little_endian)
1105                                 doubleval = tvb_get_letohieee_double(tvb, start);
1106                         else
1107                                 doubleval = tvb_get_ntohieee_double(tvb, start);
1108                         proto_tree_set_double(new_fi, doubleval);
1109                         break;
1110
1111                 case FT_STRING:
1112                         proto_tree_set_string_tvb(new_fi, tvb, start, length);
1113                         break;
1114
1115                 case FT_STRINGZ:
1116                         DISSECTOR_ASSERT(length >= -1);
1117                         /* Instead of calling proto_item_set_len(),
1118                          * since we don't yet have a proto_item, we
1119                          * set the field_info's length ourselves.
1120                          *
1121                          * XXX - our caller can't use that length to
1122                          * advance an offset unless they arrange that
1123                          * there always be a protocol tree into which
1124                          * we're putting this item.
1125                          */
1126                         if (length == -1) {
1127                                 /* This can throw an exception */
1128                                 length = tvb_strsize(tvb, start);
1129
1130                                 string = ep_alloc(length);
1131
1132                                 tvb_memcpy(tvb, string, start, length);
1133                         } else if (length == 0) {
1134                                 string = "[Empty]";
1135                         } else {
1136                                 /* In this case, length signifies
1137                                  * the length of the string.
1138                                  *
1139                                  * This could either be a null-padded
1140                                  * string, which doesn't necessarily
1141                                  * have a '\0' at the end, or a
1142                                  * null-terminated string, with a
1143                                  * trailing '\0'.  (Yes, there are
1144                                  * cases where you have a string
1145                                  * that's both counted and null-
1146                                  * terminated.)
1147                                  *
1148                                  * In the first case, we must
1149                                  * allocate a buffer of length
1150                                  * "length+1", to make room for
1151                                  * a trailing '\0'.
1152                                  *
1153                                  * In the second case, we don't
1154                                  * assume that there is a trailing
1155                                  * '\0' there, as the packet might
1156                                  * be malformed.  (XXX - should we
1157                                  * throw an exception if there's no
1158                                  * trailing '\0'?)  Therefore, we
1159                                  * allocate a buffer of length
1160                                  * "length+1", and put in a trailing
1161                                  * '\0', just to be safe.
1162                                  *
1163                                  * (XXX - this would change if
1164                                  * we made string values counted
1165                                  * rather than null-terminated.)
1166                                  */
1167                                 string = tvb_get_ephemeral_string(tvb,
1168                                                                           start,
1169                                                                           length);
1170                         }
1171                         new_fi->length = length;
1172                         proto_tree_set_string(new_fi, string);
1173                         break;
1174
1175                 case FT_EBCDIC:
1176                         proto_tree_set_ebcdic_string_tvb(new_fi, tvb, start, length);
1177                         break;
1178
1179                 case FT_UINT_STRING:
1180                         n = get_uint_value(tvb, start, length, little_endian);
1181                         proto_tree_set_string_tvb(new_fi, tvb, start + length, n);
1182
1183                         /* Instead of calling proto_item_set_len(), since we
1184                          * don't yet have a proto_item, we set the
1185                          * field_info's length ourselves.
1186                          *
1187                          * XXX - our caller can't use that length to
1188                          * advance an offset unless they arrange that
1189                          * there always be a protocol tree into which
1190                          * we're putting this item.
1191                          */
1192                         new_fi->length = n + length;
1193                         break;
1194
1195                 default:
1196                         g_error("new_fi->hfinfo->type %d (%s) not handled\n",
1197                                         new_fi->hfinfo->type,
1198                                         ftype_name(new_fi->hfinfo->type));
1199                         DISSECTOR_ASSERT_NOT_REACHED();
1200                         break;
1201         }
1202
1203         /* Don't add new node to proto_tree until now so that any exceptions
1204          * raised by a tvbuff access method doesn't leave junk in the proto_tree. */
1205         pi = proto_tree_add_node(tree, new_fi);
1206
1207         /* we did not raise an exception so we dont have to remember this
1208          * field_info struct any more.
1209          */
1210         field_info_tmp=NULL;
1211
1212         /* If the proto_tree wants to keep a record of this finfo
1213          * for quick lookup, then record it. */
1214         if (new_fi->hfinfo->ref_count) {
1215                 /*HERE*/
1216                 hash = PTREE_DATA(tree)->interesting_hfids;
1217                 ptrs = g_hash_table_lookup(hash, GINT_TO_POINTER(hfindex));
1218                 if (ptrs) {
1219                         g_ptr_array_add(ptrs, new_fi);
1220                 }
1221         }
1222
1223         return pi;
1224 }
1225
1226 /* Gets data from tvbuff, adds it to proto_tree, increments offset,
1227    and returns proto_item* */
1228 proto_item*
1229 ptvcursor_add(ptvcursor_t *ptvc, int hfindex, gint length,
1230     gboolean little_endian)
1231 {
1232         field_info              *new_fi;
1233         header_field_info       *hfinfo;
1234         gint                    item_length;
1235         guint32                 n;
1236         int                     offset;
1237
1238         offset = ptvc->offset;
1239         hfinfo = get_hfi_and_length(hfindex, ptvc->tvb, offset, &length,
1240             &item_length);
1241         ptvc->offset += length;
1242         if (hfinfo->type == FT_UINT_BYTES || hfinfo->type == FT_UINT_STRING) {
1243                 /*
1244                  * The length of the rest of the item is in the first N
1245                  * bytes of the item.
1246                  */
1247                 n = get_uint_value(ptvc->tvb, offset, length, little_endian);
1248                 ptvc->offset += n;
1249         }
1250         if (ptvc->tree == NULL)
1251                 return NULL;
1252
1253         TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfindex);
1254
1255         new_fi = new_field_info(ptvc->tree, hfinfo, ptvc->tvb, offset,
1256             item_length);
1257         if (new_fi == NULL)
1258                 return NULL;
1259
1260         return proto_tree_new_item(new_fi, ptvc->tree, hfindex, ptvc->tvb,
1261             offset, length, little_endian);
1262 }
1263
1264 /* Add an item to a proto_tree, using the text label registered to that item;
1265    the item is extracted from the tvbuff handed to it. */
1266 proto_item *
1267 proto_tree_add_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1268     gint start, gint length, gboolean little_endian)
1269 {
1270         field_info      *new_fi;
1271
1272         if (!tree)
1273                 return(NULL);
1274
1275         TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1276
1277         new_fi = alloc_field_info(tree, hfindex, tvb, start, &length);
1278
1279         if (new_fi == NULL)
1280                 return(NULL);
1281
1282         return proto_tree_new_item(new_fi, tree, hfindex, tvb, start,
1283             length, little_endian);
1284 }
1285
1286 proto_item *
1287 proto_tree_add_item_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1288     gint start, gint length, gboolean little_endian)
1289 {
1290         proto_item      *pi;
1291
1292         pi = proto_tree_add_item(tree, hfindex, tvb, start, length, little_endian);
1293         if (pi == NULL)
1294                 return(NULL);
1295
1296         PROTO_ITEM_SET_HIDDEN(pi);
1297
1298         return pi;
1299 }
1300
1301
1302 /* Add a FT_NONE to a proto_tree */
1303 proto_item *
1304 proto_tree_add_none_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1305                 gint length, const char *format, ...)
1306 {
1307         proto_item              *pi;
1308         va_list                 ap;
1309         header_field_info       *hfinfo;
1310
1311         if (!tree)
1312                 return (NULL);
1313
1314         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1315         DISSECTOR_ASSERT(hfinfo->type == FT_NONE);
1316
1317         pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, NULL);
1318
1319         va_start(ap, format);
1320         proto_tree_set_representation(pi, format, ap);
1321         va_end(ap);
1322
1323         /* no value to set for FT_NONE */
1324         return pi;
1325 }
1326
1327 /* Gets data from tvbuff, adds it to proto_tree, *DOES NOT* increment
1328  * offset, and returns proto_item* */
1329 proto_item*
1330 ptvcursor_add_no_advance(ptvcursor_t* ptvc, int hf, gint length,
1331                 gboolean endianness)
1332 {
1333         proto_item      *item;
1334
1335         item = proto_tree_add_item(ptvc->tree, hf, ptvc->tvb, ptvc->offset,
1336                         length, endianness);
1337
1338         return item;
1339 }
1340
1341 /* Advance the ptvcursor's offset within its tvbuff without
1342  * adding anything to the proto_tree. */
1343 void
1344 ptvcursor_advance(ptvcursor_t* ptvc, gint length)
1345 {
1346         ptvc->offset += length;
1347 }
1348
1349
1350 static void
1351 proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb)
1352 {
1353         fvalue_set(&fi->value, tvb, TRUE);
1354 }
1355
1356 /* Add a FT_PROTOCOL to a proto_tree */
1357 proto_item *
1358 proto_tree_add_protocol_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1359                 gint length, const char *format, ...)
1360 {
1361         proto_item              *pi;
1362         va_list                 ap;
1363         header_field_info       *hfinfo;
1364         field_info              *new_fi;
1365
1366         if (!tree)
1367                 return (NULL);
1368
1369         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1370         DISSECTOR_ASSERT(hfinfo->type == FT_PROTOCOL);
1371
1372         pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1373
1374         va_start(ap, format);
1375         proto_tree_set_representation(pi, format, ap);
1376         va_end(ap);
1377
1378         if (start == 0) {
1379                 proto_tree_set_protocol_tvb(new_fi, tvb);
1380         }
1381         else {
1382                 proto_tree_set_protocol_tvb(new_fi, NULL);
1383         }
1384         return pi;
1385 }
1386
1387
1388 /* Add a FT_BYTES to a proto_tree */
1389 proto_item *
1390 proto_tree_add_bytes(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1391                 gint length, const guint8 *start_ptr)
1392 {
1393         proto_item              *pi;
1394         field_info              *new_fi;
1395         header_field_info       *hfinfo;
1396
1397         if (!tree)
1398                 return (NULL);
1399
1400         TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1401
1402         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1403         DISSECTOR_ASSERT(hfinfo->type == FT_BYTES);
1404
1405         pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1406         proto_tree_set_bytes(new_fi, start_ptr, length);
1407
1408         return pi;
1409 }
1410
1411 proto_item *
1412 proto_tree_add_bytes_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1413                 gint length, const guint8 *start_ptr)
1414 {
1415         proto_item              *pi;
1416
1417         pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length, start_ptr);
1418         if (pi == NULL)
1419                 return (NULL);
1420
1421         PROTO_ITEM_SET_HIDDEN(pi);
1422
1423         return pi;
1424 }
1425
1426 proto_item *
1427 proto_tree_add_bytes_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1428                 gint start, gint length, const guint8 *start_ptr,
1429                 const char *format, ...)
1430 {
1431         proto_item              *pi;
1432         va_list                 ap;
1433
1434         pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length, start_ptr);
1435         if (pi == NULL)
1436                 return (NULL);
1437
1438         va_start(ap, format);
1439         proto_tree_set_representation_value(pi, format, ap);
1440         va_end(ap);
1441
1442         return pi;
1443 }
1444
1445 proto_item *
1446 proto_tree_add_bytes_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1447                 gint length, const guint8 *start_ptr, const char *format, ...)
1448 {
1449         proto_item              *pi;
1450         va_list                 ap;
1451
1452         pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length, start_ptr);
1453         if (pi == NULL)
1454                 return (NULL);
1455
1456         va_start(ap, format);
1457         proto_tree_set_representation(pi, format, ap);
1458         va_end(ap);
1459
1460         return pi;
1461 }
1462
1463 static void
1464 proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length)
1465 {
1466         GByteArray              *bytes;
1467
1468         bytes = g_byte_array_new();
1469         if (length > 0) {
1470                 g_byte_array_append(bytes, start_ptr, length);
1471         }
1472         fvalue_set(&fi->value, bytes, TRUE);
1473 }
1474
1475
1476 static void
1477 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length)
1478 {
1479         proto_tree_set_bytes(fi, tvb_get_ptr(tvb, offset, length), length);
1480 }
1481
1482 /* Add a FT_*TIME to a proto_tree */
1483 proto_item *
1484 proto_tree_add_time(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1485                 nstime_t *value_ptr)
1486 {
1487         proto_item              *pi;
1488         field_info              *new_fi;
1489         header_field_info       *hfinfo;
1490
1491         if (!tree)
1492                 return (NULL);
1493
1494         TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1495
1496         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1497         DISSECTOR_ASSERT(hfinfo->type == FT_ABSOLUTE_TIME ||
1498                                 hfinfo->type == FT_RELATIVE_TIME);
1499
1500         pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1501         proto_tree_set_time(new_fi, value_ptr);
1502
1503         return pi;
1504 }
1505
1506 proto_item *
1507 proto_tree_add_time_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1508                 nstime_t *value_ptr)
1509 {
1510         proto_item              *pi;
1511
1512         pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
1513         if (pi == NULL)
1514                 return (NULL);
1515
1516         PROTO_ITEM_SET_HIDDEN(pi);
1517
1518         return pi;
1519 }
1520
1521 proto_item *
1522 proto_tree_add_time_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1523                 gint start, gint length, nstime_t *value_ptr,
1524                 const char *format, ...)
1525 {
1526         proto_item              *pi;
1527         va_list                 ap;
1528
1529         pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
1530         if (pi == NULL)
1531                 return (NULL);
1532
1533         va_start(ap, format);
1534         proto_tree_set_representation_value(pi, format, ap);
1535         va_end(ap);
1536
1537         return pi;
1538 }
1539
1540 proto_item *
1541 proto_tree_add_time_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1542                 nstime_t *value_ptr, const char *format, ...)
1543 {
1544         proto_item              *pi;
1545         va_list                 ap;
1546
1547         pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
1548         if (pi == NULL)
1549                 return (NULL);
1550
1551         va_start(ap, format);
1552         proto_tree_set_representation(pi, format, ap);
1553         va_end(ap);
1554
1555         return pi;
1556 }
1557
1558 /* Set the FT_*TIME value */
1559 static void
1560 proto_tree_set_time(field_info *fi, nstime_t *value_ptr)
1561 {
1562         DISSECTOR_ASSERT(value_ptr != NULL);
1563         fvalue_set(&fi->value, value_ptr, FALSE);
1564 }
1565
1566 /* Add a FT_IPXNET to a proto_tree */
1567 proto_item *
1568 proto_tree_add_ipxnet(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1569                 guint32 value)
1570 {
1571         proto_item              *pi;
1572         field_info              *new_fi;
1573         header_field_info       *hfinfo;
1574
1575         if (!tree)
1576                 return (NULL);
1577
1578         TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1579
1580         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1581         DISSECTOR_ASSERT(hfinfo->type == FT_IPXNET);
1582
1583         pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1584         proto_tree_set_ipxnet(new_fi, value);
1585
1586         return pi;
1587 }
1588
1589 proto_item *
1590 proto_tree_add_ipxnet_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1591                 guint32 value)
1592 {
1593         proto_item              *pi;
1594
1595         pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
1596         if (pi == NULL)
1597                 return (NULL);
1598
1599         PROTO_ITEM_SET_HIDDEN(pi);
1600
1601         return pi;
1602 }
1603
1604 proto_item *
1605 proto_tree_add_ipxnet_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1606                 gint start, gint length, guint32 value, const char *format, ...)
1607 {
1608         proto_item              *pi;
1609         va_list                 ap;
1610
1611         pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
1612         if (pi == NULL)
1613                 return (NULL);
1614
1615         va_start(ap, format);
1616         proto_tree_set_representation_value(pi, format, ap);
1617         va_end(ap);
1618
1619         return pi;
1620 }
1621
1622 proto_item *
1623 proto_tree_add_ipxnet_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1624                 guint32 value, const char *format, ...)
1625 {
1626         proto_item              *pi;
1627         va_list                 ap;
1628
1629         pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
1630         if (pi == NULL)
1631                 return (NULL);
1632
1633         va_start(ap, format);
1634         proto_tree_set_representation(pi, format, ap);
1635         va_end(ap);
1636
1637         return pi;
1638 }
1639
1640 /* Set the FT_IPXNET value */
1641 static void
1642 proto_tree_set_ipxnet(field_info *fi, guint32 value)
1643 {
1644         fvalue_set_uinteger(&fi->value, value);
1645 }
1646
1647 /* Add a FT_IPv4 to a proto_tree */
1648 proto_item *
1649 proto_tree_add_ipv4(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1650                 guint32 value)
1651 {
1652         proto_item              *pi;
1653         field_info              *new_fi;
1654         header_field_info       *hfinfo;
1655
1656         if (!tree)
1657                 return (NULL);
1658
1659         TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1660
1661         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1662         DISSECTOR_ASSERT(hfinfo->type == FT_IPv4);
1663
1664         pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1665         proto_tree_set_ipv4(new_fi, value);
1666
1667         return pi;
1668 }
1669
1670 proto_item *
1671 proto_tree_add_ipv4_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1672                 guint32 value)
1673 {
1674         proto_item              *pi;
1675
1676         pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
1677         if (pi == NULL)
1678                 return (NULL);
1679
1680         PROTO_ITEM_SET_HIDDEN(pi);
1681
1682         return pi;
1683 }
1684
1685 proto_item *
1686 proto_tree_add_ipv4_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1687                 gint start, gint length, guint32 value, const char *format, ...)
1688 {
1689         proto_item              *pi;
1690         va_list                 ap;
1691
1692         pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
1693         if (pi == NULL)
1694                 return (NULL);
1695
1696         va_start(ap, format);
1697         proto_tree_set_representation_value(pi, format, ap);
1698         va_end(ap);
1699
1700         return pi;
1701 }
1702
1703 proto_item *
1704 proto_tree_add_ipv4_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1705                 guint32 value, const char *format, ...)
1706 {
1707         proto_item              *pi;
1708         va_list                 ap;
1709
1710         pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
1711         if (pi == NULL)
1712                 return (NULL);
1713
1714         va_start(ap, format);
1715         proto_tree_set_representation(pi, format, ap);
1716         va_end(ap);
1717
1718         return pi;
1719 }
1720
1721 /* Set the FT_IPv4 value */
1722 static void
1723 proto_tree_set_ipv4(field_info *fi, guint32 value)
1724 {
1725         fvalue_set_uinteger(&fi->value, value);
1726 }
1727
1728 /* Add a FT_IPv6 to a proto_tree */
1729 proto_item *
1730 proto_tree_add_ipv6(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1731                 const guint8* value_ptr)
1732 {
1733         proto_item              *pi;
1734         field_info              *new_fi;
1735         header_field_info       *hfinfo;
1736
1737         if (!tree)
1738                 return (NULL);
1739
1740         TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1741
1742         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1743         DISSECTOR_ASSERT(hfinfo->type == FT_IPv6);
1744
1745         pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1746         proto_tree_set_ipv6(new_fi, value_ptr);
1747
1748         return pi;
1749 }
1750
1751 proto_item *
1752 proto_tree_add_ipv6_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1753                 const guint8* value_ptr)
1754 {
1755         proto_item              *pi;
1756
1757         pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
1758         if (pi == NULL)
1759                 return (NULL);
1760
1761         PROTO_ITEM_SET_HIDDEN(pi);
1762
1763         return pi;
1764 }
1765
1766 proto_item *
1767 proto_tree_add_ipv6_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1768                 gint start, gint length, const guint8* value_ptr,
1769                 const char *format, ...)
1770 {
1771         proto_item              *pi;
1772         va_list                 ap;
1773
1774         pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
1775         if (pi == NULL)
1776                 return (NULL);
1777
1778         va_start(ap, format);
1779         proto_tree_set_representation_value(pi, format, ap);
1780         va_end(ap);
1781
1782         return pi;
1783 }
1784
1785 proto_item *
1786 proto_tree_add_ipv6_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1787                 const guint8* value_ptr, const char *format, ...)
1788 {
1789         proto_item              *pi;
1790         va_list                 ap;
1791
1792         pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
1793         if (pi == NULL)
1794                 return (NULL);
1795
1796         va_start(ap, format);
1797         proto_tree_set_representation(pi, format, ap);
1798         va_end(ap);
1799
1800         return pi;
1801 }
1802
1803 /* Set the FT_IPv6 value */
1804 static void
1805 proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr)
1806 {
1807         DISSECTOR_ASSERT(value_ptr != NULL);
1808         fvalue_set(&fi->value, (gpointer) value_ptr, FALSE);
1809 }
1810
1811 static void
1812 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start)
1813 {
1814         proto_tree_set_ipv6(fi, tvb_get_ptr(tvb, start, 16));
1815 }
1816
1817 /* Add a FT_GUID to a proto_tree */
1818 proto_item *
1819 proto_tree_add_guid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1820                 const e_guid_t *value_ptr)
1821 {
1822         proto_item              *pi;
1823         field_info              *new_fi;
1824         header_field_info       *hfinfo;
1825
1826         if (!tree)
1827                 return (NULL);
1828
1829         TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1830
1831         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1832         DISSECTOR_ASSERT(hfinfo->type == FT_GUID);
1833
1834         pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1835         proto_tree_set_guid(new_fi, value_ptr);
1836
1837         return pi;
1838 }
1839
1840 proto_item *
1841 proto_tree_add_guid_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1842                 const e_guid_t *value_ptr)
1843 {
1844         proto_item              *pi;
1845
1846         pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
1847         if (pi == NULL)
1848                 return (NULL);
1849
1850         PROTO_ITEM_SET_HIDDEN(pi);
1851
1852         return pi;
1853 }
1854
1855 proto_item *
1856 proto_tree_add_guid_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1857                 gint start, gint length, const e_guid_t *value_ptr,
1858                 const char *format, ...)
1859 {
1860         proto_item              *pi;
1861         va_list                 ap;
1862
1863         pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
1864         if (pi == NULL)
1865                 return (NULL);
1866
1867         va_start(ap, format);
1868         proto_tree_set_representation_value(pi, format, ap);
1869         va_end(ap);
1870
1871         return pi;
1872 }
1873
1874 proto_item *
1875 proto_tree_add_guid_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1876                 const e_guid_t *value_ptr, const char *format, ...)
1877 {
1878         proto_item              *pi;
1879         va_list                 ap;
1880
1881         pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
1882         if (pi == NULL)
1883                 return (NULL);
1884
1885         va_start(ap, format);
1886         proto_tree_set_representation(pi, format, ap);
1887         va_end(ap);
1888
1889         return pi;
1890 }
1891
1892 /* Set the FT_GUID value */
1893 static void
1894 proto_tree_set_guid(field_info *fi, const e_guid_t *value_ptr)
1895 {
1896         DISSECTOR_ASSERT(value_ptr != NULL);
1897         fvalue_set(&fi->value, (gpointer) value_ptr, FALSE);
1898 }
1899
1900 static void
1901 proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gboolean little_endian)
1902 {
1903         e_guid_t guid;
1904
1905         tvb_get_guid(tvb, start, &guid, little_endian);
1906         proto_tree_set_guid(fi, &guid);
1907 }
1908
1909 /* Add a FT_OID to a proto_tree */
1910 proto_item *
1911 proto_tree_add_oid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1912                 const guint8* value_ptr)
1913 {
1914         proto_item              *pi;
1915         field_info              *new_fi;
1916         header_field_info       *hfinfo;
1917
1918         if (!tree)
1919                 return (NULL);
1920
1921         TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1922
1923         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1924         DISSECTOR_ASSERT(hfinfo->type == FT_OID);
1925
1926         pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1927         proto_tree_set_oid(new_fi, value_ptr, length);
1928
1929         return pi;
1930 }
1931
1932 proto_item *
1933 proto_tree_add_oid_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1934                 const guint8* value_ptr)
1935 {
1936         proto_item              *pi;
1937
1938         pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
1939         if (pi == NULL)
1940                 return (NULL);
1941
1942         PROTO_ITEM_SET_HIDDEN(pi);
1943
1944         return pi;
1945 }
1946
1947 proto_item *
1948 proto_tree_add_oid_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1949                 gint start, gint length, const guint8* value_ptr,
1950                 const char *format, ...)
1951 {
1952         proto_item              *pi;
1953         va_list                 ap;
1954
1955         pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
1956         if (pi == NULL)
1957                 return (NULL);
1958
1959         va_start(ap, format);
1960         proto_tree_set_representation_value(pi, format, ap);
1961         va_end(ap);
1962
1963         return pi;
1964 }
1965
1966 proto_item *
1967 proto_tree_add_oid_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1968                 const guint8* value_ptr, const char *format, ...)
1969 {
1970         proto_item              *pi;
1971         va_list                 ap;
1972
1973         pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
1974         if (pi == NULL)
1975                 return (NULL);
1976
1977         va_start(ap, format);
1978         proto_tree_set_representation(pi, format, ap);
1979         va_end(ap);
1980
1981         return pi;
1982 }
1983
1984 /* Set the FT_OID value */
1985 static void
1986 proto_tree_set_oid(field_info *fi, const guint8* value_ptr, gint length)
1987 {
1988         GByteArray              *bytes;
1989
1990         DISSECTOR_ASSERT(value_ptr != NULL);
1991
1992         bytes = g_byte_array_new();
1993         if (length > 0) {
1994                 g_byte_array_append(bytes, value_ptr, length);
1995         }
1996         fvalue_set(&fi->value, bytes, TRUE);
1997 }
1998
1999 static void
2000 proto_tree_set_oid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
2001 {
2002         proto_tree_set_oid(fi, tvb_get_ptr(tvb, start, length), length);
2003 }
2004
2005 static void
2006 proto_tree_set_uint64(field_info *fi, guint64 value)
2007 {
2008         fvalue_set_integer64(&fi->value, value);
2009 }
2010
2011 static void
2012 proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start,  guint length, gboolean little_endian)
2013 {
2014         guint64 value = 0;
2015         guint8* b = ep_tvb_memdup(tvb,start,length);
2016
2017         if(little_endian) {
2018                 b += length;
2019                 switch(length) {
2020                         default: DISSECTOR_ASSERT_NOT_REACHED();
2021                         case 8: value <<= 8; value += *--b;
2022                         case 7: value <<= 8; value += *--b;
2023                         case 6: value <<= 8; value += *--b;
2024                         case 5: value <<= 8; value += *--b;
2025                         case 4: value <<= 8; value += *--b;
2026                         case 3: value <<= 8; value += *--b;
2027                         case 2: value <<= 8; value += *--b;
2028                         case 1: value <<= 8; value += *--b;
2029                                 break;
2030                 }
2031         } else {
2032                 switch(length) {
2033                         default: DISSECTOR_ASSERT_NOT_REACHED();
2034                         case 8: value <<= 8; value += *b++;
2035                         case 7: value <<= 8; value += *b++;
2036                         case 6: value <<= 8; value += *b++;
2037                         case 5: value <<= 8; value += *b++;
2038                         case 4: value <<= 8; value += *b++;
2039                         case 3: value <<= 8; value += *b++;
2040                         case 2: value <<= 8; value += *b++;
2041                         case 1: value <<= 8; value += *b++;
2042                                 break;
2043                 }
2044         }
2045
2046         proto_tree_set_uint64(fi, value);
2047 }
2048
2049 /* Add a FT_STRING or FT_STRINGZ to a proto_tree. Creates own copy of string,
2050  * and frees it when the proto_tree is destroyed. */
2051 proto_item *
2052 proto_tree_add_string(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2053                 gint length, const char* value)
2054 {
2055         proto_item              *pi;
2056         field_info              *new_fi;
2057         header_field_info       *hfinfo;
2058
2059         if (!tree)
2060                 return (NULL);
2061
2062         TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
2063
2064         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2065         DISSECTOR_ASSERT(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ);
2066
2067         pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2068         DISSECTOR_ASSERT(length >= 0);
2069         proto_tree_set_string(new_fi, value);
2070
2071         return pi;
2072 }
2073
2074 proto_item *
2075 proto_tree_add_string_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2076                 gint length, const char* value)
2077 {
2078         proto_item              *pi;
2079
2080         pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
2081         if (pi == NULL)
2082                 return (NULL);
2083
2084         PROTO_ITEM_SET_HIDDEN(pi);
2085
2086         return pi;
2087 }
2088
2089 proto_item *
2090 proto_tree_add_string_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2091                 gint start, gint length, const char* value, const char *format,
2092                 ...)
2093 {
2094         proto_item              *pi;
2095         va_list                 ap;
2096
2097         pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
2098         if (pi == NULL)
2099                 return (NULL);
2100
2101         va_start(ap, format);
2102         proto_tree_set_representation_value(pi, format, ap);
2103         va_end(ap);
2104
2105         return pi;
2106 }
2107
2108 proto_item *
2109 proto_tree_add_string_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2110                 gint length, const char* value, const char *format, ...)
2111 {
2112         proto_item              *pi;
2113         va_list                 ap;
2114
2115         pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
2116         if (pi == NULL)
2117                 return (NULL);
2118
2119         va_start(ap, format);
2120         proto_tree_set_representation(pi, format, ap);
2121         va_end(ap);
2122
2123         return pi;
2124 }
2125
2126 /* Appends string data to a FT_STRING or FT_STRINGZ, allowing progressive
2127  * field info update instead of only updating the representation as does
2128  * proto_item_append_text()
2129  */
2130 /* NOTE: this function will break with the TRY_TO_FAKE_THIS_ITEM()
2131  * speed optimization.
2132  * Currently only WSP use this function so it is not that bad but try to
2133  * avoid using this one if possible.
2134  * IF you must use this function you MUST also disable the
2135  * TRY_TO_FAKE_THIS_ITEM() optimization for your dissector/function
2136  * using proto_item_append_string().
2137  * Do that by faking that the tree is visible by calling
2138  * proto_tree_set_visible(tree, TRUE) (see packet-wsp.c)
2139  * BEFORE you create the item you are later going to use
2140  * proto_item_append_string() on.
2141  */
2142 void
2143 proto_item_append_string(proto_item *pi, const char *str)
2144 {
2145         field_info *fi;
2146         header_field_info *hfinfo;
2147         gchar *old_str, *new_str;
2148
2149         if (!pi)
2150                 return;
2151         if (!*str)
2152                 return;
2153
2154         fi = PITEM_FINFO(pi);
2155         hfinfo = fi->hfinfo;
2156         if (hfinfo->type == FT_PROTOCOL) {
2157                 /* TRY_TO_FAKE_THIS_ITEM() speed optimization: silently skip */
2158                 return;
2159         }
2160         DISSECTOR_ASSERT(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ);
2161         old_str = fvalue_get(&fi->value);
2162         new_str = ep_strdup_printf("%s%s", old_str, str);
2163         fvalue_set(&fi->value, new_str, FALSE);
2164 }
2165
2166 /* Set the FT_STRING value */
2167 static void
2168 proto_tree_set_string(field_info *fi, const char* value)
2169 {
2170         if (value)
2171                 fvalue_set(&fi->value, (gpointer) value, FALSE);
2172         else
2173                 fvalue_set(&fi->value, (gpointer) "[ Null ]", FALSE);
2174 }
2175
2176 static void
2177 proto_tree_set_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
2178 {
2179         gchar   *string;
2180
2181         if (length == -1) {
2182                 length = tvb_ensure_length_remaining(tvb, start);
2183         }
2184
2185         string = tvb_get_ephemeral_string(tvb, start, length);
2186         proto_tree_set_string(fi, string);
2187 }
2188
2189 static void
2190 proto_tree_set_ebcdic_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
2191 {
2192         gchar   *string;
2193
2194         if (length == -1) {
2195                 length = tvb_ensure_length_remaining(tvb, start);
2196         }
2197
2198         string = tvb_get_ephemeral_string(tvb, start, length);
2199         EBCDIC_to_ASCII(string, length);
2200         proto_tree_set_string(fi, string);
2201 }
2202
2203 /* Add a FT_ETHER to a proto_tree */
2204 proto_item *
2205 proto_tree_add_ether(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2206                 const guint8* value)
2207 {
2208         proto_item              *pi;
2209         field_info              *new_fi;
2210         header_field_info       *hfinfo;
2211
2212         if (!tree)
2213                 return (NULL);
2214
2215         TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
2216
2217         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2218         DISSECTOR_ASSERT(hfinfo->type == FT_ETHER);
2219
2220         pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2221         proto_tree_set_ether(new_fi, value);
2222
2223         return pi;
2224 }
2225
2226 proto_item *
2227 proto_tree_add_ether_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2228                 const guint8* value)
2229 {
2230         proto_item              *pi;
2231
2232         pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
2233         if (pi == NULL)
2234                 return (NULL);
2235
2236         PROTO_ITEM_SET_HIDDEN(pi);
2237
2238         return pi;
2239 }
2240
2241 proto_item *
2242 proto_tree_add_ether_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2243                 gint start, gint length, const guint8* value,
2244                 const char *format, ...)
2245 {
2246         proto_item              *pi;
2247         va_list                 ap;
2248
2249         pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
2250         if (pi == NULL)
2251                 return (NULL);
2252
2253         va_start(ap, format);
2254         proto_tree_set_representation_value(pi, format, ap);
2255         va_end(ap);
2256
2257         return pi;
2258 }
2259
2260 proto_item *
2261 proto_tree_add_ether_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2262                 const guint8* value, const char *format, ...)
2263 {
2264         proto_item              *pi;
2265         va_list                 ap;
2266
2267         pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
2268         if (pi == NULL)
2269                 return (NULL);
2270
2271         va_start(ap, format);
2272         proto_tree_set_representation(pi, format, ap);
2273         va_end(ap);
2274
2275         return pi;
2276 }
2277
2278 /* Set the FT_ETHER value */
2279 static void
2280 proto_tree_set_ether(field_info *fi, const guint8* value)
2281 {
2282         fvalue_set(&fi->value, (gpointer) value, FALSE);
2283 }
2284
2285 static void
2286 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start)
2287 {
2288         proto_tree_set_ether(fi, tvb_get_ptr(tvb, start, 6));
2289 }
2290
2291 /* Add a FT_BOOLEAN to a proto_tree */
2292 proto_item *
2293 proto_tree_add_boolean(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2294                 guint32 value)
2295 {
2296         proto_item              *pi;
2297         field_info              *new_fi;
2298         header_field_info       *hfinfo;
2299
2300         if (!tree)
2301                 return (NULL);
2302
2303         TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
2304
2305         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2306         DISSECTOR_ASSERT(hfinfo->type == FT_BOOLEAN);
2307
2308         pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2309         proto_tree_set_boolean(new_fi, value);
2310
2311         return pi;
2312 }
2313
2314 proto_item *
2315 proto_tree_add_boolean_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2316                 guint32 value)
2317 {
2318         proto_item              *pi;
2319
2320         pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
2321         if (pi == NULL)
2322                 return (NULL);
2323
2324         PROTO_ITEM_SET_HIDDEN(pi);
2325
2326         return pi;
2327 }
2328
2329 proto_item *
2330 proto_tree_add_boolean_format_value(proto_tree *tree, int hfindex,
2331                 tvbuff_t *tvb, gint start, gint length, guint32 value,
2332                 const char *format, ...)
2333 {
2334         proto_item              *pi;
2335         va_list                 ap;
2336
2337         pi = proto_tree_add_boolean(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_boolean_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2350                 guint32 value, const char *format, ...)
2351 {
2352         proto_item              *pi;
2353         va_list                 ap;
2354
2355         pi = proto_tree_add_boolean(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_BOOLEAN value */
2367 static void
2368 proto_tree_set_boolean(field_info *fi, guint32 value)
2369 {
2370         proto_tree_set_uint(fi, value);
2371 }
2372
2373 /* Add a FT_FLOAT to a proto_tree */
2374 proto_item *
2375 proto_tree_add_float(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2376                 float value)
2377 {
2378         proto_item              *pi;
2379         field_info              *new_fi;
2380         header_field_info       *hfinfo;
2381
2382         if (!tree)
2383                 return (NULL);
2384
2385         TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
2386
2387         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2388         DISSECTOR_ASSERT(hfinfo->type == FT_FLOAT);
2389
2390         pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2391         proto_tree_set_float(new_fi, value);
2392
2393         return pi;
2394 }
2395
2396 proto_item *
2397 proto_tree_add_float_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2398                 float value)
2399 {
2400         proto_item              *pi;
2401
2402         pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
2403         if (pi == NULL)
2404                 return (NULL);
2405
2406         PROTO_ITEM_SET_HIDDEN(pi);
2407
2408         return pi;
2409 }
2410
2411 proto_item *
2412 proto_tree_add_float_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2413                 gint start, gint length, float value, const char *format, ...)
2414 {
2415         proto_item              *pi;
2416         va_list                 ap;
2417
2418         pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
2419         if (pi == NULL)
2420                 return (NULL);
2421
2422         va_start(ap, format);
2423         proto_tree_set_representation_value(pi, format, ap);
2424         va_end(ap);
2425
2426         return pi;
2427 }
2428
2429 proto_item *
2430 proto_tree_add_float_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2431                 float value, const char *format, ...)
2432 {
2433         proto_item              *pi;
2434         va_list                 ap;
2435
2436         pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
2437         if (pi == NULL)
2438                 return (NULL);
2439
2440         va_start(ap, format);
2441         proto_tree_set_representation(pi, format, ap);
2442         va_end(ap);
2443
2444         return pi;
2445 }
2446
2447 /* Set the FT_FLOAT value */
2448 static void
2449 proto_tree_set_float(field_info *fi, float value)
2450 {
2451         fvalue_set_floating(&fi->value, value);
2452 }
2453
2454 /* Add a FT_DOUBLE to a proto_tree */
2455 proto_item *
2456 proto_tree_add_double(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2457                 double value)
2458 {
2459         proto_item              *pi;
2460         field_info              *new_fi;
2461         header_field_info       *hfinfo;
2462
2463         if (!tree)
2464                 return (NULL);
2465
2466         TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
2467
2468         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2469         DISSECTOR_ASSERT(hfinfo->type == FT_DOUBLE);
2470
2471         pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2472         proto_tree_set_double(new_fi, value);
2473
2474         return pi;
2475 }
2476
2477 proto_item *
2478 proto_tree_add_double_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2479                 double value)
2480 {
2481         proto_item              *pi;
2482
2483         pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
2484         if (pi == NULL)
2485                 return (NULL);
2486
2487         PROTO_ITEM_SET_HIDDEN(pi);
2488
2489         return pi;
2490 }
2491
2492 proto_item *
2493 proto_tree_add_double_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2494                 gint start, gint length, double value, const char *format, ...)
2495 {
2496         proto_item              *pi;
2497         va_list                 ap;
2498
2499         pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
2500         if (pi == NULL)
2501                 return (NULL);
2502
2503         va_start(ap, format);
2504         proto_tree_set_representation_value(pi, format, ap);
2505         va_end(ap);
2506
2507         return pi;
2508 }
2509
2510 proto_item *
2511 proto_tree_add_double_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2512                 double value, const char *format, ...)
2513 {
2514         proto_item              *pi;
2515         va_list                 ap;
2516
2517         pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
2518         if (pi == NULL)
2519                 return (NULL);
2520
2521         va_start(ap, format);
2522         proto_tree_set_representation(pi, format, ap);
2523         va_end(ap);
2524
2525         return pi;
2526 }
2527
2528 /* Set the FT_DOUBLE value */
2529 static void
2530 proto_tree_set_double(field_info *fi, double value)
2531 {
2532         fvalue_set_floating(&fi->value, value);
2533 }
2534
2535 /* Add FT_UINT{8,16,24,32} to a proto_tree */
2536 proto_item *
2537 proto_tree_add_uint(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2538                 guint32 value)
2539 {
2540         proto_item              *pi = NULL;
2541         field_info              *new_fi;
2542         header_field_info       *hfinfo;
2543
2544         if (!tree)
2545                 return (NULL);
2546
2547         TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
2548
2549         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2550         switch(hfinfo->type) {
2551                 case FT_UINT8:
2552                 case FT_UINT16:
2553                 case FT_UINT24:
2554                 case FT_UINT32:
2555                 case FT_FRAMENUM:
2556                         pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length,
2557                                         &new_fi);
2558                         proto_tree_set_uint(new_fi, value);
2559                         break;
2560
2561                 default:
2562                         DISSECTOR_ASSERT_NOT_REACHED();
2563         }
2564
2565         return pi;
2566 }
2567
2568 proto_item *
2569 proto_tree_add_uint_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2570                 guint32 value)
2571 {
2572         proto_item              *pi;
2573
2574         pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
2575         if (pi == NULL)
2576                 return (NULL);
2577
2578         PROTO_ITEM_SET_HIDDEN(pi);
2579
2580         return pi;
2581 }
2582
2583 proto_item *
2584 proto_tree_add_uint_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2585                 gint start, gint length, guint32 value, const char *format, ...)
2586 {
2587         proto_item              *pi;
2588         va_list                 ap;
2589
2590         pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
2591         if (pi == NULL)
2592                 return (NULL);
2593
2594         va_start(ap, format);
2595         proto_tree_set_representation_value(pi, format, ap);
2596         va_end(ap);
2597
2598         return pi;
2599 }
2600
2601 proto_item *
2602 proto_tree_add_uint_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2603                 guint32 value, const char *format, ...)
2604 {
2605         proto_item              *pi;
2606         va_list                 ap;
2607
2608         pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
2609         if (pi == NULL)
2610                 return (NULL);
2611
2612         va_start(ap, format);
2613         proto_tree_set_representation(pi, format, ap);
2614         va_end(ap);
2615
2616         return pi;
2617 }
2618
2619 /* Set the FT_UINT{8,16,24,32} value */
2620 static void
2621 proto_tree_set_uint(field_info *fi, guint32 value)
2622 {
2623         header_field_info       *hfinfo;
2624         guint32                 integer;
2625
2626         hfinfo = fi->hfinfo;
2627         integer = value;
2628
2629         if (hfinfo->bitmask) {
2630                 /* Mask out irrelevant portions */
2631                 integer &= hfinfo->bitmask;
2632
2633                 /* Shift bits */
2634                 if (hfinfo->bitshift > 0) {
2635                         integer >>= hfinfo->bitshift;
2636                 }
2637         }
2638         fvalue_set_uinteger(&fi->value, integer);
2639 }
2640
2641 /* Add FT_UINT64 to a proto_tree */
2642 proto_item *
2643 proto_tree_add_uint64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2644                 guint64 value)
2645 {
2646         proto_item              *pi = NULL;
2647         field_info              *new_fi;
2648         header_field_info       *hfinfo;
2649
2650         if (!tree)
2651                 return (NULL);
2652
2653         TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
2654
2655         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2656         DISSECTOR_ASSERT(hfinfo->type == FT_UINT64);
2657
2658         pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2659         proto_tree_set_uint64(new_fi, value);
2660
2661         return pi;
2662 }
2663
2664 proto_item *
2665 proto_tree_add_uint64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2666                 gint start, gint length, guint64 value, const char *format, ...)
2667 {
2668         proto_item              *pi;
2669         va_list                 ap;
2670
2671         pi = proto_tree_add_uint64(tree, hfindex, tvb, start, length, value);
2672         if (pi == NULL)
2673                 return (NULL);
2674
2675         va_start(ap, format);
2676         proto_tree_set_representation_value(pi, format, ap);
2677         va_end(ap);
2678
2679         return pi;
2680 }
2681
2682 proto_item *
2683 proto_tree_add_uint64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2684                 guint64 value, const char *format, ...)
2685 {
2686         proto_item              *pi;
2687         va_list                 ap;
2688
2689         pi = proto_tree_add_uint64(tree, hfindex, tvb, start, length, value);
2690         if (pi == NULL)
2691                 return (NULL);
2692
2693         va_start(ap, format);
2694         proto_tree_set_representation(pi, format, ap);
2695         va_end(ap);
2696
2697         return pi;
2698 }
2699
2700 /* Add FT_INT{8,16,24,32} to a proto_tree */
2701 proto_item *
2702 proto_tree_add_int(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2703                 gint32 value)
2704 {
2705         proto_item              *pi = NULL;
2706         field_info              *new_fi;
2707         header_field_info       *hfinfo;
2708
2709         if (!tree)
2710                 return (NULL);
2711
2712         TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
2713
2714         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2715         switch(hfinfo->type) {
2716                 case FT_INT8:
2717                 case FT_INT16:
2718                 case FT_INT24:
2719                 case FT_INT32:
2720                         pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length,
2721                                         &new_fi);
2722                         proto_tree_set_int(new_fi, value);
2723                         break;
2724
2725                 default:
2726                         DISSECTOR_ASSERT_NOT_REACHED();
2727         }
2728
2729         return pi;
2730 }
2731
2732 proto_item *
2733 proto_tree_add_int_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2734                 gint32 value)
2735 {
2736         proto_item              *pi;
2737
2738         pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
2739         if (pi == NULL)
2740                 return (NULL);
2741
2742         PROTO_ITEM_SET_HIDDEN(pi);
2743
2744         return pi;
2745 }
2746
2747 proto_item *
2748 proto_tree_add_int_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2749                 gint start, gint length, gint32 value, const char *format, ...)
2750 {
2751         proto_item              *pi = NULL;
2752         va_list                 ap;
2753
2754         pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
2755         if (pi == NULL)
2756                 return (NULL);
2757
2758         va_start(ap, format);
2759         proto_tree_set_representation_value(pi, format, ap);
2760         va_end(ap);
2761
2762         return pi;
2763 }
2764
2765 proto_item *
2766 proto_tree_add_int_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2767                 gint32 value, const char *format, ...)
2768 {
2769         proto_item              *pi = NULL;
2770         va_list                 ap;
2771
2772         pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
2773         if (pi == NULL)
2774                 return (NULL);
2775
2776         va_start(ap, format);
2777         proto_tree_set_representation(pi, format, ap);
2778         va_end(ap);
2779
2780         return pi;
2781 }
2782
2783 /* Set the FT_INT{8,16,24,32} value */
2784 static void
2785 proto_tree_set_int(field_info *fi, gint32 value)
2786 {
2787         header_field_info       *hfinfo;
2788         guint32                 integer;
2789
2790         hfinfo = fi->hfinfo;
2791         integer = (guint32) value;
2792
2793         if (hfinfo->bitmask) {
2794                 /* Mask out irrelevant portions */
2795                 integer &= hfinfo->bitmask;
2796
2797                 /* Shift bits */
2798                 if (hfinfo->bitshift > 0) {
2799                         integer >>= hfinfo->bitshift;
2800                 }
2801         }
2802         fvalue_set_sinteger(&fi->value, integer);
2803 }
2804
2805 /* Add FT_INT64 to a proto_tree */
2806 proto_item *
2807 proto_tree_add_int64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2808                 gint64 value)
2809 {
2810         proto_item              *pi = NULL;
2811         field_info              *new_fi;
2812         header_field_info       *hfinfo;
2813
2814         if (!tree)
2815                 return (NULL);
2816
2817         TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
2818
2819         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2820         DISSECTOR_ASSERT(hfinfo->type == FT_INT64);
2821
2822         pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2823         proto_tree_set_uint64(new_fi, (guint64)value);
2824
2825         return pi;
2826 }
2827
2828 proto_item *
2829 proto_tree_add_int64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2830                 gint start, gint length, gint64 value, const char *format, ...)
2831 {
2832         proto_item              *pi;
2833         va_list                 ap;
2834
2835         pi = proto_tree_add_int64(tree, hfindex, tvb, start, length, value);
2836         if (pi == NULL)
2837                 return (NULL);
2838
2839         va_start(ap, format);
2840         proto_tree_set_representation_value(pi, format, ap);
2841         va_end(ap);
2842
2843         return pi;
2844 }
2845
2846 proto_item *
2847 proto_tree_add_int64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2848                 gint64 value, const char *format, ...)
2849 {
2850         proto_item              *pi;
2851         va_list                 ap;
2852
2853         pi = proto_tree_add_int64(tree, hfindex, tvb, start, length, value);
2854         if (pi == NULL)
2855                 return (NULL);
2856
2857         va_start(ap, format);
2858         proto_tree_set_representation(pi, format, ap);
2859         va_end(ap);
2860
2861         return pi;
2862 }
2863
2864 /* Throw an exception if we exceed this many tree items. */
2865 /* XXX - This should probably be a preference */
2866 #define MAX_TREE_ITEMS (1 * 1000 * 1000)
2867 /* Add a field_info struct to the proto_tree, encapsulating it in a proto_node */
2868 static proto_item *
2869 proto_tree_add_node(proto_tree *tree, field_info *fi)
2870 {
2871         proto_node *pnode, *tnode, *sibling;
2872         field_info *tfi;
2873
2874         /*
2875          * Make sure "tree" is ready to have subtrees under it, by
2876          * checking whether it's been given an ett_ value.
2877          *
2878          * "tnode->finfo" may be null; that's the case for the root
2879          * node of the protocol tree.  That node is not displayed,
2880          * so it doesn't need an ett_ value to remember whether it
2881          * was expanded.
2882          */
2883         tnode = tree;
2884         tfi = tnode->finfo;
2885         if (tfi != NULL && (tfi->tree_type < 0 || tfi->tree_type >= num_tree_types)) {
2886                 REPORT_DISSECTOR_BUG(ep_strdup_printf("\"%s\" - \"%s\" tfi->tree_type: %u invalid (%s:%u)",
2887                         fi->hfinfo->name, fi->hfinfo->abbrev, tfi->tree_type, __FILE__, __LINE__));
2888                 /* XXX - is it safe to continue here? */
2889         }
2890
2891         DISSECTOR_ASSERT(tfi == NULL ||
2892             (tfi->tree_type >= 0 && tfi->tree_type < num_tree_types));
2893
2894         PTREE_DATA(tree)->count++;
2895         if (PTREE_DATA(tree)->count > MAX_TREE_ITEMS) {
2896                 /* Let the exception handler add items to the tree */
2897                 PTREE_DATA(tree)->count = 0;
2898                 THROW_MESSAGE(DissectorError,
2899                         ep_strdup_printf("More than %d items in the tree -- possible infinite loop", MAX_TREE_ITEMS));
2900         }
2901
2902         PROTO_NODE_NEW(pnode);
2903         pnode->parent = tnode;
2904         pnode->finfo = fi;
2905         pnode->tree_data = PTREE_DATA(tree);
2906
2907         if (tnode->last_child != NULL) {
2908                 sibling = tnode->last_child;
2909                 DISSECTOR_ASSERT(sibling->next == NULL);
2910                 sibling->next = pnode;
2911         } else
2912                 tnode->first_child = pnode;
2913         tnode->last_child = pnode;
2914
2915         return (proto_item*)pnode;
2916 }
2917
2918
2919 /* Generic way to allocate field_info and add to proto_tree.
2920  * Sets *pfi to address of newly-allocated field_info struct, if pfi is
2921  * non-NULL. */
2922 static proto_item *
2923 proto_tree_add_pi(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2924     gint *length, field_info **pfi)
2925 {
2926         proto_item      *pi;
2927         field_info      *fi;
2928         GHashTable      *hash;
2929         GPtrArray       *ptrs;
2930
2931         if (!tree)
2932                 return(NULL);
2933
2934         fi = alloc_field_info(tree, hfindex, tvb, start, length);
2935         pi = proto_tree_add_node(tree, fi);
2936
2937         /* If the proto_tree wants to keep a record of this finfo
2938          * for quick lookup, then record it. */
2939         if (fi->hfinfo->ref_count) {
2940                 /*HERE*/
2941                 hash = PTREE_DATA(tree)->interesting_hfids;
2942                 ptrs = g_hash_table_lookup(hash, GINT_TO_POINTER(hfindex));
2943                 if (ptrs) {
2944                         g_ptr_array_add(ptrs, fi);
2945                 }
2946         }
2947
2948         /* Does the caller want to know the fi pointer? */
2949         if (pfi) {
2950                 *pfi = fi;
2951         }
2952
2953         return pi;
2954 }
2955
2956
2957 static header_field_info *
2958 get_hfi_and_length(int hfindex, tvbuff_t *tvb, gint start, gint *length,
2959     gint *item_length)
2960 {
2961         header_field_info       *hfinfo;
2962         gint                    length_remaining;
2963
2964         /*
2965          * We only allow a null tvbuff if the item has a zero length,
2966          * i.e. if there's no data backing it.
2967          */
2968         DISSECTOR_ASSERT(tvb != NULL || *length == 0);
2969
2970         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2971
2972         /*
2973          * XXX - in some protocols, there are 32-bit unsigned length
2974          * fields, so lengths in protocol tree and tvbuff routines
2975          * should really be unsigned.  We should have, for those
2976          * field types for which "to the end of the tvbuff" makes sense,
2977          * additional routines that take no length argument and
2978          * add fields that run to the end of the tvbuff.
2979          */
2980         if (*length == -1) {
2981                 /*
2982                  * For FT_NONE, FT_PROTOCOL, FT_BYTES, and FT_STRING fields,
2983                  * a length of -1 means "set the length to what remains in
2984                  * the tvbuff".
2985                  *
2986                  * The assumption is either that
2987                  *
2988                  *      1) the length of the item can only be determined
2989                  *         by dissection (typically true of items with
2990                  *         subitems, which are probably FT_NONE or
2991                  *         FT_PROTOCOL)
2992                  *
2993                  * or
2994                  *
2995                  *      2) if the tvbuff is "short" (either due to a short
2996                  *         snapshot length or due to lack of reassembly of
2997                  *         fragments/segments/whatever), we want to display
2998                  *         what's available in the field (probably FT_BYTES
2999                  *         or FT_STRING) and then throw an exception later
3000                  *
3001                  * or
3002                  *
3003                  *      3) the field is defined to be "what's left in the
3004                  *         packet"
3005                  *
3006                  * so we set the length to what remains in the tvbuff so
3007                  * that, if we throw an exception while dissecting, it
3008                  * has what is probably the right value.
3009                  *
3010                  * For FT_STRINGZ, it means "the string is null-terminated,
3011                  * not null-padded; set the length to the actual length
3012                  * of the string", and if the tvbuff if short, we just
3013                  * throw an exception.
3014                  *
3015                  * It's not valid for any other type of field.
3016                  */
3017                 switch (hfinfo->type) {
3018
3019                 case FT_PROTOCOL:
3020                         /*
3021                          * We allow this to be zero-length - for
3022                          * example, an ONC RPC NULL procedure has
3023                          * neither arguments nor reply, so the
3024                          * payload for that protocol is empty.
3025                          *
3026                          * However, if the length is negative, the
3027                          * start offset is *past* the byte past the
3028                          * end of the tvbuff, so we throw an
3029                          * exception.
3030                          */
3031                         *length = tvb_length_remaining(tvb, start);
3032                         if (*length < 0) {
3033                                 /*
3034                                  * Use "tvb_ensure_bytes_exist()"
3035                                  * to force the appropriate exception
3036                                  * to be thrown.
3037                                  */
3038                                 tvb_ensure_bytes_exist(tvb, start, 0);
3039                         }
3040                         DISSECTOR_ASSERT(*length >= 0);
3041                         break;
3042
3043                 case FT_NONE:
3044                 case FT_BYTES:
3045                 case FT_STRING:
3046                         *length = tvb_ensure_length_remaining(tvb, start);
3047                         DISSECTOR_ASSERT(*length >= 0);
3048                         break;
3049
3050                 case FT_STRINGZ:
3051                         /*
3052                          * Leave the length as -1, so our caller knows
3053                          * it was -1.
3054                          */
3055                         break;
3056
3057                 default:
3058                         DISSECTOR_ASSERT_NOT_REACHED();
3059                 }
3060                 *item_length = *length;
3061         } else {
3062                 *item_length = *length;
3063                 if (hfinfo->type == FT_PROTOCOL || hfinfo->type == FT_NONE) {
3064                         /*
3065                          * These types are for interior nodes of the
3066                          * tree, and don't have data associated with
3067                          * them; if the length is negative (XXX - see
3068                          * above) or goes past the end of the tvbuff,
3069                          * cut it short at the end of the tvbuff.
3070                          * That way, if this field is selected in
3071                          * Wireshark, we don't highlight stuff past
3072                          * the end of the data.
3073                          */
3074                         /* XXX - what to do, if we don't have a tvb? */
3075                         if (tvb) {
3076                                 length_remaining = tvb_length_remaining(tvb, start);
3077                                 if (*item_length < 0 ||
3078                                     (*item_length > 0 &&
3079                                       (length_remaining < *item_length)))
3080                                         *item_length = length_remaining;
3081                         }
3082                 }
3083                 if (*item_length < 0) {
3084                         THROW(ReportedBoundsError);
3085                 }
3086         }
3087
3088         return hfinfo;
3089 }
3090
3091 static field_info *
3092 new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
3093     gint start, gint item_length)
3094 {
3095         field_info              *fi;
3096
3097         FIELD_INFO_NEW(fi);
3098
3099         fi->hfinfo = hfinfo;
3100         fi->start = start;
3101         fi->start+=(tvb)?TVB_RAW_OFFSET(tvb):0;
3102         fi->length = item_length;
3103         fi->tree_type = -1;
3104         fi->flags = 0;
3105         if (!PTREE_DATA(tree)->visible)
3106                 FI_SET_FLAG(fi, FI_HIDDEN);
3107         fvalue_init(&fi->value, fi->hfinfo->type);
3108         fi->rep = NULL;
3109
3110         /* add the data source tvbuff */
3111         fi->ds_tvb=tvb?TVB_GET_DS_TVB(tvb):NULL;
3112
3113         fi->appendix_start = 0;
3114         fi->appendix_length = 0;
3115
3116         return fi;
3117 }
3118
3119 static field_info *
3120 alloc_field_info(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3121     gint *length)
3122 {
3123         header_field_info       *hfinfo;
3124         gint                    item_length;
3125
3126         hfinfo = get_hfi_and_length(hfindex, tvb, start, length, &item_length);
3127         return new_field_info(tree, hfinfo, tvb, start, item_length);
3128 }
3129
3130 /* If the protocol tree is to be visible, set the representation of a
3131    proto_tree entry with the name of the field for the item and with
3132    the value formatted with the supplied printf-style format and
3133    argument list. */
3134 static void
3135 proto_tree_set_representation_value(proto_item *pi, const char *format, va_list ap)
3136 {
3137         int     ret;    /*tmp return value */
3138         int     replen;
3139         field_info *fi = PITEM_FINFO(pi);
3140
3141         if (!PROTO_ITEM_IS_HIDDEN(pi)) {
3142                 ITEM_LABEL_NEW(fi->rep);
3143                 replen = 0;
3144                 ret = g_snprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
3145                     "%s: ", fi->hfinfo->name);
3146                 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH)) {
3147                         /* That's all we can put in the representation. */
3148                         fi->rep->representation[ITEM_LABEL_LENGTH - 1] = '\0';
3149                         return;
3150                 }
3151                 replen = ret;
3152                 ret = g_vsnprintf(fi->rep->representation + replen,
3153                     ITEM_LABEL_LENGTH - replen, format, ap);
3154                 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH - replen))
3155                         fi->rep->representation[ITEM_LABEL_LENGTH - 1] = '\0';
3156         }
3157 }
3158
3159 /* If the protocol tree is to be visible, set the representation of a
3160    proto_tree entry with the representation formatted with the supplied
3161    printf-style format and argument list. */
3162 static void
3163 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap)
3164 {
3165         int                                     ret;    /*tmp return value */
3166         field_info *fi = PITEM_FINFO(pi);
3167
3168         if (!PROTO_ITEM_IS_HIDDEN(pi)) {
3169                 ITEM_LABEL_NEW(fi->rep);
3170                 ret = g_vsnprintf(fi->rep->representation, ITEM_LABEL_LENGTH, format, ap);
3171                 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3172                         fi->rep->representation[ITEM_LABEL_LENGTH - 1] = '\0';
3173         }
3174 }
3175
3176 /* Set text of proto_item after having already been created. */
3177 void
3178 proto_item_set_text(proto_item *pi, const char *format, ...)
3179 {
3180         field_info *fi = NULL;
3181         va_list ap;
3182
3183         if (pi==NULL) {
3184                 return;
3185         }
3186
3187         fi = PITEM_FINFO(pi);
3188
3189         if(fi->rep){
3190                 ITEM_LABEL_FREE(fi->rep);
3191         }
3192
3193         va_start(ap, format);
3194         proto_tree_set_representation(pi, format, ap);
3195         va_end(ap);
3196 }
3197
3198 /* Append to text of proto_item after having already been created. */
3199 void
3200 proto_item_append_text(proto_item *pi, const char *format, ...)
3201 {
3202         field_info *fi = NULL;
3203         size_t curlen;
3204         va_list ap;
3205         int                                     ret;    /*tmp return value */
3206
3207         if (pi==NULL) {
3208                 return;
3209         }
3210
3211         fi = PITEM_FINFO(pi);
3212         if (fi==NULL) {
3213                 return;
3214         }
3215
3216         if (!PROTO_ITEM_IS_HIDDEN(pi)) {
3217                 va_start(ap, format);
3218
3219                 /*
3220                  * If we don't already have a representation,
3221                  * generate the default representation.
3222                  */
3223                 if (fi->rep == NULL) {
3224                         ITEM_LABEL_NEW(fi->rep);
3225                         proto_item_fill_label(fi, fi->rep->representation);
3226                 }
3227
3228                 curlen = strlen(fi->rep->representation);
3229                 if (ITEM_LABEL_LENGTH > curlen) {
3230                         ret = g_vsnprintf(fi->rep->representation + curlen,
3231                             ITEM_LABEL_LENGTH - curlen, format, ap);
3232                         if ((ret == -1) || (ret >= (int)(ITEM_LABEL_LENGTH - curlen)))
3233                                 fi->rep->representation[ITEM_LABEL_LENGTH - 1] = '\0';
3234                 }
3235                 va_end(ap);
3236         }
3237 }
3238
3239 void
3240 proto_item_set_len(proto_item *pi, gint length)
3241 {
3242         field_info *fi;
3243
3244         if (pi == NULL)
3245                 return;
3246         fi = PITEM_FINFO(pi);
3247         DISSECTOR_ASSERT(length >= 0);
3248         fi->length = length;
3249
3250         if (fi->value.ftype->ftype == FT_BYTES)
3251                 fi->value.value.bytes->len = length;
3252 }
3253
3254 /*
3255  * Sets the length of the item based on its start and on the specified
3256  * offset, which is the offset past the end of the item; as the start
3257  * in the item is relative to the beginning of the data source tvbuff,
3258  * we need to pass in a tvbuff - the end offset is relative to the beginning
3259  * of that tvbuff.
3260  */
3261 void
3262 proto_item_set_end(proto_item *pi, tvbuff_t *tvb, gint end)
3263 {
3264         field_info *fi;
3265
3266         if (pi == NULL)
3267                 return;
3268         fi = PITEM_FINFO(pi);
3269         end += TVB_RAW_OFFSET(tvb);
3270         DISSECTOR_ASSERT(end >= fi->start);
3271         fi->length = end - fi->start;
3272 }
3273
3274 int
3275 proto_item_get_len(proto_item *pi)
3276 {
3277         field_info *fi = PITEM_FINFO(pi);
3278         return fi->length;
3279 }
3280
3281
3282 /** clear flags according to the mask and set new flag values */
3283 #define FI_REPLACE_FLAGS(fi, mask, flags_in) { \
3284         (fi->flags = (fi)->flags & ~(mask)); \
3285         (fi->flags = (fi)->flags | (flags_in)); \
3286 }
3287
3288 gboolean
3289 proto_item_set_expert_flags(proto_item *pi, int group, guint severity)
3290 {
3291         if(pi == NULL || pi->finfo == NULL)
3292                 return FALSE;
3293
3294         /* only change things if severity is worse or at least equal than before */
3295         if(severity >= FI_GET_FLAG(pi->finfo, PI_SEVERITY_MASK)) {
3296                 FI_REPLACE_FLAGS(pi->finfo, PI_GROUP_MASK, group);
3297                 FI_REPLACE_FLAGS(pi->finfo, PI_SEVERITY_MASK, severity);
3298
3299                 return TRUE;
3300         }
3301
3302         return FALSE;
3303 }
3304
3305
3306
3307 proto_tree*
3308 proto_tree_create_root(void)
3309 {
3310         proto_node  *pnode;
3311
3312         /* Initialize the proto_node */
3313         PROTO_NODE_NEW(pnode);
3314         pnode->parent = NULL;
3315         pnode->finfo = NULL;
3316         pnode->tree_data = g_new(tree_data_t, 1);
3317
3318         /* Initialize the tree_data_t */
3319         pnode->tree_data->interesting_hfids =
3320             g_hash_table_new(g_direct_hash, g_direct_equal);
3321
3322         /* Set the default to FALSE so it's easier to
3323          * find errors; if we expect to see the protocol tree
3324          * but for some reason the default 'visible' is not
3325          * changed, then we'll find out very quickly. */
3326         pnode->tree_data->visible = FALSE;
3327
3328         /* Keep track of the number of children */
3329         pnode->tree_data->count = 0;
3330
3331         return (proto_tree*) pnode;
3332 }
3333
3334
3335 /* "prime" a proto_tree with a single hfid that a dfilter
3336  * is interested in. */
3337 void
3338 proto_tree_prime_hfid(proto_tree *tree, gint hfid)
3339 {
3340         header_field_info *hfinfo;
3341
3342         g_hash_table_insert(PTREE_DATA(tree)->interesting_hfids,
3343                 GINT_TO_POINTER(hfid), g_ptr_array_new());
3344
3345         PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
3346         /* this field is referenced by a filter so increase the refcount.
3347            also increase the refcount for the parent, i.e the protocol.
3348         */
3349         hfinfo->ref_count++;
3350         /* only increase the refcount if there is a parent.
3351            if this is a protocol and not a field then parent will be -1
3352            and there is no parent to add any refcounting for.
3353         */
3354         if (hfinfo->parent != -1) {
3355                 header_field_info *parent_hfinfo;
3356                 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
3357                 parent_hfinfo->ref_count++;
3358         }
3359 }
3360
3361 proto_tree*
3362 proto_item_add_subtree(proto_item *pi,  gint idx) {
3363         field_info *fi;
3364
3365         if (!pi)
3366                 return(NULL);
3367
3368         fi = PITEM_FINFO(pi);
3369         DISSECTOR_ASSERT(idx >= 0 && idx < num_tree_types);
3370         fi->tree_type = idx;
3371
3372         return (proto_tree*) pi;
3373 }
3374
3375 proto_tree*
3376 proto_item_get_subtree(proto_item *pi) {
3377         field_info *fi;
3378
3379         if (!pi)
3380                 return(NULL);
3381         fi = PITEM_FINFO(pi);
3382         if ( (!fi) || (fi->tree_type == -1) )
3383                 return(NULL);
3384         return (proto_tree*) pi;
3385 }
3386
3387 proto_item*
3388 proto_item_get_parent(proto_item *ti) {
3389         if (!ti)
3390                 return (NULL);
3391         return ti->parent;
3392 }
3393
3394 proto_item*
3395 proto_item_get_parent_nth(proto_item *ti, int gen) {
3396         if (!ti)
3397                 return (NULL);
3398         while (gen--) {
3399                 ti = ti->parent;
3400                 if (!ti)
3401                         return (NULL);
3402         }
3403         return ti;
3404 }
3405
3406
3407 proto_item*
3408 proto_tree_get_parent(proto_tree *tree) {
3409         if (!tree)
3410                 return (NULL);
3411         return (proto_item*) tree;
3412 }
3413
3414 proto_tree*
3415 proto_tree_get_root(proto_tree *tree) {
3416         if (!tree)
3417                 return (NULL);
3418         while (tree->parent) {
3419                 tree = tree->parent;
3420         }
3421         return tree;
3422 }
3423
3424 void
3425 proto_tree_move_item(proto_tree *tree, proto_item *fixed_item, proto_item *item_to_move)
3426 {
3427     proto_item *curr_item;
3428
3429
3430     /*** cut item_to_move out ***/
3431
3432     /* is item_to_move the first? */
3433     if(tree->first_child == item_to_move) {
3434         /* simply change first child to next */
3435         tree->first_child = item_to_move->next;
3436     } else {
3437         /* find previous and change it's next */
3438         for(curr_item = tree->first_child; curr_item != NULL; curr_item = curr_item->next) {
3439             if(curr_item->next == item_to_move) {
3440                 break;
3441             }
3442         }
3443
3444         DISSECTOR_ASSERT(curr_item);
3445
3446         curr_item->next = item_to_move->next;
3447
3448         /* fix last_child if required */
3449         if(tree->last_child == item_to_move) {
3450             tree->last_child = curr_item;
3451         }
3452     }
3453
3454     /*** insert to_move after fixed ***/
3455     item_to_move->next = fixed_item->next;
3456     fixed_item->next = item_to_move;
3457     if(tree->last_child == fixed_item) {
3458         tree->last_child = item_to_move;
3459     }
3460 }
3461
3462 void
3463 proto_tree_set_appendix(proto_tree *tree, tvbuff_t *tvb, gint start, gint length)
3464 {
3465         field_info *fi;
3466
3467         if (tree == NULL)
3468                 return;
3469
3470         fi = tree->finfo;
3471         start += TVB_RAW_OFFSET(tvb);
3472         DISSECTOR_ASSERT(start >= 0);
3473         DISSECTOR_ASSERT(length >= 0);
3474
3475         fi->appendix_start = start;
3476         fi->appendix_length = length;
3477 }
3478
3479 int
3480 proto_register_protocol(const char *name, const char *short_name, const char *filter_name)
3481 {
3482     protocol_t *protocol;
3483     header_field_info *hfinfo;
3484     int proto_id;
3485     char *existing_name;
3486     gint *key;
3487     guint i;
3488     guchar c;
3489     gboolean found_invalid;
3490
3491     /*
3492      * Make sure there's not already a protocol with any of those
3493      * names.  Crash if there is, as that's an error in the code
3494      * or an inappropriate plugin.
3495      * This situation has to be fixed to not register more than one
3496      * protocol with the same name.
3497      *
3498      * This is done by reducing the number of strcmp (and alike) calls as much as possible,
3499      * as this significally slows down startup time.
3500      *
3501      * Drawback: As a hash value is used to reduce insert time,
3502      * this might lead to a hash collision.
3503      * However, as we have around 500+ protocols and we're using a 32 bit int this is very,
3504      * very unlikely.
3505      */
3506
3507     key = g_malloc (sizeof(gint));
3508     *key = wrs_str_hash(name);
3509     existing_name = g_hash_table_lookup(proto_names, key);
3510     if (existing_name != NULL) {
3511         /* g_error will terminate the program */
3512         g_error("Duplicate protocol name \"%s\"!"
3513             " This might be caused by an inappropriate plugin or a development error.", name);
3514     }
3515     g_hash_table_insert(proto_names, key, (gpointer)name);
3516
3517     existing_name = g_hash_table_lookup(proto_short_names, (gpointer)short_name);
3518     if (existing_name != NULL) {
3519         g_error("Duplicate protocol short_name \"%s\"!"
3520             " This might be caused by an inappropriate plugin or a development error.", short_name);
3521     }
3522     g_hash_table_insert(proto_short_names, (gpointer)short_name, (gpointer)short_name);
3523
3524     found_invalid = FALSE;
3525     for (i = 0; i < strlen(filter_name); i++) {
3526         c = filter_name[i];
3527         if (!(islower(c) || isdigit(c) || c == '-' || c == '_' || c == '.')) {
3528             found_invalid = TRUE;
3529         }
3530     }
3531     if (found_invalid) {
3532         g_error("Protocol filter name \"%s\" has one or more invalid characters."
3533             " Allowed are lower characters, digits, '-', '_' and '.'."
3534             " This might be caused by an inappropriate plugin or a development error.", filter_name);
3535     }
3536     existing_name = g_hash_table_lookup(proto_filter_names, (gpointer)filter_name);
3537     if (existing_name != NULL) {
3538         g_error("Duplicate protocol filter_name \"%s\"!"
3539             " This might be caused by an inappropriate plugin or a development error.", filter_name);
3540     }
3541     g_hash_table_insert(proto_filter_names, (gpointer)filter_name, (gpointer)filter_name);
3542
3543     /* Add this protocol to the list of known protocols; the list
3544        is sorted by protocol short name. */
3545     protocol = g_malloc(sizeof (protocol_t));
3546     protocol->name = name;
3547     protocol->short_name = short_name;
3548     protocol->filter_name = filter_name;
3549     protocol->fields = NULL;
3550     protocol->is_enabled = TRUE; /* protocol is enabled by default */
3551     protocol->can_toggle = TRUE;
3552     /* list will be sorted later by name, when all protocols completed registering */
3553     protocols = g_list_prepend(protocols, protocol);
3554
3555     /* Here we do allocate a new header_field_info struct */
3556     hfinfo = g_mem_chunk_alloc(gmc_hfinfo);
3557     hfinfo->name = name;
3558     hfinfo->abbrev = filter_name;
3559     hfinfo->type = FT_PROTOCOL;
3560     hfinfo->strings = protocol;
3561     hfinfo->bitmask = 0;
3562     hfinfo->bitshift = 0;
3563     hfinfo->ref_count = 0;
3564     hfinfo->blurb = NULL;
3565     hfinfo->parent = -1; /* this field differentiates protos and fields */
3566
3567     proto_id = proto_register_field_init(hfinfo, hfinfo->parent);
3568     protocol->proto_id = proto_id;
3569     return proto_id;
3570 }
3571
3572 /*
3573  * Routines to use to iterate over the protocols.
3574  * The argument passed to the iterator routines is an opaque cookie to
3575  * their callers; it's the GList pointer for the current element in
3576  * the list.
3577  * The ID of the protocol is returned, or -1 if there is no protocol.
3578  */
3579 int
3580 proto_get_first_protocol(void **cookie)
3581 {
3582         protocol_t *protocol;
3583
3584         if (protocols == NULL)
3585                 return -1;
3586         *cookie = protocols;
3587         protocol = protocols->data;
3588         return protocol->proto_id;
3589 }
3590
3591 int
3592 proto_get_next_protocol(void **cookie)
3593 {
3594         GList *list_item = *cookie;
3595         protocol_t *protocol;
3596
3597         list_item = g_list_next(list_item);
3598         if (list_item == NULL)
3599                 return -1;
3600         *cookie = list_item;
3601         protocol = list_item->data;
3602         return protocol->proto_id;
3603 }
3604
3605 header_field_info *
3606 proto_get_first_protocol_field(int proto_id, void **cookie)
3607 {
3608         protocol_t *protocol = find_protocol_by_id(proto_id);
3609         hf_register_info *ptr;
3610
3611         if ((protocol == NULL) || (protocol->fields == NULL))
3612                 return NULL;
3613
3614         *cookie = protocol->fields;
3615         ptr = protocol->fields->data;
3616         return &ptr->hfinfo;
3617 }
3618
3619 header_field_info *
3620 proto_get_next_protocol_field(void **cookie)
3621 {
3622         GList *list_item = *cookie;
3623         hf_register_info *ptr;
3624
3625         list_item = g_list_next(list_item);
3626         if (list_item == NULL)
3627                 return NULL;
3628
3629         *cookie = list_item;
3630         ptr = list_item->data;
3631         return &ptr->hfinfo;
3632 }
3633
3634 protocol_t *
3635 find_protocol_by_id(int proto_id)
3636 {
3637         header_field_info *hfinfo;
3638
3639         if(proto_id<0)
3640                 return NULL;
3641
3642         PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
3643         DISSECTOR_ASSERT(hfinfo->type==FT_PROTOCOL);
3644         return (protocol_t *)hfinfo->strings;
3645 }
3646
3647 static gint compare_filter_name(gconstpointer proto_arg,
3648                                 gconstpointer filter_name)
3649 {
3650         const protocol_t *protocol = proto_arg;
3651         const gchar* f_name = filter_name;
3652
3653         return (strcmp(protocol->filter_name, f_name));
3654 }
3655
3656 int
3657 proto_get_id(protocol_t *protocol)
3658 {
3659         return protocol->proto_id;
3660 }
3661
3662 int proto_get_id_by_filter_name(const gchar* filter_name)
3663 {
3664         GList *list_entry;
3665         protocol_t *protocol;
3666
3667 #if GLIB_MAJOR_VERSION < 2
3668         list_entry = g_list_find_custom(protocols, discard_const(filter_name),
3669             compare_filter_name);
3670 #else
3671         list_entry = g_list_find_custom(protocols, filter_name,
3672             compare_filter_name);
3673 #endif
3674         if (list_entry == NULL)
3675                 return -1;
3676         protocol = list_entry->data;
3677         return protocol->proto_id;
3678 }
3679
3680 const char *
3681 proto_get_protocol_name(int proto_id)
3682 {
3683         protocol_t *protocol;
3684
3685         protocol = find_protocol_by_id(proto_id);
3686         return protocol->name;
3687 }
3688
3689 const char *
3690 proto_get_protocol_short_name(protocol_t *protocol)
3691 {
3692         if (protocol == NULL)
3693                 return "(none)";
3694         return protocol->short_name;
3695 }
3696
3697 const char *
3698 proto_get_protocol_filter_name(int proto_id)
3699 {
3700         protocol_t *protocol;
3701
3702         protocol = find_protocol_by_id(proto_id);
3703         if (protocol == NULL)
3704                 return "(none)";
3705         return protocol->filter_name;
3706 }
3707
3708 gboolean
3709 proto_is_protocol_enabled(protocol_t *protocol)
3710 {
3711         return protocol->is_enabled;
3712 }
3713
3714 gboolean
3715 proto_can_toggle_protocol(int proto_id)
3716 {
3717         protocol_t *protocol;
3718
3719         protocol = find_protocol_by_id(proto_id);
3720         return protocol->can_toggle;
3721 }
3722
3723 void
3724 proto_set_decoding(int proto_id, gboolean enabled)
3725 {
3726         protocol_t *protocol;
3727
3728         protocol = find_protocol_by_id(proto_id);
3729         DISSECTOR_ASSERT(protocol->can_toggle);
3730         protocol->is_enabled = enabled;
3731 }
3732
3733 void
3734 proto_set_cant_toggle(int proto_id)
3735 {
3736         protocol_t *protocol;
3737
3738         protocol = find_protocol_by_id(proto_id);
3739         protocol->can_toggle = FALSE;
3740 }
3741
3742 /* for use with static arrays only, since we don't allocate our own copies
3743 of the header_field_info struct contained within the hf_register_info struct */
3744 void
3745 proto_register_field_array(int parent, hf_register_info *hf, int num_records)
3746 {
3747         int                     field_id, i;
3748         hf_register_info        *ptr = hf;
3749         protocol_t              *proto;
3750
3751         proto = find_protocol_by_id(parent);
3752         for (i = 0; i < num_records; i++, ptr++) {
3753                 /*
3754                  * Make sure we haven't registered this yet.
3755                  * Most fields have variables associated with them
3756                  * that are initialized to -1; some have array elements,
3757                  * or possibly uninitialized variables, so we also allow
3758                  * 0 (which is unlikely to be the field ID we get back
3759                  * from "proto_register_field_init()").
3760                  */
3761                 if (*ptr->p_id != -1 && *ptr->p_id != 0) {
3762                         fprintf(stderr,
3763                             "Duplicate field detected in call to proto_register_field_array: %s is already registered\n",
3764                             ptr->hfinfo.abbrev);
3765                         return;
3766                 }
3767
3768                 if (proto != NULL) {
3769                         if (proto->fields == NULL) {
3770                                 proto->fields = g_list_append(NULL, ptr);
3771                                 proto->last_field = proto->fields;
3772                         } else {
3773                                 proto->last_field =
3774                                     g_list_append(proto->last_field, ptr)->next;
3775                         }
3776                 }
3777                 field_id = proto_register_field_init(&ptr->hfinfo, parent);
3778                 *ptr->p_id = field_id;
3779         }
3780 }
3781
3782 /* chars allowed in field abbrev */
3783 static
3784 const guchar fld_abbrev_chars[256] = {
3785  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00-0x0F */
3786  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10-0x1F */
3787  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, /* 0x20-0x2F '-', '.'     */
3788  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 0x30-0x3F '0'-'9'      */
3789  0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x40-0x4F 'A'-'O'      */
3790  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 0x50-0x5F 'P'-'Z', '_' */
3791  0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x60-0x6F 'a'-'o'      */
3792  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 0x70-0x7F 'p'-'z'      */
3793  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80-0x8F */
3794  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90-0x9F */
3795  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xA0-0xAF */
3796  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xB0-0xBF */
3797  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xC0-0xCF */
3798  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xD0-0xDF */
3799  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xE0-0xEF */
3800  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xF0-0xFF */
3801 };
3802
3803 /* temporary function containing assert part for easier profiling */
3804 static void tmp_fld_check_assert(header_field_info *hfinfo) {
3805         /* The field must have a name (with length > 0) */
3806         DISSECTOR_ASSERT(hfinfo->name && hfinfo->name[0]);
3807
3808         /* fields with an empty string for an abbreviation aren't filterable */
3809         DISSECTOR_ASSERT(hfinfo->abbrev);
3810
3811         /* These types of fields are allowed to have value_strings, true_false_strings or a protocol_t struct*/
3812         DISSECTOR_ASSERT((hfinfo->strings == NULL) || (
3813                         (hfinfo->type == FT_UINT8) ||
3814                         (hfinfo->type == FT_UINT16) ||
3815                         (hfinfo->type == FT_UINT24) ||
3816                         (hfinfo->type == FT_UINT32) ||
3817                         (hfinfo->type == FT_INT8) ||
3818                         (hfinfo->type == FT_INT16) ||
3819                         (hfinfo->type == FT_INT24) ||
3820                         (hfinfo->type == FT_INT32) ||
3821                         (hfinfo->type == FT_BOOLEAN) ||
3822                         (hfinfo->type == FT_PROTOCOL) ||
3823                         (hfinfo->type == FT_FRAMENUM) ));
3824
3825         switch (hfinfo->type) {
3826
3827         case FT_UINT8:
3828         case FT_UINT16:
3829         case FT_UINT24:
3830         case FT_UINT32:
3831         case FT_INT8:
3832         case FT_INT16:
3833         case FT_INT24:
3834         case FT_INT32:
3835                 /* Require integral types (other than frame number, which is
3836                    always displayed in decimal) to have a number base */
3837                 DISSECTOR_ASSERT(hfinfo->display != BASE_NONE);
3838                 break;
3839
3840         case FT_FRAMENUM:
3841                 /* Don't allow bitfields or value strings for frame numbers */
3842                 DISSECTOR_ASSERT(hfinfo->bitmask == 0);
3843                 DISSECTOR_ASSERT(hfinfo->strings == NULL);
3844                 break;
3845
3846         default:
3847                 break;
3848         }
3849 }
3850
3851 static int
3852 proto_register_field_init(header_field_info *hfinfo, int parent)
3853 {
3854
3855         tmp_fld_check_assert(hfinfo);
3856
3857         /* if this is a bitfield, compute bitshift */
3858         if (hfinfo->bitmask) {
3859                 hfinfo->bitshift = wrs_count_bitshift(hfinfo->bitmask);
3860         }
3861
3862         hfinfo->parent = parent;
3863         hfinfo->same_name_next = NULL;
3864         hfinfo->same_name_prev = NULL;
3865
3866         /* if we always add and never delete, then id == len - 1 is correct */
3867         if(gpa_hfinfo.len>=gpa_hfinfo.allocated_len){
3868                 if(!gpa_hfinfo.hfi){
3869                         gpa_hfinfo.allocated_len=1000;
3870                         gpa_hfinfo.hfi=g_malloc(sizeof(header_field_info *)*1000);
3871                 } else {
3872                         gpa_hfinfo.allocated_len+=1000;
3873                         gpa_hfinfo.hfi=g_realloc(gpa_hfinfo.hfi, sizeof(header_field_info *)*gpa_hfinfo.allocated_len);
3874                 }
3875         }
3876         gpa_hfinfo.hfi[gpa_hfinfo.len]=hfinfo;
3877         gpa_hfinfo.len++;
3878         hfinfo->id = gpa_hfinfo.len - 1;
3879
3880         /* if we have real names, enter this field in the name tree */
3881         if ((hfinfo->name[0] != 0) && (hfinfo->abbrev[0] != 0 )) {
3882
3883                 header_field_info *same_name_next_hfinfo;
3884                 guchar c;
3885
3886                 /* Check that the filter name (abbreviation) is legal;
3887                  * it must contain only alphanumerics, '-', "_", and ".". */
3888                 c = wrs_check_charset(fld_abbrev_chars, hfinfo->abbrev);
3889                 if (c) {
3890                         fprintf(stderr, "OOPS: '%c' in '%s'\n", c, hfinfo->abbrev);
3891                         DISSECTOR_ASSERT(!c);
3892                 }
3893
3894                 /* We allow multiple hfinfo's to be registered under the same
3895                  * abbreviation. This was done for X.25, as, depending
3896                  * on whether it's modulo-8 or modulo-128 operation,
3897                  * some bitfield fields may be in different bits of
3898                  * a byte, and we want to be able to refer to that field
3899                  * with one name regardless of whether the packets
3900                  * are modulo-8 or modulo-128 packets. */
3901 #if GLIB_MAJOR_VERSION < 2
3902                 same_name_hfinfo = g_tree_lookup(gpa_name_tree, discard_const(hfinfo->abbrev));
3903 #else
3904                 same_name_hfinfo = NULL;
3905 #endif
3906                 g_tree_insert(gpa_name_tree, (gpointer) (hfinfo->abbrev), hfinfo);
3907                 /* GLIB 2.x - if it is already present
3908          * the previous hfinfo with the same name is saved
3909          * to same_name_hfinfo by value destroy callback */
3910                 if (same_name_hfinfo) {
3911                         /* There's already a field with this name.
3912                          * Put it after that field in the list of
3913                          * fields with this name, then allow the code
3914                          * after this if{} block to replace the old
3915                          * hfinfo with the new hfinfo in the GTree. Thus,
3916                          * we end up with a linked-list of same-named hfinfo's,
3917                          * with the root of the list being the hfinfo in the GTree */
3918                         same_name_next_hfinfo =
3919                             same_name_hfinfo->same_name_next;
3920
3921                         hfinfo->same_name_next = same_name_next_hfinfo;
3922                         if (same_name_next_hfinfo)
3923                                 same_name_next_hfinfo->same_name_prev = hfinfo;
3924
3925                         same_name_hfinfo->same_name_next = hfinfo;
3926                         hfinfo->same_name_prev = same_name_hfinfo;
3927                 }
3928         }
3929
3930         return hfinfo->id;
3931 }
3932
3933 void
3934 proto_register_subtree_array(gint *const *indices, int num_indices)
3935 {
3936         int     i;
3937         gint    *const *ptr = indices;
3938
3939         /*
3940          * If we've already allocated the array of tree types, expand
3941          * it; this lets plugins such as mate add tree types after
3942          * the initial startup.  (If we haven't already allocated it,
3943          * we don't allocate it; on the first pass, we just assign
3944          * ett values and keep track of how many we've assigned, and
3945          * when we're finished registering all dissectors we allocate
3946          * the array, so that we do only one allocation rather than
3947          * wasting CPU time and memory by growing the array for each
3948          * dissector that registers ett values.)
3949          */
3950         if (tree_is_expanded != NULL) {
3951                 tree_is_expanded =
3952                     g_realloc(tree_is_expanded,
3953                         (num_tree_types+num_indices)*sizeof (gboolean));
3954                 memset(tree_is_expanded + num_tree_types, 0,
3955                     num_indices*sizeof (gboolean));
3956         }
3957
3958         /*
3959          * Assign "num_indices" subtree numbers starting at "num_tree_types",
3960          * returning the indices through the pointers in the array whose
3961          * first element is pointed to by "indices", and update
3962          * "num_tree_types" appropriately.
3963          */
3964         for (i = 0; i < num_indices; i++, ptr++, num_tree_types++)
3965                 **ptr = num_tree_types;
3966 }
3967
3968 void
3969 proto_item_fill_label(field_info *fi, gchar *label_str)
3970 {
3971         header_field_info               *hfinfo = fi->hfinfo;
3972
3973         guint8                          *bytes;
3974         guint32                         integer;
3975         ipv4_addr                       *ipv4;
3976         e_guid_t                        *guid;
3977         guint32                         n_addr; /* network-order IPv4 address */
3978         const gchar                     *name;
3979         int                                     ret;    /*tmp return value */
3980
3981         switch(hfinfo->type) {
3982                 case FT_NONE:
3983                 case FT_PROTOCOL:
3984                         ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3985                                 "%s", hfinfo->name);
3986                         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3987                                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3988                         break;
3989
3990                 case FT_BOOLEAN:
3991                         fill_label_boolean(fi, label_str);
3992                         break;
3993
3994                 case FT_BYTES:
3995                 case FT_UINT_BYTES:
3996                         bytes = fvalue_get(&fi->value);
3997                         if (bytes) {
3998                                 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3999                                         "%s: %s", hfinfo->name,
4000                                          bytes_to_str(bytes, fvalue_length(&fi->value)));
4001                                 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4002                                         label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4003                         }
4004                         else {
4005                                 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4006                                         "%s: <MISSING>", hfinfo->name);
4007                                 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4008                                         label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4009                         }
4010                         break;
4011
4012                 /* Four types of integers to take care of:
4013                  *      Bitfield, with val_string
4014                  *      Bitfield, w/o val_string
4015                  *      Non-bitfield, with val_string
4016                  *      Non-bitfield, w/o val_string
4017                  */
4018                 case FT_UINT8:
4019                 case FT_UINT16:
4020                 case FT_UINT24:
4021                 case FT_UINT32:
4022                 case FT_FRAMENUM:
4023                         if (hfinfo->bitmask) {
4024                                 if (hfinfo->strings) {
4025                                         fill_label_enumerated_bitfield(fi, label_str);
4026                                 }
4027                                 else {
4028                                         fill_label_numeric_bitfield(fi, label_str);
4029                                 }
4030                         }
4031                         else {
4032                                 if (hfinfo->strings) {
4033                                         fill_label_enumerated_uint(fi, label_str);
4034                                 }
4035                                 else {
4036                                         fill_label_uint(fi, label_str);
4037                                 }
4038                         }
4039                         break;
4040
4041                 case FT_UINT64:
4042                         fill_label_uint64(fi, label_str);
4043                         break;
4044
4045                 case FT_INT8:
4046                 case FT_INT16:
4047                 case FT_INT24:
4048                 case FT_INT32:
4049                         DISSECTOR_ASSERT(!hfinfo->bitmask);
4050                         if (hfinfo->strings) {
4051                                 fill_label_enumerated_int(fi, label_str);
4052                         }
4053                         else {
4054                                 fill_label_int(fi, label_str);
4055                         }
4056                         break;
4057
4058                 case FT_INT64:
4059                         fill_label_int64(fi, label_str);
4060                         break;
4061
4062                 case FT_FLOAT:
4063                         ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4064                                 "%s: %." STRINGIFY(FLT_DIG) "f",
4065                                 hfinfo->name, fvalue_get_floating(&fi->value));
4066                         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4067                                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4068                         break;
4069
4070                 case FT_DOUBLE:
4071                         ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4072                                 "%s: %." STRINGIFY(DBL_DIG) "g",
4073                                 hfinfo->name, fvalue_get_floating(&fi->value));
4074                         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4075                                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4076                         break;
4077
4078                 case FT_ABSOLUTE_TIME:
4079                         ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4080                                 "%s: %s", hfinfo->name,
4081                                 abs_time_to_str(fvalue_get(&fi->value)));
4082                         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4083                                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4084                         break;
4085
4086                 case FT_RELATIVE_TIME:
4087                         ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4088                                 "%s: %s seconds", hfinfo->name,
4089                                 rel_time_to_secs_str(fvalue_get(&fi->value)));
4090                         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4091                                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4092                         break;
4093
4094                 case FT_IPXNET:
4095                         integer = fvalue_get_uinteger(&fi->value);
4096                         ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4097                                 "%s: %s (0x%08X)", hfinfo->name,
4098                                 get_ipxnet_name(integer), integer);
4099                         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4100                                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4101                         break;
4102
4103                 case FT_ETHER:
4104                         bytes = fvalue_get(&fi->value);
4105                         ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4106                                 "%s: %s (%s)", hfinfo->name,
4107                                 get_ether_name(bytes),
4108                                 ether_to_str(bytes));
4109                         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4110                                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4111                         break;
4112
4113                 case FT_IPv4:
4114                         ipv4 = fvalue_get(&fi->value);
4115                         n_addr = ipv4_get_net_order_addr(ipv4);
4116                         ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4117                                 "%s: %s (%s)", hfinfo->name,
4118                                 get_hostname(n_addr),
4119                                 ip_to_str((guint8*)&n_addr));
4120                         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4121                                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4122                         break;
4123
4124                 case FT_IPv6:
4125                         bytes = fvalue_get(&fi->value);
4126                         ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4127                                 "%s: %s (%s)", hfinfo->name,
4128                                 get_hostname6((struct e_in6_addr *)bytes),
4129                                 ip6_to_str((struct e_in6_addr*)bytes));
4130                         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4131                                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4132                         break;
4133
4134                 case FT_GUID:
4135                         guid = fvalue_get(&fi->value);
4136                         ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4137                                 "%s: %s", hfinfo->name,
4138                                  guid_to_str(guid));
4139                         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4140                                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4141                         break;
4142
4143                 case FT_OID:
4144                         bytes = fvalue_get(&fi->value);
4145                         name = oid_resolved_from_encoded(bytes, fvalue_length(&fi->value));
4146                         if (name) {
4147                                 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4148                                         "%s: %s (%s)", hfinfo->name,
4149                                          oid_encoded2string(bytes, fvalue_length(&fi->value)), name);
4150                         } else {
4151                                 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4152                                         "%s: %s", hfinfo->name,
4153                                          oid_encoded2string(bytes, fvalue_length(&fi->value)));
4154                         }
4155                         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4156                                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4157                         break;
4158
4159                 case FT_STRING:
4160                 case FT_STRINGZ:
4161                 case FT_EBCDIC:
4162                 case FT_UINT_STRING:
4163                         bytes = fvalue_get(&fi->value);
4164             if(strlen(bytes) > ITEM_LABEL_LENGTH) {
4165                             ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4166                                     "%s [truncated]: %s", hfinfo->name,
4167                                     format_text(bytes, strlen(bytes)));
4168             } else {
4169                             ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4170                                     "%s: %s", hfinfo->name,
4171                                     format_text(bytes, strlen(bytes)));
4172             }
4173                         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4174                                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4175                         break;
4176
4177                 default:
4178                         g_error("hfinfo->type %d (%s) not handled\n",
4179                                         hfinfo->type,
4180                                         ftype_name(hfinfo->type));
4181                         DISSECTOR_ASSERT_NOT_REACHED();
4182                         break;
4183         }
4184 }
4185
4186 static void
4187 fill_label_boolean(field_info *fi, gchar *label_str)
4188 {
4189         char    *p = label_str;
4190         int     bitfield_byte_length = 0, bitwidth;
4191         guint32 unshifted_value;
4192         guint32 value;
4193         int                                     ret;    /*tmp return value */
4194
4195         header_field_info               *hfinfo = fi->hfinfo;
4196         const true_false_string         *tfstring = &tfs_true_false;
4197
4198         if (hfinfo->strings) {
4199                 tfstring = (const struct true_false_string*) hfinfo->strings;
4200         }
4201
4202         value = fvalue_get_uinteger(&fi->value);
4203         if (hfinfo->bitmask) {
4204                 /* Figure out the bit width */
4205                 bitwidth = hfinfo_bitwidth(hfinfo);
4206
4207                 /* Un-shift bits */
4208                 unshifted_value = value;
4209                 if (hfinfo->bitshift > 0) {
4210                         unshifted_value <<= hfinfo->bitshift;
4211                 }
4212
4213                 /* Create the bitfield first */
4214                 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
4215                 bitfield_byte_length = p - label_str;
4216         }
4217
4218         /* Fill in the textual info */
4219         ret = g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
4220                 "%s: %s",  hfinfo->name,
4221                 value ? tfstring->true_string : tfstring->false_string);
4222         if ((ret == -1) || (ret >= (ITEM_LABEL_LENGTH - bitfield_byte_length)))
4223                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4224 }
4225
4226
4227 /* Fills data for bitfield ints with val_strings */
4228 static void
4229 fill_label_enumerated_bitfield(field_info *fi, gchar *label_str)
4230 {
4231         const char *format = NULL;
4232         char *p;
4233         int bitfield_byte_length, bitwidth;
4234         guint32 unshifted_value;
4235         guint32 value;
4236         int                                     ret;    /*tmp return value */
4237
4238         header_field_info       *hfinfo = fi->hfinfo;
4239
4240         /* Figure out the bit width */
4241         bitwidth = hfinfo_bitwidth(hfinfo);
4242
4243         /* Pick the proper format string */
4244         format = hfinfo_uint_vals_format(hfinfo);
4245
4246         /* Un-shift bits */
4247         unshifted_value = fvalue_get_uinteger(&fi->value);
4248         value = unshifted_value;
4249         if (hfinfo->bitshift > 0) {
4250                 unshifted_value <<= hfinfo->bitshift;
4251         }
4252
4253         /* Create the bitfield first */
4254         p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
4255         bitfield_byte_length = p - label_str;
4256
4257         /* Fill in the textual info using stored (shifted) value */
4258         ret = g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
4259                         format,  hfinfo->name,
4260                         val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
4261         if ((ret == -1) || (ret >= (ITEM_LABEL_LENGTH - bitfield_byte_length)))
4262                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4263 }
4264
4265 static void
4266 fill_label_numeric_bitfield(field_info *fi, gchar *label_str)
4267 {
4268         const char *format = NULL;
4269         char *p;
4270         int bitfield_byte_length, bitwidth;
4271         guint32 unshifted_value;
4272         guint32 value;
4273         int                                     ret;    /*tmp return value */
4274
4275         header_field_info       *hfinfo = fi->hfinfo;
4276
4277         /* Figure out the bit width */
4278         bitwidth = hfinfo_bitwidth(hfinfo);
4279
4280         /* Pick the proper format string */
4281         format = hfinfo_uint_format(hfinfo);
4282
4283         /* Un-shift bits */
4284         unshifted_value = fvalue_get_uinteger(&fi->value);
4285         value = unshifted_value;
4286         if (hfinfo->bitshift > 0) {
4287                 unshifted_value <<= hfinfo->bitshift;
4288         }
4289
4290         /* Create the bitfield using */
4291         p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
4292         bitfield_byte_length = p - label_str;
4293
4294         /* Fill in the textual info using stored (shifted) value */
4295         if (IS_BASE_DUAL(hfinfo->display)) {
4296                 ret = g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
4297                                 format,  hfinfo->name, value, value);
4298         } else {
4299                 ret = g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
4300                                 format,  hfinfo->name, value);
4301         }
4302         if ((ret == -1) || (ret >= (ITEM_LABEL_LENGTH - bitfield_byte_length)))
4303                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4304
4305 }
4306
4307 static void
4308 fill_label_enumerated_uint(field_info *fi, gchar *label_str)
4309 {
4310         const char *format = NULL;
4311         header_field_info       *hfinfo = fi->hfinfo;
4312         guint32 value;
4313         int                                     ret;    /*tmp return value */
4314
4315         /* Pick the proper format string */
4316         format = hfinfo_uint_vals_format(hfinfo);
4317
4318         value = fvalue_get_uinteger(&fi->value);
4319
4320         /* Fill in the textual info */
4321         if (hfinfo->display & BASE_RANGE_STRING) {
4322           ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4323                         format,  hfinfo->name,
4324                         rval_to_str(value, hfinfo->strings, "Unknown"), value);
4325         } else {
4326           ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4327                         format,  hfinfo->name,
4328                         val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
4329         }
4330         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4331                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4332 }
4333
4334 static void
4335 fill_label_uint(field_info *fi, gchar *label_str)
4336 {
4337         const char *format = NULL;
4338         header_field_info       *hfinfo = fi->hfinfo;
4339         guint32 value;
4340         int                                     ret;    /*tmp return value */
4341
4342         /* Pick the proper format string */
4343         format = hfinfo_uint_format(hfinfo);
4344         value = fvalue_get_uinteger(&fi->value);
4345
4346         /* Fill in the textual info */
4347         if (IS_BASE_DUAL(hfinfo->display)) {
4348                 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4349                                 format,  hfinfo->name, value, value);
4350         } else {
4351                 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4352                                 format,  hfinfo->name, value);
4353         }
4354         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4355                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4356 }
4357
4358 static void
4359 fill_label_uint64(field_info *fi, gchar *label_str)
4360 {
4361         const char *format = NULL;
4362         header_field_info       *hfinfo = fi->hfinfo;
4363         guint64 value;
4364         int                                     ret;    /*tmp return value */
4365
4366         /* Pick the proper format string */
4367         format = hfinfo_uint64_format(hfinfo);
4368         value = fvalue_get_integer64(&fi->value);
4369
4370         /* Fill in the textual info */
4371         if (IS_BASE_DUAL(hfinfo->display)) {
4372                 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4373                                 format,  hfinfo->name, value, value);
4374         } else {
4375                 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4376                                 format,  hfinfo->name, value);
4377         }
4378         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4379                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4380 }
4381
4382 static void
4383 fill_label_enumerated_int(field_info *fi, gchar *label_str)
4384 {
4385         const char *format = NULL;
4386         header_field_info       *hfinfo = fi->hfinfo;
4387         guint32 value;
4388         int                                     ret;    /*tmp return value */
4389
4390         /* Pick the proper format string */
4391         format = hfinfo_int_vals_format(hfinfo);
4392         value = fvalue_get_sinteger(&fi->value);
4393
4394         /* Fill in the textual info */
4395         if (hfinfo->display & BASE_RANGE_STRING) {
4396           ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4397                         format,  hfinfo->name,
4398                         rval_to_str(value, hfinfo->strings, "Unknown"), value);
4399         } else {
4400           ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4401                         format,  hfinfo->name,
4402                         val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
4403         }
4404         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4405                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4406 }
4407
4408 static void
4409 fill_label_int(field_info *fi, gchar *label_str)
4410 {
4411         const char *format = NULL;
4412         header_field_info       *hfinfo = fi->hfinfo;
4413         guint32 value;
4414         int                                     ret;    /*tmp return value */
4415
4416         /* Pick the proper format string */
4417         format = hfinfo_int_format(hfinfo);
4418         value = fvalue_get_sinteger(&fi->value);
4419
4420         /* Fill in the textual info */
4421         if (IS_BASE_DUAL(hfinfo->display)) {
4422                 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4423                                 format,  hfinfo->name, value, value);
4424         } else {
4425                 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4426                                 format,  hfinfo->name, value);
4427         }
4428         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4429                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4430 }
4431
4432 static void
4433 fill_label_int64(field_info *fi, gchar *label_str)
4434 {
4435         const char *format = NULL;
4436         header_field_info       *hfinfo = fi->hfinfo;
4437         guint64 value;
4438         int                                     ret;    /*tmp return value */
4439
4440         /* Pick the proper format string */
4441         format = hfinfo_int64_format(hfinfo);
4442         value = fvalue_get_integer64(&fi->value);
4443
4444         /* Fill in the textual info */
4445         if (IS_BASE_DUAL(hfinfo->display)) {
4446                 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4447                                 format,  hfinfo->name, value, value);
4448         } else {
4449                 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
4450                                 format,  hfinfo->name, value);
4451         }
4452         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
4453                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
4454 }
4455
4456 int
4457 hfinfo_bitwidth(header_field_info *hfinfo)
4458 {
4459         int bitwidth = 0;
4460
4461         if (!hfinfo->bitmask) {
4462                 return 0;
4463         }
4464
4465         switch(hfinfo->type) {
4466                 case FT_UINT8:
4467                 case FT_INT8:
4468                         bitwidth = 8;
4469                         break;
4470                 case FT_UINT16:
4471                 case FT_INT16:
4472                         bitwidth = 16;
4473                         break;
4474                 case FT_UINT24:
4475                 case FT_INT24:
4476                         bitwidth = 24;
4477                         break;
4478                 case FT_UINT32:
4479                 case FT_INT32:
4480                         bitwidth = 32;
4481                         break;
4482                 case FT_BOOLEAN:
4483                         bitwidth = hfinfo->display; /* hacky? :) */
4484                         break;
4485                 default:
4486                         DISSECTOR_ASSERT_NOT_REACHED();
4487                         ;
4488         }
4489         return bitwidth;
4490 }
4491
4492 static const char*
4493 hfinfo_uint_vals_format(header_field_info *hfinfo)
4494 {
4495         const char *format = NULL;
4496
4497         /* bit operation to reset the potential BASE_RANGE_STRING (or others in
4498          * the future?) */
4499         switch(hfinfo->display & BASE_STRUCTURE_RESET) {
4500                 case BASE_DEC:
4501                 case BASE_DEC_HEX:
4502                         format = "%s: %s (%u)";
4503                         break;
4504                 case BASE_OCT: /* I'm lazy */
4505                         format = "%s: %s (%o)";
4506                         break;
4507                 case BASE_HEX:
4508                 case BASE_HEX_DEC:
4509                         switch(hfinfo->type) {
4510                                 case FT_UINT8:
4511                                         format = "%s: %s (0x%02x)";
4512                                         break;
4513                                 case FT_UINT16:
4514                                         format = "%s: %s (0x%04x)";
4515                                         break;
4516                                 case FT_UINT24:
4517                                         format = "%s: %s (0x%06x)";
4518                                         break;
4519                                 case FT_UINT32:
4520                                         format = "%s: %s (0x%08x)";
4521                                         break;
4522                                 default:
4523                                         DISSECTOR_ASSERT_NOT_REACHED();
4524                                         ;
4525                         }
4526                         break;
4527                 default:
4528                         DISSECTOR_ASSERT_NOT_REACHED();
4529                         ;
4530         }
4531         return format;
4532 }
4533
4534 static const char*
4535 hfinfo_uint_format(header_field_info *hfinfo)
4536 {
4537         const char *format = NULL;
4538
4539         /* Pick the proper format string */
4540         if (hfinfo->type == FT_FRAMENUM) {
4541                 /*
4542                  * Frame numbers are always displayed in decimal.
4543                  */
4544                 format = "%s: %u";
4545         } else {
4546                 switch(hfinfo->display) {
4547                         case BASE_DEC:
4548                                 format = "%s: %u";
4549                                 break;
4550                         case BASE_DEC_HEX:
4551                                 switch(hfinfo->type) {
4552                                         case FT_UINT8:
4553                                                 format = "%s: %u (0x%02x)";
4554                                                 break;
4555                                         case FT_UINT16:
4556                                                 format = "%s: %u (0x%04x)";
4557                                                 break;
4558                                         case FT_UINT24:
4559                                                 format = "%s: %u (0x%06x)";
4560                                                 break;
4561                                         case FT_UINT32:
4562                                                 format = "%s: %u (0x%08x)";
4563                                                 break;
4564                                         default:
4565                                                 DISSECTOR_ASSERT_NOT_REACHED();
4566                                                 ;
4567                                 }
4568                                 break;
4569                         case BASE_OCT: /* I'm lazy */
4570                                 format = "%s: %o";
4571                                 break;
4572                         case BASE_HEX:
4573                                 switch(hfinfo->type) {
4574                                         case FT_UINT8:
4575                                                 format = "%s: 0x%02x";
4576                                                 break;
4577                                         case FT_UINT16:
4578                                                 format = "%s: 0x%04x";
4579                                                 break;
4580                                         case FT_UINT24:
4581                                                 format = "%s: 0x%06x";
4582                                                 break;
4583                                         case FT_UINT32:
4584                                                 format = "%s: 0x%08x";
4585                                                 break;
4586                                         default:
4587                                                 DISSECTOR_ASSERT_NOT_REACHED();
4588                                                 ;
4589                                 }
4590                                 break;
4591                         case BASE_HEX_DEC:
4592                                 switch(hfinfo->type) {
4593                                         case FT_UINT8:
4594                                                 format = "%s: 0x%02x (%u)";
4595                                                 break;
4596                                         case FT_UINT16:
4597                                                 format = "%s: 0x%04x (%u)";
4598                                                 break;
4599                                         case FT_UINT24:
4600                                                 format = "%s: 0x%06x (%u)";
4601                                                 break;
4602                                         case FT_UINT32:
4603                                                 format = "%s: 0x%08x (%u)";
4604                                                 break;
4605                                         default:
4606                                                 DISSECTOR_ASSERT_NOT_REACHED();
4607                                                 ;
4608                                 }
4609                                 break;
4610                         default:
4611                                 DISSECTOR_ASSERT_NOT_REACHED();
4612                                 ;
4613                 }
4614         }
4615         return format;
4616 }
4617
4618 static const char*
4619 hfinfo_int_vals_format(header_field_info *hfinfo)
4620 {
4621         const char *format = NULL;
4622
4623         /* bit operation to reset the potential BASE_RANGE_STRING (or others in
4624          * the future?)*/
4625         switch(hfinfo->display & BASE_STRUCTURE_RESET) {
4626                 case BASE_DEC:
4627                 case BASE_DEC_HEX:
4628                         format = "%s: %s (%d)";
4629                         break;
4630                 case BASE_OCT: /* I'm lazy */
4631                         format = "%s: %s (%o)";
4632                         break;
4633                 case BASE_HEX:
4634                 case BASE_HEX_DEC:
4635                         switch(hfinfo->type) {
4636                                 case FT_INT8:
4637                                         format = "%s: %s (0x%02x)";
4638                                         break;
4639                                 case FT_INT16:
4640                                         format = "%s: %s (0x%04x)";
4641                                         break;
4642                                 case FT_INT24:
4643                                         format = "%s: %s (0x%06x)";
4644                                         break;
4645                                 case FT_INT32:
4646                                         format = "%s: %s (0x%08x)";
4647                                         break;
4648                                 default:
4649                                         DISSECTOR_ASSERT_NOT_REACHED();
4650                                         ;
4651                         }
4652                         break;
4653                 default:
4654                         DISSECTOR_ASSERT_NOT_REACHED();
4655                         ;
4656         }
4657         return format;
4658 }
4659
4660 static const char*
4661 hfinfo_uint64_format(header_field_info *hfinfo)
4662 {
4663         const char *format = NULL;
4664
4665         /* Pick the proper format string */
4666         switch(hfinfo->display) {
4667                 case BASE_DEC:
4668                         format = "%s: %" G_GINT64_MODIFIER "u";
4669                         break;
4670                 case BASE_DEC_HEX:
4671                         format = "%s: %" G_GINT64_MODIFIER "u (%" G_GINT64_MODIFIER "x)";
4672                         break;
4673                 case BASE_OCT: /* I'm lazy */
4674                         format = "%s: %" G_GINT64_MODIFIER "o";
4675                         break;
4676                 case BASE_HEX:
4677                         format = "%s: 0x%016" G_GINT64_MODIFIER "x";
4678                         break;
4679                 case BASE_HEX_DEC:
4680                         format = "%s: 0x%016" G_GINT64_MODIFIER "x (%" G_GINT64_MODIFIER "u)";
4681                         break;
4682                 default:
4683                         DISSECTOR_ASSERT_NOT_REACHED();
4684                         ;
4685         }
4686         return format;
4687 }
4688
4689 static const char*
4690 hfinfo_int_format(header_field_info *hfinfo)
4691 {
4692         const char *format = NULL;
4693
4694         /* Pick the proper format string */
4695         switch(hfinfo->display) {
4696                 case BASE_DEC:
4697                         format = "%s: %d";
4698                         break;
4699                 case BASE_DEC_HEX:
4700                         switch(hfinfo->type) {
4701                                 case FT_INT8:
4702                                         format = "%s: %d (0x%02x)";
4703                                         break;
4704                                 case FT_INT16:
4705                                         format = "%s: %d (0x%04x)";
4706                                         break;
4707                                 case FT_INT24:
4708                                         format = "%s: %d (0x%06x)";
4709                                         break;
4710                                 case FT_INT32:
4711                                         format = "%s: %d (0x%08x)";
4712                                         break;
4713                                 default:
4714                                         DISSECTOR_ASSERT_NOT_REACHED();
4715                                         ;
4716                         }
4717                         break;
4718                 case BASE_OCT: /* I'm lazy */
4719                         format = "%s: %o";
4720                         break;
4721                 case BASE_HEX:
4722                         switch(hfinfo->type) {
4723                                 case FT_INT8:
4724                                         format = "%s: 0x%02x";
4725                                         break;
4726                                 case FT_INT16:
4727                                         format = "%s: 0x%04x";
4728                                         break;
4729                                 case FT_INT24:
4730                                         format = "%s: 0x%06x";
4731                                         break;
4732                                 case FT_INT32:
4733                                         format = "%s: 0x%08x";
4734                                         break;
4735                                 default:
4736                                         DISSECTOR_ASSERT_NOT_REACHED();
4737                                         ;
4738                         }
4739                         break;
4740                 case BASE_HEX_DEC:
4741                         switch(hfinfo->type) {
4742                                 case FT_INT8:
4743                                         format = "%s: 0x%02x (%d)";
4744                                         break;
4745                                 case FT_INT16:
4746                                         format = "%s: 0x%04x (%d)";
4747                                         break;
4748                                 case FT_INT24:
4749                                         format = "%s: 0x%06x (%d)";
4750                                         break;
4751                                 case FT_INT32:
4752                                         format = "%s: 0x%08x (%d)";
4753                                         break;
4754                                 default:
4755                                         DISSECTOR_ASSERT_NOT_REACHED();
4756                                         ;
4757                         }
4758                         break;
4759                 default:
4760                         DISSECTOR_ASSERT_NOT_REACHED();
4761                         ;
4762         }
4763         return format;
4764 }
4765
4766 static const char*
4767 hfinfo_int64_format(header_field_info *hfinfo)
4768 {
4769         const char *format = NULL;
4770
4771         /* Pick the proper format string */
4772         switch(hfinfo->display) {
4773                 case BASE_DEC:
4774                         format = "%s: %" G_GINT64_MODIFIER "d";
4775                         break;
4776                 case BASE_DEC_HEX:
4777                         format = "%s: %" G_GINT64_MODIFIER "d (%" G_GINT64_MODIFIER "x)";
4778                         break;
4779                 case BASE_OCT: /* I'm lazy */
4780                         format = "%s: %" G_GINT64_MODIFIER "o";
4781                         break;
4782                 case BASE_HEX:
4783                         format = "%s: 0x%016" G_GINT64_MODIFIER "x";
4784                         break;
4785                 case BASE_HEX_DEC:
4786                         format = "%s: 0x%016" G_GINT64_MODIFIER "x (%" G_GINT64_MODIFIER "d)";
4787                         break;
4788                 default:
4789                         DISSECTOR_ASSERT_NOT_REACHED();
4790                         ;
4791         }
4792         return format;
4793 }
4794
4795
4796
4797 int
4798 proto_registrar_n(void)
4799 {
4800         return gpa_hfinfo.len;
4801 }
4802
4803 const char*
4804 proto_registrar_get_name(int n)
4805 {
4806         header_field_info *hfinfo;
4807
4808         PROTO_REGISTRAR_GET_NTH(n, hfinfo);
4809         return hfinfo->name;
4810 }
4811
4812 const char*
4813 proto_registrar_get_abbrev(int n)
4814 {
4815         header_field_info *hfinfo;
4816
4817         PROTO_REGISTRAR_GET_NTH(n, hfinfo);
4818         return hfinfo->abbrev;
4819 }
4820
4821 int
4822 proto_registrar_get_ftype(int n)
4823 {
4824         header_field_info *hfinfo;
4825
4826         PROTO_REGISTRAR_GET_NTH(n, hfinfo);
4827         return hfinfo->type;
4828 }
4829
4830 int
4831 proto_registrar_get_parent(int n)
4832 {
4833         header_field_info *hfinfo;
4834
4835         PROTO_REGISTRAR_GET_NTH(n, hfinfo);
4836         return hfinfo->parent;
4837 }
4838
4839 gboolean
4840 proto_registrar_is_protocol(int n)
4841 {
4842         header_field_info *hfinfo;
4843
4844         PROTO_REGISTRAR_GET_NTH(n, hfinfo);
4845         return (hfinfo->parent == -1 ? TRUE : FALSE);
4846 }
4847
4848 /* Returns length of field in packet (not necessarily the length
4849  * in our internal representation, as in the case of IPv4).
4850  * 0 means undeterminable at time of registration
4851  * -1 means the field is not registered. */
4852 gint
4853 proto_registrar_get_length(int n)
4854 {
4855         header_field_info *hfinfo;
4856
4857         PROTO_REGISTRAR_GET_NTH(n, hfinfo);
4858         return ftype_length(hfinfo->type);
4859 }
4860
4861
4862
4863 /* Looks for a protocol or a field in a proto_tree. Returns TRUE if
4864  * it exists anywhere, or FALSE if it exists nowhere. */
4865 gboolean
4866 proto_check_for_protocol_or_field(proto_tree* tree, int id)
4867 {
4868         GPtrArray *ptrs = proto_get_finfo_ptr_array(tree, id);
4869
4870         if (!ptrs) {
4871                 return FALSE;
4872         }
4873         else if (g_ptr_array_len(ptrs) > 0) {
4874                 return TRUE;
4875         }
4876         else {
4877                 return FALSE;
4878         }
4879 }
4880
4881 /* Return GPtrArray* of field_info pointers for all hfindex that appear in tree.
4882  * This only works if the hfindex was "primed" before the dissection
4883  * took place, as we just pass back the already-created GPtrArray*.
4884  * The caller should *not* free the GPtrArray*; proto_tree_free_node()
4885  * handles that. */
4886 GPtrArray*
4887 proto_get_finfo_ptr_array(proto_tree *tree, int id)
4888 {
4889         return g_hash_table_lookup(PTREE_DATA(tree)->interesting_hfids,
4890             GINT_TO_POINTER(id));
4891 }
4892
4893
4894 /* Helper struct for proto_find_info() and  proto_all_finfos() */
4895 typedef struct {
4896         GPtrArray       *array;
4897         int             id;
4898 } ffdata_t;
4899
4900 /* Helper function for proto_find_info() */
4901 static gboolean
4902 find_finfo(proto_node *node, gpointer data)
4903 {
4904         field_info *fi = PITEM_FINFO(node);
4905         if (fi && fi->hfinfo) {
4906                 if (fi->hfinfo->id == ((ffdata_t*)data)->id) {
4907                         g_ptr_array_add(((ffdata_t*)data)->array, fi);
4908                 }
4909         }
4910
4911         /* Don't stop traversing. */
4912         return FALSE;
4913 }
4914
4915 /* Return GPtrArray* of field_info pointers for all hfindex that appear in a tree.
4916 * This works on any proto_tree, primed or unprimed, but actually searches
4917 * the tree, so it is slower than using proto_get_finfo_ptr_array on a primed tree.
4918 * The caller does need to free the returned GPtrArray with
4919 * g_ptr_array_free(<array>, FALSE).
4920 */
4921 GPtrArray*
4922 proto_find_finfo(proto_tree *tree, int id)
4923 {
4924         ffdata_t        ffdata;
4925
4926         ffdata.array = g_ptr_array_new();
4927         ffdata.id = id;
4928
4929         proto_tree_traverse_pre_order(tree, find_finfo, &ffdata);
4930
4931         return ffdata.array;
4932 }
4933
4934 /* Helper function for proto_all_finfos() */
4935 static gboolean
4936 every_finfo(proto_node *node, gpointer data)
4937 {
4938         field_info *fi = PITEM_FINFO(node);
4939         if (fi && fi->hfinfo) {
4940                 g_ptr_array_add(((ffdata_t*)data)->array, fi);
4941         }
4942
4943         /* Don't stop traversing. */
4944         return FALSE;
4945 }
4946
4947 /* Return GPtrArray* of field_info pointers containing all hfindexes that appear in a tree. */
4948 GPtrArray*
4949 proto_all_finfos(proto_tree *tree)
4950 {
4951         ffdata_t        ffdata;
4952
4953         ffdata.array = g_ptr_array_new();
4954         ffdata.id = 0;
4955
4956         proto_tree_traverse_pre_order(tree, every_finfo, &ffdata);
4957
4958         return ffdata.array;
4959 }
4960
4961
4962 typedef struct {
4963         guint           offset;
4964         field_info      *finfo;
4965         tvbuff_t        *tvb;
4966 } offset_search_t;
4967
4968 static gboolean
4969 check_for_offset(proto_node *node, gpointer data)
4970 {
4971         field_info          *fi = PITEM_FINFO(node);
4972         offset_search_t         *offsearch = data;
4973
4974         /* !fi == the top most container node which holds nothing */
4975         if (fi && !PROTO_ITEM_IS_HIDDEN(node) && fi->ds_tvb && offsearch->tvb == fi->ds_tvb) {
4976                 if (offsearch->offset >= (guint) fi->start &&
4977                                 offsearch->offset < (guint) (fi->start + fi->length)) {
4978
4979                         offsearch->finfo = fi;
4980                         return FALSE; /* keep traversing */
4981                 }
4982         }
4983         return FALSE; /* keep traversing */
4984 }
4985
4986 /* Search a proto_tree backwards (from leaves to root) looking for the field
4987  * whose start/length occupies 'offset' */
4988 /* XXX - I couldn't find an easy way to search backwards, so I search
4989  * forwards, w/o stopping. Therefore, the last finfo I find will the be
4990  * the one I want to return to the user. This algorithm is inefficient
4991  * and could be re-done, but I'd have to handle all the children and
4992  * siblings of each node myself. When I have more time I'll do that.
4993  * (yeah right) */
4994 field_info*
4995 proto_find_field_from_offset(proto_tree *tree, guint offset, tvbuff_t *tvb)
4996 {
4997         offset_search_t         offsearch;
4998
4999         offsearch.offset = offset;
5000         offsearch.finfo = NULL;
5001         offsearch.tvb = tvb;
5002
5003         proto_tree_traverse_pre_order(tree, check_for_offset, &offsearch);
5004
5005         return offsearch.finfo;
5006 }
5007
5008 /* Dumps the protocols in the registration database to stdout.  An independent
5009  * program can take this output and format it into nice tables or HTML or
5010  * whatever.
5011  *
5012  * There is one record per line. The fields are tab-delimited.
5013  *
5014  * Field 1 = protocol name
5015  * Field 2 = protocol short name
5016  * Field 3 = protocol filter name
5017  */
5018 void
5019 proto_registrar_dump_protocols(void)
5020 {
5021         protocol_t              *protocol;
5022         int                     i;
5023         void                    *cookie = NULL;
5024
5025         for (i = proto_get_first_protocol(&cookie); i != -1;
5026             i = proto_get_next_protocol(&cookie)) {
5027                 protocol = find_protocol_by_id(i);
5028                 printf("%s\t%s\t%s\n", protocol->name, protocol->short_name,
5029                     protocol->filter_name);
5030         }
5031 }
5032
5033 /* Dumps the value_string and true/false strings for fields that have
5034  * them. There is one record per line. Fields are tab-delimited.
5035  * There are two types of records, Value String records and True/False
5036  * String records. The first field, 'V' or 'T', indicates the type
5037  * of record.
5038  *
5039  * Value Strings
5040  * -------------
5041  * Field 1 = 'V'
5042  * Field 2 = field abbreviation to which this value string corresponds
5043  * Field 3 = Integer value
5044  * Field 4 = String
5045  *
5046  * True/False Strings
5047  * ------------------
5048  * Field 1 = 'T'
5049  * Field 2 = field abbreviation to which this true/false string corresponds
5050  * Field 3 = True String
5051  * Field 4 = False String
5052  */
5053 void
5054 proto_registrar_dump_values(void)
5055 {
5056         header_field_info       *hfinfo, *parent_hfinfo;
5057         int                     i, len, vi;
5058         const value_string      *vals;
5059         const true_false_string *tfs;
5060
5061         len = gpa_hfinfo.len;
5062         for (i = 0; i < len ; i++) {
5063                 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
5064
5065                  if (hfinfo->id == hf_text_only) {
5066                          continue;
5067                  }
5068
5069                 /* ignore protocols */
5070                 if (proto_registrar_is_protocol(i)) {
5071                         continue;
5072                 }
5073                 /* process header fields */
5074                 else {
5075                         /*
5076                          * If this field isn't at the head of the list of
5077                          * fields with this name, skip this field - all
5078                          * fields with the same name are really just versions
5079                          * of the same field stored in different bits, and
5080                          * should have the same type/radix/value list, and
5081                          * just differ in their bit masks.  (If a field isn't
5082                          * a bitfield, but can be, say, 1 or 2 bytes long,
5083                          * it can just be made FT_UINT16, meaning the
5084                          * *maximum* length is 2 bytes, and be used
5085                          * for all lengths.)
5086                          */
5087                         if (hfinfo->same_name_prev != NULL)
5088                                 continue;
5089
5090                         PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
5091
5092                         vals = NULL;
5093                         tfs = NULL;
5094
5095                         if (hfinfo->type == FT_UINT8 ||
5096                                 hfinfo->type == FT_UINT16 ||
5097                                 hfinfo->type == FT_UINT24 ||
5098                                 hfinfo->type == FT_UINT32 ||
5099                                 hfinfo->type == FT_UINT64 ||
5100                                 hfinfo->type == FT_INT8 ||
5101                                 hfinfo->type == FT_INT16 ||
5102                                 hfinfo->type == FT_INT24 ||
5103                                 hfinfo->type == FT_INT32 ||
5104                                 hfinfo->type == FT_INT64) {
5105
5106                                 vals = hfinfo->strings;
5107                         }
5108                         else if (hfinfo->type == FT_BOOLEAN) {
5109                                 tfs = hfinfo->strings;
5110                         }
5111
5112                         /* Print value strings? */
5113                         if (vals) {
5114                                 vi = 0;
5115                                 while (vals[vi].strptr) {
5116                                         /* Print in the proper base */
5117                                         if (hfinfo->display == BASE_HEX) {
5118                                                 printf("V\t%s\t0x%x\t%s\n",
5119                                                                 hfinfo->abbrev,
5120                                                                 vals[vi].value,
5121                                                                 vals[vi].strptr);
5122                                         }
5123                                         else {
5124                                                 printf("V\t%s\t%u\t%s\n",
5125                                                                 hfinfo->abbrev,
5126                                                                 vals[vi].value,
5127                                                                 vals[vi].strptr);
5128                                         }
5129                                         vi++;
5130                                 }
5131                         }
5132
5133                         /* Print true/false strings? */
5134                         else if (tfs) {
5135                                 printf("T\t%s\t%s\t%s\n", hfinfo->abbrev,
5136                                                 tfs->true_string, tfs->false_string);
5137                         }
5138                 }
5139         }
5140 }
5141
5142 /* Dumps the contents of the registration database to stdout. An indepedent
5143  * program can take this output and format it into nice tables or HTML or
5144  * whatever.
5145  *
5146  * There is one record per line. Each record is either a protocol or a header
5147  * field, differentiated by the first field. The fields are tab-delimited.
5148  *
5149  * Protocols
5150  * ---------
5151  * Field 1 = 'P'
5152  * Field 2 = descriptive protocol name
5153  * Field 3 = protocol abbreviation
5154  *
5155  * Header Fields
5156  * -------------
5157  * (format 1)
5158  * Field 1 = 'F'
5159  * Field 2 = descriptive field name
5160  * Field 3 = field abbreviation
5161  * Field 4 = type ( textual representation of the the ftenum type )
5162  * Field 5 = parent protocol abbreviation
5163  * Field 6 = blurb describing field
5164  *
5165  * (format 2)
5166  * Field 1 = 'F'
5167  * Field 2 = descriptive field name
5168  * Field 3 = field abbreviation
5169  * Field 4 = type ( textual representation of the the ftenum type )
5170  * Field 5 = parent protocol abbreviation
5171  * Field 6 = blurb describing field
5172  * Field 7 = base for display (for integer types)
5173  * Field 8 = blurb describing field (yes, apparently we repeated this accidentally)
5174  *
5175  * (format 3)
5176  * Field 1 = 'F'
5177  * Field 2 = descriptive field name
5178  * Field 3 = field abbreviation
5179  * Field 4 = type ( textual representation of the the ftenum type )
5180  * Field 5 = parent protocol abbreviation
5181  * Field 6 = blurb describing field
5182  * Field 7 = base for display (for integer types)
5183  * Field 8 = bitmask
5184  */
5185 void
5186 proto_registrar_dump_fields(int format)
5187 {
5188         header_field_info       *hfinfo, *parent_hfinfo;
5189         int                     i, len;
5190         const char              *enum_name;
5191         const char              *base_name;
5192         const char              *blurb;
5193
5194         len = gpa_hfinfo.len;
5195         for (i = 0; i < len ; i++) {
5196                 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
5197
5198                 /*
5199                  * Skip the pseudo-field for "proto_tree_add_text()" since
5200                  * we don't want it in the list of filterable fields.
5201          */
5202         if (hfinfo->id == hf_text_only)
5203                         continue;
5204
5205                 /* format for protocols */
5206                 if (proto_registrar_is_protocol(i)) {
5207                         printf("P\t%s\t%s\n", hfinfo->name, hfinfo->abbrev);
5208                 }
5209                 /* format for header fields */
5210                 else {
5211                         /*
5212                          * If this field isn't at the head of the list of
5213                          * fields with this name, skip this field - all
5214                          * fields with the same name are really just versions
5215                          * of the same field stored in different bits, and
5216                          * should have the same type/radix/value list, and
5217                          * just differ in their bit masks.  (If a field isn't
5218                          * a bitfield, but can be, say, 1 or 2 bytes long,
5219                          * it can just be made FT_UINT16, meaning the
5220                          * *maximum* length is 2 bytes, and be used
5221                          * for all lengths.)
5222                          */
5223                         if (hfinfo->same_name_prev != NULL)
5224                                 continue;
5225
5226                         PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
5227
5228                         enum_name = ftype_name(hfinfo->type);
5229                         base_name = "";
5230
5231                         if (format > 1) {
5232                                 if (hfinfo->type == FT_UINT8 ||
5233                                         hfinfo->type == FT_UINT16 ||
5234                                         hfinfo->type == FT_UINT24 ||
5235                                         hfinfo->type == FT_UINT32 ||
5236                                         hfinfo->type == FT_UINT64 ||
5237                                         hfinfo->type == FT_INT8 ||
5238                                         hfinfo->type == FT_INT16 ||
5239                                         hfinfo->type == FT_INT24 ||
5240                                         hfinfo->type == FT_INT32 ||
5241                                         hfinfo->type == FT_INT64) {
5242
5243
5244                                         switch(hfinfo->display) {
5245                                                 case BASE_NONE:
5246                                                         base_name = "BASE_NONE";
5247                                                         break;
5248                                                 case BASE_DEC:
5249                                                         base_name = "BASE_DEC";
5250                                                         break;
5251                                                 case BASE_HEX:
5252                                                         base_name = "BASE_HEX";
5253                                                         break;
5254                                                 case BASE_OCT:
5255                                                         base_name = "BASE_OCT";
5256                                                         break;
5257                                                 case BASE_DEC_HEX:
5258                                                         base_name = "BASE_DEC_HEX";
5259                                                         break;
5260                                                 case BASE_HEX_DEC:
5261                                                         base_name = "BASE_HEX_DEC";
5262                                                         break;
5263                                         }
5264                                 }
5265                         }
5266
5267                         blurb = hfinfo->blurb;
5268                         if (blurb == NULL)
5269                                 blurb = "";
5270                         if (format == 1) {
5271                                 printf("F\t%s\t%s\t%s\t%s\t%s\n",
5272                                         hfinfo->name, hfinfo->abbrev, enum_name,
5273                                         parent_hfinfo->abbrev, blurb);
5274                         }
5275                         else if (format == 2) {
5276                                 printf("F\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n",
5277                                         hfinfo->name, hfinfo->abbrev, enum_name,
5278                                         parent_hfinfo->abbrev, blurb,
5279                                         base_name, blurb);
5280                         }
5281                         else if (format == 3) {
5282                                 printf("F\t%s\t%s\t%s\t%s\t%s\t%s\t%u\n",
5283                                         hfinfo->name, hfinfo->abbrev, enum_name,
5284                                         parent_hfinfo->abbrev, blurb,
5285                                         base_name, hfinfo->bitmask);
5286                         }
5287                         else {
5288                                 g_assert_not_reached();
5289                         }
5290                 }
5291         }
5292 }
5293
5294 static const char*
5295 hfinfo_numeric_format(header_field_info *hfinfo)
5296 {
5297         const char *format = NULL;
5298
5299         /* Pick the proper format string */
5300         if (hfinfo->type == FT_FRAMENUM) {
5301                 /*
5302                  * Frame numbers are always displayed in decimal.
5303                  */
5304                 format = "%s == %u";
5305         } else {
5306                 /* Pick the proper format string */
5307                 switch(hfinfo->display) {
5308                         case BASE_DEC:
5309                         case BASE_DEC_HEX:
5310                         case BASE_OCT: /* I'm lazy */
5311                                 switch(hfinfo->type) {
5312                                         case FT_UINT8:
5313                                         case FT_UINT16:
5314                                         case FT_UINT24:
5315                                         case FT_UINT32:
5316                                                 format = "%s == %u";
5317                                                 break;
5318                                         case FT_UINT64:
5319                                                 format = "%s == %" G_GINT64_MODIFIER "u";
5320                                                 break;
5321                                         case FT_INT8:
5322                                         case FT_INT16:
5323                                         case FT_INT24:
5324                                         case FT_INT32:
5325                                                 format = "%s == %d";
5326                                                 break;
5327                                         case FT_INT64:
5328                                                 format = "%s == %" G_GINT64_MODIFIER "d";
5329                                                 break;
5330                                         default:
5331                                                 DISSECTOR_ASSERT_NOT_REACHED();
5332                                                 ;
5333                                 }
5334                                 break;
5335                         case BASE_HEX:
5336                         case BASE_HEX_DEC:
5337                                 switch(hfinfo->type) {
5338                                         case FT_UINT8:
5339                                                 format = "%s == 0x%02x";
5340                                                 break;
5341                                         case FT_UINT16:
5342                                                 format = "%s == 0x%04x";
5343                                                 break;
5344                                         case FT_UINT24:
5345                                                 format = "%s == 0x%06x";
5346                                                 break;
5347                                         case FT_UINT32:
5348                                                 format = "%s == 0x%08x";
5349                                                 break;
5350                                         case FT_UINT64:
5351                                                 format = "%s == 0x%016" G_GINT64_MODIFIER "x";
5352                                                 break;
5353                                         default:
5354                                                 DISSECTOR_ASSERT_NOT_REACHED();
5355                                                 ;
5356                                 }
5357                                 break;
5358                         default:
5359                                 DISSECTOR_ASSERT_NOT_REACHED();
5360                                 ;
5361                 }
5362         }
5363         return format;
5364 }
5365
5366 /* This function indicates whether it's possible to construct a
5367  * "match selected" display filter string for the specified field,
5368  * returns an indication of whether it's possible, and, if it's
5369  * possible and "filter" is non-null, constructs the filter and
5370  * sets "*filter" to point to it.
5371  * You do not need to [g_]free() this string since it will be automatically
5372  * freed once the next packet is dissected.
5373  */
5374 static gboolean
5375 construct_match_selected_string(field_info *finfo, epan_dissect_t *edt,
5376     char **filter)
5377 {
5378         header_field_info       *hfinfo;
5379         int                     abbrev_len;
5380         char                    *ptr;
5381         int                     buf_len;
5382         const char              *format;
5383         int                     dfilter_len, i;
5384         gint                    start, length, length_remaining;
5385         guint8                  c;
5386         gchar                   is_signed_num = FALSE;
5387
5388         hfinfo = finfo->hfinfo;
5389         DISSECTOR_ASSERT(hfinfo);
5390         abbrev_len = strlen(hfinfo->abbrev);
5391
5392         /*
5393          * XXX - we can't use the "val_to_string_repr" and "string_repr_len"
5394          * functions for FT_UINT and FT_INT types, as we choose the base in
5395          * the string expression based on the display base of the field.
5396          *
5397          * Note that the base does matter, as this is also used for
5398          * the protocolinfo tap.
5399          *
5400          * It might be nice to use them in "proto_item_fill_label()"
5401          * as well, although, there, you'd have to deal with the base
5402          * *and* with resolved values for addresses.
5403          *
5404          * Perhaps we need two different val_to_string routines, one
5405          * to generate items for display filters and one to generate
5406          * strings for display, and pass to both of them the
5407          * "display" and "strings" values in the header_field_info
5408          * structure for the field, so they can get the base and,
5409          * if the field is Boolean or an enumerated integer type,
5410          * the tables used to generate human-readable values.
5411          */
5412         switch(hfinfo->type) {
5413
5414                 case FT_INT8:
5415                 case FT_INT16:
5416                 case FT_INT24:
5417                 case FT_INT32:
5418                         is_signed_num = TRUE;
5419                 case FT_UINT8:
5420                 case FT_UINT16:
5421                 case FT_UINT24:
5422                 case FT_UINT32:
5423                 case FT_FRAMENUM:
5424                         /*
5425                          * 4 bytes for " == ".
5426                          * 11 bytes for:
5427                          *
5428                          *      a sign + up to 10 digits of 32-bit integer,
5429                          *      in decimal;
5430                          *
5431                          *      "0x" + 8 digits of 32-bit integer, in hex;
5432                          *
5433                          *      11 digits of 32-bit integer, in octal.
5434                          *      (No, we don't do octal, but this way,
5435                          *      we know that if we do, this will still
5436                          *      work.)
5437                          *
5438                          * 1 byte for the trailing '\0'.
5439                          */
5440                         if (filter != NULL) {
5441                                 dfilter_len = abbrev_len + 4 + 11 + 1;
5442                                 *filter = ep_alloc0(dfilter_len);
5443                                 format = hfinfo_numeric_format(hfinfo);
5444                                 if(is_signed_num) {
5445                                         g_snprintf(*filter, dfilter_len, format,
5446                                                    hfinfo->abbrev,
5447                                                    fvalue_get_sinteger(&finfo->value));
5448                                 } else {
5449                                         g_snprintf(*filter, dfilter_len, format,
5450                                                    hfinfo->abbrev,
5451                                                    fvalue_get_uinteger(&finfo->value));
5452                                 }
5453                         }
5454                         break;
5455
5456                 case FT_INT64:
5457                 case FT_UINT64:
5458                         /*
5459                          * 4 bytes for " == ".
5460                          * 22 bytes for:
5461                          *
5462                          *      a sign + up to 20 digits of 32-bit integer,
5463                          *      in decimal;
5464                          *
5465                          *      "0x" + 16 digits of 32-bit integer, in hex;
5466                          *
5467                          *      22 digits of 32-bit integer, in octal.
5468                          *      (No, we don't do octal, but this way,
5469                          *      we know that if we do, this will still
5470                          *      work.)
5471                          *
5472                          * 1 byte for the trailing '\0'.
5473                          */
5474                         if (filter != NULL) {
5475                                 dfilter_len = abbrev_len + 4 + 22 + 1;
5476                                 *filter = ep_alloc0(dfilter_len);
5477                                 format = hfinfo_numeric_format(hfinfo);
5478                                 g_snprintf(*filter, dfilter_len, format,
5479                                     hfinfo->abbrev,
5480                                     fvalue_get_integer64(&finfo->value));
5481                         }
5482                         break;
5483
5484                 case FT_PROTOCOL:
5485                         if (filter != NULL)
5486                                 *filter = ep_strdup(finfo->hfinfo->abbrev);
5487                         break;
5488
5489                 case FT_NONE:
5490                 case FT_PCRE:
5491                         /*
5492                          * If the length is 0, just match the name of the
5493                          * field.
5494                          *
5495                          * (Also check for negative values, just in case,
5496                          * as we'll cast it to an unsigned value later.)
5497                          */
5498                         length = finfo->length;
5499                         if (length == 0) {
5500                                 if (filter != NULL)
5501                                         *filter = ep_strdup(finfo->hfinfo->abbrev);
5502                                 break;
5503                         }
5504                         if (length < 0)
5505                                 return FALSE;
5506
5507                         /*
5508                          * This doesn't have a value, so we'd match
5509                          * on the raw bytes at this address.
5510                          *
5511                          * Should we be allowed to access to the raw bytes?
5512                          * If "edt" is NULL, the answer is "no".
5513                          */
5514                         if (edt == NULL)
5515                                 return FALSE;
5516
5517                         /*
5518                          * Is this field part of the raw frame tvbuff?
5519                          * If not, we can't use "frame[N:M]" to match
5520                          * it.
5521                          *
5522                          * XXX - should this be frame-relative, or
5523                          * protocol-relative?
5524                          *
5525                          * XXX - does this fallback for non-registered
5526                          * fields even make sense?
5527                          */
5528                         if (finfo->ds_tvb != edt->tvb)
5529                                 return FALSE;   /* you lose */
5530
5531                         /*
5532                          * Don't go past the end of that tvbuff.
5533                          */
5534                         length_remaining = tvb_length_remaining(finfo->ds_tvb, finfo->start);
5535                         if (length > length_remaining)
5536                                 length = length_remaining;
5537                         if (length <= 0)
5538                                 return FALSE;
5539
5540                         if (filter != NULL) {
5541                                 start = finfo->start;
5542                                 buf_len = 32 + length * 3;
5543                                 *filter = ep_alloc0(buf_len);
5544                                 ptr = *filter;
5545
5546                                 ptr += g_snprintf(ptr, buf_len-(ptr-*filter),
5547                                     "frame[%d:%d] == ", finfo->start, length);
5548                                 for (i=0;i<length; i++) {
5549                                         c = tvb_get_guint8(finfo->ds_tvb, start);
5550                                         start++;
5551                                         if (i == 0 ) {
5552                                                 ptr += g_snprintf(ptr, buf_len-(ptr-*filter), "%02x", c);
5553                                         }
5554                                         else {
5555                                                 ptr += g_snprintf(ptr, buf_len-(ptr-*filter), ":%02x", c);
5556                                         }
5557                                 }
5558                         }
5559                         break;
5560
5561                 /* By default, use the fvalue's "to_string_repr" method. */
5562                 default:
5563                         /* Figure out the string length needed.
5564                          *      The ft_repr length.
5565                          *      4 bytes for " == ".
5566                          *      1 byte for trailing NUL.
5567                          */
5568                         if (filter != NULL) {
5569                                 dfilter_len = fvalue_string_repr_len(&finfo->value,
5570                                                 FTREPR_DFILTER);
5571                                 dfilter_len += abbrev_len + 4 + 1;
5572                                 *filter = ep_alloc0(dfilter_len);
5573
5574                                 /* Create the string */
5575                                 g_snprintf(*filter, dfilter_len, "%s == ",
5576                                     hfinfo->abbrev);
5577                                 fvalue_to_string_repr(&finfo->value,
5578                                     FTREPR_DFILTER,
5579                                     &(*filter)[abbrev_len + 4]);
5580                         }
5581                         break;
5582         }
5583
5584         return TRUE;
5585 }
5586
5587 /*
5588  * Returns TRUE if we can do a "match selected" on the field, FALSE
5589  * otherwise.
5590  */
5591 gboolean
5592 proto_can_match_selected(field_info *finfo, epan_dissect_t *edt)
5593 {
5594         return construct_match_selected_string(finfo, edt, NULL);
5595 }
5596
5597 /* This function attempts to construct a "match selected" display filter
5598  * string for the specified field; if it can do so, it returns a pointer
5599  * to the string, otherwise it returns NULL.
5600  *
5601  * The string is allocated with packet lifetime scope.
5602  * You do not need to [g_]free() this string since it will be automatically
5603  * freed once the next packet is dissected.
5604  */
5605 char*
5606 proto_construct_match_selected_string(field_info *finfo, epan_dissect_t *edt)
5607 {
5608         char *filter;
5609
5610         if (!construct_match_selected_string(finfo, edt, &filter))
5611                 return NULL;
5612         return filter;
5613 }
5614
5615
5616 /* This function will dissect a sequence of bytes that describe a
5617  * bitmask.
5618  * hf_hdr is a 8/16/24/32 bit integer that describes the bitmask to be dissected.
5619  * This field will form an expansion under which the individual fields of the
5620  * bitmask is dissected and displayed.
5621  * This field must be of the type FT_[U]INT{8|16|24|32}.
5622  *
5623  * fields is an array of pointers to int that lists all the fields of the
5624  * bitmask. These fields can be either of the type FT_BOOLEAN for flags
5625  * or another integer of the same type/size as hf_hdr with a mask specified.
5626  * This array is terminated by a NULL entry.
5627  *
5628  * FT_BOOLEAN bits that are set to 1 will have the name added to the expansion.
5629  * FT_integer fields that have a value_string attached will have the
5630  * matched string displayed on the expansion line.
5631  */
5632 proto_item *
5633 proto_tree_add_bitmask(proto_tree *parent_tree, tvbuff_t *tvb, int offset, int hf_hdr, gint ett, const int **fields, gboolean little_endian)
5634 {
5635         proto_tree *tree=NULL;
5636         proto_item *item=NULL;
5637         header_field_info *hf_info;
5638         int len=0;
5639         guint32 value=0;
5640
5641         hf_info=proto_registrar_get_nth(hf_hdr);
5642         switch(hf_info->type){
5643         case FT_INT8:
5644         case FT_UINT8:
5645                 len=1;
5646                 value=tvb_get_guint8(tvb, offset);
5647                 break;
5648         case FT_INT16:
5649         case FT_UINT16:
5650                 len=2;
5651                 if(little_endian){
5652                         value=tvb_get_letohs(tvb, offset);
5653                 } else {
5654                         value=tvb_get_ntohs(tvb, offset);
5655                 }
5656                 break;
5657         case FT_INT24:
5658         case FT_UINT24:
5659                 len=3;
5660                 if(little_endian){
5661                         value=tvb_get_letoh24(tvb, offset);
5662                 } else {
5663                         value=tvb_get_ntoh24(tvb, offset);
5664                 }
5665                 break;
5666         case FT_INT32:
5667         case FT_UINT32:
5668                 len=4;
5669                 if(little_endian){
5670                         value=tvb_get_letohl(tvb, offset);
5671                 } else {
5672                         value=tvb_get_ntohl(tvb, offset);
5673                 }
5674                 break;
5675         default:
5676                 g_assert_not_reached();
5677         }
5678
5679         if(parent_tree){
5680                 item=proto_tree_add_item(parent_tree, hf_hdr, tvb, offset, len, little_endian);
5681                 tree=proto_item_add_subtree(item, ett);
5682         }
5683
5684         while(*fields){
5685                 header_field_info *hf_field;
5686                 guint32 tmpval, tmpmask;
5687
5688                 hf_field=proto_registrar_get_nth(**fields);
5689                 switch(hf_field->type){
5690                 case FT_INT8:
5691                 case FT_UINT8:
5692                 case FT_INT16:
5693                 case FT_UINT16:
5694                 case FT_INT24:
5695                 case FT_UINT24:
5696                 case FT_INT32:
5697                 case FT_UINT32:
5698                         proto_tree_add_item(tree, **fields, tvb, offset, len, little_endian);
5699
5700                         /* Mask and shift out the value */
5701                         tmpmask=hf_field->bitmask;
5702                         tmpval=value;
5703                         if(tmpmask){
5704                                 tmpval&=tmpmask;
5705                                 while(!(tmpmask&0x00000001)){
5706                                         tmpval>>=1;
5707                                         tmpmask>>=1;
5708                                 }
5709                         }
5710                         /* Show the value_string content (if there is one) */
5711                         if(hf_field->strings){
5712                                 proto_item_append_text(item, ",  %s", val_to_str(tmpval, hf_field->strings, "Unknown"));
5713                         }
5714
5715                         break;
5716                 case FT_BOOLEAN:
5717                         proto_tree_add_item(tree, **fields, tvb, offset, len, little_endian);
5718                         /* if the flag is set, show the name */
5719                         if(hf_field->bitmask&value){
5720                                 proto_item_append_text(item, ",  %s", hf_field->name);
5721                         }
5722                         break;
5723                 default:
5724                         g_assert_not_reached();
5725                 }
5726
5727                 fields++;
5728         }
5729
5730         return item;
5731 }
5732
5733 proto_item *
5734 proto_tree_add_bits_item(proto_tree *tree, int hf_index, tvbuff_t *tvb, gint bit_offset, gint no_of_bits, gboolean little_endian)
5735 {
5736         return proto_tree_add_bits_ret_val(tree, hf_index, tvb, bit_offset, no_of_bits, NULL, little_endian);
5737
5738 }
5739 /*
5740  * This function will dissect a sequence of bits that does not need to be byte aligned the bits
5741  * set vill be shown in the tree as ..10 10.. and the integer value returned if return_value is set.
5742  * Offset should be given in bits from the start of the tvb.
5743  */
5744
5745 proto_item *
5746 proto_tree_add_bits_ret_val(proto_tree *tree, int hf_index, tvbuff_t *tvb, gint bit_offset, gint no_of_bits, guint64 *return_value, gboolean little_endian)
5747 {
5748         gint    offset;
5749         guint   length;
5750         guint8  tot_no_bits;
5751         guint8  remaining_bits;
5752         guint64 mask = 0,tmp;
5753         char *str;
5754         header_field_info *hf_field;
5755         guint64 value = 0;
5756         int bit;
5757         int i;
5758
5759         hf_field = proto_registrar_get_nth(hf_index);
5760
5761         /* Byte align offset */
5762         offset = bit_offset>>3;
5763
5764
5765         /*
5766          * Calculate the number of octets used to hold the bits
5767          */
5768         tot_no_bits = ((bit_offset&0x7)+no_of_bits);
5769         length = tot_no_bits>>3;
5770         remaining_bits = tot_no_bits % 8;
5771         if ((remaining_bits)!=0)
5772                 length++;
5773
5774         if (no_of_bits < 9){
5775                 value = tvb_get_bits8(tvb, bit_offset, no_of_bits);
5776         }else if(no_of_bits < 17){
5777                 value = tvb_get_bits16(tvb, bit_offset, no_of_bits, little_endian);
5778         }else if(no_of_bits < 33){
5779                 value = tvb_get_bits32(tvb, bit_offset, no_of_bits, little_endian);
5780         }else if(no_of_bits < 65){
5781                 value = tvb_get_bits64(tvb, bit_offset, no_of_bits, little_endian);
5782         }else if(no_of_bits>64){
5783                 DISSECTOR_ASSERT_NOT_REACHED();
5784                 return NULL;
5785         }
5786
5787
5788         mask = 1;
5789         mask = mask << (no_of_bits-1);
5790
5791         /* prepare the string */
5792         str=ep_alloc(256);
5793         str[0]='\0';
5794         for(bit=0;bit<((int)(bit_offset&0x07));bit++){
5795                 if(bit&&(!(bit%4))){
5796                         strcat(str, " ");
5797                 }
5798                 strcat(str,".");
5799         }
5800         /* read the bits for the int */
5801         for(i=0;i<no_of_bits;i++){
5802                 if(bit&&(!(bit%4))){
5803                         strcat(str, " ");
5804                 }
5805                 if(bit&&(!(bit%8))){
5806                         strcat(str, " ");
5807                 }
5808                 bit++;
5809                 tmp = value & mask;
5810                 if(tmp != 0){
5811                         strcat(str, "1");
5812                 } else {
5813                         strcat(str, "0");
5814                 }
5815                 mask = mask>>1;
5816         }
5817         for(;bit%8;bit++){
5818                 if(bit&&(!(bit%4))){
5819                         strcat(str, " ");
5820                 }
5821                 strcat(str,".");
5822         }
5823
5824         if(return_value){
5825                 *return_value=value;
5826         }
5827         if(hf_index == -1)
5828                 return NULL;
5829
5830         strcat(str," = ");
5831         strcat(str,hf_field->name);
5832
5833         switch(hf_field->type){
5834         case FT_BOOLEAN:
5835                 /* Boolean field */
5836                 if (hf_field->strings) {
5837                         const true_false_string         *tfstring = &tfs_true_false;
5838                         tfstring = (const struct true_false_string*) hf_field->strings;
5839
5840                         return proto_tree_add_boolean_format(tree, hf_index, tvb, offset, length, (guint32)value,
5841                                 "%s: %s",
5842                                 str,
5843                                 (guint32)value ? tfstring->true_string : tfstring->false_string);
5844                 }else{
5845                         return proto_tree_add_boolean_format(tree, hf_index, tvb, offset, length, (guint32)value,
5846                                 "%s: %u",
5847                                 str,
5848                                 (guint32)value);
5849                 }
5850                 break;
5851         case FT_UINT8:
5852         case FT_UINT16:
5853         case FT_UINT24:
5854         case FT_UINT32:
5855                 /* 1 - 32 bits field */
5856                 if (hf_field->strings) {
5857                         return proto_tree_add_uint_format(tree, hf_index, tvb, offset, length, (guint32)value,
5858                                                   "%s: %s (%u)",
5859                                                   str,
5860                                                   val_to_str((guint32)value, cVALS(hf_field->strings), "Unknown "),
5861                                                   (guint32)value);
5862                         break;
5863                 }
5864                 switch(hf_field->display){
5865                         case BASE_DEC:
5866                                 return proto_tree_add_uint_format(tree, hf_index, tvb, offset, length, (guint32)value,
5867                                          "%s: %u",
5868                                                   str,
5869                                                   (guint32)value);
5870                                 break;
5871                         case BASE_HEX:
5872                                 return proto_tree_add_uint_format(tree, hf_index, tvb, offset, length, (guint32)value,
5873                                      "%s: 0x%x",
5874                                                   str,
5875                                                   (guint32)value);
5876                                 break;
5877                         default:
5878                                 DISSECTOR_ASSERT_NOT_REACHED();
5879                                 return NULL;
5880                                 break;
5881                 }
5882                 break;
5883         case FT_UINT64:
5884                 switch(hf_field->display){
5885                         case BASE_DEC:
5886                                 return proto_tree_add_uint64_format(tree, hf_index, tvb, offset, length, value,
5887                                          "%s: %" G_GINT64_MODIFIER "u",
5888                                                   str, value);
5889                                 break;
5890                         case BASE_HEX:
5891                                 return proto_tree_add_uint64_format(tree, hf_index, tvb, offset, length, value,
5892                                      "%s: 0x%" G_GINT64_MODIFIER "x",
5893                                                   str, value);
5894                                 break;
5895                         default:
5896                                 DISSECTOR_ASSERT_NOT_REACHED();
5897                                 return NULL;
5898                                 break;
5899                 }
5900                 break;
5901         default:
5902                 DISSECTOR_ASSERT_NOT_REACHED();
5903                 return NULL;
5904                 break;
5905         }
5906
5907 }