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