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