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