(on behalf of the PROFIBUS Nutzerorganisation e.V. Deutschland):
[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         g_assert(length >= 0);
1319         proto_tree_set_string(new_fi, value, FALSE);
1320
1321         return pi;
1322 }
1323
1324 proto_item *
1325 proto_tree_add_string_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1326                 gint length, const char* value)
1327 {
1328         proto_item              *pi;
1329
1330         pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
1331         if (pi == NULL)
1332                 return (NULL);
1333
1334         PROTO_ITEM_SET_HIDDEN(pi);
1335
1336         return pi;
1337 }
1338
1339 proto_item *
1340 proto_tree_add_string_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1341                 gint length, const char* value, const char *format, ...)
1342 {
1343         proto_item              *pi;
1344         va_list                 ap;
1345
1346         pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
1347         if (pi == NULL)
1348                 return (NULL);
1349
1350         va_start(ap, format);
1351         proto_tree_set_representation(pi, format, ap);
1352         va_end(ap);
1353
1354         return pi;
1355 }
1356
1357 /* Appends string data to a FT_STRING or FT_STRINGZ, allowing progressive
1358  * field info update instead of only updating the representation as does
1359  * proto_item_append_text()
1360  */
1361 void
1362 proto_item_append_string(proto_item *pi, const char *str)
1363 {
1364         field_info *fi;
1365         header_field_info *hfinfo;
1366         gchar *old_str, *new_str;
1367
1368         if (!pi)
1369                 return;
1370         if (!*str)
1371                 return;
1372
1373         fi = PITEM_FINFO(pi);
1374         hfinfo = fi->hfinfo;
1375         g_assert(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ);
1376         old_str = fvalue_get(&fi->value);
1377         new_str = g_malloc(strlen(old_str) + strlen(str) + 1);
1378         sprintf(new_str, "%s%s", old_str, str);
1379         fvalue_set(&fi->value, new_str, TRUE);
1380 }
1381
1382 /* Set the FT_STRING value */
1383 static void
1384 proto_tree_set_string(field_info *fi, const char* value,
1385                 gboolean already_allocated)
1386 {
1387         fvalue_set(&fi->value, (gpointer) value, already_allocated);
1388 }
1389
1390 static void
1391 proto_tree_set_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
1392 {
1393         gchar   *string;
1394
1395         if (length == -1) {
1396                 length = tvb_ensure_length_remaining(tvb, start);
1397         }
1398
1399         /* This memory is freed in proto_tree_free_node() */
1400         string = tvb_get_string(tvb, start, length);
1401         proto_tree_set_string(fi, string, TRUE);
1402 }
1403
1404 /* Add a FT_ETHER to a proto_tree */
1405 proto_item *
1406 proto_tree_add_ether(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1407                 const guint8* value)
1408 {
1409         proto_item              *pi;
1410         field_info              *new_fi;
1411         header_field_info       *hfinfo;
1412
1413         if (!tree)
1414                 return (NULL);
1415
1416         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1417         g_assert(hfinfo->type == FT_ETHER);
1418
1419         pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1420         proto_tree_set_ether(new_fi, value);
1421
1422         return pi;
1423 }
1424
1425 proto_item *
1426 proto_tree_add_ether_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1427                 const guint8* value)
1428 {
1429         proto_item              *pi;
1430
1431         pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
1432         if (pi == NULL)
1433                 return (NULL);
1434
1435         PROTO_ITEM_SET_HIDDEN(pi);
1436
1437         return pi;
1438 }
1439
1440 proto_item *
1441 proto_tree_add_ether_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1442                 const guint8* value, const char *format, ...)
1443 {
1444         proto_item              *pi;
1445         va_list                 ap;
1446
1447         pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
1448         if (pi == NULL)
1449                 return (NULL);
1450
1451         va_start(ap, format);
1452         proto_tree_set_representation(pi, format, ap);
1453         va_end(ap);
1454
1455         return pi;
1456 }
1457
1458 /* Set the FT_ETHER value */
1459 static void
1460 proto_tree_set_ether(field_info *fi, const guint8* value)
1461 {
1462         fvalue_set(&fi->value, (gpointer) value, FALSE);
1463 }
1464
1465 static void
1466 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start)
1467 {
1468         proto_tree_set_ether(fi, tvb_get_ptr(tvb, start, 6));
1469 }
1470
1471 /* Add a FT_BOOLEAN to a proto_tree */
1472 proto_item *
1473 proto_tree_add_boolean(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1474                 guint32 value)
1475 {
1476         proto_item              *pi;
1477         field_info              *new_fi;
1478         header_field_info       *hfinfo;
1479
1480         if (!tree)
1481                 return (NULL);
1482
1483         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1484         g_assert(hfinfo->type == FT_BOOLEAN);
1485
1486         pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1487         proto_tree_set_boolean(new_fi, value);
1488
1489         return pi;
1490 }
1491
1492 proto_item *
1493 proto_tree_add_boolean_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1494                 guint32 value)
1495 {
1496         proto_item              *pi;
1497
1498         pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
1499         if (pi == NULL)
1500                 return (NULL);
1501
1502         PROTO_ITEM_SET_HIDDEN(pi);
1503
1504         return pi;
1505 }
1506
1507 proto_item *
1508 proto_tree_add_boolean_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1509                 guint32 value, const char *format, ...)
1510 {
1511         proto_item              *pi;
1512         va_list                 ap;
1513
1514         pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
1515         if (pi == NULL)
1516                 return (NULL);
1517
1518         va_start(ap, format);
1519         proto_tree_set_representation(pi, format, ap);
1520         va_end(ap);
1521
1522         return pi;
1523 }
1524
1525 /* Set the FT_BOOLEAN value */
1526 static void
1527 proto_tree_set_boolean(field_info *fi, guint32 value)
1528 {
1529         proto_tree_set_uint(fi, value);
1530 }
1531
1532 /* Add a FT_FLOAT to a proto_tree */
1533 proto_item *
1534 proto_tree_add_float(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1535                 float value)
1536 {
1537         proto_item              *pi;
1538         field_info              *new_fi;
1539         header_field_info       *hfinfo;
1540
1541         if (!tree)
1542                 return (NULL);
1543
1544         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1545         g_assert(hfinfo->type == FT_FLOAT);
1546
1547         pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1548         proto_tree_set_float(new_fi, value);
1549
1550         return pi;
1551 }
1552
1553 proto_item *
1554 proto_tree_add_float_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1555                 float value)
1556 {
1557         proto_item              *pi;
1558
1559         pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
1560         if (pi == NULL)
1561                 return (NULL);
1562
1563         PROTO_ITEM_SET_HIDDEN(pi);
1564
1565         return pi;
1566 }
1567
1568 proto_item *
1569 proto_tree_add_float_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1570                 float value, const char *format, ...)
1571 {
1572         proto_item              *pi;
1573         va_list                 ap;
1574
1575         pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
1576         if (pi == NULL)
1577                 return (NULL);
1578
1579         va_start(ap, format);
1580         proto_tree_set_representation(pi, format, ap);
1581         va_end(ap);
1582
1583         return pi;
1584 }
1585
1586 /* Set the FT_FLOAT value */
1587 static void
1588 proto_tree_set_float(field_info *fi, float value)
1589 {
1590         fvalue_set_floating(&fi->value, value);
1591 }
1592
1593 /* Add a FT_DOUBLE to a proto_tree */
1594 proto_item *
1595 proto_tree_add_double(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1596                 double value)
1597 {
1598         proto_item              *pi;
1599         field_info              *new_fi;
1600         header_field_info       *hfinfo;
1601
1602         if (!tree)
1603                 return (NULL);
1604
1605         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1606         g_assert(hfinfo->type == FT_DOUBLE);
1607
1608         pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1609         proto_tree_set_double(new_fi, value);
1610
1611         return pi;
1612 }
1613
1614 proto_item *
1615 proto_tree_add_double_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1616                 double value)
1617 {
1618         proto_item              *pi;
1619
1620         pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
1621         if (pi == NULL)
1622                 return (NULL);
1623
1624         PROTO_ITEM_SET_HIDDEN(pi);
1625
1626         return pi;
1627 }
1628
1629 proto_item *
1630 proto_tree_add_double_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1631                 double value, const char *format, ...)
1632 {
1633         proto_item              *pi;
1634         va_list                 ap;
1635
1636         pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
1637         if (pi == NULL)
1638                 return (NULL);
1639
1640         va_start(ap, format);
1641         proto_tree_set_representation(pi, format, ap);
1642         va_end(ap);
1643
1644         return pi;
1645 }
1646
1647 /* Set the FT_DOUBLE value */
1648 static void
1649 proto_tree_set_double(field_info *fi, double value)
1650 {
1651         fvalue_set_floating(&fi->value, value);
1652 }
1653
1654 /* Add FT_UINT{8,16,24,32} to a proto_tree */
1655 proto_item *
1656 proto_tree_add_uint(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1657                 guint32 value)
1658 {
1659         proto_item              *pi = NULL;
1660         field_info              *new_fi;
1661         header_field_info       *hfinfo;
1662
1663         if (!tree)
1664                 return (NULL);
1665
1666         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1667         switch(hfinfo->type) {
1668                 case FT_UINT8:
1669                 case FT_UINT16:
1670                 case FT_UINT24:
1671                 case FT_UINT32:
1672                 case FT_FRAMENUM:
1673                         pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length,
1674                                         &new_fi);
1675                         proto_tree_set_uint(new_fi, value);
1676                         break;
1677
1678                 default:
1679                         g_assert_not_reached();
1680         }
1681
1682         return pi;
1683 }
1684
1685 proto_item *
1686 proto_tree_add_uint_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1687                 guint32 value)
1688 {
1689         proto_item              *pi;
1690
1691         pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
1692         if (pi == NULL)
1693                 return (NULL);
1694
1695         PROTO_ITEM_SET_HIDDEN(pi);
1696
1697         return pi;
1698 }
1699
1700 proto_item *
1701 proto_tree_add_uint_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1702                 guint32 value, const char *format, ...)
1703 {
1704         proto_item              *pi;
1705         va_list                 ap;
1706
1707         pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
1708         if (pi == NULL)
1709                 return (NULL);
1710
1711         va_start(ap, format);
1712         proto_tree_set_representation(pi, format, ap);
1713         va_end(ap);
1714
1715         return pi;
1716 }
1717
1718 /* Set the FT_UINT{8,16,24,32} value */
1719 static void
1720 proto_tree_set_uint(field_info *fi, guint32 value)
1721 {
1722         header_field_info       *hfinfo;
1723         guint32                 integer;
1724
1725         hfinfo = fi->hfinfo;
1726         integer = value;
1727
1728         if (hfinfo->bitmask) {
1729                 /* Mask out irrelevant portions */
1730                 integer &= hfinfo->bitmask;
1731
1732                 /* Shift bits */
1733                 if (hfinfo->bitshift > 0) {
1734                         integer >>= hfinfo->bitshift;
1735                 }
1736         }
1737         fvalue_set_integer(&fi->value, integer);
1738 }
1739
1740 /* Add FT_UINT64 to a proto_tree */
1741 proto_item *
1742 proto_tree_add_uint64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1743                 guint64 value)
1744 {
1745         proto_item              *pi = NULL;
1746         field_info              *new_fi;
1747         header_field_info       *hfinfo;
1748
1749         if (!tree)
1750                 return (NULL);
1751
1752         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1753         g_assert(hfinfo->type == FT_UINT64);
1754
1755         pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1756         proto_tree_set_uint64(new_fi, value);
1757
1758         return pi;
1759 }
1760
1761 proto_item *
1762 proto_tree_add_uint64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1763                 guint64 value, const char *format, ...)
1764 {
1765         proto_item              *pi;
1766         va_list                 ap;
1767
1768         pi = proto_tree_add_uint64(tree, hfindex, tvb, start, length, value);
1769         if (pi == NULL)
1770                 return (NULL);
1771
1772         va_start(ap, format);
1773         proto_tree_set_representation(pi, format, ap);
1774         va_end(ap);
1775
1776         return pi;
1777 }
1778
1779 /* Add FT_INT{8,16,24,32} to a proto_tree */
1780 proto_item *
1781 proto_tree_add_int(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1782                 gint32 value)
1783 {
1784         proto_item              *pi = NULL;
1785         field_info              *new_fi;
1786         header_field_info       *hfinfo;
1787
1788         if (!tree)
1789                 return (NULL);
1790
1791         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1792         switch(hfinfo->type) {
1793                 case FT_INT8:
1794                 case FT_INT16:
1795                 case FT_INT24:
1796                 case FT_INT32:
1797                         pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length,
1798                                         &new_fi);
1799                         proto_tree_set_int(new_fi, value);
1800                         break;
1801
1802                 default:
1803                         g_assert_not_reached();
1804         }
1805
1806         return pi;
1807 }
1808
1809 proto_item *
1810 proto_tree_add_int_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1811                 gint32 value)
1812 {
1813         proto_item              *pi;
1814
1815         pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
1816         if (pi == NULL)
1817                 return (NULL);
1818
1819         PROTO_ITEM_SET_HIDDEN(pi);
1820
1821         return pi;
1822 }
1823
1824 proto_item *
1825 proto_tree_add_int_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1826                 gint32 value, const char *format, ...)
1827 {
1828         proto_item              *pi = NULL;
1829         va_list                 ap;
1830
1831         pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
1832         if (pi == NULL)
1833                 return (NULL);
1834
1835         va_start(ap, format);
1836         proto_tree_set_representation(pi, format, ap);
1837         va_end(ap);
1838
1839         return pi;
1840 }
1841
1842 /* Set the FT_INT{8,16,24,32} value */
1843 static void
1844 proto_tree_set_int(field_info *fi, gint32 value)
1845 {
1846         header_field_info       *hfinfo;
1847         guint32                 integer;
1848
1849         hfinfo = fi->hfinfo;
1850         integer = (guint32) value;
1851
1852         if (hfinfo->bitmask) {
1853                 /* Mask out irrelevant portions */
1854                 integer &= hfinfo->bitmask;
1855
1856                 /* Shift bits */
1857                 if (hfinfo->bitshift > 0) {
1858                         integer >>= hfinfo->bitshift;
1859                 }
1860         }
1861         fvalue_set_integer(&fi->value, integer);
1862 }
1863
1864 /* Add FT_INT64 to a proto_tree */
1865 proto_item *
1866 proto_tree_add_int64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1867                 gint64 value)
1868 {
1869         proto_item              *pi = NULL;
1870         field_info              *new_fi;
1871         header_field_info       *hfinfo;
1872
1873         if (!tree)
1874                 return (NULL);
1875
1876         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1877         g_assert(hfinfo->type == FT_INT64);
1878
1879         pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1880         proto_tree_set_uint64(new_fi, (guint64)value);
1881
1882         return pi;
1883 }
1884
1885 proto_item *
1886 proto_tree_add_int64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1887                 gint64 value, const char *format, ...)
1888 {
1889         proto_item              *pi;
1890         va_list                 ap;
1891
1892         pi = proto_tree_add_int64(tree, hfindex, tvb, start, length, value);
1893         if (pi == NULL)
1894                 return (NULL);
1895
1896         va_start(ap, format);
1897         proto_tree_set_representation(pi, format, ap);
1898         va_end(ap);
1899
1900         return pi;
1901 }
1902
1903
1904 /* Add a field_info struct to the proto_tree, encapsulating it in a proto_node */
1905 static proto_item *
1906 proto_tree_add_node(proto_tree *tree, field_info *fi)
1907 {
1908         proto_node *pnode, *tnode, *sibling;
1909         field_info *tfi;
1910
1911         /*
1912          * Make sure "tree" is ready to have subtrees under it, by
1913          * checking whether it's been given an ett_ value.
1914          *
1915          * "tnode->finfo" may be null; that's the case for the root
1916          * node of the protocol tree.  That node is not displayed,
1917          * so it doesn't need an ett_ value to remember whether it
1918          * was expanded.
1919          */
1920         tnode = tree;
1921         tfi = tnode->finfo;
1922         g_assert(tfi == NULL ||
1923             (tfi->tree_type >= 0 && tfi->tree_type < num_tree_types));
1924
1925         PROTO_NODE_NEW(pnode);
1926         pnode->parent = tnode;
1927         pnode->finfo = fi;
1928         pnode->tree_data = PTREE_DATA(tree);
1929
1930         if (tnode->last_child != NULL) {
1931                 sibling = tnode->last_child;
1932                 g_assert(sibling->next == NULL);
1933                 sibling->next = pnode;
1934         } else
1935                 tnode->first_child = pnode;
1936         tnode->last_child = pnode;
1937
1938         return (proto_item*)pnode;
1939 }
1940
1941
1942 /* Generic way to allocate field_info and add to proto_tree.
1943  * Sets *pfi to address of newly-allocated field_info struct, if pfi is
1944  * non-NULL. */
1945 static proto_item *
1946 proto_tree_add_pi(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1947     gint *length, field_info **pfi)
1948 {
1949         proto_item      *pi;
1950         field_info      *fi;
1951         GHashTable      *hash;
1952         GPtrArray       *ptrs;
1953
1954         if (!tree)
1955                 return(NULL);
1956
1957         fi = alloc_field_info(tree, hfindex, tvb, start, length);
1958         pi = proto_tree_add_node(tree, fi);
1959
1960         /* If the proto_tree wants to keep a record of this finfo
1961          * for quick lookup, then record it. */
1962         hash = PTREE_DATA(tree)->interesting_hfids;
1963         ptrs = g_hash_table_lookup(hash, GINT_TO_POINTER(hfindex));
1964         if (ptrs) {
1965                 g_ptr_array_add(ptrs, fi);
1966         }
1967
1968         /* Does the caller want to know the fi pointer? */
1969         if (pfi) {
1970                 *pfi = fi;
1971         }
1972
1973         return pi;
1974 }
1975
1976 static field_info *
1977 alloc_field_info(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1978     gint *length)
1979 {
1980         header_field_info       *hfinfo;
1981         field_info              *fi;
1982
1983         /*
1984          * We only allow a null tvbuff if the item has a zero length,
1985          * i.e. if there's no data backing it.
1986          */
1987         g_assert(tvb != NULL || *length == 0);
1988
1989         PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1990
1991         if (*length == -1) {
1992                 /*
1993                  * For FT_NONE, FT_PROTOCOL, FT_BYTES, and FT_STRING fields,
1994                  * a length of -1 means "set the length to what remains in
1995                  * the tvbuff".
1996                  *
1997                  * The assumption is either that
1998                  *
1999                  *      1) the length of the item can only be determined
2000                  *         by dissection (typically true of items with
2001                  *         subitems, which are probably FT_NONE or
2002                  *         FT_PROTOCOL)
2003                  *
2004                  * or
2005                  *
2006                  *      2) if the tvbuff is "short" (either due to a short
2007                  *         snapshot length or due to lack of reassembly of
2008                  *         fragments/segments/whatever), we want to display
2009                  *         what's available in the field (probably FT_BYTES
2010                  *         or FT_STRING) and then throw an exception later
2011                  *
2012                  * or
2013                  *
2014                  *      3) the field is defined to be "what's left in the
2015                  *         packet"
2016                  *
2017                  * so we set the length to what remains in the tvbuff so
2018                  * that, if we throw an exception while dissecting, it
2019                  * has what is probably the right value.
2020                  *
2021                  * For FT_STRINGZ, it means "the string is null-terminated,
2022                  * not null-padded; set the length to the actual length
2023                  * of the string", and if the tvbuff if short, we just
2024                  * throw an exception.
2025                  *
2026                  * It's not valid for any other type of field.
2027                  */
2028                 switch (hfinfo->type) {
2029
2030                 case FT_PROTOCOL:
2031                         /*
2032                          * We allow this to be zero-length - for
2033                          * example, an ONC RPC NULL procedure has
2034                          * neither arguments nor reply, so the
2035                          * payload for that protocol is empty.
2036                          *
2037                          * However, if the length is negative, the
2038                          * start offset is *past* the byte past the
2039                          * end of the tvbuff, so we throw an
2040                          * exception.
2041                          */
2042                         *length = tvb_length_remaining(tvb, start);
2043                         if (*length < 0) {
2044                                 /*
2045                                  * Use "tvb_ensure_bytes_exist()"
2046                                  * to force the appropriate exception
2047                                  * to be thrown.
2048                                  */
2049                                 tvb_ensure_bytes_exist(tvb, start, 0);
2050                         }
2051                         g_assert(*length >= 0);
2052                         break;
2053
2054                 case FT_NONE:
2055                 case FT_BYTES:
2056                 case FT_STRING:
2057                         *length = tvb_ensure_length_remaining(tvb, start);
2058                         g_assert(*length >= 0);
2059                         break;
2060
2061                 case FT_STRINGZ:
2062                         /*
2063                          * Leave the length as -1, so our caller knows
2064                          * it was -1.
2065                          */
2066                         break;
2067
2068                 default:
2069                         g_assert_not_reached();
2070                 }
2071         } else
2072                 g_assert(*length >= 0);
2073
2074         FIELD_INFO_NEW(fi);
2075
2076         fi->hfinfo = hfinfo;
2077         fi->start = start;
2078         fi->start+=(tvb)?TVB_RAW_OFFSET(tvb):0;
2079         fi->length = *length;
2080         fi->tree_type = -1;
2081         fi->flags = 0;
2082         if (!PTREE_DATA(tree)->visible)
2083                 FI_SET_FLAG(fi, FI_HIDDEN);
2084         fvalue_init(&fi->value, fi->hfinfo->type);
2085         fi->rep = NULL;
2086
2087         /* add the data source tvbuff */
2088         fi->ds_tvb=tvb?TVB_GET_DS_TVB(tvb):NULL;
2089
2090         return fi;
2091 }
2092
2093 /* Set representation of a proto_tree entry, if the protocol tree is to
2094    be visible. */
2095 static void
2096 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap)
2097 {
2098         int                                     ret;    /*tmp return value */
2099         field_info *fi = PITEM_FINFO(pi);
2100
2101         if (!PROTO_ITEM_IS_HIDDEN(pi)) {
2102                 ITEM_LABEL_NEW(fi->rep);
2103                 ret = vsnprintf(fi->rep->representation, ITEM_LABEL_LENGTH, format, ap);
2104                 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
2105                         fi->rep->representation[ITEM_LABEL_LENGTH - 1] = '\0';
2106         }
2107 }
2108
2109 /* Set text of proto_item after having already been created. */
2110 void
2111 proto_item_set_text(proto_item *pi, const char *format, ...)
2112 {
2113         field_info *fi = NULL;
2114         va_list ap;
2115
2116         if (pi==NULL) {
2117                 return;
2118         }
2119
2120         fi = PITEM_FINFO(pi);
2121
2122         if(fi->rep){
2123                 ITEM_LABEL_FREE(fi->rep);
2124         }
2125
2126         va_start(ap, format);
2127         proto_tree_set_representation(pi, format, ap);
2128         va_end(ap);
2129 }
2130
2131 /* Append to text of proto_item after having already been created. */
2132 void
2133 proto_item_append_text(proto_item *pi, const char *format, ...)
2134 {
2135         field_info *fi = NULL;
2136         size_t curlen;
2137         va_list ap;
2138         int                                     ret;    /*tmp return value */
2139
2140         if (pi==NULL) {
2141                 return;
2142         }
2143
2144         fi = PITEM_FINFO(pi);
2145
2146     if (!PROTO_ITEM_IS_HIDDEN(pi)) {
2147                 va_start(ap, format);
2148
2149                 /*
2150                  * If we don't already have a representation,
2151                  * generate the default representation.
2152                  */
2153                 if (fi->rep == NULL) {
2154                         ITEM_LABEL_NEW(fi->rep);
2155                         proto_item_fill_label(fi, fi->rep->representation);
2156                 }
2157
2158                 curlen = strlen(fi->rep->representation);
2159                 if (ITEM_LABEL_LENGTH > curlen) {
2160                         ret = vsnprintf(fi->rep->representation + curlen,
2161                             ITEM_LABEL_LENGTH - curlen, format, ap);
2162                         if ((ret == -1) || (ret >= (int)(ITEM_LABEL_LENGTH - curlen)))
2163                                 fi->rep->representation[ITEM_LABEL_LENGTH - 1] = '\0';
2164                 }
2165                 va_end(ap);
2166         }
2167 }
2168
2169 void
2170 proto_item_set_len(proto_item *pi, gint length)
2171 {
2172         field_info *fi;
2173
2174         if (pi == NULL)
2175                 return;
2176         fi = PITEM_FINFO(pi);
2177         g_assert(length >= 0);
2178         fi->length = length;
2179 }
2180
2181 /*
2182  * Sets the length of the item based on its start and on the specified
2183  * offset, which is the offset past the end of the item; as the start
2184  * in the item is relative to the beginning of the data source tvbuff,
2185  * we need to pass in a tvbuff - the end offset is relative to the beginning
2186  * of that tvbuff.
2187  */
2188 void
2189 proto_item_set_end(proto_item *pi, tvbuff_t *tvb, gint end)
2190 {
2191         field_info *fi;
2192
2193         if (pi == NULL)
2194                 return;
2195         fi = PITEM_FINFO(pi);
2196         end += TVB_RAW_OFFSET(tvb);
2197         g_assert(end >= fi->start);
2198         fi->length = end - fi->start;
2199 }
2200
2201 int
2202 proto_item_get_len(proto_item *pi)
2203 {
2204         field_info *fi = PITEM_FINFO(pi);
2205         return fi->length;
2206 }
2207
2208 proto_tree*
2209 proto_tree_create_root(void)
2210 {
2211         proto_node  *pnode;
2212
2213         /* Initialize the proto_node */
2214         PROTO_NODE_NEW(pnode);
2215         pnode->parent = NULL;
2216         pnode->finfo = NULL;
2217         pnode->tree_data = g_new(tree_data_t, 1);
2218
2219         /* Initialize the tree_data_t */
2220         pnode->tree_data->interesting_hfids =
2221             g_hash_table_new(g_direct_hash, g_direct_equal);
2222
2223         /* Set the default to FALSE so it's easier to
2224          * find errors; if we expect to see the protocol tree
2225          * but for some reason the default 'visible' is not
2226          * changed, then we'll find out very quickly. */
2227         pnode->tree_data->visible = FALSE;
2228
2229         return (proto_tree*) pnode;
2230 }
2231
2232
2233 /* "prime" a proto_tree with a single hfid that a dfilter
2234  * is interested in. */
2235 void
2236 proto_tree_prime_hfid(proto_tree *tree, gint hfid)
2237 {
2238         g_hash_table_insert(PTREE_DATA(tree)->interesting_hfids,
2239                 GINT_TO_POINTER(hfid), g_ptr_array_new());
2240 }
2241
2242
2243 proto_tree*
2244 proto_item_add_subtree(proto_item *pi,  gint idx) {
2245         field_info *fi;
2246
2247         if (!pi)
2248                 return(NULL);
2249
2250         fi = PITEM_FINFO(pi);
2251         g_assert(idx >= 0 && idx < num_tree_types);
2252         fi->tree_type = idx;
2253         return (proto_tree*) pi;
2254 }
2255
2256 proto_tree*
2257 proto_item_get_subtree(proto_item *pi) {
2258         field_info *fi;
2259
2260         if (!pi)
2261                 return(NULL);
2262         fi = PITEM_FINFO(pi);
2263         if (fi->tree_type == -1)
2264                 return(NULL);
2265         return (proto_tree*) pi;
2266 }
2267
2268 proto_item*
2269 proto_item_get_parent(proto_item *ti) {
2270         if (!ti)
2271                 return (NULL);
2272         return ti->parent;
2273 }
2274
2275 proto_item*
2276 proto_item_get_parent_nth(proto_item *ti, int gen) {
2277         if (!ti)
2278                 return (NULL);
2279         while (gen--) {
2280                 ti = ti->parent;
2281                 if (!ti)
2282                         return (NULL);
2283         }
2284         return ti;
2285 }
2286
2287
2288 proto_item* 
2289 proto_tree_get_parent(proto_tree *tree) {
2290         if (!tree)
2291                 return (NULL);
2292         return (proto_item*) tree;
2293 }
2294
2295 static gint
2296 proto_match_short_name(gconstpointer p_arg, gconstpointer name_arg)
2297 {
2298         const protocol_t *p = p_arg;
2299         const char *name = name_arg;
2300
2301         return g_strcasecmp(p->short_name, name);
2302 }
2303
2304 static gint
2305 proto_match_name(gconstpointer p_arg, gconstpointer name_arg)
2306 {
2307         const protocol_t *p = p_arg;
2308         const char *name = name_arg;
2309
2310         return g_strcasecmp(p->name, name);
2311 }
2312
2313 static gint
2314 proto_match_filter_name(gconstpointer p_arg, gconstpointer name_arg)
2315 {
2316         const protocol_t *p = p_arg;
2317         const char *name = name_arg;
2318
2319         return g_strcasecmp(p->filter_name, name);
2320 }
2321
2322 static gint
2323 proto_compare_name(gconstpointer p1_arg, gconstpointer p2_arg)
2324 {
2325         const protocol_t *p1 = p1_arg;
2326         const protocol_t *p2 = p2_arg;
2327
2328         return g_strcasecmp(p1->short_name, p2->short_name);
2329 }
2330
2331 int
2332 proto_register_protocol(char *name, char *short_name, char *filter_name)
2333 {
2334         protocol_t *protocol;
2335         header_field_info *hfinfo;
2336         int proto_id;
2337
2338         /*
2339          * Make sure there's not already a protocol with any of those
2340          * names.  Crash if there is, as that's an error in the code,
2341          * and the code has to be fixed not to register more than one
2342          * protocol with the same name.
2343          */
2344         g_assert(g_list_find_custom(protocols, name, proto_match_name) == NULL);
2345         g_assert(g_list_find_custom(protocols, short_name, proto_match_short_name) == NULL);
2346         g_assert(g_list_find_custom(protocols, filter_name, proto_match_filter_name) == NULL);
2347
2348         /* Add this protocol to the list of known protocols; the list
2349            is sorted by protocol short name. */
2350         protocol = g_malloc(sizeof (protocol_t));
2351         protocol->name = name;
2352         protocol->short_name = short_name;
2353         protocol->filter_name = filter_name;
2354         protocol->fields = NULL;
2355         protocol->is_enabled = TRUE; /* protocol is enabled by default */
2356         protocol->can_toggle = TRUE;
2357         protocols = g_list_insert_sorted(protocols, protocol,
2358             proto_compare_name);
2359
2360         /* Here we do allocate a new header_field_info struct */
2361         hfinfo = g_mem_chunk_alloc(gmc_hfinfo);
2362         hfinfo->name = name;
2363         hfinfo->abbrev = filter_name;
2364         hfinfo->type = FT_PROTOCOL;
2365         hfinfo->strings = NULL;
2366         hfinfo->bitmask = 0;
2367         hfinfo->bitshift = 0;
2368         hfinfo->blurb = "";
2369         hfinfo->parent = -1; /* this field differentiates protos and fields */
2370
2371         proto_id = proto_register_field_init(hfinfo, hfinfo->parent);
2372         protocol->proto_id = proto_id;
2373         return proto_id;
2374 }
2375
2376 /*
2377  * Routines to use to iterate over the protocols.
2378  * The argument passed to the iterator routines is an opaque cookie to
2379  * their callers; it's the GList pointer for the current element in
2380  * the list.
2381  * The ID of the protocol is returned, or -1 if there is no protocol.
2382  */
2383 int
2384 proto_get_first_protocol(void **cookie)
2385 {
2386         protocol_t *protocol;
2387
2388         if (protocols == NULL)
2389                 return -1;
2390         *cookie = protocols;
2391         protocol = protocols->data;
2392         return protocol->proto_id;
2393 }
2394
2395 int
2396 proto_get_next_protocol(void **cookie)
2397 {
2398         GList *list_item = *cookie;
2399         protocol_t *protocol;
2400
2401         list_item = g_list_next(list_item);
2402         if (list_item == NULL)
2403                 return -1;
2404         *cookie = list_item;
2405         protocol = list_item->data;
2406         return protocol->proto_id;
2407 }
2408
2409 header_field_info *
2410 proto_get_first_protocol_field(int proto_id, void **cookie)
2411 {
2412         protocol_t *protocol = find_protocol_by_id(proto_id);
2413         hf_register_info *ptr;
2414
2415         if ((protocol == NULL) || (protocol->fields == NULL))
2416                 return NULL;
2417
2418         *cookie = protocol->fields;
2419         ptr = protocol->fields->data;
2420         return &ptr->hfinfo;
2421 }
2422
2423 header_field_info *
2424 proto_get_next_protocol_field(void **cookie)
2425 {
2426         GList *list_item = *cookie;
2427         hf_register_info *ptr;
2428
2429         list_item = g_list_next(list_item);
2430         if (list_item == NULL)
2431                 return NULL;
2432
2433         *cookie = list_item;
2434         ptr = list_item->data;
2435         return &ptr->hfinfo;
2436 }
2437
2438 /*
2439  * Find the protocol list entry for a protocol given its field ID.
2440  */
2441 static gint
2442 compare_proto_id(gconstpointer proto_arg, gconstpointer id_arg)
2443 {
2444         const protocol_t *protocol = proto_arg;
2445         const int *id_ptr = id_arg;
2446
2447         return (protocol->proto_id == *id_ptr) ? 0 : 1;
2448 }
2449
2450 protocol_t *
2451 find_protocol_by_id(int proto_id)
2452 {
2453         GList *list_entry;
2454
2455         list_entry = g_list_find_custom(protocols, &proto_id, compare_proto_id);
2456         if (list_entry == NULL)
2457                 return NULL;
2458         return list_entry->data;
2459 }
2460
2461 static gint compare_filter_name(gconstpointer proto_arg,
2462                                 gconstpointer filter_name)
2463 {
2464         const protocol_t *protocol = proto_arg;
2465         const gchar* f_name = filter_name;
2466
2467         return (strcmp(protocol->filter_name, f_name));
2468 }
2469
2470 int
2471 proto_get_id(protocol_t *protocol)
2472 {
2473         return protocol->proto_id;
2474 }
2475
2476 int proto_get_id_by_filter_name(gchar* filter_name)
2477 {
2478         GList *list_entry;
2479         protocol_t *protocol;
2480
2481         list_entry = g_list_find_custom(protocols, filter_name,
2482             compare_filter_name);
2483         if (list_entry == NULL)
2484                 return -1;
2485         protocol = list_entry->data;
2486         return protocol->proto_id;
2487 }
2488
2489 char *
2490 proto_get_protocol_name(int proto_id)
2491 {
2492         protocol_t *protocol;
2493
2494         protocol = find_protocol_by_id(proto_id);
2495         return protocol->name;
2496 }
2497
2498 char *
2499 proto_get_protocol_short_name(protocol_t *protocol)
2500 {
2501         if (protocol == NULL)
2502                 return "(none)";
2503         return protocol->short_name;
2504 }
2505
2506 char *
2507 proto_get_protocol_filter_name(int proto_id)
2508 {
2509         protocol_t *protocol;
2510
2511         protocol = find_protocol_by_id(proto_id);
2512         return protocol->filter_name;
2513 }
2514
2515 gboolean
2516 proto_is_protocol_enabled(protocol_t *protocol)
2517 {
2518         return protocol->is_enabled;
2519 }
2520
2521 gboolean
2522 proto_can_toggle_protocol(int proto_id)
2523 {
2524         protocol_t *protocol;
2525
2526         protocol = find_protocol_by_id(proto_id);
2527         return protocol->can_toggle;
2528 }
2529
2530 void
2531 proto_set_decoding(int proto_id, gboolean enabled)
2532 {
2533         protocol_t *protocol;
2534
2535         protocol = find_protocol_by_id(proto_id);
2536         g_assert(protocol->can_toggle);
2537         protocol->is_enabled = enabled;
2538 }
2539
2540 void
2541 proto_set_cant_toggle(int proto_id)
2542 {
2543         protocol_t *protocol;
2544
2545         protocol = find_protocol_by_id(proto_id);
2546         protocol->can_toggle = FALSE;
2547 }
2548
2549 /* for use with static arrays only, since we don't allocate our own copies
2550 of the header_field_info struct contained within the hf_register_info struct */
2551 void
2552 proto_register_field_array(int parent, hf_register_info *hf, int num_records)
2553 {
2554         int                     field_id, i;
2555         hf_register_info        *ptr = hf;
2556         protocol_t              *proto;
2557
2558         proto = find_protocol_by_id(parent);
2559         for (i = 0; i < num_records; i++, ptr++) {
2560                 /*
2561                  * Make sure we haven't registered this yet.
2562                  * Most fields have variables associated with them
2563                  * that are initialized to -1; some have array elements,
2564                  * or possibly uninitialized variables, so we also allow
2565                  * 0 (which is unlikely to be the field ID we get back
2566                  * from "proto_register_field_init()").
2567                  */
2568                 g_assert(*ptr->p_id == -1 || *ptr->p_id == 0);
2569
2570                 if (proto != NULL) {
2571                         if (proto->fields == NULL) {
2572                                 proto->fields = g_list_append(NULL, ptr);
2573                                 proto->last_field = proto->fields;
2574                         } else {
2575                                 proto->last_field =
2576                                     g_list_append(proto->last_field, ptr)->next;
2577                         }
2578                 }
2579                 field_id = proto_register_field_init(&ptr->hfinfo, parent);
2580                 *ptr->p_id = field_id;
2581         }
2582 }
2583
2584 static int
2585 proto_register_field_init(header_field_info *hfinfo, int parent)
2586 {
2587         /* The field must have names */
2588         g_assert(hfinfo->name);
2589         g_assert(hfinfo->abbrev);
2590
2591         /* These types of fields are allowed to have value_strings or true_false_strings */
2592         g_assert((hfinfo->strings == NULL) || (
2593                         (hfinfo->type == FT_UINT8) ||
2594                         (hfinfo->type == FT_UINT16) ||
2595                         (hfinfo->type == FT_UINT24) ||
2596                         (hfinfo->type == FT_UINT32) ||
2597                         (hfinfo->type == FT_INT8) ||
2598                         (hfinfo->type == FT_INT16) ||
2599                         (hfinfo->type == FT_INT24) ||
2600                         (hfinfo->type == FT_INT32) ||
2601                         (hfinfo->type == FT_BOOLEAN) ||
2602                         (hfinfo->type == FT_FRAMENUM) ));
2603
2604         switch (hfinfo->type) {
2605
2606         case FT_UINT8:
2607         case FT_UINT16:
2608         case FT_UINT24:
2609         case FT_UINT32:
2610         case FT_INT8:
2611         case FT_INT16:
2612         case FT_INT24:
2613         case FT_INT32:
2614                 /* Require integral types (other than frame number, which is
2615                    always displayed in decimal) to have a number base */
2616                 g_assert(hfinfo->display != BASE_NONE);
2617                 break;
2618
2619         case FT_FRAMENUM:
2620                 /* Don't allow bitfields or value strings for frame numbers */
2621                 g_assert(hfinfo->bitmask == 0);
2622                 g_assert(hfinfo->strings == NULL);
2623                 break;
2624
2625         default:
2626                 break;
2627         }
2628         /* if this is a bitfield, compute bitshift */
2629         if (hfinfo->bitmask) {
2630                 while ((hfinfo->bitmask & (1 << hfinfo->bitshift)) == 0)
2631                         hfinfo->bitshift++;
2632         }
2633
2634         hfinfo->parent = parent;
2635         hfinfo->same_name_next = NULL;
2636         hfinfo->same_name_prev = NULL;
2637
2638         /* if we always add and never delete, then id == len - 1 is correct */
2639         if(gpa_hfinfo.len>=gpa_hfinfo.allocated_len){
2640                 if(!gpa_hfinfo.hfi){
2641                         gpa_hfinfo.allocated_len=1000;
2642                         gpa_hfinfo.hfi=g_malloc(sizeof(header_field_info *)*1000);
2643                 } else {
2644                         gpa_hfinfo.allocated_len+=1000;
2645                         gpa_hfinfo.hfi=g_realloc(gpa_hfinfo.hfi, sizeof(header_field_info *)*gpa_hfinfo.allocated_len);
2646                 }
2647         }
2648         gpa_hfinfo.hfi[gpa_hfinfo.len]=hfinfo;
2649         gpa_hfinfo.len++;
2650         hfinfo->id = gpa_hfinfo.len - 1;
2651
2652         /* if we have real names, enter this field in the name tree */
2653         if ((hfinfo->name[0] != 0) && (hfinfo->abbrev[0] != 0 )) {
2654
2655                 header_field_info *same_name_hfinfo, *same_name_next_hfinfo;
2656                 char *p;
2657                 guchar c;
2658
2659                 /* Check that the filter name (abbreviation) is legal;
2660                  * it must contain only alphanumerics, '-', "_", and ".". */
2661                 for (p = hfinfo->abbrev; (c = *p) != '\0'; p++)
2662                         g_assert(isalnum(c) || c == '-' || c == '_' ||
2663                             c == '.');
2664
2665                 /* We allow multiple hfinfo's to be registered under the same
2666                  * abbreviation. This was done for X.25, as, depending
2667                  * on whether it's modulo-8 or modulo-128 operation,
2668                  * some bitfield fields may be in different bits of
2669                  * a byte, and we want to be able to refer to that field
2670                  * with one name regardless of whether the packets
2671                  * are modulo-8 or modulo-128 packets. */
2672                 same_name_hfinfo = g_tree_lookup(gpa_name_tree, hfinfo->abbrev);
2673                 if (same_name_hfinfo) {
2674                         /* There's already a field with this name.
2675                          * Put it after that field in the list of
2676                          * fields with this name, then allow the code
2677                          * after this if{} block to replace the old
2678                          * hfinfo with the new hfinfo in the GTree. Thus,
2679                          * we end up with a linked-list of same-named hfinfo's,
2680                          * with the root of the list being the hfinfo in the GTree */
2681                         same_name_next_hfinfo =
2682                             same_name_hfinfo->same_name_next;
2683
2684                         hfinfo->same_name_next = same_name_next_hfinfo;
2685                         if (same_name_next_hfinfo)
2686                                 same_name_next_hfinfo->same_name_prev = hfinfo;
2687
2688                         same_name_hfinfo->same_name_next = hfinfo;
2689                         hfinfo->same_name_prev = same_name_hfinfo;
2690                 }
2691                 g_tree_insert(gpa_name_tree, hfinfo->abbrev, hfinfo);
2692         }
2693
2694         return hfinfo->id;
2695 }
2696
2697 void
2698 proto_register_subtree_array(gint **indices, int num_indices)
2699 {
2700         int     i;
2701         gint    **ptr = indices;
2702
2703         /*
2704          * Make sure we haven't already allocated the array of "tree is
2705          * expanded" flags.
2706          *
2707          * XXX - if it's *really* important to allow more ett_ values to
2708          * be given out after "proto_init()" is called, we could expand
2709          * the array.
2710          */
2711         g_assert(tree_is_expanded == NULL);
2712
2713         /*
2714          * Assign "num_indices" subtree numbers starting at "num_tree_types",
2715          * returning the indices through the pointers in the array whose
2716          * first element is pointed to by "indices", and update
2717          * "num_tree_types" appropriately.
2718          */
2719         for (i = 0; i < num_indices; i++, ptr++, num_tree_types++)
2720                 **ptr = num_tree_types;
2721 }
2722
2723 void
2724 proto_item_fill_label(field_info *fi, gchar *label_str)
2725 {
2726         header_field_info               *hfinfo = fi->hfinfo;
2727
2728         guint8                          *bytes;
2729         guint32                         integer;
2730         ipv4_addr                       *ipv4;
2731         guint32                         n_addr; /* network-order IPv4 address */
2732         int                                     ret;    /*tmp return value */
2733
2734         switch(hfinfo->type) {
2735                 case FT_NONE:
2736                 case FT_PROTOCOL:
2737                         ret = snprintf(label_str, ITEM_LABEL_LENGTH,
2738                                 "%s", hfinfo->name);
2739                         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
2740                                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
2741                         break;
2742
2743                 case FT_BOOLEAN:
2744                         fill_label_boolean(fi, label_str);
2745                         break;
2746
2747                 case FT_BYTES:
2748                 case FT_UINT_BYTES:
2749                         bytes = fvalue_get(&fi->value);
2750                         if (bytes) {
2751                                 ret = snprintf(label_str, ITEM_LABEL_LENGTH,
2752                                         "%s: %s", hfinfo->name,
2753                                          bytes_to_str(bytes, fvalue_length(&fi->value)));
2754                                 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
2755                                         label_str[ITEM_LABEL_LENGTH - 1] = '\0';
2756                         }
2757                         else {
2758                                 ret = snprintf(label_str, ITEM_LABEL_LENGTH,
2759                                         "%s: <MISSING>", hfinfo->name);
2760                                 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
2761                                         label_str[ITEM_LABEL_LENGTH - 1] = '\0';
2762                         }
2763                         break;
2764
2765                 /* Four types of integers to take care of:
2766                  *      Bitfield, with val_string
2767                  *      Bitfield, w/o val_string
2768                  *      Non-bitfield, with val_string
2769                  *      Non-bitfield, w/o val_string
2770                  */
2771                 case FT_UINT8:
2772                 case FT_UINT16:
2773                 case FT_UINT24:
2774                 case FT_UINT32:
2775                 case FT_FRAMENUM:
2776                         if (hfinfo->bitmask) {
2777                                 if (hfinfo->strings) {
2778                                         fill_label_enumerated_bitfield(fi, label_str);
2779                                 }
2780                                 else {
2781                                         fill_label_numeric_bitfield(fi, label_str);
2782                                 }
2783                         }
2784                         else {
2785                                 if (hfinfo->strings) {
2786                                         fill_label_enumerated_uint(fi, label_str);
2787                                 }
2788                                 else {
2789                                         fill_label_uint(fi, label_str);
2790                                 }
2791                         }
2792                         break;
2793
2794                 case FT_UINT64:
2795                         fill_label_uint64(fi, label_str);
2796                         break;
2797
2798                 case FT_INT8:
2799                 case FT_INT16:
2800                 case FT_INT24:
2801                 case FT_INT32:
2802                         g_assert(!hfinfo->bitmask);
2803                         if (hfinfo->strings) {
2804                                 fill_label_enumerated_int(fi, label_str);
2805                         }
2806                         else {
2807                                 fill_label_int(fi, label_str);
2808                         }
2809                         break;
2810
2811                 case FT_INT64:
2812                         fill_label_int64(fi, label_str);
2813                         break;
2814
2815                 case FT_FLOAT:
2816                         ret = snprintf(label_str, ITEM_LABEL_LENGTH,
2817                                 "%s: %." STRINGIFY(FLT_DIG) "f",
2818                                 hfinfo->name, fvalue_get_floating(&fi->value));
2819                         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
2820                                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
2821                         break;
2822
2823                 case FT_DOUBLE:
2824                         ret = snprintf(label_str, ITEM_LABEL_LENGTH,
2825                                 "%s: %." STRINGIFY(DBL_DIG) "g",
2826                                 hfinfo->name, fvalue_get_floating(&fi->value));
2827                         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
2828                                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
2829                         break;
2830
2831                 case FT_ABSOLUTE_TIME:
2832                         ret = snprintf(label_str, ITEM_LABEL_LENGTH,
2833                                 "%s: %s", hfinfo->name,
2834                                 abs_time_to_str(fvalue_get(&fi->value)));
2835                         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
2836                                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
2837                         break;
2838
2839                 case FT_RELATIVE_TIME:
2840                         ret = snprintf(label_str, ITEM_LABEL_LENGTH,
2841                                 "%s: %s seconds", hfinfo->name,
2842                                 rel_time_to_secs_str(fvalue_get(&fi->value)));
2843                         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
2844                                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
2845                         break;
2846
2847                 case FT_IPXNET:
2848                         integer = fvalue_get_integer(&fi->value);
2849                         ret = snprintf(label_str, ITEM_LABEL_LENGTH,
2850                                 "%s: 0x%08X (%s)", hfinfo->name,
2851                                 integer, get_ipxnet_name(integer));
2852                         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
2853                                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
2854                         break;
2855
2856                 case FT_ETHER:
2857                         bytes = fvalue_get(&fi->value);
2858                         ret = snprintf(label_str, ITEM_LABEL_LENGTH,
2859                                 "%s: %s (%s)", hfinfo->name,
2860                                 ether_to_str(bytes),
2861                                 get_ether_name(bytes));
2862                         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
2863                                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
2864                         break;
2865
2866                 case FT_IPv4:
2867                         ipv4 = fvalue_get(&fi->value);
2868                         n_addr = ipv4_get_net_order_addr(ipv4);
2869                         ret = snprintf(label_str, ITEM_LABEL_LENGTH,
2870                                 "%s: %s (%s)", hfinfo->name,
2871                                 get_hostname(n_addr),
2872                                 ip_to_str((guint8*)&n_addr));
2873                         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
2874                                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
2875                         break;
2876
2877                 case FT_IPv6:
2878                         bytes = fvalue_get(&fi->value);
2879                         ret = snprintf(label_str, ITEM_LABEL_LENGTH,
2880                                 "%s: %s (%s)", hfinfo->name,
2881                                 get_hostname6((struct e_in6_addr *)bytes),
2882                                 ip6_to_str((struct e_in6_addr*)bytes));
2883                         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
2884                                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
2885                         break;
2886
2887                 case FT_STRING:
2888                 case FT_STRINGZ:
2889                 case FT_UINT_STRING:
2890                         bytes = fvalue_get(&fi->value);
2891                         ret = snprintf(label_str, ITEM_LABEL_LENGTH,
2892                                 "%s: %s", hfinfo->name,
2893                                 format_text(bytes, strlen(bytes)));
2894                         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
2895                                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
2896                         break;
2897
2898                 default:
2899                         g_error("hfinfo->type %d (%s) not handled\n",
2900                                         hfinfo->type,
2901                                         ftype_name(hfinfo->type));
2902                         g_assert_not_reached();
2903                         break;
2904         }
2905 }
2906
2907 static void
2908 fill_label_boolean(field_info *fi, gchar *label_str)
2909 {
2910         char    *p = label_str;
2911         int     bitfield_byte_length = 0, bitwidth;
2912         guint32 unshifted_value;
2913         guint32 value;
2914         int                                     ret;    /*tmp return value */
2915
2916         header_field_info               *hfinfo = fi->hfinfo;
2917         static const true_false_string  default_tf = { "True", "False" };
2918         const true_false_string         *tfstring = &default_tf;
2919
2920         if (hfinfo->strings) {
2921                 tfstring = (const struct true_false_string*) hfinfo->strings;
2922         }
2923
2924         value = fvalue_get_integer(&fi->value);
2925         if (hfinfo->bitmask) {
2926                 /* Figure out the bit width */
2927                 bitwidth = hfinfo_bitwidth(hfinfo);
2928
2929                 /* Un-shift bits */
2930                 unshifted_value = value;
2931                 if (hfinfo->bitshift > 0) {
2932                         unshifted_value <<= hfinfo->bitshift;
2933                 }
2934
2935                 /* Create the bitfield first */
2936                 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
2937                 bitfield_byte_length = p - label_str;
2938         }
2939
2940         /* Fill in the textual info */
2941         ret = snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
2942                 "%s: %s",  hfinfo->name,
2943                 value ? tfstring->true_string : tfstring->false_string);
2944         if ((ret == -1) || (ret >= (ITEM_LABEL_LENGTH - bitfield_byte_length)))
2945                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
2946 }
2947
2948
2949 /* Fills data for bitfield ints with val_strings */
2950 static void
2951 fill_label_enumerated_bitfield(field_info *fi, gchar *label_str)
2952 {
2953         char *format = NULL, *p;
2954         int bitfield_byte_length, bitwidth;
2955         guint32 unshifted_value;
2956         guint32 value;
2957         int                                     ret;    /*tmp return value */
2958
2959         header_field_info       *hfinfo = fi->hfinfo;
2960
2961         /* Figure out the bit width */
2962         bitwidth = hfinfo_bitwidth(hfinfo);
2963
2964         /* Pick the proper format string */
2965         format = hfinfo_uint_vals_format(hfinfo);
2966
2967         /* Un-shift bits */
2968         unshifted_value = fvalue_get_integer(&fi->value);
2969         value = unshifted_value;
2970         if (hfinfo->bitshift > 0) {
2971                 unshifted_value <<= hfinfo->bitshift;
2972         }
2973
2974         /* Create the bitfield first */
2975         p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
2976         bitfield_byte_length = p - label_str;
2977
2978         /* Fill in the textual info using stored (shifted) value */
2979         ret = snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
2980                         format,  hfinfo->name,
2981                         val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
2982         if ((ret == -1) || (ret >= (ITEM_LABEL_LENGTH - bitfield_byte_length)))
2983                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
2984 }
2985
2986 static void
2987 fill_label_numeric_bitfield(field_info *fi, gchar *label_str)
2988 {
2989         char *format = NULL, *p;
2990         int bitfield_byte_length, bitwidth;
2991         guint32 unshifted_value;
2992         guint32 value;
2993         int                                     ret;    /*tmp return value */
2994
2995         header_field_info       *hfinfo = fi->hfinfo;
2996
2997         /* Figure out the bit width */
2998         bitwidth = hfinfo_bitwidth(hfinfo);
2999
3000         /* Pick the proper format string */
3001         format = hfinfo_uint_format(hfinfo);
3002
3003         /* Un-shift bits */
3004         unshifted_value = fvalue_get_integer(&fi->value);
3005         value = unshifted_value;
3006         if (hfinfo->bitshift > 0) {
3007                 unshifted_value <<= hfinfo->bitshift;
3008         }
3009
3010         /* Create the bitfield using */
3011         p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
3012         bitfield_byte_length = p - label_str;
3013
3014         /* Fill in the textual info using stored (shifted) value */
3015         ret = snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
3016                         format,  hfinfo->name, value);
3017         if ((ret == -1) || (ret >= (ITEM_LABEL_LENGTH - bitfield_byte_length)))
3018                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3019
3020 }
3021
3022 static void
3023 fill_label_enumerated_uint(field_info *fi, gchar *label_str)
3024 {
3025         char *format = NULL;
3026         header_field_info       *hfinfo = fi->hfinfo;
3027         guint32 value;
3028         int                                     ret;    /*tmp return value */
3029
3030         /* Pick the proper format string */
3031         format = hfinfo_uint_vals_format(hfinfo);
3032
3033         value = fvalue_get_integer(&fi->value);
3034
3035         /* Fill in the textual info */
3036         ret = snprintf(label_str, ITEM_LABEL_LENGTH,
3037                         format,  hfinfo->name,
3038                         val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
3039         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3040                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3041 }
3042
3043 static void
3044 fill_label_uint(field_info *fi, gchar *label_str)
3045 {
3046         char *format = NULL;
3047         header_field_info       *hfinfo = fi->hfinfo;
3048         guint32 value;
3049         int                                     ret;    /*tmp return value */
3050
3051         /* Pick the proper format string */
3052         format = hfinfo_uint_format(hfinfo);
3053         value = fvalue_get_integer(&fi->value);
3054
3055         /* Fill in the textual info */
3056         ret = snprintf(label_str, ITEM_LABEL_LENGTH,
3057                         format,  hfinfo->name, value);
3058         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3059                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3060 }
3061
3062 static void
3063 fill_label_uint64(field_info *fi, gchar *label_str)
3064 {
3065         char *format = NULL;
3066         header_field_info       *hfinfo = fi->hfinfo;
3067         guint64 value;
3068         int                                     ret;    /*tmp return value */
3069
3070         /* Pick the proper format string */
3071         format = hfinfo_uint64_format(hfinfo);
3072         value = fvalue_get_integer64(&fi->value);
3073
3074         /* Fill in the textual info */
3075         ret = snprintf(label_str, ITEM_LABEL_LENGTH,
3076                         format,  hfinfo->name, value);
3077         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3078                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3079 }
3080
3081 static void
3082 fill_label_enumerated_int(field_info *fi, gchar *label_str)
3083 {
3084         char *format = NULL;
3085         header_field_info       *hfinfo = fi->hfinfo;
3086         guint32 value;
3087         int                                     ret;    /*tmp return value */
3088
3089         /* Pick the proper format string */
3090         format = hfinfo_int_vals_format(hfinfo);
3091         value = fvalue_get_integer(&fi->value);
3092
3093         /* Fill in the textual info */
3094         ret = snprintf(label_str, ITEM_LABEL_LENGTH,
3095                         format,  hfinfo->name,
3096                         val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
3097         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3098                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3099 }
3100
3101 static void
3102 fill_label_int(field_info *fi, gchar *label_str)
3103 {
3104         char *format = NULL;
3105         header_field_info       *hfinfo = fi->hfinfo;
3106         guint32 value;
3107         int                                     ret;    /*tmp return value */
3108
3109         /* Pick the proper format string */
3110         format = hfinfo_int_format(hfinfo);
3111         value = fvalue_get_integer(&fi->value);
3112
3113         /* Fill in the textual info */
3114         ret = snprintf(label_str, ITEM_LABEL_LENGTH,
3115                         format,  hfinfo->name, value);
3116         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3117                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3118 }
3119
3120 static void
3121 fill_label_int64(field_info *fi, gchar *label_str)
3122 {
3123         char *format = NULL;
3124         header_field_info       *hfinfo = fi->hfinfo;
3125         guint64 value;
3126         int                                     ret;    /*tmp return value */
3127
3128         /* Pick the proper format string */
3129         format = hfinfo_int64_format(hfinfo);
3130         value = fvalue_get_integer64(&fi->value);
3131
3132         /* Fill in the textual info */
3133         ret = snprintf(label_str, ITEM_LABEL_LENGTH,
3134                         format,  hfinfo->name, value);
3135         if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3136                 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3137 }
3138
3139 int
3140 hfinfo_bitwidth(header_field_info *hfinfo)
3141 {
3142         int bitwidth = 0;
3143
3144         if (!hfinfo->bitmask) {
3145                 return 0;
3146         }
3147
3148         switch(hfinfo->type) {
3149                 case FT_UINT8:
3150                 case FT_INT8:
3151                         bitwidth = 8;
3152                         break;
3153                 case FT_UINT16:
3154                 case FT_INT16:
3155                         bitwidth = 16;
3156                         break;
3157                 case FT_UINT24:
3158                 case FT_INT24:
3159                         bitwidth = 24;
3160                         break;
3161                 case FT_UINT32:
3162                 case FT_INT32:
3163                         bitwidth = 32;
3164                         break;
3165                 case FT_BOOLEAN:
3166                         bitwidth = hfinfo->display; /* hacky? :) */
3167                         break;
3168                 default:
3169                         g_assert_not_reached();
3170                         ;
3171         }
3172         return bitwidth;
3173 }
3174
3175 static char*
3176 hfinfo_uint_vals_format(header_field_info *hfinfo)
3177 {
3178         char *format = NULL;
3179
3180         switch(hfinfo->display) {
3181                 case BASE_DEC:
3182                         format = "%s: %s (%u)";
3183                         break;
3184                 case BASE_OCT: /* I'm lazy */
3185                         format = "%s: %s (%o)";
3186                         break;
3187                 case BASE_HEX:
3188                         switch(hfinfo->type) {
3189                                 case FT_UINT8:
3190                                         format = "%s: %s (0x%02x)";
3191                                         break;
3192                                 case FT_UINT16:
3193                                         format = "%s: %s (0x%04x)";
3194                                         break;
3195                                 case FT_UINT24:
3196                                         format = "%s: %s (0x%06x)";
3197                                         break;
3198                                 case FT_UINT32:
3199                                         format = "%s: %s (0x%08x)";
3200                                         break;
3201                                 default:
3202                                         g_assert_not_reached();
3203                                         ;
3204                         }
3205                         break;
3206                 default:
3207                         g_assert_not_reached();
3208                         ;
3209         }
3210         return format;
3211 }
3212
3213 static char*
3214 hfinfo_uint_format(header_field_info *hfinfo)
3215 {
3216         char *format = NULL;
3217
3218         /* Pick the proper format string */
3219         if (hfinfo->type == FT_FRAMENUM) {
3220                 /*
3221                  * Frame numbers are always displayed in decimal.
3222                  */
3223                 format = "%s: %u";
3224         } else {
3225                 switch(hfinfo->display) {
3226                         case BASE_DEC:
3227                                 format = "%s: %u";
3228                                 break;
3229                         case BASE_OCT: /* I'm lazy */
3230                                 format = "%s: %o";
3231                                 break;
3232                         case BASE_HEX:
3233                                 switch(hfinfo->type) {
3234                                         case FT_UINT8:
3235                                                 format = "%s: 0x%02x";
3236                                                 break;
3237                                         case FT_UINT16:
3238                                                 format = "%s: 0x%04x";
3239                                                 break;
3240                                         case FT_UINT24:
3241                                                 format = "%s: 0x%06x";
3242                                                 break;
3243                                         case FT_UINT32:
3244                                                 format = "%s: 0x%08x";
3245                                                 break;
3246                                         default:
3247                                                 g_assert_not_reached();
3248                                                 ;
3249                                 }
3250                                 break;
3251                         default:
3252                                 g_assert_not_reached();
3253                                 ;
3254                 }
3255         }
3256         return format;
3257 }
3258
3259 static char*
3260 hfinfo_int_vals_format(header_field_info *hfinfo)
3261 {
3262         char *format = NULL;
3263
3264         switch(hfinfo->display) {
3265                 case BASE_DEC:
3266                         format = "%s: %s (%d)";
3267                         break;
3268                 case BASE_OCT: /* I'm lazy */
3269                         format = "%s: %s (%o)";
3270                         break;
3271                 case BASE_HEX:
3272                         switch(hfinfo->type) {
3273                                 case FT_INT8:
3274                                         format = "%s: %s (0x%02x)";
3275                                         break;
3276                                 case FT_INT16:
3277                                         format = "%s: %s (0x%04x)";
3278                                         break;
3279                                 case FT_INT24:
3280                                         format = "%s: %s (0x%06x)";
3281                                         break;
3282                                 case FT_INT32:
3283                                         format = "%s: %s (0x%08x)";
3284                                         break;
3285                                 default:
3286                                         g_assert_not_reached();
3287                                         ;
3288                         }
3289                         break;
3290                 default:
3291                         g_assert_not_reached();
3292                         ;
3293         }
3294         return format;
3295 }
3296
3297 static char*
3298 hfinfo_uint64_format(header_field_info *hfinfo)
3299 {
3300         char *format = NULL;
3301
3302         /* Pick the proper format string */
3303         switch(hfinfo->display) {
3304                 case BASE_DEC:
3305                         format = "%s: %" PRIu64;
3306                         break;
3307                 case BASE_OCT: /* I'm lazy */
3308                         format = "%s: %" PRIo64;
3309                         break;
3310                 case BASE_HEX:
3311                         format = "%s: 0x%016" PRIx64;
3312                         break;
3313                 default:
3314                         g_assert_not_reached();
3315                         ;
3316         }
3317         return format;
3318 }
3319
3320 static char*
3321 hfinfo_int_format(header_field_info *hfinfo)
3322 {
3323         char *format = NULL;
3324
3325         /* Pick the proper format string */
3326         switch(hfinfo->display) {
3327                 case BASE_DEC:
3328                         format = "%s: %d";
3329                         break;
3330                 case BASE_OCT: /* I'm lazy */
3331                         format = "%s: %o";
3332                         break;
3333                 case BASE_HEX:
3334                         switch(hfinfo->type) {
3335                                 case FT_INT8:
3336                                         format = "%s: 0x%02x";
3337                                         break;
3338                                 case FT_INT16:
3339                                         format = "%s: 0x%04x";
3340                                         break;
3341                                 case FT_INT24:
3342                                         format = "%s: 0x%06x";
3343                                         break;
3344                                 case FT_INT32:
3345                                         format = "%s: 0x%08x";
3346                                         break;
3347                                 default:
3348                                         g_assert_not_reached();
3349                                         ;
3350                         }
3351                         break;
3352                 default:
3353                         g_assert_not_reached();
3354                         ;
3355         }
3356         return format;
3357 }
3358
3359 static char*
3360 hfinfo_int64_format(header_field_info *hfinfo)
3361 {
3362         char *format = NULL;
3363
3364         /* Pick the proper format string */
3365         switch(hfinfo->display) {
3366                 case BASE_DEC:
3367                         format = "%s: %" PRId64;
3368                         break;
3369                 case BASE_OCT: /* I'm lazy */
3370                         format = "%s: %" PRIo64;
3371                         break;
3372                 case BASE_HEX:
3373                         format = "%s: 0x%016" PRIx64;
3374                         break;
3375                 default:
3376                         g_assert_not_reached();
3377                         ;
3378         }
3379         return format;
3380 }
3381
3382
3383
3384 int
3385 proto_registrar_n(void)
3386 {
3387         return gpa_hfinfo.len;
3388 }
3389
3390 char*
3391 proto_registrar_get_name(int n)
3392 {
3393         header_field_info *hfinfo;
3394
3395         PROTO_REGISTRAR_GET_NTH(n, hfinfo);
3396         return hfinfo->name;
3397 }
3398
3399 char*
3400 proto_registrar_get_abbrev(int n)
3401 {
3402         header_field_info *hfinfo;
3403
3404         PROTO_REGISTRAR_GET_NTH(n, hfinfo);
3405         return hfinfo->abbrev;
3406 }
3407
3408 int
3409 proto_registrar_get_ftype(int n)
3410 {
3411         header_field_info *hfinfo;
3412
3413         PROTO_REGISTRAR_GET_NTH(n, hfinfo);
3414         return hfinfo->type;
3415 }
3416
3417 int
3418 proto_registrar_get_parent(int n)
3419 {
3420         header_field_info *hfinfo;
3421
3422         PROTO_REGISTRAR_GET_NTH(n, hfinfo);
3423         return hfinfo->parent;
3424 }
3425
3426 gboolean
3427 proto_registrar_is_protocol(int n)
3428 {
3429         header_field_info *hfinfo;
3430
3431         PROTO_REGISTRAR_GET_NTH(n, hfinfo);
3432         return (hfinfo->parent == -1 ? TRUE : FALSE);
3433 }
3434
3435 /* Returns length of field in packet (not necessarily the length
3436  * in our internal representation, as in the case of IPv4).
3437  * 0 means undeterminable at time of registration
3438  * -1 means the field is not registered. */
3439 gint
3440 proto_registrar_get_length(int n)
3441 {
3442         header_field_info *hfinfo;
3443
3444         PROTO_REGISTRAR_GET_NTH(n, hfinfo);
3445         return ftype_length(hfinfo->type);
3446 }
3447
3448
3449
3450 /* Looks for a protocol or a field in a proto_tree. Returns TRUE if
3451  * it exists anywhere, or FALSE if it exists nowhere. */
3452 gboolean
3453 proto_check_for_protocol_or_field(proto_tree* tree, int id)
3454 {
3455         GPtrArray *ptrs = proto_get_finfo_ptr_array(tree, id);
3456
3457         if (!ptrs) {
3458                 return FALSE;
3459         }
3460         else if (g_ptr_array_len(ptrs) > 0) {
3461                 return TRUE;
3462         }
3463         else {
3464                 return FALSE;
3465         }
3466 }
3467
3468 /* Return GPtrArray* of field_info pointers for all hfindex that appear in tree.
3469  * This only works if the hfindex was "primed" before the dissection
3470  * took place, as we just pass back the already-created GPtrArray*.
3471  * The caller should *not* free the GPtrArray*; proto_tree_free_node()
3472  * handles that. */
3473 GPtrArray*
3474 proto_get_finfo_ptr_array(proto_tree *tree, int id)
3475 {
3476         return g_hash_table_lookup(PTREE_DATA(tree)->interesting_hfids,
3477             GINT_TO_POINTER(id));
3478 }
3479
3480
3481 /* Helper struct and function for proto_find_info() */
3482 typedef struct {
3483         GPtrArray       *array;
3484         int             id;
3485 } ffdata_t;
3486
3487 static gboolean
3488 find_finfo(proto_node *node, gpointer data)
3489 {
3490         field_info *fi = PITEM_FINFO(node);
3491         if (fi && fi->hfinfo) {
3492                 if (fi->hfinfo->id == ((ffdata_t*)data)->id) {
3493                         g_ptr_array_add(((ffdata_t*)data)->array, fi);
3494                 }
3495         }
3496
3497         /* Don't stop traversing. */
3498         return FALSE;
3499 }
3500
3501 /* Return GPtrArray* of field_info pointers for all hfindex that appear in a tree.
3502  * This works on any proto_tree, primed or unprimed, but actually searches
3503  * the tree, so it is slower than using proto_get_finfo_ptr_array on a primed tree.
3504  * The caller does need to free the returned GPtrArray with
3505  * g_ptr_array_free(<array>, FALSE).
3506  */
3507 GPtrArray*
3508 proto_find_finfo(proto_tree *tree, int id)
3509 {
3510         ffdata_t        ffdata;
3511
3512         ffdata.array = g_ptr_array_new();
3513         ffdata.id = id;
3514
3515         proto_tree_traverse_pre_order(tree, find_finfo, &ffdata);
3516
3517         return ffdata.array;
3518 }       
3519
3520
3521 typedef struct {
3522         guint           offset;
3523         field_info      *finfo;
3524         tvbuff_t        *tvb;
3525 } offset_search_t;
3526
3527 static gboolean
3528 check_for_offset(proto_node *node, gpointer data)
3529 {
3530         field_info          *fi = PITEM_FINFO(node);
3531         offset_search_t         *offsearch = data;
3532
3533         /* !fi == the top most container node which holds nothing */
3534         if (fi && !PROTO_ITEM_IS_HIDDEN(node) && fi->ds_tvb && offsearch->tvb == fi->ds_tvb) {
3535                 if (offsearch->offset >= (guint) fi->start &&
3536                                 offsearch->offset < (guint) (fi->start + fi->length)) {
3537
3538                         offsearch->finfo = fi;
3539                         return FALSE; /* keep traversing */
3540                 }
3541         }
3542         return FALSE; /* keep traversing */
3543 }
3544
3545 /* Search a proto_tree backwards (from leaves to root) looking for the field
3546  * whose start/length occupies 'offset' */
3547 /* XXX - I couldn't find an easy way to search backwards, so I search
3548  * forwards, w/o stopping. Therefore, the last finfo I find will the be
3549  * the one I want to return to the user. This algorithm is inefficient
3550  * and could be re-done, but I'd have to handle all the children and
3551  * siblings of each node myself. When I have more time I'll do that.
3552  * (yeah right) */
3553 field_info*
3554 proto_find_field_from_offset(proto_tree *tree, guint offset, tvbuff_t *tvb)
3555 {
3556         offset_search_t         offsearch;
3557
3558         offsearch.offset = offset;
3559         offsearch.finfo = NULL;
3560         offsearch.tvb = tvb;
3561
3562         proto_tree_traverse_pre_order(tree, check_for_offset, &offsearch);
3563
3564         return offsearch.finfo;
3565 }
3566
3567 /* Dumps the protocols in the registration database to stdout.  An independent
3568  * program can take this output and format it into nice tables or HTML or
3569  * whatever.
3570  *
3571  * There is one record per line. The fields are tab-delimited.
3572  *
3573  * Field 1 = protocol name
3574  * Field 2 = protocol short name
3575  * Field 3 = protocol filter name
3576  */
3577 void
3578 proto_registrar_dump_protocols(void)
3579 {
3580         protocol_t              *protocol;
3581         int                     i;
3582         void                    *cookie;
3583
3584         for (i = proto_get_first_protocol(&cookie); i != -1;
3585             i = proto_get_next_protocol(&cookie)) {
3586                 protocol = find_protocol_by_id(i);
3587                 printf("%s\t%s\t%s\n", protocol->name, protocol->short_name,
3588                     protocol->filter_name);
3589         }
3590 }
3591
3592 /* Dumps the value_string and true/false strings for fields that have
3593  * them. There is one record per line. Fields are tab-delimited.
3594  * There are two types of records, Value String records and True/False
3595  * String records. The first field, 'V' or 'T', indicates the type
3596  * of record.
3597  *
3598  * Value Strings
3599  * -------------
3600  * Field 1 = 'V'
3601  * Field 2 = field abbreviation to which this value string corresponds
3602  * Field 3 = Integer value
3603  * Field 4 = String
3604  *
3605  * True/False Strings
3606  * ------------------
3607  * Field 1 = 'T'
3608  * Field 2 = field abbreviation to which this true/false string corresponds
3609  * Field 3 = True String
3610  * Field 4 = False String
3611  */
3612 void
3613 proto_registrar_dump_values(void)
3614 {
3615         header_field_info       *hfinfo, *parent_hfinfo;
3616         int                     i, len, vi;
3617         const value_string      *vals;
3618         const true_false_string *tfs;
3619
3620         len = gpa_hfinfo.len;
3621         for (i = 0; i < len ; i++) {
3622                 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
3623
3624                  if (hfinfo->id == hf_text_only) {
3625                          continue;
3626                  }
3627
3628                 /* ignore protocols */
3629                 if (proto_registrar_is_protocol(i)) {
3630                         continue;
3631                 }
3632                 /* process header fields */
3633                 else {
3634                         /*
3635                          * If this field isn't at the head of the list of
3636                          * fields with this name, skip this field - all
3637                          * fields with the same name are really just versions
3638                          * of the same field stored in different bits, and
3639                          * should have the same type/radix/value list, and
3640                          * just differ in their bit masks.  (If a field isn't
3641                          * a bitfield, but can be, say, 1 or 2 bytes long,
3642                          * it can just be made FT_UINT16, meaning the
3643                          * *maximum* length is 2 bytes, and be used
3644                          * for all lengths.)
3645                          */
3646                         if (hfinfo->same_name_prev != NULL)
3647                                 continue;
3648
3649                         PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
3650
3651                         vals = NULL;
3652                         tfs = NULL;
3653
3654                         if (hfinfo->type == FT_UINT8 ||
3655                                 hfinfo->type == FT_UINT16 ||
3656                                 hfinfo->type == FT_UINT24 ||
3657                                 hfinfo->type == FT_UINT32 ||
3658                                 hfinfo->type == FT_UINT64 ||
3659                                 hfinfo->type == FT_INT8 ||
3660                                 hfinfo->type == FT_INT16 ||
3661                                 hfinfo->type == FT_INT24 ||
3662                                 hfinfo->type == FT_INT32 ||
3663                                 hfinfo->type == FT_INT64) {
3664
3665                                 vals = hfinfo->strings;
3666                         }
3667                         else if (hfinfo->type == FT_BOOLEAN) {
3668                                 tfs = hfinfo->strings;
3669                         }
3670
3671                         /* Print value strings? */
3672                         if (vals) {
3673                                 vi = 0;
3674                                 while (vals[vi].strptr) {
3675                                         /* Print in the proper base */
3676                                         if (hfinfo->display == BASE_HEX) {
3677                                                 printf("V\t%s\t0x%x\t%s\n",
3678                                                                 hfinfo->abbrev,
3679                                                                 vals[vi].value,
3680                                                                 vals[vi].strptr);
3681                                         }
3682                                         else {
3683                                                 printf("V\t%s\t%u\t%s\n",
3684                                                                 hfinfo->abbrev,
3685                                                                 vals[vi].value,
3686                                                                 vals[vi].strptr);
3687                                         }
3688                                         vi++;
3689                                 }
3690                         }
3691
3692                         /* Print true/false strings? */
3693                         else if (tfs) {
3694                                 printf("T\t%s\t%s\t%s\n", hfinfo->abbrev,
3695                                                 tfs->true_string, tfs->false_string);
3696                         }
3697                 }
3698         }
3699 }
3700
3701 /* Dumps the contents of the registration database to stdout. An indepedent
3702  * program can take this output and format it into nice tables or HTML or
3703  * whatever.
3704  *
3705  * There is one record per line. Each record is either a protocol or a header
3706  * field, differentiated by the first field. The fields are tab-delimited.
3707  *
3708  * Protocols
3709  * ---------
3710  * Field 1 = 'P'
3711  * Field 2 = descriptive protocol name
3712  * Field 3 = protocol abbreviation
3713  *
3714  * Header Fields
3715  * -------------
3716  * (format 1)
3717  * Field 1 = 'F'
3718  * Field 2 = descriptive field name
3719  * Field 3 = field abbreviation
3720  * Field 4 = type ( textual representation of the the ftenum type )
3721  * Field 5 = parent protocol abbreviation
3722  *
3723  * (format 2 adds these fields:)
3724  * Field 6 = base for display (for integer types)
3725  * Field 7 = blurb describing field
3726  */
3727 void
3728 proto_registrar_dump_fields(int format)
3729 {
3730         header_field_info       *hfinfo, *parent_hfinfo;
3731         int                     i, len;
3732         const char              *enum_name;
3733         const char              *base_name;
3734
3735         len = gpa_hfinfo.len;
3736         for (i = 0; i < len ; i++) {
3737                 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
3738
3739                 /*
3740                  * Skip fields with zero-length names or abbreviations;
3741                  * the pseudo-field for "proto_tree_add_text()" is such
3742                  * a field, and we don't want it in the list of filterable
3743                  * fields.
3744                  *
3745                  *
3746                  * XXX - perhaps the name and abbrev field should be null
3747                  * pointers rather than null strings for that pseudo-field,
3748                  * but we'd have to add checks for null pointers in some
3749                  * places if we did that.
3750                  *
3751                  * Or perhaps protocol tree items added with
3752                  * "proto_tree_add_text()" should have -1 as the field index,
3753                  * with no pseudo-field being used, but that might also
3754                  * require special checks for -1 to be added.
3755                  */
3756                 /* XXX - we could just skip the special text
3757                  * pseudo-field by testing: if (hfinfo->id == hf_text_only)
3758                  * */
3759                 if (hfinfo->name[0] == 0 || hfinfo->abbrev[0] == 0)
3760                         continue;
3761
3762                 /* format for protocols */
3763                 if (proto_registrar_is_protocol(i)) {
3764                         printf("P\t%s\t%s\n", hfinfo->name, hfinfo->abbrev);
3765                 }
3766                 /* format for header fields */
3767                 else {
3768                         /*
3769                          * If this field isn't at the head of the list of
3770                          * fields with this name, skip this field - all
3771                          * fields with the same name are really just versions
3772                          * of the same field stored in different bits, and
3773                          * should have the same type/radix/value list, and
3774                          * just differ in their bit masks.  (If a field isn't
3775                          * a bitfield, but can be, say, 1 or 2 bytes long,
3776                          * it can just be made FT_UINT16, meaning the
3777                          * *maximum* length is 2 bytes, and be used
3778                          * for all lengths.)
3779                          */
3780                         if (hfinfo->same_name_prev != NULL)
3781                                 continue;
3782
3783                         PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
3784
3785                         enum_name = ftype_name(hfinfo->type);
3786                         base_name = "";
3787
3788                         if (format > 1) {
3789                                 if (hfinfo->type == FT_UINT8 ||
3790                                         hfinfo->type == FT_UINT16 ||
3791                                         hfinfo->type == FT_UINT24 ||
3792                                         hfinfo->type == FT_UINT32 ||
3793                                         hfinfo->type == FT_UINT64 ||
3794                                         hfinfo->type == FT_INT8 ||
3795                                         hfinfo->type == FT_INT16 ||
3796                                         hfinfo->type == FT_INT24 ||
3797                                         hfinfo->type == FT_INT32 ||
3798                                         hfinfo->type == FT_INT64) {
3799
3800                                         
3801                                         switch(hfinfo->display) {
3802                                                 case BASE_NONE:
3803                                                         base_name = "BASE_NONE";
3804                                                         break;
3805                                                 case BASE_DEC:
3806                                                         base_name = "BASE_DEC";
3807                                                         break;
3808                                                 case BASE_HEX:
3809                                                         base_name = "BASE_HEX";
3810                                                         break;
3811                                                 case BASE_OCT:
3812                                                         base_name = "BASE_OCT";
3813                                                         break;
3814                                         }
3815                                 }
3816                         }
3817
3818                         if (format == 1) {
3819                                 printf("F\t%s\t%s\t%s\t%s\t%s\n", hfinfo->name, hfinfo->abbrev,
3820                                         enum_name,parent_hfinfo->abbrev, hfinfo->blurb);
3821                         }
3822                         else if (format == 2) {
3823                                 printf("F\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n",
3824                                         hfinfo->name, hfinfo->abbrev,
3825                                         enum_name,parent_hfinfo->abbrev, hfinfo->blurb,
3826                                         base_name, hfinfo->blurb);
3827                         }
3828                 }
3829         }
3830 }
3831
3832 static char*
3833 hfinfo_numeric_format(header_field_info *hfinfo)
3834 {
3835         char *format = NULL;
3836
3837         /* Pick the proper format string */
3838         if (hfinfo->type == FT_FRAMENUM) {
3839                 /*
3840                  * Frame numbers are always displayed in decimal.
3841                  */
3842                 format = "%s == %u";
3843         } else {
3844                 /* Pick the proper format string */
3845                 switch(hfinfo->display) {
3846                         case BASE_DEC:
3847                         case BASE_OCT: /* I'm lazy */
3848                                 switch(hfinfo->type) {
3849                                         case FT_UINT8:
3850                                         case FT_UINT16:
3851                                         case FT_UINT24:
3852                                         case FT_UINT32:
3853                                                 format = "%s == %u";
3854                                                 break;
3855                                         case FT_UINT64:
3856                                                 format = "%s == %" PRIu64;
3857                                                 break;
3858                                         case FT_INT8:
3859                                         case FT_INT16:
3860                                         case FT_INT24:
3861                                         case FT_INT32:
3862                                                 format = "%s == %d";
3863                                                 break;
3864                                         case FT_INT64:
3865                                                 format = "%s == %" PRId64;
3866                                                 break;
3867                                         default:
3868                                                 g_assert_not_reached();
3869                                                 ;
3870                                 }
3871                                 break;
3872                         case BASE_HEX:
3873                                 switch(hfinfo->type) {
3874                                         case FT_UINT8:
3875                                                 format = "%s == 0x%02x";
3876                                                 break;
3877                                         case FT_UINT16:
3878                                                 format = "%s == 0x%04x";
3879                                                 break;
3880                                         case FT_UINT24:
3881                                                 format = "%s == 0x%06x";
3882                                                 break;
3883                                         case FT_UINT32:
3884                                                 format = "%s == 0x%08x";
3885                                                 break;
3886                                         case FT_UINT64:
3887                                                 format = "%s == 0x%016" PRIx64;
3888                                                 break;
3889                                         default:
3890                                                 g_assert_not_reached();
3891                                                 ;
3892                                 }
3893                                 break;
3894                         default:
3895                                 g_assert_not_reached();
3896                                 ;
3897                 }
3898         }
3899         return format;
3900 }
3901
3902 /*
3903  * Returns TRUE if we can do a "match selected" on the field, FALSE
3904  * otherwise.
3905  */
3906 gboolean
3907 proto_can_match_selected(field_info *finfo, epan_dissect_t *edt)
3908 {
3909         header_field_info       *hfinfo;
3910         gint                    length;
3911
3912         hfinfo = finfo->hfinfo;
3913         g_assert(hfinfo);
3914
3915         switch(hfinfo->type) {
3916
3917                 case FT_BOOLEAN:
3918                 case FT_UINT8:
3919                 case FT_UINT16:
3920                 case FT_UINT24:
3921                 case FT_UINT32:
3922                 case FT_INT8:
3923                 case FT_INT16:
3924                 case FT_INT24:
3925                 case FT_INT32:
3926                 case FT_FRAMENUM:
3927                 case FT_UINT64:
3928                 case FT_INT64:
3929                 case FT_IPv4:
3930                 case FT_IPXNET:
3931                 case FT_IPv6:
3932                 case FT_FLOAT:
3933                 case FT_DOUBLE:
3934                 case FT_ABSOLUTE_TIME:
3935                 case FT_RELATIVE_TIME:
3936                 case FT_STRING:
3937                 case FT_STRINGZ:
3938                 case FT_UINT_STRING:
3939                 case FT_ETHER:
3940                 case FT_BYTES:
3941                 case FT_UINT_BYTES:
3942                 case FT_PROTOCOL:
3943                         /*
3944                          * These all have values, so we can match.
3945                          */
3946                         return TRUE;
3947
3948                 default:
3949                         /*
3950                          * This doesn't have a value, so we'd match
3951                          * on the raw bytes at this address.
3952                          *
3953                          * Should we be allowed to access to the raw bytes?
3954                          * If "edt" is NULL, the answer is "no".
3955                          */
3956                         if (edt == NULL)
3957                                 return FALSE;
3958
3959                         /*
3960                          * Is this field part of the raw frame tvbuff?
3961                          * If not, we can't use "frame[N:M]" to match
3962                          * it.
3963                          *
3964                          * XXX - should this be frame-relative, or
3965                          * protocol-relative?
3966                          *
3967                          * XXX - does this fallback for non-registered
3968                          * fields even make sense?
3969                          */
3970                         if (finfo->ds_tvb != edt->tvb)
3971                                 return FALSE;
3972
3973                         /*
3974                          * If the length is 0, there's nothing to match, so
3975                          * we can't match.  (Also check for negative values,
3976                          * just in case, as we'll cast it to an unsigned
3977                          * value later.)
3978                          */
3979                         length = finfo->length;
3980                         if (length <= 0)
3981                                 return FALSE;
3982
3983                         /*
3984                          * Don't go past the end of that tvbuff.
3985                          */
3986                         if ((guint)length > tvb_length(finfo->ds_tvb))
3987                                 length = tvb_length(finfo->ds_tvb);
3988                         if (length <= 0)
3989                                 return FALSE;
3990                         return TRUE;
3991         }
3992 }
3993
3994 char*
3995 proto_construct_dfilter_string(field_info *finfo, epan_dissect_t *edt)
3996 {
3997         header_field_info       *hfinfo;
3998         int                     abbrev_len;
3999         char                    *buf, *stringified, *format, *ptr;
4000         int                     dfilter_len, i;
4001         gint                    start, length, length_remaining;
4002         guint8                  c;
4003
4004         hfinfo = finfo->hfinfo;
4005         g_assert(hfinfo);
4006         abbrev_len = strlen(hfinfo->abbrev);
4007
4008         /*
4009          * XXX - we should add "val_to_string_repr" and "string_repr_len"
4010          * functions for more types, and use them whenever possible.
4011          *
4012          * The FT_UINT and FT_INT types are the only tricky ones, as
4013          * we choose the base in the string expression based on the
4014          * display base of the field.
4015          *
4016          * Note that the base does matter, as this is also used for
4017          * the protocolinfo tap.
4018          *
4019          * It might be nice to use that in "proto_item_fill_label()"
4020          * as well, although, there, you'd have to deal with the base
4021          * *and* with resolved values for addresses.
4022          *
4023          * Perhaps we need two different val_to_string routines, one
4024          * to generate items for display filters and one to generate
4025          * strings for display, and pass to both of them the
4026          * "display" and "strings" values in the header_field_info
4027          * structure for the field, so they can get the base and,
4028          * if the field is Boolean or an enumerated integer type,
4029          * the tables used to generate human-readable values.
4030          */
4031         switch(hfinfo->type) {
4032
4033                 case FT_UINT8:
4034                 case FT_UINT16:
4035                 case FT_UINT24:
4036                 case FT_UINT32:
4037                 case FT_INT8:
4038                 case FT_INT16:
4039                 case FT_INT24:
4040                 case FT_INT32:
4041                 case FT_FRAMENUM:
4042                         /*
4043                          * 4 bytes for " == ".
4044                          * 11 bytes for:
4045                          *
4046                          *      a sign + up to 10 digits of 32-bit integer,
4047                          *      in decimal;
4048                          *
4049                          *      "0x" + 8 digits of 32-bit integer, in hex;
4050                          *
4051                          *      11 digits of 32-bit integer, in octal.
4052                          *      (No, we don't do octal, but this way,
4053                          *      we know that if we do, this will still
4054                          *      work.)
4055                          *
4056                          * 1 byte for the trailing '\0'.
4057                          */
4058                         dfilter_len = abbrev_len + 4 + 11 + 1;
4059                         buf = g_malloc0(dfilter_len);
4060                         format = hfinfo_numeric_format(hfinfo);
4061                         snprintf(buf, dfilter_len, format, hfinfo->abbrev, fvalue_get_integer(&finfo->value));
4062                         break;
4063
4064                 case FT_INT64:
4065                 case FT_UINT64:
4066                         /*
4067                          * 4 bytes for " == ".
4068                          * 22 bytes for:
4069                          *
4070                          *      a sign + up to 20 digits of 32-bit integer,
4071                          *      in decimal;
4072                          *
4073                          *      "0x" + 16 digits of 32-bit integer, in hex;
4074                          *
4075                          *      22 digits of 32-bit integer, in octal.
4076                          *      (No, we don't do octal, but this way,
4077                          *      we know that if we do, this will still
4078                          *      work.)
4079                          *
4080                          * 1 byte for the trailing '\0'.
4081                          */
4082                         dfilter_len = abbrev_len + 4 + 22 + 1;
4083                         buf = g_malloc0(dfilter_len);
4084                         format = hfinfo_numeric_format(hfinfo);
4085                         snprintf(buf, dfilter_len, format, hfinfo->abbrev, fvalue_get_integer64(&finfo->value));
4086                         break;
4087
4088                 case FT_IPXNET:
4089                         /*
4090                          * 4 bytes for " == ".
4091                          * 2 bytes for "0x".
4092                          * 8 bytes for 8 digits of 32-bit hex number.
4093                          * 1 byte for the trailing '\0'.
4094                          */
4095                         dfilter_len = abbrev_len + 4 + 2 + 8 + 1;
4096                         buf = g_malloc0(dfilter_len);
4097                         snprintf(buf, dfilter_len, "%s == 0x%08x", hfinfo->abbrev,
4098                                         fvalue_get_integer(&finfo->value));
4099                         break;
4100
4101                 case FT_IPv6:
4102                         /*
4103                          * 4 bytes for " == ".
4104                          * N bytes for the string for the address.
4105                          * 1 byte for the trailing '\0'.
4106                          */
4107                         stringified = ip6_to_str((struct e_in6_addr*) fvalue_get(&finfo->value));
4108                         dfilter_len = abbrev_len + 4 + strlen(stringified) + 1;
4109                         buf = g_malloc0(dfilter_len);
4110                         snprintf(buf, dfilter_len, "%s == %s", hfinfo->abbrev,
4111                                         stringified);
4112                         break;
4113
4114                 /* These use the fvalue's "to_string_repr" method. */
4115                 case FT_BOOLEAN:
4116                 case FT_STRING:
4117                 case FT_ETHER:
4118                 case FT_BYTES:
4119                 case FT_UINT_BYTES:
4120                 case FT_FLOAT:
4121                 case FT_DOUBLE:
4122                 case FT_ABSOLUTE_TIME:
4123                 case FT_RELATIVE_TIME:
4124                 case FT_IPv4:
4125                         /* Figure out the string length needed.
4126                          *      The ft_repr length.
4127                          *      4 bytes for " == ".
4128                          *      1 byte for trailing NUL.
4129                          */
4130                         dfilter_len = fvalue_string_repr_len(&finfo->value,
4131                                         FTREPR_DFILTER);
4132                         dfilter_len += abbrev_len + 4 + 1;
4133                         buf = g_malloc0(dfilter_len);
4134
4135                         /* Create the string */
4136                         snprintf(buf, dfilter_len, "%s == ", hfinfo->abbrev);
4137                         fvalue_to_string_repr(&finfo->value,
4138                                         FTREPR_DFILTER,
4139                                         &buf[abbrev_len + 4]);
4140                         break;
4141
4142                 case FT_PROTOCOL:
4143                         buf = g_strdup(finfo->hfinfo->abbrev);
4144                         break;
4145
4146                 default:
4147                         /*
4148                          * This doesn't have a value, so we'd match
4149                          * on the raw bytes at this address.
4150                          *
4151                          * Should we be allowed to access to the raw bytes?
4152                          * If "edt" is NULL, the answer is "no".
4153                          */
4154                         if (edt == NULL)
4155                                 return FALSE;
4156
4157                         /*
4158                          * Is this field part of the raw frame tvbuff?
4159                          * If not, we can't use "frame[N:M]" to match
4160                          * it.
4161                          *
4162                          * XXX - should this be frame-relative, or
4163                          * protocol-relative?
4164                          *
4165                          * XXX - does this fallback for non-registered
4166                          * fields even make sense?
4167                          */
4168                         if (finfo->ds_tvb != edt->tvb)
4169                                 return NULL;    /* you lose */
4170
4171                         /*
4172                          * If the length is 0, there's nothing to match, so
4173                          * we can't match.  (Also check for negative values,
4174                          * just in case, as we'll cast it to an unsigned
4175                          * value later.)
4176                          */
4177                         length = finfo->length;
4178                         if (length <= 0)
4179                                 return NULL;
4180
4181                         /*
4182                          * Don't go past the end of that tvbuff.
4183                          */
4184                         length_remaining = tvb_length_remaining(finfo->ds_tvb, finfo->start);
4185                         if (length > length_remaining)
4186                                 length = length_remaining;
4187                         if (length <= 0)
4188                                 return NULL;
4189                         
4190                         start = finfo->start;
4191                         buf = g_malloc0(32 + length * 3);
4192                         ptr = buf;
4193
4194                         sprintf(ptr, "frame[%d:%d] == ", finfo->start, length);
4195                         ptr = buf+strlen(buf);
4196
4197                         for (i=0;i<length; i++) {
4198                                 c = tvb_get_guint8(finfo->ds_tvb, start);
4199                                 start++;
4200                                 if (i == 0 ) {
4201                                         sprintf(ptr, "%02x", c);
4202                                 }
4203                                 else {
4204                                         sprintf(ptr, ":%02x", c);
4205                                 }
4206                                 ptr = buf+strlen(buf);
4207                         }
4208                         break;
4209         }
4210
4211         return buf;
4212 }