Clean up indentation.
[obnox/wireshark/wip.git] / epan / proto.c
1 /* proto.c
2  * Routines for protocol tree
3  *
4  * $Id: proto.c,v 1.47 2001/12/07 03:39:26 gram Exp $
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 #ifdef HAVE_SYS_TYPES_H
30 # include <sys/types.h>
31 #endif
32
33 #include <stdio.h>
34 #include <string.h>
35 #include <glib.h>
36
37 #ifdef NEED_SNPRINTF_H
38 # include "snprintf.h"
39 #endif
40
41 #include "packet.h"
42 #include "strutil.h"
43 #include "resolv.h"
44 #include "plugins.h"
45 #include "ipv6-utils.h"
46 #include "proto.h"
47 #include "int-64bit.h"
48
49 #define cVALS(x) (const value_string*)(x)
50
51 static gboolean
52 proto_tree_free_node(GNode *node, gpointer data);
53
54 static void fill_label_boolean(field_info *fi, gchar *label_str);
55 static void fill_label_uint(field_info *fi, gchar *label_str);
56 static void fill_label_uint64(field_info *fi, gchar *label_str);
57 static void fill_label_int64(field_info *fi, gchar *label_str);
58 static void fill_label_enumerated_uint(field_info *fi, gchar *label_str);
59 static void fill_label_enumerated_bitfield(field_info *fi, gchar *label_str);
60 static void fill_label_numeric_bitfield(field_info *fi, gchar *label_str);
61 static void fill_label_int(field_info *fi, gchar *label_str);
62 static void fill_label_enumerated_int(field_info *fi, gchar *label_str);
63
64 int hfinfo_bitwidth(header_field_info *hfinfo);
65 static char* hfinfo_uint_vals_format(header_field_info *hfinfo);
66 static char* hfinfo_uint_format(header_field_info *hfinfo);
67 static char* hfinfo_int_vals_format(header_field_info *hfinfo);
68 static char* hfinfo_int_format(header_field_info *hfinfo);
69
70 static gboolean check_for_protocol_or_field_id(GNode *node, gpointer data);
71
72 static proto_item*
73 proto_tree_add_node(proto_tree *tree, field_info *fi);
74
75 static field_info *
76 alloc_field_info(int hfindex, tvbuff_t *tvb, gint start, gint length);
77
78 static proto_item *
79 proto_tree_add_pi(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
80                 field_info **pfi);
81 static void
82 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap);
83
84 static void
85 proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb);
86 static void
87 proto_tree_set_uint64(field_info *fi, const guint8 *value_ptr, gboolean little_endian);
88 static void
89 proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start, gboolean little_endian);
90 static void
91 proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length);
92 static void
93 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length);
94 static void
95 proto_tree_set_time(field_info *fi, nstime_t *value_ptr);
96 static void
97 proto_tree_set_string(field_info *fi, const char* value);
98 static void
99 proto_tree_set_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
100 static void
101 proto_tree_set_ether(field_info *fi, const guint8* value);
102 static void
103 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start);
104 static void
105 proto_tree_set_ipxnet(field_info *fi, guint32 value);
106 static void
107 proto_tree_set_ipv4(field_info *fi, guint32 value);
108 static void
109 proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr);
110 static void
111 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start);
112 static void
113 proto_tree_set_boolean(field_info *fi, guint32 value);
114 static void
115 proto_tree_set_double(field_info *fi, double value);
116 static void
117 proto_tree_set_uint(field_info *fi, guint32 value);
118 static void
119 proto_tree_set_int(field_info *fi, gint32 value);
120
121 static int proto_register_field_init(header_field_info *hfinfo, int parent);
122
123 /* special-case header field used within proto.c */
124 int hf_text_only = 1;
125
126 /* Structure for information about a protocol */
127 typedef struct {
128         char    *name;          /* long description */
129         char    *short_name;    /* short description */
130         char    *filter_name;   /* name of this protocol in filters */
131         int     proto_id;       /* field ID for this protocol */
132         GList   *fields;        /* fields for this protocol */
133         GList   *last_field;    /* pointer to end of list of fields */
134         gboolean is_enabled;    /* TRUE if protocol is enabled */
135         gboolean can_disable;   /* TRUE if protocol can be disabled */
136 } protocol_t;
137
138 /* List of all protocols */
139 static GList *protocols;
140
141 /* Contains information about protocols and header fields. Used when
142  * dissectors register their data */
143 static GMemChunk *gmc_hfinfo = NULL;
144
145 /* Contains information about a field when a dissector calls
146  * proto_tree_add_item.  */
147 static GMemChunk *gmc_field_info = NULL;
148
149 /* String space for protocol and field items for the GUI */
150 static GMemChunk *gmc_item_labels = NULL;
151
152 /* List which stores protocols and fields that have been registered */
153 static GPtrArray *gpa_hfinfo = NULL;
154
155 /* Points to the first element of an array of Booleans, indexed by
156    a subtree item type; that array element is TRUE if subtrees of
157    an item of that type are to be expanded. */
158 gboolean        *tree_is_expanded;
159
160 /* Number of elements in that array. */
161 int             num_tree_types;
162
163 /* Is the parsing being done for a visible proto_tree or an invisible one?
164  * By setting this correctly, the proto_tree creation is sped up by not
165  * having to call vsnprintf and copy strings around.
166  */
167 gboolean proto_tree_is_visible = FALSE;
168
169 /* initialize data structures and register protocols and fields */
170 void
171 proto_init(const char *plugin_dir,void (register_all_protocols)(void),
172            void (register_all_protocol_handoffs)(void))
173 {
174         static hf_register_info hf[] = {
175                 { &hf_text_only,
176                 { "",   "", FT_NONE, BASE_NONE, NULL, 0x0,
177                         NULL, HFILL }},
178         };
179
180         if (gmc_hfinfo)
181                 g_mem_chunk_destroy(gmc_hfinfo);
182         if (gmc_field_info)
183                 g_mem_chunk_destroy(gmc_field_info);
184         if (gmc_item_labels)
185                 g_mem_chunk_destroy(gmc_item_labels);
186         if (gpa_hfinfo)
187                 g_ptr_array_free(gpa_hfinfo, TRUE);
188         if (tree_is_expanded != NULL)
189                 g_free(tree_is_expanded);
190
191         gmc_hfinfo = g_mem_chunk_new("gmc_hfinfo",
192                 sizeof(header_field_info), 50 * sizeof(header_field_info), G_ALLOC_ONLY);
193         gmc_field_info = g_mem_chunk_new("gmc_field_info",
194                 sizeof(struct field_info), 200 * sizeof(struct field_info),
195                 G_ALLOC_AND_FREE);
196         gmc_item_labels = g_mem_chunk_new("gmc_item_labels",
197                 ITEM_LABEL_LENGTH, 20 * ITEM_LABEL_LENGTH,
198                 G_ALLOC_AND_FREE);
199         gpa_hfinfo = g_ptr_array_new();
200
201         /* Allocate "tree_is_expanded", with one element for ETT_NONE,
202            and initialize that element to FALSE. */
203         tree_is_expanded = g_malloc(sizeof (gint));
204         tree_is_expanded[0] = FALSE;
205         num_tree_types = 1;
206
207         /* Initialize the ftype subsystem */
208         ftypes_initialize();
209
210         /* Have each built-in dissector register its protocols, fields,
211            dissector tables, and dissectors to be called through a
212            handle, and do whatever one-time initialization it needs to
213            do. */
214         register_all_protocols();
215
216 #ifdef HAVE_PLUGINS
217         /* Now scan for plugins and load all the ones we find, calling
218            their register routines to do the stuff described above. */
219         init_plugins(plugin_dir);
220 #endif
221
222         /* Now call the "handoff registration" routines of all built-in
223            dissectors; those routines register the dissector in other
224            dissectors' handoff tables, and fetch any dissector handles
225            they need. */
226         register_all_protocol_handoffs();
227
228 #ifdef HAVE_PLUGINS
229         /* Now do the same with plugins. */
230         register_all_plugin_handoffs();
231 #endif
232
233         /* Register one special-case FT_TEXT_ONLY field for use when
234            converting ethereal to new-style proto_tree. These fields
235            are merely strings on the GUI tree; they are not filterable */
236         proto_register_field_array(-1, hf, array_length(hf));
237
238         /* We've assigned all the subtree type values; allocate the array
239            for them, and zero it out. */
240         tree_is_expanded = g_malloc(num_tree_types*sizeof (gint *));
241         memset(tree_is_expanded, '\0', num_tree_types*sizeof (gint *));
242 }
243
244 void
245 proto_cleanup(void)
246 {
247         if (gmc_hfinfo)
248                 g_mem_chunk_destroy(gmc_hfinfo);
249         if (gmc_field_info)
250                 g_mem_chunk_destroy(gmc_field_info);
251         if (gmc_item_labels)
252                 g_mem_chunk_destroy(gmc_item_labels);
253         if (gpa_hfinfo)
254                 g_ptr_array_free(gpa_hfinfo, TRUE);
255
256         /* Cleanup the ftype subsystem */
257         ftypes_cleanup();
258 }
259
260 /* frees the resources that the dissection a proto_tree uses */
261 void
262 proto_tree_free(proto_tree *tree)
263 {
264         g_node_traverse((GNode*)tree, G_IN_ORDER, G_TRAVERSE_ALL, -1,
265                 proto_tree_free_node, NULL);
266         g_node_destroy((GNode*)tree);
267 }
268
269 /* We accept a void* instead of a field_info* to satisfy CLEANUP_POP */
270 static void
271 free_field_info(void *fi)
272 {
273         g_mem_chunk_free(gmc_field_info, (field_info*)fi);
274 }
275
276 static gboolean
277 proto_tree_free_node(GNode *node, gpointer data)
278 {
279         field_info *fi = (field_info*) (node->data);
280
281         if (fi != NULL) {
282                 if (fi->representation) {
283                         g_mem_chunk_free(gmc_item_labels, fi->representation);
284                 }
285                 fvalue_free(fi->value);
286                 free_field_info(fi);
287         }
288         return FALSE; /* FALSE = do not end traversal of GNode tree */
289 }       
290
291 /* Finds a record in the hf_info_records array by id. */
292 header_field_info*
293 proto_registrar_get_nth(int hfindex)
294 {
295         g_assert(hfindex >= 0 && (guint) hfindex < gpa_hfinfo->len);
296         return g_ptr_array_index(gpa_hfinfo, hfindex);
297 }
298
299
300 /* Add a text-only node, leaving it to our caller to fill the text in */
301 static proto_item *
302 proto_tree_add_text_node(proto_tree *tree, tvbuff_t *tvb, gint start, gint length)
303 {
304         proto_item      *pi;
305
306         pi = proto_tree_add_pi(tree, hf_text_only, tvb, start, length, NULL);
307         if (pi == NULL)
308                 return(NULL);
309
310         return pi;
311 }
312
313 /* Add a text-only node to the proto_tree */
314 proto_item *
315 proto_tree_add_text(proto_tree *tree, tvbuff_t *tvb, gint start, gint length,
316         const char *format, ...)
317 {
318         proto_item      *pi;
319         va_list         ap;
320
321         pi = proto_tree_add_text_node(tree, tvb, start, length);
322         if (pi == NULL)
323                 return(NULL);
324
325         va_start(ap, format);
326         proto_tree_set_representation(pi, format, ap);
327         va_end(ap);
328
329         return pi;
330 }
331
332 /* Add a text-only node to the proto_tree (va_list version) */
333 proto_item *
334 proto_tree_add_text_valist(proto_tree *tree, tvbuff_t *tvb, gint start, 
335         gint length, const char *format, va_list ap)
336 {
337         proto_item      *pi;
338
339         pi = proto_tree_add_text_node(tree, tvb, start, length);
340         if (pi == NULL)
341                 return(NULL);
342
343         proto_tree_set_representation(pi, format, ap);
344
345         return pi;
346 }
347
348 /* Add a text-only node for debugging purposes. The caller doesn't need
349  * to worry about tvbuff, start, or length. Debug message gets sent to
350  * STDOUT, too */
351 proto_item *
352 proto_tree_add_debug_text(proto_tree *tree, const char *format, ...)
353 {
354         proto_item      *pi;
355         va_list         ap;
356
357         pi = proto_tree_add_text_node(tree, NULL, 0, 0);
358         if (pi == NULL)
359                 return(NULL);
360
361         va_start(ap, format);
362         proto_tree_set_representation(pi, format, ap);
363         vprintf(format, ap);
364         va_end(ap);
365         printf("\n");
366
367         return pi;
368 }
369
370
371 static guint32
372 get_uint_value(tvbuff_t *tvb, gint offset, gint length, gboolean little_endian)
373 {
374         guint32 value;
375
376         switch (length) {
377
378         case 1:
379                 value = tvb_get_guint8(tvb, offset);
380                 break;
381
382         case 2:
383                 value = little_endian ? tvb_get_letohs(tvb, offset)
384                                       : tvb_get_ntohs(tvb, offset);
385                 break;
386
387         case 3:
388                 value = little_endian ? tvb_get_letoh24(tvb, offset)
389                                       : tvb_get_ntoh24(tvb, offset);
390                 break;
391
392         case 4:
393                 value = little_endian ? tvb_get_letohl(tvb, offset)
394                                       : tvb_get_ntohl(tvb, offset);
395                 break;
396
397         default:
398                 g_assert_not_reached();
399                 value = 0;
400                 break;
401         }
402         return value;
403 }
404
405 static gint32
406 get_int_value(tvbuff_t *tvb, gint offset, gint length, gboolean little_endian)
407 {
408         gint32 value;
409
410         switch (length) {
411
412         case 1:
413                 value = (gint8)tvb_get_guint8(tvb, offset);
414                 break;
415
416         case 2:
417                 value = (gint16) (little_endian ? tvb_get_letohs(tvb, offset)
418                                                 : tvb_get_ntohs(tvb, offset));
419                 break;
420
421         case 3:
422                 value = little_endian ? tvb_get_letoh24(tvb, offset)
423                                       : tvb_get_ntoh24(tvb, offset);
424                 if (value & 0x00800000) {
425                         /* Sign bit is set; sign-extend it. */
426                         value |= 0xFF000000;
427                 }
428                 break;
429
430         case 4:
431                 value = little_endian ? tvb_get_letohl(tvb, offset)
432                                       : tvb_get_ntohl(tvb, offset);
433                 break;
434
435         default:
436                 g_assert_not_reached();
437                 value = 0;
438                 break;
439         }
440         return value;
441 }
442
443 /* Add an item to a proto_tree, using the text label registered to that item;
444    the item is extracted from the tvbuff handed to it. */
445 proto_item *
446 proto_tree_add_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
447     gint start, gint length, gboolean little_endian)
448 {
449         field_info      *new_fi;
450         proto_item      *pi;
451         guint32         value, n;
452         char            *string;
453         int             found_length;
454
455         if (!tree)
456                 return(NULL);
457
458         new_fi = alloc_field_info(hfindex, tvb, start, length);
459
460         if (new_fi == NULL)
461                 return(NULL);
462
463         /* Register a cleanup function in case on of our tvbuff accesses
464          * throws an exception. We need to clean up new_fi. */
465         CLEANUP_PUSH(free_field_info, new_fi);
466
467         switch(new_fi->hfinfo->type) {
468                 case FT_NONE:
469                         /* no value to set for FT_NONE */
470                         break;
471
472                 case FT_PROTOCOL:
473                         proto_tree_set_protocol_tvb(new_fi, tvb);
474                         break;
475
476                 case FT_BYTES:
477                         proto_tree_set_bytes_tvb(new_fi, tvb, start, length);
478                         break;
479
480                 case FT_BOOLEAN:
481                         proto_tree_set_boolean(new_fi,
482                             get_uint_value(tvb, start, length, little_endian));
483                         break;
484
485                 /* XXX - make these just FT_UINT? */
486                 case FT_UINT8:
487                 case FT_UINT16:
488                 case FT_UINT24:
489                 case FT_UINT32:
490                         proto_tree_set_uint(new_fi,
491                             get_uint_value(tvb, start, length, little_endian));
492                         break;
493
494                 case FT_INT64:
495                 case FT_UINT64:
496                         g_assert(length == 8);
497                         proto_tree_set_uint64_tvb(new_fi, tvb, start, little_endian);
498                         break;
499
500                 /* XXX - make these just FT_INT? */
501                 case FT_INT8:
502                 case FT_INT16:
503                 case FT_INT24:
504                 case FT_INT32:
505                         proto_tree_set_int(new_fi,
506                             get_int_value(tvb, start, length, little_endian));
507                         break;
508
509                 case FT_IPv4:
510                         g_assert(length == 4);
511                         tvb_memcpy(tvb, (guint8 *)&value, start, 4);
512                         proto_tree_set_ipv4(new_fi, value);
513                         break;
514
515                 case FT_IPXNET:
516                         g_assert(length == 4);
517                         proto_tree_set_ipxnet(new_fi,
518                             get_uint_value(tvb, start, 4, FALSE));
519                         break;
520
521                 case FT_IPv6:
522                         g_assert(length == 16);
523                         proto_tree_set_ipv6_tvb(new_fi, tvb, start);
524                         break;
525
526                 case FT_ETHER:
527                         g_assert(length == 6);
528                         proto_tree_set_ether_tvb(new_fi, tvb, start);
529                         break;
530
531                 case FT_STRING:
532                         /* This g_strdup'ed memory is freed in proto_tree_free_node() */
533                         proto_tree_set_string_tvb(new_fi, tvb, start, length);
534                         break;
535
536                 case FT_STRINGZ:
537                         /* This g_strdup'ed memory is freed in proto_tree_free_node() */
538                         string = g_malloc(length);
539
540                         CLEANUP_PUSH(g_free, string);
541
542                         found_length = tvb_get_nstringz(tvb, start, length, string);
543                         if (found_length < 1) {
544                                 found_length = tvb_get_nstringz0(tvb, start, length, string);
545                         }
546
547                         CLEANUP_POP;
548
549                         proto_tree_set_string(new_fi, string);
550                         new_fi->length = found_length + 1;
551
552                         break;
553
554                 case FT_UINT_STRING:
555                         /* This g_strdup'ed memory is freed in proto_tree_free_node() */
556                         n = get_uint_value(tvb, start, length, little_endian);
557                         proto_tree_set_string_tvb(new_fi, tvb, start + length, n);
558
559                         /* Instead of calling proto_item_set_len(), since we don't yet
560                          * have a proto_item, we set the field_info's length ourselves. */
561                         new_fi->length = n + length;
562                         break;
563                 default:
564                         g_error("new_fi->hfinfo->type %d (%s) not handled\n",
565                                         new_fi->hfinfo->type,
566                                         ftype_name(new_fi->hfinfo->type));
567                         g_assert_not_reached();
568                         break;
569
570         }
571         CLEANUP_POP;
572
573         /* Don't add to proto_item to proto_tree until now so that any exceptions
574          * raised by a tvbuff access method doesn't leave junk in the proto_tree. */
575         pi = proto_tree_add_node(tree, new_fi);
576
577         return pi;
578 }
579
580 proto_item *
581 proto_tree_add_item_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb,
582     gint start, gint length, gboolean little_endian)
583 {
584         proto_item      *pi;
585         field_info      *fi;
586
587         pi = proto_tree_add_item(tree, hfindex, tvb, start, length, little_endian);
588         if (pi == NULL)
589                 return(NULL);
590
591         fi = (field_info*) (((GNode*)pi)->data);
592         fi->visible = FALSE;
593
594         return pi;
595 }
596
597
598 /* Add a FT_NONE to a proto_tree */
599 proto_item *
600 proto_tree_add_none_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
601                 gint length, const char *format, ...)
602 {
603         proto_item              *pi;
604         va_list                 ap;
605         header_field_info       *hfinfo;
606
607         if (!tree)
608                 return (NULL);
609
610         hfinfo = proto_registrar_get_nth(hfindex);
611         g_assert(hfinfo->type == FT_NONE);
612
613         pi = proto_tree_add_pi(tree, hfindex, tvb, start, length, NULL);
614
615         va_start(ap, format);
616         proto_tree_set_representation(pi, format, ap);
617         va_end(ap);
618
619         /* no value to set for FT_NONE */
620         return pi;
621 }
622
623         
624 static void
625 proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb)
626 {
627         fvalue_set(fi->value, tvb, TRUE);
628 }
629
630 /* Add a FT_PROTOCOL to a proto_tree */
631 proto_item *
632 proto_tree_add_protocol_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
633                 gint length, const char *format, ...)
634 {
635         proto_item              *pi;
636         va_list                 ap;
637         header_field_info       *hfinfo;
638         field_info              *new_fi;
639
640         if (!tree)
641                 return (NULL);
642
643         hfinfo = proto_registrar_get_nth(hfindex);
644         g_assert(hfinfo->type == FT_PROTOCOL);
645
646         pi = proto_tree_add_pi(tree, hfindex, tvb, start, length, &new_fi);
647
648         va_start(ap, format);
649         proto_tree_set_representation(pi, format, ap);
650         va_end(ap);
651
652         if (start == 0) {
653                 proto_tree_set_protocol_tvb(new_fi, tvb);
654         }
655         else {
656                 proto_tree_set_protocol_tvb(new_fi, NULL);
657         }
658         return pi;
659 }
660
661
662 /* Add a FT_BYTES to a proto_tree */
663 proto_item *
664 proto_tree_add_bytes(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
665                 gint length, const guint8 *start_ptr)
666 {
667         proto_item              *pi;
668         field_info              *new_fi;
669         header_field_info       *hfinfo;
670
671         if (!tree)
672                 return (NULL);
673
674         hfinfo = proto_registrar_get_nth(hfindex);
675         g_assert(hfinfo->type == FT_BYTES);
676
677         pi = proto_tree_add_pi(tree, hfindex, tvb, start, length, &new_fi);
678         proto_tree_set_bytes(new_fi, start_ptr, length);
679
680         return pi;
681 }
682
683 proto_item *
684 proto_tree_add_bytes_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
685                 gint length, const guint8 *start_ptr)
686 {
687         proto_item              *pi;
688         field_info              *fi;
689
690         pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length, start_ptr);
691         if (pi == NULL)
692                 return (NULL);
693
694         fi = (field_info*) (((GNode*)pi)->data);
695         fi->visible = FALSE;
696
697         return pi;
698 }
699
700 proto_item *
701 proto_tree_add_bytes_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
702                 gint length, const guint8 *start_ptr, const char *format, ...)
703 {
704         proto_item              *pi;
705         va_list                 ap;
706
707         pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length, start_ptr);
708         if (pi == NULL)
709                 return (NULL);
710
711         va_start(ap, format);
712         proto_tree_set_representation(pi, format, ap);
713         va_end(ap);
714
715         return pi;
716 }
717
718 static void
719 proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length)
720 {
721         GByteArray              *bytes;
722
723         bytes = g_byte_array_new();
724         if (length > 0) {
725                 g_byte_array_append(bytes, start_ptr, length);
726         }
727         fvalue_set(fi->value, bytes, TRUE);
728 }
729
730
731 static void
732 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length)
733 {
734         proto_tree_set_bytes(fi, tvb_get_ptr(tvb, offset, length), length);
735 }
736
737 /* Add a FT_*TIME to a proto_tree */
738 proto_item *
739 proto_tree_add_time(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
740                 nstime_t *value_ptr)
741 {
742         proto_item              *pi;
743         field_info              *new_fi;
744         header_field_info       *hfinfo;
745
746         if (!tree)
747                 return (NULL);
748
749         hfinfo = proto_registrar_get_nth(hfindex);
750         g_assert(hfinfo->type == FT_ABSOLUTE_TIME ||
751                                 hfinfo->type == FT_RELATIVE_TIME);
752
753         pi = proto_tree_add_pi(tree, hfindex, tvb, start, length, &new_fi);
754         proto_tree_set_time(new_fi, value_ptr);
755
756         return pi;
757 }
758
759 proto_item *
760 proto_tree_add_time_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
761                 nstime_t *value_ptr)
762 {
763         proto_item              *pi;
764         field_info              *fi;
765
766         pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
767         if (pi == NULL)
768                 return (NULL);
769
770         fi = (field_info*) (((GNode*)pi)->data);
771         fi->visible = FALSE;
772
773         return pi;
774 }
775
776 proto_item *
777 proto_tree_add_time_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
778                 nstime_t *value_ptr, const char *format, ...)
779 {
780         proto_item              *pi;
781         va_list                 ap;
782
783         pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
784         if (pi == NULL)
785                 return (NULL);
786
787         va_start(ap, format);
788         proto_tree_set_representation(pi, format, ap);
789         va_end(ap);
790
791         return pi;
792 }
793
794 /* Set the FT_*TIME value */
795 static void
796 proto_tree_set_time(field_info *fi, nstime_t *value_ptr)
797 {
798         fvalue_set(fi->value, value_ptr, FALSE);
799 }
800
801 /* Add a FT_IPXNET to a proto_tree */
802 proto_item *
803 proto_tree_add_ipxnet(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
804                 guint32 value)
805 {
806         proto_item              *pi;
807         field_info              *new_fi;
808         header_field_info       *hfinfo;
809
810         if (!tree)
811                 return (NULL);
812
813         hfinfo = proto_registrar_get_nth(hfindex);
814         g_assert(hfinfo->type == FT_IPXNET);
815
816         pi = proto_tree_add_pi(tree, hfindex, tvb, start, length, &new_fi);
817         proto_tree_set_ipxnet(new_fi, value);
818
819         return pi;
820 }
821
822 proto_item *
823 proto_tree_add_ipxnet_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
824                 guint32 value)
825 {
826         proto_item              *pi;
827         field_info              *fi;
828
829         pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
830         if (pi == NULL)
831                 return (NULL);
832
833         fi = (field_info*) (((GNode*)pi)->data);
834         fi->visible = FALSE;
835
836         return pi;
837 }
838
839 proto_item *
840 proto_tree_add_ipxnet_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
841                 guint32 value, const char *format, ...)
842 {
843         proto_item              *pi;
844         va_list                 ap;
845
846         pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
847         if (pi == NULL)
848                 return (NULL);
849
850         va_start(ap, format);
851         proto_tree_set_representation(pi, format, ap);
852         va_end(ap);
853
854         return pi;
855 }
856
857 /* Set the FT_IPXNET value */
858 static void
859 proto_tree_set_ipxnet(field_info *fi, guint32 value)
860 {
861         fvalue_set_integer(fi->value, value);
862 }
863
864 /* Add a FT_IPv4 to a proto_tree */
865 proto_item *
866 proto_tree_add_ipv4(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
867                 guint32 value)
868 {
869         proto_item              *pi;
870         field_info              *new_fi;
871         header_field_info       *hfinfo;
872
873         if (!tree)
874                 return (NULL);
875
876         hfinfo = proto_registrar_get_nth(hfindex);
877         g_assert(hfinfo->type == FT_IPv4);
878
879         pi = proto_tree_add_pi(tree, hfindex, tvb, start, length, &new_fi);
880         proto_tree_set_ipv4(new_fi, value);
881
882         return pi;
883 }
884
885 proto_item *
886 proto_tree_add_ipv4_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
887                 guint32 value)
888 {
889         proto_item              *pi;
890         field_info              *fi;
891
892         pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
893         if (pi == NULL)
894                 return (NULL);
895
896         fi = (field_info*) (((GNode*)pi)->data);
897         fi->visible = FALSE;
898
899         return pi;
900 }
901
902 proto_item *
903 proto_tree_add_ipv4_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
904                 guint32 value, const char *format, ...)
905 {
906         proto_item              *pi;
907         va_list                 ap;
908
909         pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
910         if (pi == NULL)
911                 return (NULL);
912
913         va_start(ap, format);
914         proto_tree_set_representation(pi, format, ap);
915         va_end(ap);
916
917         return pi;
918 }
919
920 /* Set the FT_IPv4 value */
921 static void
922 proto_tree_set_ipv4(field_info *fi, guint32 value)
923 {
924         fvalue_set_integer(fi->value, value);
925 }
926
927 /* Add a FT_IPv6 to a proto_tree */
928 proto_item *
929 proto_tree_add_ipv6(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
930                 const guint8* value_ptr)
931 {
932         proto_item              *pi;
933         field_info              *new_fi;
934         header_field_info       *hfinfo;
935
936         if (!tree)
937                 return (NULL);
938
939         hfinfo = proto_registrar_get_nth(hfindex);
940         g_assert(hfinfo->type == FT_IPv6);
941
942         pi = proto_tree_add_pi(tree, hfindex, tvb, start, length, &new_fi);
943         proto_tree_set_ipv6(new_fi, value_ptr);
944
945         return pi;
946 }
947
948 proto_item *
949 proto_tree_add_ipv6_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
950                 const guint8* value_ptr)
951 {
952         proto_item              *pi;
953         field_info              *fi;
954
955         pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
956         if (pi == NULL)
957                 return (NULL);
958
959         fi = (field_info*) (((GNode*)pi)->data);
960         fi->visible = FALSE;
961
962         return pi;
963 }
964
965 proto_item *
966 proto_tree_add_ipv6_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
967                 const guint8* value_ptr, const char *format, ...)
968 {
969         proto_item              *pi;
970         va_list                 ap;
971
972         pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
973         if (pi == NULL)
974                 return (NULL);
975
976         va_start(ap, format);
977         proto_tree_set_representation(pi, format, ap);
978         va_end(ap);
979
980         return pi;
981 }
982
983 /* Set the FT_IPv6 value */
984 static void
985 proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr)
986 {
987         fvalue_set(fi->value, (gpointer) value_ptr, FALSE);
988 }
989
990 static void
991 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start)
992 {
993         proto_tree_set_ipv6(fi, tvb_get_ptr(tvb, start, 16));
994 }
995
996 static void
997 proto_tree_set_uint64(field_info *fi, const guint8 *value_ptr, gboolean little_endian)
998 {
999         if(little_endian){
1000                 unsigned char buffer[8];
1001                 int i;
1002
1003                 for(i=0;i<8;i++){
1004                         buffer[i]=value_ptr[7-i];
1005                 }
1006                 fvalue_set(fi->value, (gpointer)buffer, FALSE);
1007         } else {
1008                 fvalue_set(fi->value, (gpointer)value_ptr, FALSE);
1009         }
1010 }
1011
1012 static void
1013 proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start, gboolean little_endian)
1014 {
1015         proto_tree_set_uint64(fi, tvb_get_ptr(tvb, start, 8), little_endian);
1016 }
1017
1018 /* Add a FT_STRING to a proto_tree */
1019 proto_item *
1020 proto_tree_add_string(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1021                 gint length, const char* value)
1022 {
1023         proto_item              *pi;
1024         field_info              *new_fi;
1025         header_field_info       *hfinfo;
1026
1027         if (!tree)
1028                 return (NULL);
1029
1030         hfinfo = proto_registrar_get_nth(hfindex);
1031         g_assert(hfinfo->type == FT_STRING);
1032
1033         pi = proto_tree_add_pi(tree, hfindex, tvb, start, length, &new_fi);
1034         proto_tree_set_string(new_fi, value);
1035
1036         return pi;
1037 }
1038
1039 proto_item *
1040 proto_tree_add_string_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1041                 gint length, const char* value)
1042 {
1043         proto_item              *pi;
1044         field_info              *fi;
1045
1046         pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
1047         if (pi == NULL)
1048                 return (NULL);
1049
1050         fi = (field_info*) (((GNode*)pi)->data);
1051         fi->visible = FALSE;
1052
1053         return pi;
1054 }
1055
1056 proto_item *
1057 proto_tree_add_string_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1058                 gint length, const char* value, const char *format, ...)
1059 {
1060         proto_item              *pi;
1061         va_list                 ap;
1062
1063         pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
1064         if (pi == NULL)
1065                 return (NULL);
1066
1067         va_start(ap, format);
1068         proto_tree_set_representation(pi, format, ap);
1069         va_end(ap);
1070
1071         return pi;
1072 }
1073
1074 /* Set the FT_STRING value */
1075 static void
1076 proto_tree_set_string(field_info *fi, const char* value)
1077 {
1078         fvalue_set(fi->value, (gpointer) value, FALSE);
1079 }
1080
1081 static void
1082 proto_tree_set_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
1083 {
1084         gchar   *string;
1085
1086         /* This memory is freed in proto_tree_free_node() */
1087         string = g_malloc(length + 1);
1088         tvb_memcpy(tvb, string, start, length);
1089         string[length] = '\0';
1090         fvalue_set(fi->value, string, TRUE);
1091 }
1092
1093 /* Add a FT_ETHER to a proto_tree */
1094 proto_item *
1095 proto_tree_add_ether(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1096                 const guint8* value)
1097 {
1098         proto_item              *pi;
1099         field_info              *new_fi;
1100         header_field_info       *hfinfo;
1101
1102         if (!tree)
1103                 return (NULL);
1104
1105         hfinfo = proto_registrar_get_nth(hfindex);
1106         g_assert(hfinfo->type == FT_ETHER);
1107
1108         pi = proto_tree_add_pi(tree, hfindex, tvb, start, length, &new_fi);
1109         proto_tree_set_ether(new_fi, value);
1110
1111         return pi;
1112 }
1113
1114 proto_item *
1115 proto_tree_add_ether_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1116                 const guint8* value)
1117 {
1118         proto_item              *pi;
1119         field_info              *fi;
1120
1121         pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
1122         if (pi == NULL)
1123                 return (NULL);
1124
1125         fi = (field_info*) (((GNode*)pi)->data);
1126         fi->visible = FALSE;
1127
1128         return pi;
1129 }
1130
1131 proto_item *
1132 proto_tree_add_ether_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1133                 const guint8* value, const char *format, ...)
1134 {
1135         proto_item              *pi;
1136         va_list                 ap;
1137
1138         pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
1139         if (pi == NULL)
1140                 return (NULL);
1141
1142         va_start(ap, format);
1143         proto_tree_set_representation(pi, format, ap);
1144         va_end(ap);
1145
1146         return pi;
1147 }
1148
1149 /* Set the FT_ETHER value */
1150 static void
1151 proto_tree_set_ether(field_info *fi, const guint8* value)
1152 {
1153         fvalue_set(fi->value, (gpointer) value, FALSE);
1154 }
1155
1156 static void
1157 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start)
1158 {
1159         proto_tree_set_ether(fi, tvb_get_ptr(tvb, start, 6));
1160 }
1161
1162 /* Add a FT_BOOLEAN to a proto_tree */
1163 proto_item *
1164 proto_tree_add_boolean(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1165                 guint32 value)
1166 {
1167         proto_item              *pi;
1168         field_info              *new_fi;
1169         header_field_info       *hfinfo;
1170
1171         if (!tree)
1172                 return (NULL);
1173
1174         hfinfo = proto_registrar_get_nth(hfindex);
1175         g_assert(hfinfo->type == FT_BOOLEAN);
1176
1177         pi = proto_tree_add_pi(tree, hfindex, tvb, start, length, &new_fi);
1178         proto_tree_set_boolean(new_fi, value);
1179
1180         return pi;
1181 }
1182
1183 proto_item *
1184 proto_tree_add_boolean_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1185                 guint32 value)
1186 {
1187         proto_item              *pi;
1188         field_info              *fi;
1189
1190         pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
1191         if (pi == NULL)
1192                 return (NULL);
1193
1194         fi = (field_info*) (((GNode*)pi)->data);
1195         fi->visible = FALSE;
1196
1197         return pi;
1198 }
1199
1200 proto_item *
1201 proto_tree_add_boolean_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1202                 guint32 value, const char *format, ...)
1203 {
1204         proto_item              *pi;
1205         va_list                 ap;
1206
1207         pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
1208         if (pi == NULL)
1209                 return (NULL);
1210
1211         va_start(ap, format);
1212         proto_tree_set_representation(pi, format, ap);
1213         va_end(ap);
1214
1215         return pi;
1216 }
1217
1218 /* Set the FT_BOOLEAN value */
1219 static void
1220 proto_tree_set_boolean(field_info *fi, guint32 value)
1221 {
1222         proto_tree_set_uint(fi, value);
1223 }
1224
1225 /* Add a FT_DOUBLE to a proto_tree */
1226 proto_item *
1227 proto_tree_add_double(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1228                 double value)
1229 {
1230         proto_item              *pi;
1231         field_info              *new_fi;
1232         header_field_info       *hfinfo;
1233
1234         if (!tree)
1235                 return (NULL);
1236
1237         hfinfo = proto_registrar_get_nth(hfindex);
1238         g_assert(hfinfo->type == FT_DOUBLE);
1239
1240         pi = proto_tree_add_pi(tree, hfindex, tvb, start, length, &new_fi);
1241         proto_tree_set_double(new_fi, value);
1242
1243         return pi;
1244 }
1245
1246 proto_item *
1247 proto_tree_add_double_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1248                 double value)
1249 {
1250         proto_item              *pi;
1251         field_info              *fi;
1252
1253         pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
1254         if (pi == NULL)
1255                 return (NULL);
1256
1257         fi = (field_info*) (((GNode*)pi)->data);
1258         fi->visible = FALSE;
1259
1260         return pi;
1261 }
1262
1263 proto_item *
1264 proto_tree_add_double_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1265                 double value, const char *format, ...)
1266 {
1267         proto_item              *pi;
1268         va_list                 ap;
1269
1270         pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
1271         if (pi == NULL)
1272                 return (NULL);
1273
1274         va_start(ap, format);
1275         proto_tree_set_representation(pi, format, ap);
1276         va_end(ap);
1277
1278         return pi;
1279 }
1280
1281 /* Set the FT_DOUBLE value */
1282 static void
1283 proto_tree_set_double(field_info *fi, double value)
1284 {
1285         fvalue_set_floating(fi->value, value);
1286 }
1287
1288 /* Add any FT_UINT* to a proto_tree */
1289 proto_item *
1290 proto_tree_add_uint(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1291                 guint32 value)
1292 {
1293         proto_item              *pi = NULL;
1294         field_info              *new_fi;
1295         header_field_info       *hfinfo;
1296
1297         if (!tree)
1298                 return (NULL);
1299
1300         hfinfo = proto_registrar_get_nth(hfindex);
1301         switch(hfinfo->type) {
1302                 case FT_UINT8:
1303                 case FT_UINT16:
1304                 case FT_UINT24:
1305                 case FT_UINT32:
1306                         pi = proto_tree_add_pi(tree, hfindex, tvb, start, length,
1307                                         &new_fi);
1308                         proto_tree_set_uint(new_fi, value);
1309                         break;
1310
1311                 default:
1312                         g_assert_not_reached();
1313         }
1314
1315         return pi;
1316 }
1317
1318 proto_item *
1319 proto_tree_add_uint_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1320                 guint32 value)
1321 {
1322         proto_item              *pi;
1323         field_info              *fi;
1324
1325         pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
1326         if (pi == NULL)
1327                 return (NULL);
1328
1329         fi = (field_info*) (((GNode*)pi)->data);
1330         fi->visible = FALSE;
1331
1332         return pi;
1333 }
1334
1335 proto_item *
1336 proto_tree_add_uint_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1337                 guint32 value, const char *format, ...)
1338 {
1339         proto_item              *pi;
1340         va_list                 ap;
1341
1342         pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
1343         if (pi == NULL)
1344                 return (NULL);
1345
1346         va_start(ap, format);
1347         proto_tree_set_representation(pi, format, ap);
1348         va_end(ap);
1349
1350         return pi;
1351 }
1352
1353 /* Set the FT_UINT* value */
1354 static void
1355 proto_tree_set_uint(field_info *fi, guint32 value)
1356 {
1357         header_field_info       *hfinfo;
1358         guint32                 integer;
1359
1360         hfinfo = fi->hfinfo;
1361         integer = value;
1362
1363         if (hfinfo->bitmask) {
1364                 /* Mask out irrelevant portions */
1365                 integer &= hfinfo->bitmask;
1366
1367                 /* Shift bits */
1368                 if (hfinfo->bitshift > 0) {
1369                         integer >>= hfinfo->bitshift;
1370                 }
1371         }
1372         fvalue_set_integer(fi->value, integer);
1373 }
1374
1375 /* Add any FT_INT* to a proto_tree */
1376 proto_item *
1377 proto_tree_add_int(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1378                 gint32 value)
1379 {
1380         proto_item              *pi = NULL;
1381         field_info              *new_fi;
1382         header_field_info       *hfinfo;
1383
1384         if (!tree)
1385                 return (NULL);
1386
1387         hfinfo = proto_registrar_get_nth(hfindex);
1388         switch(hfinfo->type) {
1389                 case FT_INT8:
1390                 case FT_INT16:
1391                 case FT_INT24:
1392                 case FT_INT32:
1393                         pi = proto_tree_add_pi(tree, hfindex, tvb, start, length,
1394                                         &new_fi);
1395                         proto_tree_set_int(new_fi, value);
1396                         break;
1397
1398                 default:
1399                         g_assert_not_reached();
1400         }
1401
1402         return pi;
1403 }
1404
1405 proto_item *
1406 proto_tree_add_int_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1407                 gint32 value)
1408 {
1409         proto_item              *pi;
1410         field_info              *fi;
1411
1412         pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
1413         if (pi == NULL)
1414                 return (NULL);
1415
1416         fi = (field_info*) (((GNode*)pi)->data);
1417         fi->visible = FALSE;
1418
1419         return pi;
1420 }
1421
1422 proto_item *
1423 proto_tree_add_int_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1424                 gint32 value, const char *format, ...)
1425 {
1426         proto_item              *pi = NULL;
1427         va_list                 ap;
1428
1429         pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
1430         if (pi == NULL)
1431                 return (NULL);
1432
1433         va_start(ap, format);
1434         proto_tree_set_representation(pi, format, ap);
1435         va_end(ap);
1436
1437         return pi;
1438 }
1439
1440 /* Set the FT_INT* value */
1441 static void
1442 proto_tree_set_int(field_info *fi, gint32 value)
1443 {
1444         header_field_info       *hfinfo;
1445         guint32                 integer;
1446
1447         hfinfo = fi->hfinfo;
1448         integer = (guint32) value;
1449
1450         if (hfinfo->bitmask) {
1451                 /* Mask out irrelevant portions */
1452                 integer &= hfinfo->bitmask;
1453
1454                 /* Shift bits */
1455                 if (hfinfo->bitshift > 0) {
1456                         integer >>= hfinfo->bitshift;
1457                 }
1458         }
1459         fvalue_set_integer(fi->value, integer);
1460 }
1461
1462
1463 /* Add a field_info struct to the proto_tree, encapsulating it in a GNode (proto_item) */
1464 static proto_item *
1465 proto_tree_add_node(proto_tree *tree, field_info *fi)
1466 {
1467         proto_item *pi;
1468
1469         pi = (proto_item*) g_node_new(fi);
1470         g_node_append((GNode*)tree, (GNode*)pi);
1471
1472         return pi;
1473 }
1474
1475
1476 /* Generic way to allocate field_info and add to proto_tree.
1477  * Sets *pfi to address of newly-allocated field_info struct, if pfi is non-NULL. */
1478 static proto_item *
1479 proto_tree_add_pi(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1480                 field_info **pfi)
1481 {
1482         proto_item      *pi;
1483         field_info      *fi;
1484
1485         if (!tree)
1486                 return(NULL);
1487
1488         fi = alloc_field_info(hfindex, tvb, start, length);
1489         pi = proto_tree_add_node(tree, fi);
1490
1491         if (pfi) {
1492                 *pfi = fi;
1493         }
1494
1495         return pi;
1496 }
1497
1498 static field_info *
1499 alloc_field_info(int hfindex, tvbuff_t *tvb, gint start, gint length)
1500 {
1501         field_info      *fi;
1502
1503         fi = g_mem_chunk_alloc(gmc_field_info);
1504
1505         g_assert(hfindex >= 0 && (guint) hfindex < gpa_hfinfo->len);
1506
1507         /*
1508          * We only allow a null tvbuff if the item has a zero length,
1509          * i.e. if there's no data backing it.
1510          */
1511         g_assert(tvb != NULL || length == 0);
1512         fi->hfinfo = proto_registrar_get_nth(hfindex);
1513         g_assert(fi->hfinfo != NULL);
1514         fi->start = start;
1515         if (tvb) {
1516                 fi->start += tvb_raw_offset(tvb);
1517         }
1518         fi->length = length;
1519         fi->tree_type = ETT_NONE;
1520         fi->visible = proto_tree_is_visible;
1521         fi->representation = NULL;
1522
1523         fi->value = fvalue_new(fi->hfinfo->type);
1524
1525         /* add the data source name */
1526         if (tvb) {
1527                 fi->ds_name = tvb_get_name(tvb);
1528         } else {
1529                 fi->ds_name = NULL;
1530         }
1531
1532         return fi;
1533 }
1534
1535 /* Set representation of a proto_tree entry, if the protocol tree is to
1536    be visible. */
1537 static void
1538 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap)
1539 {
1540         field_info *fi = (field_info*) (((GNode*)pi)->data);
1541
1542         if (fi->visible) {
1543                 fi->representation = g_mem_chunk_alloc(gmc_item_labels);
1544                 vsnprintf(fi->representation, ITEM_LABEL_LENGTH, format, ap);
1545         }
1546 }
1547
1548 /* Set text of proto_item after having already been created. */
1549 void
1550 proto_item_set_text(proto_item *pi, const char *format, ...)
1551 {
1552         field_info *fi = NULL;
1553         va_list ap;
1554
1555         if (pi==NULL) {
1556                 return;
1557         }
1558
1559         fi = (field_info *)(((GNode*)pi)->data);
1560
1561         if (fi->representation)
1562                 g_mem_chunk_free(gmc_item_labels, fi->representation);
1563
1564         va_start(ap, format);
1565         proto_tree_set_representation(pi, format, ap);
1566         va_end(ap);
1567 }
1568
1569 /* Append to text of proto_item after having already been created. */
1570 void
1571 proto_item_append_text(proto_item *pi, const char *format, ...)
1572 {
1573         field_info *fi = NULL;
1574         size_t curlen;
1575         va_list ap;
1576
1577         if (pi==NULL) {
1578                 return;
1579         }
1580
1581         fi = (field_info*) (((GNode*)pi)->data);
1582
1583         if (fi->visible) {
1584                 va_start(ap, format);
1585                 /*
1586                  * XXX - this will blow up if we haven't already set
1587                  * "fi->representation"; that seems OK to me - you
1588                  * can't append to something that doesn't exist - but
1589                  * there might be cases where that's not convenient.
1590                  */
1591                 curlen = strlen(fi->representation);
1592                 if (ITEM_LABEL_LENGTH > curlen)
1593                         vsnprintf(fi->representation + curlen,
1594                             ITEM_LABEL_LENGTH - curlen, format, ap);
1595                 va_end(ap);
1596         }
1597 }
1598
1599 void
1600 proto_item_set_len(proto_item *pi, gint length)
1601 {
1602         field_info *fi;
1603         
1604         if (pi == NULL)
1605                 return;
1606         fi = (field_info*) (((GNode*)pi)->data);
1607         fi->length = length;
1608 }
1609
1610 int
1611 proto_item_get_len(proto_item *pi)
1612 {
1613         field_info *fi = (field_info*) (((GNode*)pi)->data);
1614         return fi->length;
1615 }
1616
1617 proto_tree*
1618 proto_tree_create_root(void)
1619 {
1620         return (proto_tree*) g_node_new(NULL);
1621 }
1622
1623 proto_tree*
1624 proto_item_add_subtree(proto_item *pi,  gint idx) {
1625         field_info *fi;
1626
1627         if (!pi)
1628                 return(NULL);
1629
1630         fi = (field_info*) (((GNode*)pi)->data);
1631         g_assert(idx >= 0 && idx < num_tree_types);
1632         fi->tree_type = idx;
1633         return (proto_tree*) pi;
1634 }
1635
1636 static gint
1637 proto_compare_name(gconstpointer p1_arg, gconstpointer p2_arg)
1638 {
1639         const protocol_t *p1 = p1_arg;
1640         const protocol_t *p2 = p2_arg;
1641
1642         return g_strcasecmp(p1->short_name, p2->short_name);
1643 }
1644
1645 int
1646 proto_register_protocol(char *name, char *short_name, char *filter_name)
1647 {
1648         protocol_t *protocol;
1649         header_field_info *hfinfo;
1650         int proto_id;
1651
1652         /* Add this protocol to the list of known protocols; the list
1653            is sorted by protocol short name. */
1654         protocol = g_malloc(sizeof (protocol_t));
1655         protocol->name = name;
1656         protocol->short_name = short_name;
1657         protocol->filter_name = filter_name;
1658         protocol->fields = NULL;
1659         protocol->is_enabled = TRUE; /* protocol is enabled by default */
1660         protocol->can_disable = TRUE;
1661         protocols = g_list_insert_sorted(protocols, protocol,
1662             proto_compare_name);
1663
1664         /* Here we do allocate a new header_field_info struct */
1665         hfinfo = g_mem_chunk_alloc(gmc_hfinfo);
1666         hfinfo->name = name;
1667         hfinfo->abbrev = filter_name;
1668         hfinfo->type = FT_PROTOCOL;
1669         hfinfo->strings = NULL;
1670         hfinfo->bitmask = 0;
1671         hfinfo->bitshift = 0;
1672         hfinfo->blurb = "";
1673         hfinfo->parent = -1; /* this field differentiates protos and fields */
1674
1675         proto_id = proto_register_field_init(hfinfo, hfinfo->parent);
1676         protocol->proto_id = proto_id;
1677         return proto_id;
1678 }
1679
1680 /*
1681  * Routines to use to iterate over the protocols.
1682  * The argument passed to the iterator routines is an opaque cookie to
1683  * their callers; it's the GList pointer for the current element in
1684  * the list.
1685  * The ID of the protocol is returned, or -1 if there is no protocol.
1686  */
1687 int
1688 proto_get_first_protocol(void **cookie)
1689 {
1690         protocol_t *protocol;
1691
1692         if (protocols == NULL)
1693                 return -1;
1694         *cookie = protocols;
1695         protocol = protocols->data;
1696         return protocol->proto_id;
1697 }
1698
1699 int
1700 proto_get_next_protocol(void **cookie)
1701 {
1702         GList *list_item = *cookie;
1703         protocol_t *protocol;
1704
1705         list_item = g_list_next(list_item);
1706         if (list_item == NULL)
1707                 return -1;
1708         *cookie = list_item;
1709         protocol = list_item->data;
1710         return protocol->proto_id;
1711 }
1712
1713 /*
1714  * Find the protocol list entry for a protocol given its field ID.
1715  */
1716 static gint
1717 compare_proto_id(gconstpointer proto_arg, gconstpointer id_arg)
1718 {
1719         const protocol_t *protocol = proto_arg;
1720         const int *id_ptr = id_arg;
1721
1722         return (protocol->proto_id == *id_ptr) ? 0 : 1;
1723 }
1724
1725 static protocol_t *
1726 find_protocol_by_id(int proto_id)
1727 {
1728         GList *list_entry;
1729         
1730         list_entry = g_list_find_custom(protocols, &proto_id, compare_proto_id);
1731         if (list_entry == NULL)
1732                 return NULL;
1733         return list_entry->data;
1734 }
1735
1736 static gint compare_filter_name(gconstpointer proto_arg, 
1737                                 gconstpointer filter_name)
1738 {
1739   const protocol_t *protocol = proto_arg;
1740   const gchar* f_name = filter_name;
1741   return (strcmp(protocol->filter_name, f_name));
1742 }
1743
1744 int proto_get_id_by_filter_name(gchar* filter_name)
1745 {
1746   GList *list_entry;
1747   protocol_t *protocol;
1748   list_entry = g_list_find_custom(protocols,filter_name,compare_filter_name); 
1749   if(list_entry == NULL)
1750     return -1;
1751   protocol = list_entry->data;
1752   return(protocol->proto_id);
1753 }
1754
1755 char *
1756 proto_get_protocol_name(int proto_id)
1757 {
1758         protocol_t *protocol;
1759
1760         protocol = find_protocol_by_id(proto_id);
1761         return protocol->name;
1762 }
1763
1764 char *
1765 proto_get_protocol_short_name(int proto_id)
1766 {
1767         protocol_t *protocol;
1768
1769         if (proto_id == -1)
1770                 return "(none)";
1771         protocol = find_protocol_by_id(proto_id);
1772         return protocol->short_name;
1773 }
1774
1775 char *
1776 proto_get_protocol_filter_name(int proto_id)
1777 {
1778         protocol_t *protocol;
1779
1780         protocol = find_protocol_by_id(proto_id);
1781         return protocol->filter_name;
1782 }
1783
1784 gboolean
1785 proto_is_protocol_enabled(int proto_id)
1786 {
1787         protocol_t *protocol;
1788
1789         protocol = find_protocol_by_id(proto_id);
1790         return protocol->is_enabled;
1791 }
1792
1793 gboolean
1794 proto_can_disable_protocol(int proto_id)
1795 {
1796         protocol_t *protocol;
1797
1798         protocol = find_protocol_by_id(proto_id);
1799         return protocol->can_disable;
1800 }
1801
1802 void 
1803 proto_set_decoding(int proto_id, gboolean enabled)
1804 {
1805         protocol_t *protocol;
1806
1807         protocol = find_protocol_by_id(proto_id);
1808         g_assert(enabled || protocol->can_disable);
1809         protocol->is_enabled = enabled;
1810 }
1811
1812 void 
1813 proto_set_cant_disable(int proto_id)
1814 {
1815         protocol_t *protocol;
1816
1817         protocol = find_protocol_by_id(proto_id);
1818         protocol->can_disable = FALSE;
1819 }
1820
1821 /* for use with static arrays only, since we don't allocate our own copies
1822 of the header_field_info struct contained withing the hf_register_info struct */
1823 void
1824 proto_register_field_array(int parent, hf_register_info *hf, int num_records)
1825 {
1826         int                     field_id, i;
1827         hf_register_info        *ptr = hf;
1828         protocol_t              *proto;
1829
1830         proto = find_protocol_by_id(parent);
1831         for (i = 0; i < num_records; i++, ptr++) {
1832                 if (proto != NULL) {
1833                         if (proto->fields == NULL) {
1834                                 proto->fields = g_list_append(NULL, ptr);
1835                                 proto->last_field = proto->fields;
1836                         } else {
1837                                 proto->last_field =
1838                                     g_list_append(proto->last_field, ptr)->next;
1839                         }
1840                 }
1841                 field_id = proto_register_field_init(&ptr->hfinfo, parent);
1842                 *ptr->p_id = field_id;
1843         }
1844 }
1845
1846 static int
1847 proto_register_field_init(header_field_info *hfinfo, int parent)
1848 {
1849         /* These types of fields are allowed to have value_strings or true_false_strings */
1850         g_assert((hfinfo->strings == NULL) || (
1851                         (hfinfo->type == FT_UINT8) ||
1852                         (hfinfo->type == FT_UINT16) ||
1853                         (hfinfo->type == FT_UINT24) ||
1854                         (hfinfo->type == FT_UINT32) ||
1855                         (hfinfo->type == FT_INT8) ||
1856                         (hfinfo->type == FT_INT16) ||
1857                         (hfinfo->type == FT_INT24) ||
1858                         (hfinfo->type == FT_INT32) ||
1859                         (hfinfo->type == FT_BOOLEAN) ));
1860
1861         /* Require integral types to have a number base */
1862         switch (hfinfo->type) {
1863
1864         case FT_UINT8:
1865         case FT_UINT16:
1866         case FT_UINT24:
1867         case FT_UINT32:
1868         case FT_INT8:
1869         case FT_INT16:
1870         case FT_INT24:
1871         case FT_INT32:
1872                 g_assert(hfinfo->display != BASE_NONE);
1873                 break;
1874
1875         default:
1876                 break;
1877         }
1878         /* if this is a bitfield, compure bitshift */
1879         if (hfinfo->bitmask) {
1880                 while ((hfinfo->bitmask & (1 << hfinfo->bitshift)) == 0)
1881                         hfinfo->bitshift++;
1882         }
1883
1884         hfinfo->parent = parent;
1885         hfinfo->same_name_next = NULL;
1886         hfinfo->same_name_prev = NULL;
1887
1888         /* if we always add and never delete, then id == len - 1 is correct */
1889         g_ptr_array_add(gpa_hfinfo, hfinfo);
1890         hfinfo->id = gpa_hfinfo->len - 1;
1891         return hfinfo->id;
1892 }
1893
1894 void
1895 proto_register_subtree_array(gint **indices, int num_indices)
1896 {
1897         int     i;
1898         gint    **ptr = indices;
1899
1900         /*
1901          * Add "num_indices" elements to "tree_is_expanded".
1902          */
1903         tree_is_expanded = g_realloc(tree_is_expanded,
1904             (num_tree_types + num_indices)*sizeof (gint));
1905
1906         /*
1907          * Assign "num_indices" subtree numbers starting at "num_tree_types",
1908          * returning the indices through the pointers in the array whose
1909          * first element is pointed to by "indices", set to FALSE the
1910          * elements to which those subtree numbers refer, and update
1911          * "num_tree_types" appropriately.
1912          */
1913         for (i = 0; i < num_indices; i++, ptr++, num_tree_types++) {
1914                 tree_is_expanded[num_tree_types] = FALSE;
1915                 **ptr = num_tree_types;
1916         }
1917 }
1918
1919 void
1920 proto_item_fill_label(field_info *fi, gchar *label_str)
1921 {
1922         header_field_info               *hfinfo = fi->hfinfo;
1923
1924         guint8                          *bytes;
1925         guint32                         integer;
1926         ipv4_addr                       *ipv4;
1927         guint32                         n_addr; /* network-order IPv4 address */
1928
1929         switch(hfinfo->type) {
1930                 case FT_NONE:
1931                 case FT_PROTOCOL:
1932                         snprintf(label_str, ITEM_LABEL_LENGTH,
1933                                 "%s", hfinfo->name);
1934                         break;
1935
1936                 case FT_BOOLEAN:
1937                         fill_label_boolean(fi, label_str);
1938                         break;
1939
1940                 case FT_BYTES:
1941                         bytes = fvalue_get(fi->value);
1942                         if (bytes) {
1943                                 snprintf(label_str, ITEM_LABEL_LENGTH,
1944                                         "%s: %s", hfinfo->name, 
1945                                          bytes_to_str(bytes, fi->length));
1946                         }
1947                         else {
1948                                 snprintf(label_str, ITEM_LABEL_LENGTH,
1949                                         "%s: <MISSING>", hfinfo->name);
1950                         }
1951                         break;
1952
1953                 /* Four types of integers to take care of:
1954                  *      Bitfield, with val_string
1955                  *      Bitfield, w/o val_string
1956                  *      Non-bitfield, with val_string
1957                  *      Non-bitfield, w/o val_string
1958                  */
1959                 case FT_UINT8:
1960                 case FT_UINT16:
1961                 case FT_UINT24:
1962                 case FT_UINT32:
1963                         if (hfinfo->bitmask) {
1964                                 if (hfinfo->strings) {
1965                                         fill_label_enumerated_bitfield(fi, label_str);
1966                                 }
1967                                 else {
1968                                         fill_label_numeric_bitfield(fi, label_str);
1969                                 }
1970                         }
1971                         else {
1972                                 if (hfinfo->strings) {
1973                                         fill_label_enumerated_uint(fi, label_str);
1974                                 }
1975                                 else {
1976                                         fill_label_uint(fi, label_str);
1977                                 }
1978                         }
1979                         break;
1980
1981                 case FT_UINT64:
1982                         fill_label_uint64(fi, label_str);
1983                         break;
1984
1985                 case FT_INT8:
1986                 case FT_INT16:
1987                 case FT_INT24:
1988                 case FT_INT32:
1989                         g_assert(!hfinfo->bitmask);
1990                         if (hfinfo->strings) {
1991                                 fill_label_enumerated_int(fi, label_str);
1992                         }
1993                         else {
1994                                 fill_label_int(fi, label_str);
1995                         }
1996                         break;
1997
1998                 case FT_INT64:
1999                         fill_label_int64(fi, label_str);
2000                         break;
2001
2002                 case FT_DOUBLE:
2003                         snprintf(label_str, ITEM_LABEL_LENGTH,
2004                                 "%s: %g", hfinfo->name, fvalue_get_floating(fi->value));
2005                         break;
2006
2007                 case FT_ABSOLUTE_TIME:
2008                         snprintf(label_str, ITEM_LABEL_LENGTH,
2009                                 "%s: %s", hfinfo->name,
2010                                 abs_time_to_str(fvalue_get(fi->value)));
2011                         break;
2012
2013                 case FT_RELATIVE_TIME:
2014                         snprintf(label_str, ITEM_LABEL_LENGTH,
2015                                 "%s: %s seconds", hfinfo->name,
2016                                 rel_time_to_secs_str(fvalue_get(fi->value)));
2017                         break;
2018
2019                 case FT_IPXNET:
2020                         integer = fvalue_get_integer(fi->value);
2021                         snprintf(label_str, ITEM_LABEL_LENGTH,
2022                                 "%s: 0x%08X (%s)", hfinfo->name,
2023                                 integer, get_ipxnet_name(integer));
2024                         break;
2025
2026                 case FT_ETHER:
2027                         bytes = fvalue_get(fi->value);
2028                         snprintf(label_str, ITEM_LABEL_LENGTH,
2029                                 "%s: %s (%s)", hfinfo->name,
2030                                 ether_to_str(bytes),
2031                                 get_ether_name(bytes));
2032                         break;
2033
2034                 case FT_IPv4:
2035                         ipv4 = fvalue_get(fi->value);
2036                         n_addr = ipv4_get_net_order_addr(ipv4);
2037                         snprintf(label_str, ITEM_LABEL_LENGTH,
2038                                 "%s: %s (%s)", hfinfo->name,
2039                                 get_hostname(n_addr),
2040                                 ip_to_str((guint8*)&n_addr));
2041                         break;
2042
2043                 case FT_IPv6:
2044                         bytes = fvalue_get(fi->value);
2045                         snprintf(label_str, ITEM_LABEL_LENGTH,
2046                                 "%s: %s (%s)", hfinfo->name,
2047                                 get_hostname6((struct e_in6_addr *)bytes),
2048                                 ip6_to_str((struct e_in6_addr*)bytes));
2049                         break;
2050         
2051                 case FT_STRING:
2052                 case FT_STRINGZ:
2053                 case FT_UINT_STRING:
2054                         snprintf(label_str, ITEM_LABEL_LENGTH,
2055                                 "%s: %s", hfinfo->name, (char*) fvalue_get(fi->value));
2056                         break;
2057
2058                 default:
2059                         g_error("hfinfo->type %d (%s) not handled\n",
2060                                         hfinfo->type,
2061                                         ftype_name(hfinfo->type));
2062                         g_assert_not_reached();
2063                         break;
2064         }
2065 }
2066
2067 static void
2068 fill_label_uint64(field_info *fi, gchar *label_str)
2069 {
2070         unsigned char *bytes;
2071         header_field_info *hfinfo = fi->hfinfo;
2072
2073         bytes=fvalue_get(fi->value);
2074         switch(hfinfo->display){
2075         case BASE_DEC:
2076                 snprintf(label_str, ITEM_LABEL_LENGTH,
2077                         "%s: %s", hfinfo->name,
2078                         u64toa(bytes));
2079                 break;
2080         case BASE_HEX:
2081                 snprintf(label_str, ITEM_LABEL_LENGTH,
2082                         "%s: %s", hfinfo->name,
2083                         u64toh(bytes));
2084                 break;
2085         default:
2086                 g_assert_not_reached();
2087                 ;
2088         }
2089 }
2090
2091 static void
2092 fill_label_int64(field_info *fi, gchar *label_str)
2093 {
2094         unsigned char *bytes;
2095         header_field_info *hfinfo = fi->hfinfo;
2096
2097         bytes=fvalue_get(fi->value);
2098         switch(hfinfo->display){
2099         case BASE_DEC:
2100                 snprintf(label_str, ITEM_LABEL_LENGTH,
2101                         "%s: %s", hfinfo->name,
2102                         i64toa(bytes));
2103                 break;
2104         case BASE_HEX:
2105                 snprintf(label_str, ITEM_LABEL_LENGTH,
2106                         "%s: %s", hfinfo->name,
2107                         u64toh(bytes));
2108                 break;
2109         default:
2110                 g_assert_not_reached();
2111                 ;
2112         }
2113 }
2114
2115 static void
2116 fill_label_boolean(field_info *fi, gchar *label_str)
2117 {
2118         char    *p = label_str;
2119         int     bitfield_byte_length = 0, bitwidth;
2120         guint32 unshifted_value;
2121         guint32 value;
2122
2123         header_field_info               *hfinfo = fi->hfinfo;
2124         static true_false_string        default_tf = { "True", "False" };
2125         true_false_string               *tfstring = &default_tf;
2126
2127         if (hfinfo->strings) {
2128                 tfstring = (struct true_false_string*) hfinfo->strings;
2129         }
2130
2131         value = fvalue_get_integer(fi->value);
2132         if (hfinfo->bitmask) {
2133                 /* Figure out the bit width */
2134                 bitwidth = hfinfo_bitwidth(hfinfo);
2135
2136                 /* Un-shift bits */
2137                 unshifted_value = value;
2138                 if (hfinfo->bitshift > 0) {
2139                         unshifted_value <<= hfinfo->bitshift;
2140                 }
2141
2142                 /* Create the bitfield first */
2143                 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
2144                 bitfield_byte_length = p - label_str;
2145         }
2146
2147         /* Fill in the textual info */
2148         snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
2149                 "%s: %s",  hfinfo->name,
2150                 value ? tfstring->true_string : tfstring->false_string);
2151 }
2152
2153
2154 /* Fills data for bitfield ints with val_strings */
2155 static void
2156 fill_label_enumerated_bitfield(field_info *fi, gchar *label_str)
2157 {
2158         char *format = NULL, *p;
2159         int bitfield_byte_length, bitwidth;
2160         guint32 unshifted_value;
2161         guint32 value;
2162
2163         header_field_info       *hfinfo = fi->hfinfo;
2164
2165         /* Figure out the bit width */
2166         bitwidth = hfinfo_bitwidth(hfinfo);
2167
2168         /* Pick the proper format string */
2169         format = hfinfo_uint_vals_format(hfinfo);
2170
2171         /* Un-shift bits */
2172         unshifted_value = fvalue_get_integer(fi->value);
2173         value = unshifted_value;
2174         if (hfinfo->bitshift > 0) {
2175                 unshifted_value <<= hfinfo->bitshift;
2176         }
2177
2178         /* Create the bitfield first */
2179         p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
2180         bitfield_byte_length = p - label_str;
2181
2182         /* Fill in the textual info using stored (shifted) value */
2183         snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
2184                         format,  hfinfo->name,
2185                         val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
2186 }
2187
2188 static void
2189 fill_label_numeric_bitfield(field_info *fi, gchar *label_str)
2190 {
2191         char *format = NULL, *p;
2192         int bitfield_byte_length, bitwidth;
2193         guint32 unshifted_value;
2194         guint32 value;
2195
2196         header_field_info       *hfinfo = fi->hfinfo;
2197
2198         /* Figure out the bit width */
2199         bitwidth = hfinfo_bitwidth(hfinfo);
2200
2201         /* Pick the proper format string */
2202         format = hfinfo_uint_format(hfinfo);
2203
2204         /* Un-shift bits */
2205         unshifted_value = fvalue_get_integer(fi->value);
2206         value = unshifted_value;
2207         if (hfinfo->bitshift > 0) {
2208                 unshifted_value <<= hfinfo->bitshift;
2209         }
2210
2211         /* Create the bitfield using */
2212         p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
2213         bitfield_byte_length = p - label_str;
2214
2215         /* Fill in the textual info using stored (shifted) value */
2216         snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
2217                         format,  hfinfo->name, value);
2218 }
2219
2220 static void
2221 fill_label_enumerated_uint(field_info *fi, gchar *label_str)
2222 {
2223         char *format = NULL;
2224         header_field_info       *hfinfo = fi->hfinfo;
2225         guint32 value;
2226
2227         /* Pick the proper format string */
2228         format = hfinfo_uint_vals_format(hfinfo);
2229
2230         value = fvalue_get_integer(fi->value);
2231
2232         /* Fill in the textual info */
2233         snprintf(label_str, ITEM_LABEL_LENGTH,
2234                         format,  hfinfo->name,
2235                         val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
2236 }
2237
2238 static void
2239 fill_label_uint(field_info *fi, gchar *label_str)
2240 {
2241         char *format = NULL;
2242         header_field_info       *hfinfo = fi->hfinfo;
2243         guint32 value;
2244
2245         /* Pick the proper format string */
2246         format = hfinfo_uint_format(hfinfo);
2247         value = fvalue_get_integer(fi->value);
2248
2249         /* Fill in the textual info */
2250         snprintf(label_str, ITEM_LABEL_LENGTH,
2251                         format,  hfinfo->name, value);
2252 }
2253
2254 static void
2255 fill_label_enumerated_int(field_info *fi, gchar *label_str)
2256 {
2257         char *format = NULL;
2258         header_field_info       *hfinfo = fi->hfinfo;
2259         guint32 value;
2260
2261         /* Pick the proper format string */
2262         format = hfinfo_int_vals_format(hfinfo);
2263         value = fvalue_get_integer(fi->value);
2264
2265         /* Fill in the textual info */
2266         snprintf(label_str, ITEM_LABEL_LENGTH,
2267                         format,  hfinfo->name,
2268                         val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
2269 }
2270
2271 static void
2272 fill_label_int(field_info *fi, gchar *label_str)
2273 {
2274         char *format = NULL;
2275         header_field_info       *hfinfo = fi->hfinfo;
2276         guint32 value;
2277
2278         /* Pick the proper format string */
2279         format = hfinfo_int_format(hfinfo);
2280         value = fvalue_get_integer(fi->value);
2281
2282         /* Fill in the textual info */
2283         snprintf(label_str, ITEM_LABEL_LENGTH,
2284                         format,  hfinfo->name, value);
2285 }
2286
2287 int
2288 hfinfo_bitwidth(header_field_info *hfinfo)
2289 {
2290         int bitwidth = 0;
2291
2292         if (!hfinfo->bitmask) {
2293                 return 0;
2294         }
2295
2296         switch(hfinfo->type) {
2297                 case FT_UINT8:
2298                 case FT_INT8:
2299                         bitwidth = 8;
2300                         break;
2301                 case FT_UINT16:
2302                 case FT_INT16:
2303                         bitwidth = 16;
2304                         break;
2305                 case FT_UINT24:
2306                 case FT_INT24:
2307                         bitwidth = 24;
2308                         break;
2309                 case FT_UINT32:
2310                 case FT_INT32:
2311                         bitwidth = 32;
2312                         break;
2313                 case FT_BOOLEAN:
2314                         bitwidth = hfinfo->display; /* hacky? :) */
2315                         break;
2316                 default:
2317                         g_assert_not_reached();
2318                         ;
2319         }
2320         return bitwidth;
2321 }
2322
2323 static char*
2324 hfinfo_uint_vals_format(header_field_info *hfinfo)
2325 {
2326         char *format = NULL;
2327
2328         switch(hfinfo->display) {
2329                 case BASE_DEC:
2330                 case BASE_BIN: /* I'm lazy */
2331                         format = "%s: %s (%u)";
2332                         break;
2333                 case BASE_OCT: /* I'm lazy */
2334                         format = "%s: %s (%o)";
2335                         break;
2336                 case BASE_HEX:
2337                         switch(hfinfo->type) {
2338                                 case FT_UINT8:
2339                                         format = "%s: %s (0x%02x)";
2340                                         break;
2341                                 case FT_UINT16:
2342                                         format = "%s: %s (0x%04x)";
2343                                         break;
2344                                 case FT_UINT24:
2345                                         format = "%s: %s (0x%06x)";
2346                                         break;
2347                                 case FT_UINT32:
2348                                         format = "%s: %s (0x%08x)";
2349                                         break;
2350                                 default:
2351                                         g_assert_not_reached();
2352                                         ;
2353                         }
2354                         break;
2355                 default:
2356                         g_assert_not_reached();
2357                         ;
2358         }
2359         return format;
2360 }
2361
2362 static char*
2363 hfinfo_uint_format(header_field_info *hfinfo)
2364 {
2365         char *format = NULL;
2366
2367         /* Pick the proper format string */
2368         switch(hfinfo->display) {
2369                 case BASE_DEC:
2370                 case BASE_BIN: /* I'm lazy */
2371                         format = "%s: %u";
2372                         break;
2373                 case BASE_OCT: /* I'm lazy */
2374                         format = "%s: %o";
2375                         break;
2376                 case BASE_HEX:
2377                         switch(hfinfo->type) {
2378                                 case FT_UINT8:
2379                                         format = "%s: 0x%02x";
2380                                         break;
2381                                 case FT_UINT16:
2382                                         format = "%s: 0x%04x";
2383                                         break;
2384                                 case FT_UINT24:
2385                                         format = "%s: 0x%06x";
2386                                         break;
2387                                 case FT_UINT32:
2388                                         format = "%s: 0x%08x";
2389                                         break;
2390                                 default:
2391                                         g_assert_not_reached();
2392                                         ;
2393                         }
2394                         break;
2395                 default:
2396                         g_assert_not_reached();
2397                         ;
2398         }
2399         return format;
2400 }
2401
2402 static char*
2403 hfinfo_int_vals_format(header_field_info *hfinfo)
2404 {
2405         char *format = NULL;
2406
2407         switch(hfinfo->display) {
2408                 case BASE_DEC:
2409                 case BASE_BIN: /* I'm lazy */
2410                         format = "%s: %s (%d)";
2411                         break;
2412                 case BASE_OCT: /* I'm lazy */
2413                         format = "%s: %s (%o)";
2414                         break;
2415                 case BASE_HEX:
2416                         switch(hfinfo->type) {
2417                                 case FT_INT8:
2418                                         format = "%s: %s (0x%02x)";
2419                                         break;
2420                                 case FT_INT16:
2421                                         format = "%s: %s (0x%04x)";
2422                                         break;
2423                                 case FT_INT24:
2424                                         format = "%s: %s (0x%06x)";
2425                                         break;
2426                                 case FT_INT32:
2427                                         format = "%s: %s (0x%08x)";
2428                                         break;
2429                                 default:
2430                                         g_assert_not_reached();
2431                                         ;
2432                         }
2433                         break;
2434                 default:
2435                         g_assert_not_reached();
2436                         ;
2437         }
2438         return format;
2439 }
2440
2441 static char*
2442 hfinfo_int_format(header_field_info *hfinfo)
2443 {
2444         char *format = NULL;
2445
2446         /* Pick the proper format string */
2447         switch(hfinfo->display) {
2448                 case BASE_DEC:
2449                 case BASE_BIN: /* I'm lazy */
2450                         format = "%s: %d";
2451                         break;
2452                 case BASE_OCT: /* I'm lazy */
2453                         format = "%s: %o";
2454                         break;
2455                 case BASE_HEX:
2456                         switch(hfinfo->type) {
2457                                 case FT_INT8:
2458                                         format = "%s: 0x%02x";
2459                                         break;
2460                                 case FT_INT16:
2461                                         format = "%s: 0x%04x";
2462                                         break;
2463                                 case FT_INT24:
2464                                         format = "%s: 0x%06x";
2465                                         break;
2466                                 case FT_INT32:
2467                                         format = "%s: 0x%08x";
2468                                         break;
2469                                 default:
2470                                         g_assert_not_reached();
2471                                         ;
2472                         }
2473                         break;
2474                 default:
2475                         g_assert_not_reached();
2476                         ;
2477         }
2478         return format;
2479 }
2480
2481
2482
2483 int
2484 proto_registrar_n(void)
2485 {
2486         return gpa_hfinfo->len;
2487 }
2488
2489 char*
2490 proto_registrar_get_name(int n)
2491 {
2492         header_field_info *hfinfo;
2493
2494         hfinfo = proto_registrar_get_nth(n);
2495         if (hfinfo)
2496                 return hfinfo->name;
2497         else
2498                 return NULL;
2499 }
2500
2501 char*
2502 proto_registrar_get_abbrev(int n)
2503 {
2504         header_field_info *hfinfo;
2505
2506         hfinfo = proto_registrar_get_nth(n);
2507         if (hfinfo)
2508                 return hfinfo->abbrev;
2509         else
2510                 return NULL;
2511 }
2512
2513 int
2514 proto_registrar_get_ftype(int n)
2515 {
2516         header_field_info *hfinfo;
2517
2518         hfinfo = proto_registrar_get_nth(n);
2519         if (hfinfo)
2520                 return hfinfo->type;
2521         else
2522                 return -1;
2523 }
2524
2525 int
2526 proto_registrar_get_parent(int n)
2527 {
2528         header_field_info *hfinfo;
2529
2530         hfinfo = proto_registrar_get_nth(n);
2531         if (hfinfo)
2532                 return hfinfo->parent;
2533         else
2534                 return -2;
2535 }
2536
2537 gboolean
2538 proto_registrar_is_protocol(int n)
2539 {
2540         header_field_info *hfinfo;
2541
2542         hfinfo = proto_registrar_get_nth(n);
2543         if (hfinfo)
2544                 return (hfinfo->parent == -1 ? TRUE : FALSE);
2545         else
2546                 return FALSE;
2547 }
2548
2549 /* Returns length of field in packet (not necessarily the length
2550  * in our internal representation, as in the case of IPv4).
2551  * 0 means undeterminable at time of registration
2552  * -1 means the field is not registered. */
2553 gint
2554 proto_registrar_get_length(int n)
2555 {
2556         header_field_info *hfinfo;
2557
2558         hfinfo = proto_registrar_get_nth(n);
2559         if (!hfinfo)
2560                 return -1;
2561
2562         return ftype_length(hfinfo->type);
2563 }
2564
2565
2566 /* =================================================================== */
2567 /* used when calling proto search functions */
2568 typedef struct {
2569         header_field_info       *target;
2570         const guint8            *packet_data;
2571         guint                   packet_len;
2572         gboolean                halt_on_first_hit;
2573         GNodeTraverseFunc       traverse_func; /* for traverse_subtree_for_field() */
2574         union {
2575                 GPtrArray               *ptr_array;
2576                 GNode                   *node;
2577         }                       result;
2578 } proto_tree_search_info;
2579
2580 /* Looks for a protocol at the top layer of the tree. The protocol can occur
2581  * more than once, for those encapsulated protocols. For each protocol subtree
2582  * that is found, the callback function is called.
2583  */
2584 static void
2585 proto_find_protocol_multi(proto_tree* tree, GNodeTraverseFunc callback,
2586                         proto_tree_search_info *sinfo)
2587 {
2588         g_assert(callback != NULL);
2589         g_node_traverse((GNode*)tree, G_IN_ORDER, G_TRAVERSE_ALL, 2, callback, (gpointer*)sinfo);
2590 }
2591
2592 /* Calls a traversal function for all subtrees.
2593  */
2594 static gboolean
2595 traverse_subtree_for_field(GNode *node, gpointer data)
2596 {
2597         field_info              *fi = (field_info*) (node->data);
2598         proto_tree_search_info  *sinfo = (proto_tree_search_info*) data;
2599
2600         if (fi) { /* !fi == the top most container node which holds nothing */
2601                         g_node_traverse(node, G_IN_ORDER, G_TRAVERSE_ALL, -1,
2602                                         sinfo->traverse_func, sinfo);
2603                         if (sinfo->result.node)
2604                                 return sinfo->halt_on_first_hit; /* halt? continue? */
2605         }
2606         return FALSE; /* keep traversing */
2607 }
2608
2609 static gboolean
2610 check_for_protocol_or_field_id(GNode *node, gpointer data)
2611 {
2612         field_info              *fi = (field_info*) (node->data);
2613         proto_tree_search_info  *sinfo = (proto_tree_search_info*) data;
2614         header_field_info       *hfinfo;
2615
2616         if (fi) { /* !fi == the top most container node which holds nothing */
2617                 /* Is this field one of the fields in the specified list
2618                  * of fields? */
2619                 for (hfinfo = sinfo->target; hfinfo != NULL;
2620                     hfinfo = hfinfo->same_name_next) {
2621                         if (fi->hfinfo == hfinfo) {
2622                                 sinfo->result.node = node;
2623                                 return TRUE; /* halt traversal */
2624                         }
2625                 }
2626         }
2627         return FALSE; /* keep traversing */
2628 }
2629
2630 /* Looks for a protocol or a field in a proto_tree. Returns TRUE if
2631  * it exists anywhere, or FALSE if it exists nowhere. */
2632 gboolean
2633 proto_check_for_protocol_or_field(proto_tree* tree, int id)
2634 {
2635         proto_tree_search_info  sinfo;
2636         header_field_info       *hfinfo;
2637
2638         hfinfo = proto_registrar_get_nth(id);
2639
2640         /* Find the first entry on the list of fields with the same
2641          * name as this field. */
2642         while (hfinfo->same_name_prev != NULL)
2643                 hfinfo = hfinfo->same_name_prev;
2644
2645         sinfo.target            = hfinfo;
2646         sinfo.result.node       = NULL;
2647         sinfo.traverse_func     = check_for_protocol_or_field_id;
2648         sinfo.halt_on_first_hit = TRUE;
2649
2650         /* do a quicker check if target is a protocol */
2651         if (proto_registrar_is_protocol(id) == TRUE) {
2652                 proto_find_protocol_multi(tree, check_for_protocol_or_field_id, &sinfo);
2653         }
2654         else {
2655                 /* Go through each protocol subtree. */
2656                 g_node_traverse((GNode*)tree, G_IN_ORDER, G_TRAVERSE_ALL, 2,
2657                                                 traverse_subtree_for_field, &sinfo);
2658         }
2659
2660         if (sinfo.result.node)
2661                 return TRUE;
2662         else
2663                 return FALSE;
2664 }
2665
2666
2667
2668 static gboolean
2669 get_finfo_ptr_array(GNode *node, gpointer data)
2670 {
2671         field_info              *fi = (field_info*) (node->data);
2672         proto_tree_search_info  *sinfo = (proto_tree_search_info*) data;
2673         header_field_info       *hfinfo;
2674
2675         if (fi) { /* !fi == the top most container node which holds nothing */
2676                 /* Is this field one of the fields in the specified list
2677                  * of fields? */
2678                 for (hfinfo = sinfo->target; hfinfo != NULL;
2679                     hfinfo = hfinfo->same_name_next) {
2680                         if (fi->hfinfo == hfinfo) {
2681                                 if (!sinfo->result.ptr_array) {
2682                                         sinfo->result.ptr_array = g_ptr_array_new();
2683                                 }
2684                                 g_ptr_array_add(sinfo->result.ptr_array,
2685                                                 (gpointer)fi);
2686                                 return FALSE; /* keep traversing */
2687                         }
2688                 }
2689         }
2690         return FALSE; /* keep traversing */
2691 }
2692
2693 /* Return GPtrArray* of field_info pointers for all hfindex that appear in tree
2694  * (we assume that a field will only appear under its registered parent's subtree) */
2695 GPtrArray*
2696 proto_get_finfo_ptr_array(proto_tree *tree, int id)
2697 {
2698         proto_tree_search_info  sinfo;
2699         header_field_info       *hfinfo;
2700
2701         hfinfo = proto_registrar_get_nth(id);
2702
2703         /* Find the first entry on the list of fields with the same
2704          * name as this field. */
2705         while (hfinfo->same_name_prev != NULL)
2706                 hfinfo = hfinfo->same_name_prev;
2707
2708         sinfo.target            = hfinfo;
2709         sinfo.result.ptr_array  = NULL;
2710         sinfo.traverse_func     = get_finfo_ptr_array;
2711         sinfo.halt_on_first_hit = FALSE;
2712
2713         /* do a quicker check if target is a protocol */
2714         if (proto_registrar_is_protocol(id) == TRUE) {
2715                 proto_find_protocol_multi(tree, get_finfo_ptr_array, &sinfo);
2716         }
2717         else {
2718                 /* Go through each protocol subtree. */
2719                 sinfo.traverse_func = get_finfo_ptr_array;
2720                 g_node_traverse((GNode*)tree, G_IN_ORDER, G_TRAVERSE_ALL, 2,
2721                                                 traverse_subtree_for_field, &sinfo);
2722         }
2723
2724         return sinfo.result.ptr_array;
2725 }
2726
2727
2728
2729 typedef struct {
2730         guint           offset;
2731         field_info      *finfo;
2732         gchar           *name;
2733 } offset_search_t;
2734
2735 static gboolean
2736 check_for_offset(GNode *node, gpointer data)
2737 {
2738         field_info              *fi = node->data;
2739         offset_search_t         *offsearch = data;
2740
2741         /* !fi == the top most container node which holds nothing */
2742         if (fi && fi->visible && fi->ds_name &&
2743             strcmp(offsearch->name, fi->ds_name) == 0) {
2744                 if (offsearch->offset >= (guint) fi->start &&
2745                                 offsearch->offset < (guint) (fi->start + fi->length)) {
2746
2747                         offsearch->finfo = fi;
2748                         return FALSE; /* keep traversing */
2749                 }
2750         }
2751         return FALSE; /* keep traversing */
2752 }
2753
2754 /* Search a proto_tree backwards (from leaves to root) looking for the field
2755  * whose start/length occupies 'offset' */
2756 /* XXX - I couldn't find an easy way to search backwards, so I search
2757  * forwards, w/o stopping. Therefore, the last finfo I find will the be
2758  * the one I want to return to the user. This algorithm is inefficient
2759  * and could be re-done, but I'd have to handle all the children and
2760  * siblings of each node myself. When I have more time I'll do that.
2761  * (yeah right) */
2762 field_info*
2763 proto_find_field_from_offset(proto_tree *tree, guint offset, char* ds_name)
2764 {
2765         offset_search_t         offsearch;
2766
2767         offsearch.offset = offset;
2768         offsearch.finfo = NULL;
2769         offsearch.name = ds_name;
2770
2771         g_node_traverse((GNode*)tree, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
2772                         check_for_offset, &offsearch);
2773
2774         return offsearch.finfo;
2775 }
2776
2777
2778
2779         
2780
2781 /* Dumps the contents of the registration database to stdout. An indepedent program can take
2782  * this output and format it into nice tables or HTML or whatever.
2783  *
2784  * There is one record per line. Each record is either a protocol or a header
2785  * field, differentiated by the first field. The fields are tab-delimited.
2786  *
2787  * Protocols
2788  * ---------
2789  * Field 1 = 'P'
2790  * Field 2 = protocol name
2791  * Field 3 = protocol abbreviation
2792  *
2793  * Header Fields
2794  * -------------
2795  * Field 1 = 'F'
2796  * Field 2 = field name
2797  * Field 3 = field abbreviation
2798  * Field 4 = type ( textual representation of the the ftenum type )
2799  * Field 5 = parent protocol abbreviation
2800  */
2801 void
2802 proto_registrar_dump(void)
2803 {
2804         header_field_info       *hfinfo, *parent_hfinfo;
2805         int                     i, len;
2806         const char              *enum_name;
2807
2808         len = gpa_hfinfo->len;
2809         for (i = 0; i < len ; i++) {
2810                 hfinfo = proto_registrar_get_nth(i);
2811
2812                 /*
2813                  * Skip fields with zero-length names or abbreviations;
2814                  * the pseudo-field for "proto_tree_add_text()" is such
2815                  * a field, and we don't want it in the list of filterable
2816                  * fields.
2817                  *
2818                  *
2819                  * XXX - perhaps the name and abbrev field should be null
2820                  * pointers rather than null strings for that pseudo-field,
2821                  * but we'd have to add checks for null pointers in some
2822                  * places if we did that.
2823                  *
2824                  * Or perhaps protocol tree items added with
2825                  * "proto_tree_add_text()" should have -1 as the field index,
2826                  * with no pseudo-field being used, but that might also
2827                  * require special checks for -1 to be added.
2828                  */
2829                 if (strlen(hfinfo->name) == 0 || strlen(hfinfo->abbrev) == 0)
2830                         continue;
2831
2832                 /* format for protocols */
2833                 if (proto_registrar_is_protocol(i)) {
2834                         printf("P\t%s\t%s\n", hfinfo->name, hfinfo->abbrev);
2835                 }
2836                 /* format for header fields */
2837                 else {
2838                         /*
2839                          * If this field isn't at the head of the list of
2840                          * fields with this name, skip this field - all
2841                          * fields with the same name are really just versions
2842                          * of the same field stored in different bits, and
2843                          * should have the same type/radix/value list, and
2844                          * just differ in their bit masks.  (If a field isn't
2845                          * a bitfield, but can be, say, 1 or 2 bytes long,
2846                          * it can just be made FT_UINT16, meaning the
2847                          * *maximum* length is 2 bytes, and be used
2848                          * for all lengths.)
2849                          */
2850                         if (hfinfo->same_name_prev != NULL)
2851                                 continue;
2852
2853                         parent_hfinfo = proto_registrar_get_nth(hfinfo->parent);
2854                         g_assert(parent_hfinfo);
2855
2856                         enum_name = ftype_name(hfinfo->type);
2857                         printf("F\t%s\t%s\t%s\t%s\n", hfinfo->name, hfinfo->abbrev,
2858                                 enum_name,parent_hfinfo->abbrev);
2859                 }
2860         }
2861 }
2862
2863 static char*
2864 hfinfo_numeric_format(header_field_info *hfinfo)
2865 {
2866         char *format = NULL;
2867
2868         /* Pick the proper format string */
2869         switch(hfinfo->display) {
2870                 case BASE_DEC:
2871                 case BASE_OCT: /* I'm lazy */
2872                 case BASE_BIN: /* I'm lazy */
2873                         switch(hfinfo->type) {
2874                                 case FT_UINT8:
2875                                 case FT_UINT16:
2876                                 case FT_UINT24:
2877                                 case FT_UINT32:
2878                                         format = "%s == %u";
2879                                         break;
2880                                 case FT_INT8:
2881                                 case FT_INT16:
2882                                 case FT_INT24:
2883                                 case FT_INT32:
2884                                         format = "%s == %d";
2885                                         break;
2886                                 default:
2887                                         g_assert_not_reached();
2888                                         ;
2889                         }
2890                         break;
2891                 case BASE_HEX:
2892                         switch(hfinfo->type) {
2893                                 case FT_UINT8:
2894                                         format = "%s == 0x%02x";
2895                                         break;
2896                                 case FT_UINT16:
2897                                         format = "%s == 0x%04x";
2898                                         break;
2899                                 case FT_UINT24:
2900                                         format = "%s == 0x%06x";
2901                                         break;
2902                                 case FT_UINT32:
2903                                         format = "%s == 0x%08x";
2904                                         break;
2905                                 default:
2906                                         g_assert_not_reached();
2907                                         ;
2908                         }
2909                         break;
2910                 default:
2911                         g_assert_not_reached();
2912                         ;
2913         }
2914         return format;
2915 }
2916
2917 /*
2918  * Returns TRUE if we can do a "match selected" on the field, FALSE
2919  * otherwise.
2920  */
2921 gboolean
2922 proto_can_match_selected(field_info *finfo)
2923 {
2924         header_field_info       *hfinfo;
2925
2926         hfinfo = finfo->hfinfo;
2927         g_assert(hfinfo);
2928
2929         switch(hfinfo->type) {
2930
2931                 case FT_BOOLEAN:
2932                 case FT_UINT8:
2933                 case FT_UINT16:
2934                 case FT_UINT24:
2935                 case FT_UINT32:
2936                 case FT_UINT64:
2937                 case FT_INT8:
2938                 case FT_INT16:
2939                 case FT_INT24:
2940                 case FT_INT32:
2941                 case FT_INT64:
2942                 case FT_IPv4:
2943                 case FT_IPXNET:
2944                 case FT_IPv6:
2945                 case FT_DOUBLE:
2946                 case FT_ETHER:
2947                 case FT_ABSOLUTE_TIME:
2948                 case FT_RELATIVE_TIME:
2949                 case FT_STRING:
2950                 case FT_BYTES:
2951                         /*
2952                          * These all have values, so we can match.
2953                          */
2954                         return TRUE;
2955
2956                 default:
2957                         /*
2958                          * This doesn't have a value, so we'd match
2959                          * on the raw bytes at this address;
2960                          * however, if the length is 0, there's nothing
2961                          * to match, so we can't match.
2962                          */
2963                         return (finfo->length != 0);
2964         }
2965 }
2966
2967 char*
2968 proto_alloc_dfilter_string(field_info *finfo, guint8 *pd)
2969 {
2970         header_field_info       *hfinfo;
2971         int                     abbrev_len;
2972         char                    *buf, *stringified, *format, *ptr, *value_str;
2973         int                     dfilter_len, i;
2974         guint8                  *c;
2975
2976         hfinfo = finfo->hfinfo;
2977         g_assert(hfinfo);
2978         abbrev_len = strlen(hfinfo->abbrev);
2979
2980         switch(hfinfo->type) {
2981
2982                 case FT_BOOLEAN:
2983                         dfilter_len = abbrev_len + 6;
2984                         buf = g_malloc0(dfilter_len);
2985                         snprintf(buf, dfilter_len, "%s == %s",
2986                                         hfinfo->abbrev,
2987                                         fvalue_get_integer(finfo->value) ? "1" : "0");
2988                         break;
2989
2990                 case FT_UINT8:
2991                 case FT_UINT16:
2992                 case FT_UINT24:
2993                 case FT_UINT32:
2994                 case FT_INT8:
2995                 case FT_INT16:
2996                 case FT_INT24:
2997                 case FT_INT32:
2998                         dfilter_len = abbrev_len + 20;
2999                         buf = g_malloc0(dfilter_len);
3000                         format = hfinfo_numeric_format(hfinfo);
3001                         snprintf(buf, dfilter_len, format, hfinfo->abbrev, fvalue_get_integer(finfo->value));
3002                         break;
3003
3004                 case FT_UINT64:
3005                         stringified = u64toa(fvalue_get(finfo->value));
3006                         dfilter_len = abbrev_len + 4 + strlen(stringified) +1;
3007                         buf = g_malloc0(dfilter_len);
3008                         snprintf(buf, dfilter_len, "%s == %s", hfinfo->abbrev,
3009                                         stringified);
3010                         break;
3011
3012                 case FT_INT64:
3013                         stringified = i64toa(fvalue_get(finfo->value));
3014                         dfilter_len = abbrev_len + 4 + strlen(stringified) +1;
3015                         buf = g_malloc0(dfilter_len);
3016                         snprintf(buf, dfilter_len, "%s == %s", hfinfo->abbrev,
3017                                         stringified);
3018                         break;
3019
3020                 case FT_IPv4:
3021                         dfilter_len = abbrev_len + 4 + 15 + 1;
3022                         buf = g_malloc0(dfilter_len);
3023                         snprintf(buf, dfilter_len, "%s == %s", hfinfo->abbrev,
3024                                         ipv4_addr_str(fvalue_get(finfo->value)));
3025                         break;
3026
3027                 case FT_IPXNET:
3028                         dfilter_len = abbrev_len + 15;
3029                         buf = g_malloc0(dfilter_len);
3030                         snprintf(buf, dfilter_len, "%s == 0x%08x", hfinfo->abbrev,
3031                                         fvalue_get_integer(finfo->value));
3032                         break;
3033
3034                 case FT_IPv6:
3035                         stringified = ip6_to_str((struct e_in6_addr*) fvalue_get(finfo->value));
3036                         dfilter_len = abbrev_len + 4 + strlen(stringified) + 1;
3037                         buf = g_malloc0(dfilter_len);
3038                         snprintf(buf, dfilter_len, "%s == %s", hfinfo->abbrev,
3039                                         stringified);
3040                         break;
3041
3042                 case FT_DOUBLE:
3043                         dfilter_len = abbrev_len + 30;
3044                         buf = g_malloc0(dfilter_len);
3045                         snprintf(buf, dfilter_len, "%s == %f", hfinfo->abbrev,
3046                                         fvalue_get_floating(finfo->value));
3047                         break;
3048
3049                 case FT_ETHER:
3050                         dfilter_len = abbrev_len + 22;
3051                         buf = g_malloc0(dfilter_len);
3052                         snprintf(buf, dfilter_len, "%s == %s",
3053                                         hfinfo->abbrev,
3054                                         ether_to_str(fvalue_get(finfo->value)));
3055                         break;
3056
3057                 case FT_ABSOLUTE_TIME:
3058                         value_str =
3059                             abs_time_to_str((nstime_t *)fvalue_get(finfo->value));
3060                         dfilter_len = abbrev_len + strlen(value_str) + 7;
3061                         buf = g_malloc0(dfilter_len);
3062                         snprintf(buf, dfilter_len, "%s == \"%s\"",
3063                                         hfinfo->abbrev, value_str);
3064                         break;
3065
3066                 case FT_RELATIVE_TIME:
3067                         value_str =
3068                             rel_time_to_secs_str((nstime_t *)fvalue_get(finfo->value));
3069                         dfilter_len = abbrev_len + strlen(value_str) + 4;
3070                         buf = g_malloc0(dfilter_len);
3071                         snprintf(buf, dfilter_len, "%s == %s",
3072                                         hfinfo->abbrev, value_str);
3073                         break;
3074
3075 #if 0
3076                 case FT_TEXT_ONLY:
3077                         ; /* nothing */
3078                         break;
3079 #endif
3080
3081                 case FT_STRING:
3082                         value_str = fvalue_get(finfo->value);
3083                         dfilter_len = abbrev_len + strlen(value_str) + 7;
3084                         buf = g_malloc0(dfilter_len);
3085                         snprintf(buf, dfilter_len, "%s == \"%s\"",
3086                                  hfinfo->abbrev, value_str);
3087                         break;
3088
3089                 case FT_BYTES:
3090                         dfilter_len = finfo->length*3 - 1;
3091                         dfilter_len += abbrev_len + 7;
3092                         buf = g_malloc0(dfilter_len);
3093                         snprintf(buf, dfilter_len, "%s == %s",
3094                                  hfinfo->abbrev,
3095                                  bytes_to_str_punct(fvalue_get(finfo->value), finfo->length,':'));
3096                         break;       
3097
3098                 default:
3099                         c = pd + finfo->start;
3100                         buf = g_malloc0(32 + finfo->length * 3);
3101                         ptr = buf;
3102
3103                         sprintf(ptr, "frame[%d] == ", finfo->start);
3104                         ptr = buf+strlen(buf);
3105
3106                         for (i=0;i<finfo->length; i++) {
3107                                 if (i == 0 ) {
3108                                         sprintf(ptr, "%02x", *c++);
3109                                 }
3110                                 else {
3111                                         sprintf(ptr, ":%02x", *c++);
3112                                 }
3113                                 ptr = buf+strlen(buf);
3114                         }
3115                         break;
3116         }
3117
3118         return buf;
3119 }