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