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