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