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