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