From Richard van der Hoff:
[obnox/wireshark/wip.git] / epan / proto.c
1 /* proto.c
2  * Routines for protocol tree
3  *
4  * $Id$
5  *
6  * Ethereal - Network traffic analyzer
7  * By Gerald Combs <gerald@ethereal.com>
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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, 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 #ifdef NEED_SNPRINTF_H
36 # include "snprintf.h"
37 #endif
38
39 #include "packet.h"
40 #include "strutil.h"
41 #include "addr_resolv.h"
42 #include "plugins.h"
43 #include "ipv6-utils.h"
44 #include "proto.h"
45 #include "epan_dissect.h"
46 #include "slab.h"
47 #include "tvbuff.h"
48
49 #define cVALS(x) (const value_string*)(x)
50
51 #if 1
52 #define TRY_TO_FAKE_THIS_ITEM(tree, hfindex) \
53         /* If this item is not referenced we dont have to do much work  \
54            at all but we should still return a node so that             \
55            field items below this node ( think proto_item_add_subtree() )\
56            will still have somewhere to attach to                       \
57            or else filtering will not work (they would be ignored since tree\
58            would be NULL).                                              \
59            DONT try to fake a node where PITEM_FINFO(pi) is NULL        \
60            since dissectors that want to do proto_item_set_len() ot     \
61            other operations that dereference this would crash.          \
62            We dont fake FT_PROTOCOL either since these are cheap and    \
63            some stuff (proto hier stat) assumes they always exist.      \
64         */                                                              \
65         if(!(PTREE_DATA(tree)->visible)){                               \
66                 if(PITEM_FINFO(tree)){                                  \
67                         register header_field_info *hfinfo;             \
68                         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);       \
69                         if((hfinfo->ref_count == 0)                     \
70                         && (hfinfo->type!=FT_PROTOCOL)){                \
71                                 /* just return tree back to the caller */\
72                                 return tree;                            \
73                         }                                               \
74                 }                                                       \
75         }
76 #else
77 #define TRY_TO_FAKE_THIS_ITEM(tree, hfindex) ;
78 #endif
79
80 static gboolean
81 proto_tree_free_node(proto_node *node, gpointer data);
82
83 static void fill_label_boolean(field_info *fi, gchar *label_str);
84 static void fill_label_uint(field_info *fi, gchar *label_str);
85 static void fill_label_uint64(field_info *fi, gchar *label_str);
86 static void fill_label_enumerated_uint(field_info *fi, gchar *label_str);
87 static void fill_label_enumerated_bitfield(field_info *fi, gchar *label_str);
88 static void fill_label_numeric_bitfield(field_info *fi, gchar *label_str);
89 static void fill_label_int(field_info *fi, gchar *label_str);
90 static void fill_label_int64(field_info *fi, gchar *label_str);
91 static void fill_label_enumerated_int(field_info *fi, gchar *label_str);
92
93 int hfinfo_bitwidth(header_field_info *hfinfo);
94 static char* hfinfo_uint_vals_format(header_field_info *hfinfo);
95 static char* hfinfo_uint_format(header_field_info *hfinfo);
96 static char* hfinfo_uint64_format(header_field_info *hfinfo);
97 static char* hfinfo_int_vals_format(header_field_info *hfinfo);
98 static char* hfinfo_int_format(header_field_info *hfinfo);
99 static char* hfinfo_int64_format(header_field_info *hfinfo);
100
101 static proto_item*
102 proto_tree_add_node(proto_tree *tree, field_info *fi);
103
104 static field_info *
105 alloc_field_info(proto_tree *tree, int hfindex, tvbuff_t *tvb,
106         gint start, gint *length);
107
108 static proto_item *
109 proto_tree_add_pi(proto_tree *tree, int hfindex, tvbuff_t *tvb,
110         gint start, gint *length, field_info **pfi);
111
112 static void
113 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap);
114
115 static void
116 proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb);
117 static void
118 proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length);
119 static void
120 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length);
121 static void
122 proto_tree_set_time(field_info *fi, nstime_t *value_ptr);
123 static void
124 proto_tree_set_string(field_info *fi, const char* value, gboolean);
125 static void
126 proto_tree_set_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
127 static void
128 proto_tree_set_ether(field_info *fi, const guint8* value);
129 static void
130 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start);
131 static void
132 proto_tree_set_ipxnet(field_info *fi, guint32 value);
133 static void
134 proto_tree_set_ipv4(field_info *fi, guint32 value);
135 static void
136 proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr);
137 static void
138 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start);
139 static void
140 proto_tree_set_guid(field_info *fi, const guint8* value_ptr);
141 static void
142 proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, gint start);
143 static void
144 proto_tree_set_boolean(field_info *fi, guint32 value);
145 static void
146 proto_tree_set_float(field_info *fi, float value);
147 static void
148 proto_tree_set_double(field_info *fi, double value);
149 static void
150 proto_tree_set_uint(field_info *fi, guint32 value);
151 static void
152 proto_tree_set_int(field_info *fi, gint32 value);
153 static void
154 proto_tree_set_uint64(field_info *fi, guint64 value);
155 static void
156 proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start, gboolean little_endian);
157
158 static int proto_register_field_init(header_field_info *hfinfo, int parent);
159
160 /* Comparision function for tree insertion. A wrapper around strcmp() */
161 static int g_strcmp(gconstpointer a, gconstpointer b);
162
163 /* special-case header field used within proto.c */
164 int hf_text_only = -1;
165
166 /* Structure for information about a protocol */
167 struct _protocol {
168         const char *name;               /* long description */
169         const char *short_name;         /* short description */
170         const char *filter_name;        /* name of this protocol in filters */
171         int     proto_id;               /* field ID for this protocol */
172         GList   *fields;                /* fields for this protocol */
173         GList   *last_field;            /* pointer to end of list of fields */
174         gboolean is_enabled;            /* TRUE if protocol is enabled */
175         gboolean can_toggle;            /* TRUE if is_enabled can be changed */
176 };
177
178 /* List of all protocols */
179 static GList *protocols = NULL;
180
181 #define INITIAL_NUM_PROTOCOL_HFINFO     200
182
183
184 /* Contains information about protocols and header fields. Used when
185  * dissectors register their data */
186 static GMemChunk *gmc_hfinfo = NULL;
187
188 /* Contains information about a field when a dissector calls
189  * proto_tree_add_item.  */
190 SLAB_ITEM_TYPE_DEFINE(field_info)
191 static SLAB_FREE_LIST_DEFINE(field_info)
192 static field_info *field_info_tmp=NULL;
193 #define FIELD_INFO_NEW(fi)                                      \
194         SLAB_ALLOC(fi, field_info)
195 #define FIELD_INFO_FREE(fi)                                     \
196         SLAB_FREE(fi, field_info)
197
198
199
200 /* Contains the space for proto_nodes. */
201 SLAB_ITEM_TYPE_DEFINE(proto_node)
202 static SLAB_FREE_LIST_DEFINE(proto_node)
203 #define PROTO_NODE_NEW(node)                            \
204         SLAB_ALLOC(node, proto_node)                    \
205         node->first_child = NULL;                       \
206         node->last_child = NULL;                        \
207         node->next = NULL;
208
209 #define PROTO_NODE_FREE(node)                           \
210         SLAB_FREE(node, proto_node)
211
212
213
214 /* String space for protocol and field items for the GUI */
215 SLAB_ITEM_TYPE_DEFINE(item_label_t)
216 static SLAB_FREE_LIST_DEFINE(item_label_t)
217 #define ITEM_LABEL_NEW(il)                              \
218         SLAB_ALLOC(il, item_label_t)
219 #define ITEM_LABEL_FREE(il)                             \
220         SLAB_FREE(il, item_label_t)
221
222
223 #define PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo) \
224         DISSECTOR_ASSERT((guint)hfindex < gpa_hfinfo.len); \
225         hfinfo=gpa_hfinfo.hfi[hfindex];         
226
227
228 /* List which stores protocols and fields that have been registered */
229 typedef struct _gpa_hfinfo_t {
230         guint32 len;
231         guint32 allocated_len;
232         header_field_info **hfi;
233 } gpa_hfinfo_t;
234 gpa_hfinfo_t gpa_hfinfo;
235
236 /* Balanced tree of abbreviations and IDs */
237 static GTree *gpa_name_tree = NULL;
238
239 /* Points to the first element of an array of Booleans, indexed by
240    a subtree item type; that array element is TRUE if subtrees of
241    an item of that type are to be expanded. */
242 gboolean        *tree_is_expanded;
243
244 /* Number of elements in that array. */
245 int             num_tree_types;
246
247 /* Name hashtables for fast detection of duplicate names */
248 static GHashTable* proto_names = NULL;
249 static GHashTable* proto_short_names = NULL;
250 static GHashTable* proto_filter_names = NULL;
251
252 static gint
253 proto_compare_name(gconstpointer p1_arg, gconstpointer p2_arg)
254 {
255         const protocol_t *p1 = p1_arg;
256         const protocol_t *p2 = p2_arg;
257
258         return g_strcasecmp(p1->short_name, p2->short_name);
259 }
260
261
262 /* initialize data structures and register protocols and fields */
263 void
264 proto_init(const char *plugin_dir
265 #ifndef HAVE_PLUGINS
266                                  _U_
267 #endif
268            ,
269            void (register_all_protocols)(void),
270            void (register_all_protocol_handoffs)(void))
271 {
272         static hf_register_info hf[] = {
273                 { &hf_text_only,
274                 { "",   "", FT_NONE, BASE_NONE, NULL, 0x0,
275                         NULL, HFILL }},
276         };
277
278
279     proto_names = g_hash_table_new(g_int_hash, g_int_equal);
280     proto_short_names = g_hash_table_new(g_int_hash, g_int_equal);
281     proto_filter_names = g_hash_table_new(g_int_hash, g_int_equal);
282
283         proto_cleanup();
284
285         gmc_hfinfo = g_mem_chunk_new("gmc_hfinfo",
286                 sizeof(header_field_info),
287         INITIAL_NUM_PROTOCOL_HFINFO * sizeof(header_field_info),
288         G_ALLOC_ONLY);
289
290         gpa_hfinfo.len=0;
291         gpa_hfinfo.allocated_len=0;
292         gpa_hfinfo.hfi=NULL;
293         gpa_name_tree = g_tree_new(g_strcmp);
294
295         /* Initialize the ftype subsystem */
296         ftypes_initialize();
297
298         /* Register one special-case FT_TEXT_ONLY field for use when
299            converting ethereal to new-style proto_tree. These fields
300            are merely strings on the GUI tree; they are not filterable */
301         proto_register_field_array(-1, hf, array_length(hf));
302
303         /* Have each built-in dissector register its protocols, fields,
304            dissector tables, and dissectors to be called through a
305            handle, and do whatever one-time initialization it needs to
306            do. */
307         register_all_protocols();
308
309 #ifdef HAVE_PLUGINS
310         /* Now scan for plugins and load all the ones we find, calling
311            their register routines to do the stuff described above. */
312         init_plugins(plugin_dir);
313 #endif
314
315         /* Now call the "handoff registration" routines of all built-in
316            dissectors; those routines register the dissector in other
317            dissectors' handoff tables, and fetch any dissector handles
318            they need. */
319         register_all_protocol_handoffs();
320
321 #ifdef HAVE_PLUGINS
322         /* Now do the same with plugins. */
323         register_all_plugin_handoffs();
324 #endif
325
326     /* sort the protocols by protocol name */
327     protocols = g_list_sort(protocols, proto_compare_name);
328
329         /* We've assigned all the subtree type values; allocate the array
330            for them, and zero it out. */
331         tree_is_expanded = g_malloc(num_tree_types*sizeof (gint *));
332         memset(tree_is_expanded, 0, num_tree_types*sizeof (gint *));
333 }
334
335 /* String comparison func for dfilter_token GTree */
336 static int
337 g_strcmp(gconstpointer a, gconstpointer b)
338 {
339         return strcmp((const char*)a, (const char*)b);
340 }
341
342 void
343 proto_cleanup(void)
344 {
345         /* Free the abbrev/ID GTree */
346         if (gpa_name_tree) {
347                 g_tree_destroy(gpa_name_tree);
348                 gpa_name_tree = NULL;
349         }
350
351         if (gmc_hfinfo)
352                 g_mem_chunk_destroy(gmc_hfinfo);
353
354         if(gpa_hfinfo.allocated_len){
355                 gpa_hfinfo.len=0;
356                 gpa_hfinfo.allocated_len=0;
357                 g_free(gpa_hfinfo.hfi);
358                 gpa_hfinfo.hfi=NULL;
359         }
360         if (tree_is_expanded != NULL)
361                 g_free(tree_is_expanded);
362
363 }
364
365 typedef gboolean (*proto_tree_traverse_func)(proto_node *, gpointer);
366
367 static gboolean
368 proto_tree_traverse_pre_order(proto_tree *tree, proto_tree_traverse_func func,
369     gpointer data)
370 {
371         proto_node *pnode = tree;
372         proto_node *child;
373         proto_node *current;
374
375         if (func(pnode, data))
376                 return TRUE;
377
378         child = pnode->first_child;
379         while (child != NULL) {
380                 /*
381                  * The routine we call might modify the child, e.g. by
382                  * freeing it, so we get the child's successor before
383                  * calling that routine.
384                  */
385                 current = child;
386                 child = current->next;
387                 if (proto_tree_traverse_pre_order((proto_tree *)current, func,
388                     data))
389                         return TRUE;
390         }
391
392         return FALSE;
393 }
394
395 static gboolean
396 proto_tree_traverse_in_order(proto_tree *tree, proto_tree_traverse_func func,
397     gpointer data)
398 {
399         proto_node *pnode = tree;
400         proto_node *child;
401         proto_node *current;
402
403         child = pnode->first_child;
404         if (child != NULL) {
405                 /*
406                  * The routine we call might modify the child, e.g. by
407                  * freeing it, so we get the child's successor before
408                  * calling that routine.
409                  */
410                 current = child;
411                 child = current->next;
412
413                 if (proto_tree_traverse_in_order((proto_tree *)current, func,
414                     data))
415                         return TRUE;
416
417                 if (func(pnode, data))
418                         return TRUE;
419
420                 while (child != NULL) {
421                         /*
422                          * The routine we call might modify the child, e.g. by
423                          * freeing it, so we get the child's successor before
424                          * calling that routine.
425                          */
426                         current = child;
427                         child = current->next;
428                         if (proto_tree_traverse_in_order((proto_tree *)current,
429                             func, data))
430                                 return TRUE;
431                 }
432         } else {
433                 if (func(pnode, data))
434                         return TRUE;
435         }
436
437         return FALSE;
438 }
439
440 void
441 proto_tree_children_foreach(proto_tree *tree, proto_tree_foreach_func func,
442     gpointer data)
443 {
444         proto_node *node = tree;
445         proto_node *current;
446
447         node = node->first_child;
448         while (node != NULL) {
449                 current = node;
450                 node = current->next;
451                 func((proto_tree *)current, data);
452         }
453 }
454
455 /* frees the resources that the dissection a proto_tree uses */
456 void
457 proto_tree_free(proto_tree *tree)
458 {
459         proto_tree_traverse_in_order(tree, proto_tree_free_node, NULL);
460 }
461
462 static void
463 free_GPtrArray_value(gpointer key _U_, gpointer value, gpointer user_data _U_)
464 {
465         GPtrArray   *ptrs = value;
466         gint hfid = (gint)key;
467         header_field_info *hfinfo;
468
469         
470         PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
471         if(hfinfo->ref_count){
472                 /* when a field is referenced by a filter this also 
473                    affects the refcount for the parent protocol so we need
474                    to adjust the refcount for the parent as well
475                 */
476                 if( (hfinfo->parent != -1) && (hfinfo->ref_count) ){
477                         header_field_info *parent_hfinfo;
478                         PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
479                         parent_hfinfo->ref_count -= hfinfo->ref_count;
480                 }
481                 hfinfo->ref_count = 0;
482         }
483
484         g_ptr_array_free(ptrs, TRUE);
485 }
486
487 static void
488 free_node_tree_data(tree_data_t *tree_data)
489 {
490         /* Free all the GPtrArray's in the interesting_hfids hash. */
491         g_hash_table_foreach(tree_data->interesting_hfids,
492             free_GPtrArray_value, NULL);
493
494         /* And then destroy the hash. */
495         g_hash_table_destroy(tree_data->interesting_hfids);
496
497         /* And finally the tree_data_t itself. */
498         g_free(tree_data);
499 }
500
501 #define FREE_NODE_FIELD_INFO(finfo)     \
502         if(finfo->rep){                 \
503                 ITEM_LABEL_FREE(finfo->rep);    \
504         }                               \
505         FVALUE_CLEANUP(&finfo->value);  \
506         FIELD_INFO_FREE(finfo);
507
508 static gboolean
509 proto_tree_free_node(proto_node *node, gpointer data _U_)
510 {
511         field_info *finfo = PITEM_FINFO(node);
512
513         if (finfo == NULL) {
514                 /* This is the root node. Destroy the per-tree data.
515                  * There is no field_info to destroy. */
516                 free_node_tree_data(PTREE_DATA(node));
517         }
518         else {
519                 /* This is a child node. Don't free the per-tree data, but
520                  * do free the field_info data. */
521                 FREE_NODE_FIELD_INFO(finfo);
522         }
523
524         /* Free the proto_node. */
525         PROTO_NODE_FREE(node);
526
527         return FALSE; /* FALSE = do not end traversal of protocol tree */
528 }
529
530 /* Is the parsing being done for a visible proto_tree or an invisible one?
531  * By setting this correctly, the proto_tree creation is sped up by not
532  * having to call vsnprintf and copy strings around.
533  */
534 void
535 proto_tree_set_visible(proto_tree *tree, gboolean visible)
536 {
537         PTREE_DATA(tree)->visible = visible;
538 }
539
540 /* Assume dissector set only its protocol fields.
541    This function is called by dissectors and allowes to speed up filtering
542    in ethereal, if this function returns FALSE it is safe to reset tree to NULL
543    and thus skip calling most of the expensive proto_tree_add_...()
544    functions.
545    If the tree is visible we implicitely assume the field is referenced.
546 */
547 gboolean
548 proto_field_is_referenced(proto_tree *tree, int proto_id)
549 {
550         register header_field_info *hfinfo;
551
552
553         if (!tree)
554                 return FALSE;
555
556         if (PTREE_DATA(tree)->visible)
557                 return TRUE;
558
559         PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
560         if (hfinfo->ref_count != 0)
561                 return TRUE;
562
563         return FALSE;
564 }
565
566
567 /* Finds a record in the hf_info_records array by id. */
568 header_field_info*
569 proto_registrar_get_nth(guint hfindex)
570 {
571         register header_field_info      *hfinfo;
572
573         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
574         return hfinfo;
575 }
576
577 /* Finds a record in the hf_info_records array by name.
578  */
579 header_field_info*
580 proto_registrar_get_byname(const char *field_name)
581 {
582         DISSECTOR_ASSERT(field_name != NULL);
583         return g_tree_lookup(gpa_name_tree, field_name);
584 }
585
586 /* Add a text-only node, leaving it to our caller to fill the text in */
587 static proto_item *
588 proto_tree_add_text_node(proto_tree *tree, tvbuff_t *tvb, gint start, gint length)
589 {
590         proto_item      *pi;
591
592         pi = proto_tree_add_pi(tree, hf_text_only, tvb, start, &length, NULL);
593         if (pi == NULL)
594                 return(NULL);
595
596         return pi;
597 }
598
599 /* Add a text-only node to the proto_tree */
600 proto_item *
601 proto_tree_add_text(proto_tree *tree, tvbuff_t *tvb, gint start, gint length,
602         const char *format, ...)
603 {
604         proto_item      *pi;
605         va_list         ap;
606
607         pi = proto_tree_add_text_node(tree, tvb, start, length);
608         if (pi == NULL)
609                 return(NULL);
610
611         va_start(ap, format);
612         proto_tree_set_representation(pi, format, ap);
613         va_end(ap);
614
615         return pi;
616 }
617
618 /* Add a text-only node to the proto_tree (va_list version) */
619 proto_item *
620 proto_tree_add_text_valist(proto_tree *tree, tvbuff_t *tvb, gint start,
621         gint length, const char *format, va_list ap)
622 {
623         proto_item      *pi;
624
625         pi = proto_tree_add_text_node(tree, tvb, start, length);
626         if (pi == NULL)
627                 return(NULL);
628
629         proto_tree_set_representation(pi, format, ap);
630
631         return pi;
632 }
633
634 /* Add a text-only node for debugging purposes. The caller doesn't need
635  * to worry about tvbuff, start, or length. Debug message gets sent to
636  * STDOUT, too */
637 proto_item *
638 proto_tree_add_debug_text(proto_tree *tree, const char *format, ...)
639 {
640         proto_item      *pi;
641         va_list         ap;
642
643         pi = proto_tree_add_text_node(tree, NULL, 0, 0);
644         if (pi == NULL)
645                 return(NULL);
646
647         va_start(ap, format);
648         proto_tree_set_representation(pi, format, ap);
649         vprintf(format, ap);
650         va_end(ap);
651         printf("\n");
652
653         return pi;
654 }
655
656
657 static guint32
658 get_uint_value(tvbuff_t *tvb, gint offset, gint length, gboolean little_endian)
659 {
660         guint32 value;
661
662         switch (length) {
663
664         case 1:
665                 value = tvb_get_guint8(tvb, offset);
666                 break;
667
668         case 2:
669                 value = little_endian ? tvb_get_letohs(tvb, offset)
670                                       : tvb_get_ntohs(tvb, offset);
671                 break;
672
673         case 3:
674                 value = little_endian ? tvb_get_letoh24(tvb, offset)
675                                       : tvb_get_ntoh24(tvb, offset);
676                 break;
677
678         case 4:
679                 value = little_endian ? tvb_get_letohl(tvb, offset)
680                                       : tvb_get_ntohl(tvb, offset);
681                 break;
682
683         default:
684                 THROW(ReportedBoundsError);
685                 value = 0;
686                 break;
687         }
688         return value;
689 }
690
691 static gint32
692 get_int_value(tvbuff_t *tvb, gint offset, gint length, gboolean little_endian)
693 {
694         gint32 value;
695
696         switch (length) {
697
698         case 1:
699                 value = (gint8)tvb_get_guint8(tvb, offset);
700                 break;
701
702         case 2:
703                 value = (gint16) (little_endian ? tvb_get_letohs(tvb, offset)
704                                                 : tvb_get_ntohs(tvb, offset));
705                 break;
706
707         case 3:
708                 value = little_endian ? tvb_get_letoh24(tvb, offset)
709                                       : tvb_get_ntoh24(tvb, offset);
710                 if (value & 0x00800000) {
711                         /* Sign bit is set; sign-extend it. */
712                         value |= 0xFF000000;
713                 }
714                 break;
715
716         case 4:
717                 value = little_endian ? tvb_get_letohl(tvb, offset)
718                                       : tvb_get_ntohl(tvb, offset);
719                 break;
720
721         default:
722                 THROW(ReportedBoundsError);
723                 value = 0;
724                 break;
725         }
726         return value;
727 }
728
729 /* Add an item to a proto_tree, using the text label registered to that item;
730    the item is extracted from the tvbuff handed to it. */
731 proto_item *
732 proto_tree_add_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
733     gint start, gint length, gboolean little_endian)
734 {
735         field_info      *new_fi;
736         proto_item      *pi;
737         guint32         value, n;
738         float           floatval;
739         double          doubleval;
740         char            *string;
741         GHashTable      *hash;
742         GPtrArray       *ptrs;
743
744         if (!tree)
745                 return(NULL);
746
747         TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
748
749         new_fi = alloc_field_info(tree, hfindex, tvb, start, &length);
750
751         if (new_fi == NULL)
752                 return(NULL);
753
754         /* there is a possibility here that we might raise an exception
755          * and thus would lose track of the field_info.
756          * store it in a temp so that if we come here again we can reclaim
757          * the field_info without leaking memory.
758          */
759         /* XXX this only keeps track of one field_info struct,
760            if we ever go multithreaded for calls to this function
761            we have to change this code to use per thread variable.
762         */
763         if(field_info_tmp){
764                 /* oops, last one we got must have been lost due
765                  * to an exception.
766                  * good thing we saved it, now we can reverse the
767                  * memory leak and reclaim it.
768                  */
769                 SLAB_FREE(field_info_tmp, field_info);
770         }
771         /* we might throw an exception, keep track of this one
772          * across the "dangerous" section below.
773         */
774         field_info_tmp=new_fi;
775
776         switch(new_fi->hfinfo->type) {
777                 case FT_NONE:
778                         /* no value to set for FT_NONE */
779                         break;
780
781                 case FT_PROTOCOL:
782                         proto_tree_set_protocol_tvb(new_fi, tvb);
783                         break;
784
785                 case FT_BYTES:
786                         proto_tree_set_bytes_tvb(new_fi, tvb, start, length);
787                         break;
788
789                 case FT_UINT_BYTES:
790                         n = get_uint_value(tvb, start, length, little_endian);
791                         proto_tree_set_bytes_tvb(new_fi, tvb, start + length, n);
792
793                         /* Instead of calling proto_item_set_len(), since we don't yet
794                          * have a proto_item, we set the field_info's length ourselves. */
795                         new_fi->length = n + length;
796                         break;
797
798                 case FT_BOOLEAN:
799                         proto_tree_set_boolean(new_fi,
800                             get_uint_value(tvb, start, length, little_endian));
801                         break;
802
803                 /* XXX - make these just FT_UINT? */
804                 case FT_UINT8:
805                 case FT_UINT16:
806                 case FT_UINT24:
807                 case FT_UINT32:
808                         proto_tree_set_uint(new_fi,
809                             get_uint_value(tvb, start, length, little_endian));
810                         break;
811
812                 case FT_INT64:
813                 case FT_UINT64:
814                         DISSECTOR_ASSERT(length == 8);
815                         proto_tree_set_uint64_tvb(new_fi, tvb, start, little_endian);
816                         break;
817
818                 /* XXX - make these just FT_INT? */
819                 case FT_INT8:
820                 case FT_INT16:
821                 case FT_INT24:
822                 case FT_INT32:
823                         proto_tree_set_int(new_fi,
824                             get_int_value(tvb, start, length, little_endian));
825                         break;
826
827                 case FT_IPv4:
828                         DISSECTOR_ASSERT(length == 4);
829                         tvb_memcpy(tvb, (guint8 *)&value, start, 4);
830                         proto_tree_set_ipv4(new_fi, little_endian ? GUINT32_SWAP_LE_BE(value) : value);
831                         break;
832
833                 case FT_IPXNET:
834                         DISSECTOR_ASSERT(length == 4);
835                         proto_tree_set_ipxnet(new_fi,
836                             get_uint_value(tvb, start, 4, FALSE));
837                         break;
838
839                 case FT_IPv6:
840                         DISSECTOR_ASSERT(length == 16);
841                         proto_tree_set_ipv6_tvb(new_fi, tvb, start);
842                         break;
843
844                 case FT_ETHER:
845                         DISSECTOR_ASSERT(length == 6);
846                         proto_tree_set_ether_tvb(new_fi, tvb, start);
847                         break;
848
849                 case FT_GUID:
850                         DISSECTOR_ASSERT(length == 16);
851                         proto_tree_set_guid_tvb(new_fi, tvb, start);
852                         break;
853
854                 case FT_FLOAT:
855                         DISSECTOR_ASSERT(length == 4);
856                         if (little_endian)
857                                 floatval = tvb_get_letohieee_float(tvb, start);
858                         else
859                                 floatval = tvb_get_ntohieee_float(tvb, start);
860                         proto_tree_set_float(new_fi, floatval);
861                         break;
862
863                 case FT_DOUBLE:
864                         DISSECTOR_ASSERT(length == 8);
865                         if (little_endian)
866                                 doubleval = tvb_get_letohieee_double(tvb, start);
867                         else
868                                 doubleval = tvb_get_ntohieee_double(tvb, start);
869                         proto_tree_set_double(new_fi, doubleval);
870                         break;
871
872                 case FT_STRING:
873                         /* This g_strdup'ed memory is freed in proto_tree_free_node() */
874                         proto_tree_set_string_tvb(new_fi, tvb, start, length);
875                         break;
876
877                 case FT_STRINGZ:
878                         DISSECTOR_ASSERT(length >= -1);
879                         /* Instead of calling proto_item_set_len(),
880                          * since we don't yet have a proto_item, we
881                          * set the field_info's length ourselves.
882                          *
883                          * XXX - our caller can't use that length to
884                          * advance an offset unless they arrange that
885                          * there always be a protocol tree into which
886                          * we're putting this item.
887                          */
888                         if (length == -1) {
889                                 /* This can throw an exception */
890                                 length = tvb_strsize(tvb, start);
891
892                                 /* This g_malloc'ed memory is freed
893                                    in proto_tree_free_node() */
894                                 string = g_malloc(length);
895
896                                 tvb_memcpy(tvb, string, start, length);
897                         } else if (length == 0) {
898                                 string = g_strdup("[Empty]");
899                         } else {
900                                 /* In this case, length signifies
901                                  * the length of the string.
902                                  *
903                                  * This could either be a null-padded
904                                  * string, which doesn't necessarily
905                                  * have a '\0' at the end, or a
906                                  * null-terminated string, with a
907                                  * trailing '\0'.  (Yes, there are
908                                  * cases where you have a string
909                                  * that's both counted and null-
910                                  * terminated.)
911                                  *
912                                  * In the first case, we must
913                                  * allocate a buffer of length
914                                  * "length+1", to make room for
915                                  * a trailing '\0'.
916                                  *
917                                  * In the second case, we don't
918                                  * assume that there is a trailing
919                                  * '\0' there, as the packet might
920                                  * be malformed.  (XXX - should we
921                                  * throw an exception if there's no
922                                  * trailing '\0'?)  Therefore, we
923                                  * allocate a buffer of length
924                                  * "length+1", and put in a trailing
925                                  * '\0', just to be safe.
926                                  *
927                                  * (XXX - this would change if
928                                  * we made string values counted
929                                  * rather than null-terminated.)
930                                  */
931
932                                 /* This g_malloc'ed memory is freed
933                                  * in proto_tree_free_node() */
934                                 string = tvb_get_string(tvb, start,
935                                         length);
936                         }
937                         new_fi->length = length;
938                         proto_tree_set_string(new_fi, string, TRUE);
939                         break;
940
941                 case FT_UINT_STRING:
942                         /* This g_strdup'ed memory is freed in proto_tree_free_node() */
943                         n = get_uint_value(tvb, start, length, little_endian);
944                         proto_tree_set_string_tvb(new_fi, tvb, start + length, n);
945
946                         /* Instead of calling proto_item_set_len(), since we
947                          * don't yet have a proto_item, we set the
948                          * field_info's length ourselves.
949                          *
950                          * XXX - our caller can't use that length to
951                          * advance an offset unless they arrange that
952                          * there always be a protocol tree into which
953                          * we're putting this item.
954                          */
955                         new_fi->length = n + length;
956                         break;
957
958                 default:
959                         g_error("new_fi->hfinfo->type %d (%s) not handled\n",
960                                         new_fi->hfinfo->type,
961                                         ftype_name(new_fi->hfinfo->type));
962                         DISSECTOR_ASSERT_NOT_REACHED();
963                         break;
964         }
965
966         /* Don't add new node to proto_tree until now so that any exceptions
967          * raised by a tvbuff access method doesn't leave junk in the proto_tree. */
968         pi = proto_tree_add_node(tree, new_fi);
969
970         /* we did not raise an exception so we dont have to remember this
971          * field_info struct any more.
972          */
973         field_info_tmp=NULL;
974
975         /* If the proto_tree wants to keep a record of this finfo
976          * for quick lookup, then record it. */
977         if (new_fi->hfinfo->ref_count) {
978                 hash = PTREE_DATA(tree)->interesting_hfids;
979                 ptrs = g_hash_table_lookup(hash, GINT_TO_POINTER(hfindex));
980                 if (ptrs) {
981                         g_ptr_array_add(ptrs, new_fi);
982                 }
983         }
984
985         return pi;
986 }
987
988 proto_item *
989 proto_tree_add_item_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb,
990     gint start, gint length, gboolean little_endian)
991 {
992         proto_item      *pi;
993
994         pi = proto_tree_add_item(tree, hfindex, tvb, start, length, little_endian);
995         if (pi == NULL)
996                 return(NULL);
997
998         PROTO_ITEM_SET_HIDDEN(pi);
999
1000         return pi;
1001 }
1002
1003
1004 /* Add a FT_NONE to a proto_tree */
1005 proto_item *
1006 proto_tree_add_none_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1007                 gint length, const char *format, ...)
1008 {
1009         proto_item              *pi;
1010         va_list                 ap;
1011         header_field_info       *hfinfo;
1012
1013         if (!tree)
1014                 return (NULL);
1015
1016         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1017         DISSECTOR_ASSERT(hfinfo->type == FT_NONE);
1018
1019         pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, NULL);
1020
1021         va_start(ap, format);
1022         proto_tree_set_representation(pi, format, ap);
1023         va_end(ap);
1024
1025         /* no value to set for FT_NONE */
1026         return pi;
1027 }
1028
1029
1030 static void
1031 proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb)
1032 {
1033         fvalue_set(&fi->value, tvb, TRUE);
1034 }
1035
1036 /* Add a FT_PROTOCOL to a proto_tree */
1037 proto_item *
1038 proto_tree_add_protocol_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1039                 gint length, const char *format, ...)
1040 {
1041         proto_item              *pi;
1042         va_list                 ap;
1043         header_field_info       *hfinfo;
1044         field_info              *new_fi;
1045
1046         if (!tree)
1047                 return (NULL);
1048
1049         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1050         DISSECTOR_ASSERT(hfinfo->type == FT_PROTOCOL);
1051
1052         pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1053
1054         va_start(ap, format);
1055         proto_tree_set_representation(pi, format, ap);
1056         va_end(ap);
1057
1058         if (start == 0) {
1059                 proto_tree_set_protocol_tvb(new_fi, tvb);
1060         }
1061         else {
1062                 proto_tree_set_protocol_tvb(new_fi, NULL);
1063         }
1064         return pi;
1065 }
1066
1067
1068 /* Add a FT_BYTES to a proto_tree */
1069 proto_item *
1070 proto_tree_add_bytes(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1071                 gint length, const guint8 *start_ptr)
1072 {
1073         proto_item              *pi;
1074         field_info              *new_fi;
1075         header_field_info       *hfinfo;
1076
1077         if (!tree)
1078                 return (NULL);
1079
1080         TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1081
1082         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1083         DISSECTOR_ASSERT(hfinfo->type == FT_BYTES);
1084
1085         pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1086         proto_tree_set_bytes(new_fi, start_ptr, length);
1087
1088         return pi;
1089 }
1090
1091 proto_item *
1092 proto_tree_add_bytes_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1093                 gint length, const guint8 *start_ptr)
1094 {
1095         proto_item              *pi;
1096
1097         pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length, start_ptr);
1098         if (pi == NULL)
1099                 return (NULL);
1100
1101         PROTO_ITEM_SET_HIDDEN(pi);
1102
1103         return pi;
1104 }
1105
1106 proto_item *
1107 proto_tree_add_bytes_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1108                 gint length, const guint8 *start_ptr, const char *format, ...)
1109 {
1110         proto_item              *pi;
1111         va_list                 ap;
1112
1113         pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length, start_ptr);
1114         if (pi == NULL)
1115                 return (NULL);
1116
1117         va_start(ap, format);
1118         proto_tree_set_representation(pi, format, ap);
1119         va_end(ap);
1120
1121         return pi;
1122 }
1123
1124 static void
1125 proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length)
1126 {
1127         GByteArray              *bytes;
1128
1129         bytes = g_byte_array_new();
1130         if (length > 0) {
1131                 g_byte_array_append(bytes, start_ptr, length);
1132         }
1133         fvalue_set(&fi->value, bytes, TRUE);
1134 }
1135
1136
1137 static void
1138 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length)
1139 {
1140         proto_tree_set_bytes(fi, tvb_get_ptr(tvb, offset, length), length);
1141 }
1142
1143 /* Add a FT_*TIME to a proto_tree */
1144 proto_item *
1145 proto_tree_add_time(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1146                 nstime_t *value_ptr)
1147 {
1148         proto_item              *pi;
1149         field_info              *new_fi;
1150         header_field_info       *hfinfo;
1151
1152         if (!tree)
1153                 return (NULL);
1154
1155         TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1156
1157         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1158         DISSECTOR_ASSERT(hfinfo->type == FT_ABSOLUTE_TIME ||
1159                                 hfinfo->type == FT_RELATIVE_TIME);
1160
1161         pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1162         proto_tree_set_time(new_fi, value_ptr);
1163
1164         return pi;
1165 }
1166
1167 proto_item *
1168 proto_tree_add_time_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1169                 nstime_t *value_ptr)
1170 {
1171         proto_item              *pi;
1172
1173         pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
1174         if (pi == NULL)
1175                 return (NULL);
1176
1177         PROTO_ITEM_SET_HIDDEN(pi);
1178
1179         return pi;
1180 }
1181
1182 proto_item *
1183 proto_tree_add_time_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1184                 nstime_t *value_ptr, const char *format, ...)
1185 {
1186         proto_item              *pi;
1187         va_list                 ap;
1188
1189         pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
1190         if (pi == NULL)
1191                 return (NULL);
1192
1193         va_start(ap, format);
1194         proto_tree_set_representation(pi, format, ap);
1195         va_end(ap);
1196
1197         return pi;
1198 }
1199
1200 /* Set the FT_*TIME value */
1201 static void
1202 proto_tree_set_time(field_info *fi, nstime_t *value_ptr)
1203 {
1204         fvalue_set(&fi->value, value_ptr, FALSE);
1205 }
1206
1207 /* Add a FT_IPXNET to a proto_tree */
1208 proto_item *
1209 proto_tree_add_ipxnet(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1210                 guint32 value)
1211 {
1212         proto_item              *pi;
1213         field_info              *new_fi;
1214         header_field_info       *hfinfo;
1215
1216         if (!tree)
1217                 return (NULL);
1218
1219         TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1220
1221         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1222         DISSECTOR_ASSERT(hfinfo->type == FT_IPXNET);
1223
1224         pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1225         proto_tree_set_ipxnet(new_fi, value);
1226
1227         return pi;
1228 }
1229
1230 proto_item *
1231 proto_tree_add_ipxnet_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1232                 guint32 value)
1233 {
1234         proto_item              *pi;
1235
1236         pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
1237         if (pi == NULL)
1238                 return (NULL);
1239
1240         PROTO_ITEM_SET_HIDDEN(pi);
1241
1242         return pi;
1243 }
1244
1245 proto_item *
1246 proto_tree_add_ipxnet_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1247                 guint32 value, const char *format, ...)
1248 {
1249         proto_item              *pi;
1250         va_list                 ap;
1251
1252         pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
1253         if (pi == NULL)
1254                 return (NULL);
1255
1256         va_start(ap, format);
1257         proto_tree_set_representation(pi, format, ap);
1258         va_end(ap);
1259
1260         return pi;
1261 }
1262
1263 /* Set the FT_IPXNET value */
1264 static void
1265 proto_tree_set_ipxnet(field_info *fi, guint32 value)
1266 {
1267         fvalue_set_integer(&fi->value, value);
1268 }
1269
1270 /* Add a FT_IPv4 to a proto_tree */
1271 proto_item *
1272 proto_tree_add_ipv4(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1273                 guint32 value)
1274 {
1275         proto_item              *pi;
1276         field_info              *new_fi;
1277         header_field_info       *hfinfo;
1278
1279         if (!tree)
1280                 return (NULL);
1281
1282         TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1283
1284         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1285         DISSECTOR_ASSERT(hfinfo->type == FT_IPv4);
1286
1287         pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1288         proto_tree_set_ipv4(new_fi, value);
1289
1290         return pi;
1291 }
1292
1293 proto_item *
1294 proto_tree_add_ipv4_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1295                 guint32 value)
1296 {
1297         proto_item              *pi;
1298
1299         pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
1300         if (pi == NULL)
1301                 return (NULL);
1302
1303         PROTO_ITEM_SET_HIDDEN(pi);
1304
1305         return pi;
1306 }
1307
1308 proto_item *
1309 proto_tree_add_ipv4_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1310                 guint32 value, const char *format, ...)
1311 {
1312         proto_item              *pi;
1313         va_list                 ap;
1314
1315         pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
1316         if (pi == NULL)
1317                 return (NULL);
1318
1319         va_start(ap, format);
1320         proto_tree_set_representation(pi, format, ap);
1321         va_end(ap);
1322
1323         return pi;
1324 }
1325
1326 /* Set the FT_IPv4 value */
1327 static void
1328 proto_tree_set_ipv4(field_info *fi, guint32 value)
1329 {
1330         fvalue_set_integer(&fi->value, value);
1331 }
1332
1333 /* Add a FT_IPv6 to a proto_tree */
1334 proto_item *
1335 proto_tree_add_ipv6(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1336                 const guint8* value_ptr)
1337 {
1338         proto_item              *pi;
1339         field_info              *new_fi;
1340         header_field_info       *hfinfo;
1341
1342         if (!tree)
1343                 return (NULL);
1344
1345         TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1346
1347         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1348         DISSECTOR_ASSERT(hfinfo->type == FT_IPv6);
1349
1350         pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1351         proto_tree_set_ipv6(new_fi, value_ptr);
1352
1353         return pi;
1354 }
1355
1356 proto_item *
1357 proto_tree_add_ipv6_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1358                 const guint8* value_ptr)
1359 {
1360         proto_item              *pi;
1361
1362         pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
1363         if (pi == NULL)
1364                 return (NULL);
1365
1366         PROTO_ITEM_SET_HIDDEN(pi);
1367
1368         return pi;
1369 }
1370
1371 proto_item *
1372 proto_tree_add_ipv6_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1373                 const guint8* value_ptr, const char *format, ...)
1374 {
1375         proto_item              *pi;
1376         va_list                 ap;
1377
1378         pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
1379         if (pi == NULL)
1380                 return (NULL);
1381
1382         va_start(ap, format);
1383         proto_tree_set_representation(pi, format, ap);
1384         va_end(ap);
1385
1386         return pi;
1387 }
1388
1389 /* Set the FT_IPv6 value */
1390 static void
1391 proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr)
1392 {
1393         fvalue_set(&fi->value, (gpointer) value_ptr, FALSE);
1394 }
1395
1396 static void
1397 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start)
1398 {
1399         proto_tree_set_ipv6(fi, tvb_get_ptr(tvb, start, 16));
1400 }
1401
1402 /* Add a FT_GUID to a proto_tree */
1403 proto_item *
1404 proto_tree_add_guid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1405                 const guint8* value_ptr)
1406 {
1407         proto_item              *pi;
1408         field_info              *new_fi;
1409         header_field_info       *hfinfo;
1410
1411         if (!tree)
1412                 return (NULL);
1413
1414         TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1415
1416         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1417         DISSECTOR_ASSERT(hfinfo->type == FT_GUID);
1418
1419         pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1420         proto_tree_set_guid(new_fi, value_ptr);
1421
1422         return pi;
1423 }
1424
1425 proto_item *
1426 proto_tree_add_guid_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1427                 const guint8* value_ptr)
1428 {
1429         proto_item              *pi;
1430
1431         pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
1432         if (pi == NULL)
1433                 return (NULL);
1434
1435         PROTO_ITEM_SET_HIDDEN(pi);
1436
1437         return pi;
1438 }
1439
1440 proto_item *
1441 proto_tree_add_guid_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1442                 const guint8* value_ptr, const char *format, ...)
1443 {
1444         proto_item              *pi;
1445         va_list                 ap;
1446
1447         pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
1448         if (pi == NULL)
1449                 return (NULL);
1450
1451         va_start(ap, format);
1452         proto_tree_set_representation(pi, format, ap);
1453         va_end(ap);
1454
1455         return pi;
1456 }
1457
1458 /* Set the FT_GUID value */
1459 static void
1460 proto_tree_set_guid(field_info *fi, const guint8* value_ptr)
1461 {
1462         fvalue_set(&fi->value, (gpointer) value_ptr, FALSE);
1463 }
1464
1465 static void
1466 proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, gint start)
1467 {
1468         proto_tree_set_guid(fi, tvb_get_ptr(tvb, start, 16));
1469 }
1470
1471 static void
1472 proto_tree_set_uint64(field_info *fi, guint64 value)
1473 {
1474         fvalue_set_integer64(&fi->value, value);
1475 }
1476
1477 static void
1478 proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start, gboolean little_endian)
1479 {
1480         guint64 value;
1481
1482         value = little_endian ? tvb_get_letoh64(tvb, start)
1483                               : tvb_get_ntoh64(tvb, start);
1484
1485         proto_tree_set_uint64(fi, value);
1486 }
1487
1488 /* Add a FT_STRING or FT_STRINGZ to a proto_tree. Creates own copy of string,
1489  * and frees it when the proto_tree is destroyed. */
1490 proto_item *
1491 proto_tree_add_string(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1492                 gint length, const char* value)
1493 {
1494         proto_item              *pi;
1495         field_info              *new_fi;
1496         header_field_info       *hfinfo;
1497
1498         if (!tree)
1499                 return (NULL);
1500
1501         TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1502
1503         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1504         DISSECTOR_ASSERT(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ);
1505
1506         pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1507         DISSECTOR_ASSERT(length >= 0);
1508         proto_tree_set_string(new_fi, value, FALSE);
1509
1510         return pi;
1511 }
1512
1513 proto_item *
1514 proto_tree_add_string_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1515                 gint length, const char* value)
1516 {
1517         proto_item              *pi;
1518
1519         pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
1520         if (pi == NULL)
1521                 return (NULL);
1522
1523         PROTO_ITEM_SET_HIDDEN(pi);
1524
1525         return pi;
1526 }
1527
1528 proto_item *
1529 proto_tree_add_string_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1530                 gint length, const char* value, const char *format, ...)
1531 {
1532         proto_item              *pi;
1533         va_list                 ap;
1534
1535         pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
1536         if (pi == NULL)
1537                 return (NULL);
1538
1539         va_start(ap, format);
1540         proto_tree_set_representation(pi, format, ap);
1541         va_end(ap);
1542
1543         return pi;
1544 }
1545
1546 /* Appends string data to a FT_STRING or FT_STRINGZ, allowing progressive
1547  * field info update instead of only updating the representation as does
1548  * proto_item_append_text()
1549  */
1550 /* NOTE: this function will break with the TRY_TO_FAKE_THIS_ITEM() 
1551  * speed optimization.
1552  * Currently only WSP use this function so it is not that bad but try to 
1553  * avoid using this one if possible.
1554  * IF you must use this function you MUST also disable the 
1555  * TRY_TO_FAKE_THIS_ITEM() optimization for your dissector/function
1556  * using proto_item_append_string().
1557  * Do that by faking that the tree is visible by setting :
1558  *   PTREE_DATA(tree)->visible=1;  (see packet-wsp.c)
1559  * BEFORE you create the item you are later going to use
1560  * proto_item_append_string() on.
1561  */
1562 void
1563 proto_item_append_string(proto_item *pi, const char *str)
1564 {
1565         field_info *fi;
1566         header_field_info *hfinfo;
1567         gchar *old_str, *new_str;
1568
1569         if (!pi)
1570                 return;
1571         if (!*str)
1572                 return;
1573
1574         fi = PITEM_FINFO(pi);
1575         hfinfo = fi->hfinfo;
1576         DISSECTOR_ASSERT(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ);
1577         old_str = fvalue_get(&fi->value);
1578         new_str = g_malloc(strlen(old_str) + strlen(str) + 1);
1579         sprintf(new_str, "%s%s", old_str, str);
1580         fvalue_set(&fi->value, new_str, TRUE);
1581 }
1582
1583 /* Set the FT_STRING value */
1584 static void
1585 proto_tree_set_string(field_info *fi, const char* value,
1586                 gboolean already_allocated)
1587 {
1588         if (value)
1589                 fvalue_set(&fi->value, (gpointer) value, already_allocated);
1590         else
1591                 fvalue_set(&fi->value, (gpointer) "[ Null ]", already_allocated);
1592 }
1593
1594 static void
1595 proto_tree_set_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
1596 {
1597         gchar   *string;
1598
1599         if (length == -1) {
1600                 length = tvb_ensure_length_remaining(tvb, start);
1601         }
1602
1603         /* This memory is freed in proto_tree_free_node() */
1604         string = tvb_get_string(tvb, start, length);
1605         proto_tree_set_string(fi, string, TRUE);
1606 }
1607
1608 /* Add a FT_ETHER to a proto_tree */
1609 proto_item *
1610 proto_tree_add_ether(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1611                 const guint8* value)
1612 {
1613         proto_item              *pi;
1614         field_info              *new_fi;
1615         header_field_info       *hfinfo;
1616
1617         if (!tree)
1618                 return (NULL);
1619
1620         TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1621
1622         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1623         DISSECTOR_ASSERT(hfinfo->type == FT_ETHER);
1624
1625         pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1626         proto_tree_set_ether(new_fi, value);
1627
1628         return pi;
1629 }
1630
1631 proto_item *
1632 proto_tree_add_ether_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1633                 const guint8* value)
1634 {
1635         proto_item              *pi;
1636
1637         pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
1638         if (pi == NULL)
1639                 return (NULL);
1640
1641         PROTO_ITEM_SET_HIDDEN(pi);
1642
1643         return pi;
1644 }
1645
1646 proto_item *
1647 proto_tree_add_ether_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1648                 const guint8* value, const char *format, ...)
1649 {
1650         proto_item              *pi;
1651         va_list                 ap;
1652
1653         pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
1654         if (pi == NULL)
1655                 return (NULL);
1656
1657         va_start(ap, format);
1658         proto_tree_set_representation(pi, format, ap);
1659         va_end(ap);
1660
1661         return pi;
1662 }
1663
1664 /* Set the FT_ETHER value */
1665 static void
1666 proto_tree_set_ether(field_info *fi, const guint8* value)
1667 {
1668         fvalue_set(&fi->value, (gpointer) value, FALSE);
1669 }
1670
1671 static void
1672 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start)
1673 {
1674         proto_tree_set_ether(fi, tvb_get_ptr(tvb, start, 6));
1675 }
1676
1677 /* Add a FT_BOOLEAN to a proto_tree */
1678 proto_item *
1679 proto_tree_add_boolean(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1680                 guint32 value)
1681 {
1682         proto_item              *pi;
1683         field_info              *new_fi;
1684         header_field_info       *hfinfo;
1685
1686         if (!tree)
1687                 return (NULL);
1688
1689         TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1690
1691         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1692         DISSECTOR_ASSERT(hfinfo->type == FT_BOOLEAN);
1693
1694         pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1695         proto_tree_set_boolean(new_fi, value);
1696
1697         return pi;
1698 }
1699
1700 proto_item *
1701 proto_tree_add_boolean_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1702                 guint32 value)
1703 {
1704         proto_item              *pi;
1705
1706         pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
1707         if (pi == NULL)
1708                 return (NULL);
1709
1710         PROTO_ITEM_SET_HIDDEN(pi);
1711
1712         return pi;
1713 }
1714
1715 proto_item *
1716 proto_tree_add_boolean_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1717                 guint32 value, const char *format, ...)
1718 {
1719         proto_item              *pi;
1720         va_list                 ap;
1721
1722         pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
1723         if (pi == NULL)
1724                 return (NULL);
1725
1726         va_start(ap, format);
1727         proto_tree_set_representation(pi, format, ap);
1728         va_end(ap);
1729
1730         return pi;
1731 }
1732
1733 /* Set the FT_BOOLEAN value */
1734 static void
1735 proto_tree_set_boolean(field_info *fi, guint32 value)
1736 {
1737         proto_tree_set_uint(fi, value);
1738 }
1739
1740 /* Add a FT_FLOAT to a proto_tree */
1741 proto_item *
1742 proto_tree_add_float(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1743                 float value)
1744 {
1745         proto_item              *pi;
1746         field_info              *new_fi;
1747         header_field_info       *hfinfo;
1748
1749         if (!tree)
1750                 return (NULL);
1751
1752         TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1753
1754         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1755         DISSECTOR_ASSERT(hfinfo->type == FT_FLOAT);
1756
1757         pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1758         proto_tree_set_float(new_fi, value);
1759
1760         return pi;
1761 }
1762
1763 proto_item *
1764 proto_tree_add_float_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1765                 float value)
1766 {
1767         proto_item              *pi;
1768
1769         pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
1770         if (pi == NULL)
1771                 return (NULL);
1772
1773         PROTO_ITEM_SET_HIDDEN(pi);
1774
1775         return pi;
1776 }
1777
1778 proto_item *
1779 proto_tree_add_float_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1780                 float value, const char *format, ...)
1781 {
1782         proto_item              *pi;
1783         va_list                 ap;
1784
1785         pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
1786         if (pi == NULL)
1787                 return (NULL);
1788
1789         va_start(ap, format);
1790         proto_tree_set_representation(pi, format, ap);
1791         va_end(ap);
1792
1793         return pi;
1794 }
1795
1796 /* Set the FT_FLOAT value */
1797 static void
1798 proto_tree_set_float(field_info *fi, float value)
1799 {
1800         fvalue_set_floating(&fi->value, value);
1801 }
1802
1803 /* Add a FT_DOUBLE to a proto_tree */
1804 proto_item *
1805 proto_tree_add_double(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1806                 double value)
1807 {
1808         proto_item              *pi;
1809         field_info              *new_fi;
1810         header_field_info       *hfinfo;
1811
1812         if (!tree)
1813                 return (NULL);
1814
1815         TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1816
1817         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1818         DISSECTOR_ASSERT(hfinfo->type == FT_DOUBLE);
1819
1820         pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1821         proto_tree_set_double(new_fi, value);
1822
1823         return pi;
1824 }
1825
1826 proto_item *
1827 proto_tree_add_double_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1828                 double value)
1829 {
1830         proto_item              *pi;
1831
1832         pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
1833         if (pi == NULL)
1834                 return (NULL);
1835
1836         PROTO_ITEM_SET_HIDDEN(pi);
1837
1838         return pi;
1839 }
1840
1841 proto_item *
1842 proto_tree_add_double_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1843                 double value, const char *format, ...)
1844 {
1845         proto_item              *pi;
1846         va_list                 ap;
1847
1848         pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
1849         if (pi == NULL)
1850                 return (NULL);
1851
1852         va_start(ap, format);
1853         proto_tree_set_representation(pi, format, ap);
1854         va_end(ap);
1855
1856         return pi;
1857 }
1858
1859 /* Set the FT_DOUBLE value */
1860 static void
1861 proto_tree_set_double(field_info *fi, double value)
1862 {
1863         fvalue_set_floating(&fi->value, value);
1864 }
1865
1866 /* Add FT_UINT{8,16,24,32} to a proto_tree */
1867 proto_item *
1868 proto_tree_add_uint(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1869                 guint32 value)
1870 {
1871         proto_item              *pi = NULL;
1872         field_info              *new_fi;
1873         header_field_info       *hfinfo;
1874
1875         if (!tree)
1876                 return (NULL);
1877
1878         TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1879
1880         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1881         switch(hfinfo->type) {
1882                 case FT_UINT8:
1883                 case FT_UINT16:
1884                 case FT_UINT24:
1885                 case FT_UINT32:
1886                 case FT_FRAMENUM:
1887                         pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length,
1888                                         &new_fi);
1889                         proto_tree_set_uint(new_fi, value);
1890                         break;
1891
1892                 default:
1893                         DISSECTOR_ASSERT_NOT_REACHED();
1894         }
1895
1896         return pi;
1897 }
1898
1899 proto_item *
1900 proto_tree_add_uint_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1901                 guint32 value)
1902 {
1903         proto_item              *pi;
1904
1905         pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
1906         if (pi == NULL)
1907                 return (NULL);
1908
1909         PROTO_ITEM_SET_HIDDEN(pi);
1910
1911         return pi;
1912 }
1913
1914 proto_item *
1915 proto_tree_add_uint_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1916                 guint32 value, const char *format, ...)
1917 {
1918         proto_item              *pi;
1919         va_list                 ap;
1920
1921         pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
1922         if (pi == NULL)
1923                 return (NULL);
1924
1925         va_start(ap, format);
1926         proto_tree_set_representation(pi, format, ap);
1927         va_end(ap);
1928
1929         return pi;
1930 }
1931
1932 /* Set the FT_UINT{8,16,24,32} value */
1933 static void
1934 proto_tree_set_uint(field_info *fi, guint32 value)
1935 {
1936         header_field_info       *hfinfo;
1937         guint32                 integer;
1938
1939         hfinfo = fi->hfinfo;
1940         integer = value;
1941
1942         if (hfinfo->bitmask) {
1943                 /* Mask out irrelevant portions */
1944                 integer &= hfinfo->bitmask;
1945
1946                 /* Shift bits */
1947                 if (hfinfo->bitshift > 0) {
1948                         integer >>= hfinfo->bitshift;
1949                 }
1950         }
1951         fvalue_set_integer(&fi->value, integer);
1952 }
1953
1954 /* Add FT_UINT64 to a proto_tree */
1955 proto_item *
1956 proto_tree_add_uint64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1957                 guint64 value)
1958 {
1959         proto_item              *pi = NULL;
1960         field_info              *new_fi;
1961         header_field_info       *hfinfo;
1962
1963         if (!tree)
1964                 return (NULL);
1965
1966         TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1967
1968         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1969         DISSECTOR_ASSERT(hfinfo->type == FT_UINT64);
1970
1971         pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1972         proto_tree_set_uint64(new_fi, value);
1973
1974         return pi;
1975 }
1976
1977 proto_item *
1978 proto_tree_add_uint64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1979                 guint64 value, const char *format, ...)
1980 {
1981         proto_item              *pi;
1982         va_list                 ap;
1983
1984         pi = proto_tree_add_uint64(tree, hfindex, tvb, start, length, value);
1985         if (pi == NULL)
1986                 return (NULL);
1987
1988         va_start(ap, format);
1989         proto_tree_set_representation(pi, format, ap);
1990         va_end(ap);
1991
1992         return pi;
1993 }
1994
1995 /* Add FT_INT{8,16,24,32} to a proto_tree */
1996 proto_item *
1997 proto_tree_add_int(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1998                 gint32 value)
1999 {
2000         proto_item              *pi = NULL;
2001         field_info              *new_fi;
2002         header_field_info       *hfinfo;
2003
2004         if (!tree)
2005                 return (NULL);
2006
2007         TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
2008
2009         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2010         switch(hfinfo->type) {
2011                 case FT_INT8:
2012                 case FT_INT16:
2013                 case FT_INT24:
2014                 case FT_INT32:
2015                         pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length,
2016                                         &new_fi);
2017                         proto_tree_set_int(new_fi, value);
2018                         break;
2019
2020                 default:
2021                         DISSECTOR_ASSERT_NOT_REACHED();
2022         }
2023
2024         return pi;
2025 }
2026
2027 proto_item *
2028 proto_tree_add_int_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2029                 gint32 value)
2030 {
2031         proto_item              *pi;
2032
2033         pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
2034         if (pi == NULL)
2035                 return (NULL);
2036
2037         PROTO_ITEM_SET_HIDDEN(pi);
2038
2039         return pi;
2040 }
2041
2042 proto_item *
2043 proto_tree_add_int_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2044                 gint32 value, const char *format, ...)
2045 {
2046         proto_item              *pi = NULL;
2047         va_list                 ap;
2048
2049         pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
2050         if (pi == NULL)
2051                 return (NULL);
2052
2053         va_start(ap, format);
2054         proto_tree_set_representation(pi, format, ap);
2055         va_end(ap);
2056
2057         return pi;
2058 }
2059
2060 /* Set the FT_INT{8,16,24,32} value */
2061 static void
2062 proto_tree_set_int(field_info *fi, gint32 value)
2063 {
2064         header_field_info       *hfinfo;
2065         guint32                 integer;
2066
2067         hfinfo = fi->hfinfo;
2068         integer = (guint32) value;
2069
2070         if (hfinfo->bitmask) {
2071                 /* Mask out irrelevant portions */
2072                 integer &= hfinfo->bitmask;
2073
2074                 /* Shift bits */
2075                 if (hfinfo->bitshift > 0) {
2076                         integer >>= hfinfo->bitshift;
2077                 }
2078         }
2079         fvalue_set_integer(&fi->value, integer);
2080 }
2081
2082 /* Add FT_INT64 to a proto_tree */
2083 proto_item *
2084 proto_tree_add_int64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2085                 gint64 value)
2086 {
2087         proto_item              *pi = NULL;
2088         field_info              *new_fi;
2089         header_field_info       *hfinfo;
2090
2091         if (!tree)
2092                 return (NULL);
2093
2094         TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
2095
2096         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2097         DISSECTOR_ASSERT(hfinfo->type == FT_INT64);
2098
2099         pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2100         proto_tree_set_uint64(new_fi, (guint64)value);
2101
2102         return pi;
2103 }
2104
2105 proto_item *
2106 proto_tree_add_int64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2107                 gint64 value, const char *format, ...)
2108 {
2109         proto_item              *pi;
2110         va_list                 ap;
2111
2112         pi = proto_tree_add_int64(tree, hfindex, tvb, start, length, value);
2113         if (pi == NULL)
2114                 return (NULL);
2115
2116         va_start(ap, format);
2117         proto_tree_set_representation(pi, format, ap);
2118         va_end(ap);
2119
2120         return pi;
2121 }
2122
2123
2124 /* Add a field_info struct to the proto_tree, encapsulating it in a proto_node */
2125 static proto_item *
2126 proto_tree_add_node(proto_tree *tree, field_info *fi)
2127 {
2128         proto_node *pnode, *tnode, *sibling;
2129         field_info *tfi;
2130
2131         /*
2132          * Make sure "tree" is ready to have subtrees under it, by
2133          * checking whether it's been given an ett_ value.
2134          *
2135          * "tnode->finfo" may be null; that's the case for the root
2136          * node of the protocol tree.  That node is not displayed,
2137          * so it doesn't need an ett_ value to remember whether it
2138          * was expanded.
2139          */
2140         tnode = tree;
2141         tfi = tnode->finfo;
2142         if (tfi != NULL && (tfi->tree_type < 0 || tfi->tree_type >= num_tree_types)) {
2143                 REPORT_DISSECTOR_BUG(g_strdup_printf("\"%s\" - \"%s\" tfi->tree_type: %u invalid (%s:%u)",
2144                         fi->hfinfo->name, fi->hfinfo->abbrev, tfi->tree_type, __FILE__, __LINE__));
2145         /* XXX - is it safe to continue here? */
2146     }
2147
2148         DISSECTOR_ASSERT(tfi == NULL ||
2149             (tfi->tree_type >= 0 && tfi->tree_type < num_tree_types));
2150
2151         PROTO_NODE_NEW(pnode);
2152         pnode->parent = tnode;
2153         pnode->finfo = fi;
2154         pnode->tree_data = PTREE_DATA(tree);
2155
2156         if (tnode->last_child != NULL) {
2157                 sibling = tnode->last_child;
2158                 DISSECTOR_ASSERT(sibling->next == NULL);
2159                 sibling->next = pnode;
2160         } else
2161                 tnode->first_child = pnode;
2162         tnode->last_child = pnode;
2163
2164         return (proto_item*)pnode;
2165 }
2166
2167
2168 /* Generic way to allocate field_info and add to proto_tree.
2169  * Sets *pfi to address of newly-allocated field_info struct, if pfi is
2170  * non-NULL. */
2171 static proto_item *
2172 proto_tree_add_pi(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2173     gint *length, field_info **pfi)
2174 {
2175         proto_item      *pi;
2176         field_info      *fi;
2177         GHashTable      *hash;
2178         GPtrArray       *ptrs;
2179
2180         if (!tree)
2181                 return(NULL);
2182
2183         fi = alloc_field_info(tree, hfindex, tvb, start, length);
2184         pi = proto_tree_add_node(tree, fi);
2185
2186         /* If the proto_tree wants to keep a record of this finfo
2187          * for quick lookup, then record it. */
2188         if (fi->hfinfo->ref_count) {
2189                 hash = PTREE_DATA(tree)->interesting_hfids;
2190                 ptrs = g_hash_table_lookup(hash, GINT_TO_POINTER(hfindex));
2191                 if (ptrs) {
2192                         g_ptr_array_add(ptrs, fi);
2193                 }
2194         }
2195
2196         /* Does the caller want to know the fi pointer? */
2197         if (pfi) {
2198                 *pfi = fi;
2199         }
2200
2201         return pi;
2202 }
2203
2204 static field_info *
2205 alloc_field_info(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2206     gint *length)
2207 {
2208         header_field_info       *hfinfo;
2209         field_info              *fi;
2210         gint                    item_length;
2211         gint                    length_remaining;
2212
2213         /*
2214          * We only allow a null tvbuff if the item has a zero length,
2215          * i.e. if there's no data backing it.
2216          */
2217         DISSECTOR_ASSERT(tvb != NULL || *length == 0);
2218
2219         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2220
2221         /*
2222          * XXX - in some protocols, there are 32-bit unsigned length
2223          * fields, so lengths in protocol tree and tvbuff routines
2224          * should really be unsigned.  We should have, for those
2225          * field types for which "to the end of the tvbuff" makes sense,
2226          * additional routines that take no length argument and
2227          * add fields that run to the end of the tvbuff.
2228          */
2229         if (*length == -1) {
2230                 /*
2231                  * For FT_NONE, FT_PROTOCOL, FT_BYTES, and FT_STRING fields,
2232                  * a length of -1 means "set the length to what remains in
2233                  * the tvbuff".
2234                  *
2235                  * The assumption is either that
2236                  *
2237                  *      1) the length of the item can only be determined
2238                  *         by dissection (typically true of items with
2239                  *         subitems, which are probably FT_NONE or
2240                  *         FT_PROTOCOL)
2241                  *
2242                  * or
2243                  *
2244                  *      2) if the tvbuff is "short" (either due to a short
2245                  *         snapshot length or due to lack of reassembly of
2246                  *         fragments/segments/whatever), we want to display
2247                  *         what's available in the field (probably FT_BYTES
2248                  *         or FT_STRING) and then throw an exception later
2249                  *
2250                  * or
2251                  *
2252                  *      3) the field is defined to be "what's left in the
2253                  *         packet"
2254                  *
2255                  * so we set the length to what remains in the tvbuff so
2256                  * that, if we throw an exception while dissecting, it
2257                  * has what is probably the right value.
2258                  *
2259                  * For FT_STRINGZ, it means "the string is null-terminated,
2260                  * not null-padded; set the length to the actual length
2261                  * of the string", and if the tvbuff if short, we just
2262                  * throw an exception.
2263                  *
2264                  * It's not valid for any other type of field.
2265                  */
2266                 switch (hfinfo->type) {
2267
2268                 case FT_PROTOCOL:
2269                         /*
2270                          * We allow this to be zero-length - for
2271                          * example, an ONC RPC NULL procedure has
2272                          * neither arguments nor reply, so the
2273                          * payload for that protocol is empty.
2274                          *
2275                          * However, if the length is negative, the
2276                          * start offset is *past* the byte past the
2277                          * end of the tvbuff, so we throw an
2278                          * exception.
2279                          */
2280                         *length = tvb_length_remaining(tvb, start);
2281                         if (*length < 0) {
2282                                 /*
2283                                  * Use "tvb_ensure_bytes_exist()"
2284                                  * to force the appropriate exception
2285                                  * to be thrown.
2286                                  */
2287                                 tvb_ensure_bytes_exist(tvb, start, 0);
2288                         }
2289                         DISSECTOR_ASSERT(*length >= 0);
2290                         break;
2291
2292                 case FT_NONE:
2293                 case FT_BYTES:
2294                 case FT_STRING:
2295                         *length = tvb_ensure_length_remaining(tvb, start);
2296                         DISSECTOR_ASSERT(*length >= 0);
2297                         break;
2298
2299                 case FT_STRINGZ:
2300                         /*
2301                          * Leave the length as -1, so our caller knows
2302                          * it was -1.
2303                          */
2304                         break;
2305
2306                 default:
2307                         DISSECTOR_ASSERT_NOT_REACHED();
2308                 }
2309                 item_length = *length;
2310         } else {
2311                 item_length = *length;
2312                 if (hfinfo->type == FT_PROTOCOL || hfinfo->type == FT_NONE) {
2313                         /*
2314                          * These types are for interior nodes of the
2315                          * tree, and don't have data associated with
2316                          * them; if the length is negative (XXX - see
2317                          * above) or goes past the end of the tvbuff,
2318                          * cut it short at the end of the tvbuff.
2319                          * That way, if this field is selected in
2320                          * Ethereal, we don't highlight stuff past
2321                          * the end of the data.
2322                          */
2323             /* XXX - what to do, if we don't have a tvb? */
2324             if(tvb) {
2325                             length_remaining = tvb_length_remaining(tvb, start);
2326                             if (item_length < 0 || (item_length > 0 && (length_remaining < item_length)))
2327                                     item_length = length_remaining;
2328             }
2329                 }
2330                 if (item_length < 0) {
2331                         THROW(ReportedBoundsError);
2332                 }
2333         }
2334
2335         FIELD_INFO_NEW(fi);
2336
2337         fi->hfinfo = hfinfo;
2338         fi->start = start;
2339         fi->start+=(tvb)?TVB_RAW_OFFSET(tvb):0;
2340         fi->length = item_length;
2341         fi->tree_type = -1;
2342         fi->flags = 0;
2343         if (!PTREE_DATA(tree)->visible)
2344                 FI_SET_FLAG(fi, FI_HIDDEN);
2345         fvalue_init(&fi->value, fi->hfinfo->type);
2346         fi->rep = NULL;
2347
2348         /* add the data source tvbuff */
2349         fi->ds_tvb=tvb?TVB_GET_DS_TVB(tvb):NULL;
2350
2351         return fi;
2352 }
2353
2354 /* Set representation of a proto_tree entry, if the protocol tree is to
2355    be visible. */
2356 static void
2357 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap)
2358 {
2359         int                                     ret;    /*tmp return value */
2360         field_info *fi = PITEM_FINFO(pi);
2361
2362         if (!PROTO_ITEM_IS_HIDDEN(pi)) {
2363                 ITEM_LABEL_NEW(fi->rep);
2364                 ret = vsnprintf(fi->rep->representation, ITEM_LABEL_LENGTH, format, ap);
2365                 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
2366                         fi->rep->representation[ITEM_LABEL_LENGTH - 1] = '\0';
2367         }
2368 }
2369
2370 /* Set text of proto_item after having already been created. */
2371 void
2372 proto_item_set_text(proto_item *pi, const char *format, ...)
2373 {
2374         field_info *fi = NULL;
2375         va_list ap;
2376
2377         if (pi==NULL) {
2378                 return;
2379         }
2380
2381         fi = PITEM_FINFO(pi);
2382
2383         if(fi->rep){
2384                 ITEM_LABEL_FREE(fi->rep);
2385         }
2386
2387         va_start(ap, format);
2388         proto_tree_set_representation(pi, format, ap);
2389         va_end(ap);
2390 }
2391
2392 /* Append to text of proto_item after having already been created. */
2393 void
2394 proto_item_append_text(proto_item *pi, const char *format, ...)
2395 {
2396         field_info *fi = NULL;
2397         size_t curlen;
2398         va_list ap;
2399         int                                     ret;    /*tmp return value */
2400
2401         if (pi==NULL) {
2402                 return;
2403         }
2404
2405         fi = PITEM_FINFO(pi);
2406
2407     if (!PROTO_ITEM_IS_HIDDEN(pi)) {
2408                 va_start(ap, format);
2409
2410                 /*
2411                  * If we don't already have a representation,
2412                  * generate the default representation.
2413                  */
2414                 if (fi->rep == NULL) {
2415                         ITEM_LABEL_NEW(fi->rep);
2416                         proto_item_fill_label(fi, fi->rep->representation);
2417                 }
2418
2419                 curlen = strlen(fi->rep->representation);
2420                 if (ITEM_LABEL_LENGTH > curlen) {
2421                         ret = vsnprintf(fi->rep->representation + curlen,
2422                             ITEM_LABEL_LENGTH - curlen, format, ap);
2423                         if ((ret == -1) || (ret >= (int)(ITEM_LABEL_LENGTH - curlen)))
2424                                 fi->rep->representation[ITEM_LABEL_LENGTH - 1] = '\0';
2425                 }
2426                 va_end(ap);
2427         }
2428 }
2429
2430 void
2431 proto_item_set_len(proto_item *pi, gint length)
2432 {
2433         field_info *fi;
2434
2435         if (pi == NULL)
2436                 return;
2437         fi = PITEM_FINFO(pi);
2438         DISSECTOR_ASSERT(length >= 0);
2439         fi->length = length;
2440 }
2441
2442 /*
2443  * Sets the length of the item based on its start and on the specified
2444  * offset, which is the offset past the end of the item; as the start
2445  * in the item is relative to the beginning of the data source tvbuff,
2446  * we need to pass in a tvbuff - the end offset is relative to the beginning
2447  * of that tvbuff.
2448  */
2449 void
2450 proto_item_set_end(proto_item *pi, tvbuff_t *tvb, gint end)
2451 {
2452         field_info *fi;
2453
2454         if (pi == NULL)
2455                 return;
2456         fi = PITEM_FINFO(pi);
2457         end += TVB_RAW_OFFSET(tvb);
2458         DISSECTOR_ASSERT(end >= fi->start);
2459         fi->length = end - fi->start;
2460 }
2461
2462 int
2463 proto_item_get_len(proto_item *pi)
2464 {
2465         field_info *fi = PITEM_FINFO(pi);
2466         return fi->length;
2467 }
2468
2469 proto_tree*
2470 proto_tree_create_root(void)
2471 {
2472         proto_node  *pnode;
2473
2474         /* Initialize the proto_node */
2475         PROTO_NODE_NEW(pnode);
2476         pnode->parent = NULL;
2477         pnode->finfo = NULL;
2478         pnode->tree_data = g_new(tree_data_t, 1);
2479
2480         /* Initialize the tree_data_t */
2481         pnode->tree_data->interesting_hfids =
2482             g_hash_table_new(g_direct_hash, g_direct_equal);
2483
2484         /* Set the default to FALSE so it's easier to
2485          * find errors; if we expect to see the protocol tree
2486          * but for some reason the default 'visible' is not
2487          * changed, then we'll find out very quickly. */
2488         pnode->tree_data->visible = FALSE;
2489
2490         return (proto_tree*) pnode;
2491 }
2492
2493
2494 /* "prime" a proto_tree with a single hfid that a dfilter
2495  * is interested in. */
2496 void
2497 proto_tree_prime_hfid(proto_tree *tree, gint hfid)
2498 {
2499         header_field_info *hfinfo;
2500
2501         g_hash_table_insert(PTREE_DATA(tree)->interesting_hfids,
2502                 GINT_TO_POINTER(hfid), g_ptr_array_new());
2503
2504         PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
2505         /* this field is referenced by a filter so increase the refcount.
2506            also increase the refcount for the parent, i.e the protocol.
2507         */
2508         hfinfo->ref_count++;
2509         /* only increase the refcount if there is a parent.
2510            if this is a protocol and not a field then parent will be -1
2511            and there is no parent to add any refcounting for.
2512         */
2513         if (hfinfo->parent != -1) {
2514                 header_field_info *parent_hfinfo;
2515                 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
2516                 parent_hfinfo->ref_count++;
2517         }
2518 }
2519
2520 proto_tree*
2521 proto_item_add_subtree(proto_item *pi,  gint idx) {
2522         field_info *fi;
2523
2524         if (!pi)
2525                 return(NULL);
2526
2527         fi = PITEM_FINFO(pi);
2528         DISSECTOR_ASSERT(idx >= 0 && idx < num_tree_types);
2529         fi->tree_type = idx;
2530
2531         return (proto_tree*) pi;
2532 }
2533
2534 proto_tree*
2535 proto_item_get_subtree(proto_item *pi) {
2536         field_info *fi;
2537
2538         if (!pi)
2539                 return(NULL);
2540         fi = PITEM_FINFO(pi);
2541         if ( (!fi) || (fi->tree_type == -1) )
2542                 return(NULL);
2543         return (proto_tree*) pi;
2544 }
2545
2546 proto_item*
2547 proto_item_get_parent(proto_item *ti) {
2548         /* dont bother if tree is not visible */
2549         if( (!ti) || (!(PTREE_DATA(ti)->visible)) )
2550                 return (NULL);
2551         return ti->parent;
2552 }
2553
2554 proto_item*
2555 proto_item_get_parent_nth(proto_item *ti, int gen) {
2556         /* dont bother if tree is not visible */
2557         if( (!ti) || (!(PTREE_DATA(ti)->visible)) )
2558                 return (NULL);
2559         while (gen--) {
2560                 ti = ti->parent;
2561                 if (!ti)
2562                         return (NULL);
2563         }
2564         return ti;
2565 }
2566
2567
2568 proto_item* 
2569 proto_tree_get_parent(proto_tree *tree) {
2570         /* dont bother if tree is not visible */
2571         if( (!tree) || (!(PTREE_DATA(tree)->visible)) )
2572                 return (NULL);
2573         return (proto_item*) tree;
2574 }
2575
2576
2577 void
2578 proto_tree_move_item(proto_tree *tree, proto_item *fixed_item, proto_item *item_to_move)
2579 {
2580     proto_item *curr_item;
2581
2582
2583     /*** cut item_to_move out ***/
2584
2585     /* is item_to_move the first? */
2586     if(tree->first_child == item_to_move) {
2587         /* simply change first child to next */
2588         tree->first_child = item_to_move->next;
2589     } else {
2590         /* find previous and change it's next */
2591         for(curr_item = tree->first_child; curr_item != NULL; curr_item = curr_item->next) {
2592             if(curr_item->next == item_to_move) {
2593                 break;
2594             }
2595         }
2596
2597         DISSECTOR_ASSERT(curr_item);
2598
2599         curr_item->next = item_to_move->next;
2600
2601         /* fix last_child if required */
2602         if(tree->last_child == item_to_move) {
2603             tree->last_child = curr_item;
2604         } 
2605     }
2606
2607     /*** insert to_move after fixed ***/
2608     item_to_move->next = fixed_item->next;
2609     fixed_item->next = item_to_move;
2610     if(tree->last_child == fixed_item) {
2611         tree->last_child = item_to_move;
2612     }
2613 }
2614
2615
2616 int
2617 proto_register_protocol(const char *name, const char *short_name, const char *filter_name)
2618 {
2619     protocol_t *protocol;
2620     header_field_info *hfinfo;
2621     int proto_id;
2622     char *existing_name;
2623     gint *key;
2624     guint i;
2625     gboolean found_invalid;
2626
2627     /*
2628      * Make sure there's not already a protocol with any of those
2629      * names.  Crash if there is, as that's an error in the code
2630      * or an inappropriate plugin.
2631      * This situation has to be fixed to not register more than one
2632      * protocol with the same name.
2633      *
2634      * This is done by reducing the number of strcmp (and alike) calls as much as possible,
2635      * as this significally slows down startup time.
2636      *
2637      * Drawback: As a hash value is used to reduce insert time, 
2638      * this might lead to a hash collision.
2639      * However, as we have around 500+ protocols and we're using a 32 bit int this is very,
2640      * very unlikely.
2641      */
2642
2643     key = g_malloc (sizeof(gint));
2644     *key = g_str_hash(name);
2645     existing_name = g_hash_table_lookup(proto_names, key);
2646     if (existing_name != NULL) {
2647         /* g_error will terminate the program */
2648         g_error("Duplicate protocol name \"%s\"!"
2649             " This might be caused by an inappropriate plugin or a development error.", name);
2650     }
2651     g_hash_table_insert(proto_names, key, (gpointer)name);
2652
2653     key = g_malloc (sizeof(gint));
2654     *key = g_str_hash(short_name);
2655     existing_name = g_hash_table_lookup(proto_short_names, key);
2656     if (existing_name != NULL) {
2657         g_error("Duplicate protocol short_name \"%s\"!"
2658             " This might be caused by an inappropriate plugin or a development error.", short_name);
2659     }
2660     g_hash_table_insert(proto_short_names, key, (gpointer)short_name);
2661
2662     found_invalid = FALSE;
2663     for (i = 0; i < strlen(filter_name); i++) {
2664         if (! (islower(filter_name[i]) ||
2665                isdigit(filter_name[i]) ||
2666                filter_name[i] == '-'   ||
2667                filter_name[i] == '_'   ||
2668                filter_name[i] == '.'   )) {
2669             found_invalid = TRUE;
2670         }
2671     }
2672     if (found_invalid) {
2673         g_warning("Protocol filter name \"%s\" has one or more invalid characters.", filter_name);
2674     }
2675     key = g_malloc (sizeof(gint));
2676     *key = g_str_hash(filter_name);
2677     existing_name = g_hash_table_lookup(proto_filter_names, key);
2678     if (existing_name != NULL) {
2679         g_error("Duplicate protocol filter_name \"%s\"!"
2680             " This might be caused by an inappropriate plugin or a development error.", filter_name);
2681     }
2682     g_hash_table_insert(proto_filter_names, key, (gpointer)filter_name);
2683
2684     /* Add this protocol to the list of known protocols; the list
2685        is sorted by protocol short name. */
2686     protocol = g_malloc(sizeof (protocol_t));
2687     protocol->name = name;
2688     protocol->short_name = short_name;
2689     protocol->filter_name = filter_name;
2690     protocol->fields = NULL;
2691     protocol->is_enabled = TRUE; /* protocol is enabled by default */
2692     protocol->can_toggle = TRUE;
2693     /* list will be sorted later by name, when all protocols completed registering */
2694     protocols = g_list_append(protocols, protocol);
2695
2696     /* Here we do allocate a new header_field_info struct */
2697     hfinfo = g_mem_chunk_alloc(gmc_hfinfo);
2698     hfinfo->name = name;
2699     hfinfo->abbrev = filter_name;
2700     hfinfo->type = FT_PROTOCOL;
2701     hfinfo->strings = protocol;
2702     hfinfo->bitmask = 0;
2703     hfinfo->bitshift = 0;
2704     hfinfo->ref_count = 0;
2705     hfinfo->blurb = "";
2706     hfinfo->parent = -1; /* this field differentiates protos and fields */
2707
2708     proto_id = proto_register_field_init(hfinfo, hfinfo->parent);
2709     protocol->proto_id = proto_id;
2710     return proto_id;
2711 }
2712
2713 /*
2714  * Routines to use to iterate over the protocols.
2715  * The argument passed to the iterator routines is an opaque cookie to
2716  * their callers; it's the GList pointer for the current element in
2717  * the list.
2718  * The ID of the protocol is returned, or -1 if there is no protocol.
2719  */
2720 int
2721 proto_get_first_protocol(void **cookie)
2722 {
2723         protocol_t *protocol;
2724
2725         if (protocols == NULL)
2726                 return -1;
2727         *cookie = protocols;
2728         protocol = protocols->data;
2729         return protocol->proto_id;
2730 }
2731
2732 int
2733 proto_get_next_protocol(void **cookie)
2734 {
2735         GList *list_item = *cookie;
2736         protocol_t *protocol;
2737
2738         list_item = g_list_next(list_item);
2739         if (list_item == NULL)
2740                 return -1;
2741         *cookie = list_item;
2742         protocol = list_item->data;
2743         return protocol->proto_id;
2744 }
2745
2746 header_field_info *
2747 proto_get_first_protocol_field(int proto_id, void **cookie)
2748 {
2749         protocol_t *protocol = find_protocol_by_id(proto_id);
2750         hf_register_info *ptr;
2751
2752         if ((protocol == NULL) || (protocol->fields == NULL))
2753                 return NULL;
2754
2755         *cookie = protocol->fields;
2756         ptr = protocol->fields->data;
2757         return &ptr->hfinfo;
2758 }
2759
2760 header_field_info *
2761 proto_get_next_protocol_field(void **cookie)
2762 {
2763         GList *list_item = *cookie;
2764         hf_register_info *ptr;
2765
2766         list_item = g_list_next(list_item);
2767         if (list_item == NULL)
2768                 return NULL;
2769
2770         *cookie = list_item;
2771         ptr = list_item->data;
2772         return &ptr->hfinfo;
2773 }
2774
2775 protocol_t *
2776 find_protocol_by_id(int proto_id)
2777 {
2778         header_field_info *hfinfo;
2779
2780         if(proto_id<0)
2781                 return NULL;
2782
2783         PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
2784         DISSECTOR_ASSERT(hfinfo->type==FT_PROTOCOL);
2785         return (protocol_t *)hfinfo->strings;
2786 }
2787
2788 static gint compare_filter_name(gconstpointer proto_arg,
2789                                 gconstpointer filter_name)
2790 {
2791         const protocol_t *protocol = proto_arg;
2792         const gchar* f_name = filter_name;
2793
2794         return (strcmp(protocol->filter_name, f_name));
2795 }
2796
2797 int
2798 proto_get_id(protocol_t *protocol)
2799 {
2800         return protocol->proto_id;
2801 }
2802
2803 int proto_get_id_by_filter_name(const gchar* filter_name)
2804 {
2805         GList *list_entry;
2806         protocol_t *protocol;
2807
2808         list_entry = g_list_find_custom(protocols, filter_name,
2809             compare_filter_name);
2810         if (list_entry == NULL)
2811                 return -1;
2812         protocol = list_entry->data;
2813         return protocol->proto_id;
2814 }
2815
2816 const char *
2817 proto_get_protocol_name(int proto_id)
2818 {
2819         protocol_t *protocol;
2820
2821         protocol = find_protocol_by_id(proto_id);
2822         return protocol->name;
2823 }
2824
2825 const char *
2826 proto_get_protocol_short_name(protocol_t *protocol)
2827 {
2828         if (protocol == NULL)
2829                 return "(none)";
2830         return protocol->short_name;
2831 }
2832
2833 const char *
2834 proto_get_protocol_filter_name(int proto_id)
2835 {
2836         protocol_t *protocol;
2837
2838         protocol = find_protocol_by_id(proto_id);
2839         return protocol->filter_name;
2840 }
2841
2842 gboolean
2843 proto_is_protocol_enabled(protocol_t *protocol)
2844 {
2845         return protocol->is_enabled;
2846 }
2847
2848 gboolean
2849 proto_can_toggle_protocol(int proto_id)
2850 {
2851         protocol_t *protocol;
2852
2853         protocol = find_protocol_by_id(proto_id);
2854         return protocol->can_toggle;
2855 }
2856
2857 void
2858 proto_set_decoding(int proto_id, gboolean enabled)
2859 {
2860         protocol_t *protocol;
2861
2862         protocol = find_protocol_by_id(proto_id);
2863         DISSECTOR_ASSERT(protocol->can_toggle);
2864         protocol->is_enabled = enabled;
2865 }
2866
2867 void
2868 proto_set_cant_toggle(int proto_id)
2869 {
2870         protocol_t *protocol;
2871
2872         protocol = find_protocol_by_id(proto_id);
2873         protocol->can_toggle = FALSE;
2874 }
2875
2876 /* for use with static arrays only, since we don't allocate our own copies
2877 of the header_field_info struct contained within the hf_register_info struct */
2878 void
2879 proto_register_field_array(int parent, hf_register_info *hf, int num_records)
2880 {
2881         int                     field_id, i;
2882         hf_register_info        *ptr = hf;
2883         protocol_t              *proto;
2884
2885         proto = find_protocol_by_id(parent);
2886         for (i = 0; i < num_records; i++, ptr++) {
2887                 /*
2888                  * Make sure we haven't registered this yet.
2889                  * Most fields have variables associated with them
2890                  * that are initialized to -1; some have array elements,
2891                  * or possibly uninitialized variables, so we also allow
2892                  * 0 (which is unlikely to be the field ID we get back
2893                  * from "proto_register_field_init()").
2894                  */
2895                 DISSECTOR_ASSERT(*ptr->p_id == -1 || *ptr->p_id == 0);
2896
2897                 if (proto != NULL) {
2898                         if (proto->fields == NULL) {
2899                                 proto->fields = g_list_append(NULL, ptr);
2900                                 proto->last_field = proto->fields;
2901                         } else {
2902                                 proto->last_field =
2903                                     g_list_append(proto->last_field, ptr)->next;
2904                         }
2905                 }
2906                 field_id = proto_register_field_init(&ptr->hfinfo, parent);
2907                 *ptr->p_id = field_id;
2908         }
2909 }
2910
2911 static int
2912 proto_register_field_init(header_field_info *hfinfo, int parent)
2913 {
2914         /* The field must have names */
2915         DISSECTOR_ASSERT(hfinfo->name);
2916         DISSECTOR_ASSERT(hfinfo->abbrev);
2917
2918         /* These types of fields are allowed to have value_strings, true_false_strings or a protocol_t struct*/
2919         DISSECTOR_ASSERT((hfinfo->strings == NULL) || (
2920                         (hfinfo->type == FT_UINT8) ||
2921                         (hfinfo->type == FT_UINT16) ||
2922                         (hfinfo->type == FT_UINT24) ||
2923                         (hfinfo->type == FT_UINT32) ||
2924                         (hfinfo->type == FT_INT8) ||
2925                         (hfinfo->type == FT_INT16) ||
2926                         (hfinfo->type == FT_INT24) ||
2927                         (hfinfo->type == FT_INT32) ||
2928                         (hfinfo->type == FT_BOOLEAN) ||
2929                         (hfinfo->type == FT_PROTOCOL) ||
2930                         (hfinfo->type == FT_FRAMENUM) ));
2931
2932         switch (hfinfo->type) {
2933
2934         case FT_UINT8:
2935         case FT_UINT16:
2936         case FT_UINT24:
2937         case FT_UINT32:
2938         case FT_INT8:
2939         case FT_INT16:
2940         case FT_INT24:
2941         case FT_INT32:
2942                 /* Require integral types (other than frame number, which is
2943                    always displayed in decimal) to have a number base */
2944                 DISSECTOR_ASSERT(hfinfo->display != BASE_NONE);
2945                 break;
2946
2947         case FT_FRAMENUM:
2948                 /* Don't allow bitfields or value strings for frame numbers */
2949                 DISSECTOR_ASSERT(hfinfo->bitmask == 0);
2950                 DISSECTOR_ASSERT(hfinfo->strings == NULL);
2951                 break;
2952
2953         default:
2954                 break;
2955         }
2956         /* if this is a bitfield, compute bitshift */
2957         if (hfinfo->bitmask) {
2958                 while ((hfinfo->bitmask & (1 << hfinfo->bitshift)) == 0)
2959                         hfinfo->bitshift++;
2960         }
2961
2962         hfinfo->parent = parent;
2963         hfinfo->same_name_next = NULL;
2964         hfinfo->same_name_prev = NULL;
2965
2966         /* if we always add and never delete, then id == len - 1 is correct */
2967         if(gpa_hfinfo.len>=gpa_hfinfo.allocated_len){
2968                 if(!gpa_hfinfo.hfi){
2969                         gpa_hfinfo.allocated_len=1000;
2970                         gpa_hfinfo.hfi=g_malloc(sizeof(header_field_info *)*1000);
2971                 } else {
2972                         gpa_hfinfo.allocated_len+=1000;
2973                         gpa_hfinfo.hfi=g_realloc(gpa_hfinfo.hfi, sizeof(header_field_info *)*gpa_hfinfo.allocated_len);
2974                 }
2975         }
2976         gpa_hfinfo.hfi[gpa_hfinfo.len]=hfinfo;
2977         gpa_hfinfo.len++;
2978         hfinfo->id = gpa_hfinfo.len - 1;
2979
2980         /* if we have real names, enter this field in the name tree */
2981         if ((hfinfo->name[0] != 0) && (hfinfo->abbrev[0] != 0 )) {
2982
2983                 header_field_info *same_name_hfinfo, *same_name_next_hfinfo;
2984                 const char *p;
2985                 guchar c;
2986
2987                 /* Check that the filter name (abbreviation) is legal;
2988                  * it must contain only alphanumerics, '-', "_", and ".". */
2989                 for (p = hfinfo->abbrev; (c = *p) != '\0'; p++)
2990                         DISSECTOR_ASSERT(isalnum(c) || c == '-' || c == '_' ||
2991                             c == '.');
2992
2993                 /* We allow multiple hfinfo's to be registered under the same
2994                  * abbreviation. This was done for X.25, as, depending
2995                  * on whether it's modulo-8 or modulo-128 operation,
2996                  * some bitfield fields may be in different bits of
2997                  * a byte, and we want to be able to refer to that field
2998                  * with one name regardless of whether the packets
2999                  * are modulo-8 or modulo-128 packets. */
3000                 same_name_hfinfo = g_tree_lookup(gpa_name_tree, hfinfo->abbrev);
3001                 if (same_name_hfinfo) {
3002                         /* There's already a field with this name.
3003                          * Put it after that field in the list of
3004                          * fields with this name, then allow the code
3005                          * after this if{} block to replace the old
3006                          * hfinfo with the new hfinfo in the GTree. Thus,
3007                          * we end up with a linked-list of same-named hfinfo's,
3008                          * with the root of the list being the hfinfo in the GTree */
3009                         same_name_next_hfinfo =
3010                             same_name_hfinfo->same_name_next;
3011
3012                         hfinfo->same_name_next = same_name_next_hfinfo;
3013                         if (same_name_next_hfinfo)
3014                                 same_name_next_hfinfo->same_name_prev = hfinfo;
3015
3016                         same_name_hfinfo->same_name_next = hfinfo;
3017                         hfinfo->same_name_prev = same_name_hfinfo;
3018                 }
3019                 g_tree_insert(gpa_name_tree, (gpointer) (hfinfo->abbrev), hfinfo);
3020         }
3021
3022         return hfinfo->id;
3023 }
3024
3025 void
3026 proto_register_subtree_array(gint *const *indices, int num_indices)
3027 {
3028         int     i;
3029         gint    *const *ptr = indices;
3030
3031         /*
3032          * If we've already allocated the array of tree types, expand
3033          * it; this lets plugins such as mate add tree types after
3034          * the initial startup.  (If we haven't already allocated it,
3035          * we don't allocate it; on the first pass, we just assign
3036          * ett values and keep track of how many we've assigned, and
3037          * when we're finished registering all dissectors we allocate
3038          * the array, so that we do only one allocation rather than
3039          * wasting CPU time and memory by growing the array for each
3040          * dissector that registers ett values.)
3041          */
3042         if (tree_is_expanded != NULL) {
3043                 tree_is_expanded =
3044                     g_realloc(tree_is_expanded,
3045                         (num_tree_types+num_indices)*sizeof (gint *));
3046                 memset(tree_is_expanded + num_tree_types, 0,
3047                     num_indices*sizeof (gint *));
3048         }
3049
3050         /*
3051          * Assign "num_indices" subtree numbers starting at "num_tree_types",
3052          * returning the indices through the pointers in the array whose
3053          * first element is pointed to by "indices", and update
3054          * "num_tree_types" appropriately.
3055          */
3056         for (i = 0; i < num_indices; i++, ptr++, num_tree_types++)
3057                 **ptr = num_tree_types;
3058 }
3059
3060 void
3061 proto_item_fill_label(field_info *fi, gchar *label_str)
3062 {
3063         header_field_info               *hfinfo = fi->hfinfo;
3064
3065         guint8                          *bytes;
3066         guint32                         integer;
3067         ipv4_addr                       *ipv4;
3068         guint32                         n_addr; /* network-order IPv4 address */
3069         int                                     ret;    /*tmp return value */
3070
3071         switch(hfinfo->type) {
3072                 case FT_NONE:
3073                 case FT_PROTOCOL:
3074                         ret = snprintf(label_str, ITEM_LABEL_LENGTH,
3075                                 "%s", hfinfo->name);
3076                         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3077                                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3078                         break;
3079
3080                 case FT_BOOLEAN:
3081                         fill_label_boolean(fi, label_str);
3082                         break;
3083
3084                 case FT_BYTES:
3085                 case FT_UINT_BYTES:
3086                         bytes = fvalue_get(&fi->value);
3087                         if (bytes) {
3088                                 ret = snprintf(label_str, ITEM_LABEL_LENGTH,
3089                                         "%s: %s", hfinfo->name,
3090                                          bytes_to_str(bytes, fvalue_length(&fi->value)));
3091                                 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3092                                         label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3093                         }
3094                         else {
3095                                 ret = snprintf(label_str, ITEM_LABEL_LENGTH,
3096                                         "%s: <MISSING>", hfinfo->name);
3097                                 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3098                                         label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3099                         }
3100                         break;
3101
3102                 /* Four types of integers to take care of:
3103                  *      Bitfield, with val_string
3104                  *      Bitfield, w/o val_string
3105                  *      Non-bitfield, with val_string
3106                  *      Non-bitfield, w/o val_string
3107                  */
3108                 case FT_UINT8:
3109                 case FT_UINT16:
3110                 case FT_UINT24:
3111                 case FT_UINT32:
3112                 case FT_FRAMENUM:
3113                         if (hfinfo->bitmask) {
3114                                 if (hfinfo->strings) {
3115                                         fill_label_enumerated_bitfield(fi, label_str);
3116                                 }
3117                                 else {
3118                                         fill_label_numeric_bitfield(fi, label_str);
3119                                 }
3120                         }
3121                         else {
3122                                 if (hfinfo->strings) {
3123                                         fill_label_enumerated_uint(fi, label_str);
3124                                 }
3125                                 else {
3126                                         fill_label_uint(fi, label_str);
3127                                 }
3128                         }
3129                         break;
3130
3131                 case FT_UINT64:
3132                         fill_label_uint64(fi, label_str);
3133                         break;
3134
3135                 case FT_INT8:
3136                 case FT_INT16:
3137                 case FT_INT24:
3138                 case FT_INT32:
3139                         DISSECTOR_ASSERT(!hfinfo->bitmask);
3140                         if (hfinfo->strings) {
3141                                 fill_label_enumerated_int(fi, label_str);
3142                         }
3143                         else {
3144                                 fill_label_int(fi, label_str);
3145                         }
3146                         break;
3147
3148                 case FT_INT64:
3149                         fill_label_int64(fi, label_str);
3150                         break;
3151
3152                 case FT_FLOAT:
3153                         ret = snprintf(label_str, ITEM_LABEL_LENGTH,
3154                                 "%s: %." STRINGIFY(FLT_DIG) "f",
3155                                 hfinfo->name, fvalue_get_floating(&fi->value));
3156                         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3157                                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3158                         break;
3159
3160                 case FT_DOUBLE:
3161                         ret = snprintf(label_str, ITEM_LABEL_LENGTH,
3162                                 "%s: %." STRINGIFY(DBL_DIG) "g",
3163                                 hfinfo->name, fvalue_get_floating(&fi->value));
3164                         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3165                                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3166                         break;
3167
3168                 case FT_ABSOLUTE_TIME:
3169                         ret = snprintf(label_str, ITEM_LABEL_LENGTH,
3170                                 "%s: %s", hfinfo->name,
3171                                 abs_time_to_str(fvalue_get(&fi->value)));
3172                         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3173                                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3174                         break;
3175
3176                 case FT_RELATIVE_TIME:
3177                         ret = snprintf(label_str, ITEM_LABEL_LENGTH,
3178                                 "%s: %s seconds", hfinfo->name,
3179                                 rel_time_to_secs_str(fvalue_get(&fi->value)));
3180                         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3181                                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3182                         break;
3183
3184                 case FT_IPXNET:
3185                         integer = fvalue_get_integer(&fi->value);
3186                         ret = snprintf(label_str, ITEM_LABEL_LENGTH,
3187                                 "%s: %s (0x%08X)", hfinfo->name,
3188                                 get_ipxnet_name(integer), integer);
3189                         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3190                                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3191                         break;
3192
3193                 case FT_ETHER:
3194                         bytes = fvalue_get(&fi->value);
3195                         ret = snprintf(label_str, ITEM_LABEL_LENGTH,
3196                                 "%s: %s (%s)", hfinfo->name,
3197                                 get_ether_name(bytes),
3198                                 ether_to_str(bytes));
3199                         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3200                                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3201                         break;
3202
3203                 case FT_IPv4:
3204                         ipv4 = fvalue_get(&fi->value);
3205                         n_addr = ipv4_get_net_order_addr(ipv4);
3206                         ret = snprintf(label_str, ITEM_LABEL_LENGTH,
3207                                 "%s: %s (%s)", hfinfo->name,
3208                                 get_hostname(n_addr),
3209                                 ip_to_str((guint8*)&n_addr));
3210                         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3211                                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3212                         break;
3213
3214                 case FT_IPv6:
3215                         bytes = fvalue_get(&fi->value);
3216                         ret = snprintf(label_str, ITEM_LABEL_LENGTH,
3217                                 "%s: %s (%s)", hfinfo->name,
3218                                 get_hostname6((struct e_in6_addr *)bytes),
3219                                 ip6_to_str((struct e_in6_addr*)bytes));
3220                         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3221                                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3222                         break;
3223
3224                 case FT_GUID:
3225                         bytes = fvalue_get(&fi->value);
3226                         ret = snprintf(label_str, ITEM_LABEL_LENGTH,
3227                                 "%s: %s", hfinfo->name,
3228                                  guid_to_str(bytes));
3229                         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3230                                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3231                         break;
3232
3233                 case FT_STRING:
3234                 case FT_STRINGZ:
3235                 case FT_UINT_STRING:
3236                         bytes = fvalue_get(&fi->value);
3237             if(strlen(bytes) > ITEM_LABEL_LENGTH) {
3238                             ret = snprintf(label_str, ITEM_LABEL_LENGTH,
3239                                     "%s [truncated]: %s", hfinfo->name,
3240                                     format_text(bytes, strlen(bytes)));
3241             } else {
3242                             ret = snprintf(label_str, ITEM_LABEL_LENGTH,
3243                                     "%s: %s", hfinfo->name,
3244                                     format_text(bytes, strlen(bytes)));
3245             }
3246                         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3247                                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3248                         break;
3249
3250                 default:
3251                         g_error("hfinfo->type %d (%s) not handled\n",
3252                                         hfinfo->type,
3253                                         ftype_name(hfinfo->type));
3254                         DISSECTOR_ASSERT_NOT_REACHED();
3255                         break;
3256         }
3257 }
3258
3259 static void
3260 fill_label_boolean(field_info *fi, gchar *label_str)
3261 {
3262         char    *p = label_str;
3263         int     bitfield_byte_length = 0, bitwidth;
3264         guint32 unshifted_value;
3265         guint32 value;
3266         int                                     ret;    /*tmp return value */
3267
3268         header_field_info               *hfinfo = fi->hfinfo;
3269         static const true_false_string  default_tf = { "True", "False" };
3270         const true_false_string         *tfstring = &default_tf;
3271
3272         if (hfinfo->strings) {
3273                 tfstring = (const struct true_false_string*) hfinfo->strings;
3274         }
3275
3276         value = fvalue_get_integer(&fi->value);
3277         if (hfinfo->bitmask) {
3278                 /* Figure out the bit width */
3279                 bitwidth = hfinfo_bitwidth(hfinfo);
3280
3281                 /* Un-shift bits */
3282                 unshifted_value = value;
3283                 if (hfinfo->bitshift > 0) {
3284                         unshifted_value <<= hfinfo->bitshift;
3285                 }
3286
3287                 /* Create the bitfield first */
3288                 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
3289                 bitfield_byte_length = p - label_str;
3290         }
3291
3292         /* Fill in the textual info */
3293         ret = snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
3294                 "%s: %s",  hfinfo->name,
3295                 value ? tfstring->true_string : tfstring->false_string);
3296         if ((ret == -1) || (ret >= (ITEM_LABEL_LENGTH - bitfield_byte_length)))
3297                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3298 }
3299
3300
3301 /* Fills data for bitfield ints with val_strings */
3302 static void
3303 fill_label_enumerated_bitfield(field_info *fi, gchar *label_str)
3304 {
3305         char *format = NULL, *p;
3306         int bitfield_byte_length, bitwidth;
3307         guint32 unshifted_value;
3308         guint32 value;
3309         int                                     ret;    /*tmp return value */
3310
3311         header_field_info       *hfinfo = fi->hfinfo;
3312
3313         /* Figure out the bit width */
3314         bitwidth = hfinfo_bitwidth(hfinfo);
3315
3316         /* Pick the proper format string */
3317         format = hfinfo_uint_vals_format(hfinfo);
3318
3319         /* Un-shift bits */
3320         unshifted_value = fvalue_get_integer(&fi->value);
3321         value = unshifted_value;
3322         if (hfinfo->bitshift > 0) {
3323                 unshifted_value <<= hfinfo->bitshift;
3324         }
3325
3326         /* Create the bitfield first */
3327         p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
3328         bitfield_byte_length = p - label_str;
3329
3330         /* Fill in the textual info using stored (shifted) value */
3331         ret = snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
3332                         format,  hfinfo->name,
3333                         val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
3334         if ((ret == -1) || (ret >= (ITEM_LABEL_LENGTH - bitfield_byte_length)))
3335                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3336 }
3337
3338 static void
3339 fill_label_numeric_bitfield(field_info *fi, gchar *label_str)
3340 {
3341         char *format = NULL, *p;
3342         int bitfield_byte_length, bitwidth;
3343         guint32 unshifted_value;
3344         guint32 value;
3345         int                                     ret;    /*tmp return value */
3346
3347         header_field_info       *hfinfo = fi->hfinfo;
3348
3349         /* Figure out the bit width */
3350         bitwidth = hfinfo_bitwidth(hfinfo);
3351
3352         /* Pick the proper format string */
3353         format = hfinfo_uint_format(hfinfo);
3354
3355         /* Un-shift bits */
3356         unshifted_value = fvalue_get_integer(&fi->value);
3357         value = unshifted_value;
3358         if (hfinfo->bitshift > 0) {
3359                 unshifted_value <<= hfinfo->bitshift;
3360         }
3361
3362         /* Create the bitfield using */
3363         p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
3364         bitfield_byte_length = p - label_str;
3365
3366         /* Fill in the textual info using stored (shifted) value */
3367         ret = snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
3368                         format,  hfinfo->name, value);
3369         if ((ret == -1) || (ret >= (ITEM_LABEL_LENGTH - bitfield_byte_length)))
3370                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3371
3372 }
3373
3374 static void
3375 fill_label_enumerated_uint(field_info *fi, gchar *label_str)
3376 {
3377         char *format = NULL;
3378         header_field_info       *hfinfo = fi->hfinfo;
3379         guint32 value;
3380         int                                     ret;    /*tmp return value */
3381
3382         /* Pick the proper format string */
3383         format = hfinfo_uint_vals_format(hfinfo);
3384
3385         value = fvalue_get_integer(&fi->value);
3386
3387         /* Fill in the textual info */
3388         ret = snprintf(label_str, ITEM_LABEL_LENGTH,
3389                         format,  hfinfo->name,
3390                         val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
3391         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3392                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3393 }
3394
3395 static void
3396 fill_label_uint(field_info *fi, gchar *label_str)
3397 {
3398         char *format = NULL;
3399         header_field_info       *hfinfo = fi->hfinfo;
3400         guint32 value;
3401         int                                     ret;    /*tmp return value */
3402
3403         /* Pick the proper format string */
3404         format = hfinfo_uint_format(hfinfo);
3405         value = fvalue_get_integer(&fi->value);
3406
3407         /* Fill in the textual info */
3408         ret = snprintf(label_str, ITEM_LABEL_LENGTH,
3409                         format,  hfinfo->name, value);
3410         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3411                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3412 }
3413
3414 static void
3415 fill_label_uint64(field_info *fi, gchar *label_str)
3416 {
3417         char *format = NULL;
3418         header_field_info       *hfinfo = fi->hfinfo;
3419         guint64 value;
3420         int                                     ret;    /*tmp return value */
3421
3422         /* Pick the proper format string */
3423         format = hfinfo_uint64_format(hfinfo);
3424         value = fvalue_get_integer64(&fi->value);
3425
3426         /* Fill in the textual info */
3427         ret = snprintf(label_str, ITEM_LABEL_LENGTH,
3428                         format,  hfinfo->name, value);
3429         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3430                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3431 }
3432
3433 static void
3434 fill_label_enumerated_int(field_info *fi, gchar *label_str)
3435 {
3436         char *format = NULL;
3437         header_field_info       *hfinfo = fi->hfinfo;
3438         guint32 value;
3439         int                                     ret;    /*tmp return value */
3440
3441         /* Pick the proper format string */
3442         format = hfinfo_int_vals_format(hfinfo);
3443         value = fvalue_get_integer(&fi->value);
3444
3445         /* Fill in the textual info */
3446         ret = snprintf(label_str, ITEM_LABEL_LENGTH,
3447                         format,  hfinfo->name,
3448                         val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
3449         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3450                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3451 }
3452
3453 static void
3454 fill_label_int(field_info *fi, gchar *label_str)
3455 {
3456         char *format = NULL;
3457         header_field_info       *hfinfo = fi->hfinfo;
3458         guint32 value;
3459         int                                     ret;    /*tmp return value */
3460
3461         /* Pick the proper format string */
3462         format = hfinfo_int_format(hfinfo);
3463         value = fvalue_get_integer(&fi->value);
3464
3465         /* Fill in the textual info */
3466         ret = snprintf(label_str, ITEM_LABEL_LENGTH,
3467                         format,  hfinfo->name, value);
3468         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3469                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3470 }
3471
3472 static void
3473 fill_label_int64(field_info *fi, gchar *label_str)
3474 {
3475         char *format = NULL;
3476         header_field_info       *hfinfo = fi->hfinfo;
3477         guint64 value;
3478         int                                     ret;    /*tmp return value */
3479
3480         /* Pick the proper format string */
3481         format = hfinfo_int64_format(hfinfo);
3482         value = fvalue_get_integer64(&fi->value);
3483
3484         /* Fill in the textual info */
3485         ret = snprintf(label_str, ITEM_LABEL_LENGTH,
3486                         format,  hfinfo->name, value);
3487         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3488                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3489 }
3490
3491 int
3492 hfinfo_bitwidth(header_field_info *hfinfo)
3493 {
3494         int bitwidth = 0;
3495
3496         if (!hfinfo->bitmask) {
3497                 return 0;
3498         }
3499
3500         switch(hfinfo->type) {
3501                 case FT_UINT8:
3502                 case FT_INT8:
3503                         bitwidth = 8;
3504                         break;
3505                 case FT_UINT16:
3506                 case FT_INT16:
3507                         bitwidth = 16;
3508                         break;
3509                 case FT_UINT24:
3510                 case FT_INT24:
3511                         bitwidth = 24;
3512                         break;
3513                 case FT_UINT32:
3514                 case FT_INT32:
3515                         bitwidth = 32;
3516                         break;
3517                 case FT_BOOLEAN:
3518                         bitwidth = hfinfo->display; /* hacky? :) */
3519                         break;
3520                 default:
3521                         DISSECTOR_ASSERT_NOT_REACHED();
3522                         ;
3523         }
3524         return bitwidth;
3525 }
3526
3527 static char*
3528 hfinfo_uint_vals_format(header_field_info *hfinfo)
3529 {
3530         char *format = NULL;
3531
3532         switch(hfinfo->display) {
3533                 case BASE_DEC:
3534                         format = "%s: %s (%u)";
3535                         break;
3536                 case BASE_OCT: /* I'm lazy */
3537                         format = "%s: %s (%o)";
3538                         break;
3539                 case BASE_HEX:
3540                         switch(hfinfo->type) {
3541                                 case FT_UINT8:
3542                                         format = "%s: %s (0x%02x)";
3543                                         break;
3544                                 case FT_UINT16:
3545                                         format = "%s: %s (0x%04x)";
3546                                         break;
3547                                 case FT_UINT24:
3548                                         format = "%s: %s (0x%06x)";
3549                                         break;
3550                                 case FT_UINT32:
3551                                         format = "%s: %s (0x%08x)";
3552                                         break;
3553                                 default:
3554                                         DISSECTOR_ASSERT_NOT_REACHED();
3555                                         ;
3556                         }
3557                         break;
3558                 default:
3559                         DISSECTOR_ASSERT_NOT_REACHED();
3560                         ;
3561         }
3562         return format;
3563 }
3564
3565 static char*
3566 hfinfo_uint_format(header_field_info *hfinfo)
3567 {
3568         char *format = NULL;
3569
3570         /* Pick the proper format string */
3571         if (hfinfo->type == FT_FRAMENUM) {
3572                 /*
3573                  * Frame numbers are always displayed in decimal.
3574                  */
3575                 format = "%s: %u";
3576         } else {
3577                 switch(hfinfo->display) {
3578                         case BASE_DEC:
3579                                 format = "%s: %u";
3580                                 break;
3581                         case BASE_OCT: /* I'm lazy */
3582                                 format = "%s: %o";
3583                                 break;
3584                         case BASE_HEX:
3585                                 switch(hfinfo->type) {
3586                                         case FT_UINT8:
3587                                                 format = "%s: 0x%02x";
3588                                                 break;
3589                                         case FT_UINT16:
3590                                                 format = "%s: 0x%04x";
3591                                                 break;
3592                                         case FT_UINT24:
3593                                                 format = "%s: 0x%06x";
3594                                                 break;
3595                                         case FT_UINT32:
3596                                                 format = "%s: 0x%08x";
3597                                                 break;
3598                                         default:
3599                                                 DISSECTOR_ASSERT_NOT_REACHED();
3600                                                 ;
3601                                 }
3602                                 break;
3603                         default:
3604                                 DISSECTOR_ASSERT_NOT_REACHED();
3605                                 ;
3606                 }
3607         }
3608         return format;
3609 }
3610
3611 static char*
3612 hfinfo_int_vals_format(header_field_info *hfinfo)
3613 {
3614         char *format = NULL;
3615
3616         switch(hfinfo->display) {
3617                 case BASE_DEC:
3618                         format = "%s: %s (%d)";
3619                         break;
3620                 case BASE_OCT: /* I'm lazy */
3621                         format = "%s: %s (%o)";
3622                         break;
3623                 case BASE_HEX:
3624                         switch(hfinfo->type) {
3625                                 case FT_INT8:
3626                                         format = "%s: %s (0x%02x)";
3627                                         break;
3628                                 case FT_INT16:
3629                                         format = "%s: %s (0x%04x)";
3630                                         break;
3631                                 case FT_INT24:
3632                                         format = "%s: %s (0x%06x)";
3633                                         break;
3634                                 case FT_INT32:
3635                                         format = "%s: %s (0x%08x)";
3636                                         break;
3637                                 default:
3638                                         DISSECTOR_ASSERT_NOT_REACHED();
3639                                         ;
3640                         }
3641                         break;
3642                 default:
3643                         DISSECTOR_ASSERT_NOT_REACHED();
3644                         ;
3645         }
3646         return format;
3647 }
3648
3649 static char*
3650 hfinfo_uint64_format(header_field_info *hfinfo)
3651 {
3652         char *format = NULL;
3653
3654         /* Pick the proper format string */
3655         switch(hfinfo->display) {
3656                 case BASE_DEC:
3657                         format = "%s: %" PRIu64;
3658                         break;
3659                 case BASE_OCT: /* I'm lazy */
3660                         format = "%s: %" PRIo64;
3661                         break;
3662                 case BASE_HEX:
3663                         format = "%s: 0x%016" PRIx64;
3664                         break;
3665                 default:
3666                         DISSECTOR_ASSERT_NOT_REACHED();
3667                         ;
3668         }
3669         return format;
3670 }
3671
3672 static char*
3673 hfinfo_int_format(header_field_info *hfinfo)
3674 {
3675         char *format = NULL;
3676
3677         /* Pick the proper format string */
3678         switch(hfinfo->display) {
3679                 case BASE_DEC:
3680                         format = "%s: %d";
3681                         break;
3682                 case BASE_OCT: /* I'm lazy */
3683                         format = "%s: %o";
3684                         break;
3685                 case BASE_HEX:
3686                         switch(hfinfo->type) {
3687                                 case FT_INT8:
3688                                         format = "%s: 0x%02x";
3689                                         break;
3690                                 case FT_INT16:
3691                                         format = "%s: 0x%04x";
3692                                         break;
3693                                 case FT_INT24:
3694                                         format = "%s: 0x%06x";
3695                                         break;
3696                                 case FT_INT32:
3697                                         format = "%s: 0x%08x";
3698                                         break;
3699                                 default:
3700                                         DISSECTOR_ASSERT_NOT_REACHED();
3701                                         ;
3702                         }
3703                         break;
3704                 default:
3705                         DISSECTOR_ASSERT_NOT_REACHED();
3706                         ;
3707         }
3708         return format;
3709 }
3710
3711 static char*
3712 hfinfo_int64_format(header_field_info *hfinfo)
3713 {
3714         char *format = NULL;
3715
3716         /* Pick the proper format string */
3717         switch(hfinfo->display) {
3718                 case BASE_DEC:
3719                         format = "%s: %" PRId64;
3720                         break;
3721                 case BASE_OCT: /* I'm lazy */
3722                         format = "%s: %" PRIo64;
3723                         break;
3724                 case BASE_HEX:
3725                         format = "%s: 0x%016" PRIx64;
3726                         break;
3727                 default:
3728                         DISSECTOR_ASSERT_NOT_REACHED();
3729                         ;
3730         }
3731         return format;
3732 }
3733
3734
3735
3736 int
3737 proto_registrar_n(void)
3738 {
3739         return gpa_hfinfo.len;
3740 }
3741
3742 const char*
3743 proto_registrar_get_name(int n)
3744 {
3745         header_field_info *hfinfo;
3746
3747         PROTO_REGISTRAR_GET_NTH(n, hfinfo);
3748         return hfinfo->name;
3749 }
3750
3751 const char*
3752 proto_registrar_get_abbrev(int n)
3753 {
3754         header_field_info *hfinfo;
3755
3756         PROTO_REGISTRAR_GET_NTH(n, hfinfo);
3757         return hfinfo->abbrev;
3758 }
3759
3760 int
3761 proto_registrar_get_ftype(int n)
3762 {
3763         header_field_info *hfinfo;
3764
3765         PROTO_REGISTRAR_GET_NTH(n, hfinfo);
3766         return hfinfo->type;
3767 }
3768
3769 int
3770 proto_registrar_get_parent(int n)
3771 {
3772         header_field_info *hfinfo;
3773
3774         PROTO_REGISTRAR_GET_NTH(n, hfinfo);
3775         return hfinfo->parent;
3776 }
3777
3778 gboolean
3779 proto_registrar_is_protocol(int n)
3780 {
3781         header_field_info *hfinfo;
3782
3783         PROTO_REGISTRAR_GET_NTH(n, hfinfo);
3784         return (hfinfo->parent == -1 ? TRUE : FALSE);
3785 }
3786
3787 /* Returns length of field in packet (not necessarily the length
3788  * in our internal representation, as in the case of IPv4).
3789  * 0 means undeterminable at time of registration
3790  * -1 means the field is not registered. */
3791 gint
3792 proto_registrar_get_length(int n)
3793 {
3794         header_field_info *hfinfo;
3795
3796         PROTO_REGISTRAR_GET_NTH(n, hfinfo);
3797         return ftype_length(hfinfo->type);
3798 }
3799
3800
3801
3802 /* Looks for a protocol or a field in a proto_tree. Returns TRUE if
3803  * it exists anywhere, or FALSE if it exists nowhere. */
3804 gboolean
3805 proto_check_for_protocol_or_field(proto_tree* tree, int id)
3806 {
3807         GPtrArray *ptrs = proto_get_finfo_ptr_array(tree, id);
3808
3809         if (!ptrs) {
3810                 return FALSE;
3811         }
3812         else if (g_ptr_array_len(ptrs) > 0) {
3813                 return TRUE;
3814         }
3815         else {
3816                 return FALSE;
3817         }
3818 }
3819
3820 /* Return GPtrArray* of field_info pointers for all hfindex that appear in tree.
3821  * This only works if the hfindex was "primed" before the dissection
3822  * took place, as we just pass back the already-created GPtrArray*.
3823  * The caller should *not* free the GPtrArray*; proto_tree_free_node()
3824  * handles that. */
3825 GPtrArray*
3826 proto_get_finfo_ptr_array(proto_tree *tree, int id)
3827 {
3828         return g_hash_table_lookup(PTREE_DATA(tree)->interesting_hfids,
3829             GINT_TO_POINTER(id));
3830 }
3831
3832
3833 /* Helper struct and function for proto_find_info() */
3834 typedef struct {
3835         GPtrArray       *array;
3836         int             id;
3837 } ffdata_t;
3838
3839 static gboolean
3840 find_finfo(proto_node *node, gpointer data)
3841 {
3842         field_info *fi = PITEM_FINFO(node);
3843         if (fi && fi->hfinfo) {
3844                 if (fi->hfinfo->id == ((ffdata_t*)data)->id) {
3845                         g_ptr_array_add(((ffdata_t*)data)->array, fi);
3846                 }
3847         }
3848
3849         /* Don't stop traversing. */
3850         return FALSE;
3851 }
3852
3853 /* Return GPtrArray* of field_info pointers for all hfindex that appear in a tree.
3854  * This works on any proto_tree, primed or unprimed, but actually searches
3855  * the tree, so it is slower than using proto_get_finfo_ptr_array on a primed tree.
3856  * The caller does need to free the returned GPtrArray with
3857  * g_ptr_array_free(<array>, FALSE).
3858  */
3859 GPtrArray*
3860 proto_find_finfo(proto_tree *tree, int id)
3861 {
3862         ffdata_t        ffdata;
3863
3864         ffdata.array = g_ptr_array_new();
3865         ffdata.id = id;
3866
3867         proto_tree_traverse_pre_order(tree, find_finfo, &ffdata);
3868
3869         return ffdata.array;
3870 }       
3871
3872
3873 typedef struct {
3874         guint           offset;
3875         field_info      *finfo;
3876         tvbuff_t        *tvb;
3877 } offset_search_t;
3878
3879 static gboolean
3880 check_for_offset(proto_node *node, gpointer data)
3881 {
3882         field_info          *fi = PITEM_FINFO(node);
3883         offset_search_t         *offsearch = data;
3884
3885         /* !fi == the top most container node which holds nothing */
3886         if (fi && !PROTO_ITEM_IS_HIDDEN(node) && fi->ds_tvb && offsearch->tvb == fi->ds_tvb) {
3887                 if (offsearch->offset >= (guint) fi->start &&
3888                                 offsearch->offset < (guint) (fi->start + fi->length)) {
3889
3890                         offsearch->finfo = fi;
3891                         return FALSE; /* keep traversing */
3892                 }
3893         }
3894         return FALSE; /* keep traversing */
3895 }
3896
3897 /* Search a proto_tree backwards (from leaves to root) looking for the field
3898  * whose start/length occupies 'offset' */
3899 /* XXX - I couldn't find an easy way to search backwards, so I search
3900  * forwards, w/o stopping. Therefore, the last finfo I find will the be
3901  * the one I want to return to the user. This algorithm is inefficient
3902  * and could be re-done, but I'd have to handle all the children and
3903  * siblings of each node myself. When I have more time I'll do that.
3904  * (yeah right) */
3905 field_info*
3906 proto_find_field_from_offset(proto_tree *tree, guint offset, tvbuff_t *tvb)
3907 {
3908         offset_search_t         offsearch;
3909
3910         offsearch.offset = offset;
3911         offsearch.finfo = NULL;
3912         offsearch.tvb = tvb;
3913
3914         proto_tree_traverse_pre_order(tree, check_for_offset, &offsearch);
3915
3916         return offsearch.finfo;
3917 }
3918
3919 /* Dumps the protocols in the registration database to stdout.  An independent
3920  * program can take this output and format it into nice tables or HTML or
3921  * whatever.
3922  *
3923  * There is one record per line. The fields are tab-delimited.
3924  *
3925  * Field 1 = protocol name
3926  * Field 2 = protocol short name
3927  * Field 3 = protocol filter name
3928  */
3929 void
3930 proto_registrar_dump_protocols(void)
3931 {
3932         protocol_t              *protocol;
3933         int                     i;
3934         void                    *cookie;
3935
3936         for (i = proto_get_first_protocol(&cookie); i != -1;
3937             i = proto_get_next_protocol(&cookie)) {
3938                 protocol = find_protocol_by_id(i);
3939                 printf("%s\t%s\t%s\n", protocol->name, protocol->short_name,
3940                     protocol->filter_name);
3941         }
3942 }
3943
3944 /* Dumps the value_string and true/false strings for fields that have
3945  * them. There is one record per line. Fields are tab-delimited.
3946  * There are two types of records, Value String records and True/False
3947  * String records. The first field, 'V' or 'T', indicates the type
3948  * of record.
3949  *
3950  * Value Strings
3951  * -------------
3952  * Field 1 = 'V'
3953  * Field 2 = field abbreviation to which this value string corresponds
3954  * Field 3 = Integer value
3955  * Field 4 = String
3956  *
3957  * True/False Strings
3958  * ------------------
3959  * Field 1 = 'T'
3960  * Field 2 = field abbreviation to which this true/false string corresponds
3961  * Field 3 = True String
3962  * Field 4 = False String
3963  */
3964 void
3965 proto_registrar_dump_values(void)
3966 {
3967         header_field_info       *hfinfo, *parent_hfinfo;
3968         int                     i, len, vi;
3969         const value_string      *vals;
3970         const true_false_string *tfs;
3971
3972         len = gpa_hfinfo.len;
3973         for (i = 0; i < len ; i++) {
3974                 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
3975
3976                  if (hfinfo->id == hf_text_only) {
3977                          continue;
3978                  }
3979
3980                 /* ignore protocols */
3981                 if (proto_registrar_is_protocol(i)) {
3982                         continue;
3983                 }
3984                 /* process header fields */
3985                 else {
3986                         /*
3987                          * If this field isn't at the head of the list of
3988                          * fields with this name, skip this field - all
3989                          * fields with the same name are really just versions
3990                          * of the same field stored in different bits, and
3991                          * should have the same type/radix/value list, and
3992                          * just differ in their bit masks.  (If a field isn't
3993                          * a bitfield, but can be, say, 1 or 2 bytes long,
3994                          * it can just be made FT_UINT16, meaning the
3995                          * *maximum* length is 2 bytes, and be used
3996                          * for all lengths.)
3997                          */
3998                         if (hfinfo->same_name_prev != NULL)
3999                                 continue;
4000
4001                         PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
4002
4003                         vals = NULL;
4004                         tfs = NULL;
4005
4006                         if (hfinfo->type == FT_UINT8 ||
4007                                 hfinfo->type == FT_UINT16 ||
4008                                 hfinfo->type == FT_UINT24 ||
4009                                 hfinfo->type == FT_UINT32 ||
4010                                 hfinfo->type == FT_UINT64 ||
4011                                 hfinfo->type == FT_INT8 ||
4012                                 hfinfo->type == FT_INT16 ||
4013                                 hfinfo->type == FT_INT24 ||
4014                                 hfinfo->type == FT_INT32 ||
4015                                 hfinfo->type == FT_INT64) {
4016
4017                                 vals = hfinfo->strings;
4018                         }
4019                         else if (hfinfo->type == FT_BOOLEAN) {
4020                                 tfs = hfinfo->strings;
4021                         }
4022
4023                         /* Print value strings? */
4024                         if (vals) {
4025                                 vi = 0;
4026                                 while (vals[vi].strptr) {
4027                                         /* Print in the proper base */
4028                                         if (hfinfo->display == BASE_HEX) {
4029                                                 printf("V\t%s\t0x%x\t%s\n",
4030                                                                 hfinfo->abbrev,
4031                                                                 vals[vi].value,
4032                                                                 vals[vi].strptr);
4033                                         }
4034                                         else {
4035                                                 printf("V\t%s\t%u\t%s\n",
4036                                                                 hfinfo->abbrev,
4037                                                                 vals[vi].value,
4038                                                                 vals[vi].strptr);
4039                                         }
4040                                         vi++;
4041                                 }
4042                         }
4043
4044                         /* Print true/false strings? */
4045                         else if (tfs) {
4046                                 printf("T\t%s\t%s\t%s\n", hfinfo->abbrev,
4047                                                 tfs->true_string, tfs->false_string);
4048                         }
4049                 }
4050         }
4051 }
4052
4053 /* Dumps the contents of the registration database to stdout. An indepedent
4054  * program can take this output and format it into nice tables or HTML or
4055  * whatever.
4056  *
4057  * There is one record per line. Each record is either a protocol or a header
4058  * field, differentiated by the first field. The fields are tab-delimited.
4059  *
4060  * Protocols
4061  * ---------
4062  * Field 1 = 'P'
4063  * Field 2 = descriptive protocol name
4064  * Field 3 = protocol abbreviation
4065  *
4066  * Header Fields
4067  * -------------
4068  * (format 1)
4069  * Field 1 = 'F'
4070  * Field 2 = descriptive field name
4071  * Field 3 = field abbreviation
4072  * Field 4 = type ( textual representation of the the ftenum type )
4073  * Field 5 = parent protocol abbreviation
4074  * Field 6 = blurb describing field
4075  *
4076  * (format 2)
4077  * Field 1 = 'F'
4078  * Field 2 = descriptive field name
4079  * Field 3 = field abbreviation
4080  * Field 4 = type ( textual representation of the the ftenum type )
4081  * Field 5 = parent protocol abbreviation
4082  * Field 6 = blurb describing field
4083  * Field 7 = base for display (for integer types)
4084  * Field 8 = blurb describing field (yes, apparently we repeated this accidentally)
4085  *
4086  * (format 3)
4087  * Field 1 = 'F'
4088  * Field 2 = descriptive field name
4089  * Field 3 = field abbreviation
4090  * Field 4 = type ( textual representation of the the ftenum type )
4091  * Field 5 = parent protocol abbreviation
4092  * Field 6 = blurb describing field
4093  * Field 7 = base for display (for integer types)
4094  * Field 8 = bitmask
4095  */
4096 void
4097 proto_registrar_dump_fields(int format)
4098 {
4099         header_field_info       *hfinfo, *parent_hfinfo;
4100         int                     i, len;
4101         const char              *enum_name;
4102         const char              *base_name;
4103
4104         len = gpa_hfinfo.len;
4105         for (i = 0; i < len ; i++) {
4106                 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
4107
4108                 /*
4109                  * Skip fields with zero-length names or abbreviations;
4110                  * the pseudo-field for "proto_tree_add_text()" is such
4111                  * a field, and we don't want it in the list of filterable
4112                  * fields.
4113                  *
4114                  *
4115                  * XXX - perhaps the name and abbrev field should be null
4116                  * pointers rather than null strings for that pseudo-field,
4117                  * but we'd have to add checks for null pointers in some
4118                  * places if we did that.
4119                  *
4120                  * Or perhaps protocol tree items added with
4121                  * "proto_tree_add_text()" should have -1 as the field index,
4122                  * with no pseudo-field being used, but that might also
4123                  * require special checks for -1 to be added.
4124                  */
4125                 /* XXX - we could just skip the special text
4126                  * pseudo-field by testing: if (hfinfo->id == hf_text_only)
4127                  * */
4128                 if (hfinfo->name[0] == 0 || hfinfo->abbrev[0] == 0)
4129                         continue;
4130
4131                 /* format for protocols */
4132                 if (proto_registrar_is_protocol(i)) {
4133                         printf("P\t%s\t%s\n", hfinfo->name, hfinfo->abbrev);
4134                 }
4135                 /* format for header fields */
4136                 else {
4137                         /*
4138                          * If this field isn't at the head of the list of
4139                          * fields with this name, skip this field - all
4140                          * fields with the same name are really just versions
4141                          * of the same field stored in different bits, and
4142                          * should have the same type/radix/value list, and
4143                          * just differ in their bit masks.  (If a field isn't
4144                          * a bitfield, but can be, say, 1 or 2 bytes long,
4145                          * it can just be made FT_UINT16, meaning the
4146                          * *maximum* length is 2 bytes, and be used
4147                          * for all lengths.)
4148                          */
4149                         if (hfinfo->same_name_prev != NULL)
4150                                 continue;
4151
4152                         PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
4153
4154                         enum_name = ftype_name(hfinfo->type);
4155                         base_name = "";
4156
4157                         if (format > 1) {
4158                                 if (hfinfo->type == FT_UINT8 ||
4159                                         hfinfo->type == FT_UINT16 ||
4160                                         hfinfo->type == FT_UINT24 ||
4161                                         hfinfo->type == FT_UINT32 ||
4162                                         hfinfo->type == FT_UINT64 ||
4163                                         hfinfo->type == FT_INT8 ||
4164                                         hfinfo->type == FT_INT16 ||
4165                                         hfinfo->type == FT_INT24 ||
4166                                         hfinfo->type == FT_INT32 ||
4167                                         hfinfo->type == FT_INT64) {
4168
4169                                         
4170                                         switch(hfinfo->display) {
4171                                                 case BASE_NONE:
4172                                                         base_name = "BASE_NONE";
4173                                                         break;
4174                                                 case BASE_DEC:
4175                                                         base_name = "BASE_DEC";
4176                                                         break;
4177                                                 case BASE_HEX:
4178                                                         base_name = "BASE_HEX";
4179                                                         break;
4180                                                 case BASE_OCT:
4181                                                         base_name = "BASE_OCT";
4182                                                         break;
4183                                         }
4184                                 }
4185                         }
4186
4187                         if (format == 1) {
4188                                 printf("F\t%s\t%s\t%s\t%s\t%s\n", hfinfo->name, hfinfo->abbrev,
4189                                         enum_name,parent_hfinfo->abbrev, hfinfo->blurb);
4190                         }
4191                         else if (format == 2) {
4192                                 printf("F\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n",
4193                                         hfinfo->name, hfinfo->abbrev,
4194                                         enum_name,parent_hfinfo->abbrev, hfinfo->blurb,
4195                                         base_name, hfinfo->blurb);
4196                         }
4197                         else if (format == 3) {
4198                                 printf("F\t%s\t%s\t%s\t%s\t%s\t%s\t%u\n",
4199                                         hfinfo->name, hfinfo->abbrev,
4200                                         enum_name,parent_hfinfo->abbrev, hfinfo->blurb,
4201                                         base_name, hfinfo->bitmask);
4202                         }
4203                         else {
4204                                 g_assert_not_reached();
4205                         }
4206                 }
4207         }
4208 }
4209
4210 static char*
4211 hfinfo_numeric_format(header_field_info *hfinfo)
4212 {
4213         char *format = NULL;
4214
4215         /* Pick the proper format string */
4216         if (hfinfo->type == FT_FRAMENUM) {
4217                 /*
4218                  * Frame numbers are always displayed in decimal.
4219                  */
4220                 format = "%s == %u";
4221         } else {
4222                 /* Pick the proper format string */
4223                 switch(hfinfo->display) {
4224                         case BASE_DEC:
4225                         case BASE_OCT: /* I'm lazy */
4226                                 switch(hfinfo->type) {
4227                                         case FT_UINT8:
4228                                         case FT_UINT16:
4229                                         case FT_UINT24:
4230                                         case FT_UINT32:
4231                                                 format = "%s == %u";
4232                                                 break;
4233                                         case FT_UINT64:
4234                                                 format = "%s == %" PRIu64;
4235                                                 break;
4236                                         case FT_INT8:
4237                                         case FT_INT16:
4238                                         case FT_INT24:
4239                                         case FT_INT32:
4240                                                 format = "%s == %d";
4241                                                 break;
4242                                         case FT_INT64:
4243                                                 format = "%s == %" PRId64;
4244                                                 break;
4245                                         default:
4246                                                 DISSECTOR_ASSERT_NOT_REACHED();
4247                                                 ;
4248                                 }
4249                                 break;
4250                         case BASE_HEX:
4251                                 switch(hfinfo->type) {
4252                                         case FT_UINT8:
4253                                                 format = "%s == 0x%02x";
4254                                                 break;
4255                                         case FT_UINT16:
4256                                                 format = "%s == 0x%04x";
4257                                                 break;
4258                                         case FT_UINT24:
4259                                                 format = "%s == 0x%06x";
4260                                                 break;
4261                                         case FT_UINT32:
4262                                                 format = "%s == 0x%08x";
4263                                                 break;
4264                                         case FT_UINT64:
4265                                                 format = "%s == 0x%016" PRIx64;
4266                                                 break;
4267                                         default:
4268                                                 DISSECTOR_ASSERT_NOT_REACHED();
4269                                                 ;
4270                                 }
4271                                 break;
4272                         default:
4273                                 DISSECTOR_ASSERT_NOT_REACHED();
4274                                 ;
4275                 }
4276         }
4277         return format;
4278 }
4279
4280 /*
4281  * Returns TRUE if we can do a "match selected" on the field, FALSE
4282  * otherwise.
4283  */
4284 gboolean
4285 proto_can_match_selected(field_info *finfo, epan_dissect_t *edt)
4286 {
4287         header_field_info       *hfinfo;
4288         gint                    length;
4289
4290         hfinfo = finfo->hfinfo;
4291         DISSECTOR_ASSERT(hfinfo);
4292
4293         switch(hfinfo->type) {
4294
4295                 case FT_BOOLEAN:
4296                 case FT_UINT8:
4297                 case FT_UINT16:
4298                 case FT_UINT24:
4299                 case FT_UINT32:
4300                 case FT_INT8:
4301                 case FT_INT16:
4302                 case FT_INT24:
4303                 case FT_INT32:
4304                 case FT_FRAMENUM:
4305                 case FT_UINT64:
4306                 case FT_INT64:
4307                 case FT_IPv4:
4308                 case FT_IPXNET:
4309                 case FT_IPv6:
4310                 case FT_FLOAT:
4311                 case FT_DOUBLE:
4312                 case FT_ABSOLUTE_TIME:
4313                 case FT_RELATIVE_TIME:
4314                 case FT_STRING:
4315                 case FT_STRINGZ:
4316                 case FT_UINT_STRING:
4317                 case FT_ETHER:
4318                 case FT_BYTES:
4319                 case FT_UINT_BYTES:
4320                 case FT_PROTOCOL:
4321                 case FT_GUID:
4322                         /*
4323                          * These all have values, so we can match.
4324                          */
4325                         return TRUE;
4326
4327                 default:
4328                         /*
4329                          * This doesn't have a value, so we'd match
4330                          * on the raw bytes at this address.
4331                          *
4332                          * Should we be allowed to access to the raw bytes?
4333                          * If "edt" is NULL, the answer is "no".
4334                          */
4335                         if (edt == NULL)
4336                                 return FALSE;
4337
4338                         /*
4339                          * Is this field part of the raw frame tvbuff?
4340                          * If not, we can't use "frame[N:M]" to match
4341                          * it.
4342                          *
4343                          * XXX - should this be frame-relative, or
4344                          * protocol-relative?
4345                          *
4346                          * XXX - does this fallback for non-registered
4347                          * fields even make sense?
4348                          */
4349                         if (finfo->ds_tvb != edt->tvb)
4350                                 return FALSE;
4351
4352                         /*
4353                          * If the length is 0, there's nothing to match, so
4354                          * we can't match.  (Also check for negative values,
4355                          * just in case, as we'll cast it to an unsigned
4356                          * value later.)
4357                          */
4358                         length = finfo->length;
4359                         if (length <= 0)
4360                                 return FALSE;
4361
4362                         /*
4363                          * Don't go past the end of that tvbuff.
4364                          */
4365                         if ((guint)length > tvb_length(finfo->ds_tvb))
4366                                 length = tvb_length(finfo->ds_tvb);
4367                         if (length <= 0)
4368                                 return FALSE;
4369                         return TRUE;
4370         }
4371 }
4372
4373 char*
4374 proto_construct_dfilter_string(field_info *finfo, epan_dissect_t *edt)
4375 {
4376         header_field_info       *hfinfo;
4377         int                     abbrev_len;
4378         char                    *buf, *stringified, *format, *ptr;
4379         int                     dfilter_len, i;
4380         gint                    start, length, length_remaining;
4381         guint8                  c;
4382
4383         hfinfo = finfo->hfinfo;
4384         DISSECTOR_ASSERT(hfinfo);
4385         abbrev_len = strlen(hfinfo->abbrev);
4386
4387         /*
4388          * XXX - we should add "val_to_string_repr" and "string_repr_len"
4389          * functions for more types, and use them whenever possible.
4390          *
4391          * The FT_UINT and FT_INT types are the only tricky ones, as
4392          * we choose the base in the string expression based on the
4393          * display base of the field.
4394          *
4395          * Note that the base does matter, as this is also used for
4396          * the protocolinfo tap.
4397          *
4398          * It might be nice to use that in "proto_item_fill_label()"
4399          * as well, although, there, you'd have to deal with the base
4400          * *and* with resolved values for addresses.
4401          *
4402          * Perhaps we need two different val_to_string routines, one
4403          * to generate items for display filters and one to generate
4404          * strings for display, and pass to both of them the
4405          * "display" and "strings" values in the header_field_info
4406          * structure for the field, so they can get the base and,
4407          * if the field is Boolean or an enumerated integer type,
4408          * the tables used to generate human-readable values.
4409          */
4410         switch(hfinfo->type) {
4411
4412                 case FT_UINT8:
4413                 case FT_UINT16:
4414                 case FT_UINT24:
4415                 case FT_UINT32:
4416                 case FT_INT8:
4417                 case FT_INT16:
4418                 case FT_INT24:
4419                 case FT_INT32:
4420                 case FT_FRAMENUM:
4421                         /*
4422                          * 4 bytes for " == ".
4423                          * 11 bytes for:
4424                          *
4425                          *      a sign + up to 10 digits of 32-bit integer,
4426                          *      in decimal;
4427                          *
4428                          *      "0x" + 8 digits of 32-bit integer, in hex;
4429                          *
4430                          *      11 digits of 32-bit integer, in octal.
4431                          *      (No, we don't do octal, but this way,
4432                          *      we know that if we do, this will still
4433                          *      work.)
4434                          *
4435                          * 1 byte for the trailing '\0'.
4436                          */
4437                         dfilter_len = abbrev_len + 4 + 11 + 1;
4438                         buf = g_malloc0(dfilter_len);
4439                         format = hfinfo_numeric_format(hfinfo);
4440                         snprintf(buf, dfilter_len, format, hfinfo->abbrev, fvalue_get_integer(&finfo->value));
4441                         break;
4442
4443                 case FT_INT64:
4444                 case FT_UINT64:
4445                         /*
4446                          * 4 bytes for " == ".
4447                          * 22 bytes for:
4448                          *
4449                          *      a sign + up to 20 digits of 32-bit integer,
4450                          *      in decimal;
4451                          *
4452                          *      "0x" + 16 digits of 32-bit integer, in hex;
4453                          *
4454                          *      22 digits of 32-bit integer, in octal.
4455                          *      (No, we don't do octal, but this way,
4456                          *      we know that if we do, this will still
4457                          *      work.)
4458                          *
4459                          * 1 byte for the trailing '\0'.
4460                          */
4461                         dfilter_len = abbrev_len + 4 + 22 + 1;
4462                         buf = g_malloc0(dfilter_len);
4463                         format = hfinfo_numeric_format(hfinfo);
4464                         snprintf(buf, dfilter_len, format, hfinfo->abbrev, fvalue_get_integer64(&finfo->value));
4465                         break;
4466
4467                 case FT_IPXNET:
4468                         /*
4469                          * 4 bytes for " == ".
4470                          * 2 bytes for "0x".
4471                          * 8 bytes for 8 digits of 32-bit hex number.
4472                          * 1 byte for the trailing '\0'.
4473                          */
4474                         dfilter_len = abbrev_len + 4 + 2 + 8 + 1;
4475                         buf = g_malloc0(dfilter_len);
4476                         snprintf(buf, dfilter_len, "%s == 0x%08x", hfinfo->abbrev,
4477                                         fvalue_get_integer(&finfo->value));
4478                         break;
4479
4480                 case FT_IPv6:
4481                         /*
4482                          * 4 bytes for " == ".
4483                          * N bytes for the string for the address.
4484                          * 1 byte for the trailing '\0'.
4485                          */
4486                         stringified = ip6_to_str((struct e_in6_addr*) fvalue_get(&finfo->value));
4487                         dfilter_len = abbrev_len + 4 + strlen(stringified) + 1;
4488                         buf = g_malloc0(dfilter_len);
4489                         snprintf(buf, dfilter_len, "%s == %s", hfinfo->abbrev,
4490                                         stringified);
4491                         break;
4492
4493                 /* These use the fvalue's "to_string_repr" method. */
4494                 case FT_BOOLEAN:
4495                 case FT_STRING:
4496                 case FT_ETHER:
4497                 case FT_BYTES:
4498                 case FT_UINT_BYTES:
4499                 case FT_FLOAT:
4500                 case FT_DOUBLE:
4501                 case FT_ABSOLUTE_TIME:
4502                 case FT_RELATIVE_TIME:
4503                 case FT_IPv4:
4504                 case FT_GUID:
4505                         /* Figure out the string length needed.
4506                          *      The ft_repr length.
4507                          *      4 bytes for " == ".
4508                          *      1 byte for trailing NUL.
4509                          */
4510                         dfilter_len = fvalue_string_repr_len(&finfo->value,
4511                                         FTREPR_DFILTER);
4512                         dfilter_len += abbrev_len + 4 + 1;
4513                         buf = g_malloc0(dfilter_len);
4514
4515                         /* Create the string */
4516                         snprintf(buf, dfilter_len, "%s == ", hfinfo->abbrev);
4517                         fvalue_to_string_repr(&finfo->value,
4518                                         FTREPR_DFILTER,
4519                                         &buf[abbrev_len + 4]);
4520                         break;
4521
4522                 case FT_PROTOCOL:
4523                         buf = g_strdup(finfo->hfinfo->abbrev);
4524                         break;
4525
4526                 default:
4527                         /*
4528                          * This doesn't have a value, so we'd match
4529                          * on the raw bytes at this address.
4530                          *
4531                          * Should we be allowed to access to the raw bytes?
4532                          * If "edt" is NULL, the answer is "no".
4533                          */
4534                         if (edt == NULL)
4535                                 return FALSE;
4536
4537                         /*
4538                          * Is this field part of the raw frame tvbuff?
4539                          * If not, we can't use "frame[N:M]" to match
4540                          * it.
4541                          *
4542                          * XXX - should this be frame-relative, or
4543                          * protocol-relative?
4544                          *
4545                          * XXX - does this fallback for non-registered
4546                          * fields even make sense?
4547                          */
4548                         if (finfo->ds_tvb != edt->tvb)
4549                                 return NULL;    /* you lose */
4550
4551                         /*
4552                          * If the length is 0, there's nothing to match, so
4553                          * we can't match.  (Also check for negative values,
4554                          * just in case, as we'll cast it to an unsigned
4555                          * value later.)
4556                          */
4557                         length = finfo->length;
4558                         if (length <= 0)
4559                                 return NULL;
4560
4561                         /*
4562                          * Don't go past the end of that tvbuff.
4563                          */
4564                         length_remaining = tvb_length_remaining(finfo->ds_tvb, finfo->start);
4565                         if (length > length_remaining)
4566                                 length = length_remaining;
4567                         if (length <= 0)
4568                                 return NULL;
4569                         
4570                         start = finfo->start;
4571                         buf = g_malloc0(32 + length * 3);
4572                         ptr = buf;
4573
4574                         sprintf(ptr, "frame[%d:%d] == ", finfo->start, length);
4575                         ptr = buf+strlen(buf);
4576
4577                         for (i=0;i<length; i++) {
4578                                 c = tvb_get_guint8(finfo->ds_tvb, start);
4579                                 start++;
4580                                 if (i == 0 ) {
4581                                         sprintf(ptr, "%02x", c);
4582                                 }
4583                                 else {
4584                                         sprintf(ptr, ":%02x", c);
4585                                 }
4586                                 ptr = buf+strlen(buf);
4587                         }
4588                         break;
4589         }
4590
4591         return buf;
4592 }