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