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