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