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