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