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