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