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