1999-07-07 22:52:57 +00:00
|
|
|
/* proto.c
|
|
|
|
* Routines for protocol tree
|
|
|
|
*
|
Convert IPX-and-friend dissectors in packet-ipx.c to use
tvbuffs.
In doing so, I realied that my recommendation for using
tvb_new_subset(pi.compat_top_tvb, -1, -1) was incorrect, because
some dissectors (ethernet!) change pi.len and pi.cap_len. So, I have
to take those two variables into account instead of using -1 and -1.
So, I provide a macro called tvb_create_from_top(offset), where
offset is the name of your offset variable. It is a wrapper around
tvb_new_subset().
I converted the lines that followed my suggestion to use
tvb_create_from_top().
In proto.c I added
proto_tree_add_debug_text(proto_tree*, const char*, ...)
It's much like proto_tree_add_text(), except that it takes no offset
or length; it's soley for temporarily putting debug text into the
proto_tree while debugging a dissector. In making sure that its
use is temporary, the funciton also prints the debug string to stdout
to remind the programmer that the debug code needs to be removed
before shipping the code.
svn path=/trunk/; revision=2068
2000-06-15 03:49:00 +00:00
|
|
|
* $Id: proto.c,v 1.69 2000/06/15 03:48:44 gram Exp $
|
1999-07-07 22:52:57 +00:00
|
|
|
*
|
|
|
|
* Ethereal - Network traffic analyzer
|
|
|
|
* By Gerald Combs <gerald@zing.org>
|
|
|
|
* Copyright 1998 Gerald Combs
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include "config.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef HAVE_SYS_TYPES_H
|
|
|
|
# include <sys/types.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef _STDIO_H
|
|
|
|
#include <stdio.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <stdarg.h>
|
|
|
|
|
|
|
|
#ifndef _STRING_H
|
|
|
|
#include <string.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef NEED_SNPRINTF_H
|
|
|
|
# include "snprintf.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef __G_LIB_H__
|
|
|
|
#include <glib.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef __PROTO_H__
|
|
|
|
#include "proto.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef __PACKET_H__
|
|
|
|
#include "packet.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef __RESOLV_H__
|
|
|
|
#include "resolv.h"
|
|
|
|
#endif
|
|
|
|
|
1999-10-20 06:28:29 +00:00
|
|
|
#ifndef __REGISTER_H__
|
|
|
|
#include "register.h"
|
|
|
|
#endif
|
|
|
|
|
1999-10-11 17:05:49 +00:00
|
|
|
#include "packet-ipv6.h"
|
|
|
|
|
1999-07-07 22:52:57 +00:00
|
|
|
#define cVALS(x) (const value_string*)(x)
|
|
|
|
|
1999-08-04 23:43:42 +00:00
|
|
|
static gboolean
|
1999-07-07 22:52:57 +00:00
|
|
|
proto_tree_free_node(GNode *node, gpointer data);
|
|
|
|
|
1999-10-12 06:21:15 +00:00
|
|
|
static void fill_label_boolean(field_info *fi, gchar *label_str);
|
|
|
|
static void fill_label_uint(field_info *fi, gchar *label_str);
|
|
|
|
static void fill_label_enumerated_uint(field_info *fi, gchar *label_str);
|
|
|
|
static void fill_label_enumerated_bitfield(field_info *fi, gchar *label_str);
|
|
|
|
static void fill_label_numeric_bitfield(field_info *fi, gchar *label_str);
|
1999-10-13 03:07:30 +00:00
|
|
|
static void fill_label_int(field_info *fi, gchar *label_str);
|
|
|
|
static void fill_label_enumerated_int(field_info *fi, gchar *label_str);
|
1999-10-12 06:21:15 +00:00
|
|
|
|
|
|
|
static int hfinfo_bitwidth(header_field_info *hfinfo);
|
|
|
|
static char* hfinfo_uint_vals_format(header_field_info *hfinfo);
|
|
|
|
static char* hfinfo_uint_format(header_field_info *hfinfo);
|
1999-10-13 03:07:30 +00:00
|
|
|
static char* hfinfo_int_vals_format(header_field_info *hfinfo);
|
|
|
|
static char* hfinfo_int_format(header_field_info *hfinfo);
|
1999-10-12 06:21:15 +00:00
|
|
|
|
1999-08-29 04:06:43 +00:00
|
|
|
static gboolean check_for_protocol_or_field_id(GNode *node, gpointer data);
|
|
|
|
static gboolean check_for_field_within_protocol(GNode *node, gpointer data);
|
1999-07-07 22:52:57 +00:00
|
|
|
|
2000-03-12 04:48:32 +00:00
|
|
|
static proto_item*
|
|
|
|
proto_tree_add_node(proto_tree *tree, field_info *fi);
|
|
|
|
|
|
|
|
static proto_item *
|
2000-05-11 08:18:09 +00:00
|
|
|
proto_tree_add_pi(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
|
2000-05-31 05:09:07 +00:00
|
|
|
field_info **pfi);
|
|
|
|
static void
|
|
|
|
proto_tree_set_representation(proto_item *pi, const char *format, va_list ap);
|
2000-03-12 04:48:32 +00:00
|
|
|
|
|
|
|
static void
|
2000-03-14 06:03:26 +00:00
|
|
|
proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length);
|
2000-03-12 04:48:32 +00:00
|
|
|
static void
|
2000-05-31 05:09:07 +00:00
|
|
|
proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length);
|
|
|
|
static void
|
2000-03-12 04:48:32 +00:00
|
|
|
proto_tree_set_time(field_info *fi, struct timeval *value_ptr);
|
|
|
|
static void
|
2000-03-14 06:03:26 +00:00
|
|
|
proto_tree_set_string(field_info *fi, const char* value);
|
2000-03-12 04:48:32 +00:00
|
|
|
static void
|
2000-05-31 05:09:07 +00:00
|
|
|
proto_tree_set_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
|
|
|
|
static void
|
|
|
|
proto_tree_set_ether(field_info *fi, const guint8* value);
|
|
|
|
static void
|
|
|
|
proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start);
|
2000-03-12 04:48:32 +00:00
|
|
|
static void
|
|
|
|
proto_tree_set_ipxnet(field_info *fi, guint32 value);
|
|
|
|
static void
|
|
|
|
proto_tree_set_ipv4(field_info *fi, guint32 value);
|
|
|
|
static void
|
2000-05-31 05:09:07 +00:00
|
|
|
proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr);
|
|
|
|
static void
|
|
|
|
proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start);
|
2000-03-12 04:48:32 +00:00
|
|
|
static void
|
|
|
|
proto_tree_set_boolean(field_info *fi, guint32 value);
|
|
|
|
static void
|
|
|
|
proto_tree_set_double(field_info *fi, double value);
|
|
|
|
static void
|
|
|
|
proto_tree_set_uint(field_info *fi, guint32 value);
|
2000-04-25 21:43:50 +00:00
|
|
|
static void
|
|
|
|
proto_tree_set_int(field_info *fi, gint32 value);
|
2000-03-12 04:48:32 +00:00
|
|
|
|
1999-07-15 15:33:52 +00:00
|
|
|
static int proto_register_field_init(header_field_info *hfinfo, int parent);
|
|
|
|
|
|
|
|
/* special-case header field used within proto.c */
|
1999-07-07 22:52:57 +00:00
|
|
|
int hf_text_only = 1;
|
|
|
|
|
|
|
|
/* Contains information about protocols and header fields. Used when
|
|
|
|
* dissectors register their data */
|
|
|
|
GMemChunk *gmc_hfinfo = NULL;
|
|
|
|
|
|
|
|
/* Contains information about a field when a dissector calls
|
|
|
|
* proto_tree_add_item. */
|
|
|
|
GMemChunk *gmc_field_info = NULL;
|
|
|
|
|
|
|
|
/* String space for protocol and field items for the GUI */
|
|
|
|
GMemChunk *gmc_item_labels = NULL;
|
|
|
|
|
|
|
|
/* List which stores protocols and fields that have been registered */
|
|
|
|
GPtrArray *gpa_hfinfo = NULL;
|
|
|
|
|
1999-11-16 11:44:20 +00:00
|
|
|
/* Points to the first element of an array of Booleans, indexed by
|
|
|
|
a subtree item type; that array element is TRUE if subtrees of
|
|
|
|
an item of that type are to be expanded. */
|
|
|
|
gboolean *tree_is_expanded;
|
|
|
|
|
|
|
|
/* Number of elements in that array. */
|
|
|
|
int num_tree_types;
|
|
|
|
|
1999-08-26 07:01:44 +00:00
|
|
|
/* Is the parsing being done for a visible proto_tree or an invisible one?
|
|
|
|
* By setting this correctly, the proto_tree creation is sped up by not
|
|
|
|
* having to call vsnprintf and copy strings around.
|
|
|
|
*/
|
2000-05-18 08:35:01 +00:00
|
|
|
gboolean proto_tree_is_visible = FALSE;
|
1999-07-07 22:52:57 +00:00
|
|
|
|
|
|
|
/* initialize data structures and register protocols and fields */
|
|
|
|
void
|
|
|
|
proto_init(void)
|
|
|
|
{
|
1999-10-12 06:21:15 +00:00
|
|
|
static hf_register_info hf[] = {
|
|
|
|
{ &hf_text_only,
|
|
|
|
{ "Text", "text", FT_TEXT_ONLY, BASE_NONE, NULL, 0x0,
|
|
|
|
"" }},
|
|
|
|
};
|
|
|
|
|
1999-07-07 22:52:57 +00:00
|
|
|
if (gmc_hfinfo)
|
|
|
|
g_mem_chunk_destroy(gmc_hfinfo);
|
|
|
|
if (gmc_field_info)
|
|
|
|
g_mem_chunk_destroy(gmc_field_info);
|
|
|
|
if (gmc_item_labels)
|
|
|
|
g_mem_chunk_destroy(gmc_item_labels);
|
|
|
|
if (gpa_hfinfo)
|
1999-08-26 06:20:50 +00:00
|
|
|
g_ptr_array_free(gpa_hfinfo, FALSE);
|
1999-11-16 11:44:20 +00:00
|
|
|
if (tree_is_expanded != NULL)
|
|
|
|
g_free(tree_is_expanded);
|
1999-07-07 22:52:57 +00:00
|
|
|
|
|
|
|
gmc_hfinfo = g_mem_chunk_new("gmc_hfinfo",
|
|
|
|
sizeof(struct header_field_info), 50 * sizeof(struct
|
|
|
|
header_field_info), G_ALLOC_ONLY);
|
|
|
|
gmc_field_info = g_mem_chunk_new("gmc_field_info",
|
|
|
|
sizeof(struct field_info), 200 * sizeof(struct field_info),
|
|
|
|
G_ALLOC_AND_FREE);
|
|
|
|
gmc_item_labels = g_mem_chunk_new("gmc_item_labels",
|
|
|
|
ITEM_LABEL_LENGTH, 20 * ITEM_LABEL_LENGTH,
|
|
|
|
G_ALLOC_AND_FREE);
|
|
|
|
gpa_hfinfo = g_ptr_array_new();
|
|
|
|
|
1999-11-16 11:44:20 +00:00
|
|
|
/* Allocate "tree_is_expanded", with one element for ETT_NONE,
|
|
|
|
and initialize that element to FALSE. */
|
|
|
|
tree_is_expanded = g_malloc(sizeof (gint));
|
|
|
|
tree_is_expanded[0] = FALSE;
|
|
|
|
num_tree_types = 1;
|
|
|
|
|
2000-04-04 06:17:30 +00:00
|
|
|
/* Have each dissector register its protocols and fields, and
|
|
|
|
do whatever one-time initialization it needs to do. */
|
1999-10-20 06:28:29 +00:00
|
|
|
register_all_protocols();
|
1999-07-07 22:52:57 +00:00
|
|
|
|
2000-04-04 06:17:30 +00:00
|
|
|
/* Now have the ones that register a "handoff", i.e. that
|
|
|
|
specify that another dissector for a protocol under which
|
|
|
|
this dissector's protocol lives call it. */
|
|
|
|
register_all_protocol_handoffs();
|
|
|
|
|
1999-07-07 22:52:57 +00:00
|
|
|
/* Register one special-case FT_TEXT_ONLY field for use when
|
|
|
|
converting ethereal to new-style proto_tree. These fields
|
|
|
|
are merely strings on the GUI tree; they are not filterable */
|
1999-10-12 06:21:15 +00:00
|
|
|
proto_register_field_array(-1, hf, array_length(hf));
|
1999-11-16 11:44:20 +00:00
|
|
|
|
|
|
|
/* We've assigned all the subtree type values; allocate the array
|
|
|
|
for them, and zero it out. */
|
|
|
|
tree_is_expanded = g_malloc(num_tree_types*sizeof (gint *));
|
|
|
|
memset(tree_is_expanded, '\0', num_tree_types*sizeof (gint *));
|
1999-07-07 22:52:57 +00:00
|
|
|
}
|
|
|
|
|
1999-08-26 06:20:50 +00:00
|
|
|
void
|
|
|
|
proto_cleanup(void)
|
|
|
|
{
|
|
|
|
if (gmc_hfinfo)
|
|
|
|
g_mem_chunk_destroy(gmc_hfinfo);
|
|
|
|
if (gmc_field_info)
|
|
|
|
g_mem_chunk_destroy(gmc_field_info);
|
|
|
|
if (gmc_item_labels)
|
|
|
|
g_mem_chunk_destroy(gmc_item_labels);
|
|
|
|
if (gpa_hfinfo)
|
|
|
|
g_ptr_array_free(gpa_hfinfo, FALSE);
|
|
|
|
}
|
|
|
|
|
1999-07-07 22:52:57 +00:00
|
|
|
/* frees the resources that the dissection a proto_tree uses */
|
|
|
|
void
|
|
|
|
proto_tree_free(proto_tree *tree)
|
|
|
|
{
|
|
|
|
g_node_traverse((GNode*)tree, G_IN_ORDER, G_TRAVERSE_ALL, -1,
|
1999-08-04 23:43:42 +00:00
|
|
|
proto_tree_free_node, NULL);
|
1999-08-07 01:34:29 +00:00
|
|
|
g_node_destroy((GNode*)tree);
|
1999-07-07 22:52:57 +00:00
|
|
|
}
|
|
|
|
|
1999-08-04 23:43:42 +00:00
|
|
|
static gboolean
|
1999-07-07 22:52:57 +00:00
|
|
|
proto_tree_free_node(GNode *node, gpointer data)
|
|
|
|
{
|
|
|
|
field_info *fi = (field_info*) (node->data);
|
1999-08-04 23:43:42 +00:00
|
|
|
|
|
|
|
if (fi != NULL) {
|
|
|
|
if (fi->representation)
|
|
|
|
g_mem_chunk_free(gmc_item_labels, fi->representation);
|
|
|
|
if (fi->hfinfo->type == FT_STRING)
|
|
|
|
g_free(fi->value.string);
|
1999-09-18 15:44:41 +00:00
|
|
|
else if (fi->hfinfo->type == FT_BYTES)
|
|
|
|
g_free(fi->value.bytes);
|
1999-08-04 23:43:42 +00:00
|
|
|
g_mem_chunk_free(gmc_field_info, fi);
|
|
|
|
}
|
|
|
|
return FALSE; /* FALSE = do not end traversal of GNode tree */
|
1999-07-07 22:52:57 +00:00
|
|
|
}
|
|
|
|
|
2000-04-03 09:24:12 +00:00
|
|
|
/* Finds a record in the hf_info_records array by id. */
|
|
|
|
struct header_field_info*
|
2000-04-04 02:34:40 +00:00
|
|
|
proto_registrar_get_nth(int hfindex)
|
1999-07-07 22:52:57 +00:00
|
|
|
{
|
|
|
|
g_assert(hfindex >= 0 && hfindex < gpa_hfinfo->len);
|
|
|
|
return g_ptr_array_index(gpa_hfinfo, hfindex);
|
|
|
|
}
|
|
|
|
|
2000-03-12 04:48:32 +00:00
|
|
|
|
|
|
|
/* Add a node with no text */
|
1999-07-07 22:52:57 +00:00
|
|
|
proto_item *
|
2000-05-11 08:18:09 +00:00
|
|
|
proto_tree_add_notext(proto_tree *tree, tvbuff_t *tvb, gint start, gint length)
|
1999-07-07 22:52:57 +00:00
|
|
|
{
|
|
|
|
proto_item *pi;
|
|
|
|
|
2000-05-31 05:09:07 +00:00
|
|
|
pi = proto_tree_add_pi(tree, hf_text_only, tvb, start, length, NULL);
|
|
|
|
if (pi == NULL)
|
2000-03-12 04:48:32 +00:00
|
|
|
return(NULL);
|
|
|
|
|
1999-07-07 22:52:57 +00:00
|
|
|
return pi;
|
|
|
|
}
|
|
|
|
|
2000-03-12 04:48:32 +00:00
|
|
|
/* Add a text-only node to the proto_tree */
|
1999-07-07 22:52:57 +00:00
|
|
|
proto_item *
|
2000-05-11 08:18:09 +00:00
|
|
|
proto_tree_add_text(proto_tree *tree, tvbuff_t *tvb, gint start, gint length,
|
2000-03-12 04:48:32 +00:00
|
|
|
const char *format, ...)
|
1999-07-07 22:52:57 +00:00
|
|
|
{
|
|
|
|
proto_item *pi;
|
|
|
|
va_list ap;
|
|
|
|
|
2000-05-31 05:09:07 +00:00
|
|
|
pi = proto_tree_add_notext(tree, tvb, start, length);
|
|
|
|
if (pi == NULL)
|
2000-03-12 04:48:32 +00:00
|
|
|
return(NULL);
|
1999-07-07 22:52:57 +00:00
|
|
|
|
2000-05-31 05:09:07 +00:00
|
|
|
va_start(ap, format);
|
|
|
|
proto_tree_set_representation(pi, format, ap);
|
|
|
|
va_end(ap);
|
1999-07-07 22:52:57 +00:00
|
|
|
|
|
|
|
return pi;
|
|
|
|
}
|
|
|
|
|
Convert IPX-and-friend dissectors in packet-ipx.c to use
tvbuffs.
In doing so, I realied that my recommendation for using
tvb_new_subset(pi.compat_top_tvb, -1, -1) was incorrect, because
some dissectors (ethernet!) change pi.len and pi.cap_len. So, I have
to take those two variables into account instead of using -1 and -1.
So, I provide a macro called tvb_create_from_top(offset), where
offset is the name of your offset variable. It is a wrapper around
tvb_new_subset().
I converted the lines that followed my suggestion to use
tvb_create_from_top().
In proto.c I added
proto_tree_add_debug_text(proto_tree*, const char*, ...)
It's much like proto_tree_add_text(), except that it takes no offset
or length; it's soley for temporarily putting debug text into the
proto_tree while debugging a dissector. In making sure that its
use is temporary, the funciton also prints the debug string to stdout
to remind the programmer that the debug code needs to be removed
before shipping the code.
svn path=/trunk/; revision=2068
2000-06-15 03:49:00 +00:00
|
|
|
/* Add a text-only node for debugging purposes. The caller doesn't need
|
|
|
|
* to worry about tvbuff, start, or length. Debug message gets sent to
|
|
|
|
* STDOUT, too */
|
|
|
|
proto_item *
|
|
|
|
proto_tree_add_debug_text(proto_tree *tree, const char *format, ...)
|
|
|
|
{
|
|
|
|
proto_item *pi;
|
|
|
|
va_list ap;
|
|
|
|
|
|
|
|
pi = proto_tree_add_notext(tree, NULL, 0, 0);
|
|
|
|
if (pi == NULL)
|
|
|
|
return(NULL);
|
|
|
|
|
|
|
|
va_start(ap, format);
|
|
|
|
proto_tree_set_representation(pi, format, ap);
|
|
|
|
vprintf(format, ap);
|
|
|
|
va_end(ap);
|
|
|
|
printf("\n");
|
|
|
|
|
|
|
|
return pi;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2000-05-31 05:09:07 +00:00
|
|
|
static guint32
|
|
|
|
get_uint_value(tvbuff_t *tvb, gint offset, gint length, gboolean little_endian)
|
|
|
|
{
|
|
|
|
guint32 value;
|
|
|
|
|
|
|
|
switch (length) {
|
|
|
|
|
|
|
|
case 1:
|
|
|
|
value = tvb_get_guint8(tvb, offset);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 2:
|
|
|
|
value = little_endian ? tvb_get_letohs(tvb, offset)
|
|
|
|
: tvb_get_ntohs(tvb, offset);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 3:
|
|
|
|
value = little_endian ? tvb_get_letoh24(tvb, offset)
|
|
|
|
: tvb_get_ntoh24(tvb, offset);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 4:
|
|
|
|
value = little_endian ? tvb_get_letohl(tvb, offset)
|
|
|
|
: tvb_get_ntohl(tvb, offset);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
g_assert_not_reached();
|
|
|
|
value = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gint32
|
|
|
|
get_int_value(tvbuff_t *tvb, gint offset, gint length, gboolean little_endian)
|
|
|
|
{
|
|
|
|
gint32 value;
|
|
|
|
|
|
|
|
switch (length) {
|
|
|
|
|
|
|
|
case 1:
|
|
|
|
value = (gint8)tvb_get_guint8(tvb, offset);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 2:
|
|
|
|
value = (gint16) (little_endian ? tvb_get_letohs(tvb, offset)
|
|
|
|
: tvb_get_ntohs(tvb, offset));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 3:
|
|
|
|
value = little_endian ? tvb_get_letoh24(tvb, offset)
|
|
|
|
: tvb_get_ntoh24(tvb, offset);
|
|
|
|
if (value & 0x00800000) {
|
|
|
|
/* Sign bit is set; sign-extend it. */
|
|
|
|
value |= 0xFF000000;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 4:
|
|
|
|
value = little_endian ? tvb_get_letohl(tvb, offset)
|
|
|
|
: tvb_get_ntohl(tvb, offset);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
g_assert_not_reached();
|
|
|
|
value = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Add an item to a proto_tree, using the text label registered to that item;
|
|
|
|
the item is extracted from the tvbuff handed to it. */
|
|
|
|
proto_item *
|
|
|
|
proto_tree_add_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
|
|
|
|
gint start, gint length, gboolean little_endian)
|
1999-07-07 22:52:57 +00:00
|
|
|
{
|
|
|
|
proto_item *pi;
|
2000-03-12 04:48:32 +00:00
|
|
|
field_info *new_fi;
|
2000-05-31 05:09:07 +00:00
|
|
|
guint32 value;
|
2000-03-12 04:48:32 +00:00
|
|
|
|
2000-05-31 05:09:07 +00:00
|
|
|
pi = proto_tree_add_pi(tree, hfindex, tvb, start, length, &new_fi);
|
|
|
|
if (pi == NULL)
|
2000-03-12 04:48:32 +00:00
|
|
|
return(NULL);
|
1999-07-07 22:52:57 +00:00
|
|
|
|
2000-05-31 05:09:07 +00:00
|
|
|
switch(new_fi->hfinfo->type) {
|
|
|
|
case FT_NONE:
|
|
|
|
/* no value to set for FT_NONE */
|
|
|
|
break;
|
|
|
|
|
|
|
|
case FT_BYTES:
|
|
|
|
proto_tree_set_bytes_tvb(new_fi, tvb, start, length);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case FT_BOOLEAN:
|
|
|
|
proto_tree_set_boolean(new_fi,
|
|
|
|
get_uint_value(tvb, start, length, little_endian));
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* XXX - make these just FT_UINT? */
|
|
|
|
case FT_UINT8:
|
|
|
|
case FT_UINT16:
|
|
|
|
case FT_UINT24:
|
|
|
|
case FT_UINT32:
|
|
|
|
proto_tree_set_uint(new_fi,
|
|
|
|
get_uint_value(tvb, start, length, little_endian));
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* XXX - make these just FT_INT? */
|
|
|
|
case FT_INT8:
|
|
|
|
case FT_INT16:
|
|
|
|
case FT_INT24:
|
|
|
|
case FT_INT32:
|
|
|
|
proto_tree_set_int(new_fi,
|
|
|
|
get_int_value(tvb, start, length, little_endian));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case FT_IPv4:
|
|
|
|
g_assert(length == 4);
|
|
|
|
tvb_memcpy(tvb, (guint8 *)&value, start, 4);
|
|
|
|
proto_tree_set_ipv4(new_fi, value);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case FT_IPXNET:
|
Convert IPX-and-friend dissectors in packet-ipx.c to use
tvbuffs.
In doing so, I realied that my recommendation for using
tvb_new_subset(pi.compat_top_tvb, -1, -1) was incorrect, because
some dissectors (ethernet!) change pi.len and pi.cap_len. So, I have
to take those two variables into account instead of using -1 and -1.
So, I provide a macro called tvb_create_from_top(offset), where
offset is the name of your offset variable. It is a wrapper around
tvb_new_subset().
I converted the lines that followed my suggestion to use
tvb_create_from_top().
In proto.c I added
proto_tree_add_debug_text(proto_tree*, const char*, ...)
It's much like proto_tree_add_text(), except that it takes no offset
or length; it's soley for temporarily putting debug text into the
proto_tree while debugging a dissector. In making sure that its
use is temporary, the funciton also prints the debug string to stdout
to remind the programmer that the debug code needs to be removed
before shipping the code.
svn path=/trunk/; revision=2068
2000-06-15 03:49:00 +00:00
|
|
|
g_assert(length == 4);
|
|
|
|
proto_tree_set_ipxnet(new_fi,
|
|
|
|
get_uint_value(tvb, start, 4, FALSE));
|
2000-05-31 05:09:07 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case FT_IPv6:
|
|
|
|
g_assert(length == 16);
|
|
|
|
proto_tree_set_ipv6_tvb(new_fi, tvb, start);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case FT_ETHER:
|
|
|
|
g_assert(length == 6);
|
|
|
|
proto_tree_set_ether_tvb(new_fi, tvb, start);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case FT_STRING:
|
|
|
|
/* This g_strdup'ed memory is freed in proto_tree_free_node() */
|
|
|
|
proto_tree_set_string_tvb(new_fi, tvb, start, length);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
g_error("new_fi->hfinfo->type %d not handled\n", new_fi->hfinfo->type);
|
|
|
|
g_assert_not_reached();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return pi;
|
|
|
|
}
|
|
|
|
|
|
|
|
proto_item *
|
|
|
|
proto_tree_add_item_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb,
|
|
|
|
gint start, gint length, gboolean little_endian)
|
|
|
|
{
|
|
|
|
proto_item *pi;
|
|
|
|
field_info *fi;
|
|
|
|
|
|
|
|
pi = proto_tree_add_item(tree, hfindex, tvb, start, length, little_endian);
|
|
|
|
if (pi == NULL)
|
|
|
|
return(NULL);
|
|
|
|
|
|
|
|
fi = (field_info*) (((GNode*)pi)->data);
|
|
|
|
fi->visible = FALSE;
|
1999-07-07 22:52:57 +00:00
|
|
|
|
|
|
|
return pi;
|
|
|
|
}
|
|
|
|
|
2000-03-12 04:48:32 +00:00
|
|
|
|
|
|
|
/* Add a FT_NONE to a proto_tree */
|
|
|
|
proto_item *
|
2000-05-11 08:18:09 +00:00
|
|
|
proto_tree_add_protocol_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
|
|
|
|
gint length, const char *format, ...)
|
2000-03-12 04:48:32 +00:00
|
|
|
{
|
|
|
|
proto_item *pi;
|
|
|
|
va_list ap;
|
|
|
|
header_field_info *hfinfo;
|
|
|
|
|
|
|
|
if (!tree)
|
|
|
|
return (NULL);
|
|
|
|
|
2000-04-04 02:34:40 +00:00
|
|
|
hfinfo = proto_registrar_get_nth(hfindex);
|
2000-03-12 04:48:32 +00:00
|
|
|
g_assert(hfinfo->type == FT_NONE);
|
|
|
|
|
2000-05-31 05:09:07 +00:00
|
|
|
pi = proto_tree_add_pi(tree, hfindex, tvb, start, length, NULL);
|
|
|
|
|
2000-03-12 04:48:32 +00:00
|
|
|
va_start(ap, format);
|
2000-05-31 05:09:07 +00:00
|
|
|
proto_tree_set_representation(pi, format, ap);
|
2000-03-12 04:48:32 +00:00
|
|
|
va_end(ap);
|
|
|
|
|
2000-05-31 05:09:07 +00:00
|
|
|
/* no value to set for FT_NONE */
|
|
|
|
|
2000-03-12 04:48:32 +00:00
|
|
|
return pi;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Add a FT_BYTES to a proto_tree */
|
|
|
|
proto_item *
|
2000-05-31 05:09:07 +00:00
|
|
|
proto_tree_add_bytes(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
|
|
|
|
gint length, const guint8 *start_ptr)
|
2000-03-12 04:48:32 +00:00
|
|
|
{
|
|
|
|
proto_item *pi;
|
|
|
|
field_info *new_fi;
|
|
|
|
header_field_info *hfinfo;
|
|
|
|
|
|
|
|
if (!tree)
|
|
|
|
return (NULL);
|
|
|
|
|
2000-04-04 02:34:40 +00:00
|
|
|
hfinfo = proto_registrar_get_nth(hfindex);
|
2000-03-12 04:48:32 +00:00
|
|
|
g_assert(hfinfo->type == FT_BYTES);
|
|
|
|
|
2000-05-31 05:09:07 +00:00
|
|
|
pi = proto_tree_add_pi(tree, hfindex, tvb, start, length, &new_fi);
|
2000-03-12 04:48:32 +00:00
|
|
|
proto_tree_set_bytes(new_fi, start_ptr, length);
|
2000-05-31 05:09:07 +00:00
|
|
|
|
|
|
|
return pi;
|
|
|
|
}
|
|
|
|
|
|
|
|
proto_item *
|
|
|
|
proto_tree_add_bytes_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
|
|
|
|
gint length, const guint8 *start_ptr)
|
|
|
|
{
|
|
|
|
proto_item *pi;
|
|
|
|
field_info *fi;
|
|
|
|
|
|
|
|
pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length, start_ptr);
|
|
|
|
if (pi == NULL)
|
|
|
|
return (NULL);
|
|
|
|
|
|
|
|
fi = (field_info*) (((GNode*)pi)->data);
|
|
|
|
fi->visible = FALSE;
|
|
|
|
|
|
|
|
return pi;
|
|
|
|
}
|
|
|
|
|
|
|
|
proto_item *
|
|
|
|
proto_tree_add_bytes_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
|
|
|
|
gint length, const guint8 *start_ptr, const char *format, ...)
|
|
|
|
{
|
|
|
|
proto_item *pi;
|
|
|
|
va_list ap;
|
|
|
|
|
|
|
|
pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length, start_ptr);
|
|
|
|
if (pi == NULL)
|
|
|
|
return (NULL);
|
|
|
|
|
|
|
|
va_start(ap, format);
|
|
|
|
proto_tree_set_representation(pi, format, ap);
|
2000-03-12 04:48:32 +00:00
|
|
|
va_end(ap);
|
|
|
|
|
|
|
|
return pi;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Set the FT_BYTES value */
|
|
|
|
static void
|
2000-03-14 06:03:26 +00:00
|
|
|
proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length)
|
2000-03-12 04:48:32 +00:00
|
|
|
{
|
2000-04-04 17:07:07 +00:00
|
|
|
g_assert(start_ptr != NULL);
|
2000-05-19 04:54:36 +00:00
|
|
|
|
|
|
|
if (length > 0) {
|
|
|
|
/* This g_malloc'ed memory is freed in
|
|
|
|
proto_tree_free_node() */
|
|
|
|
fi->value.bytes = g_malloc(length);
|
|
|
|
memcpy(fi->value.bytes, start_ptr, length);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
fi->value.bytes = NULL;
|
|
|
|
}
|
2000-03-12 04:48:32 +00:00
|
|
|
}
|
|
|
|
|
2000-05-31 05:09:07 +00:00
|
|
|
static void
|
|
|
|
proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length)
|
|
|
|
{
|
|
|
|
if (length > 0) {
|
|
|
|
/* This g_malloc'ed memory is freed in
|
|
|
|
proto_tree_free_node() */
|
|
|
|
fi->value.bytes = tvb_memdup(tvb, offset, length);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
fi->value.bytes = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2000-03-12 04:48:32 +00:00
|
|
|
/* Add a FT_*TIME to a proto_tree */
|
|
|
|
proto_item *
|
2000-05-31 05:09:07 +00:00
|
|
|
proto_tree_add_time(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
|
|
|
|
struct timeval *value_ptr)
|
2000-03-12 04:48:32 +00:00
|
|
|
{
|
|
|
|
proto_item *pi;
|
|
|
|
field_info *new_fi;
|
|
|
|
header_field_info *hfinfo;
|
|
|
|
|
|
|
|
if (!tree)
|
|
|
|
return (NULL);
|
|
|
|
|
2000-04-04 02:34:40 +00:00
|
|
|
hfinfo = proto_registrar_get_nth(hfindex);
|
2000-03-12 04:48:32 +00:00
|
|
|
g_assert(hfinfo->type == FT_ABSOLUTE_TIME ||
|
|
|
|
hfinfo->type == FT_RELATIVE_TIME);
|
|
|
|
|
2000-05-31 05:09:07 +00:00
|
|
|
pi = proto_tree_add_pi(tree, hfindex, tvb, start, length, &new_fi);
|
2000-03-12 04:48:32 +00:00
|
|
|
proto_tree_set_time(new_fi, value_ptr);
|
2000-05-31 05:09:07 +00:00
|
|
|
|
|
|
|
return pi;
|
|
|
|
}
|
|
|
|
|
|
|
|
proto_item *
|
|
|
|
proto_tree_add_time_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
|
|
|
|
struct timeval *value_ptr)
|
|
|
|
{
|
|
|
|
proto_item *pi;
|
|
|
|
field_info *fi;
|
|
|
|
|
|
|
|
pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
|
|
|
|
if (pi == NULL)
|
|
|
|
return (NULL);
|
|
|
|
|
|
|
|
fi = (field_info*) (((GNode*)pi)->data);
|
|
|
|
fi->visible = FALSE;
|
|
|
|
|
|
|
|
return pi;
|
|
|
|
}
|
|
|
|
|
|
|
|
proto_item *
|
|
|
|
proto_tree_add_time_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
|
|
|
|
struct timeval *value_ptr, const char *format, ...)
|
|
|
|
{
|
|
|
|
proto_item *pi;
|
|
|
|
va_list ap;
|
|
|
|
|
|
|
|
pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
|
|
|
|
if (pi == NULL)
|
|
|
|
return (NULL);
|
|
|
|
|
|
|
|
va_start(ap, format);
|
|
|
|
proto_tree_set_representation(pi, format, ap);
|
2000-03-12 04:48:32 +00:00
|
|
|
va_end(ap);
|
|
|
|
|
|
|
|
return pi;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Set the FT_*TIME value */
|
|
|
|
static void
|
|
|
|
proto_tree_set_time(field_info *fi, struct timeval *value_ptr)
|
|
|
|
{
|
|
|
|
memcpy(&fi->value.time, value_ptr, sizeof(struct timeval));
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Add a FT_IPXNET to a proto_tree */
|
|
|
|
proto_item *
|
2000-05-31 05:09:07 +00:00
|
|
|
proto_tree_add_ipxnet(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
|
|
|
|
guint32 value)
|
2000-03-12 04:48:32 +00:00
|
|
|
{
|
|
|
|
proto_item *pi;
|
|
|
|
field_info *new_fi;
|
|
|
|
header_field_info *hfinfo;
|
|
|
|
|
|
|
|
if (!tree)
|
|
|
|
return (NULL);
|
|
|
|
|
2000-04-04 02:34:40 +00:00
|
|
|
hfinfo = proto_registrar_get_nth(hfindex);
|
2000-03-12 04:48:32 +00:00
|
|
|
g_assert(hfinfo->type == FT_IPXNET);
|
|
|
|
|
2000-05-31 05:09:07 +00:00
|
|
|
pi = proto_tree_add_pi(tree, hfindex, tvb, start, length, &new_fi);
|
2000-03-12 04:48:32 +00:00
|
|
|
proto_tree_set_ipxnet(new_fi, value);
|
2000-05-31 05:09:07 +00:00
|
|
|
|
|
|
|
return pi;
|
|
|
|
}
|
|
|
|
|
|
|
|
proto_item *
|
|
|
|
proto_tree_add_ipxnet_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
|
|
|
|
guint32 value)
|
|
|
|
{
|
|
|
|
proto_item *pi;
|
|
|
|
field_info *fi;
|
|
|
|
|
|
|
|
pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
|
|
|
|
if (pi == NULL)
|
|
|
|
return (NULL);
|
|
|
|
|
|
|
|
fi = (field_info*) (((GNode*)pi)->data);
|
|
|
|
fi->visible = FALSE;
|
|
|
|
|
|
|
|
return pi;
|
|
|
|
}
|
|
|
|
|
|
|
|
proto_item *
|
|
|
|
proto_tree_add_ipxnet_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
|
|
|
|
guint32 value, const char *format, ...)
|
|
|
|
{
|
|
|
|
proto_item *pi;
|
|
|
|
va_list ap;
|
|
|
|
|
|
|
|
pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
|
|
|
|
if (pi == NULL)
|
|
|
|
return (NULL);
|
|
|
|
|
|
|
|
va_start(ap, format);
|
|
|
|
proto_tree_set_representation(pi, format, ap);
|
2000-03-12 04:48:32 +00:00
|
|
|
va_end(ap);
|
|
|
|
|
|
|
|
return pi;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Set the FT_IPXNET value */
|
|
|
|
static void
|
|
|
|
proto_tree_set_ipxnet(field_info *fi, guint32 value)
|
|
|
|
{
|
|
|
|
fi->value.numeric = value;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Add a FT_IPv4 to a proto_tree */
|
|
|
|
proto_item *
|
2000-05-31 05:09:07 +00:00
|
|
|
proto_tree_add_ipv4(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
|
|
|
|
guint32 value)
|
2000-03-12 04:48:32 +00:00
|
|
|
{
|
|
|
|
proto_item *pi;
|
|
|
|
field_info *new_fi;
|
|
|
|
header_field_info *hfinfo;
|
|
|
|
|
|
|
|
if (!tree)
|
|
|
|
return (NULL);
|
|
|
|
|
2000-04-04 02:34:40 +00:00
|
|
|
hfinfo = proto_registrar_get_nth(hfindex);
|
2000-03-12 04:48:32 +00:00
|
|
|
g_assert(hfinfo->type == FT_IPv4);
|
|
|
|
|
2000-05-31 05:09:07 +00:00
|
|
|
pi = proto_tree_add_pi(tree, hfindex, tvb, start, length, &new_fi);
|
2000-03-12 04:48:32 +00:00
|
|
|
proto_tree_set_ipv4(new_fi, value);
|
2000-05-31 05:09:07 +00:00
|
|
|
|
|
|
|
return pi;
|
|
|
|
}
|
|
|
|
|
|
|
|
proto_item *
|
|
|
|
proto_tree_add_ipv4_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
|
|
|
|
guint32 value)
|
|
|
|
{
|
|
|
|
proto_item *pi;
|
|
|
|
field_info *fi;
|
|
|
|
|
|
|
|
pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
|
|
|
|
if (pi == NULL)
|
|
|
|
return (NULL);
|
|
|
|
|
|
|
|
fi = (field_info*) (((GNode*)pi)->data);
|
|
|
|
fi->visible = FALSE;
|
|
|
|
|
|
|
|
return pi;
|
|
|
|
}
|
|
|
|
|
|
|
|
proto_item *
|
|
|
|
proto_tree_add_ipv4_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
|
|
|
|
guint32 value, const char *format, ...)
|
|
|
|
{
|
|
|
|
proto_item *pi;
|
|
|
|
va_list ap;
|
|
|
|
|
|
|
|
pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
|
|
|
|
if (pi == NULL)
|
|
|
|
return (NULL);
|
|
|
|
|
|
|
|
va_start(ap, format);
|
|
|
|
proto_tree_set_representation(pi, format, ap);
|
2000-03-12 04:48:32 +00:00
|
|
|
va_end(ap);
|
|
|
|
|
|
|
|
return pi;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Set the FT_IPv4 value */
|
|
|
|
static void
|
|
|
|
proto_tree_set_ipv4(field_info *fi, guint32 value)
|
|
|
|
{
|
|
|
|
ipv4_addr_set_net_order_addr(&(fi->value.ipv4), value);
|
|
|
|
ipv4_addr_set_netmask_bits(&(fi->value.ipv4), 32);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Add a FT_IPv6 to a proto_tree */
|
|
|
|
proto_item *
|
2000-05-31 05:09:07 +00:00
|
|
|
proto_tree_add_ipv6(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
|
|
|
|
const guint8* value_ptr)
|
2000-03-12 04:48:32 +00:00
|
|
|
{
|
|
|
|
proto_item *pi;
|
|
|
|
field_info *new_fi;
|
|
|
|
header_field_info *hfinfo;
|
|
|
|
|
|
|
|
if (!tree)
|
|
|
|
return (NULL);
|
|
|
|
|
2000-04-04 02:34:40 +00:00
|
|
|
hfinfo = proto_registrar_get_nth(hfindex);
|
2000-03-12 04:48:32 +00:00
|
|
|
g_assert(hfinfo->type == FT_IPv6);
|
|
|
|
|
2000-05-31 05:09:07 +00:00
|
|
|
pi = proto_tree_add_pi(tree, hfindex, tvb, start, length, &new_fi);
|
2000-03-12 04:48:32 +00:00
|
|
|
proto_tree_set_ipv6(new_fi, value_ptr);
|
2000-05-31 05:09:07 +00:00
|
|
|
|
|
|
|
return pi;
|
|
|
|
}
|
|
|
|
|
|
|
|
proto_item *
|
|
|
|
proto_tree_add_ipv6_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
|
|
|
|
const guint8* value_ptr)
|
|
|
|
{
|
|
|
|
proto_item *pi;
|
|
|
|
field_info *fi;
|
|
|
|
|
|
|
|
pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
|
|
|
|
if (pi == NULL)
|
|
|
|
return (NULL);
|
|
|
|
|
|
|
|
fi = (field_info*) (((GNode*)pi)->data);
|
|
|
|
fi->visible = FALSE;
|
|
|
|
|
|
|
|
return pi;
|
|
|
|
}
|
|
|
|
|
|
|
|
proto_item *
|
|
|
|
proto_tree_add_ipv6_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
|
|
|
|
const guint8* value_ptr, const char *format, ...)
|
|
|
|
{
|
|
|
|
proto_item *pi;
|
|
|
|
va_list ap;
|
|
|
|
|
|
|
|
pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
|
|
|
|
if (pi == NULL)
|
|
|
|
return (NULL);
|
|
|
|
|
|
|
|
va_start(ap, format);
|
|
|
|
proto_tree_set_representation(pi, format, ap);
|
2000-03-12 04:48:32 +00:00
|
|
|
va_end(ap);
|
|
|
|
|
|
|
|
return pi;
|
|
|
|
}
|
|
|
|
|
2000-05-31 05:09:07 +00:00
|
|
|
/* Set the FT_IPv6 value */
|
2000-03-12 04:48:32 +00:00
|
|
|
static void
|
2000-05-31 05:09:07 +00:00
|
|
|
proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr)
|
2000-03-12 04:48:32 +00:00
|
|
|
{
|
|
|
|
memcpy(fi->value.ipv6, value_ptr, 16);
|
|
|
|
}
|
|
|
|
|
2000-05-31 05:09:07 +00:00
|
|
|
static void
|
|
|
|
proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start)
|
|
|
|
{
|
|
|
|
tvb_memcpy(tvb, fi->value.ipv6, start, 16);
|
|
|
|
}
|
|
|
|
|
2000-03-12 04:48:32 +00:00
|
|
|
/* Add a FT_STRING to a proto_tree */
|
|
|
|
proto_item *
|
2000-05-31 05:09:07 +00:00
|
|
|
proto_tree_add_string(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
|
|
|
|
gint length, const char* value)
|
2000-03-12 04:48:32 +00:00
|
|
|
{
|
|
|
|
proto_item *pi;
|
|
|
|
field_info *new_fi;
|
|
|
|
header_field_info *hfinfo;
|
|
|
|
|
|
|
|
if (!tree)
|
|
|
|
return (NULL);
|
|
|
|
|
2000-04-04 02:34:40 +00:00
|
|
|
hfinfo = proto_registrar_get_nth(hfindex);
|
2000-03-12 04:48:32 +00:00
|
|
|
g_assert(hfinfo->type == FT_STRING);
|
|
|
|
|
2000-05-31 05:09:07 +00:00
|
|
|
pi = proto_tree_add_pi(tree, hfindex, tvb, start, length, &new_fi);
|
2000-03-12 04:48:32 +00:00
|
|
|
proto_tree_set_string(new_fi, value);
|
2000-05-31 05:09:07 +00:00
|
|
|
|
|
|
|
return pi;
|
|
|
|
}
|
|
|
|
|
|
|
|
proto_item *
|
|
|
|
proto_tree_add_string_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
|
|
|
|
gint length, const char* value)
|
|
|
|
{
|
|
|
|
proto_item *pi;
|
|
|
|
field_info *fi;
|
|
|
|
|
|
|
|
pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
|
|
|
|
if (pi == NULL)
|
|
|
|
return (NULL);
|
|
|
|
|
|
|
|
fi = (field_info*) (((GNode*)pi)->data);
|
|
|
|
fi->visible = FALSE;
|
|
|
|
|
|
|
|
return pi;
|
|
|
|
}
|
|
|
|
|
|
|
|
proto_item *
|
|
|
|
proto_tree_add_string_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
|
|
|
|
gint length, const char* value, const char *format, ...)
|
|
|
|
{
|
|
|
|
proto_item *pi;
|
|
|
|
va_list ap;
|
|
|
|
|
|
|
|
pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
|
|
|
|
if (pi == NULL)
|
|
|
|
return (NULL);
|
|
|
|
|
|
|
|
va_start(ap, format);
|
|
|
|
proto_tree_set_representation(pi, format, ap);
|
2000-03-12 04:48:32 +00:00
|
|
|
va_end(ap);
|
|
|
|
|
|
|
|
return pi;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Set the FT_STRING value */
|
|
|
|
static void
|
2000-03-14 06:03:26 +00:00
|
|
|
proto_tree_set_string(field_info *fi, const char* value)
|
2000-03-12 04:48:32 +00:00
|
|
|
{
|
|
|
|
/* This g_strdup'ed memory is freed in proto_tree_free_node() */
|
|
|
|
fi->value.string = g_strdup(value);
|
|
|
|
}
|
|
|
|
|
2000-05-31 05:09:07 +00:00
|
|
|
static void
|
|
|
|
proto_tree_set_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
|
|
|
|
{
|
|
|
|
/* This g_strdup'ed memory is freed in proto_tree_free_node() */
|
|
|
|
fi->value.string = tvb_memdup(tvb, start, length);
|
|
|
|
}
|
|
|
|
|
2000-03-12 04:48:32 +00:00
|
|
|
/* Add a FT_ETHER to a proto_tree */
|
|
|
|
proto_item *
|
2000-05-31 05:09:07 +00:00
|
|
|
proto_tree_add_ether(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
|
|
|
|
const guint8* value)
|
2000-03-12 04:48:32 +00:00
|
|
|
{
|
|
|
|
proto_item *pi;
|
|
|
|
field_info *new_fi;
|
|
|
|
header_field_info *hfinfo;
|
|
|
|
|
|
|
|
if (!tree)
|
|
|
|
return (NULL);
|
|
|
|
|
2000-04-04 02:34:40 +00:00
|
|
|
hfinfo = proto_registrar_get_nth(hfindex);
|
2000-03-12 04:48:32 +00:00
|
|
|
g_assert(hfinfo->type == FT_ETHER);
|
|
|
|
|
2000-05-31 05:09:07 +00:00
|
|
|
pi = proto_tree_add_pi(tree, hfindex, tvb, start, length, &new_fi);
|
2000-03-12 04:48:32 +00:00
|
|
|
proto_tree_set_ether(new_fi, value);
|
2000-05-31 05:09:07 +00:00
|
|
|
|
|
|
|
return pi;
|
|
|
|
}
|
|
|
|
|
|
|
|
proto_item *
|
|
|
|
proto_tree_add_ether_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
|
|
|
|
const guint8* value)
|
|
|
|
{
|
|
|
|
proto_item *pi;
|
|
|
|
field_info *fi;
|
|
|
|
|
|
|
|
pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
|
|
|
|
if (pi == NULL)
|
|
|
|
return (NULL);
|
|
|
|
|
|
|
|
fi = (field_info*) (((GNode*)pi)->data);
|
|
|
|
fi->visible = FALSE;
|
|
|
|
|
|
|
|
return pi;
|
|
|
|
}
|
|
|
|
|
|
|
|
proto_item *
|
|
|
|
proto_tree_add_ether_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
|
|
|
|
const guint8* value, const char *format, ...)
|
|
|
|
{
|
|
|
|
proto_item *pi;
|
|
|
|
va_list ap;
|
|
|
|
|
|
|
|
pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
|
|
|
|
if (pi == NULL)
|
|
|
|
return (NULL);
|
|
|
|
|
|
|
|
va_start(ap, format);
|
|
|
|
proto_tree_set_representation(pi, format, ap);
|
2000-03-12 04:48:32 +00:00
|
|
|
va_end(ap);
|
|
|
|
|
|
|
|
return pi;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Set the FT_ETHER value */
|
|
|
|
static void
|
2000-05-31 05:09:07 +00:00
|
|
|
proto_tree_set_ether(field_info *fi, const guint8* value)
|
2000-03-12 04:48:32 +00:00
|
|
|
{
|
|
|
|
memcpy(fi->value.ether, value, 6);
|
|
|
|
}
|
|
|
|
|
2000-05-31 05:09:07 +00:00
|
|
|
static void
|
|
|
|
proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start)
|
|
|
|
{
|
|
|
|
tvb_memcpy(tvb, fi->value.ether, start, 6);
|
|
|
|
}
|
|
|
|
|
2000-03-12 04:48:32 +00:00
|
|
|
/* Add a FT_BOOLEAN to a proto_tree */
|
|
|
|
proto_item *
|
2000-05-31 05:09:07 +00:00
|
|
|
proto_tree_add_boolean(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
|
|
|
|
guint32 value)
|
2000-03-12 04:48:32 +00:00
|
|
|
{
|
|
|
|
proto_item *pi;
|
|
|
|
field_info *new_fi;
|
|
|
|
header_field_info *hfinfo;
|
|
|
|
|
|
|
|
if (!tree)
|
|
|
|
return (NULL);
|
|
|
|
|
2000-04-04 02:34:40 +00:00
|
|
|
hfinfo = proto_registrar_get_nth(hfindex);
|
2000-03-12 04:48:32 +00:00
|
|
|
g_assert(hfinfo->type == FT_BOOLEAN);
|
|
|
|
|
2000-05-31 05:09:07 +00:00
|
|
|
pi = proto_tree_add_pi(tree, hfindex, tvb, start, length, &new_fi);
|
2000-03-12 04:48:32 +00:00
|
|
|
proto_tree_set_boolean(new_fi, value);
|
2000-05-31 05:09:07 +00:00
|
|
|
|
|
|
|
return pi;
|
|
|
|
}
|
|
|
|
|
|
|
|
proto_item *
|
|
|
|
proto_tree_add_boolean_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
|
|
|
|
guint32 value)
|
|
|
|
{
|
|
|
|
proto_item *pi;
|
|
|
|
field_info *fi;
|
|
|
|
|
|
|
|
pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
|
|
|
|
if (pi == NULL)
|
|
|
|
return (NULL);
|
|
|
|
|
|
|
|
fi = (field_info*) (((GNode*)pi)->data);
|
|
|
|
fi->visible = FALSE;
|
|
|
|
|
|
|
|
return pi;
|
|
|
|
}
|
|
|
|
|
|
|
|
proto_item *
|
|
|
|
proto_tree_add_boolean_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
|
|
|
|
guint32 value, const char *format, ...)
|
|
|
|
{
|
|
|
|
proto_item *pi;
|
|
|
|
va_list ap;
|
|
|
|
|
|
|
|
pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
|
|
|
|
if (pi == NULL)
|
|
|
|
return (NULL);
|
|
|
|
|
|
|
|
va_start(ap, format);
|
|
|
|
proto_tree_set_representation(pi, format, ap);
|
2000-03-12 04:48:32 +00:00
|
|
|
va_end(ap);
|
|
|
|
|
|
|
|
return pi;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Set the FT_BOOLEAN value */
|
|
|
|
static void
|
|
|
|
proto_tree_set_boolean(field_info *fi, guint32 value)
|
|
|
|
{
|
2000-04-11 16:07:40 +00:00
|
|
|
proto_tree_set_uint(fi, value);
|
2000-03-12 04:48:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Add a FT_DOUBLE to a proto_tree */
|
|
|
|
proto_item *
|
2000-05-31 05:09:07 +00:00
|
|
|
proto_tree_add_double(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
|
|
|
|
double value)
|
2000-03-12 04:48:32 +00:00
|
|
|
{
|
|
|
|
proto_item *pi;
|
|
|
|
field_info *new_fi;
|
|
|
|
header_field_info *hfinfo;
|
|
|
|
|
|
|
|
if (!tree)
|
|
|
|
return (NULL);
|
|
|
|
|
2000-04-04 02:34:40 +00:00
|
|
|
hfinfo = proto_registrar_get_nth(hfindex);
|
2000-03-12 04:48:32 +00:00
|
|
|
g_assert(hfinfo->type == FT_DOUBLE);
|
|
|
|
|
2000-05-31 05:09:07 +00:00
|
|
|
pi = proto_tree_add_pi(tree, hfindex, tvb, start, length, &new_fi);
|
2000-03-12 04:48:32 +00:00
|
|
|
proto_tree_set_double(new_fi, value);
|
2000-05-31 05:09:07 +00:00
|
|
|
|
|
|
|
return pi;
|
|
|
|
}
|
|
|
|
|
|
|
|
proto_item *
|
|
|
|
proto_tree_add_double_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
|
|
|
|
double value)
|
|
|
|
{
|
|
|
|
proto_item *pi;
|
|
|
|
field_info *fi;
|
|
|
|
|
|
|
|
pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
|
|
|
|
if (pi == NULL)
|
|
|
|
return (NULL);
|
|
|
|
|
|
|
|
fi = (field_info*) (((GNode*)pi)->data);
|
|
|
|
fi->visible = FALSE;
|
|
|
|
|
|
|
|
return pi;
|
|
|
|
}
|
|
|
|
|
|
|
|
proto_item *
|
|
|
|
proto_tree_add_double_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
|
|
|
|
double value, const char *format, ...)
|
|
|
|
{
|
|
|
|
proto_item *pi;
|
|
|
|
va_list ap;
|
|
|
|
|
|
|
|
pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
|
|
|
|
if (pi == NULL)
|
|
|
|
return (NULL);
|
|
|
|
|
|
|
|
va_start(ap, format);
|
|
|
|
proto_tree_set_representation(pi, format, ap);
|
2000-03-12 04:48:32 +00:00
|
|
|
va_end(ap);
|
|
|
|
|
|
|
|
return pi;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Set the FT_DOUBLE value */
|
|
|
|
static void
|
|
|
|
proto_tree_set_double(field_info *fi, double value)
|
|
|
|
{
|
|
|
|
fi->value.floating = value;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Add any FT_UINT* to a proto_tree */
|
|
|
|
proto_item *
|
2000-05-31 05:09:07 +00:00
|
|
|
proto_tree_add_uint(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
|
|
|
|
guint32 value)
|
2000-03-12 04:48:32 +00:00
|
|
|
{
|
2000-03-14 06:03:26 +00:00
|
|
|
proto_item *pi = NULL;
|
2000-03-12 04:48:32 +00:00
|
|
|
field_info *new_fi;
|
|
|
|
header_field_info *hfinfo;
|
|
|
|
|
|
|
|
if (!tree)
|
|
|
|
return (NULL);
|
|
|
|
|
2000-04-04 02:34:40 +00:00
|
|
|
hfinfo = proto_registrar_get_nth(hfindex);
|
2000-03-12 04:48:32 +00:00
|
|
|
switch(hfinfo->type) {
|
|
|
|
case FT_UINT8:
|
|
|
|
case FT_UINT16:
|
|
|
|
case FT_UINT24:
|
|
|
|
case FT_UINT32:
|
2000-05-11 08:18:09 +00:00
|
|
|
pi = proto_tree_add_pi(tree, hfindex, tvb, start, length,
|
2000-05-31 05:09:07 +00:00
|
|
|
&new_fi);
|
2000-03-12 04:48:32 +00:00
|
|
|
proto_tree_set_uint(new_fi, value);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
g_assert_not_reached();
|
|
|
|
}
|
|
|
|
|
|
|
|
return pi;
|
|
|
|
}
|
|
|
|
|
2000-05-31 05:09:07 +00:00
|
|
|
proto_item *
|
|
|
|
proto_tree_add_uint_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
|
|
|
|
guint32 value)
|
|
|
|
{
|
|
|
|
proto_item *pi;
|
|
|
|
field_info *fi;
|
|
|
|
|
|
|
|
pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
|
|
|
|
if (pi == NULL)
|
|
|
|
return (NULL);
|
|
|
|
|
|
|
|
fi = (field_info*) (((GNode*)pi)->data);
|
|
|
|
fi->visible = FALSE;
|
|
|
|
|
|
|
|
return pi;
|
|
|
|
}
|
|
|
|
|
|
|
|
proto_item *
|
|
|
|
proto_tree_add_uint_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
|
|
|
|
guint32 value, const char *format, ...)
|
|
|
|
{
|
|
|
|
proto_item *pi;
|
|
|
|
va_list ap;
|
|
|
|
|
|
|
|
pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
|
|
|
|
if (pi == NULL)
|
|
|
|
return (NULL);
|
|
|
|
|
|
|
|
va_start(ap, format);
|
|
|
|
proto_tree_set_representation(pi, format, ap);
|
|
|
|
va_end(ap);
|
|
|
|
|
|
|
|
return pi;
|
|
|
|
}
|
|
|
|
|
2000-03-12 04:48:32 +00:00
|
|
|
/* Set the FT_UINT* value */
|
|
|
|
static void
|
|
|
|
proto_tree_set_uint(field_info *fi, guint32 value)
|
|
|
|
{
|
|
|
|
header_field_info *hfinfo;
|
|
|
|
|
|
|
|
hfinfo = fi->hfinfo;
|
|
|
|
fi->value.numeric = value;
|
|
|
|
if (hfinfo->bitmask) {
|
|
|
|
/* Mask out irrelevant portions */
|
|
|
|
fi->value.numeric &= hfinfo->bitmask;
|
|
|
|
|
|
|
|
/* Shift bits */
|
|
|
|
if (hfinfo->bitshift > 0) {
|
|
|
|
fi->value.numeric >>= hfinfo->bitshift;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2000-04-25 21:43:50 +00:00
|
|
|
/* Add any FT_INT* to a proto_tree */
|
|
|
|
proto_item *
|
2000-05-31 05:09:07 +00:00
|
|
|
proto_tree_add_int(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
|
|
|
|
gint32 value)
|
2000-04-25 21:43:50 +00:00
|
|
|
{
|
|
|
|
proto_item *pi = NULL;
|
|
|
|
field_info *new_fi;
|
|
|
|
header_field_info *hfinfo;
|
|
|
|
|
|
|
|
if (!tree)
|
|
|
|
return (NULL);
|
|
|
|
|
|
|
|
hfinfo = proto_registrar_get_nth(hfindex);
|
|
|
|
switch(hfinfo->type) {
|
|
|
|
case FT_INT8:
|
|
|
|
case FT_INT16:
|
|
|
|
case FT_INT24:
|
|
|
|
case FT_INT32:
|
2000-05-11 08:18:09 +00:00
|
|
|
pi = proto_tree_add_pi(tree, hfindex, tvb, start, length,
|
2000-05-31 05:09:07 +00:00
|
|
|
&new_fi);
|
2000-04-25 21:43:50 +00:00
|
|
|
proto_tree_set_int(new_fi, value);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
g_assert_not_reached();
|
|
|
|
}
|
|
|
|
|
|
|
|
return pi;
|
|
|
|
}
|
|
|
|
|
2000-05-31 05:09:07 +00:00
|
|
|
proto_item *
|
|
|
|
proto_tree_add_int_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
|
|
|
|
gint32 value)
|
|
|
|
{
|
|
|
|
proto_item *pi;
|
|
|
|
field_info *fi;
|
|
|
|
|
|
|
|
pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
|
|
|
|
if (pi == NULL)
|
|
|
|
return (NULL);
|
|
|
|
|
|
|
|
fi = (field_info*) (((GNode*)pi)->data);
|
|
|
|
fi->visible = FALSE;
|
|
|
|
|
|
|
|
return pi;
|
|
|
|
}
|
|
|
|
|
|
|
|
proto_item *
|
|
|
|
proto_tree_add_int_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
|
|
|
|
gint32 value, const char *format, ...)
|
|
|
|
{
|
|
|
|
proto_item *pi = NULL;
|
|
|
|
va_list ap;
|
|
|
|
|
|
|
|
pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
|
|
|
|
if (pi == NULL)
|
|
|
|
return (NULL);
|
|
|
|
|
|
|
|
va_start(ap, format);
|
|
|
|
proto_tree_set_representation(pi, format, ap);
|
|
|
|
va_end(ap);
|
|
|
|
|
|
|
|
return pi;
|
|
|
|
}
|
|
|
|
|
2000-04-25 21:43:50 +00:00
|
|
|
/* Set the FT_INT* value */
|
|
|
|
static void
|
|
|
|
proto_tree_set_int(field_info *fi, gint32 value)
|
|
|
|
{
|
|
|
|
header_field_info *hfinfo;
|
|
|
|
|
|
|
|
hfinfo = fi->hfinfo;
|
|
|
|
fi->value.numeric = (guint32) value;
|
|
|
|
if (hfinfo->bitmask) {
|
|
|
|
/* Mask out irrelevant portions */
|
|
|
|
fi->value.numeric &= hfinfo->bitmask;
|
|
|
|
|
|
|
|
/* Shift bits */
|
|
|
|
if (hfinfo->bitshift > 0) {
|
|
|
|
fi->value.numeric >>= hfinfo->bitshift;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2000-03-12 04:48:32 +00:00
|
|
|
|
|
|
|
|
|
|
|
/* Add a field_info struct to the proto_tree, encapsulating it in a GNode (proto_item) */
|
|
|
|
static proto_item *
|
|
|
|
proto_tree_add_node(proto_tree *tree, field_info *fi)
|
|
|
|
{
|
|
|
|
proto_item *pi;
|
1999-07-07 22:52:57 +00:00
|
|
|
|
|
|
|
pi = (proto_item*) g_node_new(fi);
|
|
|
|
g_node_append((GNode*)tree, (GNode*)pi);
|
|
|
|
|
2000-03-12 04:48:32 +00:00
|
|
|
return pi;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2000-05-31 05:09:07 +00:00
|
|
|
/* Generic way to allocate field_info and add to proto_tree.
|
2000-03-12 04:48:32 +00:00
|
|
|
* Sets *pfi to address of newly-allocated field_info struct, if pfi is non-NULL. */
|
|
|
|
static proto_item *
|
2000-05-11 08:18:09 +00:00
|
|
|
proto_tree_add_pi(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
|
2000-05-31 05:09:07 +00:00
|
|
|
field_info **pfi)
|
2000-03-12 04:48:32 +00:00
|
|
|
{
|
|
|
|
proto_item *pi;
|
|
|
|
field_info *fi;
|
|
|
|
|
|
|
|
if (!tree)
|
|
|
|
return(NULL);
|
|
|
|
|
2000-05-31 05:09:07 +00:00
|
|
|
fi = g_mem_chunk_alloc(gmc_field_info);
|
2000-03-12 04:48:32 +00:00
|
|
|
|
2000-05-31 05:09:07 +00:00
|
|
|
g_assert(hfindex >= 0 && hfindex < gpa_hfinfo->len);
|
|
|
|
fi->hfinfo = proto_registrar_get_nth(hfindex);
|
|
|
|
g_assert(fi->hfinfo != NULL);
|
|
|
|
fi->start = start;
|
|
|
|
if (tvb) {
|
|
|
|
fi->start += tvb_raw_offset(tvb);
|
|
|
|
}
|
|
|
|
fi->length = length;
|
|
|
|
fi->tree_type = ETT_NONE;
|
|
|
|
fi->visible = proto_tree_is_visible;
|
|
|
|
fi->representation = NULL;
|
2000-03-12 04:48:32 +00:00
|
|
|
|
|
|
|
pi = proto_tree_add_node(tree, fi);
|
|
|
|
|
|
|
|
if (pfi) {
|
|
|
|
*pfi = fi;
|
|
|
|
}
|
|
|
|
|
1999-07-07 22:52:57 +00:00
|
|
|
return pi;
|
|
|
|
}
|
|
|
|
|
2000-05-31 05:09:07 +00:00
|
|
|
/* Set representation of a proto_tree entry, if the protocol tree is to
|
|
|
|
be visible. */
|
|
|
|
static void
|
|
|
|
proto_tree_set_representation(proto_item *pi, const char *format, va_list ap)
|
|
|
|
{
|
|
|
|
field_info *fi = (field_info*) (((GNode*)pi)->data);
|
|
|
|
|
|
|
|
if (fi->visible) {
|
|
|
|
fi->representation = g_mem_chunk_alloc(gmc_item_labels);
|
|
|
|
vsnprintf(fi->representation, ITEM_LABEL_LENGTH, format, ap);
|
|
|
|
}
|
|
|
|
}
|
2000-03-12 04:48:32 +00:00
|
|
|
|
2000-01-22 04:59:55 +00:00
|
|
|
void
|
2000-03-07 05:54:52 +00:00
|
|
|
proto_item_set_text(proto_item *pi, const char *format, ...)
|
2000-01-22 04:59:55 +00:00
|
|
|
{
|
|
|
|
field_info *fi = (field_info*) (((GNode*)pi)->data);
|
|
|
|
va_list ap;
|
|
|
|
|
|
|
|
if (fi->representation)
|
|
|
|
g_mem_chunk_free(gmc_item_labels, fi->representation);
|
|
|
|
|
2000-03-07 05:54:52 +00:00
|
|
|
va_start(ap, format);
|
2000-05-31 05:09:07 +00:00
|
|
|
proto_tree_set_representation(pi, format, ap);
|
2000-01-22 04:59:55 +00:00
|
|
|
va_end(ap);
|
|
|
|
}
|
|
|
|
|
1999-07-07 22:52:57 +00:00
|
|
|
void
|
|
|
|
proto_item_set_len(proto_item *pi, gint length)
|
|
|
|
{
|
|
|
|
field_info *fi = (field_info*) (((GNode*)pi)->data);
|
|
|
|
fi->length = length;
|
|
|
|
}
|
|
|
|
|
|
|
|
proto_tree*
|
|
|
|
proto_tree_create_root(void)
|
|
|
|
{
|
|
|
|
return (proto_tree*) g_node_new(NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
proto_tree*
|
|
|
|
proto_item_add_subtree(proto_item *pi, gint idx) {
|
|
|
|
field_info *fi = (field_info*) (((GNode*)pi)->data);
|
1999-11-16 11:44:20 +00:00
|
|
|
g_assert(idx >= 0 && idx < num_tree_types);
|
1999-07-07 22:52:57 +00:00
|
|
|
fi->tree_type = idx;
|
|
|
|
return (proto_tree*) pi;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
proto_register_protocol(char *name, char *abbrev)
|
|
|
|
{
|
1999-10-12 06:21:15 +00:00
|
|
|
struct header_field_info *hfinfo;
|
|
|
|
|
|
|
|
/* Here we do allocate a new header_field_info struct */
|
|
|
|
hfinfo = g_mem_chunk_alloc(gmc_hfinfo);
|
|
|
|
hfinfo->name = name;
|
|
|
|
hfinfo->abbrev = abbrev;
|
|
|
|
hfinfo->type = FT_NONE;
|
|
|
|
hfinfo->strings = NULL;
|
|
|
|
hfinfo->bitmask = 0;
|
|
|
|
hfinfo->bitshift = 0;
|
|
|
|
hfinfo->blurb = "";
|
|
|
|
hfinfo->parent = -1; /* this field differentiates protos and fields */
|
|
|
|
|
|
|
|
return proto_register_field_init(hfinfo, hfinfo->parent);
|
1999-07-07 22:52:57 +00:00
|
|
|
}
|
|
|
|
|
1999-07-15 15:33:52 +00:00
|
|
|
/* for use with static arrays only, since we don't allocate our own copies
|
|
|
|
of the header_field_info struct contained withing the hf_register_info struct */
|
1999-07-07 22:52:57 +00:00
|
|
|
void
|
1999-07-15 15:33:52 +00:00
|
|
|
proto_register_field_array(int parent, hf_register_info *hf, int num_records)
|
1999-07-07 22:52:57 +00:00
|
|
|
{
|
|
|
|
int field_id, i;
|
1999-07-15 15:33:52 +00:00
|
|
|
hf_register_info *ptr = hf;
|
1999-07-07 22:52:57 +00:00
|
|
|
|
|
|
|
for (i = 0; i < num_records; i++, ptr++) {
|
1999-07-15 15:33:52 +00:00
|
|
|
field_id = proto_register_field_init(&ptr->hfinfo, parent);
|
1999-07-07 22:52:57 +00:00
|
|
|
*ptr->p_id = field_id;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-07-15 15:33:52 +00:00
|
|
|
static int
|
|
|
|
proto_register_field_init(header_field_info *hfinfo, int parent)
|
|
|
|
{
|
1999-10-12 06:21:15 +00:00
|
|
|
/* These types of fields are allowed to have value_strings or true_false_strings */
|
|
|
|
g_assert((hfinfo->strings == NULL) || (
|
|
|
|
(hfinfo->type == FT_UINT8) ||
|
|
|
|
(hfinfo->type == FT_UINT16) ||
|
|
|
|
(hfinfo->type == FT_UINT24) ||
|
|
|
|
(hfinfo->type == FT_UINT32) ||
|
|
|
|
(hfinfo->type == FT_INT8) ||
|
|
|
|
(hfinfo->type == FT_INT16) ||
|
|
|
|
(hfinfo->type == FT_INT24) ||
|
|
|
|
(hfinfo->type == FT_INT32) ||
|
|
|
|
(hfinfo->type == FT_BOOLEAN) ));
|
|
|
|
|
|
|
|
/* if this is a bitfield, compure bitshift */
|
|
|
|
if (hfinfo->bitmask) {
|
|
|
|
while ((hfinfo->bitmask & (1 << hfinfo->bitshift)) == 0)
|
|
|
|
hfinfo->bitshift++;
|
|
|
|
}
|
1999-07-15 15:33:52 +00:00
|
|
|
|
|
|
|
hfinfo->parent = parent;
|
1999-07-07 22:52:57 +00:00
|
|
|
|
|
|
|
/* if we always add and never delete, then id == len - 1 is correct */
|
|
|
|
g_ptr_array_add(gpa_hfinfo, hfinfo);
|
|
|
|
hfinfo->id = gpa_hfinfo->len - 1;
|
|
|
|
return hfinfo->id;
|
|
|
|
}
|
|
|
|
|
1999-11-16 11:44:20 +00:00
|
|
|
void
|
|
|
|
proto_register_subtree_array(gint **indices, int num_indices)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
gint **ptr = indices;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Add "num_indices" elements to "tree_is_expanded".
|
|
|
|
*/
|
|
|
|
tree_is_expanded = g_realloc(tree_is_expanded,
|
|
|
|
(num_tree_types + num_indices)*sizeof (gint));
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Assign "num_indices" subtree numbers starting at "num_tree_types",
|
|
|
|
* returning the indices through the pointers in the array whose
|
|
|
|
* first element is pointed to by "indices", set to FALSE the
|
|
|
|
* elements to which those subtree numbers refer, and update
|
|
|
|
* "num_tree_types" appropriately.
|
|
|
|
*/
|
|
|
|
for (i = 0; i < num_indices; i++, ptr++, num_tree_types++) {
|
|
|
|
tree_is_expanded[num_tree_types] = FALSE;
|
|
|
|
**ptr = num_tree_types;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-07-07 22:52:57 +00:00
|
|
|
void
|
|
|
|
proto_item_fill_label(field_info *fi, gchar *label_str)
|
|
|
|
{
|
1999-10-12 06:21:15 +00:00
|
|
|
struct header_field_info *hfinfo = fi->hfinfo;
|
1999-11-15 06:32:38 +00:00
|
|
|
guint32 n_addr; /* network-order IPv4 address */
|
1999-07-07 22:52:57 +00:00
|
|
|
|
1999-10-12 06:21:15 +00:00
|
|
|
switch(hfinfo->type) {
|
1999-07-07 22:52:57 +00:00
|
|
|
case FT_NONE:
|
|
|
|
snprintf(label_str, ITEM_LABEL_LENGTH,
|
1999-10-12 06:21:15 +00:00
|
|
|
"%s", hfinfo->name);
|
1999-07-07 22:52:57 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case FT_BOOLEAN:
|
1999-10-12 06:21:15 +00:00
|
|
|
fill_label_boolean(fi, label_str);
|
1999-07-07 22:52:57 +00:00
|
|
|
break;
|
|
|
|
|
1999-09-18 15:44:41 +00:00
|
|
|
case FT_BYTES:
|
2000-05-19 04:54:36 +00:00
|
|
|
if (fi->value.bytes) {
|
|
|
|
snprintf(label_str, ITEM_LABEL_LENGTH,
|
|
|
|
"%s: %s", hfinfo->name,
|
|
|
|
bytes_to_str(fi->value.bytes, fi->length));
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
snprintf(label_str, ITEM_LABEL_LENGTH,
|
|
|
|
"%s: <MISSING>", hfinfo->name);
|
|
|
|
}
|
1999-09-18 15:44:41 +00:00
|
|
|
break;
|
|
|
|
|
1999-10-12 06:21:15 +00:00
|
|
|
/* Four types of integers to take care of:
|
|
|
|
* Bitfield, with val_string
|
|
|
|
* Bitfield, w/o val_string
|
|
|
|
* Non-bitfield, with val_string
|
|
|
|
* Non-bitfield, w/o val_string
|
|
|
|
*/
|
1999-07-07 22:52:57 +00:00
|
|
|
case FT_UINT8:
|
|
|
|
case FT_UINT16:
|
1999-10-12 22:51:58 +00:00
|
|
|
case FT_UINT24:
|
1999-07-07 22:52:57 +00:00
|
|
|
case FT_UINT32:
|
1999-10-12 06:21:15 +00:00
|
|
|
if (hfinfo->bitmask) {
|
|
|
|
if (hfinfo->strings) {
|
|
|
|
fill_label_enumerated_bitfield(fi, label_str);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
fill_label_numeric_bitfield(fi, label_str);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (hfinfo->strings) {
|
|
|
|
fill_label_enumerated_uint(fi, label_str);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
fill_label_uint(fi, label_str);
|
|
|
|
}
|
|
|
|
}
|
1999-07-07 22:52:57 +00:00
|
|
|
break;
|
|
|
|
|
1999-10-13 03:07:30 +00:00
|
|
|
case FT_INT8:
|
|
|
|
case FT_INT16:
|
|
|
|
case FT_INT24:
|
|
|
|
case FT_INT32:
|
|
|
|
g_assert(!hfinfo->bitmask);
|
|
|
|
if (hfinfo->strings) {
|
|
|
|
fill_label_enumerated_int(fi, label_str);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
fill_label_int(fi, label_str);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
1999-09-12 06:11:51 +00:00
|
|
|
case FT_DOUBLE:
|
|
|
|
snprintf(label_str, ITEM_LABEL_LENGTH,
|
|
|
|
"%s: %g", fi->hfinfo->name,
|
|
|
|
fi->value.floating);
|
|
|
|
break;
|
|
|
|
|
1999-07-07 22:52:57 +00:00
|
|
|
case FT_ABSOLUTE_TIME:
|
|
|
|
snprintf(label_str, ITEM_LABEL_LENGTH,
|
|
|
|
"%s: %s", fi->hfinfo->name,
|
1999-09-12 06:11:51 +00:00
|
|
|
abs_time_to_str(&fi->value.time));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case FT_RELATIVE_TIME:
|
|
|
|
snprintf(label_str, ITEM_LABEL_LENGTH,
|
|
|
|
"%s: %s seconds", fi->hfinfo->name,
|
|
|
|
rel_time_to_str(&fi->value.time));
|
1999-07-07 22:52:57 +00:00
|
|
|
break;
|
|
|
|
|
Changed the display filter scanner from GLIB's GScanner to lex. The code
as it standed depends on your lex being flex, but that only matters if you're
a developer. The distribution will include the dfilter-scanner.c file, so
that if the user doesn't modify dfilter-scanner.l, he won't need flex to
re-create the *.c file.
The new lex scanner gives me better syntax checking for ether addresses. I
thought I could get by using GScanner, but it simply wasn't powerful enough.
All operands have English-like abbreviations and C-like syntax:
and, && ; or, || ; eq, == ; ne, != ; , etc.
I removed the ETHER_VENDOR type in favor of letting the user use the [x:y]
notation: ether.src[0:3] == 0:6:29 instead of ether.srcvendor == 00:06:29
I implemented the IPXNET field type; it had been there before, but was
not implemented. I chose to make it use integer values rather than byte
ranges, since an IPX Network is 4 bytes. So a display filter looks like this:
ipx.srcnet == 0xc0a82c00
rather than this:
ipx.srcnet == c0:a8:2c:00
I can supposrt the byte-range type IPXNET in the future, very trivially.
I still have more work to do on the parser though. It needs to check ranges
when extracting byte ranges ([x:y]) from packets. And I need to get rid
of those reduce/reduce errors from yacc!
svn path=/trunk/; revision=414
1999-08-01 04:28:20 +00:00
|
|
|
case FT_IPXNET:
|
|
|
|
snprintf(label_str, ITEM_LABEL_LENGTH,
|
1999-11-21 16:32:23 +00:00
|
|
|
"%s: 0x%08X (%s)", fi->hfinfo->name,
|
|
|
|
fi->value.numeric, get_ipxnet_name(fi->value.numeric));
|
Changed the display filter scanner from GLIB's GScanner to lex. The code
as it standed depends on your lex being flex, but that only matters if you're
a developer. The distribution will include the dfilter-scanner.c file, so
that if the user doesn't modify dfilter-scanner.l, he won't need flex to
re-create the *.c file.
The new lex scanner gives me better syntax checking for ether addresses. I
thought I could get by using GScanner, but it simply wasn't powerful enough.
All operands have English-like abbreviations and C-like syntax:
and, && ; or, || ; eq, == ; ne, != ; , etc.
I removed the ETHER_VENDOR type in favor of letting the user use the [x:y]
notation: ether.src[0:3] == 0:6:29 instead of ether.srcvendor == 00:06:29
I implemented the IPXNET field type; it had been there before, but was
not implemented. I chose to make it use integer values rather than byte
ranges, since an IPX Network is 4 bytes. So a display filter looks like this:
ipx.srcnet == 0xc0a82c00
rather than this:
ipx.srcnet == c0:a8:2c:00
I can supposrt the byte-range type IPXNET in the future, very trivially.
I still have more work to do on the parser though. It needs to check ranges
when extracting byte ranges ([x:y]) from packets. And I need to get rid
of those reduce/reduce errors from yacc!
svn path=/trunk/; revision=414
1999-08-01 04:28:20 +00:00
|
|
|
break;
|
|
|
|
|
1999-07-07 22:52:57 +00:00
|
|
|
case FT_ETHER:
|
|
|
|
snprintf(label_str, ITEM_LABEL_LENGTH,
|
|
|
|
"%s: %s (%s)", fi->hfinfo->name,
|
|
|
|
ether_to_str(fi->value.ether),
|
|
|
|
get_ether_name(fi->value.ether));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case FT_IPv4:
|
1999-11-15 06:32:38 +00:00
|
|
|
n_addr = ipv4_get_net_order_addr(&fi->value.ipv4);
|
1999-07-07 22:52:57 +00:00
|
|
|
snprintf(label_str, ITEM_LABEL_LENGTH,
|
|
|
|
"%s: %s (%s)", fi->hfinfo->name,
|
1999-11-15 06:32:38 +00:00
|
|
|
get_hostname(n_addr),
|
|
|
|
ip_to_str((guint8*)&n_addr));
|
1999-07-07 22:52:57 +00:00
|
|
|
break;
|
1999-10-11 17:05:49 +00:00
|
|
|
|
|
|
|
case FT_IPv6:
|
|
|
|
snprintf(label_str, ITEM_LABEL_LENGTH,
|
|
|
|
"%s: %s (%s)", fi->hfinfo->name,
|
|
|
|
get_hostname6((struct e_in6_addr *)fi->value.ipv6),
|
|
|
|
ip6_to_str((struct e_in6_addr*)fi->value.ipv6));
|
|
|
|
break;
|
1999-07-07 22:52:57 +00:00
|
|
|
|
|
|
|
case FT_STRING:
|
|
|
|
snprintf(label_str, ITEM_LABEL_LENGTH,
|
|
|
|
"%s: %s", fi->hfinfo->name, fi->value.string);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
g_error("hfinfo->type %d not handled\n", fi->hfinfo->type);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-10-12 06:21:15 +00:00
|
|
|
static void
|
|
|
|
fill_label_boolean(field_info *fi, gchar *label_str)
|
|
|
|
{
|
|
|
|
char *p = label_str;
|
|
|
|
int bitfield_byte_length = 0, bitwidth;
|
|
|
|
guint32 unshifted_value;
|
|
|
|
|
|
|
|
struct header_field_info *hfinfo = fi->hfinfo;
|
|
|
|
struct true_false_string default_tf = { "True", "False" };
|
|
|
|
struct true_false_string *tfstring = &default_tf;
|
|
|
|
|
|
|
|
if (hfinfo->strings) {
|
|
|
|
tfstring = (struct true_false_string*) hfinfo->strings;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (hfinfo->bitmask) {
|
|
|
|
/* Figure out the bit width */
|
|
|
|
bitwidth = hfinfo_bitwidth(hfinfo);
|
|
|
|
|
|
|
|
/* Un-shift bits */
|
|
|
|
unshifted_value = fi->value.numeric;
|
|
|
|
if (hfinfo->bitshift > 0) {
|
|
|
|
unshifted_value <<= hfinfo->bitshift;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Create the bitfield first */
|
|
|
|
p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
|
|
|
|
bitfield_byte_length = p - label_str;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Fill in the textual info */
|
|
|
|
snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
|
|
|
|
"%s: %s", hfinfo->name,
|
|
|
|
fi->value.numeric ? tfstring->true_string : tfstring->false_string);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Fills data for bitfield ints with val_strings */
|
|
|
|
static void
|
|
|
|
fill_label_enumerated_bitfield(field_info *fi, gchar *label_str)
|
|
|
|
{
|
|
|
|
char *format = NULL, *p;
|
|
|
|
int bitfield_byte_length, bitwidth;
|
|
|
|
guint32 unshifted_value;
|
|
|
|
|
|
|
|
struct header_field_info *hfinfo = fi->hfinfo;
|
|
|
|
|
|
|
|
/* Figure out the bit width */
|
|
|
|
bitwidth = hfinfo_bitwidth(hfinfo);
|
|
|
|
|
|
|
|
/* Pick the proper format string */
|
|
|
|
format = hfinfo_uint_vals_format(hfinfo);
|
|
|
|
|
|
|
|
/* Un-shift bits */
|
|
|
|
unshifted_value = fi->value.numeric;
|
|
|
|
if (hfinfo->bitshift > 0) {
|
|
|
|
unshifted_value <<= hfinfo->bitshift;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Create the bitfield first */
|
|
|
|
p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
|
|
|
|
bitfield_byte_length = p - label_str;
|
|
|
|
|
|
|
|
/* Fill in the textual info using stored (shifted) value */
|
|
|
|
snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
|
|
|
|
format, hfinfo->name,
|
|
|
|
val_to_str(fi->value.numeric, cVALS(hfinfo->strings), "Unknown"),
|
|
|
|
fi->value.numeric);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
fill_label_numeric_bitfield(field_info *fi, gchar *label_str)
|
|
|
|
{
|
|
|
|
char *format = NULL, *p;
|
|
|
|
int bitfield_byte_length, bitwidth;
|
|
|
|
guint32 unshifted_value;
|
|
|
|
|
|
|
|
struct header_field_info *hfinfo = fi->hfinfo;
|
|
|
|
|
|
|
|
/* Figure out the bit width */
|
|
|
|
bitwidth = hfinfo_bitwidth(hfinfo);
|
|
|
|
|
|
|
|
/* Pick the proper format string */
|
|
|
|
format = hfinfo_uint_format(hfinfo);
|
|
|
|
|
|
|
|
/* Un-shift bits */
|
|
|
|
unshifted_value = fi->value.numeric;
|
|
|
|
if (hfinfo->bitshift > 0) {
|
|
|
|
unshifted_value <<= hfinfo->bitshift;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Create the bitfield using */
|
|
|
|
p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
|
|
|
|
bitfield_byte_length = p - label_str;
|
|
|
|
|
|
|
|
/* Fill in the textual info using stored (shifted) value */
|
|
|
|
snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
|
|
|
|
format, hfinfo->name, fi->value.numeric);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
fill_label_enumerated_uint(field_info *fi, gchar *label_str)
|
|
|
|
{
|
|
|
|
char *format = NULL;
|
|
|
|
struct header_field_info *hfinfo = fi->hfinfo;
|
|
|
|
|
|
|
|
/* Pick the proper format string */
|
|
|
|
format = hfinfo_uint_vals_format(hfinfo);
|
|
|
|
|
|
|
|
/* Fill in the textual info */
|
|
|
|
snprintf(label_str, ITEM_LABEL_LENGTH,
|
|
|
|
format, hfinfo->name,
|
|
|
|
val_to_str(fi->value.numeric, cVALS(hfinfo->strings), "Unknown"),
|
|
|
|
fi->value.numeric);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
fill_label_uint(field_info *fi, gchar *label_str)
|
|
|
|
{
|
|
|
|
char *format = NULL;
|
|
|
|
struct header_field_info *hfinfo = fi->hfinfo;
|
|
|
|
|
|
|
|
/* Pick the proper format string */
|
|
|
|
format = hfinfo_uint_format(hfinfo);
|
|
|
|
|
|
|
|
/* Fill in the textual info */
|
|
|
|
snprintf(label_str, ITEM_LABEL_LENGTH,
|
|
|
|
format, hfinfo->name, fi->value.numeric);
|
|
|
|
}
|
|
|
|
|
1999-10-13 03:07:30 +00:00
|
|
|
static void
|
|
|
|
fill_label_enumerated_int(field_info *fi, gchar *label_str)
|
|
|
|
{
|
|
|
|
char *format = NULL;
|
|
|
|
struct header_field_info *hfinfo = fi->hfinfo;
|
|
|
|
|
|
|
|
/* Pick the proper format string */
|
|
|
|
format = hfinfo_int_vals_format(hfinfo);
|
|
|
|
|
|
|
|
/* Fill in the textual info */
|
|
|
|
snprintf(label_str, ITEM_LABEL_LENGTH,
|
|
|
|
format, hfinfo->name,
|
|
|
|
val_to_str(fi->value.numeric, cVALS(hfinfo->strings), "Unknown"),
|
|
|
|
fi->value.numeric);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
fill_label_int(field_info *fi, gchar *label_str)
|
|
|
|
{
|
|
|
|
char *format = NULL;
|
|
|
|
struct header_field_info *hfinfo = fi->hfinfo;
|
|
|
|
|
|
|
|
/* Pick the proper format string */
|
|
|
|
format = hfinfo_int_format(hfinfo);
|
|
|
|
|
|
|
|
/* Fill in the textual info */
|
|
|
|
snprintf(label_str, ITEM_LABEL_LENGTH,
|
|
|
|
format, hfinfo->name, fi->value.numeric);
|
|
|
|
}
|
|
|
|
|
1999-10-12 06:21:15 +00:00
|
|
|
static int
|
|
|
|
hfinfo_bitwidth(header_field_info *hfinfo)
|
|
|
|
{
|
|
|
|
int bitwidth = 0;
|
|
|
|
|
|
|
|
if (!hfinfo->bitmask) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch(hfinfo->type) {
|
|
|
|
case FT_UINT8:
|
|
|
|
case FT_INT8:
|
|
|
|
bitwidth = 8;
|
|
|
|
break;
|
|
|
|
case FT_UINT16:
|
|
|
|
case FT_INT16:
|
|
|
|
bitwidth = 16;
|
|
|
|
break;
|
|
|
|
case FT_UINT24:
|
|
|
|
case FT_INT24:
|
|
|
|
bitwidth = 24;
|
|
|
|
break;
|
|
|
|
case FT_UINT32:
|
|
|
|
case FT_INT32:
|
|
|
|
bitwidth = 32;
|
|
|
|
break;
|
|
|
|
case FT_BOOLEAN:
|
|
|
|
bitwidth = hfinfo->display; /* hacky? :) */
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
g_assert_not_reached();
|
|
|
|
;
|
|
|
|
}
|
|
|
|
return bitwidth;
|
|
|
|
}
|
|
|
|
|
|
|
|
static char*
|
|
|
|
hfinfo_uint_vals_format(header_field_info *hfinfo)
|
|
|
|
{
|
|
|
|
char *format = NULL;
|
|
|
|
|
|
|
|
switch(hfinfo->display) {
|
|
|
|
case BASE_DEC:
|
|
|
|
case BASE_NONE:
|
|
|
|
case BASE_OCT: /* I'm lazy */
|
|
|
|
case BASE_BIN: /* I'm lazy */
|
|
|
|
format = "%s: %s (%u)";
|
|
|
|
break;
|
|
|
|
case BASE_HEX:
|
|
|
|
switch(hfinfo->type) {
|
|
|
|
case FT_UINT8:
|
|
|
|
format = "%s: %s (0x%02x)";
|
|
|
|
break;
|
|
|
|
case FT_UINT16:
|
|
|
|
format = "%s: %s (0x%04x)";
|
|
|
|
break;
|
|
|
|
case FT_UINT24:
|
|
|
|
format = "%s: %s (0x%06x)";
|
|
|
|
break;
|
|
|
|
case FT_UINT32:
|
|
|
|
format = "%s: %s (0x%08x)";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
g_assert_not_reached();
|
|
|
|
;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
g_assert_not_reached();
|
|
|
|
;
|
|
|
|
}
|
|
|
|
return format;
|
|
|
|
}
|
|
|
|
|
|
|
|
static char*
|
|
|
|
hfinfo_uint_format(header_field_info *hfinfo)
|
|
|
|
{
|
|
|
|
char *format = NULL;
|
|
|
|
|
|
|
|
/* Pick the proper format string */
|
|
|
|
switch(hfinfo->display) {
|
|
|
|
case BASE_DEC:
|
|
|
|
case BASE_NONE:
|
|
|
|
case BASE_OCT: /* I'm lazy */
|
|
|
|
case BASE_BIN: /* I'm lazy */
|
|
|
|
format = "%s: %u";
|
|
|
|
break;
|
|
|
|
case BASE_HEX:
|
|
|
|
switch(hfinfo->type) {
|
|
|
|
case FT_UINT8:
|
|
|
|
format = "%s: 0x%02x";
|
|
|
|
break;
|
|
|
|
case FT_UINT16:
|
|
|
|
format = "%s: 0x%04x";
|
|
|
|
break;
|
|
|
|
case FT_UINT24:
|
|
|
|
format = "%s: 0x%06x";
|
|
|
|
break;
|
|
|
|
case FT_UINT32:
|
1999-10-13 03:07:30 +00:00
|
|
|
format = "%s: 0x%08x";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
g_assert_not_reached();
|
|
|
|
;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
g_assert_not_reached();
|
|
|
|
;
|
|
|
|
}
|
|
|
|
return format;
|
|
|
|
}
|
|
|
|
|
|
|
|
static char*
|
|
|
|
hfinfo_int_vals_format(header_field_info *hfinfo)
|
|
|
|
{
|
|
|
|
char *format = NULL;
|
|
|
|
|
|
|
|
switch(hfinfo->display) {
|
|
|
|
case BASE_DEC:
|
|
|
|
case BASE_NONE:
|
|
|
|
case BASE_OCT: /* I'm lazy */
|
|
|
|
case BASE_BIN: /* I'm lazy */
|
|
|
|
format = "%s: %s (%d)";
|
|
|
|
break;
|
|
|
|
case BASE_HEX:
|
|
|
|
switch(hfinfo->type) {
|
|
|
|
case FT_INT8:
|
|
|
|
format = "%s: %s (0x%02x)";
|
|
|
|
break;
|
|
|
|
case FT_INT16:
|
|
|
|
format = "%s: %s (0x%04x)";
|
|
|
|
break;
|
|
|
|
case FT_INT24:
|
|
|
|
format = "%s: %s (0x%06x)";
|
|
|
|
break;
|
|
|
|
case FT_INT32:
|
|
|
|
format = "%s: %s (0x%08x)";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
g_assert_not_reached();
|
|
|
|
;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
g_assert_not_reached();
|
|
|
|
;
|
|
|
|
}
|
|
|
|
return format;
|
|
|
|
}
|
|
|
|
|
|
|
|
static char*
|
|
|
|
hfinfo_int_format(header_field_info *hfinfo)
|
|
|
|
{
|
|
|
|
char *format = NULL;
|
|
|
|
|
|
|
|
/* Pick the proper format string */
|
|
|
|
switch(hfinfo->display) {
|
|
|
|
case BASE_DEC:
|
|
|
|
case BASE_NONE:
|
|
|
|
case BASE_OCT: /* I'm lazy */
|
|
|
|
case BASE_BIN: /* I'm lazy */
|
|
|
|
format = "%s: %d";
|
|
|
|
break;
|
|
|
|
case BASE_HEX:
|
|
|
|
switch(hfinfo->type) {
|
|
|
|
case FT_INT8:
|
|
|
|
format = "%s: 0x%02x";
|
|
|
|
break;
|
|
|
|
case FT_INT16:
|
|
|
|
format = "%s: 0x%04x";
|
|
|
|
break;
|
|
|
|
case FT_INT24:
|
|
|
|
format = "%s: 0x%06x";
|
|
|
|
break;
|
1999-10-12 06:21:15 +00:00
|
|
|
case FT_INT32:
|
|
|
|
format = "%s: 0x%08x";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
g_assert_not_reached();
|
|
|
|
;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
g_assert_not_reached();
|
|
|
|
;
|
|
|
|
}
|
|
|
|
return format;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
1999-07-07 22:52:57 +00:00
|
|
|
int
|
|
|
|
proto_registrar_n(void)
|
|
|
|
{
|
|
|
|
return gpa_hfinfo->len;
|
|
|
|
}
|
|
|
|
|
1999-11-11 16:20:25 +00:00
|
|
|
char*
|
|
|
|
proto_registrar_get_name(int n)
|
|
|
|
{
|
|
|
|
struct header_field_info *hfinfo;
|
2000-04-04 02:34:40 +00:00
|
|
|
hfinfo = proto_registrar_get_nth(n);
|
1999-11-11 16:20:25 +00:00
|
|
|
if (hfinfo)
|
|
|
|
return hfinfo->name;
|
|
|
|
else return NULL;
|
|
|
|
}
|
|
|
|
|
1999-07-07 22:52:57 +00:00
|
|
|
char*
|
|
|
|
proto_registrar_get_abbrev(int n)
|
|
|
|
{
|
|
|
|
struct header_field_info *hfinfo;
|
|
|
|
|
2000-04-04 02:34:40 +00:00
|
|
|
hfinfo = proto_registrar_get_nth(n);
|
1999-07-07 22:52:57 +00:00
|
|
|
if (hfinfo)
|
|
|
|
return hfinfo->abbrev;
|
|
|
|
else
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
proto_registrar_get_ftype(int n)
|
|
|
|
{
|
|
|
|
struct header_field_info *hfinfo;
|
|
|
|
|
2000-04-04 02:34:40 +00:00
|
|
|
hfinfo = proto_registrar_get_nth(n);
|
1999-07-07 22:52:57 +00:00
|
|
|
if (hfinfo)
|
|
|
|
return hfinfo->type;
|
|
|
|
else
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
proto_registrar_get_parent(int n)
|
|
|
|
{
|
|
|
|
struct header_field_info *hfinfo;
|
|
|
|
|
2000-04-04 02:34:40 +00:00
|
|
|
hfinfo = proto_registrar_get_nth(n);
|
1999-07-07 22:52:57 +00:00
|
|
|
if (hfinfo)
|
|
|
|
return hfinfo->parent;
|
|
|
|
else
|
|
|
|
return -2;
|
|
|
|
}
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
proto_registrar_is_protocol(int n)
|
|
|
|
{
|
|
|
|
struct header_field_info *hfinfo;
|
|
|
|
|
2000-04-04 02:34:40 +00:00
|
|
|
hfinfo = proto_registrar_get_nth(n);
|
1999-07-07 22:52:57 +00:00
|
|
|
if (hfinfo)
|
|
|
|
return (hfinfo->parent == -1 ? TRUE : FALSE);
|
|
|
|
else
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
1999-11-15 06:32:38 +00:00
|
|
|
/* Returns length of field in packet (not necessarily the length
|
|
|
|
* in our internal representation, as in the case of IPv4).
|
1999-10-12 04:21:13 +00:00
|
|
|
* 0 means undeterminable at time of registration
|
|
|
|
* -1 means the field is not registered. */
|
|
|
|
gint
|
|
|
|
proto_registrar_get_length(int n)
|
|
|
|
{
|
|
|
|
struct header_field_info *hfinfo;
|
|
|
|
|
2000-04-04 02:34:40 +00:00
|
|
|
hfinfo = proto_registrar_get_nth(n);
|
1999-10-12 04:21:13 +00:00
|
|
|
if (!hfinfo)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
switch (hfinfo->type) {
|
|
|
|
case FT_TEXT_ONLY: /* not filterable */
|
|
|
|
case NUM_FIELD_TYPES: /* satisfy picky compilers */
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
case FT_NONE:
|
|
|
|
case FT_BYTES:
|
|
|
|
case FT_BOOLEAN:
|
|
|
|
case FT_STRING:
|
|
|
|
case FT_DOUBLE:
|
|
|
|
case FT_ABSOLUTE_TIME:
|
|
|
|
case FT_RELATIVE_TIME:
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
case FT_UINT8:
|
1999-10-12 06:21:15 +00:00
|
|
|
case FT_INT8:
|
1999-10-12 04:21:13 +00:00
|
|
|
return 1;
|
|
|
|
|
|
|
|
case FT_UINT16:
|
1999-10-12 06:21:15 +00:00
|
|
|
case FT_INT16:
|
1999-10-12 04:21:13 +00:00
|
|
|
return 2;
|
|
|
|
|
1999-10-12 06:21:15 +00:00
|
|
|
case FT_UINT24:
|
|
|
|
case FT_INT24:
|
1999-10-12 04:21:13 +00:00
|
|
|
return 3;
|
|
|
|
|
|
|
|
case FT_UINT32:
|
1999-10-12 06:21:15 +00:00
|
|
|
case FT_INT32:
|
1999-10-12 04:21:13 +00:00
|
|
|
case FT_IPXNET:
|
|
|
|
case FT_IPv4:
|
|
|
|
return 4;
|
|
|
|
|
|
|
|
case FT_ETHER:
|
|
|
|
return 6;
|
|
|
|
|
|
|
|
case FT_IPv6:
|
1999-10-12 19:47:44 +00:00
|
|
|
return 16;
|
1999-10-12 04:21:13 +00:00
|
|
|
}
|
|
|
|
g_assert_not_reached();
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
1999-08-29 04:06:43 +00:00
|
|
|
/* Looks for a protocol or a field in a proto_tree. Returns TRUE if
|
|
|
|
* it exists anywhere, or FALSE if it exists nowhere. */
|
|
|
|
gboolean
|
|
|
|
proto_check_for_protocol_or_field(proto_tree* tree, int id)
|
1999-07-07 22:52:57 +00:00
|
|
|
{
|
1999-08-29 04:06:43 +00:00
|
|
|
proto_tree_search_info sinfo;
|
1999-07-07 22:52:57 +00:00
|
|
|
|
1999-08-29 04:06:43 +00:00
|
|
|
sinfo.target = id;
|
|
|
|
sinfo.result.node = NULL;
|
|
|
|
sinfo.parent = -1;
|
|
|
|
sinfo.traverse_func = NULL;
|
1999-07-07 22:52:57 +00:00
|
|
|
|
1999-08-29 04:06:43 +00:00
|
|
|
/* do a quicker check if target is a protocol */
|
1999-07-07 22:52:57 +00:00
|
|
|
if (proto_registrar_is_protocol(id) == TRUE) {
|
1999-08-29 04:06:43 +00:00
|
|
|
proto_find_protocol_multi(tree, id, &check_for_protocol_or_field_id, &sinfo);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* find the field's parent protocol */
|
|
|
|
sinfo.parent = proto_registrar_get_parent(id);
|
|
|
|
|
|
|
|
/* Go through each protocol subtree, checking if the protocols
|
|
|
|
* is the parent protocol of the field that we're looking for.
|
|
|
|
* We may have protocols that occur more than once (e.g., IP in IP),
|
|
|
|
* so we do indeed have to check all protocol subtrees, looking
|
|
|
|
* for the parent protocol. That's why proto_find_protocol()
|
|
|
|
* is not used --- it assumes a protocol occurs only once. */
|
|
|
|
g_node_traverse((GNode*)tree, G_IN_ORDER, G_TRAVERSE_ALL, 2,
|
|
|
|
check_for_field_within_protocol, &sinfo);
|
1999-07-07 22:52:57 +00:00
|
|
|
}
|
|
|
|
|
1999-08-29 04:06:43 +00:00
|
|
|
if (sinfo.result.node)
|
|
|
|
return TRUE;
|
|
|
|
else
|
|
|
|
return FALSE;
|
1999-07-07 22:52:57 +00:00
|
|
|
}
|
|
|
|
|
1999-08-29 04:06:43 +00:00
|
|
|
static gboolean
|
|
|
|
check_for_protocol_or_field_id(GNode *node, gpointer data)
|
1999-07-07 22:52:57 +00:00
|
|
|
{
|
1999-08-29 04:06:43 +00:00
|
|
|
field_info *fi = (field_info*) (node->data);
|
|
|
|
proto_tree_search_info *sinfo = (proto_tree_search_info*) data;
|
1999-07-07 22:52:57 +00:00
|
|
|
|
1999-08-29 04:06:43 +00:00
|
|
|
if (fi) { /* !fi == the top most container node which holds nothing */
|
|
|
|
if (fi->hfinfo->id == sinfo->target) {
|
|
|
|
sinfo->result.node = node;
|
|
|
|
return TRUE; /* halt traversal */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return FALSE; /* keep traversing */
|
1999-07-07 22:52:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
1999-08-29 04:06:43 +00:00
|
|
|
check_for_field_within_protocol(GNode *node, gpointer data)
|
1999-07-07 22:52:57 +00:00
|
|
|
{
|
1999-08-29 04:06:43 +00:00
|
|
|
field_info *fi = (field_info*) (node->data);
|
|
|
|
proto_tree_search_info *sinfo = (proto_tree_search_info*) data;
|
1999-07-07 22:52:57 +00:00
|
|
|
|
|
|
|
if (fi) { /* !fi == the top most container node which holds nothing */
|
1999-08-29 04:06:43 +00:00
|
|
|
if (fi->hfinfo->id == sinfo->parent) {
|
|
|
|
g_node_traverse(node, G_IN_ORDER, G_TRAVERSE_ALL, -1,
|
|
|
|
check_for_protocol_or_field_id, sinfo);
|
|
|
|
if (sinfo->result.node)
|
|
|
|
return TRUE; /* halt traversal */
|
1999-07-07 22:52:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return FALSE; /* keep traversing */
|
|
|
|
}
|
|
|
|
|
1999-08-29 04:06:43 +00:00
|
|
|
/* Looks for a protocol at the top layer of the tree. The protocol can occur
|
|
|
|
* more than once, for those encapsulated protocols. For each protocol subtree
|
|
|
|
* that is found, the callback function is called.
|
|
|
|
*/
|
1999-07-07 22:52:57 +00:00
|
|
|
void
|
1999-08-29 04:06:43 +00:00
|
|
|
proto_find_protocol_multi(proto_tree* tree, int target, GNodeTraverseFunc callback,
|
|
|
|
proto_tree_search_info *sinfo)
|
|
|
|
{
|
|
|
|
g_assert(callback != NULL);
|
|
|
|
g_node_traverse((GNode*)tree, G_IN_ORDER, G_TRAVERSE_ALL, 2, callback, (gpointer*)sinfo);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Simple wrappter to traverse all nodes, calling the sinfo traverse function with sinfo as an arg */
|
|
|
|
gboolean
|
|
|
|
proto_get_field_values(proto_tree* subtree, proto_tree_search_info *sinfo)
|
1999-07-07 22:52:57 +00:00
|
|
|
{
|
1999-08-30 15:51:44 +00:00
|
|
|
/* Don't try to check value of top-level NULL GNode */
|
|
|
|
if (!((GNode*)subtree)->data) {
|
|
|
|
return FALSE; /* don't halt */
|
|
|
|
}
|
1999-08-29 04:06:43 +00:00
|
|
|
g_node_traverse((GNode*)subtree, G_IN_ORDER, G_TRAVERSE_ALL, -1, sinfo->traverse_func, (gpointer*)sinfo);
|
1999-08-30 15:51:44 +00:00
|
|
|
return FALSE; /* don't halt */
|
1999-07-07 22:52:57 +00:00
|
|
|
}
|
1999-07-15 15:33:52 +00:00
|
|
|
|
|
|
|
/* Dumps the contents of the registration database to stdout. An indepedent program can take
|
|
|
|
* this output and format it into nice tables or HTML or whatever.
|
|
|
|
*
|
|
|
|
* There is one record per line. Each record is either a protocol or a header
|
|
|
|
* field, differentiated by the first field. The fields are tab-delimited.
|
|
|
|
*
|
|
|
|
* Protocols
|
|
|
|
* ---------
|
|
|
|
* Field 1 = 'P'
|
|
|
|
* Field 2 = protocol name
|
|
|
|
* Field 3 = protocol abbreviation
|
|
|
|
*
|
|
|
|
* Header Fields
|
|
|
|
* -------------
|
|
|
|
* Field 1 = 'F'
|
|
|
|
* Field 2 = field name
|
|
|
|
* Field 3 = field abbreviation
|
|
|
|
* Field 4 = type ( textual representation of the the ftenum type )
|
|
|
|
* Field 5 = parent protocol abbreviation
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
proto_registrar_dump(void)
|
|
|
|
{
|
|
|
|
header_field_info *hfinfo, *parent_hfinfo;
|
|
|
|
int i, len;
|
|
|
|
const char *enum_name;
|
|
|
|
|
|
|
|
len = gpa_hfinfo->len;
|
|
|
|
for (i = 0; i < len ; i++) {
|
2000-04-04 02:34:40 +00:00
|
|
|
hfinfo = proto_registrar_get_nth(i);
|
1999-07-15 15:33:52 +00:00
|
|
|
|
|
|
|
/* format for protocols */
|
|
|
|
if (proto_registrar_is_protocol(i)) {
|
|
|
|
printf("P\t%s\t%s\n", hfinfo->name, hfinfo->abbrev);
|
|
|
|
}
|
|
|
|
/* format for header fields */
|
|
|
|
else {
|
2000-04-04 02:34:40 +00:00
|
|
|
parent_hfinfo = proto_registrar_get_nth(hfinfo->parent);
|
1999-07-15 15:33:52 +00:00
|
|
|
g_assert(parent_hfinfo);
|
|
|
|
|
|
|
|
switch(hfinfo->type) {
|
|
|
|
case FT_NONE:
|
|
|
|
enum_name = "FT_NONE";
|
|
|
|
break;
|
|
|
|
case FT_BOOLEAN:
|
|
|
|
enum_name = "FT_BOOLEAN";
|
|
|
|
break;
|
|
|
|
case FT_UINT8:
|
|
|
|
enum_name = "FT_UINT8";
|
|
|
|
break;
|
|
|
|
case FT_UINT16:
|
|
|
|
enum_name = "FT_UINT16";
|
|
|
|
break;
|
1999-10-16 15:46:01 +00:00
|
|
|
case FT_UINT24:
|
|
|
|
enum_name = "FT_UINT24";
|
|
|
|
break;
|
1999-07-15 15:33:52 +00:00
|
|
|
case FT_UINT32:
|
|
|
|
enum_name = "FT_UINT32";
|
|
|
|
break;
|
1999-10-12 06:21:15 +00:00
|
|
|
case FT_INT8:
|
|
|
|
enum_name = "FT_INT8";
|
|
|
|
break;
|
|
|
|
case FT_INT16:
|
|
|
|
enum_name = "FT_INT16";
|
|
|
|
break;
|
|
|
|
case FT_INT24:
|
|
|
|
enum_name = "FT_INT24";
|
|
|
|
break;
|
|
|
|
case FT_INT32:
|
|
|
|
enum_name = "FT_INT32";
|
|
|
|
break;
|
1999-09-12 06:11:51 +00:00
|
|
|
case FT_DOUBLE:
|
|
|
|
enum_name = "FT_DOUBLE";
|
|
|
|
break;
|
1999-07-15 15:33:52 +00:00
|
|
|
case FT_ABSOLUTE_TIME:
|
|
|
|
enum_name = "FT_ABSOLUTE_TIME";
|
|
|
|
break;
|
|
|
|
case FT_RELATIVE_TIME:
|
|
|
|
enum_name = "FT_RELATIVE_TIME";
|
|
|
|
break;
|
|
|
|
case FT_STRING:
|
|
|
|
enum_name = "FT_STRING";
|
|
|
|
break;
|
|
|
|
case FT_ETHER:
|
|
|
|
enum_name = "FT_ETHER";
|
|
|
|
break;
|
|
|
|
case FT_BYTES:
|
|
|
|
enum_name = "FT_BYTES";
|
|
|
|
break;
|
|
|
|
case FT_IPv4:
|
|
|
|
enum_name = "FT_IPv4";
|
|
|
|
break;
|
|
|
|
case FT_IPv6:
|
|
|
|
enum_name = "FT_IPv6";
|
|
|
|
break;
|
Changed the display filter scanner from GLIB's GScanner to lex. The code
as it standed depends on your lex being flex, but that only matters if you're
a developer. The distribution will include the dfilter-scanner.c file, so
that if the user doesn't modify dfilter-scanner.l, he won't need flex to
re-create the *.c file.
The new lex scanner gives me better syntax checking for ether addresses. I
thought I could get by using GScanner, but it simply wasn't powerful enough.
All operands have English-like abbreviations and C-like syntax:
and, && ; or, || ; eq, == ; ne, != ; , etc.
I removed the ETHER_VENDOR type in favor of letting the user use the [x:y]
notation: ether.src[0:3] == 0:6:29 instead of ether.srcvendor == 00:06:29
I implemented the IPXNET field type; it had been there before, but was
not implemented. I chose to make it use integer values rather than byte
ranges, since an IPX Network is 4 bytes. So a display filter looks like this:
ipx.srcnet == 0xc0a82c00
rather than this:
ipx.srcnet == c0:a8:2c:00
I can supposrt the byte-range type IPXNET in the future, very trivially.
I still have more work to do on the parser though. It needs to check ranges
when extracting byte ranges ([x:y]) from packets. And I need to get rid
of those reduce/reduce errors from yacc!
svn path=/trunk/; revision=414
1999-08-01 04:28:20 +00:00
|
|
|
case FT_IPXNET:
|
|
|
|
enum_name = "FT_IPXNET";
|
1999-07-15 15:33:52 +00:00
|
|
|
break;
|
|
|
|
case FT_TEXT_ONLY:
|
|
|
|
enum_name = "FT_TEXT_ONLY";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
enum_name = "UNKNOWN";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
printf("F\t%s\t%s\t%s\t%s\n", hfinfo->name, hfinfo->abbrev,
|
|
|
|
enum_name,parent_hfinfo->abbrev);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|