1999-07-07 22:52:57 +00:00
|
|
|
/* proto.c
|
|
|
|
* Routines for protocol tree
|
|
|
|
*
|
2004-07-18 00:24:25 +00:00
|
|
|
* $Id$
|
1999-07-07 22:52:57 +00:00
|
|
|
*
|
|
|
|
* Ethereal - Network traffic analyzer
|
Enable "Match Selected" only if there's a field selected *and* we can do
a "Match Selected" on it - we can't do a "Match Selected" if the field
has no value (e.g., FT_NULL) and has a length of 0.
If we unselect the current packet, we don't have a protocol tree, so we
don't have a currently selected field - clear the "Match Selected" menu
item and the display in the status line of information about the
currently selected field.
Move the low-level statusbar manipulation into "gtk/main.c", in routines
whose API doesn't expose anything GTK+-ish.
"close_cap_file()" calls one of those routines to clear out the status
bar, so it doesn't need to take a pointer to the statusbar widget as an
argument.
"clear_tree_and_hex_views()" is purely a display-manipulating routine;
move it to "gtk/proto_draw.c".
Extract from "tree_view_unselect_row_cb()" an "unselect_field()" routine
to do all the work that needs to be done if the currently selected
protocol tree row is unselected, and call it if the currently selected
packet list row is unselected (if it's unselected, there *is* no
protocol tree, so no row can be selected), as well as from
"tree_view_unselect_row_cb()".
Before pushing a new field-description message onto the statusbar, pop
the old one off.
Get rid of an unused variable (set, but not used).
svn path=/trunk/; revision=3513
2001-06-05 07:39:31 +00:00
|
|
|
* By Gerald Combs <gerald@ethereal.com>
|
1999-07-07 22:52:57 +00:00
|
|
|
* Copyright 1998 Gerald Combs
|
2002-08-28 20:41:00 +00:00
|
|
|
*
|
1999-07-07 22:52:57 +00:00
|
|
|
* 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.
|
2002-08-28 20:41:00 +00:00
|
|
|
*
|
1999-07-07 22:52:57 +00:00
|
|
|
* 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.
|
2002-08-28 20:41:00 +00:00
|
|
|
*
|
1999-07-07 22:52:57 +00:00
|
|
|
* 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
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
2003-11-13 23:38:33 +00:00
|
|
|
#include <ctype.h>
|
1999-07-07 22:52:57 +00:00
|
|
|
#include <glib.h>
|
2003-07-04 03:41:00 +00:00
|
|
|
#include <float.h>
|
1999-07-07 22:52:57 +00:00
|
|
|
|
|
|
|
#include "packet.h"
|
2005-10-22 05:43:09 +00:00
|
|
|
#include "ptvcursor.h"
|
2000-11-13 07:19:37 +00:00
|
|
|
#include "strutil.h"
|
2004-08-06 19:57:49 +00:00
|
|
|
#include "addr_resolv.h"
|
2005-12-06 11:45:55 +00:00
|
|
|
#include "oid_resolv.h"
|
Clean up the dissector registration up a bit - arrange that all plugins
be loaded and their initialization routines called in right after we
call the initialization routines for built-in dissectors, but don't call
their handoff registration routines yet, and then call the handoff
registration routines right after calling the handoff registration
routines for built-in dissectors.
Do all that in "proto_init()", rather than "epan_init()".
That way, we call all dissector registration routines together, and then
call all dissector handoff registration routines together; all the
registration routines are called before any handoff registration
routines, as is required, and, as "proto_init()" is called by
"epan_init()" before "dfilter_init()" is called, all filterable fields
have been registered before "dfilter_init()" is called, and no plugins
have to call "dfilter_init()" themselves to get their fields registered.
Remove pointers to "dfilter_init()" and "dfilter_cleanup()" from the
plugin address table, as plugins shouldn't be calling them any more, and
remove calls to them from plugins.
svn path=/trunk/; revision=2940
2001-01-26 06:14:53 +00:00
|
|
|
#include "plugins.h"
|
2000-08-11 13:37:21 +00:00
|
|
|
#include "proto.h"
|
Rename "proto_alloc_dfilter_string()" to
"proto_construct_dfilter_string()", to more accurately reflect what it
does.
Give it, and "proto_can_match_selected()", an "epan_dissect_t *"
argument, which replaces the raw data pointer argument to
"proto_construct_dfilter_string()".
For fields that don't have a type we can directly filter on, we don't
support filtering on the field as raw data if:
the "epan_dissect_t *" argument is null;
the data source tvbuff for the field isn't the tvbuff for the
"epan_dissect_t" in question (i.e., it's in the result of a
reassembly, and "frame[N:M]" can't get at it).
Trim the length the raw data in the case of such a field to the length
of the tvbuff for the "epan_dissect_t" in question, so we don't go past
it. Fetch the raw data bytes to match from that tvbuff.
Have "proto_construct_dfilter_string()" return a null pointer if it
can't construct the filter string, and have "protocolinfo_packet()" in
the tap-protocolinfo tap ignore a field if
"proto_construct_dfilter_string()" can't construct a filter string for
it - and have it pass NULL as the "epan_dissect_t *", for now. If
somebody decides it makes sense to dump out a "frame[N:M] =" value for
non-registered fields, it can be changed to pass "edt".
svn path=/trunk/; revision=7635
2003-05-03 00:48:37 +00:00
|
|
|
#include "epan_dissect.h"
|
2003-12-02 09:11:16 +00:00
|
|
|
#include "slab.h"
|
2003-12-02 10:23:18 +00:00
|
|
|
#include "tvbuff.h"
|
2005-09-01 09:03:29 +00:00
|
|
|
#include "emem.h"
|
2000-08-10 19:41:45 +00:00
|
|
|
|
2005-10-22 05:43:09 +00:00
|
|
|
struct ptvcursor {
|
|
|
|
proto_tree *tree;
|
|
|
|
tvbuff_t *tvb;
|
|
|
|
gint offset;
|
|
|
|
};
|
|
|
|
|
1999-07-07 22:52:57 +00:00
|
|
|
#define cVALS(x) (const value_string*)(x)
|
|
|
|
|
2005-04-11 08:43:51 +00:00
|
|
|
#if 1
|
|
|
|
#define TRY_TO_FAKE_THIS_ITEM(tree, hfindex) \
|
|
|
|
/* If this item is not referenced we dont have to do much work \
|
|
|
|
at all but we should still return a node so that \
|
|
|
|
field items below this node ( think proto_item_add_subtree() )\
|
|
|
|
will still have somewhere to attach to \
|
|
|
|
or else filtering will not work (they would be ignored since tree\
|
|
|
|
would be NULL). \
|
|
|
|
DONT try to fake a node where PITEM_FINFO(pi) is NULL \
|
|
|
|
since dissectors that want to do proto_item_set_len() ot \
|
|
|
|
other operations that dereference this would crash. \
|
|
|
|
We dont fake FT_PROTOCOL either since these are cheap and \
|
|
|
|
some stuff (proto hier stat) assumes they always exist. \
|
|
|
|
*/ \
|
|
|
|
if(!(PTREE_DATA(tree)->visible)){ \
|
|
|
|
if(PITEM_FINFO(tree)){ \
|
|
|
|
register header_field_info *hfinfo; \
|
|
|
|
PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo); \
|
|
|
|
if((hfinfo->ref_count == 0) \
|
|
|
|
&& (hfinfo->type!=FT_PROTOCOL)){ \
|
|
|
|
/* just return tree back to the caller */\
|
|
|
|
return tree; \
|
|
|
|
} \
|
|
|
|
} \
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
#define TRY_TO_FAKE_THIS_ITEM(tree, hfindex) ;
|
|
|
|
#endif
|
|
|
|
|
1999-08-04 23:43:42 +00:00
|
|
|
static gboolean
|
2003-12-04 10:59:34 +00:00
|
|
|
proto_tree_free_node(proto_node *node, gpointer data);
|
1999-07-07 22:52:57 +00:00
|
|
|
|
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);
|
2001-10-29 21:13:13 +00:00
|
|
|
static void fill_label_uint64(field_info *fi, gchar *label_str);
|
1999-10-12 06:21:15 +00:00
|
|
|
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);
|
2004-08-22 00:31:58 +00:00
|
|
|
static void fill_label_int64(field_info *fi, gchar *label_str);
|
1999-10-13 03:07:30 +00:00
|
|
|
static void fill_label_enumerated_int(field_info *fi, gchar *label_str);
|
1999-10-12 06:21:15 +00:00
|
|
|
|
2001-02-01 20:21:25 +00:00
|
|
|
int hfinfo_bitwidth(header_field_info *hfinfo);
|
2005-08-05 13:23:47 +00:00
|
|
|
static const char* hfinfo_uint_vals_format(header_field_info *hfinfo);
|
|
|
|
static const char* hfinfo_uint_format(header_field_info *hfinfo);
|
|
|
|
static const char* hfinfo_uint64_format(header_field_info *hfinfo);
|
|
|
|
static const char* hfinfo_int_vals_format(header_field_info *hfinfo);
|
|
|
|
static const char* hfinfo_int_format(header_field_info *hfinfo);
|
|
|
|
static const char* hfinfo_int64_format(header_field_info *hfinfo);
|
1999-10-12 06:21:15 +00:00
|
|
|
|
2000-03-12 04:48:32 +00:00
|
|
|
static proto_item*
|
|
|
|
proto_tree_add_node(proto_tree *tree, field_info *fi);
|
|
|
|
|
2005-10-22 05:43:09 +00:00
|
|
|
static header_field_info *
|
|
|
|
get_hfi_and_length(int hfindex, tvbuff_t *tvb, gint start, gint *length,
|
|
|
|
gint *item_length);
|
|
|
|
|
|
|
|
static field_info *
|
|
|
|
new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
|
|
|
|
gint start, gint item_length);
|
|
|
|
|
2000-07-27 06:41:59 +00:00
|
|
|
static field_info *
|
2001-12-18 19:09:08 +00:00
|
|
|
alloc_field_info(proto_tree *tree, int hfindex, tvbuff_t *tvb,
|
2002-02-18 22:26:29 +00:00
|
|
|
gint start, gint *length);
|
2000-07-27 06:41:59 +00:00
|
|
|
|
2000-03-12 04:48:32 +00:00
|
|
|
static proto_item *
|
2001-12-18 19:09:08 +00:00
|
|
|
proto_tree_add_pi(proto_tree *tree, int hfindex, tvbuff_t *tvb,
|
2002-02-18 22:26:29 +00:00
|
|
|
gint start, gint *length, field_info **pfi);
|
|
|
|
|
2000-05-31 05:09:07 +00:00
|
|
|
static void
|
|
|
|
proto_tree_set_representation(proto_item *pi, const char *format, va_list ap);
|
2000-03-12 04:48:32 +00:00
|
|
|
|
2001-02-01 21:48:02 +00:00
|
|
|
static void
|
|
|
|
proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb);
|
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
|
2001-09-14 07:10:13 +00:00
|
|
|
proto_tree_set_time(field_info *fi, nstime_t *value_ptr);
|
2000-03-12 04:48:32 +00:00
|
|
|
static void
|
tvb_get_nstringz() needs to terminate a string with a NUL if the
end of the tvbuff is reached before the maximum_length passed by the
caller is reached and before a terminating NUL is found. In this case,
tvb_get_nstringz() returns a -1, but if the string is not artificially
terminated with a NUL by tvb_get_nstringz(), the
caller has no idea where the string should end because 1) the
return value "-1" gives the impression that the string ends
at the end of the buffer but 2) the string does
not end at the end of the buffer, but somewhere in the middle, due
to the packet being shorter than expected.
tvb_get_nstringz() and tvb_get_nstringz0() were both modified.
The FT_STRINGZ case in proto_tree_add_item() is made simpler.
During regression testing, when investigating a regression that I later
corrected, I discovered that strings added through proto_tree_add_item
(FT_STRING, FT_STRINGZ, and FT_UINT_STRING) leaked memory due to double
allocation of the string. The proto_tree_add_string*() functions do
not leak memory, since they only copy the string once. The memory
leak was fixed by adding another argument to the static function
proto_tree_set_string() to let the string ftype code know to g_strdup()
the string or not.
svn path=/trunk/; revision=4891
2002-03-06 19:17:06 +00:00
|
|
|
proto_tree_set_string(field_info *fi, const char* value, gboolean);
|
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
|
2005-07-04 13:04:53 +00:00
|
|
|
proto_tree_set_guid(field_info *fi, const guint8* value_ptr);
|
|
|
|
static void
|
|
|
|
proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, gint start);
|
|
|
|
static void
|
2005-12-02 13:16:58 +00:00
|
|
|
proto_tree_set_oid(field_info *fi, const guint8* value_ptr, gint length);
|
|
|
|
static void
|
|
|
|
proto_tree_set_oid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
|
|
|
|
static void
|
2000-03-12 04:48:32 +00:00
|
|
|
proto_tree_set_boolean(field_info *fi, guint32 value);
|
|
|
|
static void
|
2002-08-24 19:45:28 +00:00
|
|
|
proto_tree_set_float(field_info *fi, float value);
|
|
|
|
static void
|
2000-03-12 04:48:32 +00:00
|
|
|
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);
|
2004-08-22 00:31:58 +00:00
|
|
|
static void
|
|
|
|
proto_tree_set_uint64(field_info *fi, guint64 value);
|
|
|
|
static void
|
|
|
|
proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start, gboolean little_endian);
|
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);
|
|
|
|
|
2002-04-29 07:55:32 +00:00
|
|
|
/* Comparision function for tree insertion. A wrapper around strcmp() */
|
|
|
|
static int g_strcmp(gconstpointer a, gconstpointer b);
|
|
|
|
|
1999-07-15 15:33:52 +00:00
|
|
|
/* special-case header field used within proto.c */
|
2003-08-25 00:15:02 +00:00
|
|
|
int hf_text_only = -1;
|
1999-07-07 22:52:57 +00:00
|
|
|
|
2001-01-03 06:56:03 +00:00
|
|
|
/* Structure for information about a protocol */
|
2003-11-16 23:17:27 +00:00
|
|
|
struct _protocol {
|
2005-07-24 19:01:28 +00:00
|
|
|
const char *name; /* long description */
|
|
|
|
const char *short_name; /* short description */
|
|
|
|
const char *filter_name; /* name of this protocol in filters */
|
|
|
|
int proto_id; /* field ID for this protocol */
|
|
|
|
GList *fields; /* fields for this protocol */
|
|
|
|
GList *last_field; /* pointer to end of list of fields */
|
|
|
|
gboolean is_enabled; /* TRUE if protocol is enabled */
|
|
|
|
gboolean can_toggle; /* TRUE if is_enabled can be changed */
|
2003-11-16 23:17:27 +00:00
|
|
|
};
|
2003-08-25 00:15:02 +00:00
|
|
|
|
2001-01-03 06:56:03 +00:00
|
|
|
/* List of all protocols */
|
2005-01-12 21:31:22 +00:00
|
|
|
static GList *protocols = NULL;
|
2001-01-03 06:56:03 +00:00
|
|
|
|
2001-12-18 19:09:08 +00:00
|
|
|
#define INITIAL_NUM_PROTOCOL_HFINFO 200
|
|
|
|
|
|
|
|
|
1999-07-07 22:52:57 +00:00
|
|
|
/* Contains information about protocols and header fields. Used when
|
|
|
|
* dissectors register their data */
|
2001-01-03 06:56:03 +00:00
|
|
|
static GMemChunk *gmc_hfinfo = NULL;
|
1999-07-07 22:52:57 +00:00
|
|
|
|
|
|
|
/* Contains information about a field when a dissector calls
|
|
|
|
* proto_tree_add_item. */
|
2004-07-04 02:29:43 +00:00
|
|
|
SLAB_ITEM_TYPE_DEFINE(field_info)
|
2004-07-04 00:28:11 +00:00
|
|
|
static SLAB_FREE_LIST_DEFINE(field_info)
|
2003-11-24 21:12:10 +00:00
|
|
|
static field_info *field_info_tmp=NULL;
|
2003-11-25 14:10:27 +00:00
|
|
|
#define FIELD_INFO_NEW(fi) \
|
2004-07-04 00:28:11 +00:00
|
|
|
SLAB_ALLOC(fi, field_info)
|
2003-11-26 12:22:22 +00:00
|
|
|
#define FIELD_INFO_FREE(fi) \
|
2004-07-04 00:28:11 +00:00
|
|
|
SLAB_FREE(fi, field_info)
|
2003-11-24 21:12:10 +00:00
|
|
|
|
|
|
|
|
1999-07-07 22:52:57 +00:00
|
|
|
|
2001-12-18 19:09:08 +00:00
|
|
|
/* Contains the space for proto_nodes. */
|
2004-07-04 02:29:43 +00:00
|
|
|
SLAB_ITEM_TYPE_DEFINE(proto_node)
|
2004-07-04 00:28:11 +00:00
|
|
|
static SLAB_FREE_LIST_DEFINE(proto_node)
|
2003-11-26 12:22:22 +00:00
|
|
|
#define PROTO_NODE_NEW(node) \
|
2004-07-04 00:28:11 +00:00
|
|
|
SLAB_ALLOC(node, proto_node) \
|
2003-12-04 10:59:34 +00:00
|
|
|
node->first_child = NULL; \
|
|
|
|
node->last_child = NULL; \
|
|
|
|
node->next = NULL;
|
|
|
|
|
2003-11-26 12:22:22 +00:00
|
|
|
#define PROTO_NODE_FREE(node) \
|
2004-07-04 00:28:11 +00:00
|
|
|
SLAB_FREE(node, proto_node)
|
2003-11-26 12:22:22 +00:00
|
|
|
|
|
|
|
|
2001-12-18 19:09:08 +00:00
|
|
|
|
1999-07-07 22:52:57 +00:00
|
|
|
/* String space for protocol and field items for the GUI */
|
2004-07-04 02:29:43 +00:00
|
|
|
SLAB_ITEM_TYPE_DEFINE(item_label_t)
|
2004-07-04 00:28:11 +00:00
|
|
|
static SLAB_FREE_LIST_DEFINE(item_label_t)
|
2003-11-25 14:07:45 +00:00
|
|
|
#define ITEM_LABEL_NEW(il) \
|
2004-07-04 00:28:11 +00:00
|
|
|
SLAB_ALLOC(il, item_label_t)
|
2003-11-26 12:22:22 +00:00
|
|
|
#define ITEM_LABEL_FREE(il) \
|
2004-07-04 00:28:11 +00:00
|
|
|
SLAB_FREE(il, item_label_t)
|
2003-11-26 12:22:22 +00:00
|
|
|
|
|
|
|
|
2005-04-11 08:43:51 +00:00
|
|
|
#define PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo) \
|
|
|
|
DISSECTOR_ASSERT((guint)hfindex < gpa_hfinfo.len); \
|
|
|
|
hfinfo=gpa_hfinfo.hfi[hfindex];
|
|
|
|
|
2003-11-26 12:22:22 +00:00
|
|
|
|
1999-07-07 22:52:57 +00:00
|
|
|
/* List which stores protocols and fields that have been registered */
|
2003-11-21 14:58:49 +00:00
|
|
|
typedef struct _gpa_hfinfo_t {
|
|
|
|
guint32 len;
|
|
|
|
guint32 allocated_len;
|
|
|
|
header_field_info **hfi;
|
|
|
|
} gpa_hfinfo_t;
|
|
|
|
gpa_hfinfo_t gpa_hfinfo;
|
1999-07-07 22:52:57 +00:00
|
|
|
|
2002-04-29 07:55:32 +00:00
|
|
|
/* Balanced tree of abbreviations and IDs */
|
|
|
|
static GTree *gpa_name_tree = 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;
|
|
|
|
|
2005-01-12 21:31:22 +00:00
|
|
|
/* Name hashtables for fast detection of duplicate names */
|
|
|
|
static GHashTable* proto_names = NULL;
|
|
|
|
static GHashTable* proto_short_names = NULL;
|
|
|
|
static GHashTable* proto_filter_names = NULL;
|
|
|
|
|
|
|
|
static gint
|
|
|
|
proto_compare_name(gconstpointer p1_arg, gconstpointer p2_arg)
|
|
|
|
{
|
|
|
|
const protocol_t *p1 = p1_arg;
|
|
|
|
const protocol_t *p2 = p2_arg;
|
|
|
|
|
|
|
|
return g_strcasecmp(p1->short_name, p2->short_name);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
1999-07-07 22:52:57 +00:00
|
|
|
/* initialize data structures and register protocols and fields */
|
|
|
|
void
|
2003-07-07 20:29:45 +00:00
|
|
|
proto_init(const char *plugin_dir
|
|
|
|
#ifndef HAVE_PLUGINS
|
|
|
|
_U_
|
|
|
|
#endif
|
|
|
|
,
|
|
|
|
void (register_all_protocols)(void),
|
2001-04-02 00:38:36 +00:00
|
|
|
void (register_all_protocol_handoffs)(void))
|
1999-07-07 22:52:57 +00:00
|
|
|
{
|
1999-10-12 06:21:15 +00:00
|
|
|
static hf_register_info hf[] = {
|
|
|
|
{ &hf_text_only,
|
2001-04-19 23:06:23 +00:00
|
|
|
{ "", "", FT_NONE, BASE_NONE, NULL, 0x0,
|
2001-07-13 00:55:58 +00:00
|
|
|
NULL, HFILL }},
|
1999-10-12 06:21:15 +00:00
|
|
|
};
|
|
|
|
|
2005-01-12 21:31:22 +00:00
|
|
|
|
|
|
|
proto_names = g_hash_table_new(g_int_hash, g_int_equal);
|
|
|
|
proto_short_names = g_hash_table_new(g_int_hash, g_int_equal);
|
|
|
|
proto_filter_names = g_hash_table_new(g_int_hash, g_int_equal);
|
|
|
|
|
2003-08-25 00:15:02 +00:00
|
|
|
proto_cleanup();
|
1999-07-07 22:52:57 +00:00
|
|
|
|
|
|
|
gmc_hfinfo = g_mem_chunk_new("gmc_hfinfo",
|
2001-12-18 19:09:08 +00:00
|
|
|
sizeof(header_field_info),
|
|
|
|
INITIAL_NUM_PROTOCOL_HFINFO * sizeof(header_field_info),
|
|
|
|
G_ALLOC_ONLY);
|
|
|
|
|
2003-11-21 14:58:49 +00:00
|
|
|
gpa_hfinfo.len=0;
|
|
|
|
gpa_hfinfo.allocated_len=0;
|
|
|
|
gpa_hfinfo.hfi=NULL;
|
2003-08-25 00:15:02 +00:00
|
|
|
gpa_name_tree = g_tree_new(g_strcmp);
|
1999-07-07 22:52:57 +00:00
|
|
|
|
2001-02-01 20:21:25 +00:00
|
|
|
/* Initialize the ftype subsystem */
|
|
|
|
ftypes_initialize();
|
|
|
|
|
2003-08-25 00:15:02 +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 */
|
|
|
|
proto_register_field_array(-1, hf, array_length(hf));
|
|
|
|
|
Clean up the dissector registration up a bit - arrange that all plugins
be loaded and their initialization routines called in right after we
call the initialization routines for built-in dissectors, but don't call
their handoff registration routines yet, and then call the handoff
registration routines right after calling the handoff registration
routines for built-in dissectors.
Do all that in "proto_init()", rather than "epan_init()".
That way, we call all dissector registration routines together, and then
call all dissector handoff registration routines together; all the
registration routines are called before any handoff registration
routines, as is required, and, as "proto_init()" is called by
"epan_init()" before "dfilter_init()" is called, all filterable fields
have been registered before "dfilter_init()" is called, and no plugins
have to call "dfilter_init()" themselves to get their fields registered.
Remove pointers to "dfilter_init()" and "dfilter_cleanup()" from the
plugin address table, as plugins shouldn't be calling them any more, and
remove calls to them from plugins.
svn path=/trunk/; revision=2940
2001-01-26 06:14:53 +00:00
|
|
|
/* Have each built-in dissector register its protocols, fields,
|
|
|
|
dissector tables, and dissectors to be called through a
|
|
|
|
handle, 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
|
|
|
|
Clean up the dissector registration up a bit - arrange that all plugins
be loaded and their initialization routines called in right after we
call the initialization routines for built-in dissectors, but don't call
their handoff registration routines yet, and then call the handoff
registration routines right after calling the handoff registration
routines for built-in dissectors.
Do all that in "proto_init()", rather than "epan_init()".
That way, we call all dissector registration routines together, and then
call all dissector handoff registration routines together; all the
registration routines are called before any handoff registration
routines, as is required, and, as "proto_init()" is called by
"epan_init()" before "dfilter_init()" is called, all filterable fields
have been registered before "dfilter_init()" is called, and no plugins
have to call "dfilter_init()" themselves to get their fields registered.
Remove pointers to "dfilter_init()" and "dfilter_cleanup()" from the
plugin address table, as plugins shouldn't be calling them any more, and
remove calls to them from plugins.
svn path=/trunk/; revision=2940
2001-01-26 06:14:53 +00:00
|
|
|
#ifdef HAVE_PLUGINS
|
|
|
|
/* Now scan for plugins and load all the ones we find, calling
|
|
|
|
their register routines to do the stuff described above. */
|
|
|
|
init_plugins(plugin_dir);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* Now call the "handoff registration" routines of all built-in
|
|
|
|
dissectors; those routines register the dissector in other
|
|
|
|
dissectors' handoff tables, and fetch any dissector handles
|
|
|
|
they need. */
|
2000-04-04 06:17:30 +00:00
|
|
|
register_all_protocol_handoffs();
|
|
|
|
|
2001-04-05 19:25:16 +00:00
|
|
|
#ifdef HAVE_PLUGINS
|
Clean up the dissector registration up a bit - arrange that all plugins
be loaded and their initialization routines called in right after we
call the initialization routines for built-in dissectors, but don't call
their handoff registration routines yet, and then call the handoff
registration routines right after calling the handoff registration
routines for built-in dissectors.
Do all that in "proto_init()", rather than "epan_init()".
That way, we call all dissector registration routines together, and then
call all dissector handoff registration routines together; all the
registration routines are called before any handoff registration
routines, as is required, and, as "proto_init()" is called by
"epan_init()" before "dfilter_init()" is called, all filterable fields
have been registered before "dfilter_init()" is called, and no plugins
have to call "dfilter_init()" themselves to get their fields registered.
Remove pointers to "dfilter_init()" and "dfilter_cleanup()" from the
plugin address table, as plugins shouldn't be calling them any more, and
remove calls to them from plugins.
svn path=/trunk/; revision=2940
2001-01-26 06:14:53 +00:00
|
|
|
/* Now do the same with plugins. */
|
|
|
|
register_all_plugin_handoffs();
|
2001-04-05 19:25:16 +00:00
|
|
|
#endif
|
Clean up the dissector registration up a bit - arrange that all plugins
be loaded and their initialization routines called in right after we
call the initialization routines for built-in dissectors, but don't call
their handoff registration routines yet, and then call the handoff
registration routines right after calling the handoff registration
routines for built-in dissectors.
Do all that in "proto_init()", rather than "epan_init()".
That way, we call all dissector registration routines together, and then
call all dissector handoff registration routines together; all the
registration routines are called before any handoff registration
routines, as is required, and, as "proto_init()" is called by
"epan_init()" before "dfilter_init()" is called, all filterable fields
have been registered before "dfilter_init()" is called, and no plugins
have to call "dfilter_init()" themselves to get their fields registered.
Remove pointers to "dfilter_init()" and "dfilter_cleanup()" from the
plugin address table, as plugins shouldn't be calling them any more, and
remove calls to them from plugins.
svn path=/trunk/; revision=2940
2001-01-26 06:14:53 +00:00
|
|
|
|
2005-01-12 21:31:22 +00:00
|
|
|
/* sort the protocols by protocol name */
|
|
|
|
protocols = g_list_sort(protocols, proto_compare_name);
|
|
|
|
|
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. */
|
2005-12-22 01:36:42 +00:00
|
|
|
tree_is_expanded = g_malloc(num_tree_types*sizeof (gboolean));
|
|
|
|
memset(tree_is_expanded, 0, num_tree_types*sizeof (gboolean));
|
1999-07-07 22:52:57 +00:00
|
|
|
}
|
|
|
|
|
2002-04-29 07:55:32 +00:00
|
|
|
/* String comparison func for dfilter_token GTree */
|
|
|
|
static int
|
|
|
|
g_strcmp(gconstpointer a, gconstpointer b)
|
|
|
|
{
|
|
|
|
return strcmp((const char*)a, (const char*)b);
|
|
|
|
}
|
|
|
|
|
1999-08-26 06:20:50 +00:00
|
|
|
void
|
|
|
|
proto_cleanup(void)
|
|
|
|
{
|
2002-04-29 07:55:32 +00:00
|
|
|
/* Free the abbrev/ID GTree */
|
|
|
|
if (gpa_name_tree) {
|
|
|
|
g_tree_destroy(gpa_name_tree);
|
|
|
|
gpa_name_tree = NULL;
|
|
|
|
}
|
|
|
|
|
1999-08-26 06:20:50 +00:00
|
|
|
if (gmc_hfinfo)
|
|
|
|
g_mem_chunk_destroy(gmc_hfinfo);
|
2003-11-24 21:12:10 +00:00
|
|
|
|
2003-11-21 14:58:49 +00:00
|
|
|
if(gpa_hfinfo.allocated_len){
|
|
|
|
gpa_hfinfo.len=0;
|
|
|
|
gpa_hfinfo.allocated_len=0;
|
|
|
|
g_free(gpa_hfinfo.hfi);
|
|
|
|
gpa_hfinfo.hfi=NULL;
|
|
|
|
}
|
2001-12-18 19:09:08 +00:00
|
|
|
if (tree_is_expanded != NULL)
|
|
|
|
g_free(tree_is_expanded);
|
2001-02-01 20:21:25 +00:00
|
|
|
|
1999-08-26 06:20:50 +00:00
|
|
|
}
|
|
|
|
|
2003-12-04 10:59:34 +00:00
|
|
|
typedef gboolean (*proto_tree_traverse_func)(proto_node *, gpointer);
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
proto_tree_traverse_pre_order(proto_tree *tree, proto_tree_traverse_func func,
|
|
|
|
gpointer data)
|
|
|
|
{
|
|
|
|
proto_node *pnode = tree;
|
|
|
|
proto_node *child;
|
|
|
|
proto_node *current;
|
|
|
|
|
|
|
|
if (func(pnode, data))
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
child = pnode->first_child;
|
|
|
|
while (child != NULL) {
|
|
|
|
/*
|
|
|
|
* The routine we call might modify the child, e.g. by
|
|
|
|
* freeing it, so we get the child's successor before
|
|
|
|
* calling that routine.
|
|
|
|
*/
|
|
|
|
current = child;
|
|
|
|
child = current->next;
|
|
|
|
if (proto_tree_traverse_pre_order((proto_tree *)current, func,
|
|
|
|
data))
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
proto_tree_traverse_in_order(proto_tree *tree, proto_tree_traverse_func func,
|
|
|
|
gpointer data)
|
|
|
|
{
|
|
|
|
proto_node *pnode = tree;
|
|
|
|
proto_node *child;
|
|
|
|
proto_node *current;
|
|
|
|
|
|
|
|
child = pnode->first_child;
|
|
|
|
if (child != NULL) {
|
|
|
|
/*
|
|
|
|
* The routine we call might modify the child, e.g. by
|
|
|
|
* freeing it, so we get the child's successor before
|
|
|
|
* calling that routine.
|
|
|
|
*/
|
|
|
|
current = child;
|
|
|
|
child = current->next;
|
|
|
|
|
|
|
|
if (proto_tree_traverse_in_order((proto_tree *)current, func,
|
|
|
|
data))
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
if (func(pnode, data))
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
while (child != NULL) {
|
|
|
|
/*
|
|
|
|
* The routine we call might modify the child, e.g. by
|
|
|
|
* freeing it, so we get the child's successor before
|
|
|
|
* calling that routine.
|
|
|
|
*/
|
|
|
|
current = child;
|
|
|
|
child = current->next;
|
|
|
|
if (proto_tree_traverse_in_order((proto_tree *)current,
|
|
|
|
func, data))
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (func(pnode, data))
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
proto_tree_children_foreach(proto_tree *tree, proto_tree_foreach_func func,
|
|
|
|
gpointer data)
|
|
|
|
{
|
|
|
|
proto_node *node = tree;
|
|
|
|
proto_node *current;
|
|
|
|
|
|
|
|
node = node->first_child;
|
|
|
|
while (node != NULL) {
|
|
|
|
current = node;
|
|
|
|
node = current->next;
|
|
|
|
func((proto_tree *)current, data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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)
|
|
|
|
{
|
2003-12-04 10:59:34 +00:00
|
|
|
proto_tree_traverse_in_order(tree, proto_tree_free_node, NULL);
|
1999-07-07 22:52:57 +00:00
|
|
|
}
|
|
|
|
|
2001-12-18 19:09:08 +00:00
|
|
|
static void
|
2002-03-02 20:51:46 +00:00
|
|
|
free_GPtrArray_value(gpointer key _U_, gpointer value, gpointer user_data _U_)
|
1999-07-07 22:52:57 +00:00
|
|
|
{
|
2002-04-20 08:07:56 +00:00
|
|
|
GPtrArray *ptrs = value;
|
2005-04-11 08:43:51 +00:00
|
|
|
gint hfid = (gint)key;
|
|
|
|
header_field_info *hfinfo;
|
|
|
|
|
|
|
|
|
|
|
|
PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
|
|
|
|
if(hfinfo->ref_count){
|
|
|
|
/* when a field is referenced by a filter this also
|
|
|
|
affects the refcount for the parent protocol so we need
|
|
|
|
to adjust the refcount for the parent as well
|
|
|
|
*/
|
|
|
|
if( (hfinfo->parent != -1) && (hfinfo->ref_count) ){
|
|
|
|
header_field_info *parent_hfinfo;
|
|
|
|
PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
|
|
|
|
parent_hfinfo->ref_count -= hfinfo->ref_count;
|
|
|
|
}
|
|
|
|
hfinfo->ref_count = 0;
|
|
|
|
}
|
1999-08-04 23:43:42 +00:00
|
|
|
|
2002-04-20 08:07:56 +00:00
|
|
|
g_ptr_array_free(ptrs, TRUE);
|
2001-12-18 19:09:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
free_node_tree_data(tree_data_t *tree_data)
|
|
|
|
{
|
|
|
|
/* Free all the GPtrArray's in the interesting_hfids hash. */
|
|
|
|
g_hash_table_foreach(tree_data->interesting_hfids,
|
|
|
|
free_GPtrArray_value, NULL);
|
|
|
|
|
|
|
|
/* And then destroy the hash. */
|
|
|
|
g_hash_table_destroy(tree_data->interesting_hfids);
|
|
|
|
|
|
|
|
/* And finally the tree_data_t itself. */
|
|
|
|
g_free(tree_data);
|
|
|
|
}
|
|
|
|
|
2003-11-25 14:16:30 +00:00
|
|
|
#define FREE_NODE_FIELD_INFO(finfo) \
|
2003-11-26 12:22:22 +00:00
|
|
|
if(finfo->rep){ \
|
|
|
|
ITEM_LABEL_FREE(finfo->rep); \
|
|
|
|
} \
|
2003-12-02 21:15:49 +00:00
|
|
|
FVALUE_CLEANUP(&finfo->value); \
|
2003-11-25 14:11:44 +00:00
|
|
|
FIELD_INFO_FREE(finfo);
|
2001-12-18 19:09:08 +00:00
|
|
|
|
|
|
|
static gboolean
|
2003-12-04 10:59:34 +00:00
|
|
|
proto_tree_free_node(proto_node *node, gpointer data _U_)
|
2001-12-18 19:09:08 +00:00
|
|
|
{
|
|
|
|
field_info *finfo = PITEM_FINFO(node);
|
|
|
|
|
2002-04-18 20:19:10 +00:00
|
|
|
if (finfo == NULL) {
|
2003-12-04 10:59:34 +00:00
|
|
|
/* This is the root node. Destroy the per-tree data.
|
2002-04-18 20:19:10 +00:00
|
|
|
* There is no field_info to destroy. */
|
|
|
|
free_node_tree_data(PTREE_DATA(node));
|
|
|
|
}
|
|
|
|
else {
|
2003-12-04 10:59:34 +00:00
|
|
|
/* This is a child node. Don't free the per-tree data, but
|
2002-04-18 20:19:10 +00:00
|
|
|
* do free the field_info data. */
|
2003-11-25 14:16:30 +00:00
|
|
|
FREE_NODE_FIELD_INFO(finfo);
|
1999-08-04 23:43:42 +00:00
|
|
|
}
|
2001-12-18 19:09:08 +00:00
|
|
|
|
2002-04-18 20:19:10 +00:00
|
|
|
/* Free the proto_node. */
|
2003-12-04 10:59:34 +00:00
|
|
|
PROTO_NODE_FREE(node);
|
2001-12-18 19:09:08 +00:00
|
|
|
|
2003-12-04 10:59:34 +00:00
|
|
|
return FALSE; /* FALSE = do not end traversal of protocol tree */
|
2001-12-18 19:09:08 +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
|
2005-08-18 19:31:15 +00:00
|
|
|
* having to call g_vsnprintf and copy strings around.
|
2001-12-18 19:09:08 +00:00
|
|
|
*/
|
|
|
|
void
|
|
|
|
proto_tree_set_visible(proto_tree *tree, gboolean visible)
|
|
|
|
{
|
2002-04-18 20:19:10 +00:00
|
|
|
PTREE_DATA(tree)->visible = visible;
|
2001-12-18 19:09:08 +00:00
|
|
|
}
|
1999-07-07 22:52:57 +00:00
|
|
|
|
2005-04-11 08:43:51 +00:00
|
|
|
/* Assume dissector set only its protocol fields.
|
|
|
|
This function is called by dissectors and allowes to speed up filtering
|
|
|
|
in ethereal, if this function returns FALSE it is safe to reset tree to NULL
|
|
|
|
and thus skip calling most of the expensive proto_tree_add_...()
|
|
|
|
functions.
|
|
|
|
If the tree is visible we implicitely assume the field is referenced.
|
|
|
|
*/
|
|
|
|
gboolean
|
|
|
|
proto_field_is_referenced(proto_tree *tree, int proto_id)
|
|
|
|
{
|
|
|
|
register header_field_info *hfinfo;
|
|
|
|
|
|
|
|
|
|
|
|
if (!tree)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (PTREE_DATA(tree)->visible)
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
|
|
|
|
if (hfinfo->ref_count != 0)
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2003-11-22 04:41:31 +00:00
|
|
|
|
2000-04-03 09:24:12 +00:00
|
|
|
/* Finds a record in the hf_info_records array by id. */
|
2001-02-01 20:21:25 +00:00
|
|
|
header_field_info*
|
2003-11-21 14:58:49 +00:00
|
|
|
proto_registrar_get_nth(guint hfindex)
|
1999-07-07 22:52:57 +00:00
|
|
|
{
|
2003-11-22 04:41:31 +00:00
|
|
|
register header_field_info *hfinfo;
|
|
|
|
|
|
|
|
PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
|
|
|
|
return hfinfo;
|
1999-07-07 22:52:57 +00:00
|
|
|
}
|
|
|
|
|
2002-04-18 20:19:10 +00:00
|
|
|
/* Finds a record in the hf_info_records array by name.
|
|
|
|
*/
|
|
|
|
header_field_info*
|
2004-12-31 02:02:19 +00:00
|
|
|
proto_registrar_get_byname(const char *field_name)
|
2002-04-18 20:19:10 +00:00
|
|
|
{
|
2005-03-23 00:09:12 +00:00
|
|
|
DISSECTOR_ASSERT(field_name != NULL);
|
2005-07-23 11:41:25 +00:00
|
|
|
return g_tree_lookup(gpa_name_tree, field_name);
|
2002-04-18 20:19:10 +00:00
|
|
|
}
|
2000-03-12 04:48:32 +00:00
|
|
|
|
2005-10-22 05:43:09 +00:00
|
|
|
/* Allocates an initializes a ptvcursor_t with 3 variables:
|
|
|
|
* proto_tree, tvbuff, and offset. */
|
|
|
|
ptvcursor_t*
|
|
|
|
ptvcursor_new(proto_tree *tree, tvbuff_t *tvb, gint offset)
|
|
|
|
{
|
|
|
|
ptvcursor_t *ptvc;
|
|
|
|
|
|
|
|
ptvc = g_new(ptvcursor_t, 1);
|
|
|
|
ptvc->tree = tree;
|
|
|
|
ptvc->tvb = tvb;
|
|
|
|
ptvc->offset = offset;
|
|
|
|
return ptvc;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Frees memory for ptvcursor_t, but nothing deeper than that. */
|
|
|
|
void
|
|
|
|
ptvcursor_free(ptvcursor_t *ptvc)
|
|
|
|
{
|
|
|
|
g_free(ptvc);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Returns tvbuff. */
|
|
|
|
tvbuff_t*
|
|
|
|
ptvcursor_tvbuff(ptvcursor_t* ptvc)
|
|
|
|
{
|
|
|
|
return ptvc->tvb;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Returns current offset. */
|
|
|
|
gint
|
|
|
|
ptvcursor_current_offset(ptvcursor_t* ptvc)
|
|
|
|
{
|
|
|
|
return ptvc->offset;
|
|
|
|
}
|
|
|
|
|
|
|
|
proto_tree*
|
|
|
|
ptvcursor_tree(ptvcursor_t* ptvc)
|
|
|
|
{
|
|
|
|
return ptvc->tree;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
ptvcursor_set_tree(ptvcursor_t* ptvc, proto_tree *tree)
|
|
|
|
{
|
|
|
|
ptvc->tree = tree;
|
|
|
|
}
|
|
|
|
|
Get rid of "proto_tree_add_notext()" - if you create a subtree using it,
but, before you set the text, you throw an exception while putting stuff
under the subtree, you end up with an absolutely blank protocol tree
item, which is really gross. Instead of calling
"proto_tree_add_notext()", call "proto_tree_add_text()" with at least a
minimal label - yes, it does mean you do some work that will probably be
unnecessary, but, absent a scheme to arrange to do that work if it *is*
necessary (e.g., catching exceptions), the alternative is an ugly
protocol tree display.
svn path=/trunk/; revision=3879
2001-08-28 08:28:19 +00:00
|
|
|
/* Add a text-only node, leaving it to our caller to fill the text in */
|
|
|
|
static proto_item *
|
|
|
|
proto_tree_add_text_node(proto_tree *tree, tvbuff_t *tvb, gint start, gint length)
|
1999-07-07 22:52:57 +00:00
|
|
|
{
|
|
|
|
proto_item *pi;
|
|
|
|
|
2002-02-18 22:26:29 +00:00
|
|
|
pi = proto_tree_add_pi(tree, hf_text_only, tvb, start, &length, NULL);
|
2000-05-31 05:09:07 +00:00
|
|
|
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;
|
|
|
|
|
Get rid of "proto_tree_add_notext()" - if you create a subtree using it,
but, before you set the text, you throw an exception while putting stuff
under the subtree, you end up with an absolutely blank protocol tree
item, which is really gross. Instead of calling
"proto_tree_add_notext()", call "proto_tree_add_text()" with at least a
minimal label - yes, it does mean you do some work that will probably be
unnecessary, but, absent a scheme to arrange to do that work if it *is*
necessary (e.g., catching exceptions), the alternative is an ugly
protocol tree display.
svn path=/trunk/; revision=3879
2001-08-28 08:28:19 +00:00
|
|
|
pi = proto_tree_add_text_node(tree, tvb, start, length);
|
2000-05-31 05:09:07 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2000-08-10 16:04:33 +00:00
|
|
|
/* Add a text-only node to the proto_tree (va_list version) */
|
|
|
|
proto_item *
|
2002-08-28 20:41:00 +00:00
|
|
|
proto_tree_add_text_valist(proto_tree *tree, tvbuff_t *tvb, gint start,
|
2000-08-10 16:04:33 +00:00
|
|
|
gint length, const char *format, va_list ap)
|
|
|
|
{
|
|
|
|
proto_item *pi;
|
|
|
|
|
Get rid of "proto_tree_add_notext()" - if you create a subtree using it,
but, before you set the text, you throw an exception while putting stuff
under the subtree, you end up with an absolutely blank protocol tree
item, which is really gross. Instead of calling
"proto_tree_add_notext()", call "proto_tree_add_text()" with at least a
minimal label - yes, it does mean you do some work that will probably be
unnecessary, but, absent a scheme to arrange to do that work if it *is*
necessary (e.g., catching exceptions), the alternative is an ugly
protocol tree display.
svn path=/trunk/; revision=3879
2001-08-28 08:28:19 +00:00
|
|
|
pi = proto_tree_add_text_node(tree, tvb, start, length);
|
2000-08-10 16:04:33 +00:00
|
|
|
if (pi == NULL)
|
|
|
|
return(NULL);
|
|
|
|
|
|
|
|
proto_tree_set_representation(pi, format, ap);
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
Get rid of "proto_tree_add_notext()" - if you create a subtree using it,
but, before you set the text, you throw an exception while putting stuff
under the subtree, you end up with an absolutely blank protocol tree
item, which is really gross. Instead of calling
"proto_tree_add_notext()", call "proto_tree_add_text()" with at least a
minimal label - yes, it does mean you do some work that will probably be
unnecessary, but, absent a scheme to arrange to do that work if it *is*
necessary (e.g., catching exceptions), the alternative is an ugly
protocol tree display.
svn path=/trunk/; revision=3879
2001-08-28 08:28:19 +00:00
|
|
|
pi = proto_tree_add_text_node(tree, NULL, 0, 0);
|
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
|
|
|
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:
|
2005-05-26 14:53:39 +00:00
|
|
|
THROW(ReportedBoundsError);
|
2000-05-31 05:09:07 +00:00
|
|
|
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:
|
2005-05-26 14:53:39 +00:00
|
|
|
THROW(ReportedBoundsError);
|
2000-05-31 05:09:07 +00:00
|
|
|
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. */
|
2005-10-22 05:43:09 +00:00
|
|
|
static proto_item *
|
|
|
|
proto_tree_new_item(field_info *new_fi, proto_tree *tree, int hfindex,
|
|
|
|
tvbuff_t *tvb, gint start, gint length, gboolean little_endian)
|
1999-07-07 22:52:57 +00:00
|
|
|
{
|
2000-07-27 06:41:59 +00:00
|
|
|
proto_item *pi;
|
|
|
|
guint32 value, n;
|
2004-08-10 21:23:34 +00:00
|
|
|
float floatval;
|
|
|
|
double doubleval;
|
2000-08-30 02:50:18 +00:00
|
|
|
char *string;
|
2002-02-18 22:26:29 +00:00
|
|
|
GHashTable *hash;
|
|
|
|
GPtrArray *ptrs;
|
2000-03-12 04:48:32 +00:00
|
|
|
|
2003-11-24 21:12:10 +00:00
|
|
|
/* there is a possibility here that we might raise an exception
|
|
|
|
* and thus would lose track of the field_info.
|
|
|
|
* store it in a temp so that if we come here again we can reclaim
|
|
|
|
* the field_info without leaking memory.
|
|
|
|
*/
|
|
|
|
/* XXX this only keeps track of one field_info struct,
|
|
|
|
if we ever go multithreaded for calls to this function
|
|
|
|
we have to change this code to use per thread variable.
|
|
|
|
*/
|
|
|
|
if(field_info_tmp){
|
|
|
|
/* oops, last one we got must have been lost due
|
|
|
|
* to an exception.
|
|
|
|
* good thing we saved it, now we can reverse the
|
|
|
|
* memory leak and reclaim it.
|
|
|
|
*/
|
2004-07-04 00:28:11 +00:00
|
|
|
SLAB_FREE(field_info_tmp, field_info);
|
2003-11-24 21:12:10 +00:00
|
|
|
}
|
|
|
|
/* we might throw an exception, keep track of this one
|
|
|
|
* across the "dangerous" section below.
|
|
|
|
*/
|
|
|
|
field_info_tmp=new_fi;
|
2000-08-24 02:55:36 +00:00
|
|
|
|
2003-12-03 09:28:26 +00:00
|
|
|
switch(new_fi->hfinfo->type) {
|
2000-05-31 05:09:07 +00:00
|
|
|
case FT_NONE:
|
|
|
|
/* no value to set for FT_NONE */
|
|
|
|
break;
|
|
|
|
|
2001-02-01 20:21:25 +00:00
|
|
|
case FT_PROTOCOL:
|
|
|
|
proto_tree_set_protocol_tvb(new_fi, tvb);
|
|
|
|
break;
|
|
|
|
|
2000-05-31 05:09:07 +00:00
|
|
|
case FT_BYTES:
|
|
|
|
proto_tree_set_bytes_tvb(new_fi, tvb, start, length);
|
|
|
|
break;
|
|
|
|
|
2002-05-09 23:50:34 +00:00
|
|
|
case FT_UINT_BYTES:
|
|
|
|
n = get_uint_value(tvb, start, length, little_endian);
|
|
|
|
proto_tree_set_bytes_tvb(new_fi, tvb, start + length, n);
|
|
|
|
|
|
|
|
/* Instead of calling proto_item_set_len(), since we don't yet
|
|
|
|
* have a proto_item, we set the field_info's length ourselves. */
|
|
|
|
new_fi->length = n + length;
|
|
|
|
break;
|
|
|
|
|
2000-05-31 05:09:07 +00:00
|
|
|
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;
|
|
|
|
|
2001-11-02 10:09:51 +00:00
|
|
|
case FT_INT64:
|
2001-10-29 21:13:13 +00:00
|
|
|
case FT_UINT64:
|
2005-03-23 00:09:12 +00:00
|
|
|
DISSECTOR_ASSERT(length == 8);
|
2001-10-29 21:13:13 +00:00
|
|
|
proto_tree_set_uint64_tvb(new_fi, tvb, start, little_endian);
|
|
|
|
break;
|
|
|
|
|
2000-05-31 05:09:07 +00:00
|
|
|
/* 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:
|
2005-03-23 00:09:12 +00:00
|
|
|
DISSECTOR_ASSERT(length == 4);
|
2005-09-10 19:43:41 +00:00
|
|
|
value = tvb_get_ipv4(tvb, start);
|
2004-09-08 19:36:25 +00:00
|
|
|
proto_tree_set_ipv4(new_fi, little_endian ? GUINT32_SWAP_LE_BE(value) : value);
|
2000-05-31 05:09:07 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case FT_IPXNET:
|
2005-03-23 00:09:12 +00:00
|
|
|
DISSECTOR_ASSERT(length == 4);
|
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
|
|
|
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:
|
2005-03-23 00:09:12 +00:00
|
|
|
DISSECTOR_ASSERT(length == 16);
|
2000-05-31 05:09:07 +00:00
|
|
|
proto_tree_set_ipv6_tvb(new_fi, tvb, start);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case FT_ETHER:
|
2005-03-23 00:09:12 +00:00
|
|
|
DISSECTOR_ASSERT(length == 6);
|
2000-05-31 05:09:07 +00:00
|
|
|
proto_tree_set_ether_tvb(new_fi, tvb, start);
|
|
|
|
break;
|
|
|
|
|
2005-07-04 13:04:53 +00:00
|
|
|
case FT_GUID:
|
|
|
|
DISSECTOR_ASSERT(length == 16);
|
|
|
|
proto_tree_set_guid_tvb(new_fi, tvb, start);
|
|
|
|
break;
|
|
|
|
|
2005-12-02 13:16:58 +00:00
|
|
|
case FT_OID:
|
|
|
|
proto_tree_set_oid_tvb(new_fi, tvb, start, length);
|
|
|
|
break;
|
|
|
|
|
2004-08-10 21:23:34 +00:00
|
|
|
case FT_FLOAT:
|
2005-03-23 00:09:12 +00:00
|
|
|
DISSECTOR_ASSERT(length == 4);
|
2004-08-10 21:23:34 +00:00
|
|
|
if (little_endian)
|
|
|
|
floatval = tvb_get_letohieee_float(tvb, start);
|
|
|
|
else
|
|
|
|
floatval = tvb_get_ntohieee_float(tvb, start);
|
|
|
|
proto_tree_set_float(new_fi, floatval);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case FT_DOUBLE:
|
2005-03-23 00:09:12 +00:00
|
|
|
DISSECTOR_ASSERT(length == 8);
|
2004-08-10 21:23:34 +00:00
|
|
|
if (little_endian)
|
|
|
|
doubleval = tvb_get_letohieee_double(tvb, start);
|
|
|
|
else
|
|
|
|
doubleval = tvb_get_ntohieee_double(tvb, start);
|
|
|
|
proto_tree_set_double(new_fi, doubleval);
|
|
|
|
break;
|
|
|
|
|
2000-05-31 05:09:07 +00:00
|
|
|
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;
|
|
|
|
|
2000-08-30 02:50:18 +00:00
|
|
|
case FT_STRINGZ:
|
2005-06-15 15:10:02 +00:00
|
|
|
DISSECTOR_ASSERT(length >= -1);
|
|
|
|
/* Instead of calling proto_item_set_len(),
|
|
|
|
* since we don't yet have a proto_item, we
|
|
|
|
* set the field_info's length ourselves.
|
|
|
|
*
|
|
|
|
* XXX - our caller can't use that length to
|
|
|
|
* advance an offset unless they arrange that
|
|
|
|
* there always be a protocol tree into which
|
|
|
|
* we're putting this item.
|
|
|
|
*/
|
|
|
|
if (length == -1) {
|
|
|
|
/* This can throw an exception */
|
|
|
|
length = tvb_strsize(tvb, start);
|
|
|
|
|
|
|
|
/* This g_malloc'ed memory is freed
|
|
|
|
in proto_tree_free_node() */
|
|
|
|
string = g_malloc(length);
|
|
|
|
|
|
|
|
tvb_memcpy(tvb, string, start, length);
|
|
|
|
} else if (length == 0) {
|
|
|
|
string = g_strdup("[Empty]");
|
|
|
|
} else {
|
|
|
|
/* In this case, length signifies
|
|
|
|
* the length of the string.
|
When "proto_tree_add_item()" is used with an FT_STRINGZ and given a
length (rather than being given -1), the length is, in most cases, the
maximum length of a null-*padded* string, rather than the actual length
of a null-*terminated* string. Treat it as such - allocate a buffer one
larger than the length (to leave room for a terminating '\0'), and pass
the size of that buffer to "tvb_get_nstringz0()". (Otherwise, in those
cases, the last character of the string is chopped off.)
Allow "proto_tree_add_string()" to add FT_STRINGZ items to the protocol
tree, as well as FT_STRING items.
In "alloc_field_info()", if we're passed a length of -1 and the field is
an FT_STRINGZ, don't make the length be the length remaining in the
tvbuff; that way, you *can* use a length of -1 in
"proto_tree_add_item()" for an FT_STRINGZ item, and have it get the
actual length by looking for the terminating '\0'.
(We might want to distinguish between null-terminated and null-padded
strings, e.g. with an FT_STRINGZPAD type. Null-terminated strings
rarely, if ever, have a specified length; the length is found by
scanning for the terminating '\0'. Null-padded strings presumably
always have a specified length, which is the length to which the string
is padded.)
svn path=/trunk/; revision=7784
2003-06-04 21:51:54 +00:00
|
|
|
*
|
2005-06-15 15:10:02 +00:00
|
|
|
* This could either be a null-padded
|
|
|
|
* string, which doesn't necessarily
|
|
|
|
* have a '\0' at the end, or a
|
|
|
|
* null-terminated string, with a
|
|
|
|
* trailing '\0'. (Yes, there are
|
|
|
|
* cases where you have a string
|
|
|
|
* that's both counted and null-
|
|
|
|
* terminated.)
|
|
|
|
*
|
|
|
|
* In the first case, we must
|
|
|
|
* allocate a buffer of length
|
|
|
|
* "length+1", to make room for
|
|
|
|
* a trailing '\0'.
|
|
|
|
*
|
|
|
|
* In the second case, we don't
|
|
|
|
* assume that there is a trailing
|
|
|
|
* '\0' there, as the packet might
|
|
|
|
* be malformed. (XXX - should we
|
|
|
|
* throw an exception if there's no
|
|
|
|
* trailing '\0'?) Therefore, we
|
|
|
|
* allocate a buffer of length
|
|
|
|
* "length+1", and put in a trailing
|
|
|
|
* '\0', just to be safe.
|
|
|
|
*
|
|
|
|
* (XXX - this would change if
|
|
|
|
* we made string values counted
|
|
|
|
* rather than null-terminated.)
|
When "proto_tree_add_item()" is used with an FT_STRINGZ and given a
length (rather than being given -1), the length is, in most cases, the
maximum length of a null-*padded* string, rather than the actual length
of a null-*terminated* string. Treat it as such - allocate a buffer one
larger than the length (to leave room for a terminating '\0'), and pass
the size of that buffer to "tvb_get_nstringz0()". (Otherwise, in those
cases, the last character of the string is chopped off.)
Allow "proto_tree_add_string()" to add FT_STRINGZ items to the protocol
tree, as well as FT_STRING items.
In "alloc_field_info()", if we're passed a length of -1 and the field is
an FT_STRINGZ, don't make the length be the length remaining in the
tvbuff; that way, you *can* use a length of -1 in
"proto_tree_add_item()" for an FT_STRINGZ item, and have it get the
actual length by looking for the terminating '\0'.
(We might want to distinguish between null-terminated and null-padded
strings, e.g. with an FT_STRINGZPAD type. Null-terminated strings
rarely, if ever, have a specified length; the length is found by
scanning for the terminating '\0'. Null-padded strings presumably
always have a specified length, which is the length to which the string
is padded.)
svn path=/trunk/; revision=7784
2003-06-04 21:51:54 +00:00
|
|
|
*/
|
2005-06-15 15:10:02 +00:00
|
|
|
|
|
|
|
/* This g_malloc'ed memory is freed
|
|
|
|
* in proto_tree_free_node() */
|
|
|
|
string = tvb_get_string(tvb, start,
|
|
|
|
length);
|
2002-05-09 23:50:34 +00:00
|
|
|
}
|
2005-06-15 15:10:02 +00:00
|
|
|
new_fi->length = length;
|
|
|
|
proto_tree_set_string(new_fi, string, TRUE);
|
2000-08-30 02:50:18 +00:00
|
|
|
break;
|
|
|
|
|
2000-08-22 06:38:32 +00:00
|
|
|
case FT_UINT_STRING:
|
2000-07-27 06:41:59 +00:00
|
|
|
/* This g_strdup'ed memory is freed in proto_tree_free_node() */
|
2000-08-22 06:38:32 +00:00
|
|
|
n = get_uint_value(tvb, start, length, little_endian);
|
2001-08-04 19:57:30 +00:00
|
|
|
proto_tree_set_string_tvb(new_fi, tvb, start + length, n);
|
2000-08-22 06:38:32 +00:00
|
|
|
|
When "proto_tree_add_item()" is used with an FT_STRINGZ and given a
length (rather than being given -1), the length is, in most cases, the
maximum length of a null-*padded* string, rather than the actual length
of a null-*terminated* string. Treat it as such - allocate a buffer one
larger than the length (to leave room for a terminating '\0'), and pass
the size of that buffer to "tvb_get_nstringz0()". (Otherwise, in those
cases, the last character of the string is chopped off.)
Allow "proto_tree_add_string()" to add FT_STRINGZ items to the protocol
tree, as well as FT_STRING items.
In "alloc_field_info()", if we're passed a length of -1 and the field is
an FT_STRINGZ, don't make the length be the length remaining in the
tvbuff; that way, you *can* use a length of -1 in
"proto_tree_add_item()" for an FT_STRINGZ item, and have it get the
actual length by looking for the terminating '\0'.
(We might want to distinguish between null-terminated and null-padded
strings, e.g. with an FT_STRINGZPAD type. Null-terminated strings
rarely, if ever, have a specified length; the length is found by
scanning for the terminating '\0'. Null-padded strings presumably
always have a specified length, which is the length to which the string
is padded.)
svn path=/trunk/; revision=7784
2003-06-04 21:51:54 +00:00
|
|
|
/* Instead of calling proto_item_set_len(), since we
|
|
|
|
* don't yet have a proto_item, we set the
|
|
|
|
* field_info's length ourselves.
|
|
|
|
*
|
|
|
|
* XXX - our caller can't use that length to
|
|
|
|
* advance an offset unless they arrange that
|
|
|
|
* there always be a protocol tree into which
|
|
|
|
* we're putting this item.
|
|
|
|
*/
|
2001-08-04 19:57:30 +00:00
|
|
|
new_fi->length = n + length;
|
2000-07-27 06:41:59 +00:00
|
|
|
break;
|
When "proto_tree_add_item()" is used with an FT_STRINGZ and given a
length (rather than being given -1), the length is, in most cases, the
maximum length of a null-*padded* string, rather than the actual length
of a null-*terminated* string. Treat it as such - allocate a buffer one
larger than the length (to leave room for a terminating '\0'), and pass
the size of that buffer to "tvb_get_nstringz0()". (Otherwise, in those
cases, the last character of the string is chopped off.)
Allow "proto_tree_add_string()" to add FT_STRINGZ items to the protocol
tree, as well as FT_STRING items.
In "alloc_field_info()", if we're passed a length of -1 and the field is
an FT_STRINGZ, don't make the length be the length remaining in the
tvbuff; that way, you *can* use a length of -1 in
"proto_tree_add_item()" for an FT_STRINGZ item, and have it get the
actual length by looking for the terminating '\0'.
(We might want to distinguish between null-terminated and null-padded
strings, e.g. with an FT_STRINGZPAD type. Null-terminated strings
rarely, if ever, have a specified length; the length is found by
scanning for the terminating '\0'. Null-padded strings presumably
always have a specified length, which is the length to which the string
is padded.)
svn path=/trunk/; revision=7784
2003-06-04 21:51:54 +00:00
|
|
|
|
2000-05-31 05:09:07 +00:00
|
|
|
default:
|
2003-12-03 09:28:26 +00:00
|
|
|
g_error("new_fi->hfinfo->type %d (%s) not handled\n",
|
|
|
|
new_fi->hfinfo->type,
|
|
|
|
ftype_name(new_fi->hfinfo->type));
|
2005-03-23 00:09:12 +00:00
|
|
|
DISSECTOR_ASSERT_NOT_REACHED();
|
2001-05-09 01:22:46 +00:00
|
|
|
break;
|
2000-05-31 05:09:07 +00:00
|
|
|
}
|
|
|
|
|
tvb_get_nstringz() needs to terminate a string with a NUL if the
end of the tvbuff is reached before the maximum_length passed by the
caller is reached and before a terminating NUL is found. In this case,
tvb_get_nstringz() returns a -1, but if the string is not artificially
terminated with a NUL by tvb_get_nstringz(), the
caller has no idea where the string should end because 1) the
return value "-1" gives the impression that the string ends
at the end of the buffer but 2) the string does
not end at the end of the buffer, but somewhere in the middle, due
to the packet being shorter than expected.
tvb_get_nstringz() and tvb_get_nstringz0() were both modified.
The FT_STRINGZ case in proto_tree_add_item() is made simpler.
During regression testing, when investigating a regression that I later
corrected, I discovered that strings added through proto_tree_add_item
(FT_STRING, FT_STRINGZ, and FT_UINT_STRING) leaked memory due to double
allocation of the string. The proto_tree_add_string*() functions do
not leak memory, since they only copy the string once. The memory
leak was fixed by adding another argument to the static function
proto_tree_set_string() to let the string ftype code know to g_strdup()
the string or not.
svn path=/trunk/; revision=4891
2002-03-06 19:17:06 +00:00
|
|
|
/* Don't add new node to proto_tree until now so that any exceptions
|
2000-07-27 06:41:59 +00:00
|
|
|
* raised by a tvbuff access method doesn't leave junk in the proto_tree. */
|
|
|
|
pi = proto_tree_add_node(tree, new_fi);
|
|
|
|
|
2003-11-24 21:12:10 +00:00
|
|
|
/* we did not raise an exception so we dont have to remember this
|
|
|
|
* field_info struct any more.
|
|
|
|
*/
|
|
|
|
field_info_tmp=NULL;
|
tvb_get_nstringz() needs to terminate a string with a NUL if the
end of the tvbuff is reached before the maximum_length passed by the
caller is reached and before a terminating NUL is found. In this case,
tvb_get_nstringz() returns a -1, but if the string is not artificially
terminated with a NUL by tvb_get_nstringz(), the
caller has no idea where the string should end because 1) the
return value "-1" gives the impression that the string ends
at the end of the buffer but 2) the string does
not end at the end of the buffer, but somewhere in the middle, due
to the packet being shorter than expected.
tvb_get_nstringz() and tvb_get_nstringz0() were both modified.
The FT_STRINGZ case in proto_tree_add_item() is made simpler.
During regression testing, when investigating a regression that I later
corrected, I discovered that strings added through proto_tree_add_item
(FT_STRING, FT_STRINGZ, and FT_UINT_STRING) leaked memory due to double
allocation of the string. The proto_tree_add_string*() functions do
not leak memory, since they only copy the string once. The memory
leak was fixed by adding another argument to the static function
proto_tree_set_string() to let the string ftype code know to g_strdup()
the string or not.
svn path=/trunk/; revision=4891
2002-03-06 19:17:06 +00:00
|
|
|
|
When "proto_tree_add_item()" is used with an FT_STRINGZ and given a
length (rather than being given -1), the length is, in most cases, the
maximum length of a null-*padded* string, rather than the actual length
of a null-*terminated* string. Treat it as such - allocate a buffer one
larger than the length (to leave room for a terminating '\0'), and pass
the size of that buffer to "tvb_get_nstringz0()". (Otherwise, in those
cases, the last character of the string is chopped off.)
Allow "proto_tree_add_string()" to add FT_STRINGZ items to the protocol
tree, as well as FT_STRING items.
In "alloc_field_info()", if we're passed a length of -1 and the field is
an FT_STRINGZ, don't make the length be the length remaining in the
tvbuff; that way, you *can* use a length of -1 in
"proto_tree_add_item()" for an FT_STRINGZ item, and have it get the
actual length by looking for the terminating '\0'.
(We might want to distinguish between null-terminated and null-padded
strings, e.g. with an FT_STRINGZPAD type. Null-terminated strings
rarely, if ever, have a specified length; the length is found by
scanning for the terminating '\0'. Null-padded strings presumably
always have a specified length, which is the length to which the string
is padded.)
svn path=/trunk/; revision=7784
2003-06-04 21:51:54 +00:00
|
|
|
/* If the proto_tree wants to keep a record of this finfo
|
|
|
|
* for quick lookup, then record it. */
|
2005-04-11 08:43:51 +00:00
|
|
|
if (new_fi->hfinfo->ref_count) {
|
|
|
|
hash = PTREE_DATA(tree)->interesting_hfids;
|
|
|
|
ptrs = g_hash_table_lookup(hash, GINT_TO_POINTER(hfindex));
|
|
|
|
if (ptrs) {
|
|
|
|
g_ptr_array_add(ptrs, new_fi);
|
|
|
|
}
|
When "proto_tree_add_item()" is used with an FT_STRINGZ and given a
length (rather than being given -1), the length is, in most cases, the
maximum length of a null-*padded* string, rather than the actual length
of a null-*terminated* string. Treat it as such - allocate a buffer one
larger than the length (to leave room for a terminating '\0'), and pass
the size of that buffer to "tvb_get_nstringz0()". (Otherwise, in those
cases, the last character of the string is chopped off.)
Allow "proto_tree_add_string()" to add FT_STRINGZ items to the protocol
tree, as well as FT_STRING items.
In "alloc_field_info()", if we're passed a length of -1 and the field is
an FT_STRINGZ, don't make the length be the length remaining in the
tvbuff; that way, you *can* use a length of -1 in
"proto_tree_add_item()" for an FT_STRINGZ item, and have it get the
actual length by looking for the terminating '\0'.
(We might want to distinguish between null-terminated and null-padded
strings, e.g. with an FT_STRINGZPAD type. Null-terminated strings
rarely, if ever, have a specified length; the length is found by
scanning for the terminating '\0'. Null-padded strings presumably
always have a specified length, which is the length to which the string
is padded.)
svn path=/trunk/; revision=7784
2003-06-04 21:51:54 +00:00
|
|
|
}
|
2001-12-18 19:09:08 +00:00
|
|
|
|
2000-05-31 05:09:07 +00:00
|
|
|
return pi;
|
|
|
|
}
|
|
|
|
|
2005-10-22 05:43:09 +00:00
|
|
|
/* Gets data from tvbuff, adds it to proto_tree, increments offset,
|
|
|
|
and returns proto_item* */
|
|
|
|
proto_item*
|
|
|
|
ptvcursor_add(ptvcursor_t *ptvc, int hfindex, gint length,
|
|
|
|
gboolean little_endian)
|
|
|
|
{
|
|
|
|
field_info *new_fi;
|
|
|
|
header_field_info *hfinfo;
|
|
|
|
gint item_length;
|
|
|
|
guint32 n;
|
|
|
|
int offset;
|
|
|
|
|
|
|
|
offset = ptvc->offset;
|
|
|
|
hfinfo = get_hfi_and_length(hfindex, ptvc->tvb, offset, &length,
|
|
|
|
&item_length);
|
|
|
|
ptvc->offset += length;
|
|
|
|
if (hfinfo->type == FT_UINT_BYTES || hfinfo->type == FT_UINT_STRING) {
|
|
|
|
/*
|
|
|
|
* The length of the rest of the item is in the first N
|
|
|
|
* bytes of the item.
|
|
|
|
*/
|
|
|
|
n = get_uint_value(ptvc->tvb, offset, length, little_endian);
|
|
|
|
ptvc->offset += n;
|
|
|
|
}
|
|
|
|
if (ptvc->tree == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfindex);
|
|
|
|
|
|
|
|
new_fi = new_field_info(ptvc->tree, hfinfo, ptvc->tvb, offset,
|
|
|
|
item_length);
|
|
|
|
if (new_fi == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
return proto_tree_new_item(new_fi, ptvc->tree, hfindex, ptvc->tvb,
|
|
|
|
offset, length, little_endian);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* 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)
|
|
|
|
{
|
|
|
|
field_info *new_fi;
|
|
|
|
|
|
|
|
if (!tree)
|
|
|
|
return(NULL);
|
|
|
|
|
|
|
|
TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
|
|
|
|
|
|
|
|
new_fi = alloc_field_info(tree, hfindex, tvb, start, &length);
|
|
|
|
|
|
|
|
if (new_fi == NULL)
|
|
|
|
return(NULL);
|
|
|
|
|
|
|
|
return proto_tree_new_item(new_fi, tree, hfindex, tvb, start,
|
|
|
|
length, little_endian);
|
|
|
|
}
|
|
|
|
|
2000-05-31 05:09:07 +00:00
|
|
|
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;
|
|
|
|
|
|
|
|
pi = proto_tree_add_item(tree, hfindex, tvb, start, length, little_endian);
|
|
|
|
if (pi == NULL)
|
|
|
|
return(NULL);
|
|
|
|
|
2004-05-01 15:15:08 +00:00
|
|
|
PROTO_ITEM_SET_HIDDEN(pi);
|
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 *
|
2001-02-01 20:21:25 +00:00
|
|
|
proto_tree_add_none_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
|
2000-05-11 08:18:09 +00:00
|
|
|
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);
|
|
|
|
|
2003-11-22 04:41:31 +00:00
|
|
|
PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
|
2005-03-23 00:09:12 +00:00
|
|
|
DISSECTOR_ASSERT(hfinfo->type == FT_NONE);
|
2000-03-12 04:48:32 +00:00
|
|
|
|
2002-02-18 22:26:29 +00:00
|
|
|
pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, NULL);
|
2000-05-31 05:09:07 +00:00
|
|
|
|
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 */
|
2001-02-01 20:21:25 +00:00
|
|
|
return pi;
|
|
|
|
}
|
|
|
|
|
2005-10-22 05:43:09 +00:00
|
|
|
/* Gets data from tvbuff, adds it to proto_tree, *DOES NOT* increment
|
|
|
|
* offset, and returns proto_item* */
|
|
|
|
proto_item*
|
|
|
|
ptvcursor_add_no_advance(ptvcursor_t* ptvc, int hf, gint length,
|
|
|
|
gboolean endianness)
|
|
|
|
{
|
|
|
|
proto_item *item;
|
|
|
|
|
|
|
|
item = proto_tree_add_item(ptvc->tree, hf, ptvc->tvb, ptvc->offset,
|
|
|
|
length, endianness);
|
|
|
|
|
|
|
|
return item;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Advance the ptvcursor's offset within its tvbuff without
|
|
|
|
* adding anything to the proto_tree. */
|
|
|
|
void
|
|
|
|
ptvcursor_advance(ptvcursor_t* ptvc, gint length)
|
|
|
|
{
|
|
|
|
ptvc->offset += length;
|
|
|
|
}
|
|
|
|
|
2002-08-28 20:41:00 +00:00
|
|
|
|
2001-02-01 20:21:25 +00:00
|
|
|
static void
|
|
|
|
proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb)
|
|
|
|
{
|
2003-12-02 21:15:49 +00:00
|
|
|
fvalue_set(&fi->value, tvb, TRUE);
|
2001-02-01 20:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Add a FT_PROTOCOL to a proto_tree */
|
|
|
|
proto_item *
|
|
|
|
proto_tree_add_protocol_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
|
|
|
|
gint length, const char *format, ...)
|
|
|
|
{
|
|
|
|
proto_item *pi;
|
|
|
|
va_list ap;
|
|
|
|
header_field_info *hfinfo;
|
|
|
|
field_info *new_fi;
|
|
|
|
|
|
|
|
if (!tree)
|
|
|
|
return (NULL);
|
2000-05-31 05:09:07 +00:00
|
|
|
|
2003-11-22 04:41:31 +00:00
|
|
|
PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
|
2005-03-23 00:09:12 +00:00
|
|
|
DISSECTOR_ASSERT(hfinfo->type == FT_PROTOCOL);
|
2001-02-01 20:21:25 +00:00
|
|
|
|
2002-02-18 22:26:29 +00:00
|
|
|
pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
|
2001-02-01 20:21:25 +00:00
|
|
|
|
|
|
|
va_start(ap, format);
|
|
|
|
proto_tree_set_representation(pi, format, ap);
|
|
|
|
va_end(ap);
|
|
|
|
|
|
|
|
if (start == 0) {
|
|
|
|
proto_tree_set_protocol_tvb(new_fi, tvb);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
proto_tree_set_protocol_tvb(new_fi, NULL);
|
|
|
|
}
|
2000-03-12 04:48:32 +00:00
|
|
|
return pi;
|
|
|
|
}
|
|
|
|
|
2001-02-01 20:21:25 +00:00
|
|
|
|
2000-03-12 04:48:32 +00:00
|
|
|
/* 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);
|
|
|
|
|
2005-04-11 08:43:51 +00:00
|
|
|
TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
|
|
|
|
|
2003-11-22 04:41:31 +00:00
|
|
|
PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
|
2005-03-23 00:09:12 +00:00
|
|
|
DISSECTOR_ASSERT(hfinfo->type == FT_BYTES);
|
2000-03-12 04:48:32 +00:00
|
|
|
|
2002-02-18 22:26:29 +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;
|
|
|
|
|
|
|
|
pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length, start_ptr);
|
|
|
|
if (pi == NULL)
|
|
|
|
return (NULL);
|
|
|
|
|
2004-05-01 15:15:08 +00:00
|
|
|
PROTO_ITEM_SET_HIDDEN(pi);
|
2000-05-31 05:09:07 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
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
|
|
|
{
|
2001-02-01 20:21:25 +00:00
|
|
|
GByteArray *bytes;
|
2000-05-19 04:54:36 +00:00
|
|
|
|
2001-02-01 20:21:25 +00:00
|
|
|
bytes = g_byte_array_new();
|
2000-05-19 04:54:36 +00:00
|
|
|
if (length > 0) {
|
2001-02-01 20:21:25 +00:00
|
|
|
g_byte_array_append(bytes, start_ptr, length);
|
2000-05-19 04:54:36 +00:00
|
|
|
}
|
2003-12-02 21:15:49 +00:00
|
|
|
fvalue_set(&fi->value, bytes, TRUE);
|
2000-03-12 04:48:32 +00:00
|
|
|
}
|
|
|
|
|
2001-02-01 20:21:25 +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)
|
|
|
|
{
|
2001-02-01 20:21:25 +00:00
|
|
|
proto_tree_set_bytes(fi, tvb_get_ptr(tvb, offset, length), length);
|
2000-05-31 05:09:07 +00:00
|
|
|
}
|
|
|
|
|
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,
|
2001-09-14 07:10:13 +00:00
|
|
|
nstime_t *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);
|
|
|
|
|
2005-04-11 08:43:51 +00:00
|
|
|
TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
|
|
|
|
|
2003-11-22 04:41:31 +00:00
|
|
|
PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
|
2005-03-23 00:09:12 +00:00
|
|
|
DISSECTOR_ASSERT(hfinfo->type == FT_ABSOLUTE_TIME ||
|
2000-03-12 04:48:32 +00:00
|
|
|
hfinfo->type == FT_RELATIVE_TIME);
|
|
|
|
|
2002-02-18 22:26:29 +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,
|
2001-09-14 07:10:13 +00:00
|
|
|
nstime_t *value_ptr)
|
2000-05-31 05:09:07 +00:00
|
|
|
{
|
|
|
|
proto_item *pi;
|
|
|
|
|
|
|
|
pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
|
|
|
|
if (pi == NULL)
|
|
|
|
return (NULL);
|
|
|
|
|
2004-05-01 15:15:08 +00:00
|
|
|
PROTO_ITEM_SET_HIDDEN(pi);
|
2000-05-31 05:09:07 +00:00
|
|
|
|
|
|
|
return pi;
|
|
|
|
}
|
|
|
|
|
|
|
|
proto_item *
|
|
|
|
proto_tree_add_time_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
|
2001-09-14 07:10:13 +00:00
|
|
|
nstime_t *value_ptr, const char *format, ...)
|
2000-05-31 05:09:07 +00:00
|
|
|
{
|
|
|
|
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
|
2001-09-14 07:10:13 +00:00
|
|
|
proto_tree_set_time(field_info *fi, nstime_t *value_ptr)
|
2000-03-12 04:48:32 +00:00
|
|
|
{
|
2005-08-16 16:04:30 +00:00
|
|
|
DISSECTOR_ASSERT(value_ptr != NULL);
|
2003-12-02 21:15:49 +00:00
|
|
|
fvalue_set(&fi->value, value_ptr, FALSE);
|
2000-03-12 04:48:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* 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);
|
|
|
|
|
2005-04-11 08:43:51 +00:00
|
|
|
TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
|
|
|
|
|
2003-11-22 04:41:31 +00:00
|
|
|
PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
|
2005-03-23 00:09:12 +00:00
|
|
|
DISSECTOR_ASSERT(hfinfo->type == FT_IPXNET);
|
2000-03-12 04:48:32 +00:00
|
|
|
|
2002-02-18 22:26:29 +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;
|
|
|
|
|
|
|
|
pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
|
|
|
|
if (pi == NULL)
|
|
|
|
return (NULL);
|
|
|
|
|
2004-05-01 15:15:08 +00:00
|
|
|
PROTO_ITEM_SET_HIDDEN(pi);
|
2000-05-31 05:09:07 +00:00
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
2003-12-02 21:15:49 +00:00
|
|
|
fvalue_set_integer(&fi->value, value);
|
2000-03-12 04:48:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* 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);
|
|
|
|
|
2005-04-11 08:43:51 +00:00
|
|
|
TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
|
|
|
|
|
2003-11-22 04:41:31 +00:00
|
|
|
PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
|
2005-03-23 00:09:12 +00:00
|
|
|
DISSECTOR_ASSERT(hfinfo->type == FT_IPv4);
|
2000-03-12 04:48:32 +00:00
|
|
|
|
2002-02-18 22:26:29 +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;
|
|
|
|
|
|
|
|
pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
|
|
|
|
if (pi == NULL)
|
|
|
|
return (NULL);
|
|
|
|
|
2004-05-01 15:15:08 +00:00
|
|
|
PROTO_ITEM_SET_HIDDEN(pi);
|
2000-05-31 05:09:07 +00:00
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
2003-12-02 21:15:49 +00:00
|
|
|
fvalue_set_integer(&fi->value, value);
|
2000-03-12 04:48:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* 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);
|
|
|
|
|
2005-04-11 08:43:51 +00:00
|
|
|
TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
|
|
|
|
|
2003-11-22 04:41:31 +00:00
|
|
|
PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
|
2005-03-23 00:09:12 +00:00
|
|
|
DISSECTOR_ASSERT(hfinfo->type == FT_IPv6);
|
2000-03-12 04:48:32 +00:00
|
|
|
|
2002-02-18 22:26:29 +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;
|
|
|
|
|
|
|
|
pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
|
|
|
|
if (pi == NULL)
|
|
|
|
return (NULL);
|
|
|
|
|
2004-05-01 15:15:08 +00:00
|
|
|
PROTO_ITEM_SET_HIDDEN(pi);
|
2000-05-31 05:09:07 +00:00
|
|
|
|
|
|
|
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
|
|
|
{
|
2005-08-16 16:04:30 +00:00
|
|
|
DISSECTOR_ASSERT(value_ptr != NULL);
|
2003-12-02 21:15:49 +00:00
|
|
|
fvalue_set(&fi->value, (gpointer) value_ptr, FALSE);
|
2000-03-12 04:48:32 +00:00
|
|
|
}
|
|
|
|
|
2000-05-31 05:09:07 +00:00
|
|
|
static void
|
|
|
|
proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start)
|
|
|
|
{
|
2001-02-01 20:21:25 +00:00
|
|
|
proto_tree_set_ipv6(fi, tvb_get_ptr(tvb, start, 16));
|
2000-05-31 05:09:07 +00:00
|
|
|
}
|
|
|
|
|
2005-07-04 13:04:53 +00:00
|
|
|
/* Add a FT_GUID to a proto_tree */
|
|
|
|
proto_item *
|
|
|
|
proto_tree_add_guid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
|
|
|
|
const guint8* value_ptr)
|
|
|
|
{
|
|
|
|
proto_item *pi;
|
|
|
|
field_info *new_fi;
|
|
|
|
header_field_info *hfinfo;
|
|
|
|
|
|
|
|
if (!tree)
|
|
|
|
return (NULL);
|
|
|
|
|
|
|
|
TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
|
|
|
|
|
|
|
|
PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
|
|
|
|
DISSECTOR_ASSERT(hfinfo->type == FT_GUID);
|
|
|
|
|
|
|
|
pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
|
|
|
|
proto_tree_set_guid(new_fi, value_ptr);
|
|
|
|
|
|
|
|
return pi;
|
|
|
|
}
|
|
|
|
|
|
|
|
proto_item *
|
|
|
|
proto_tree_add_guid_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
|
|
|
|
const guint8* value_ptr)
|
|
|
|
{
|
|
|
|
proto_item *pi;
|
|
|
|
|
|
|
|
pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
|
|
|
|
if (pi == NULL)
|
|
|
|
return (NULL);
|
|
|
|
|
|
|
|
PROTO_ITEM_SET_HIDDEN(pi);
|
|
|
|
|
|
|
|
return pi;
|
|
|
|
}
|
|
|
|
|
|
|
|
proto_item *
|
|
|
|
proto_tree_add_guid_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_guid(tree, hfindex, tvb, start, length, value_ptr);
|
|
|
|
if (pi == NULL)
|
|
|
|
return (NULL);
|
|
|
|
|
|
|
|
va_start(ap, format);
|
|
|
|
proto_tree_set_representation(pi, format, ap);
|
|
|
|
va_end(ap);
|
|
|
|
|
|
|
|
return pi;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Set the FT_GUID value */
|
|
|
|
static void
|
|
|
|
proto_tree_set_guid(field_info *fi, const guint8* value_ptr)
|
|
|
|
{
|
2005-08-16 16:04:30 +00:00
|
|
|
DISSECTOR_ASSERT(value_ptr != NULL);
|
2005-07-04 13:04:53 +00:00
|
|
|
fvalue_set(&fi->value, (gpointer) value_ptr, FALSE);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, gint start)
|
|
|
|
{
|
|
|
|
proto_tree_set_guid(fi, tvb_get_ptr(tvb, start, 16));
|
|
|
|
}
|
|
|
|
|
2005-12-02 13:16:58 +00:00
|
|
|
/* Add a FT_OID to a proto_tree */
|
|
|
|
proto_item *
|
|
|
|
proto_tree_add_oid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
|
|
|
|
const guint8* value_ptr)
|
|
|
|
{
|
|
|
|
proto_item *pi;
|
|
|
|
field_info *new_fi;
|
|
|
|
header_field_info *hfinfo;
|
|
|
|
|
|
|
|
if (!tree)
|
|
|
|
return (NULL);
|
|
|
|
|
|
|
|
TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
|
|
|
|
|
|
|
|
PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
|
|
|
|
DISSECTOR_ASSERT(hfinfo->type == FT_OID);
|
|
|
|
|
|
|
|
pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
|
|
|
|
proto_tree_set_oid(new_fi, value_ptr, length);
|
|
|
|
|
|
|
|
return pi;
|
|
|
|
}
|
|
|
|
|
|
|
|
proto_item *
|
|
|
|
proto_tree_add_oid_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
|
|
|
|
const guint8* value_ptr)
|
|
|
|
{
|
|
|
|
proto_item *pi;
|
|
|
|
|
|
|
|
pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
|
|
|
|
if (pi == NULL)
|
|
|
|
return (NULL);
|
|
|
|
|
|
|
|
PROTO_ITEM_SET_HIDDEN(pi);
|
|
|
|
|
|
|
|
return pi;
|
|
|
|
}
|
|
|
|
|
|
|
|
proto_item *
|
|
|
|
proto_tree_add_oid_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_oid(tree, hfindex, tvb, start, length, value_ptr);
|
|
|
|
if (pi == NULL)
|
|
|
|
return (NULL);
|
|
|
|
|
|
|
|
va_start(ap, format);
|
|
|
|
proto_tree_set_representation(pi, format, ap);
|
|
|
|
va_end(ap);
|
|
|
|
|
|
|
|
return pi;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Set the FT_OID value */
|
|
|
|
static void
|
|
|
|
proto_tree_set_oid(field_info *fi, const guint8* value_ptr, gint length)
|
|
|
|
{
|
|
|
|
GByteArray *bytes;
|
|
|
|
|
|
|
|
DISSECTOR_ASSERT(value_ptr != NULL);
|
|
|
|
|
|
|
|
bytes = g_byte_array_new();
|
|
|
|
if (length > 0) {
|
|
|
|
g_byte_array_append(bytes, value_ptr, length);
|
|
|
|
}
|
|
|
|
fvalue_set(&fi->value, bytes, TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
proto_tree_set_oid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
|
|
|
|
{
|
|
|
|
proto_tree_set_oid(fi, tvb_get_ptr(tvb, start, length), length);
|
|
|
|
}
|
|
|
|
|
2001-10-29 21:13:13 +00:00
|
|
|
static void
|
2004-08-22 00:31:58 +00:00
|
|
|
proto_tree_set_uint64(field_info *fi, guint64 value)
|
2001-10-29 21:13:13 +00:00
|
|
|
{
|
2004-08-22 00:31:58 +00:00
|
|
|
fvalue_set_integer64(&fi->value, value);
|
2001-10-29 21:13:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start, gboolean little_endian)
|
|
|
|
{
|
2004-08-22 00:31:58 +00:00
|
|
|
guint64 value;
|
|
|
|
|
|
|
|
value = little_endian ? tvb_get_letoh64(tvb, start)
|
|
|
|
: tvb_get_ntoh64(tvb, start);
|
|
|
|
|
|
|
|
proto_tree_set_uint64(fi, value);
|
2001-10-29 21:13:13 +00:00
|
|
|
}
|
|
|
|
|
When "proto_tree_add_item()" is used with an FT_STRINGZ and given a
length (rather than being given -1), the length is, in most cases, the
maximum length of a null-*padded* string, rather than the actual length
of a null-*terminated* string. Treat it as such - allocate a buffer one
larger than the length (to leave room for a terminating '\0'), and pass
the size of that buffer to "tvb_get_nstringz0()". (Otherwise, in those
cases, the last character of the string is chopped off.)
Allow "proto_tree_add_string()" to add FT_STRINGZ items to the protocol
tree, as well as FT_STRING items.
In "alloc_field_info()", if we're passed a length of -1 and the field is
an FT_STRINGZ, don't make the length be the length remaining in the
tvbuff; that way, you *can* use a length of -1 in
"proto_tree_add_item()" for an FT_STRINGZ item, and have it get the
actual length by looking for the terminating '\0'.
(We might want to distinguish between null-terminated and null-padded
strings, e.g. with an FT_STRINGZPAD type. Null-terminated strings
rarely, if ever, have a specified length; the length is found by
scanning for the terminating '\0'. Null-padded strings presumably
always have a specified length, which is the length to which the string
is padded.)
svn path=/trunk/; revision=7784
2003-06-04 21:51:54 +00:00
|
|
|
/* Add a FT_STRING or FT_STRINGZ to a proto_tree. Creates own copy of string,
|
tvb_get_nstringz() needs to terminate a string with a NUL if the
end of the tvbuff is reached before the maximum_length passed by the
caller is reached and before a terminating NUL is found. In this case,
tvb_get_nstringz() returns a -1, but if the string is not artificially
terminated with a NUL by tvb_get_nstringz(), the
caller has no idea where the string should end because 1) the
return value "-1" gives the impression that the string ends
at the end of the buffer but 2) the string does
not end at the end of the buffer, but somewhere in the middle, due
to the packet being shorter than expected.
tvb_get_nstringz() and tvb_get_nstringz0() were both modified.
The FT_STRINGZ case in proto_tree_add_item() is made simpler.
During regression testing, when investigating a regression that I later
corrected, I discovered that strings added through proto_tree_add_item
(FT_STRING, FT_STRINGZ, and FT_UINT_STRING) leaked memory due to double
allocation of the string. The proto_tree_add_string*() functions do
not leak memory, since they only copy the string once. The memory
leak was fixed by adding another argument to the static function
proto_tree_set_string() to let the string ftype code know to g_strdup()
the string or not.
svn path=/trunk/; revision=4891
2002-03-06 19:17:06 +00:00
|
|
|
* and frees it when the proto_tree is destroyed. */
|
2000-03-12 04:48:32 +00:00
|
|
|
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);
|
|
|
|
|
2005-04-11 08:43:51 +00:00
|
|
|
TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
|
|
|
|
|
2003-11-22 04:41:31 +00:00
|
|
|
PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
|
2005-03-23 00:09:12 +00:00
|
|
|
DISSECTOR_ASSERT(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ);
|
2000-03-12 04:48:32 +00:00
|
|
|
|
2002-02-18 22:26:29 +00:00
|
|
|
pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
|
2005-03-23 00:09:12 +00:00
|
|
|
DISSECTOR_ASSERT(length >= 0);
|
tvb_get_nstringz() needs to terminate a string with a NUL if the
end of the tvbuff is reached before the maximum_length passed by the
caller is reached and before a terminating NUL is found. In this case,
tvb_get_nstringz() returns a -1, but if the string is not artificially
terminated with a NUL by tvb_get_nstringz(), the
caller has no idea where the string should end because 1) the
return value "-1" gives the impression that the string ends
at the end of the buffer but 2) the string does
not end at the end of the buffer, but somewhere in the middle, due
to the packet being shorter than expected.
tvb_get_nstringz() and tvb_get_nstringz0() were both modified.
The FT_STRINGZ case in proto_tree_add_item() is made simpler.
During regression testing, when investigating a regression that I later
corrected, I discovered that strings added through proto_tree_add_item
(FT_STRING, FT_STRINGZ, and FT_UINT_STRING) leaked memory due to double
allocation of the string. The proto_tree_add_string*() functions do
not leak memory, since they only copy the string once. The memory
leak was fixed by adding another argument to the static function
proto_tree_set_string() to let the string ftype code know to g_strdup()
the string or not.
svn path=/trunk/; revision=4891
2002-03-06 19:17:06 +00:00
|
|
|
proto_tree_set_string(new_fi, value, FALSE);
|
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;
|
|
|
|
|
|
|
|
pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
|
|
|
|
if (pi == NULL)
|
|
|
|
return (NULL);
|
|
|
|
|
2004-05-01 15:15:08 +00:00
|
|
|
PROTO_ITEM_SET_HIDDEN(pi);
|
2000-05-31 05:09:07 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2003-10-29 23:48:14 +00:00
|
|
|
/* Appends string data to a FT_STRING or FT_STRINGZ, allowing progressive
|
|
|
|
* field info update instead of only updating the representation as does
|
|
|
|
* proto_item_append_text()
|
|
|
|
*/
|
2005-05-27 06:00:08 +00:00
|
|
|
/* NOTE: this function will break with the TRY_TO_FAKE_THIS_ITEM()
|
|
|
|
* speed optimization.
|
|
|
|
* Currently only WSP use this function so it is not that bad but try to
|
|
|
|
* avoid using this one if possible.
|
|
|
|
* IF you must use this function you MUST also disable the
|
|
|
|
* TRY_TO_FAKE_THIS_ITEM() optimization for your dissector/function
|
|
|
|
* using proto_item_append_string().
|
|
|
|
* Do that by faking that the tree is visible by setting :
|
|
|
|
* PTREE_DATA(tree)->visible=1; (see packet-wsp.c)
|
|
|
|
* BEFORE you create the item you are later going to use
|
|
|
|
* proto_item_append_string() on.
|
|
|
|
*/
|
2003-10-29 23:48:14 +00:00
|
|
|
void
|
|
|
|
proto_item_append_string(proto_item *pi, const char *str)
|
|
|
|
{
|
|
|
|
field_info *fi;
|
|
|
|
header_field_info *hfinfo;
|
|
|
|
gchar *old_str, *new_str;
|
|
|
|
|
|
|
|
if (!pi)
|
|
|
|
return;
|
|
|
|
if (!*str)
|
|
|
|
return;
|
|
|
|
|
|
|
|
fi = PITEM_FINFO(pi);
|
2003-12-03 09:28:26 +00:00
|
|
|
hfinfo = fi->hfinfo;
|
2005-09-28 07:08:57 +00:00
|
|
|
if (hfinfo->type == FT_PROTOCOL) {
|
|
|
|
/* TRY_TO_FAKE_THIS_ITEM() speed optimization: silently skip */
|
|
|
|
return;
|
|
|
|
}
|
2005-03-23 00:09:12 +00:00
|
|
|
DISSECTOR_ASSERT(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ);
|
2003-12-02 21:15:49 +00:00
|
|
|
old_str = fvalue_get(&fi->value);
|
2005-08-08 18:50:39 +00:00
|
|
|
new_str = g_strdup_printf("%s%s", old_str, str);
|
2003-12-02 21:15:49 +00:00
|
|
|
fvalue_set(&fi->value, new_str, TRUE);
|
2003-10-29 23:48:14 +00:00
|
|
|
}
|
|
|
|
|
2000-03-12 04:48:32 +00:00
|
|
|
/* Set the FT_STRING value */
|
|
|
|
static void
|
tvb_get_nstringz() needs to terminate a string with a NUL if the
end of the tvbuff is reached before the maximum_length passed by the
caller is reached and before a terminating NUL is found. In this case,
tvb_get_nstringz() returns a -1, but if the string is not artificially
terminated with a NUL by tvb_get_nstringz(), the
caller has no idea where the string should end because 1) the
return value "-1" gives the impression that the string ends
at the end of the buffer but 2) the string does
not end at the end of the buffer, but somewhere in the middle, due
to the packet being shorter than expected.
tvb_get_nstringz() and tvb_get_nstringz0() were both modified.
The FT_STRINGZ case in proto_tree_add_item() is made simpler.
During regression testing, when investigating a regression that I later
corrected, I discovered that strings added through proto_tree_add_item
(FT_STRING, FT_STRINGZ, and FT_UINT_STRING) leaked memory due to double
allocation of the string. The proto_tree_add_string*() functions do
not leak memory, since they only copy the string once. The memory
leak was fixed by adding another argument to the static function
proto_tree_set_string() to let the string ftype code know to g_strdup()
the string or not.
svn path=/trunk/; revision=4891
2002-03-06 19:17:06 +00:00
|
|
|
proto_tree_set_string(field_info *fi, const char* value,
|
|
|
|
gboolean already_allocated)
|
2000-03-12 04:48:32 +00:00
|
|
|
{
|
2005-05-03 19:33:02 +00:00
|
|
|
if (value)
|
|
|
|
fvalue_set(&fi->value, (gpointer) value, already_allocated);
|
|
|
|
else
|
|
|
|
fvalue_set(&fi->value, (gpointer) "[ Null ]", already_allocated);
|
2000-03-12 04:48:32 +00:00
|
|
|
}
|
|
|
|
|
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)
|
|
|
|
{
|
2001-02-01 20:21:25 +00:00
|
|
|
gchar *string;
|
|
|
|
|
2002-02-01 04:34:17 +00:00
|
|
|
if (length == -1) {
|
|
|
|
length = tvb_ensure_length_remaining(tvb, start);
|
|
|
|
}
|
|
|
|
|
2000-07-27 06:41:59 +00:00
|
|
|
/* This memory is freed in proto_tree_free_node() */
|
2003-11-20 05:20:17 +00:00
|
|
|
string = tvb_get_string(tvb, start, length);
|
tvb_get_nstringz() needs to terminate a string with a NUL if the
end of the tvbuff is reached before the maximum_length passed by the
caller is reached and before a terminating NUL is found. In this case,
tvb_get_nstringz() returns a -1, but if the string is not artificially
terminated with a NUL by tvb_get_nstringz(), the
caller has no idea where the string should end because 1) the
return value "-1" gives the impression that the string ends
at the end of the buffer but 2) the string does
not end at the end of the buffer, but somewhere in the middle, due
to the packet being shorter than expected.
tvb_get_nstringz() and tvb_get_nstringz0() were both modified.
The FT_STRINGZ case in proto_tree_add_item() is made simpler.
During regression testing, when investigating a regression that I later
corrected, I discovered that strings added through proto_tree_add_item
(FT_STRING, FT_STRINGZ, and FT_UINT_STRING) leaked memory due to double
allocation of the string. The proto_tree_add_string*() functions do
not leak memory, since they only copy the string once. The memory
leak was fixed by adding another argument to the static function
proto_tree_set_string() to let the string ftype code know to g_strdup()
the string or not.
svn path=/trunk/; revision=4891
2002-03-06 19:17:06 +00:00
|
|
|
proto_tree_set_string(fi, string, TRUE);
|
2000-05-31 05:09:07 +00:00
|
|
|
}
|
|
|
|
|
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);
|
|
|
|
|
2005-04-11 08:43:51 +00:00
|
|
|
TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
|
|
|
|
|
2003-11-22 04:41:31 +00:00
|
|
|
PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
|
2005-03-23 00:09:12 +00:00
|
|
|
DISSECTOR_ASSERT(hfinfo->type == FT_ETHER);
|
2000-03-12 04:48:32 +00:00
|
|
|
|
2002-02-18 22:26:29 +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;
|
|
|
|
|
|
|
|
pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
|
|
|
|
if (pi == NULL)
|
|
|
|
return (NULL);
|
|
|
|
|
2004-05-01 15:15:08 +00:00
|
|
|
PROTO_ITEM_SET_HIDDEN(pi);
|
2000-05-31 05:09:07 +00:00
|
|
|
|
|
|
|
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
|
|
|
{
|
2003-12-02 21:15:49 +00:00
|
|
|
fvalue_set(&fi->value, (gpointer) value, FALSE);
|
2000-03-12 04:48:32 +00:00
|
|
|
}
|
|
|
|
|
2000-05-31 05:09:07 +00:00
|
|
|
static void
|
|
|
|
proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start)
|
|
|
|
{
|
2001-02-01 20:21:25 +00:00
|
|
|
proto_tree_set_ether(fi, tvb_get_ptr(tvb, start, 6));
|
2000-05-31 05:09:07 +00:00
|
|
|
}
|
|
|
|
|
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);
|
|
|
|
|
2005-04-11 08:43:51 +00:00
|
|
|
TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
|
|
|
|
|
2003-11-22 04:41:31 +00:00
|
|
|
PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
|
2005-03-23 00:09:12 +00:00
|
|
|
DISSECTOR_ASSERT(hfinfo->type == FT_BOOLEAN);
|
2000-03-12 04:48:32 +00:00
|
|
|
|
2002-02-18 22:26:29 +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;
|
|
|
|
|
|
|
|
pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
|
|
|
|
if (pi == NULL)
|
|
|
|
return (NULL);
|
|
|
|
|
2004-05-01 15:15:08 +00:00
|
|
|
PROTO_ITEM_SET_HIDDEN(pi);
|
2000-05-31 05:09:07 +00:00
|
|
|
|
|
|
|
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
|
2001-02-01 20:21:25 +00:00
|
|
|
proto_tree_set_boolean(field_info *fi, guint32 value)
|
2000-03-12 04:48:32 +00:00
|
|
|
{
|
2000-04-11 16:07:40 +00:00
|
|
|
proto_tree_set_uint(fi, value);
|
2000-03-12 04:48:32 +00:00
|
|
|
}
|
|
|
|
|
2002-08-24 19:45:28 +00:00
|
|
|
/* Add a FT_FLOAT to a proto_tree */
|
|
|
|
proto_item *
|
|
|
|
proto_tree_add_float(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
|
|
|
|
float value)
|
|
|
|
{
|
|
|
|
proto_item *pi;
|
|
|
|
field_info *new_fi;
|
|
|
|
header_field_info *hfinfo;
|
|
|
|
|
|
|
|
if (!tree)
|
|
|
|
return (NULL);
|
|
|
|
|
2005-04-11 08:43:51 +00:00
|
|
|
TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
|
|
|
|
|
2003-11-22 04:41:31 +00:00
|
|
|
PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
|
2005-03-23 00:09:12 +00:00
|
|
|
DISSECTOR_ASSERT(hfinfo->type == FT_FLOAT);
|
2002-08-24 19:45:28 +00:00
|
|
|
|
|
|
|
pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
|
|
|
|
proto_tree_set_float(new_fi, value);
|
|
|
|
|
|
|
|
return pi;
|
|
|
|
}
|
|
|
|
|
|
|
|
proto_item *
|
|
|
|
proto_tree_add_float_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
|
|
|
|
float value)
|
|
|
|
{
|
|
|
|
proto_item *pi;
|
|
|
|
|
|
|
|
pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
|
|
|
|
if (pi == NULL)
|
|
|
|
return (NULL);
|
|
|
|
|
2004-05-01 15:15:08 +00:00
|
|
|
PROTO_ITEM_SET_HIDDEN(pi);
|
2002-08-24 19:45:28 +00:00
|
|
|
|
|
|
|
return pi;
|
|
|
|
}
|
|
|
|
|
|
|
|
proto_item *
|
|
|
|
proto_tree_add_float_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
|
|
|
|
float value, const char *format, ...)
|
|
|
|
{
|
|
|
|
proto_item *pi;
|
|
|
|
va_list ap;
|
|
|
|
|
|
|
|
pi = proto_tree_add_float(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;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Set the FT_FLOAT value */
|
|
|
|
static void
|
|
|
|
proto_tree_set_float(field_info *fi, float value)
|
|
|
|
{
|
2003-12-02 21:15:49 +00:00
|
|
|
fvalue_set_floating(&fi->value, value);
|
2002-08-24 19:45:28 +00:00
|
|
|
}
|
|
|
|
|
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);
|
|
|
|
|
2005-04-11 08:43:51 +00:00
|
|
|
TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
|
|
|
|
|
2003-11-22 04:41:31 +00:00
|
|
|
PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
|
2005-03-23 00:09:12 +00:00
|
|
|
DISSECTOR_ASSERT(hfinfo->type == FT_DOUBLE);
|
2000-03-12 04:48:32 +00:00
|
|
|
|
2002-02-18 22:26:29 +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;
|
|
|
|
|
|
|
|
pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
|
|
|
|
if (pi == NULL)
|
|
|
|
return (NULL);
|
|
|
|
|
2004-05-01 15:15:08 +00:00
|
|
|
PROTO_ITEM_SET_HIDDEN(pi);
|
2000-05-31 05:09:07 +00:00
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
2003-12-02 21:15:49 +00:00
|
|
|
fvalue_set_floating(&fi->value, value);
|
2000-03-12 04:48:32 +00:00
|
|
|
}
|
|
|
|
|
2004-08-22 00:31:58 +00:00
|
|
|
/* Add FT_UINT{8,16,24,32} to a proto_tree */
|
2000-03-12 04:48:32 +00:00
|
|
|
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);
|
|
|
|
|
2005-04-11 08:43:51 +00:00
|
|
|
TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
|
|
|
|
|
2003-11-22 04:41:31 +00:00
|
|
|
PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
|
2000-03-12 04:48:32 +00:00
|
|
|
switch(hfinfo->type) {
|
|
|
|
case FT_UINT8:
|
|
|
|
case FT_UINT16:
|
|
|
|
case FT_UINT24:
|
|
|
|
case FT_UINT32:
|
2002-12-19 02:58:53 +00:00
|
|
|
case FT_FRAMENUM:
|
2002-02-18 22:26:29 +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:
|
2005-03-23 00:09:12 +00:00
|
|
|
DISSECTOR_ASSERT_NOT_REACHED();
|
2000-03-12 04:48:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
|
|
|
|
if (pi == NULL)
|
|
|
|
return (NULL);
|
|
|
|
|
2004-05-01 15:15:08 +00:00
|
|
|
PROTO_ITEM_SET_HIDDEN(pi);
|
2000-05-31 05:09:07 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2004-08-22 00:31:58 +00:00
|
|
|
/* Set the FT_UINT{8,16,24,32} value */
|
2000-03-12 04:48:32 +00:00
|
|
|
static void
|
|
|
|
proto_tree_set_uint(field_info *fi, guint32 value)
|
|
|
|
{
|
2001-02-01 20:21:25 +00:00
|
|
|
header_field_info *hfinfo;
|
|
|
|
guint32 integer;
|
2000-03-12 04:48:32 +00:00
|
|
|
|
2003-12-03 09:28:26 +00:00
|
|
|
hfinfo = fi->hfinfo;
|
2001-02-01 20:21:25 +00:00
|
|
|
integer = value;
|
|
|
|
|
2000-03-12 04:48:32 +00:00
|
|
|
if (hfinfo->bitmask) {
|
|
|
|
/* Mask out irrelevant portions */
|
2001-02-01 20:21:25 +00:00
|
|
|
integer &= hfinfo->bitmask;
|
2000-03-12 04:48:32 +00:00
|
|
|
|
|
|
|
/* Shift bits */
|
|
|
|
if (hfinfo->bitshift > 0) {
|
2001-02-01 20:21:25 +00:00
|
|
|
integer >>= hfinfo->bitshift;
|
2000-03-12 04:48:32 +00:00
|
|
|
}
|
|
|
|
}
|
2003-12-02 21:15:49 +00:00
|
|
|
fvalue_set_integer(&fi->value, integer);
|
2000-03-12 04:48:32 +00:00
|
|
|
}
|
|
|
|
|
2004-08-22 00:31:58 +00:00
|
|
|
/* Add FT_UINT64 to a proto_tree */
|
|
|
|
proto_item *
|
|
|
|
proto_tree_add_uint64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
|
|
|
|
guint64 value)
|
|
|
|
{
|
|
|
|
proto_item *pi = NULL;
|
|
|
|
field_info *new_fi;
|
|
|
|
header_field_info *hfinfo;
|
|
|
|
|
|
|
|
if (!tree)
|
|
|
|
return (NULL);
|
|
|
|
|
2005-04-11 08:43:51 +00:00
|
|
|
TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
|
|
|
|
|
2004-08-22 00:31:58 +00:00
|
|
|
PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
|
2005-03-23 00:09:12 +00:00
|
|
|
DISSECTOR_ASSERT(hfinfo->type == FT_UINT64);
|
2004-08-22 00:31:58 +00:00
|
|
|
|
|
|
|
pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
|
|
|
|
proto_tree_set_uint64(new_fi, value);
|
|
|
|
|
|
|
|
return pi;
|
|
|
|
}
|
|
|
|
|
|
|
|
proto_item *
|
|
|
|
proto_tree_add_uint64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
|
|
|
|
guint64 value, const char *format, ...)
|
|
|
|
{
|
|
|
|
proto_item *pi;
|
|
|
|
va_list ap;
|
|
|
|
|
|
|
|
pi = proto_tree_add_uint64(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;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Add FT_INT{8,16,24,32} to a proto_tree */
|
2000-04-25 21:43:50 +00:00
|
|
|
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);
|
|
|
|
|
2005-04-11 08:43:51 +00:00
|
|
|
TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
|
|
|
|
|
2003-11-22 04:41:31 +00:00
|
|
|
PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
|
2000-04-25 21:43:50 +00:00
|
|
|
switch(hfinfo->type) {
|
|
|
|
case FT_INT8:
|
|
|
|
case FT_INT16:
|
|
|
|
case FT_INT24:
|
|
|
|
case FT_INT32:
|
2002-02-18 22:26:29 +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:
|
2005-03-23 00:09:12 +00:00
|
|
|
DISSECTOR_ASSERT_NOT_REACHED();
|
2000-04-25 21:43:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
|
|
|
|
if (pi == NULL)
|
|
|
|
return (NULL);
|
|
|
|
|
2004-05-01 15:15:08 +00:00
|
|
|
PROTO_ITEM_SET_HIDDEN(pi);
|
2000-05-31 05:09:07 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2004-08-22 00:31:58 +00:00
|
|
|
/* Set the FT_INT{8,16,24,32} value */
|
2000-04-25 21:43:50 +00:00
|
|
|
static void
|
|
|
|
proto_tree_set_int(field_info *fi, gint32 value)
|
|
|
|
{
|
2001-02-01 20:21:25 +00:00
|
|
|
header_field_info *hfinfo;
|
|
|
|
guint32 integer;
|
2000-04-25 21:43:50 +00:00
|
|
|
|
2003-12-03 09:28:26 +00:00
|
|
|
hfinfo = fi->hfinfo;
|
2001-02-01 20:21:25 +00:00
|
|
|
integer = (guint32) value;
|
|
|
|
|
2000-04-25 21:43:50 +00:00
|
|
|
if (hfinfo->bitmask) {
|
|
|
|
/* Mask out irrelevant portions */
|
2001-02-01 20:21:25 +00:00
|
|
|
integer &= hfinfo->bitmask;
|
2000-04-25 21:43:50 +00:00
|
|
|
|
|
|
|
/* Shift bits */
|
|
|
|
if (hfinfo->bitshift > 0) {
|
2001-02-01 20:21:25 +00:00
|
|
|
integer >>= hfinfo->bitshift;
|
2000-04-25 21:43:50 +00:00
|
|
|
}
|
|
|
|
}
|
2003-12-02 21:15:49 +00:00
|
|
|
fvalue_set_integer(&fi->value, integer);
|
2000-04-25 21:43:50 +00:00
|
|
|
}
|
2000-03-12 04:48:32 +00:00
|
|
|
|
2004-08-22 00:31:58 +00:00
|
|
|
/* Add FT_INT64 to a proto_tree */
|
|
|
|
proto_item *
|
|
|
|
proto_tree_add_int64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
|
|
|
|
gint64 value)
|
|
|
|
{
|
|
|
|
proto_item *pi = NULL;
|
|
|
|
field_info *new_fi;
|
|
|
|
header_field_info *hfinfo;
|
|
|
|
|
|
|
|
if (!tree)
|
|
|
|
return (NULL);
|
|
|
|
|
2005-04-11 08:43:51 +00:00
|
|
|
TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
|
|
|
|
|
2004-08-22 00:31:58 +00:00
|
|
|
PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
|
2005-03-23 00:09:12 +00:00
|
|
|
DISSECTOR_ASSERT(hfinfo->type == FT_INT64);
|
2004-08-22 00:31:58 +00:00
|
|
|
|
|
|
|
pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
|
|
|
|
proto_tree_set_uint64(new_fi, (guint64)value);
|
|
|
|
|
|
|
|
return pi;
|
|
|
|
}
|
|
|
|
|
|
|
|
proto_item *
|
|
|
|
proto_tree_add_int64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
|
|
|
|
gint64 value, const char *format, ...)
|
|
|
|
{
|
|
|
|
proto_item *pi;
|
|
|
|
va_list ap;
|
|
|
|
|
|
|
|
pi = proto_tree_add_int64(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
|
|
|
|
2003-12-04 10:59:34 +00:00
|
|
|
/* Add a field_info struct to the proto_tree, encapsulating it in a proto_node */
|
2000-03-12 04:48:32 +00:00
|
|
|
static proto_item *
|
|
|
|
proto_tree_add_node(proto_tree *tree, field_info *fi)
|
|
|
|
{
|
2003-12-04 10:59:34 +00:00
|
|
|
proto_node *pnode, *tnode, *sibling;
|
2002-04-04 20:23:50 +00:00
|
|
|
field_info *tfi;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Make sure "tree" is ready to have subtrees under it, by
|
|
|
|
* checking whether it's been given an ett_ value.
|
|
|
|
*
|
|
|
|
* "tnode->finfo" may be null; that's the case for the root
|
|
|
|
* node of the protocol tree. That node is not displayed,
|
|
|
|
* so it doesn't need an ett_ value to remember whether it
|
|
|
|
* was expanded.
|
|
|
|
*/
|
2003-12-04 10:59:34 +00:00
|
|
|
tnode = tree;
|
2002-04-04 20:23:50 +00:00
|
|
|
tfi = tnode->finfo;
|
2005-01-26 23:17:00 +00:00
|
|
|
if (tfi != NULL && (tfi->tree_type < 0 || tfi->tree_type >= num_tree_types)) {
|
2005-09-28 16:16:37 +00:00
|
|
|
REPORT_DISSECTOR_BUG(ep_strdup_printf("\"%s\" - \"%s\" tfi->tree_type: %u invalid (%s:%u)",
|
2005-01-26 23:17:00 +00:00
|
|
|
fi->hfinfo->name, fi->hfinfo->abbrev, tfi->tree_type, __FILE__, __LINE__));
|
2005-09-28 16:16:37 +00:00
|
|
|
/* XXX - is it safe to continue here? */
|
|
|
|
}
|
2005-01-26 23:17:00 +00:00
|
|
|
|
2005-03-23 00:09:12 +00:00
|
|
|
DISSECTOR_ASSERT(tfi == NULL ||
|
2002-04-04 20:23:50 +00:00
|
|
|
(tfi->tree_type >= 0 && tfi->tree_type < num_tree_types));
|
1999-07-07 22:52:57 +00:00
|
|
|
|
2003-11-26 12:22:22 +00:00
|
|
|
PROTO_NODE_NEW(pnode);
|
2003-12-04 19:53:54 +00:00
|
|
|
pnode->parent = tnode;
|
2002-01-07 01:05:33 +00:00
|
|
|
pnode->finfo = fi;
|
|
|
|
pnode->tree_data = PTREE_DATA(tree);
|
1999-07-07 22:52:57 +00:00
|
|
|
|
2003-12-04 10:59:34 +00:00
|
|
|
if (tnode->last_child != NULL) {
|
|
|
|
sibling = tnode->last_child;
|
2005-03-23 00:09:12 +00:00
|
|
|
DISSECTOR_ASSERT(sibling->next == NULL);
|
2003-12-04 10:59:34 +00:00
|
|
|
sibling->next = pnode;
|
|
|
|
} else
|
|
|
|
tnode->first_child = pnode;
|
|
|
|
tnode->last_child = pnode;
|
2001-12-18 19:09:08 +00:00
|
|
|
|
2003-12-04 10:59:34 +00:00
|
|
|
return (proto_item*)pnode;
|
2000-03-12 04:48:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2000-05-31 05:09:07 +00:00
|
|
|
/* Generic way to allocate field_info and add to proto_tree.
|
2002-01-07 01:05:33 +00:00
|
|
|
* Sets *pfi to address of newly-allocated field_info struct, if pfi is
|
|
|
|
* non-NULL. */
|
2000-03-12 04:48:32 +00:00
|
|
|
static proto_item *
|
2002-02-18 22:26:29 +00:00
|
|
|
proto_tree_add_pi(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
|
|
|
|
gint *length, field_info **pfi)
|
2000-03-12 04:48:32 +00:00
|
|
|
{
|
|
|
|
proto_item *pi;
|
|
|
|
field_info *fi;
|
2002-01-07 01:05:33 +00:00
|
|
|
GHashTable *hash;
|
|
|
|
GPtrArray *ptrs;
|
2000-03-12 04:48:32 +00:00
|
|
|
|
|
|
|
if (!tree)
|
|
|
|
return(NULL);
|
|
|
|
|
2001-12-18 19:09:08 +00:00
|
|
|
fi = alloc_field_info(tree, hfindex, tvb, start, length);
|
2000-07-27 06:41:59 +00:00
|
|
|
pi = proto_tree_add_node(tree, fi);
|
|
|
|
|
2002-01-07 01:05:33 +00:00
|
|
|
/* If the proto_tree wants to keep a record of this finfo
|
|
|
|
* for quick lookup, then record it. */
|
2005-04-11 08:43:51 +00:00
|
|
|
if (fi->hfinfo->ref_count) {
|
|
|
|
hash = PTREE_DATA(tree)->interesting_hfids;
|
|
|
|
ptrs = g_hash_table_lookup(hash, GINT_TO_POINTER(hfindex));
|
|
|
|
if (ptrs) {
|
|
|
|
g_ptr_array_add(ptrs, fi);
|
|
|
|
}
|
2002-01-07 01:05:33 +00:00
|
|
|
}
|
2001-12-18 19:09:08 +00:00
|
|
|
|
2002-01-07 01:05:33 +00:00
|
|
|
/* Does the caller want to know the fi pointer? */
|
2000-07-27 06:41:59 +00:00
|
|
|
if (pfi) {
|
|
|
|
*pfi = fi;
|
|
|
|
}
|
|
|
|
|
|
|
|
return pi;
|
|
|
|
}
|
|
|
|
|
2005-10-22 05:43:09 +00:00
|
|
|
|
|
|
|
static header_field_info *
|
|
|
|
get_hfi_and_length(int hfindex, tvbuff_t *tvb, gint start, gint *length,
|
|
|
|
gint *item_length)
|
2000-07-27 06:41:59 +00:00
|
|
|
{
|
Allow a length of -1 to be specified when adding FT_NONE and FT_PROTOCOL
items to the protocol tree; it's interpreted as "the rest of the data in
the tvbuff". This can be used if
1) the item covers the entire packet or the remaining payload in
the packet
or
2) the item's length won't be known until it's dissected, and
will be then set with "proto_item_set_len()" - if an
exception is thrown in the dissection, it means the item ran
*past* the end of the tvbuff, so saying it runs to the end of
the tvbuff is reasonable.
Convert a number of "proto_tree_add_XXX()" calls using
"tvb_length_remaining()", values derived from the result of
"tvb_length()", or 0 (in the case of items whose length is unknown) to
use -1 instead (using 0 means that if an exception is thrown, selecting
the item highlights nothing; using -1 means it highlights all the data
for that item that's available).
In some places where "tvb_length()" or "tvb_length_remaining()" was used
to determine how large a packet is, use "tvb_reported_length()" or
"tvb_reported_length_remaining()", instead - the first two calls
indicate how much captured data was in the packet, the latter two calls
indicate how large the packet actually was (and the fact that using the
latter could cause BoundsError exceptions to be thrown is a feature - if
such an exception is thrown, the frame really *was* short, and it should
be tagged as such).
Replace some "proto_tree_add_XXX()" calls with equivalent
"proto_tree_add_item()" calls.
Fix some indentation.
svn path=/trunk/; revision=4578
2002-01-20 22:12:39 +00:00
|
|
|
header_field_info *hfinfo;
|
2005-03-26 03:27:22 +00:00
|
|
|
gint length_remaining;
|
2001-11-20 09:07:34 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* We only allow a null tvbuff if the item has a zero length,
|
|
|
|
* i.e. if there's no data backing it.
|
|
|
|
*/
|
2005-03-23 00:09:12 +00:00
|
|
|
DISSECTOR_ASSERT(tvb != NULL || *length == 0);
|
Allow a length of -1 to be specified when adding FT_NONE and FT_PROTOCOL
items to the protocol tree; it's interpreted as "the rest of the data in
the tvbuff". This can be used if
1) the item covers the entire packet or the remaining payload in
the packet
or
2) the item's length won't be known until it's dissected, and
will be then set with "proto_item_set_len()" - if an
exception is thrown in the dissection, it means the item ran
*past* the end of the tvbuff, so saying it runs to the end of
the tvbuff is reasonable.
Convert a number of "proto_tree_add_XXX()" calls using
"tvb_length_remaining()", values derived from the result of
"tvb_length()", or 0 (in the case of items whose length is unknown) to
use -1 instead (using 0 means that if an exception is thrown, selecting
the item highlights nothing; using -1 means it highlights all the data
for that item that's available).
In some places where "tvb_length()" or "tvb_length_remaining()" was used
to determine how large a packet is, use "tvb_reported_length()" or
"tvb_reported_length_remaining()", instead - the first two calls
indicate how much captured data was in the packet, the latter two calls
indicate how large the packet actually was (and the fact that using the
latter could cause BoundsError exceptions to be thrown is a feature - if
such an exception is thrown, the frame really *was* short, and it should
be tagged as such).
Replace some "proto_tree_add_XXX()" calls with equivalent
"proto_tree_add_item()" calls.
Fix some indentation.
svn path=/trunk/; revision=4578
2002-01-20 22:12:39 +00:00
|
|
|
|
2003-11-22 04:41:31 +00:00
|
|
|
PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
|
Allow a length of -1 to be specified when adding FT_NONE and FT_PROTOCOL
items to the protocol tree; it's interpreted as "the rest of the data in
the tvbuff". This can be used if
1) the item covers the entire packet or the remaining payload in
the packet
or
2) the item's length won't be known until it's dissected, and
will be then set with "proto_item_set_len()" - if an
exception is thrown in the dissection, it means the item ran
*past* the end of the tvbuff, so saying it runs to the end of
the tvbuff is reasonable.
Convert a number of "proto_tree_add_XXX()" calls using
"tvb_length_remaining()", values derived from the result of
"tvb_length()", or 0 (in the case of items whose length is unknown) to
use -1 instead (using 0 means that if an exception is thrown, selecting
the item highlights nothing; using -1 means it highlights all the data
for that item that's available).
In some places where "tvb_length()" or "tvb_length_remaining()" was used
to determine how large a packet is, use "tvb_reported_length()" or
"tvb_reported_length_remaining()", instead - the first two calls
indicate how much captured data was in the packet, the latter two calls
indicate how large the packet actually was (and the fact that using the
latter could cause BoundsError exceptions to be thrown is a feature - if
such an exception is thrown, the frame really *was* short, and it should
be tagged as such).
Replace some "proto_tree_add_XXX()" calls with equivalent
"proto_tree_add_item()" calls.
Fix some indentation.
svn path=/trunk/; revision=4578
2002-01-20 22:12:39 +00:00
|
|
|
|
2005-03-26 03:27:22 +00:00
|
|
|
/*
|
|
|
|
* XXX - in some protocols, there are 32-bit unsigned length
|
|
|
|
* fields, so lengths in protocol tree and tvbuff routines
|
|
|
|
* should really be unsigned. We should have, for those
|
|
|
|
* field types for which "to the end of the tvbuff" makes sense,
|
|
|
|
* additional routines that take no length argument and
|
|
|
|
* add fields that run to the end of the tvbuff.
|
|
|
|
*/
|
2005-04-28 03:30:07 +00:00
|
|
|
if (*length == -1) {
|
Allow a length of -1 to be specified when adding FT_NONE and FT_PROTOCOL
items to the protocol tree; it's interpreted as "the rest of the data in
the tvbuff". This can be used if
1) the item covers the entire packet or the remaining payload in
the packet
or
2) the item's length won't be known until it's dissected, and
will be then set with "proto_item_set_len()" - if an
exception is thrown in the dissection, it means the item ran
*past* the end of the tvbuff, so saying it runs to the end of
the tvbuff is reasonable.
Convert a number of "proto_tree_add_XXX()" calls using
"tvb_length_remaining()", values derived from the result of
"tvb_length()", or 0 (in the case of items whose length is unknown) to
use -1 instead (using 0 means that if an exception is thrown, selecting
the item highlights nothing; using -1 means it highlights all the data
for that item that's available).
In some places where "tvb_length()" or "tvb_length_remaining()" was used
to determine how large a packet is, use "tvb_reported_length()" or
"tvb_reported_length_remaining()", instead - the first two calls
indicate how much captured data was in the packet, the latter two calls
indicate how large the packet actually was (and the fact that using the
latter could cause BoundsError exceptions to be thrown is a feature - if
such an exception is thrown, the frame really *was* short, and it should
be tagged as such).
Replace some "proto_tree_add_XXX()" calls with equivalent
"proto_tree_add_item()" calls.
Fix some indentation.
svn path=/trunk/; revision=4578
2002-01-20 22:12:39 +00:00
|
|
|
/*
|
2002-02-18 22:26:29 +00:00
|
|
|
* For FT_NONE, FT_PROTOCOL, FT_BYTES, and FT_STRING fields,
|
|
|
|
* a length of -1 means "set the length to what remains in
|
|
|
|
* the tvbuff".
|
|
|
|
*
|
|
|
|
* The assumption is either that
|
|
|
|
*
|
|
|
|
* 1) the length of the item can only be determined
|
|
|
|
* by dissection (typically true of items with
|
|
|
|
* subitems, which are probably FT_NONE or
|
|
|
|
* FT_PROTOCOL)
|
|
|
|
*
|
|
|
|
* or
|
|
|
|
*
|
|
|
|
* 2) if the tvbuff is "short" (either due to a short
|
|
|
|
* snapshot length or due to lack of reassembly of
|
|
|
|
* fragments/segments/whatever), we want to display
|
|
|
|
* what's available in the field (probably FT_BYTES
|
|
|
|
* or FT_STRING) and then throw an exception later
|
|
|
|
*
|
|
|
|
* or
|
|
|
|
*
|
|
|
|
* 3) the field is defined to be "what's left in the
|
|
|
|
* packet"
|
|
|
|
*
|
|
|
|
* so we set the length to what remains in the tvbuff so
|
|
|
|
* that, if we throw an exception while dissecting, it
|
|
|
|
* has what is probably the right value.
|
Allow a length of -1 to be specified when adding FT_NONE and FT_PROTOCOL
items to the protocol tree; it's interpreted as "the rest of the data in
the tvbuff". This can be used if
1) the item covers the entire packet or the remaining payload in
the packet
or
2) the item's length won't be known until it's dissected, and
will be then set with "proto_item_set_len()" - if an
exception is thrown in the dissection, it means the item ran
*past* the end of the tvbuff, so saying it runs to the end of
the tvbuff is reasonable.
Convert a number of "proto_tree_add_XXX()" calls using
"tvb_length_remaining()", values derived from the result of
"tvb_length()", or 0 (in the case of items whose length is unknown) to
use -1 instead (using 0 means that if an exception is thrown, selecting
the item highlights nothing; using -1 means it highlights all the data
for that item that's available).
In some places where "tvb_length()" or "tvb_length_remaining()" was used
to determine how large a packet is, use "tvb_reported_length()" or
"tvb_reported_length_remaining()", instead - the first two calls
indicate how much captured data was in the packet, the latter two calls
indicate how large the packet actually was (and the fact that using the
latter could cause BoundsError exceptions to be thrown is a feature - if
such an exception is thrown, the frame really *was* short, and it should
be tagged as such).
Replace some "proto_tree_add_XXX()" calls with equivalent
"proto_tree_add_item()" calls.
Fix some indentation.
svn path=/trunk/; revision=4578
2002-01-20 22:12:39 +00:00
|
|
|
*
|
When "proto_tree_add_item()" is used with an FT_STRINGZ and given a
length (rather than being given -1), the length is, in most cases, the
maximum length of a null-*padded* string, rather than the actual length
of a null-*terminated* string. Treat it as such - allocate a buffer one
larger than the length (to leave room for a terminating '\0'), and pass
the size of that buffer to "tvb_get_nstringz0()". (Otherwise, in those
cases, the last character of the string is chopped off.)
Allow "proto_tree_add_string()" to add FT_STRINGZ items to the protocol
tree, as well as FT_STRING items.
In "alloc_field_info()", if we're passed a length of -1 and the field is
an FT_STRINGZ, don't make the length be the length remaining in the
tvbuff; that way, you *can* use a length of -1 in
"proto_tree_add_item()" for an FT_STRINGZ item, and have it get the
actual length by looking for the terminating '\0'.
(We might want to distinguish between null-terminated and null-padded
strings, e.g. with an FT_STRINGZPAD type. Null-terminated strings
rarely, if ever, have a specified length; the length is found by
scanning for the terminating '\0'. Null-padded strings presumably
always have a specified length, which is the length to which the string
is padded.)
svn path=/trunk/; revision=7784
2003-06-04 21:51:54 +00:00
|
|
|
* For FT_STRINGZ, it means "the string is null-terminated,
|
|
|
|
* not null-padded; set the length to the actual length
|
|
|
|
* of the string", and if the tvbuff if short, we just
|
|
|
|
* throw an exception.
|
|
|
|
*
|
Allow a length of -1 to be specified when adding FT_NONE and FT_PROTOCOL
items to the protocol tree; it's interpreted as "the rest of the data in
the tvbuff". This can be used if
1) the item covers the entire packet or the remaining payload in
the packet
or
2) the item's length won't be known until it's dissected, and
will be then set with "proto_item_set_len()" - if an
exception is thrown in the dissection, it means the item ran
*past* the end of the tvbuff, so saying it runs to the end of
the tvbuff is reasonable.
Convert a number of "proto_tree_add_XXX()" calls using
"tvb_length_remaining()", values derived from the result of
"tvb_length()", or 0 (in the case of items whose length is unknown) to
use -1 instead (using 0 means that if an exception is thrown, selecting
the item highlights nothing; using -1 means it highlights all the data
for that item that's available).
In some places where "tvb_length()" or "tvb_length_remaining()" was used
to determine how large a packet is, use "tvb_reported_length()" or
"tvb_reported_length_remaining()", instead - the first two calls
indicate how much captured data was in the packet, the latter two calls
indicate how large the packet actually was (and the fact that using the
latter could cause BoundsError exceptions to be thrown is a feature - if
such an exception is thrown, the frame really *was* short, and it should
be tagged as such).
Replace some "proto_tree_add_XXX()" calls with equivalent
"proto_tree_add_item()" calls.
Fix some indentation.
svn path=/trunk/; revision=4578
2002-01-20 22:12:39 +00:00
|
|
|
* It's not valid for any other type of field.
|
|
|
|
*/
|
When "proto_tree_add_item()" is used with an FT_STRINGZ and given a
length (rather than being given -1), the length is, in most cases, the
maximum length of a null-*padded* string, rather than the actual length
of a null-*terminated* string. Treat it as such - allocate a buffer one
larger than the length (to leave room for a terminating '\0'), and pass
the size of that buffer to "tvb_get_nstringz0()". (Otherwise, in those
cases, the last character of the string is chopped off.)
Allow "proto_tree_add_string()" to add FT_STRINGZ items to the protocol
tree, as well as FT_STRING items.
In "alloc_field_info()", if we're passed a length of -1 and the field is
an FT_STRINGZ, don't make the length be the length remaining in the
tvbuff; that way, you *can* use a length of -1 in
"proto_tree_add_item()" for an FT_STRINGZ item, and have it get the
actual length by looking for the terminating '\0'.
(We might want to distinguish between null-terminated and null-padded
strings, e.g. with an FT_STRINGZPAD type. Null-terminated strings
rarely, if ever, have a specified length; the length is found by
scanning for the terminating '\0'. Null-padded strings presumably
always have a specified length, which is the length to which the string
is padded.)
svn path=/trunk/; revision=7784
2003-06-04 21:51:54 +00:00
|
|
|
switch (hfinfo->type) {
|
|
|
|
|
|
|
|
case FT_PROTOCOL:
|
2003-12-24 23:37:28 +00:00
|
|
|
/*
|
|
|
|
* We allow this to be zero-length - for
|
|
|
|
* example, an ONC RPC NULL procedure has
|
|
|
|
* neither arguments nor reply, so the
|
|
|
|
* payload for that protocol is empty.
|
|
|
|
*
|
|
|
|
* However, if the length is negative, the
|
|
|
|
* start offset is *past* the byte past the
|
|
|
|
* end of the tvbuff, so we throw an
|
|
|
|
* exception.
|
|
|
|
*/
|
2003-12-24 11:07:03 +00:00
|
|
|
*length = tvb_length_remaining(tvb, start);
|
2003-12-24 23:37:28 +00:00
|
|
|
if (*length < 0) {
|
|
|
|
/*
|
|
|
|
* Use "tvb_ensure_bytes_exist()"
|
|
|
|
* to force the appropriate exception
|
|
|
|
* to be thrown.
|
|
|
|
*/
|
|
|
|
tvb_ensure_bytes_exist(tvb, start, 0);
|
|
|
|
}
|
2005-03-23 00:09:12 +00:00
|
|
|
DISSECTOR_ASSERT(*length >= 0);
|
2003-12-24 11:07:03 +00:00
|
|
|
break;
|
|
|
|
|
When "proto_tree_add_item()" is used with an FT_STRINGZ and given a
length (rather than being given -1), the length is, in most cases, the
maximum length of a null-*padded* string, rather than the actual length
of a null-*terminated* string. Treat it as such - allocate a buffer one
larger than the length (to leave room for a terminating '\0'), and pass
the size of that buffer to "tvb_get_nstringz0()". (Otherwise, in those
cases, the last character of the string is chopped off.)
Allow "proto_tree_add_string()" to add FT_STRINGZ items to the protocol
tree, as well as FT_STRING items.
In "alloc_field_info()", if we're passed a length of -1 and the field is
an FT_STRINGZ, don't make the length be the length remaining in the
tvbuff; that way, you *can* use a length of -1 in
"proto_tree_add_item()" for an FT_STRINGZ item, and have it get the
actual length by looking for the terminating '\0'.
(We might want to distinguish between null-terminated and null-padded
strings, e.g. with an FT_STRINGZPAD type. Null-terminated strings
rarely, if ever, have a specified length; the length is found by
scanning for the terminating '\0'. Null-padded strings presumably
always have a specified length, which is the length to which the string
is padded.)
svn path=/trunk/; revision=7784
2003-06-04 21:51:54 +00:00
|
|
|
case FT_NONE:
|
|
|
|
case FT_BYTES:
|
|
|
|
case FT_STRING:
|
|
|
|
*length = tvb_ensure_length_remaining(tvb, start);
|
2005-03-23 00:09:12 +00:00
|
|
|
DISSECTOR_ASSERT(*length >= 0);
|
When "proto_tree_add_item()" is used with an FT_STRINGZ and given a
length (rather than being given -1), the length is, in most cases, the
maximum length of a null-*padded* string, rather than the actual length
of a null-*terminated* string. Treat it as such - allocate a buffer one
larger than the length (to leave room for a terminating '\0'), and pass
the size of that buffer to "tvb_get_nstringz0()". (Otherwise, in those
cases, the last character of the string is chopped off.)
Allow "proto_tree_add_string()" to add FT_STRINGZ items to the protocol
tree, as well as FT_STRING items.
In "alloc_field_info()", if we're passed a length of -1 and the field is
an FT_STRINGZ, don't make the length be the length remaining in the
tvbuff; that way, you *can* use a length of -1 in
"proto_tree_add_item()" for an FT_STRINGZ item, and have it get the
actual length by looking for the terminating '\0'.
(We might want to distinguish between null-terminated and null-padded
strings, e.g. with an FT_STRINGZPAD type. Null-terminated strings
rarely, if ever, have a specified length; the length is found by
scanning for the terminating '\0'. Null-padded strings presumably
always have a specified length, which is the length to which the string
is padded.)
svn path=/trunk/; revision=7784
2003-06-04 21:51:54 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case FT_STRINGZ:
|
|
|
|
/*
|
|
|
|
* Leave the length as -1, so our caller knows
|
|
|
|
* it was -1.
|
|
|
|
*/
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2005-03-23 00:09:12 +00:00
|
|
|
DISSECTOR_ASSERT_NOT_REACHED();
|
When "proto_tree_add_item()" is used with an FT_STRINGZ and given a
length (rather than being given -1), the length is, in most cases, the
maximum length of a null-*padded* string, rather than the actual length
of a null-*terminated* string. Treat it as such - allocate a buffer one
larger than the length (to leave room for a terminating '\0'), and pass
the size of that buffer to "tvb_get_nstringz0()". (Otherwise, in those
cases, the last character of the string is chopped off.)
Allow "proto_tree_add_string()" to add FT_STRINGZ items to the protocol
tree, as well as FT_STRING items.
In "alloc_field_info()", if we're passed a length of -1 and the field is
an FT_STRINGZ, don't make the length be the length remaining in the
tvbuff; that way, you *can* use a length of -1 in
"proto_tree_add_item()" for an FT_STRINGZ item, and have it get the
actual length by looking for the terminating '\0'.
(We might want to distinguish between null-terminated and null-padded
strings, e.g. with an FT_STRINGZPAD type. Null-terminated strings
rarely, if ever, have a specified length; the length is found by
scanning for the terminating '\0'. Null-padded strings presumably
always have a specified length, which is the length to which the string
is padded.)
svn path=/trunk/; revision=7784
2003-06-04 21:51:54 +00:00
|
|
|
}
|
2005-10-22 05:43:09 +00:00
|
|
|
*item_length = *length;
|
2005-01-17 00:56:56 +00:00
|
|
|
} else {
|
2005-10-22 05:43:09 +00:00
|
|
|
*item_length = *length;
|
2005-03-26 03:27:22 +00:00
|
|
|
if (hfinfo->type == FT_PROTOCOL || hfinfo->type == FT_NONE) {
|
|
|
|
/*
|
|
|
|
* These types are for interior nodes of the
|
|
|
|
* tree, and don't have data associated with
|
|
|
|
* them; if the length is negative (XXX - see
|
|
|
|
* above) or goes past the end of the tvbuff,
|
|
|
|
* cut it short at the end of the tvbuff.
|
|
|
|
* That way, if this field is selected in
|
|
|
|
* Ethereal, we don't highlight stuff past
|
|
|
|
* the end of the data.
|
|
|
|
*/
|
2005-10-22 05:43:09 +00:00
|
|
|
/* XXX - what to do, if we don't have a tvb? */
|
|
|
|
if (tvb) {
|
|
|
|
length_remaining = tvb_length_remaining(tvb, start);
|
|
|
|
if (*item_length < 0 ||
|
|
|
|
(*item_length > 0 &&
|
|
|
|
(length_remaining < *item_length)))
|
|
|
|
*item_length = length_remaining;
|
|
|
|
}
|
2005-03-26 03:27:22 +00:00
|
|
|
}
|
2005-10-22 05:43:09 +00:00
|
|
|
if (*item_length < 0) {
|
2005-04-28 04:03:30 +00:00
|
|
|
THROW(ReportedBoundsError);
|
|
|
|
}
|
2005-01-17 00:56:56 +00:00
|
|
|
}
|
Allow a length of -1 to be specified when adding FT_NONE and FT_PROTOCOL
items to the protocol tree; it's interpreted as "the rest of the data in
the tvbuff". This can be used if
1) the item covers the entire packet or the remaining payload in
the packet
or
2) the item's length won't be known until it's dissected, and
will be then set with "proto_item_set_len()" - if an
exception is thrown in the dissection, it means the item ran
*past* the end of the tvbuff, so saying it runs to the end of
the tvbuff is reasonable.
Convert a number of "proto_tree_add_XXX()" calls using
"tvb_length_remaining()", values derived from the result of
"tvb_length()", or 0 (in the case of items whose length is unknown) to
use -1 instead (using 0 means that if an exception is thrown, selecting
the item highlights nothing; using -1 means it highlights all the data
for that item that's available).
In some places where "tvb_length()" or "tvb_length_remaining()" was used
to determine how large a packet is, use "tvb_reported_length()" or
"tvb_reported_length_remaining()", instead - the first two calls
indicate how much captured data was in the packet, the latter two calls
indicate how large the packet actually was (and the fact that using the
latter could cause BoundsError exceptions to be thrown is a feature - if
such an exception is thrown, the frame really *was* short, and it should
be tagged as such).
Replace some "proto_tree_add_XXX()" calls with equivalent
"proto_tree_add_item()" calls.
Fix some indentation.
svn path=/trunk/; revision=4578
2002-01-20 22:12:39 +00:00
|
|
|
|
2005-10-22 05:43:09 +00:00
|
|
|
return hfinfo;
|
|
|
|
}
|
|
|
|
|
|
|
|
static field_info *
|
|
|
|
new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
|
|
|
|
gint start, gint item_length)
|
|
|
|
{
|
|
|
|
field_info *fi;
|
|
|
|
|
2003-11-25 14:10:27 +00:00
|
|
|
FIELD_INFO_NEW(fi);
|
2003-11-24 21:12:10 +00:00
|
|
|
|
2003-12-03 09:28:26 +00:00
|
|
|
fi->hfinfo = hfinfo;
|
2000-05-31 05:09:07 +00:00
|
|
|
fi->start = start;
|
2003-12-03 09:50:40 +00:00
|
|
|
fi->start+=(tvb)?TVB_RAW_OFFSET(tvb):0;
|
2005-03-26 03:27:22 +00:00
|
|
|
fi->length = item_length;
|
2002-04-01 02:00:53 +00:00
|
|
|
fi->tree_type = -1;
|
2004-05-01 15:15:08 +00:00
|
|
|
fi->flags = 0;
|
2004-10-27 10:02:45 +00:00
|
|
|
if (!PTREE_DATA(tree)->visible)
|
|
|
|
FI_SET_FLAG(fi, FI_HIDDEN);
|
2003-12-03 09:28:26 +00:00
|
|
|
fvalue_init(&fi->value, fi->hfinfo->type);
|
2003-11-25 14:07:45 +00:00
|
|
|
fi->rep = NULL;
|
2000-03-12 04:48:32 +00:00
|
|
|
|
2002-02-18 01:08:44 +00:00
|
|
|
/* add the data source tvbuff */
|
2003-12-02 10:23:18 +00:00
|
|
|
fi->ds_tvb=tvb?TVB_GET_DS_TVB(tvb):NULL;
|
2001-03-23 14:44:04 +00:00
|
|
|
|
2000-07-27 06:41:59 +00:00
|
|
|
return fi;
|
1999-07-07 22:52:57 +00:00
|
|
|
}
|
|
|
|
|
2005-10-22 05:43:09 +00:00
|
|
|
static field_info *
|
|
|
|
alloc_field_info(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
|
|
|
|
gint *length)
|
|
|
|
{
|
|
|
|
header_field_info *hfinfo;
|
|
|
|
gint item_length;
|
|
|
|
|
|
|
|
hfinfo = get_hfi_and_length(hfindex, tvb, start, length, &item_length);
|
|
|
|
return new_field_info(tree, hfinfo, tvb, start, item_length);
|
|
|
|
}
|
|
|
|
|
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)
|
|
|
|
{
|
2002-12-31 21:37:29 +00:00
|
|
|
int ret; /*tmp return value */
|
2001-12-18 19:09:08 +00:00
|
|
|
field_info *fi = PITEM_FINFO(pi);
|
2000-05-31 05:09:07 +00:00
|
|
|
|
2004-05-01 15:15:08 +00:00
|
|
|
if (!PROTO_ITEM_IS_HIDDEN(pi)) {
|
2003-11-25 14:07:45 +00:00
|
|
|
ITEM_LABEL_NEW(fi->rep);
|
2005-08-18 19:31:15 +00:00
|
|
|
ret = g_vsnprintf(fi->rep->representation, ITEM_LABEL_LENGTH, format, ap);
|
2002-12-31 21:37:29 +00:00
|
|
|
if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
|
2003-11-25 14:07:45 +00:00
|
|
|
fi->rep->representation[ITEM_LABEL_LENGTH - 1] = '\0';
|
2000-05-31 05:09:07 +00:00
|
|
|
}
|
|
|
|
}
|
2000-03-12 04:48:32 +00:00
|
|
|
|
2001-08-29 00:51:10 +00:00
|
|
|
/* Set text of proto_item after having already been created. */
|
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
|
|
|
{
|
2001-11-03 11:42:50 +00:00
|
|
|
field_info *fi = NULL;
|
2000-01-22 04:59:55 +00:00
|
|
|
va_list ap;
|
|
|
|
|
2001-11-03 11:42:50 +00:00
|
|
|
if (pi==NULL) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2001-12-18 19:09:08 +00:00
|
|
|
fi = PITEM_FINFO(pi);
|
2001-11-03 11:42:50 +00:00
|
|
|
|
2003-11-26 12:22:22 +00:00
|
|
|
if(fi->rep){
|
|
|
|
ITEM_LABEL_FREE(fi->rep);
|
|
|
|
}
|
2000-01-22 04:59:55 +00:00
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2001-08-29 00:51:10 +00:00
|
|
|
/* Append to text of proto_item after having already been created. */
|
|
|
|
void
|
|
|
|
proto_item_append_text(proto_item *pi, const char *format, ...)
|
|
|
|
{
|
2001-11-03 11:42:50 +00:00
|
|
|
field_info *fi = NULL;
|
2001-08-29 00:51:10 +00:00
|
|
|
size_t curlen;
|
|
|
|
va_list ap;
|
2002-12-31 21:37:29 +00:00
|
|
|
int ret; /*tmp return value */
|
2001-08-29 00:51:10 +00:00
|
|
|
|
2001-11-03 11:42:50 +00:00
|
|
|
if (pi==NULL) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2001-12-18 19:09:08 +00:00
|
|
|
fi = PITEM_FINFO(pi);
|
2001-11-03 11:42:50 +00:00
|
|
|
|
2004-05-01 15:15:08 +00:00
|
|
|
if (!PROTO_ITEM_IS_HIDDEN(pi)) {
|
2001-08-29 00:51:10 +00:00
|
|
|
va_start(ap, format);
|
2002-03-19 08:42:16 +00:00
|
|
|
|
2001-08-29 00:51:10 +00:00
|
|
|
/*
|
2002-03-19 08:42:16 +00:00
|
|
|
* If we don't already have a representation,
|
|
|
|
* generate the default representation.
|
2001-08-29 00:51:10 +00:00
|
|
|
*/
|
2003-11-25 14:07:45 +00:00
|
|
|
if (fi->rep == NULL) {
|
|
|
|
ITEM_LABEL_NEW(fi->rep);
|
|
|
|
proto_item_fill_label(fi, fi->rep->representation);
|
2002-03-19 08:42:16 +00:00
|
|
|
}
|
|
|
|
|
2003-11-25 14:07:45 +00:00
|
|
|
curlen = strlen(fi->rep->representation);
|
2002-12-31 21:37:29 +00:00
|
|
|
if (ITEM_LABEL_LENGTH > curlen) {
|
2005-08-18 19:31:15 +00:00
|
|
|
ret = g_vsnprintf(fi->rep->representation + curlen,
|
2001-08-29 00:51:10 +00:00
|
|
|
ITEM_LABEL_LENGTH - curlen, format, ap);
|
2002-12-31 21:37:29 +00:00
|
|
|
if ((ret == -1) || (ret >= (int)(ITEM_LABEL_LENGTH - curlen)))
|
2003-11-25 14:07:45 +00:00
|
|
|
fi->rep->representation[ITEM_LABEL_LENGTH - 1] = '\0';
|
2002-12-31 21:37:29 +00:00
|
|
|
}
|
2001-08-29 00:51:10 +00:00
|
|
|
va_end(ap);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-07-07 22:52:57 +00:00
|
|
|
void
|
|
|
|
proto_item_set_len(proto_item *pi, gint length)
|
|
|
|
{
|
2001-05-07 21:06:59 +00:00
|
|
|
field_info *fi;
|
2002-08-28 20:41:00 +00:00
|
|
|
|
2001-05-07 21:06:59 +00:00
|
|
|
if (pi == NULL)
|
|
|
|
return;
|
2001-12-18 19:09:08 +00:00
|
|
|
fi = PITEM_FINFO(pi);
|
2005-03-23 00:09:12 +00:00
|
|
|
DISSECTOR_ASSERT(length >= 0);
|
1999-07-07 22:52:57 +00:00
|
|
|
fi->length = length;
|
|
|
|
}
|
|
|
|
|
2003-04-29 21:27:19 +00:00
|
|
|
/*
|
|
|
|
* Sets the length of the item based on its start and on the specified
|
|
|
|
* offset, which is the offset past the end of the item; as the start
|
|
|
|
* in the item is relative to the beginning of the data source tvbuff,
|
|
|
|
* we need to pass in a tvbuff - the end offset is relative to the beginning
|
|
|
|
* of that tvbuff.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
proto_item_set_end(proto_item *pi, tvbuff_t *tvb, gint end)
|
|
|
|
{
|
|
|
|
field_info *fi;
|
|
|
|
|
|
|
|
if (pi == NULL)
|
|
|
|
return;
|
|
|
|
fi = PITEM_FINFO(pi);
|
2003-12-03 09:50:40 +00:00
|
|
|
end += TVB_RAW_OFFSET(tvb);
|
2005-03-23 00:09:12 +00:00
|
|
|
DISSECTOR_ASSERT(end >= fi->start);
|
2003-04-29 21:27:19 +00:00
|
|
|
fi->length = end - fi->start;
|
|
|
|
}
|
|
|
|
|
2000-07-27 06:41:59 +00:00
|
|
|
int
|
|
|
|
proto_item_get_len(proto_item *pi)
|
|
|
|
{
|
2001-12-18 19:09:08 +00:00
|
|
|
field_info *fi = PITEM_FINFO(pi);
|
2000-07-27 06:41:59 +00:00
|
|
|
return fi->length;
|
|
|
|
}
|
|
|
|
|
2005-09-11 16:55:34 +00:00
|
|
|
|
|
|
|
/** clear flags according to the mask and set new flag values */
|
|
|
|
#define FI_REPLACE_FLAGS(fi, mask, flags_in) { \
|
|
|
|
(fi->flags = (fi)->flags & ~(mask)); \
|
|
|
|
(fi->flags = (fi)->flags | (flags_in)); \
|
|
|
|
}
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
proto_item_set_expert_flags(proto_item *pi, int group, int severity)
|
|
|
|
{
|
|
|
|
if(pi == NULL || pi->finfo == NULL)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
/* only change things if severity is worse or at least equal than before */
|
|
|
|
if(severity >= FI_GET_FLAG(pi->finfo, PI_SEVERITY_MASK)) {
|
|
|
|
FI_REPLACE_FLAGS(pi->finfo, PI_GROUP_MASK, group);
|
|
|
|
FI_REPLACE_FLAGS(pi->finfo, PI_SEVERITY_MASK, severity);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
1999-07-07 22:52:57 +00:00
|
|
|
proto_tree*
|
|
|
|
proto_tree_create_root(void)
|
|
|
|
{
|
2002-04-04 20:23:50 +00:00
|
|
|
proto_node *pnode;
|
2001-12-18 19:09:08 +00:00
|
|
|
|
2002-04-04 20:23:50 +00:00
|
|
|
/* Initialize the proto_node */
|
2003-11-26 12:22:22 +00:00
|
|
|
PROTO_NODE_NEW(pnode);
|
2003-12-04 19:53:54 +00:00
|
|
|
pnode->parent = NULL;
|
2002-04-04 20:23:50 +00:00
|
|
|
pnode->finfo = NULL;
|
|
|
|
pnode->tree_data = g_new(tree_data_t, 1);
|
|
|
|
|
|
|
|
/* Initialize the tree_data_t */
|
|
|
|
pnode->tree_data->interesting_hfids =
|
|
|
|
g_hash_table_new(g_direct_hash, g_direct_equal);
|
|
|
|
|
|
|
|
/* Set the default to FALSE so it's easier to
|
|
|
|
* find errors; if we expect to see the protocol tree
|
|
|
|
* but for some reason the default 'visible' is not
|
|
|
|
* changed, then we'll find out very quickly. */
|
|
|
|
pnode->tree_data->visible = FALSE;
|
2001-12-18 19:09:08 +00:00
|
|
|
|
2003-12-04 10:59:34 +00:00
|
|
|
return (proto_tree*) pnode;
|
2001-12-18 19:09:08 +00:00
|
|
|
}
|
|
|
|
|
2002-08-28 20:41:00 +00:00
|
|
|
|
2002-05-09 23:50:34 +00:00
|
|
|
/* "prime" a proto_tree with a single hfid that a dfilter
|
|
|
|
* is interested in. */
|
2001-12-18 19:09:08 +00:00
|
|
|
void
|
2002-05-09 23:50:34 +00:00
|
|
|
proto_tree_prime_hfid(proto_tree *tree, gint hfid)
|
2001-12-18 19:09:08 +00:00
|
|
|
{
|
2005-04-11 08:43:51 +00:00
|
|
|
header_field_info *hfinfo;
|
|
|
|
|
2002-04-20 08:07:56 +00:00
|
|
|
g_hash_table_insert(PTREE_DATA(tree)->interesting_hfids,
|
2002-05-09 23:50:34 +00:00
|
|
|
GINT_TO_POINTER(hfid), g_ptr_array_new());
|
1999-07-07 22:52:57 +00:00
|
|
|
|
2005-04-11 08:43:51 +00:00
|
|
|
PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
|
|
|
|
/* this field is referenced by a filter so increase the refcount.
|
|
|
|
also increase the refcount for the parent, i.e the protocol.
|
|
|
|
*/
|
|
|
|
hfinfo->ref_count++;
|
|
|
|
/* only increase the refcount if there is a parent.
|
|
|
|
if this is a protocol and not a field then parent will be -1
|
|
|
|
and there is no parent to add any refcounting for.
|
|
|
|
*/
|
|
|
|
if (hfinfo->parent != -1) {
|
|
|
|
header_field_info *parent_hfinfo;
|
|
|
|
PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
|
|
|
|
parent_hfinfo->ref_count++;
|
|
|
|
}
|
|
|
|
}
|
2002-05-09 23:50:34 +00:00
|
|
|
|
1999-07-07 22:52:57 +00:00
|
|
|
proto_tree*
|
|
|
|
proto_item_add_subtree(proto_item *pi, gint idx) {
|
2001-03-26 17:58:33 +00:00
|
|
|
field_info *fi;
|
|
|
|
|
|
|
|
if (!pi)
|
|
|
|
return(NULL);
|
|
|
|
|
2001-12-18 19:09:08 +00:00
|
|
|
fi = PITEM_FINFO(pi);
|
2005-03-23 00:09:12 +00:00
|
|
|
DISSECTOR_ASSERT(idx >= 0 && idx < num_tree_types);
|
1999-07-07 22:52:57 +00:00
|
|
|
fi->tree_type = idx;
|
2005-04-11 08:43:51 +00:00
|
|
|
|
1999-07-07 22:52:57 +00:00
|
|
|
return (proto_tree*) pi;
|
|
|
|
}
|
|
|
|
|
2004-03-25 09:18:03 +00:00
|
|
|
proto_tree*
|
|
|
|
proto_item_get_subtree(proto_item *pi) {
|
|
|
|
field_info *fi;
|
|
|
|
|
|
|
|
if (!pi)
|
|
|
|
return(NULL);
|
|
|
|
fi = PITEM_FINFO(pi);
|
2005-04-19 11:59:40 +00:00
|
|
|
if ( (!fi) || (fi->tree_type == -1) )
|
2004-03-25 09:18:03 +00:00
|
|
|
return(NULL);
|
|
|
|
return (proto_tree*) pi;
|
|
|
|
}
|
|
|
|
|
2004-03-25 23:55:21 +00:00
|
|
|
proto_item*
|
|
|
|
proto_item_get_parent(proto_item *ti) {
|
2005-04-11 08:43:51 +00:00
|
|
|
/* dont bother if tree is not visible */
|
|
|
|
if( (!ti) || (!(PTREE_DATA(ti)->visible)) )
|
2004-03-25 23:55:21 +00:00
|
|
|
return (NULL);
|
|
|
|
return ti->parent;
|
|
|
|
}
|
|
|
|
|
|
|
|
proto_item*
|
|
|
|
proto_item_get_parent_nth(proto_item *ti, int gen) {
|
2005-04-11 08:43:51 +00:00
|
|
|
/* dont bother if tree is not visible */
|
|
|
|
if( (!ti) || (!(PTREE_DATA(ti)->visible)) )
|
2004-03-25 23:55:21 +00:00
|
|
|
return (NULL);
|
|
|
|
while (gen--) {
|
|
|
|
ti = ti->parent;
|
|
|
|
if (!ti)
|
|
|
|
return (NULL);
|
|
|
|
}
|
|
|
|
return ti;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-03-25 09:18:03 +00:00
|
|
|
proto_item*
|
|
|
|
proto_tree_get_parent(proto_tree *tree) {
|
2005-04-11 08:43:51 +00:00
|
|
|
/* dont bother if tree is not visible */
|
|
|
|
if( (!tree) || (!(PTREE_DATA(tree)->visible)) )
|
2004-03-25 09:18:03 +00:00
|
|
|
return (NULL);
|
|
|
|
return (proto_item*) tree;
|
|
|
|
}
|
|
|
|
|
1999-07-07 22:52:57 +00:00
|
|
|
|
2005-06-02 18:35:20 +00:00
|
|
|
void
|
|
|
|
proto_tree_move_item(proto_tree *tree, proto_item *fixed_item, proto_item *item_to_move)
|
|
|
|
{
|
|
|
|
proto_item *curr_item;
|
|
|
|
|
|
|
|
|
|
|
|
/*** cut item_to_move out ***/
|
|
|
|
|
|
|
|
/* is item_to_move the first? */
|
|
|
|
if(tree->first_child == item_to_move) {
|
|
|
|
/* simply change first child to next */
|
|
|
|
tree->first_child = item_to_move->next;
|
|
|
|
} else {
|
|
|
|
/* find previous and change it's next */
|
|
|
|
for(curr_item = tree->first_child; curr_item != NULL; curr_item = curr_item->next) {
|
|
|
|
if(curr_item->next == item_to_move) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
DISSECTOR_ASSERT(curr_item);
|
|
|
|
|
|
|
|
curr_item->next = item_to_move->next;
|
|
|
|
|
|
|
|
/* fix last_child if required */
|
|
|
|
if(tree->last_child == item_to_move) {
|
|
|
|
tree->last_child = curr_item;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*** insert to_move after fixed ***/
|
|
|
|
item_to_move->next = fixed_item->next;
|
|
|
|
fixed_item->next = item_to_move;
|
|
|
|
if(tree->last_child == fixed_item) {
|
|
|
|
tree->last_child = item_to_move;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
1999-07-07 22:52:57 +00:00
|
|
|
int
|
2005-07-20 11:01:35 +00:00
|
|
|
proto_register_protocol(const char *name, const char *short_name, const char *filter_name)
|
1999-07-07 22:52:57 +00:00
|
|
|
{
|
2005-03-29 14:56:09 +00:00
|
|
|
protocol_t *protocol;
|
|
|
|
header_field_info *hfinfo;
|
|
|
|
int proto_id;
|
2005-01-12 21:31:22 +00:00
|
|
|
char *existing_name;
|
2005-03-29 16:02:02 +00:00
|
|
|
gint *key;
|
|
|
|
guint i;
|
2005-11-10 07:42:23 +00:00
|
|
|
guchar c;
|
2005-03-29 14:56:09 +00:00
|
|
|
gboolean found_invalid;
|
2001-01-03 06:56:03 +00:00
|
|
|
|
2005-03-29 14:56:09 +00:00
|
|
|
/*
|
|
|
|
* Make sure there's not already a protocol with any of those
|
|
|
|
* names. Crash if there is, as that's an error in the code
|
2005-01-12 21:31:22 +00:00
|
|
|
* or an inappropriate plugin.
|
|
|
|
* This situation has to be fixed to not register more than one
|
2005-03-29 14:56:09 +00:00
|
|
|
* protocol with the same name.
|
|
|
|
*
|
2005-01-12 21:31:22 +00:00
|
|
|
* This is done by reducing the number of strcmp (and alike) calls as much as possible,
|
|
|
|
* as this significally slows down startup time.
|
|
|
|
*
|
|
|
|
* Drawback: As a hash value is used to reduce insert time,
|
|
|
|
* this might lead to a hash collision.
|
|
|
|
* However, as we have around 500+ protocols and we're using a 32 bit int this is very,
|
|
|
|
* very unlikely.
|
|
|
|
*/
|
|
|
|
|
|
|
|
key = g_malloc (sizeof(gint));
|
|
|
|
*key = g_str_hash(name);
|
|
|
|
existing_name = g_hash_table_lookup(proto_names, key);
|
|
|
|
if (existing_name != NULL) {
|
|
|
|
/* g_error will terminate the program */
|
2005-03-29 14:56:09 +00:00
|
|
|
g_error("Duplicate protocol name \"%s\"!"
|
2005-01-12 21:31:22 +00:00
|
|
|
" This might be caused by an inappropriate plugin or a development error.", name);
|
|
|
|
}
|
2005-07-24 19:01:28 +00:00
|
|
|
g_hash_table_insert(proto_names, key, (gpointer)name);
|
2005-01-12 21:31:22 +00:00
|
|
|
|
|
|
|
key = g_malloc (sizeof(gint));
|
|
|
|
*key = g_str_hash(short_name);
|
|
|
|
existing_name = g_hash_table_lookup(proto_short_names, key);
|
|
|
|
if (existing_name != NULL) {
|
2005-03-29 14:56:09 +00:00
|
|
|
g_error("Duplicate protocol short_name \"%s\"!"
|
2005-01-12 21:31:22 +00:00
|
|
|
" This might be caused by an inappropriate plugin or a development error.", short_name);
|
|
|
|
}
|
2005-07-24 19:01:28 +00:00
|
|
|
g_hash_table_insert(proto_short_names, key, (gpointer)short_name);
|
2005-01-12 21:31:22 +00:00
|
|
|
|
2005-03-29 14:56:09 +00:00
|
|
|
found_invalid = FALSE;
|
|
|
|
for (i = 0; i < strlen(filter_name); i++) {
|
2005-11-10 07:42:23 +00:00
|
|
|
c = filter_name[i];
|
|
|
|
if (!(islower(c) || isdigit(c) || c == '-' || c == '_' || c == '.')) {
|
2005-03-29 14:56:09 +00:00
|
|
|
found_invalid = TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (found_invalid) {
|
|
|
|
g_warning("Protocol filter name \"%s\" has one or more invalid characters.", filter_name);
|
|
|
|
}
|
2005-01-12 21:31:22 +00:00
|
|
|
key = g_malloc (sizeof(gint));
|
|
|
|
*key = g_str_hash(filter_name);
|
|
|
|
existing_name = g_hash_table_lookup(proto_filter_names, key);
|
|
|
|
if (existing_name != NULL) {
|
2005-03-29 14:56:09 +00:00
|
|
|
g_error("Duplicate protocol filter_name \"%s\"!"
|
2005-01-12 21:31:22 +00:00
|
|
|
" This might be caused by an inappropriate plugin or a development error.", filter_name);
|
|
|
|
}
|
2005-07-24 19:01:28 +00:00
|
|
|
g_hash_table_insert(proto_filter_names, key, (gpointer)filter_name);
|
2002-10-15 05:21:07 +00:00
|
|
|
|
2005-03-29 14:56:09 +00:00
|
|
|
/* Add this protocol to the list of known protocols; the list
|
|
|
|
is sorted by protocol short name. */
|
|
|
|
protocol = g_malloc(sizeof (protocol_t));
|
|
|
|
protocol->name = name;
|
|
|
|
protocol->short_name = short_name;
|
|
|
|
protocol->filter_name = filter_name;
|
|
|
|
protocol->fields = NULL;
|
|
|
|
protocol->is_enabled = TRUE; /* protocol is enabled by default */
|
|
|
|
protocol->can_toggle = TRUE;
|
2005-01-12 21:31:22 +00:00
|
|
|
/* list will be sorted later by name, when all protocols completed registering */
|
|
|
|
protocols = g_list_append(protocols, protocol);
|
1999-10-12 06:21:15 +00:00
|
|
|
|
2005-03-29 14:56:09 +00:00
|
|
|
/* Here we do allocate a new header_field_info struct */
|
|
|
|
hfinfo = g_mem_chunk_alloc(gmc_hfinfo);
|
|
|
|
hfinfo->name = name;
|
|
|
|
hfinfo->abbrev = filter_name;
|
|
|
|
hfinfo->type = FT_PROTOCOL;
|
2005-04-07 12:00:03 +00:00
|
|
|
hfinfo->strings = protocol;
|
2005-03-29 14:56:09 +00:00
|
|
|
hfinfo->bitmask = 0;
|
|
|
|
hfinfo->bitshift = 0;
|
2005-04-11 08:43:51 +00:00
|
|
|
hfinfo->ref_count = 0;
|
2005-12-04 04:22:43 +00:00
|
|
|
hfinfo->blurb = NULL;
|
2005-03-29 14:56:09 +00:00
|
|
|
hfinfo->parent = -1; /* this field differentiates protos and fields */
|
|
|
|
|
|
|
|
proto_id = proto_register_field_init(hfinfo, hfinfo->parent);
|
|
|
|
protocol->proto_id = proto_id;
|
|
|
|
return proto_id;
|
1999-07-07 22:52:57 +00:00
|
|
|
}
|
|
|
|
|
2001-01-03 06:56:03 +00:00
|
|
|
/*
|
|
|
|
* Routines to use to iterate over the protocols.
|
|
|
|
* The argument passed to the iterator routines is an opaque cookie to
|
|
|
|
* their callers; it's the GList pointer for the current element in
|
|
|
|
* the list.
|
|
|
|
* The ID of the protocol is returned, or -1 if there is no protocol.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
proto_get_first_protocol(void **cookie)
|
|
|
|
{
|
|
|
|
protocol_t *protocol;
|
|
|
|
|
|
|
|
if (protocols == NULL)
|
|
|
|
return -1;
|
|
|
|
*cookie = protocols;
|
|
|
|
protocol = protocols->data;
|
|
|
|
return protocol->proto_id;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
proto_get_next_protocol(void **cookie)
|
|
|
|
{
|
|
|
|
GList *list_item = *cookie;
|
|
|
|
protocol_t *protocol;
|
|
|
|
|
|
|
|
list_item = g_list_next(list_item);
|
|
|
|
if (list_item == NULL)
|
|
|
|
return -1;
|
|
|
|
*cookie = list_item;
|
|
|
|
protocol = list_item->data;
|
|
|
|
return protocol->proto_id;
|
|
|
|
}
|
Add the "Edit:Protocols..." feature which currently only implements
the following:
It is now possible to enable/disable a particular protocol decoding
(i.e. the protocol dissector is void or not). When a protocol
is disabled, it is displayed as Data and of course, all linked
sub-protocols are disabled as well.
Disabling a protocol could be interesting:
- in case of buggy dissectors
- in case of wrong heuristics
- for performance reasons
- to decode the data as another protocol (TODO)
Currently (if I am not wrong), all dissectors but NFS can be disabled
(and dissectors that do not register protocols :-)
I do not like the way the RPC sub-dissectors are disabled (in the
sub-dissectors) since this could be done in the RPC dissector itself,
knowing the sub-protocol hfinfo entry (this is why, I've not modified
the NFS one yet).
Two functions are added in proto.c :
gboolean proto_is_protocol_enabled(int n);
void proto_set_decoding(int n, gboolean enabled);
and two MACROs which can be used in dissectors:
OLD_CHECK_DISPLAY_AS_DATA(index, pd, offset, fd, tree)
CHECK_DISPLAY_AS_DATA(index, tvb, pinfo, tree)
See also the XXX in proto_dlg.c and proto.c around the new functions.
svn path=/trunk/; revision=2267
2000-08-13 14:09:15 +00:00
|
|
|
|
2003-08-25 00:15:02 +00:00
|
|
|
header_field_info *
|
|
|
|
proto_get_first_protocol_field(int proto_id, void **cookie)
|
|
|
|
{
|
|
|
|
protocol_t *protocol = find_protocol_by_id(proto_id);
|
|
|
|
hf_register_info *ptr;
|
|
|
|
|
|
|
|
if ((protocol == NULL) || (protocol->fields == NULL))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
*cookie = protocol->fields;
|
|
|
|
ptr = protocol->fields->data;
|
|
|
|
return &ptr->hfinfo;
|
|
|
|
}
|
|
|
|
|
|
|
|
header_field_info *
|
|
|
|
proto_get_next_protocol_field(void **cookie)
|
|
|
|
{
|
|
|
|
GList *list_item = *cookie;
|
|
|
|
hf_register_info *ptr;
|
|
|
|
|
|
|
|
list_item = g_list_next(list_item);
|
|
|
|
if (list_item == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
*cookie = list_item;
|
|
|
|
ptr = list_item->data;
|
|
|
|
return &ptr->hfinfo;
|
|
|
|
}
|
|
|
|
|
2003-11-16 23:17:27 +00:00
|
|
|
protocol_t *
|
2001-01-03 06:56:03 +00:00
|
|
|
find_protocol_by_id(int proto_id)
|
Add the "Edit:Protocols..." feature which currently only implements
the following:
It is now possible to enable/disable a particular protocol decoding
(i.e. the protocol dissector is void or not). When a protocol
is disabled, it is displayed as Data and of course, all linked
sub-protocols are disabled as well.
Disabling a protocol could be interesting:
- in case of buggy dissectors
- in case of wrong heuristics
- for performance reasons
- to decode the data as another protocol (TODO)
Currently (if I am not wrong), all dissectors but NFS can be disabled
(and dissectors that do not register protocols :-)
I do not like the way the RPC sub-dissectors are disabled (in the
sub-dissectors) since this could be done in the RPC dissector itself,
knowing the sub-protocol hfinfo entry (this is why, I've not modified
the NFS one yet).
Two functions are added in proto.c :
gboolean proto_is_protocol_enabled(int n);
void proto_set_decoding(int n, gboolean enabled);
and two MACROs which can be used in dissectors:
OLD_CHECK_DISPLAY_AS_DATA(index, pd, offset, fd, tree)
CHECK_DISPLAY_AS_DATA(index, tvb, pinfo, tree)
See also the XXX in proto_dlg.c and proto.c around the new functions.
svn path=/trunk/; revision=2267
2000-08-13 14:09:15 +00:00
|
|
|
{
|
2005-04-07 12:00:03 +00:00
|
|
|
header_field_info *hfinfo;
|
2002-08-28 20:41:00 +00:00
|
|
|
|
2005-04-07 12:00:03 +00:00
|
|
|
if(proto_id<0)
|
2001-01-03 06:56:03 +00:00
|
|
|
return NULL;
|
2005-04-07 12:00:03 +00:00
|
|
|
|
|
|
|
PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
|
|
|
|
DISSECTOR_ASSERT(hfinfo->type==FT_PROTOCOL);
|
|
|
|
return (protocol_t *)hfinfo->strings;
|
2001-01-03 06:56:03 +00:00
|
|
|
}
|
Add the "Edit:Protocols..." feature which currently only implements
the following:
It is now possible to enable/disable a particular protocol decoding
(i.e. the protocol dissector is void or not). When a protocol
is disabled, it is displayed as Data and of course, all linked
sub-protocols are disabled as well.
Disabling a protocol could be interesting:
- in case of buggy dissectors
- in case of wrong heuristics
- for performance reasons
- to decode the data as another protocol (TODO)
Currently (if I am not wrong), all dissectors but NFS can be disabled
(and dissectors that do not register protocols :-)
I do not like the way the RPC sub-dissectors are disabled (in the
sub-dissectors) since this could be done in the RPC dissector itself,
knowing the sub-protocol hfinfo entry (this is why, I've not modified
the NFS one yet).
Two functions are added in proto.c :
gboolean proto_is_protocol_enabled(int n);
void proto_set_decoding(int n, gboolean enabled);
and two MACROs which can be used in dissectors:
OLD_CHECK_DISPLAY_AS_DATA(index, pd, offset, fd, tree)
CHECK_DISPLAY_AS_DATA(index, tvb, pinfo, tree)
See also the XXX in proto_dlg.c and proto.c around the new functions.
svn path=/trunk/; revision=2267
2000-08-13 14:09:15 +00:00
|
|
|
|
2002-08-28 20:41:00 +00:00
|
|
|
static gint compare_filter_name(gconstpointer proto_arg,
|
2001-04-01 22:50:08 +00:00
|
|
|
gconstpointer filter_name)
|
|
|
|
{
|
2002-04-20 08:07:56 +00:00
|
|
|
const protocol_t *protocol = proto_arg;
|
|
|
|
const gchar* f_name = filter_name;
|
|
|
|
|
|
|
|
return (strcmp(protocol->filter_name, f_name));
|
2001-04-01 22:50:08 +00:00
|
|
|
}
|
|
|
|
|
2003-11-16 23:17:27 +00:00
|
|
|
int
|
|
|
|
proto_get_id(protocol_t *protocol)
|
|
|
|
{
|
|
|
|
return protocol->proto_id;
|
|
|
|
}
|
|
|
|
|
2005-07-23 11:41:25 +00:00
|
|
|
int proto_get_id_by_filter_name(const gchar* filter_name)
|
2001-04-01 22:50:08 +00:00
|
|
|
{
|
2002-04-20 08:07:56 +00:00
|
|
|
GList *list_entry;
|
|
|
|
protocol_t *protocol;
|
|
|
|
|
|
|
|
list_entry = g_list_find_custom(protocols, filter_name,
|
2002-08-28 20:41:00 +00:00
|
|
|
compare_filter_name);
|
2002-04-20 08:07:56 +00:00
|
|
|
if (list_entry == NULL)
|
|
|
|
return -1;
|
|
|
|
protocol = list_entry->data;
|
|
|
|
return protocol->proto_id;
|
2001-04-01 22:50:08 +00:00
|
|
|
}
|
|
|
|
|
2005-07-24 19:01:28 +00:00
|
|
|
const char *
|
2001-01-03 06:56:03 +00:00
|
|
|
proto_get_protocol_name(int proto_id)
|
|
|
|
{
|
|
|
|
protocol_t *protocol;
|
Add the "Edit:Protocols..." feature which currently only implements
the following:
It is now possible to enable/disable a particular protocol decoding
(i.e. the protocol dissector is void or not). When a protocol
is disabled, it is displayed as Data and of course, all linked
sub-protocols are disabled as well.
Disabling a protocol could be interesting:
- in case of buggy dissectors
- in case of wrong heuristics
- for performance reasons
- to decode the data as another protocol (TODO)
Currently (if I am not wrong), all dissectors but NFS can be disabled
(and dissectors that do not register protocols :-)
I do not like the way the RPC sub-dissectors are disabled (in the
sub-dissectors) since this could be done in the RPC dissector itself,
knowing the sub-protocol hfinfo entry (this is why, I've not modified
the NFS one yet).
Two functions are added in proto.c :
gboolean proto_is_protocol_enabled(int n);
void proto_set_decoding(int n, gboolean enabled);
and two MACROs which can be used in dissectors:
OLD_CHECK_DISPLAY_AS_DATA(index, pd, offset, fd, tree)
CHECK_DISPLAY_AS_DATA(index, tvb, pinfo, tree)
See also the XXX in proto_dlg.c and proto.c around the new functions.
svn path=/trunk/; revision=2267
2000-08-13 14:09:15 +00:00
|
|
|
|
2001-01-03 06:56:03 +00:00
|
|
|
protocol = find_protocol_by_id(proto_id);
|
|
|
|
return protocol->name;
|
|
|
|
}
|
|
|
|
|
2005-07-24 19:01:28 +00:00
|
|
|
const char *
|
2003-11-16 23:17:27 +00:00
|
|
|
proto_get_protocol_short_name(protocol_t *protocol)
|
2001-01-03 06:56:03 +00:00
|
|
|
{
|
2003-11-16 23:17:27 +00:00
|
|
|
if (protocol == NULL)
|
2001-02-01 07:34:33 +00:00
|
|
|
return "(none)";
|
2001-01-03 06:56:03 +00:00
|
|
|
return protocol->short_name;
|
|
|
|
}
|
|
|
|
|
2005-07-24 19:01:28 +00:00
|
|
|
const char *
|
2001-01-03 06:56:03 +00:00
|
|
|
proto_get_protocol_filter_name(int proto_id)
|
|
|
|
{
|
|
|
|
protocol_t *protocol;
|
|
|
|
|
|
|
|
protocol = find_protocol_by_id(proto_id);
|
|
|
|
return protocol->filter_name;
|
|
|
|
}
|
|
|
|
|
|
|
|
gboolean
|
2003-11-16 23:17:27 +00:00
|
|
|
proto_is_protocol_enabled(protocol_t *protocol)
|
2001-01-03 06:56:03 +00:00
|
|
|
{
|
|
|
|
return protocol->is_enabled;
|
|
|
|
}
|
|
|
|
|
|
|
|
gboolean
|
2004-01-03 18:40:08 +00:00
|
|
|
proto_can_toggle_protocol(int proto_id)
|
2001-01-03 06:56:03 +00:00
|
|
|
{
|
|
|
|
protocol_t *protocol;
|
|
|
|
|
|
|
|
protocol = find_protocol_by_id(proto_id);
|
2004-01-03 18:40:08 +00:00
|
|
|
return protocol->can_toggle;
|
Add the "Edit:Protocols..." feature which currently only implements
the following:
It is now possible to enable/disable a particular protocol decoding
(i.e. the protocol dissector is void or not). When a protocol
is disabled, it is displayed as Data and of course, all linked
sub-protocols are disabled as well.
Disabling a protocol could be interesting:
- in case of buggy dissectors
- in case of wrong heuristics
- for performance reasons
- to decode the data as another protocol (TODO)
Currently (if I am not wrong), all dissectors but NFS can be disabled
(and dissectors that do not register protocols :-)
I do not like the way the RPC sub-dissectors are disabled (in the
sub-dissectors) since this could be done in the RPC dissector itself,
knowing the sub-protocol hfinfo entry (this is why, I've not modified
the NFS one yet).
Two functions are added in proto.c :
gboolean proto_is_protocol_enabled(int n);
void proto_set_decoding(int n, gboolean enabled);
and two MACROs which can be used in dissectors:
OLD_CHECK_DISPLAY_AS_DATA(index, pd, offset, fd, tree)
CHECK_DISPLAY_AS_DATA(index, tvb, pinfo, tree)
See also the XXX in proto_dlg.c and proto.c around the new functions.
svn path=/trunk/; revision=2267
2000-08-13 14:09:15 +00:00
|
|
|
}
|
|
|
|
|
2002-08-28 20:41:00 +00:00
|
|
|
void
|
2001-01-03 06:56:03 +00:00
|
|
|
proto_set_decoding(int proto_id, gboolean enabled)
|
Add the "Edit:Protocols..." feature which currently only implements
the following:
It is now possible to enable/disable a particular protocol decoding
(i.e. the protocol dissector is void or not). When a protocol
is disabled, it is displayed as Data and of course, all linked
sub-protocols are disabled as well.
Disabling a protocol could be interesting:
- in case of buggy dissectors
- in case of wrong heuristics
- for performance reasons
- to decode the data as another protocol (TODO)
Currently (if I am not wrong), all dissectors but NFS can be disabled
(and dissectors that do not register protocols :-)
I do not like the way the RPC sub-dissectors are disabled (in the
sub-dissectors) since this could be done in the RPC dissector itself,
knowing the sub-protocol hfinfo entry (this is why, I've not modified
the NFS one yet).
Two functions are added in proto.c :
gboolean proto_is_protocol_enabled(int n);
void proto_set_decoding(int n, gboolean enabled);
and two MACROs which can be used in dissectors:
OLD_CHECK_DISPLAY_AS_DATA(index, pd, offset, fd, tree)
CHECK_DISPLAY_AS_DATA(index, tvb, pinfo, tree)
See also the XXX in proto_dlg.c and proto.c around the new functions.
svn path=/trunk/; revision=2267
2000-08-13 14:09:15 +00:00
|
|
|
{
|
2001-01-03 06:56:03 +00:00
|
|
|
protocol_t *protocol;
|
Add the "Edit:Protocols..." feature which currently only implements
the following:
It is now possible to enable/disable a particular protocol decoding
(i.e. the protocol dissector is void or not). When a protocol
is disabled, it is displayed as Data and of course, all linked
sub-protocols are disabled as well.
Disabling a protocol could be interesting:
- in case of buggy dissectors
- in case of wrong heuristics
- for performance reasons
- to decode the data as another protocol (TODO)
Currently (if I am not wrong), all dissectors but NFS can be disabled
(and dissectors that do not register protocols :-)
I do not like the way the RPC sub-dissectors are disabled (in the
sub-dissectors) since this could be done in the RPC dissector itself,
knowing the sub-protocol hfinfo entry (this is why, I've not modified
the NFS one yet).
Two functions are added in proto.c :
gboolean proto_is_protocol_enabled(int n);
void proto_set_decoding(int n, gboolean enabled);
and two MACROs which can be used in dissectors:
OLD_CHECK_DISPLAY_AS_DATA(index, pd, offset, fd, tree)
CHECK_DISPLAY_AS_DATA(index, tvb, pinfo, tree)
See also the XXX in proto_dlg.c and proto.c around the new functions.
svn path=/trunk/; revision=2267
2000-08-13 14:09:15 +00:00
|
|
|
|
2001-01-03 06:56:03 +00:00
|
|
|
protocol = find_protocol_by_id(proto_id);
|
2005-03-23 00:09:12 +00:00
|
|
|
DISSECTOR_ASSERT(protocol->can_toggle);
|
2001-01-03 06:56:03 +00:00
|
|
|
protocol->is_enabled = enabled;
|
|
|
|
}
|
|
|
|
|
2002-08-28 20:41:00 +00:00
|
|
|
void
|
2004-01-03 18:40:08 +00:00
|
|
|
proto_set_cant_toggle(int proto_id)
|
2001-01-03 06:56:03 +00:00
|
|
|
{
|
|
|
|
protocol_t *protocol;
|
|
|
|
|
|
|
|
protocol = find_protocol_by_id(proto_id);
|
2004-01-03 18:40:08 +00:00
|
|
|
protocol->can_toggle = FALSE;
|
Add the "Edit:Protocols..." feature which currently only implements
the following:
It is now possible to enable/disable a particular protocol decoding
(i.e. the protocol dissector is void or not). When a protocol
is disabled, it is displayed as Data and of course, all linked
sub-protocols are disabled as well.
Disabling a protocol could be interesting:
- in case of buggy dissectors
- in case of wrong heuristics
- for performance reasons
- to decode the data as another protocol (TODO)
Currently (if I am not wrong), all dissectors but NFS can be disabled
(and dissectors that do not register protocols :-)
I do not like the way the RPC sub-dissectors are disabled (in the
sub-dissectors) since this could be done in the RPC dissector itself,
knowing the sub-protocol hfinfo entry (this is why, I've not modified
the NFS one yet).
Two functions are added in proto.c :
gboolean proto_is_protocol_enabled(int n);
void proto_set_decoding(int n, gboolean enabled);
and two MACROs which can be used in dissectors:
OLD_CHECK_DISPLAY_AS_DATA(index, pd, offset, fd, tree)
CHECK_DISPLAY_AS_DATA(index, tvb, pinfo, tree)
See also the XXX in proto_dlg.c and proto.c around the new functions.
svn path=/trunk/; revision=2267
2000-08-13 14:09:15 +00:00
|
|
|
}
|
|
|
|
|
1999-07-15 15:33:52 +00:00
|
|
|
/* for use with static arrays only, since we don't allocate our own copies
|
2003-01-21 19:20:49 +00:00
|
|
|
of the header_field_info struct contained within 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;
|
2001-01-03 06:56:03 +00:00
|
|
|
protocol_t *proto;
|
1999-07-07 22:52:57 +00:00
|
|
|
|
2001-01-03 06:56:03 +00:00
|
|
|
proto = find_protocol_by_id(parent);
|
1999-07-07 22:52:57 +00:00
|
|
|
for (i = 0; i < num_records; i++, ptr++) {
|
2003-10-06 20:46:52 +00:00
|
|
|
/*
|
2004-09-21 23:15:59 +00:00
|
|
|
* Make sure we haven't registered this yet.
|
2003-10-06 20:46:52 +00:00
|
|
|
* Most fields have variables associated with them
|
|
|
|
* that are initialized to -1; some have array elements,
|
|
|
|
* or possibly uninitialized variables, so we also allow
|
|
|
|
* 0 (which is unlikely to be the field ID we get back
|
|
|
|
* from "proto_register_field_init()").
|
|
|
|
*/
|
2005-10-10 18:06:50 +00:00
|
|
|
if (*ptr->p_id != -1 && *ptr->p_id != 0) {
|
|
|
|
fprintf(stderr,
|
|
|
|
"Duplicate field detected in call to proto_register_field_array: %s is already registered\n",
|
|
|
|
hf->hfinfo.abbrev);
|
|
|
|
return;
|
|
|
|
}
|
2003-10-06 20:46:52 +00:00
|
|
|
|
2001-01-03 06:56:03 +00:00
|
|
|
if (proto != NULL) {
|
|
|
|
if (proto->fields == NULL) {
|
|
|
|
proto->fields = g_list_append(NULL, ptr);
|
|
|
|
proto->last_field = proto->fields;
|
|
|
|
} else {
|
|
|
|
proto->last_field =
|
|
|
|
g_list_append(proto->last_field, ptr)->next;
|
|
|
|
}
|
|
|
|
}
|
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)
|
|
|
|
{
|
2003-08-25 00:15:02 +00:00
|
|
|
/* The field must have names */
|
2005-03-23 00:09:12 +00:00
|
|
|
DISSECTOR_ASSERT(hfinfo->name);
|
|
|
|
DISSECTOR_ASSERT(hfinfo->abbrev);
|
2003-08-25 00:15:02 +00:00
|
|
|
|
2005-04-07 12:00:03 +00:00
|
|
|
/* These types of fields are allowed to have value_strings, true_false_strings or a protocol_t struct*/
|
2005-03-23 00:09:12 +00:00
|
|
|
DISSECTOR_ASSERT((hfinfo->strings == NULL) || (
|
1999-10-12 06:21:15 +00:00
|
|
|
(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) ||
|
2002-12-19 02:58:53 +00:00
|
|
|
(hfinfo->type == FT_BOOLEAN) ||
|
2005-04-07 12:00:03 +00:00
|
|
|
(hfinfo->type == FT_PROTOCOL) ||
|
2002-12-19 02:58:53 +00:00
|
|
|
(hfinfo->type == FT_FRAMENUM) ));
|
1999-10-12 06:21:15 +00:00
|
|
|
|
2001-04-23 01:19:39 +00:00
|
|
|
switch (hfinfo->type) {
|
|
|
|
|
|
|
|
case FT_UINT8:
|
|
|
|
case FT_UINT16:
|
|
|
|
case FT_UINT24:
|
|
|
|
case FT_UINT32:
|
|
|
|
case FT_INT8:
|
|
|
|
case FT_INT16:
|
|
|
|
case FT_INT24:
|
|
|
|
case FT_INT32:
|
2002-12-19 02:58:53 +00:00
|
|
|
/* Require integral types (other than frame number, which is
|
|
|
|
always displayed in decimal) to have a number base */
|
2005-03-23 00:09:12 +00:00
|
|
|
DISSECTOR_ASSERT(hfinfo->display != BASE_NONE);
|
2001-04-23 01:19:39 +00:00
|
|
|
break;
|
|
|
|
|
2002-12-19 02:58:53 +00:00
|
|
|
case FT_FRAMENUM:
|
|
|
|
/* Don't allow bitfields or value strings for frame numbers */
|
2005-03-23 00:09:12 +00:00
|
|
|
DISSECTOR_ASSERT(hfinfo->bitmask == 0);
|
|
|
|
DISSECTOR_ASSERT(hfinfo->strings == NULL);
|
2002-12-19 02:58:53 +00:00
|
|
|
break;
|
|
|
|
|
2001-04-23 01:19:39 +00:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2002-06-19 19:21:15 +00:00
|
|
|
/* if this is a bitfield, compute bitshift */
|
1999-10-12 06:21:15 +00:00
|
|
|
if (hfinfo->bitmask) {
|
|
|
|
while ((hfinfo->bitmask & (1 << hfinfo->bitshift)) == 0)
|
|
|
|
hfinfo->bitshift++;
|
|
|
|
}
|
1999-07-15 15:33:52 +00:00
|
|
|
|
|
|
|
hfinfo->parent = parent;
|
2001-02-13 18:34:51 +00:00
|
|
|
hfinfo->same_name_next = NULL;
|
|
|
|
hfinfo->same_name_prev = NULL;
|
1999-07-07 22:52:57 +00:00
|
|
|
|
|
|
|
/* if we always add and never delete, then id == len - 1 is correct */
|
2003-11-21 14:58:49 +00:00
|
|
|
if(gpa_hfinfo.len>=gpa_hfinfo.allocated_len){
|
|
|
|
if(!gpa_hfinfo.hfi){
|
|
|
|
gpa_hfinfo.allocated_len=1000;
|
|
|
|
gpa_hfinfo.hfi=g_malloc(sizeof(header_field_info *)*1000);
|
|
|
|
} else {
|
|
|
|
gpa_hfinfo.allocated_len+=1000;
|
|
|
|
gpa_hfinfo.hfi=g_realloc(gpa_hfinfo.hfi, sizeof(header_field_info *)*gpa_hfinfo.allocated_len);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
gpa_hfinfo.hfi[gpa_hfinfo.len]=hfinfo;
|
|
|
|
gpa_hfinfo.len++;
|
|
|
|
hfinfo->id = gpa_hfinfo.len - 1;
|
2003-08-25 00:15:02 +00:00
|
|
|
|
|
|
|
/* if we have real names, enter this field in the name tree */
|
|
|
|
if ((hfinfo->name[0] != 0) && (hfinfo->abbrev[0] != 0 )) {
|
|
|
|
|
|
|
|
header_field_info *same_name_hfinfo, *same_name_next_hfinfo;
|
2005-06-24 02:51:01 +00:00
|
|
|
const char *p;
|
2003-11-13 23:38:33 +00:00
|
|
|
guchar c;
|
|
|
|
|
|
|
|
/* Check that the filter name (abbreviation) is legal;
|
|
|
|
* it must contain only alphanumerics, '-', "_", and ".". */
|
|
|
|
for (p = hfinfo->abbrev; (c = *p) != '\0'; p++)
|
2005-03-23 00:09:12 +00:00
|
|
|
DISSECTOR_ASSERT(isalnum(c) || c == '-' || c == '_' ||
|
2003-11-13 23:38:33 +00:00
|
|
|
c == '.');
|
2003-08-25 00:15:02 +00:00
|
|
|
|
|
|
|
/* We allow multiple hfinfo's to be registered under the same
|
|
|
|
* abbreviation. This was done for X.25, as, depending
|
|
|
|
* on whether it's modulo-8 or modulo-128 operation,
|
|
|
|
* some bitfield fields may be in different bits of
|
|
|
|
* a byte, and we want to be able to refer to that field
|
|
|
|
* with one name regardless of whether the packets
|
|
|
|
* are modulo-8 or modulo-128 packets. */
|
|
|
|
same_name_hfinfo = g_tree_lookup(gpa_name_tree, hfinfo->abbrev);
|
|
|
|
if (same_name_hfinfo) {
|
|
|
|
/* There's already a field with this name.
|
|
|
|
* Put it after that field in the list of
|
|
|
|
* fields with this name, then allow the code
|
|
|
|
* after this if{} block to replace the old
|
|
|
|
* hfinfo with the new hfinfo in the GTree. Thus,
|
|
|
|
* we end up with a linked-list of same-named hfinfo's,
|
|
|
|
* with the root of the list being the hfinfo in the GTree */
|
|
|
|
same_name_next_hfinfo =
|
|
|
|
same_name_hfinfo->same_name_next;
|
|
|
|
|
|
|
|
hfinfo->same_name_next = same_name_next_hfinfo;
|
|
|
|
if (same_name_next_hfinfo)
|
|
|
|
same_name_next_hfinfo->same_name_prev = hfinfo;
|
|
|
|
|
|
|
|
same_name_hfinfo->same_name_next = hfinfo;
|
|
|
|
hfinfo->same_name_prev = same_name_hfinfo;
|
|
|
|
}
|
2005-06-26 11:29:04 +00:00
|
|
|
g_tree_insert(gpa_name_tree, (gpointer) (hfinfo->abbrev), hfinfo);
|
2003-08-25 00:15:02 +00:00
|
|
|
}
|
|
|
|
|
1999-07-07 22:52:57 +00:00
|
|
|
return hfinfo->id;
|
|
|
|
}
|
|
|
|
|
1999-11-16 11:44:20 +00:00
|
|
|
void
|
2005-01-07 12:56:21 +00:00
|
|
|
proto_register_subtree_array(gint *const *indices, int num_indices)
|
1999-11-16 11:44:20 +00:00
|
|
|
{
|
|
|
|
int i;
|
2005-01-07 12:56:21 +00:00
|
|
|
gint *const *ptr = indices;
|
1999-11-16 11:44:20 +00:00
|
|
|
|
2002-04-18 00:50:45 +00:00
|
|
|
/*
|
2005-01-08 23:43:29 +00:00
|
|
|
* If we've already allocated the array of tree types, expand
|
|
|
|
* it; this lets plugins such as mate add tree types after
|
|
|
|
* the initial startup. (If we haven't already allocated it,
|
|
|
|
* we don't allocate it; on the first pass, we just assign
|
|
|
|
* ett values and keep track of how many we've assigned, and
|
|
|
|
* when we're finished registering all dissectors we allocate
|
|
|
|
* the array, so that we do only one allocation rather than
|
|
|
|
* wasting CPU time and memory by growing the array for each
|
|
|
|
* dissector that registers ett values.)
|
2002-04-18 00:50:45 +00:00
|
|
|
*/
|
2005-01-08 23:43:29 +00:00
|
|
|
if (tree_is_expanded != NULL) {
|
|
|
|
tree_is_expanded =
|
|
|
|
g_realloc(tree_is_expanded,
|
2005-12-22 01:36:42 +00:00
|
|
|
(num_tree_types+num_indices)*sizeof (gboolean));
|
2005-01-08 23:43:29 +00:00
|
|
|
memset(tree_is_expanded + num_tree_types, 0,
|
2005-12-22 01:36:42 +00:00
|
|
|
num_indices*sizeof (gboolean));
|
2005-01-08 23:43:29 +00:00
|
|
|
}
|
2002-04-18 00:50:45 +00:00
|
|
|
|
1999-11-16 11:44:20 +00:00
|
|
|
/*
|
|
|
|
* Assign "num_indices" subtree numbers starting at "num_tree_types",
|
|
|
|
* returning the indices through the pointers in the array whose
|
2002-04-01 02:00:53 +00:00
|
|
|
* first element is pointed to by "indices", and update
|
1999-11-16 11:44:20 +00:00
|
|
|
* "num_tree_types" appropriately.
|
|
|
|
*/
|
2002-04-01 02:00:53 +00:00
|
|
|
for (i = 0; i < num_indices; i++, ptr++, num_tree_types++)
|
1999-11-16 11:44:20 +00:00
|
|
|
**ptr = num_tree_types;
|
|
|
|
}
|
|
|
|
|
1999-07-07 22:52:57 +00:00
|
|
|
void
|
|
|
|
proto_item_fill_label(field_info *fi, gchar *label_str)
|
|
|
|
{
|
2003-12-03 09:28:26 +00:00
|
|
|
header_field_info *hfinfo = fi->hfinfo;
|
2001-02-01 20:21:25 +00:00
|
|
|
|
|
|
|
guint8 *bytes;
|
|
|
|
guint32 integer;
|
|
|
|
ipv4_addr *ipv4;
|
1999-11-15 06:32:38 +00:00
|
|
|
guint32 n_addr; /* network-order IPv4 address */
|
2005-12-06 11:45:55 +00:00
|
|
|
const gchar *name;
|
2002-12-31 21:37:29 +00:00
|
|
|
int ret; /*tmp return value */
|
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:
|
2001-02-01 20:21:25 +00:00
|
|
|
case FT_PROTOCOL:
|
2005-08-17 23:10:28 +00:00
|
|
|
ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
|
1999-10-12 06:21:15 +00:00
|
|
|
"%s", hfinfo->name);
|
2002-12-31 21:37:29 +00:00
|
|
|
if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
|
|
|
|
label_str[ITEM_LABEL_LENGTH - 1] = '\0';
|
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:
|
2002-05-09 23:50:34 +00:00
|
|
|
case FT_UINT_BYTES:
|
2003-12-02 21:15:49 +00:00
|
|
|
bytes = fvalue_get(&fi->value);
|
2001-02-01 20:21:25 +00:00
|
|
|
if (bytes) {
|
2005-08-17 23:10:28 +00:00
|
|
|
ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
|
2002-08-28 20:41:00 +00:00
|
|
|
"%s: %s", hfinfo->name,
|
2003-12-02 21:15:49 +00:00
|
|
|
bytes_to_str(bytes, fvalue_length(&fi->value)));
|
2002-12-31 21:37:29 +00:00
|
|
|
if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
|
|
|
|
label_str[ITEM_LABEL_LENGTH - 1] = '\0';
|
2000-05-19 04:54:36 +00:00
|
|
|
}
|
|
|
|
else {
|
2005-08-17 23:10:28 +00:00
|
|
|
ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
|
2000-05-19 04:54:36 +00:00
|
|
|
"%s: <MISSING>", hfinfo->name);
|
2002-12-31 21:37:29 +00:00
|
|
|
if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
|
|
|
|
label_str[ITEM_LABEL_LENGTH - 1] = '\0';
|
2000-05-19 04:54:36 +00:00
|
|
|
}
|
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:
|
2002-12-19 02:58:53 +00:00
|
|
|
case FT_FRAMENUM:
|
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;
|
|
|
|
|
2001-10-29 21:13:13 +00:00
|
|
|
case FT_UINT64:
|
|
|
|
fill_label_uint64(fi, label_str);
|
|
|
|
break;
|
|
|
|
|
1999-10-13 03:07:30 +00:00
|
|
|
case FT_INT8:
|
|
|
|
case FT_INT16:
|
|
|
|
case FT_INT24:
|
|
|
|
case FT_INT32:
|
2005-03-23 00:09:12 +00:00
|
|
|
DISSECTOR_ASSERT(!hfinfo->bitmask);
|
1999-10-13 03:07:30 +00:00
|
|
|
if (hfinfo->strings) {
|
|
|
|
fill_label_enumerated_int(fi, label_str);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
fill_label_int(fi, label_str);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2001-11-02 10:09:51 +00:00
|
|
|
case FT_INT64:
|
|
|
|
fill_label_int64(fi, label_str);
|
|
|
|
break;
|
|
|
|
|
2002-08-24 19:45:28 +00:00
|
|
|
case FT_FLOAT:
|
2005-08-17 23:10:28 +00:00
|
|
|
ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
|
2003-07-04 03:41:00 +00:00
|
|
|
"%s: %." STRINGIFY(FLT_DIG) "f",
|
2003-12-02 21:15:49 +00:00
|
|
|
hfinfo->name, fvalue_get_floating(&fi->value));
|
2002-12-31 21:37:29 +00:00
|
|
|
if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
|
|
|
|
label_str[ITEM_LABEL_LENGTH - 1] = '\0';
|
2002-08-24 19:45:28 +00:00
|
|
|
break;
|
|
|
|
|
1999-09-12 06:11:51 +00:00
|
|
|
case FT_DOUBLE:
|
2005-08-17 23:10:28 +00:00
|
|
|
ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
|
2003-07-04 03:41:00 +00:00
|
|
|
"%s: %." STRINGIFY(DBL_DIG) "g",
|
2003-12-02 21:15:49 +00:00
|
|
|
hfinfo->name, fvalue_get_floating(&fi->value));
|
2002-12-31 21:37:29 +00:00
|
|
|
if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
|
|
|
|
label_str[ITEM_LABEL_LENGTH - 1] = '\0';
|
1999-09-12 06:11:51 +00:00
|
|
|
break;
|
|
|
|
|
1999-07-07 22:52:57 +00:00
|
|
|
case FT_ABSOLUTE_TIME:
|
2005-08-17 23:10:28 +00:00
|
|
|
ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
|
2000-08-30 02:50:18 +00:00
|
|
|
"%s: %s", hfinfo->name,
|
2003-12-02 21:15:49 +00:00
|
|
|
abs_time_to_str(fvalue_get(&fi->value)));
|
2002-12-31 21:37:29 +00:00
|
|
|
if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
|
|
|
|
label_str[ITEM_LABEL_LENGTH - 1] = '\0';
|
1999-09-12 06:11:51 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case FT_RELATIVE_TIME:
|
2005-08-17 23:10:28 +00:00
|
|
|
ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
|
2000-08-30 02:50:18 +00:00
|
|
|
"%s: %s seconds", hfinfo->name,
|
2003-12-02 21:15:49 +00:00
|
|
|
rel_time_to_secs_str(fvalue_get(&fi->value)));
|
2002-12-31 21:37:29 +00:00
|
|
|
if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
|
|
|
|
label_str[ITEM_LABEL_LENGTH - 1] = '\0';
|
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:
|
2003-12-02 21:15:49 +00:00
|
|
|
integer = fvalue_get_integer(&fi->value);
|
2005-08-17 23:10:28 +00:00
|
|
|
ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
|
2005-06-02 18:29:29 +00:00
|
|
|
"%s: %s (0x%08X)", hfinfo->name,
|
|
|
|
get_ipxnet_name(integer), integer);
|
2002-12-31 21:37:29 +00:00
|
|
|
if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
|
|
|
|
label_str[ITEM_LABEL_LENGTH - 1] = '\0';
|
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:
|
2003-12-02 21:15:49 +00:00
|
|
|
bytes = fvalue_get(&fi->value);
|
2005-08-17 23:10:28 +00:00
|
|
|
ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
|
2000-08-30 02:50:18 +00:00
|
|
|
"%s: %s (%s)", hfinfo->name,
|
2005-06-02 18:29:29 +00:00
|
|
|
get_ether_name(bytes),
|
|
|
|
ether_to_str(bytes));
|
2002-12-31 21:37:29 +00:00
|
|
|
if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
|
|
|
|
label_str[ITEM_LABEL_LENGTH - 1] = '\0';
|
1999-07-07 22:52:57 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case FT_IPv4:
|
2003-12-02 21:15:49 +00:00
|
|
|
ipv4 = fvalue_get(&fi->value);
|
2001-02-01 20:21:25 +00:00
|
|
|
n_addr = ipv4_get_net_order_addr(ipv4);
|
2005-08-17 23:10:28 +00:00
|
|
|
ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
|
2000-08-30 02:50:18 +00:00
|
|
|
"%s: %s (%s)", hfinfo->name,
|
1999-11-15 06:32:38 +00:00
|
|
|
get_hostname(n_addr),
|
|
|
|
ip_to_str((guint8*)&n_addr));
|
2002-12-31 21:37:29 +00:00
|
|
|
if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
|
|
|
|
label_str[ITEM_LABEL_LENGTH - 1] = '\0';
|
1999-07-07 22:52:57 +00:00
|
|
|
break;
|
1999-10-11 17:05:49 +00:00
|
|
|
|
|
|
|
case FT_IPv6:
|
2003-12-02 21:15:49 +00:00
|
|
|
bytes = fvalue_get(&fi->value);
|
2005-08-17 23:10:28 +00:00
|
|
|
ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
|
2000-08-30 02:50:18 +00:00
|
|
|
"%s: %s (%s)", hfinfo->name,
|
2001-02-01 20:21:25 +00:00
|
|
|
get_hostname6((struct e_in6_addr *)bytes),
|
|
|
|
ip6_to_str((struct e_in6_addr*)bytes));
|
2002-12-31 21:37:29 +00:00
|
|
|
if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
|
|
|
|
label_str[ITEM_LABEL_LENGTH - 1] = '\0';
|
1999-10-11 17:05:49 +00:00
|
|
|
break;
|
2002-08-28 20:41:00 +00:00
|
|
|
|
2005-07-04 13:04:53 +00:00
|
|
|
case FT_GUID:
|
|
|
|
bytes = fvalue_get(&fi->value);
|
2005-08-17 23:10:28 +00:00
|
|
|
ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
|
2005-07-04 13:04:53 +00:00
|
|
|
"%s: %s", hfinfo->name,
|
|
|
|
guid_to_str(bytes));
|
|
|
|
if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
|
|
|
|
label_str[ITEM_LABEL_LENGTH - 1] = '\0';
|
|
|
|
break;
|
|
|
|
|
2005-12-02 13:16:58 +00:00
|
|
|
case FT_OID:
|
|
|
|
bytes = fvalue_get(&fi->value);
|
2005-12-06 11:45:55 +00:00
|
|
|
name = (oid_resolv_enabled()) ? get_oid_name(bytes, fvalue_length(&fi->value)) : NULL;
|
|
|
|
if (name) {
|
|
|
|
ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
|
|
|
|
"%s: %s (%s)", hfinfo->name,
|
|
|
|
oid_to_str(bytes, fvalue_length(&fi->value)), name);
|
|
|
|
} else {
|
|
|
|
ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
|
|
|
|
"%s: %s", hfinfo->name,
|
|
|
|
oid_to_str(bytes, fvalue_length(&fi->value)));
|
|
|
|
}
|
2005-12-02 13:16:58 +00:00
|
|
|
if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
|
|
|
|
label_str[ITEM_LABEL_LENGTH - 1] = '\0';
|
|
|
|
break;
|
|
|
|
|
1999-07-07 22:52:57 +00:00
|
|
|
case FT_STRING:
|
2000-08-30 02:50:18 +00:00
|
|
|
case FT_STRINGZ:
|
2000-08-22 06:38:32 +00:00
|
|
|
case FT_UINT_STRING:
|
2003-12-02 21:15:49 +00:00
|
|
|
bytes = fvalue_get(&fi->value);
|
2005-05-29 11:23:42 +00:00
|
|
|
if(strlen(bytes) > ITEM_LABEL_LENGTH) {
|
2005-08-17 23:10:28 +00:00
|
|
|
ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
|
2005-05-29 11:23:42 +00:00
|
|
|
"%s [truncated]: %s", hfinfo->name,
|
|
|
|
format_text(bytes, strlen(bytes)));
|
|
|
|
} else {
|
2005-08-17 23:10:28 +00:00
|
|
|
ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
|
2005-05-29 11:23:42 +00:00
|
|
|
"%s: %s", hfinfo->name,
|
|
|
|
format_text(bytes, strlen(bytes)));
|
|
|
|
}
|
2002-12-31 21:37:29 +00:00
|
|
|
if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
|
|
|
|
label_str[ITEM_LABEL_LENGTH - 1] = '\0';
|
1999-07-07 22:52:57 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2001-05-09 01:22:46 +00:00
|
|
|
g_error("hfinfo->type %d (%s) not handled\n",
|
2000-08-30 02:50:18 +00:00
|
|
|
hfinfo->type,
|
2001-02-01 20:21:25 +00:00
|
|
|
ftype_name(hfinfo->type));
|
2005-03-23 00:09:12 +00:00
|
|
|
DISSECTOR_ASSERT_NOT_REACHED();
|
2001-05-09 01:22:46 +00:00
|
|
|
break;
|
1999-07-07 22:52:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-10-12 06:21:15 +00:00
|
|
|
static void
|
|
|
|
fill_label_boolean(field_info *fi, gchar *label_str)
|
|
|
|
{
|
2001-02-01 20:21:25 +00:00
|
|
|
char *p = label_str;
|
|
|
|
int bitfield_byte_length = 0, bitwidth;
|
|
|
|
guint32 unshifted_value;
|
|
|
|
guint32 value;
|
2002-12-31 21:37:29 +00:00
|
|
|
int ret; /*tmp return value */
|
1999-10-12 06:21:15 +00:00
|
|
|
|
2003-12-03 09:28:26 +00:00
|
|
|
header_field_info *hfinfo = fi->hfinfo;
|
2002-11-28 01:46:14 +00:00
|
|
|
static const true_false_string default_tf = { "True", "False" };
|
|
|
|
const true_false_string *tfstring = &default_tf;
|
1999-10-12 06:21:15 +00:00
|
|
|
|
|
|
|
if (hfinfo->strings) {
|
2002-11-28 01:46:14 +00:00
|
|
|
tfstring = (const struct true_false_string*) hfinfo->strings;
|
1999-10-12 06:21:15 +00:00
|
|
|
}
|
|
|
|
|
2003-12-02 21:15:49 +00:00
|
|
|
value = fvalue_get_integer(&fi->value);
|
1999-10-12 06:21:15 +00:00
|
|
|
if (hfinfo->bitmask) {
|
|
|
|
/* Figure out the bit width */
|
|
|
|
bitwidth = hfinfo_bitwidth(hfinfo);
|
|
|
|
|
|
|
|
/* Un-shift bits */
|
2001-02-01 20:21:25 +00:00
|
|
|
unshifted_value = value;
|
1999-10-12 06:21:15 +00:00
|
|
|
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 */
|
2005-08-17 23:10:28 +00:00
|
|
|
ret = g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
|
1999-10-12 06:21:15 +00:00
|
|
|
"%s: %s", hfinfo->name,
|
2001-02-01 20:21:25 +00:00
|
|
|
value ? tfstring->true_string : tfstring->false_string);
|
2002-12-31 21:37:29 +00:00
|
|
|
if ((ret == -1) || (ret >= (ITEM_LABEL_LENGTH - bitfield_byte_length)))
|
|
|
|
label_str[ITEM_LABEL_LENGTH - 1] = '\0';
|
1999-10-12 06:21:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Fills data for bitfield ints with val_strings */
|
|
|
|
static void
|
|
|
|
fill_label_enumerated_bitfield(field_info *fi, gchar *label_str)
|
|
|
|
{
|
2005-08-05 13:23:47 +00:00
|
|
|
const char *format = NULL;
|
|
|
|
char *p;
|
1999-10-12 06:21:15 +00:00
|
|
|
int bitfield_byte_length, bitwidth;
|
|
|
|
guint32 unshifted_value;
|
2001-02-01 20:21:25 +00:00
|
|
|
guint32 value;
|
2002-12-31 21:37:29 +00:00
|
|
|
int ret; /*tmp return value */
|
1999-10-12 06:21:15 +00:00
|
|
|
|
2003-12-03 09:28:26 +00:00
|
|
|
header_field_info *hfinfo = fi->hfinfo;
|
1999-10-12 06:21:15 +00:00
|
|
|
|
|
|
|
/* Figure out the bit width */
|
|
|
|
bitwidth = hfinfo_bitwidth(hfinfo);
|
|
|
|
|
|
|
|
/* Pick the proper format string */
|
|
|
|
format = hfinfo_uint_vals_format(hfinfo);
|
|
|
|
|
|
|
|
/* Un-shift bits */
|
2003-12-02 21:15:49 +00:00
|
|
|
unshifted_value = fvalue_get_integer(&fi->value);
|
2001-02-01 20:21:25 +00:00
|
|
|
value = unshifted_value;
|
1999-10-12 06:21:15 +00:00
|
|
|
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 */
|
2005-08-17 23:10:28 +00:00
|
|
|
ret = g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
|
1999-10-12 06:21:15 +00:00
|
|
|
format, hfinfo->name,
|
2001-02-01 20:21:25 +00:00
|
|
|
val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
|
2002-12-31 21:37:29 +00:00
|
|
|
if ((ret == -1) || (ret >= (ITEM_LABEL_LENGTH - bitfield_byte_length)))
|
|
|
|
label_str[ITEM_LABEL_LENGTH - 1] = '\0';
|
1999-10-12 06:21:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
fill_label_numeric_bitfield(field_info *fi, gchar *label_str)
|
|
|
|
{
|
2005-08-05 13:23:47 +00:00
|
|
|
const char *format = NULL;
|
|
|
|
char *p;
|
1999-10-12 06:21:15 +00:00
|
|
|
int bitfield_byte_length, bitwidth;
|
|
|
|
guint32 unshifted_value;
|
2001-02-01 20:21:25 +00:00
|
|
|
guint32 value;
|
2002-12-31 21:37:29 +00:00
|
|
|
int ret; /*tmp return value */
|
1999-10-12 06:21:15 +00:00
|
|
|
|
2003-12-03 09:28:26 +00:00
|
|
|
header_field_info *hfinfo = fi->hfinfo;
|
1999-10-12 06:21:15 +00:00
|
|
|
|
|
|
|
/* Figure out the bit width */
|
|
|
|
bitwidth = hfinfo_bitwidth(hfinfo);
|
|
|
|
|
|
|
|
/* Pick the proper format string */
|
|
|
|
format = hfinfo_uint_format(hfinfo);
|
|
|
|
|
|
|
|
/* Un-shift bits */
|
2003-12-02 21:15:49 +00:00
|
|
|
unshifted_value = fvalue_get_integer(&fi->value);
|
2001-02-01 20:21:25 +00:00
|
|
|
value = unshifted_value;
|
1999-10-12 06:21:15 +00:00
|
|
|
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 */
|
2005-09-05 10:56:41 +00:00
|
|
|
if (IS_BASE_DUAL(hfinfo->display)) {
|
|
|
|
ret = g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
|
|
|
|
format, hfinfo->name, value, value);
|
|
|
|
} else {
|
|
|
|
ret = g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
|
|
|
|
format, hfinfo->name, value);
|
|
|
|
}
|
2002-12-31 21:37:29 +00:00
|
|
|
if ((ret == -1) || (ret >= (ITEM_LABEL_LENGTH - bitfield_byte_length)))
|
|
|
|
label_str[ITEM_LABEL_LENGTH - 1] = '\0';
|
|
|
|
|
1999-10-12 06:21:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
fill_label_enumerated_uint(field_info *fi, gchar *label_str)
|
|
|
|
{
|
2005-08-05 13:23:47 +00:00
|
|
|
const char *format = NULL;
|
2003-12-03 09:28:26 +00:00
|
|
|
header_field_info *hfinfo = fi->hfinfo;
|
2001-02-01 20:21:25 +00:00
|
|
|
guint32 value;
|
2002-12-31 21:37:29 +00:00
|
|
|
int ret; /*tmp return value */
|
1999-10-12 06:21:15 +00:00
|
|
|
|
|
|
|
/* Pick the proper format string */
|
|
|
|
format = hfinfo_uint_vals_format(hfinfo);
|
|
|
|
|
2003-12-02 21:15:49 +00:00
|
|
|
value = fvalue_get_integer(&fi->value);
|
2001-02-01 20:21:25 +00:00
|
|
|
|
1999-10-12 06:21:15 +00:00
|
|
|
/* Fill in the textual info */
|
2005-08-17 23:10:28 +00:00
|
|
|
ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
|
1999-10-12 06:21:15 +00:00
|
|
|
format, hfinfo->name,
|
2001-02-01 20:21:25 +00:00
|
|
|
val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
|
2002-12-31 21:37:29 +00:00
|
|
|
if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
|
|
|
|
label_str[ITEM_LABEL_LENGTH - 1] = '\0';
|
1999-10-12 06:21:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
fill_label_uint(field_info *fi, gchar *label_str)
|
|
|
|
{
|
2005-08-05 13:23:47 +00:00
|
|
|
const char *format = NULL;
|
2003-12-03 09:28:26 +00:00
|
|
|
header_field_info *hfinfo = fi->hfinfo;
|
2001-02-01 20:21:25 +00:00
|
|
|
guint32 value;
|
2002-12-31 21:37:29 +00:00
|
|
|
int ret; /*tmp return value */
|
1999-10-12 06:21:15 +00:00
|
|
|
|
|
|
|
/* Pick the proper format string */
|
|
|
|
format = hfinfo_uint_format(hfinfo);
|
2003-12-02 21:15:49 +00:00
|
|
|
value = fvalue_get_integer(&fi->value);
|
1999-10-12 06:21:15 +00:00
|
|
|
|
|
|
|
/* Fill in the textual info */
|
2005-09-05 10:56:41 +00:00
|
|
|
if (IS_BASE_DUAL(hfinfo->display)) {
|
|
|
|
ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
|
|
|
|
format, hfinfo->name, value, value);
|
|
|
|
} else {
|
|
|
|
ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
|
|
|
|
format, hfinfo->name, value);
|
|
|
|
}
|
2002-12-31 21:37:29 +00:00
|
|
|
if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
|
|
|
|
label_str[ITEM_LABEL_LENGTH - 1] = '\0';
|
1999-10-12 06:21:15 +00:00
|
|
|
}
|
|
|
|
|
2004-08-22 00:31:58 +00:00
|
|
|
static void
|
|
|
|
fill_label_uint64(field_info *fi, gchar *label_str)
|
|
|
|
{
|
2005-08-05 13:23:47 +00:00
|
|
|
const char *format = NULL;
|
2004-08-22 00:31:58 +00:00
|
|
|
header_field_info *hfinfo = fi->hfinfo;
|
|
|
|
guint64 value;
|
|
|
|
int ret; /*tmp return value */
|
|
|
|
|
|
|
|
/* Pick the proper format string */
|
|
|
|
format = hfinfo_uint64_format(hfinfo);
|
|
|
|
value = fvalue_get_integer64(&fi->value);
|
|
|
|
|
|
|
|
/* Fill in the textual info */
|
2005-09-05 10:56:41 +00:00
|
|
|
if (IS_BASE_DUAL(hfinfo->display)) {
|
|
|
|
ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
|
|
|
|
format, hfinfo->name, value, value);
|
|
|
|
} else {
|
|
|
|
ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
|
|
|
|
format, hfinfo->name, value);
|
|
|
|
}
|
2004-08-22 00:31:58 +00:00
|
|
|
if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
|
|
|
|
label_str[ITEM_LABEL_LENGTH - 1] = '\0';
|
|
|
|
}
|
|
|
|
|
1999-10-13 03:07:30 +00:00
|
|
|
static void
|
|
|
|
fill_label_enumerated_int(field_info *fi, gchar *label_str)
|
|
|
|
{
|
2005-08-05 13:23:47 +00:00
|
|
|
const char *format = NULL;
|
2003-12-03 09:28:26 +00:00
|
|
|
header_field_info *hfinfo = fi->hfinfo;
|
2001-02-01 20:21:25 +00:00
|
|
|
guint32 value;
|
2002-12-31 21:37:29 +00:00
|
|
|
int ret; /*tmp return value */
|
1999-10-13 03:07:30 +00:00
|
|
|
|
|
|
|
/* Pick the proper format string */
|
|
|
|
format = hfinfo_int_vals_format(hfinfo);
|
2003-12-02 21:15:49 +00:00
|
|
|
value = fvalue_get_integer(&fi->value);
|
1999-10-13 03:07:30 +00:00
|
|
|
|
|
|
|
/* Fill in the textual info */
|
2005-08-17 23:10:28 +00:00
|
|
|
ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
|
1999-10-13 03:07:30 +00:00
|
|
|
format, hfinfo->name,
|
2001-02-01 20:21:25 +00:00
|
|
|
val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
|
2002-12-31 21:37:29 +00:00
|
|
|
if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
|
|
|
|
label_str[ITEM_LABEL_LENGTH - 1] = '\0';
|
1999-10-13 03:07:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
fill_label_int(field_info *fi, gchar *label_str)
|
|
|
|
{
|
2005-08-05 13:23:47 +00:00
|
|
|
const char *format = NULL;
|
2003-12-03 09:28:26 +00:00
|
|
|
header_field_info *hfinfo = fi->hfinfo;
|
2001-02-01 20:21:25 +00:00
|
|
|
guint32 value;
|
2002-12-31 21:37:29 +00:00
|
|
|
int ret; /*tmp return value */
|
1999-10-13 03:07:30 +00:00
|
|
|
|
|
|
|
/* Pick the proper format string */
|
|
|
|
format = hfinfo_int_format(hfinfo);
|
2003-12-02 21:15:49 +00:00
|
|
|
value = fvalue_get_integer(&fi->value);
|
1999-10-13 03:07:30 +00:00
|
|
|
|
|
|
|
/* Fill in the textual info */
|
2005-09-05 10:56:41 +00:00
|
|
|
if (IS_BASE_DUAL(hfinfo->display)) {
|
|
|
|
ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
|
|
|
|
format, hfinfo->name, value, value);
|
|
|
|
} else {
|
|
|
|
ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
|
|
|
|
format, hfinfo->name, value);
|
|
|
|
}
|
2002-12-31 21:37:29 +00:00
|
|
|
if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
|
|
|
|
label_str[ITEM_LABEL_LENGTH - 1] = '\0';
|
1999-10-13 03:07:30 +00:00
|
|
|
}
|
|
|
|
|
2004-08-22 00:31:58 +00:00
|
|
|
static void
|
|
|
|
fill_label_int64(field_info *fi, gchar *label_str)
|
|
|
|
{
|
2005-08-05 13:23:47 +00:00
|
|
|
const char *format = NULL;
|
2004-08-22 00:31:58 +00:00
|
|
|
header_field_info *hfinfo = fi->hfinfo;
|
|
|
|
guint64 value;
|
|
|
|
int ret; /*tmp return value */
|
|
|
|
|
|
|
|
/* Pick the proper format string */
|
|
|
|
format = hfinfo_int64_format(hfinfo);
|
|
|
|
value = fvalue_get_integer64(&fi->value);
|
|
|
|
|
|
|
|
/* Fill in the textual info */
|
2005-09-05 10:56:41 +00:00
|
|
|
if (IS_BASE_DUAL(hfinfo->display)) {
|
|
|
|
ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
|
|
|
|
format, hfinfo->name, value, value);
|
|
|
|
} else {
|
|
|
|
ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
|
|
|
|
format, hfinfo->name, value);
|
|
|
|
}
|
2004-08-22 00:31:58 +00:00
|
|
|
if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
|
|
|
|
label_str[ITEM_LABEL_LENGTH - 1] = '\0';
|
|
|
|
}
|
|
|
|
|
2001-02-01 20:21:25 +00:00
|
|
|
int
|
1999-10-12 06:21:15 +00:00
|
|
|
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:
|
2005-03-23 00:09:12 +00:00
|
|
|
DISSECTOR_ASSERT_NOT_REACHED();
|
1999-10-12 06:21:15 +00:00
|
|
|
;
|
|
|
|
}
|
|
|
|
return bitwidth;
|
|
|
|
}
|
|
|
|
|
2005-08-05 13:23:47 +00:00
|
|
|
static const char*
|
1999-10-12 06:21:15 +00:00
|
|
|
hfinfo_uint_vals_format(header_field_info *hfinfo)
|
|
|
|
{
|
2005-08-05 13:23:47 +00:00
|
|
|
const char *format = NULL;
|
1999-10-12 06:21:15 +00:00
|
|
|
|
|
|
|
switch(hfinfo->display) {
|
2001-05-09 01:22:46 +00:00
|
|
|
case BASE_DEC:
|
2005-09-05 10:56:41 +00:00
|
|
|
case BASE_DEC_HEX:
|
1999-10-12 06:21:15 +00:00
|
|
|
format = "%s: %s (%u)";
|
|
|
|
break;
|
2000-11-03 17:26:47 +00:00
|
|
|
case BASE_OCT: /* I'm lazy */
|
|
|
|
format = "%s: %s (%o)";
|
|
|
|
break;
|
1999-10-12 06:21:15 +00:00
|
|
|
case BASE_HEX:
|
2005-09-05 10:56:41 +00:00
|
|
|
case BASE_HEX_DEC:
|
1999-10-12 06:21:15 +00:00
|
|
|
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:
|
2005-03-23 00:09:12 +00:00
|
|
|
DISSECTOR_ASSERT_NOT_REACHED();
|
1999-10-12 06:21:15 +00:00
|
|
|
;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
2005-03-23 00:09:12 +00:00
|
|
|
DISSECTOR_ASSERT_NOT_REACHED();
|
1999-10-12 06:21:15 +00:00
|
|
|
;
|
|
|
|
}
|
|
|
|
return format;
|
|
|
|
}
|
|
|
|
|
2005-08-05 13:23:47 +00:00
|
|
|
static const char*
|
1999-10-12 06:21:15 +00:00
|
|
|
hfinfo_uint_format(header_field_info *hfinfo)
|
|
|
|
{
|
2005-08-05 13:23:47 +00:00
|
|
|
const char *format = NULL;
|
1999-10-12 06:21:15 +00:00
|
|
|
|
|
|
|
/* Pick the proper format string */
|
2002-12-19 02:58:53 +00:00
|
|
|
if (hfinfo->type == FT_FRAMENUM) {
|
|
|
|
/*
|
|
|
|
* Frame numbers are always displayed in decimal.
|
|
|
|
*/
|
|
|
|
format = "%s: %u";
|
|
|
|
} else {
|
|
|
|
switch(hfinfo->display) {
|
|
|
|
case BASE_DEC:
|
|
|
|
format = "%s: %u";
|
|
|
|
break;
|
2005-09-05 10:56:41 +00:00
|
|
|
case BASE_DEC_HEX:
|
|
|
|
switch(hfinfo->type) {
|
|
|
|
case FT_UINT8:
|
|
|
|
format = "%s: %u (0x%02x)";
|
|
|
|
break;
|
|
|
|
case FT_UINT16:
|
|
|
|
format = "%s: %u (0x%04x)";
|
|
|
|
break;
|
|
|
|
case FT_UINT24:
|
|
|
|
format = "%s: %u (0x%06x)";
|
|
|
|
break;
|
|
|
|
case FT_UINT32:
|
|
|
|
format = "%s: %u (0x%08x)";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
DISSECTOR_ASSERT_NOT_REACHED();
|
|
|
|
;
|
|
|
|
}
|
|
|
|
break;
|
2002-12-19 02:58:53 +00:00
|
|
|
case BASE_OCT: /* I'm lazy */
|
|
|
|
format = "%s: %o";
|
|
|
|
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:
|
|
|
|
format = "%s: 0x%08x";
|
|
|
|
break;
|
|
|
|
default:
|
2005-03-23 00:09:12 +00:00
|
|
|
DISSECTOR_ASSERT_NOT_REACHED();
|
2002-12-19 02:58:53 +00:00
|
|
|
;
|
|
|
|
}
|
|
|
|
break;
|
2005-09-05 10:56:41 +00:00
|
|
|
case BASE_HEX_DEC:
|
|
|
|
switch(hfinfo->type) {
|
|
|
|
case FT_UINT8:
|
|
|
|
format = "%s: 0x%02x (%u)";
|
|
|
|
break;
|
|
|
|
case FT_UINT16:
|
|
|
|
format = "%s: 0x%04x (%u)";
|
|
|
|
break;
|
|
|
|
case FT_UINT24:
|
|
|
|
format = "%s: 0x%06x (%u)";
|
|
|
|
break;
|
|
|
|
case FT_UINT32:
|
|
|
|
format = "%s: 0x%08x (%u)";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
DISSECTOR_ASSERT_NOT_REACHED();
|
|
|
|
;
|
|
|
|
}
|
|
|
|
break;
|
2002-12-19 02:58:53 +00:00
|
|
|
default:
|
2005-03-23 00:09:12 +00:00
|
|
|
DISSECTOR_ASSERT_NOT_REACHED();
|
2002-12-19 02:58:53 +00:00
|
|
|
;
|
|
|
|
}
|
1999-10-13 03:07:30 +00:00
|
|
|
}
|
|
|
|
return format;
|
|
|
|
}
|
|
|
|
|
2005-08-05 13:23:47 +00:00
|
|
|
static const char*
|
1999-10-13 03:07:30 +00:00
|
|
|
hfinfo_int_vals_format(header_field_info *hfinfo)
|
|
|
|
{
|
2005-08-05 13:23:47 +00:00
|
|
|
const char *format = NULL;
|
1999-10-13 03:07:30 +00:00
|
|
|
|
|
|
|
switch(hfinfo->display) {
|
|
|
|
case BASE_DEC:
|
2005-09-05 10:56:41 +00:00
|
|
|
case BASE_DEC_HEX:
|
1999-10-13 03:07:30 +00:00
|
|
|
format = "%s: %s (%d)";
|
|
|
|
break;
|
2000-11-03 17:26:47 +00:00
|
|
|
case BASE_OCT: /* I'm lazy */
|
|
|
|
format = "%s: %s (%o)";
|
|
|
|
break;
|
1999-10-13 03:07:30 +00:00
|
|
|
case BASE_HEX:
|
2005-09-05 10:56:41 +00:00
|
|
|
case BASE_HEX_DEC:
|
1999-10-13 03:07:30 +00:00
|
|
|
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:
|
2005-03-23 00:09:12 +00:00
|
|
|
DISSECTOR_ASSERT_NOT_REACHED();
|
1999-10-13 03:07:30 +00:00
|
|
|
;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
2005-03-23 00:09:12 +00:00
|
|
|
DISSECTOR_ASSERT_NOT_REACHED();
|
1999-10-13 03:07:30 +00:00
|
|
|
;
|
|
|
|
}
|
|
|
|
return format;
|
|
|
|
}
|
|
|
|
|
2005-08-05 13:23:47 +00:00
|
|
|
static const char*
|
2004-08-22 00:31:58 +00:00
|
|
|
hfinfo_uint64_format(header_field_info *hfinfo)
|
|
|
|
{
|
2005-08-05 13:23:47 +00:00
|
|
|
const char *format = NULL;
|
2004-08-22 00:31:58 +00:00
|
|
|
|
|
|
|
/* Pick the proper format string */
|
|
|
|
switch(hfinfo->display) {
|
|
|
|
case BASE_DEC:
|
|
|
|
format = "%s: %" PRIu64;
|
|
|
|
break;
|
2005-09-05 10:56:41 +00:00
|
|
|
case BASE_DEC_HEX:
|
|
|
|
format = "%s: %" PRIu64 " (%" PRIx64 ")";
|
|
|
|
break;
|
2004-08-22 00:31:58 +00:00
|
|
|
case BASE_OCT: /* I'm lazy */
|
|
|
|
format = "%s: %" PRIo64;
|
|
|
|
break;
|
|
|
|
case BASE_HEX:
|
|
|
|
format = "%s: 0x%016" PRIx64;
|
|
|
|
break;
|
2005-09-05 10:56:41 +00:00
|
|
|
case BASE_HEX_DEC:
|
|
|
|
format = "%s: 0x%016" PRIx64 " (%" PRIu64 ")";
|
|
|
|
break;
|
2004-08-22 00:31:58 +00:00
|
|
|
default:
|
2005-03-23 00:09:12 +00:00
|
|
|
DISSECTOR_ASSERT_NOT_REACHED();
|
2004-08-22 00:31:58 +00:00
|
|
|
;
|
|
|
|
}
|
|
|
|
return format;
|
|
|
|
}
|
|
|
|
|
2005-08-05 13:23:47 +00:00
|
|
|
static const char*
|
1999-10-13 03:07:30 +00:00
|
|
|
hfinfo_int_format(header_field_info *hfinfo)
|
|
|
|
{
|
2005-08-05 13:23:47 +00:00
|
|
|
const char *format = NULL;
|
1999-10-13 03:07:30 +00:00
|
|
|
|
|
|
|
/* Pick the proper format string */
|
|
|
|
switch(hfinfo->display) {
|
|
|
|
case BASE_DEC:
|
|
|
|
format = "%s: %d";
|
|
|
|
break;
|
2005-09-05 10:56:41 +00:00
|
|
|
case BASE_DEC_HEX:
|
|
|
|
switch(hfinfo->type) {
|
|
|
|
case FT_INT8:
|
|
|
|
format = "%s: %d (0x%02x)";
|
|
|
|
break;
|
|
|
|
case FT_INT16:
|
|
|
|
format = "%s: %d (0x%04x)";
|
|
|
|
break;
|
|
|
|
case FT_INT24:
|
|
|
|
format = "%s: %d (0x%06x)";
|
|
|
|
break;
|
|
|
|
case FT_INT32:
|
|
|
|
format = "%s: %d (0x%08x)";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
DISSECTOR_ASSERT_NOT_REACHED();
|
|
|
|
;
|
|
|
|
}
|
2000-11-03 17:26:47 +00:00
|
|
|
case BASE_OCT: /* I'm lazy */
|
|
|
|
format = "%s: %o";
|
|
|
|
break;
|
1999-10-13 03:07:30 +00:00
|
|
|
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:
|
2005-03-23 00:09:12 +00:00
|
|
|
DISSECTOR_ASSERT_NOT_REACHED();
|
1999-10-12 06:21:15 +00:00
|
|
|
;
|
|
|
|
}
|
2005-09-05 10:56:41 +00:00
|
|
|
case BASE_HEX_DEC:
|
|
|
|
switch(hfinfo->type) {
|
|
|
|
case FT_INT8:
|
|
|
|
format = "%s: 0x%02x (%d)";
|
|
|
|
break;
|
|
|
|
case FT_INT16:
|
|
|
|
format = "%s: 0x%04x (%d)";
|
|
|
|
break;
|
|
|
|
case FT_INT24:
|
|
|
|
format = "%s: 0x%06x (%d)";
|
|
|
|
break;
|
|
|
|
case FT_INT32:
|
|
|
|
format = "%s: 0x%08x (%d)";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
DISSECTOR_ASSERT_NOT_REACHED();
|
|
|
|
;
|
|
|
|
}
|
1999-10-12 06:21:15 +00:00
|
|
|
break;
|
|
|
|
default:
|
2005-03-23 00:09:12 +00:00
|
|
|
DISSECTOR_ASSERT_NOT_REACHED();
|
1999-10-12 06:21:15 +00:00
|
|
|
;
|
|
|
|
}
|
|
|
|
return format;
|
|
|
|
}
|
|
|
|
|
2005-08-05 13:23:47 +00:00
|
|
|
static const char*
|
2004-08-22 00:31:58 +00:00
|
|
|
hfinfo_int64_format(header_field_info *hfinfo)
|
|
|
|
{
|
2005-08-05 13:23:47 +00:00
|
|
|
const char *format = NULL;
|
2004-08-22 00:31:58 +00:00
|
|
|
|
|
|
|
/* Pick the proper format string */
|
|
|
|
switch(hfinfo->display) {
|
|
|
|
case BASE_DEC:
|
|
|
|
format = "%s: %" PRId64;
|
|
|
|
break;
|
2005-09-05 10:56:41 +00:00
|
|
|
case BASE_DEC_HEX:
|
|
|
|
format = "%s: %" PRId64 " (%" PRIx64 ")";
|
|
|
|
break;
|
2004-08-22 00:31:58 +00:00
|
|
|
case BASE_OCT: /* I'm lazy */
|
|
|
|
format = "%s: %" PRIo64;
|
|
|
|
break;
|
|
|
|
case BASE_HEX:
|
|
|
|
format = "%s: 0x%016" PRIx64;
|
|
|
|
break;
|
2005-09-05 10:56:41 +00:00
|
|
|
case BASE_HEX_DEC:
|
|
|
|
format = "%s: 0x%016" PRIx64 " (%" PRId64 ")";
|
|
|
|
break;
|
2004-08-22 00:31:58 +00:00
|
|
|
default:
|
2005-03-23 00:09:12 +00:00
|
|
|
DISSECTOR_ASSERT_NOT_REACHED();
|
2004-08-22 00:31:58 +00:00
|
|
|
;
|
|
|
|
}
|
|
|
|
return format;
|
|
|
|
}
|
|
|
|
|
1999-10-12 06:21:15 +00:00
|
|
|
|
|
|
|
|
1999-07-07 22:52:57 +00:00
|
|
|
int
|
|
|
|
proto_registrar_n(void)
|
|
|
|
{
|
2003-11-21 14:58:49 +00:00
|
|
|
return gpa_hfinfo.len;
|
1999-07-07 22:52:57 +00:00
|
|
|
}
|
|
|
|
|
2005-06-24 02:51:01 +00:00
|
|
|
const char*
|
1999-11-11 16:20:25 +00:00
|
|
|
proto_registrar_get_name(int n)
|
|
|
|
{
|
2001-05-09 01:22:46 +00:00
|
|
|
header_field_info *hfinfo;
|
|
|
|
|
2003-11-22 04:41:31 +00:00
|
|
|
PROTO_REGISTRAR_GET_NTH(n, hfinfo);
|
|
|
|
return hfinfo->name;
|
1999-11-11 16:20:25 +00:00
|
|
|
}
|
|
|
|
|
2005-06-24 02:51:01 +00:00
|
|
|
const char*
|
1999-07-07 22:52:57 +00:00
|
|
|
proto_registrar_get_abbrev(int n)
|
|
|
|
{
|
2001-02-01 20:21:25 +00:00
|
|
|
header_field_info *hfinfo;
|
1999-07-07 22:52:57 +00:00
|
|
|
|
2003-11-22 04:41:31 +00:00
|
|
|
PROTO_REGISTRAR_GET_NTH(n, hfinfo);
|
|
|
|
return hfinfo->abbrev;
|
1999-07-07 22:52:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
proto_registrar_get_ftype(int n)
|
|
|
|
{
|
2001-02-01 20:21:25 +00:00
|
|
|
header_field_info *hfinfo;
|
1999-07-07 22:52:57 +00:00
|
|
|
|
2003-11-22 04:41:31 +00:00
|
|
|
PROTO_REGISTRAR_GET_NTH(n, hfinfo);
|
|
|
|
return hfinfo->type;
|
1999-07-07 22:52:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
proto_registrar_get_parent(int n)
|
|
|
|
{
|
2001-02-01 20:21:25 +00:00
|
|
|
header_field_info *hfinfo;
|
1999-07-07 22:52:57 +00:00
|
|
|
|
2003-11-22 04:41:31 +00:00
|
|
|
PROTO_REGISTRAR_GET_NTH(n, hfinfo);
|
|
|
|
return hfinfo->parent;
|
1999-07-07 22:52:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
proto_registrar_is_protocol(int n)
|
|
|
|
{
|
2001-02-01 20:21:25 +00:00
|
|
|
header_field_info *hfinfo;
|
1999-07-07 22:52:57 +00:00
|
|
|
|
2003-11-22 04:41:31 +00:00
|
|
|
PROTO_REGISTRAR_GET_NTH(n, hfinfo);
|
|
|
|
return (hfinfo->parent == -1 ? TRUE : FALSE);
|
1999-07-07 22:52:57 +00:00
|
|
|
}
|
|
|
|
|
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)
|
|
|
|
{
|
2001-02-01 20:21:25 +00:00
|
|
|
header_field_info *hfinfo;
|
1999-10-12 04:21:13 +00:00
|
|
|
|
2003-11-22 04:41:31 +00:00
|
|
|
PROTO_REGISTRAR_GET_NTH(n, hfinfo);
|
2001-02-01 20:21:25 +00:00
|
|
|
return ftype_length(hfinfo->type);
|
1999-10-12 04:21:13 +00:00
|
|
|
}
|
|
|
|
|
2000-07-22 15:58:54 +00:00
|
|
|
|
|
|
|
|
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
|
|
|
{
|
2002-04-20 08:07:56 +00:00
|
|
|
GPtrArray *ptrs = proto_get_finfo_ptr_array(tree, id);
|
1999-07-07 22:52:57 +00:00
|
|
|
|
2002-04-20 08:07:56 +00:00
|
|
|
if (!ptrs) {
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
else if (g_ptr_array_len(ptrs) > 0) {
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return FALSE;
|
|
|
|
}
|
1999-07-07 22:52:57 +00:00
|
|
|
}
|
|
|
|
|
2001-12-18 19:09:08 +00:00
|
|
|
/* Return GPtrArray* of field_info pointers for all hfindex that appear in tree.
|
|
|
|
* This only works if the hfindex was "primed" before the dissection
|
|
|
|
* took place, as we just pass back the already-created GPtrArray*.
|
|
|
|
* The caller should *not* free the GPtrArray*; proto_tree_free_node()
|
|
|
|
* handles that. */
|
2000-07-22 15:58:54 +00:00
|
|
|
GPtrArray*
|
|
|
|
proto_get_finfo_ptr_array(proto_tree *tree, int id)
|
1999-07-07 22:52:57 +00:00
|
|
|
{
|
2002-04-20 08:07:56 +00:00
|
|
|
return g_hash_table_lookup(PTREE_DATA(tree)->interesting_hfids,
|
|
|
|
GINT_TO_POINTER(id));
|
1999-07-07 22:52:57 +00:00
|
|
|
}
|
2001-03-02 23:10:12 +00:00
|
|
|
|
|
|
|
|
2003-12-06 06:09:13 +00:00
|
|
|
/* Helper struct and function for proto_find_info() */
|
|
|
|
typedef struct {
|
|
|
|
GPtrArray *array;
|
|
|
|
int id;
|
|
|
|
} ffdata_t;
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
find_finfo(proto_node *node, gpointer data)
|
|
|
|
{
|
|
|
|
field_info *fi = PITEM_FINFO(node);
|
|
|
|
if (fi && fi->hfinfo) {
|
|
|
|
if (fi->hfinfo->id == ((ffdata_t*)data)->id) {
|
|
|
|
g_ptr_array_add(((ffdata_t*)data)->array, fi);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Don't stop traversing. */
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Return GPtrArray* of field_info pointers for all hfindex that appear in a tree.
|
|
|
|
* This works on any proto_tree, primed or unprimed, but actually searches
|
|
|
|
* the tree, so it is slower than using proto_get_finfo_ptr_array on a primed tree.
|
|
|
|
* The caller does need to free the returned GPtrArray with
|
|
|
|
* g_ptr_array_free(<array>, FALSE).
|
|
|
|
*/
|
|
|
|
GPtrArray*
|
|
|
|
proto_find_finfo(proto_tree *tree, int id)
|
|
|
|
{
|
|
|
|
ffdata_t ffdata;
|
|
|
|
|
|
|
|
ffdata.array = g_ptr_array_new();
|
|
|
|
ffdata.id = id;
|
|
|
|
|
|
|
|
proto_tree_traverse_pre_order(tree, find_finfo, &ffdata);
|
|
|
|
|
|
|
|
return ffdata.array;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-03-02 23:10:12 +00:00
|
|
|
typedef struct {
|
|
|
|
guint offset;
|
|
|
|
field_info *finfo;
|
2002-02-18 01:08:44 +00:00
|
|
|
tvbuff_t *tvb;
|
2001-03-02 23:10:12 +00:00
|
|
|
} offset_search_t;
|
|
|
|
|
|
|
|
static gboolean
|
2003-12-04 10:59:34 +00:00
|
|
|
check_for_offset(proto_node *node, gpointer data)
|
2001-03-02 23:10:12 +00:00
|
|
|
{
|
2001-12-18 19:09:08 +00:00
|
|
|
field_info *fi = PITEM_FINFO(node);
|
2001-03-02 23:10:12 +00:00
|
|
|
offset_search_t *offsearch = data;
|
|
|
|
|
|
|
|
/* !fi == the top most container node which holds nothing */
|
2004-05-01 15:15:08 +00:00
|
|
|
if (fi && !PROTO_ITEM_IS_HIDDEN(node) && fi->ds_tvb && offsearch->tvb == fi->ds_tvb) {
|
2001-10-26 17:29:12 +00:00
|
|
|
if (offsearch->offset >= (guint) fi->start &&
|
|
|
|
offsearch->offset < (guint) (fi->start + fi->length)) {
|
2001-03-02 23:10:12 +00:00
|
|
|
|
|
|
|
offsearch->finfo = fi;
|
|
|
|
return FALSE; /* keep traversing */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return FALSE; /* keep traversing */
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Search a proto_tree backwards (from leaves to root) looking for the field
|
|
|
|
* whose start/length occupies 'offset' */
|
|
|
|
/* XXX - I couldn't find an easy way to search backwards, so I search
|
|
|
|
* forwards, w/o stopping. Therefore, the last finfo I find will the be
|
|
|
|
* the one I want to return to the user. This algorithm is inefficient
|
|
|
|
* and could be re-done, but I'd have to handle all the children and
|
|
|
|
* siblings of each node myself. When I have more time I'll do that.
|
|
|
|
* (yeah right) */
|
|
|
|
field_info*
|
2002-02-18 01:08:44 +00:00
|
|
|
proto_find_field_from_offset(proto_tree *tree, guint offset, tvbuff_t *tvb)
|
2001-03-02 23:10:12 +00:00
|
|
|
{
|
|
|
|
offset_search_t offsearch;
|
|
|
|
|
|
|
|
offsearch.offset = offset;
|
|
|
|
offsearch.finfo = NULL;
|
2002-02-18 01:08:44 +00:00
|
|
|
offsearch.tvb = tvb;
|
2001-03-02 23:10:12 +00:00
|
|
|
|
2003-12-04 10:59:34 +00:00
|
|
|
proto_tree_traverse_pre_order(tree, check_for_offset, &offsearch);
|
2001-03-02 23:10:12 +00:00
|
|
|
|
|
|
|
return offsearch.finfo;
|
|
|
|
}
|
|
|
|
|
2002-05-14 10:15:12 +00:00
|
|
|
/* Dumps the protocols in the registration database to stdout. An independent
|
|
|
|
* program can take this output and format it into nice tables or HTML or
|
|
|
|
* whatever.
|
|
|
|
*
|
|
|
|
* There is one record per line. The fields are tab-delimited.
|
|
|
|
*
|
|
|
|
* Field 1 = protocol name
|
|
|
|
* Field 2 = protocol short name
|
|
|
|
* Field 3 = protocol filter name
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
proto_registrar_dump_protocols(void)
|
|
|
|
{
|
|
|
|
protocol_t *protocol;
|
|
|
|
int i;
|
|
|
|
void *cookie;
|
2001-03-02 23:10:12 +00:00
|
|
|
|
2002-05-14 10:15:12 +00:00
|
|
|
for (i = proto_get_first_protocol(&cookie); i != -1;
|
|
|
|
i = proto_get_next_protocol(&cookie)) {
|
|
|
|
protocol = find_protocol_by_id(i);
|
|
|
|
printf("%s\t%s\t%s\n", protocol->name, protocol->short_name,
|
|
|
|
protocol->filter_name);
|
|
|
|
}
|
|
|
|
}
|
2001-03-02 23:10:12 +00:00
|
|
|
|
2004-09-10 15:21:20 +00:00
|
|
|
/* Dumps the value_string and true/false strings for fields that have
|
|
|
|
* them. There is one record per line. Fields are tab-delimited.
|
|
|
|
* There are two types of records, Value String records and True/False
|
|
|
|
* String records. The first field, 'V' or 'T', indicates the type
|
|
|
|
* of record.
|
|
|
|
*
|
|
|
|
* Value Strings
|
|
|
|
* -------------
|
|
|
|
* Field 1 = 'V'
|
|
|
|
* Field 2 = field abbreviation to which this value string corresponds
|
|
|
|
* Field 3 = Integer value
|
|
|
|
* Field 4 = String
|
|
|
|
*
|
|
|
|
* True/False Strings
|
|
|
|
* ------------------
|
|
|
|
* Field 1 = 'T'
|
|
|
|
* Field 2 = field abbreviation to which this true/false string corresponds
|
|
|
|
* Field 3 = True String
|
|
|
|
* Field 4 = False String
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
proto_registrar_dump_values(void)
|
|
|
|
{
|
|
|
|
header_field_info *hfinfo, *parent_hfinfo;
|
|
|
|
int i, len, vi;
|
|
|
|
const value_string *vals;
|
|
|
|
const true_false_string *tfs;
|
|
|
|
|
|
|
|
len = gpa_hfinfo.len;
|
|
|
|
for (i = 0; i < len ; i++) {
|
|
|
|
PROTO_REGISTRAR_GET_NTH(i, hfinfo);
|
|
|
|
|
|
|
|
if (hfinfo->id == hf_text_only) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ignore protocols */
|
|
|
|
if (proto_registrar_is_protocol(i)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
/* process header fields */
|
|
|
|
else {
|
|
|
|
/*
|
|
|
|
* If this field isn't at the head of the list of
|
|
|
|
* fields with this name, skip this field - all
|
|
|
|
* fields with the same name are really just versions
|
|
|
|
* of the same field stored in different bits, and
|
|
|
|
* should have the same type/radix/value list, and
|
|
|
|
* just differ in their bit masks. (If a field isn't
|
|
|
|
* a bitfield, but can be, say, 1 or 2 bytes long,
|
|
|
|
* it can just be made FT_UINT16, meaning the
|
|
|
|
* *maximum* length is 2 bytes, and be used
|
|
|
|
* for all lengths.)
|
|
|
|
*/
|
|
|
|
if (hfinfo->same_name_prev != NULL)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
|
|
|
|
|
|
|
|
vals = NULL;
|
|
|
|
tfs = NULL;
|
|
|
|
|
|
|
|
if (hfinfo->type == FT_UINT8 ||
|
|
|
|
hfinfo->type == FT_UINT16 ||
|
|
|
|
hfinfo->type == FT_UINT24 ||
|
|
|
|
hfinfo->type == FT_UINT32 ||
|
|
|
|
hfinfo->type == FT_UINT64 ||
|
|
|
|
hfinfo->type == FT_INT8 ||
|
|
|
|
hfinfo->type == FT_INT16 ||
|
|
|
|
hfinfo->type == FT_INT24 ||
|
|
|
|
hfinfo->type == FT_INT32 ||
|
|
|
|
hfinfo->type == FT_INT64) {
|
|
|
|
|
|
|
|
vals = hfinfo->strings;
|
|
|
|
}
|
|
|
|
else if (hfinfo->type == FT_BOOLEAN) {
|
|
|
|
tfs = hfinfo->strings;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Print value strings? */
|
|
|
|
if (vals) {
|
|
|
|
vi = 0;
|
|
|
|
while (vals[vi].strptr) {
|
|
|
|
/* Print in the proper base */
|
|
|
|
if (hfinfo->display == BASE_HEX) {
|
|
|
|
printf("V\t%s\t0x%x\t%s\n",
|
|
|
|
hfinfo->abbrev,
|
|
|
|
vals[vi].value,
|
|
|
|
vals[vi].strptr);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
printf("V\t%s\t%u\t%s\n",
|
|
|
|
hfinfo->abbrev,
|
|
|
|
vals[vi].value,
|
|
|
|
vals[vi].strptr);
|
|
|
|
}
|
|
|
|
vi++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Print true/false strings? */
|
|
|
|
else if (tfs) {
|
|
|
|
printf("T\t%s\t%s\t%s\n", hfinfo->abbrev,
|
|
|
|
tfs->true_string, tfs->false_string);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-05-14 10:15:12 +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.
|
1999-07-15 15:33:52 +00:00
|
|
|
*
|
|
|
|
* 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'
|
2004-09-10 15:21:20 +00:00
|
|
|
* Field 2 = descriptive protocol name
|
1999-07-15 15:33:52 +00:00
|
|
|
* Field 3 = protocol abbreviation
|
|
|
|
*
|
|
|
|
* Header Fields
|
|
|
|
* -------------
|
2004-09-10 15:21:20 +00:00
|
|
|
* (format 1)
|
1999-07-15 15:33:52 +00:00
|
|
|
* Field 1 = 'F'
|
2004-09-10 15:21:20 +00:00
|
|
|
* Field 2 = descriptive field name
|
1999-07-15 15:33:52 +00:00
|
|
|
* Field 3 = field abbreviation
|
|
|
|
* Field 4 = type ( textual representation of the the ftenum type )
|
|
|
|
* Field 5 = parent protocol abbreviation
|
2005-05-27 15:13:09 +00:00
|
|
|
* Field 6 = blurb describing field
|
2004-09-10 15:21:20 +00:00
|
|
|
*
|
2005-05-27 15:13:09 +00:00
|
|
|
* (format 2)
|
|
|
|
* Field 1 = 'F'
|
|
|
|
* Field 2 = descriptive field name
|
|
|
|
* Field 3 = field abbreviation
|
|
|
|
* Field 4 = type ( textual representation of the the ftenum type )
|
|
|
|
* Field 5 = parent protocol abbreviation
|
|
|
|
* Field 6 = blurb describing field
|
|
|
|
* Field 7 = base for display (for integer types)
|
|
|
|
* Field 8 = blurb describing field (yes, apparently we repeated this accidentally)
|
|
|
|
*
|
|
|
|
* (format 3)
|
|
|
|
* Field 1 = 'F'
|
|
|
|
* Field 2 = descriptive field name
|
|
|
|
* Field 3 = field abbreviation
|
|
|
|
* Field 4 = type ( textual representation of the the ftenum type )
|
|
|
|
* Field 5 = parent protocol abbreviation
|
|
|
|
* Field 6 = blurb describing field
|
|
|
|
* Field 7 = base for display (for integer types)
|
|
|
|
* Field 8 = bitmask
|
1999-07-15 15:33:52 +00:00
|
|
|
*/
|
|
|
|
void
|
2004-09-10 15:21:20 +00:00
|
|
|
proto_registrar_dump_fields(int format)
|
1999-07-15 15:33:52 +00:00
|
|
|
{
|
|
|
|
header_field_info *hfinfo, *parent_hfinfo;
|
|
|
|
int i, len;
|
|
|
|
const char *enum_name;
|
2004-09-10 15:21:20 +00:00
|
|
|
const char *base_name;
|
2005-12-04 04:22:43 +00:00
|
|
|
const char *blurb;
|
1999-07-15 15:33:52 +00:00
|
|
|
|
2003-11-21 14:58:49 +00:00
|
|
|
len = gpa_hfinfo.len;
|
1999-07-15 15:33:52 +00:00
|
|
|
for (i = 0; i < len ; i++) {
|
2003-11-22 04:41:31 +00:00
|
|
|
PROTO_REGISTRAR_GET_NTH(i, hfinfo);
|
1999-07-15 15:33:52 +00:00
|
|
|
|
2001-04-19 23:06:23 +00:00
|
|
|
/*
|
|
|
|
* Skip fields with zero-length names or abbreviations;
|
|
|
|
* the pseudo-field for "proto_tree_add_text()" is such
|
|
|
|
* a field, and we don't want it in the list of filterable
|
|
|
|
* fields.
|
|
|
|
*
|
|
|
|
* XXX - perhaps the name and abbrev field should be null
|
|
|
|
* pointers rather than null strings for that pseudo-field,
|
|
|
|
* but we'd have to add checks for null pointers in some
|
|
|
|
* places if we did that.
|
|
|
|
*
|
|
|
|
* Or perhaps protocol tree items added with
|
|
|
|
* "proto_tree_add_text()" should have -1 as the field index,
|
|
|
|
* with no pseudo-field being used, but that might also
|
|
|
|
* require special checks for -1 to be added.
|
|
|
|
*/
|
2004-09-10 15:21:20 +00:00
|
|
|
/* XXX - we could just skip the special text
|
|
|
|
* pseudo-field by testing: if (hfinfo->id == hf_text_only)
|
|
|
|
* */
|
2003-08-25 00:15:02 +00:00
|
|
|
if (hfinfo->name[0] == 0 || hfinfo->abbrev[0] == 0)
|
2001-04-19 23:06:23 +00:00
|
|
|
continue;
|
|
|
|
|
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 {
|
2001-02-12 10:06:51 +00:00
|
|
|
/*
|
2001-02-13 18:34:51 +00:00
|
|
|
* If this field isn't at the head of the list of
|
|
|
|
* fields with this name, skip this field - all
|
|
|
|
* fields with the same name are really just versions
|
|
|
|
* of the same field stored in different bits, and
|
|
|
|
* should have the same type/radix/value list, and
|
|
|
|
* just differ in their bit masks. (If a field isn't
|
2001-02-12 10:06:51 +00:00
|
|
|
* a bitfield, but can be, say, 1 or 2 bytes long,
|
|
|
|
* it can just be made FT_UINT16, meaning the
|
|
|
|
* *maximum* length is 2 bytes, and be used
|
|
|
|
* for all lengths.)
|
|
|
|
*/
|
2001-02-13 18:34:51 +00:00
|
|
|
if (hfinfo->same_name_prev != NULL)
|
2001-02-12 10:06:51 +00:00
|
|
|
continue;
|
|
|
|
|
2003-11-22 04:41:31 +00:00
|
|
|
PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
|
1999-07-15 15:33:52 +00:00
|
|
|
|
2001-02-01 20:21:25 +00:00
|
|
|
enum_name = ftype_name(hfinfo->type);
|
2004-09-10 15:21:20 +00:00
|
|
|
base_name = "";
|
|
|
|
|
|
|
|
if (format > 1) {
|
|
|
|
if (hfinfo->type == FT_UINT8 ||
|
|
|
|
hfinfo->type == FT_UINT16 ||
|
|
|
|
hfinfo->type == FT_UINT24 ||
|
|
|
|
hfinfo->type == FT_UINT32 ||
|
|
|
|
hfinfo->type == FT_UINT64 ||
|
|
|
|
hfinfo->type == FT_INT8 ||
|
|
|
|
hfinfo->type == FT_INT16 ||
|
|
|
|
hfinfo->type == FT_INT24 ||
|
|
|
|
hfinfo->type == FT_INT32 ||
|
|
|
|
hfinfo->type == FT_INT64) {
|
|
|
|
|
|
|
|
|
|
|
|
switch(hfinfo->display) {
|
|
|
|
case BASE_NONE:
|
|
|
|
base_name = "BASE_NONE";
|
|
|
|
break;
|
|
|
|
case BASE_DEC:
|
|
|
|
base_name = "BASE_DEC";
|
|
|
|
break;
|
|
|
|
case BASE_HEX:
|
|
|
|
base_name = "BASE_HEX";
|
|
|
|
break;
|
|
|
|
case BASE_OCT:
|
|
|
|
base_name = "BASE_OCT";
|
|
|
|
break;
|
2005-09-05 10:56:41 +00:00
|
|
|
case BASE_DEC_HEX:
|
|
|
|
base_name = "BASE_DEC_HEX";
|
|
|
|
break;
|
|
|
|
case BASE_HEX_DEC:
|
|
|
|
base_name = "BASE_HEX_DEC";
|
|
|
|
break;
|
2004-09-10 15:21:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-12-04 04:22:43 +00:00
|
|
|
blurb = hfinfo->blurb;
|
|
|
|
if (blurb == NULL)
|
|
|
|
blurb = "";
|
2004-09-10 15:21:20 +00:00
|
|
|
if (format == 1) {
|
2005-12-04 04:22:43 +00:00
|
|
|
printf("F\t%s\t%s\t%s\t%s\t%s\n",
|
|
|
|
hfinfo->name, hfinfo->abbrev, enum_name,
|
|
|
|
parent_hfinfo->abbrev, blurb);
|
2004-09-10 15:21:20 +00:00
|
|
|
}
|
|
|
|
else if (format == 2) {
|
2004-09-11 22:36:16 +00:00
|
|
|
printf("F\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n",
|
2005-12-04 04:22:43 +00:00
|
|
|
hfinfo->name, hfinfo->abbrev, enum_name,
|
|
|
|
parent_hfinfo->abbrev, blurb,
|
|
|
|
base_name, blurb);
|
2004-09-10 15:21:20 +00:00
|
|
|
}
|
2005-05-27 15:13:09 +00:00
|
|
|
else if (format == 3) {
|
|
|
|
printf("F\t%s\t%s\t%s\t%s\t%s\t%s\t%u\n",
|
2005-12-04 04:22:43 +00:00
|
|
|
hfinfo->name, hfinfo->abbrev, enum_name,
|
|
|
|
parent_hfinfo->abbrev, blurb,
|
2005-05-27 15:13:09 +00:00
|
|
|
base_name, hfinfo->bitmask);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
g_assert_not_reached();
|
|
|
|
}
|
1999-07-15 15:33:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2000-08-30 02:50:18 +00:00
|
|
|
|
2005-08-05 13:23:47 +00:00
|
|
|
static const char*
|
2001-02-01 20:21:25 +00:00
|
|
|
hfinfo_numeric_format(header_field_info *hfinfo)
|
2000-08-30 02:50:18 +00:00
|
|
|
{
|
2005-08-05 13:23:47 +00:00
|
|
|
const char *format = NULL;
|
2000-08-30 02:50:18 +00:00
|
|
|
|
2001-02-01 20:21:25 +00:00
|
|
|
/* Pick the proper format string */
|
2002-12-19 02:58:53 +00:00
|
|
|
if (hfinfo->type == FT_FRAMENUM) {
|
|
|
|
/*
|
|
|
|
* Frame numbers are always displayed in decimal.
|
|
|
|
*/
|
|
|
|
format = "%s == %u";
|
|
|
|
} else {
|
|
|
|
/* Pick the proper format string */
|
|
|
|
switch(hfinfo->display) {
|
|
|
|
case BASE_DEC:
|
2005-09-05 10:56:41 +00:00
|
|
|
case BASE_DEC_HEX:
|
2002-12-19 02:58:53 +00:00
|
|
|
case BASE_OCT: /* I'm lazy */
|
|
|
|
switch(hfinfo->type) {
|
|
|
|
case FT_UINT8:
|
|
|
|
case FT_UINT16:
|
|
|
|
case FT_UINT24:
|
|
|
|
case FT_UINT32:
|
|
|
|
format = "%s == %u";
|
|
|
|
break;
|
2004-08-22 00:31:58 +00:00
|
|
|
case FT_UINT64:
|
|
|
|
format = "%s == %" PRIu64;
|
|
|
|
break;
|
2002-12-19 02:58:53 +00:00
|
|
|
case FT_INT8:
|
|
|
|
case FT_INT16:
|
|
|
|
case FT_INT24:
|
|
|
|
case FT_INT32:
|
|
|
|
format = "%s == %d";
|
|
|
|
break;
|
2004-08-22 00:31:58 +00:00
|
|
|
case FT_INT64:
|
|
|
|
format = "%s == %" PRId64;
|
|
|
|
break;
|
2002-12-19 02:58:53 +00:00
|
|
|
default:
|
2005-03-23 00:09:12 +00:00
|
|
|
DISSECTOR_ASSERT_NOT_REACHED();
|
2002-12-19 02:58:53 +00:00
|
|
|
;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case BASE_HEX:
|
2005-09-05 10:56:41 +00:00
|
|
|
case BASE_HEX_DEC:
|
2002-12-19 02:58:53 +00:00
|
|
|
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:
|
|
|
|
format = "%s == 0x%08x";
|
|
|
|
break;
|
2004-08-22 00:31:58 +00:00
|
|
|
case FT_UINT64:
|
|
|
|
format = "%s == 0x%016" PRIx64;
|
|
|
|
break;
|
2002-12-19 02:58:53 +00:00
|
|
|
default:
|
2005-03-23 00:09:12 +00:00
|
|
|
DISSECTOR_ASSERT_NOT_REACHED();
|
2002-12-19 02:58:53 +00:00
|
|
|
;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
2005-03-23 00:09:12 +00:00
|
|
|
DISSECTOR_ASSERT_NOT_REACHED();
|
2002-12-19 02:58:53 +00:00
|
|
|
;
|
|
|
|
}
|
2001-02-01 20:21:25 +00:00
|
|
|
}
|
|
|
|
return format;
|
|
|
|
}
|
|
|
|
|
Enable "Match Selected" only if there's a field selected *and* we can do
a "Match Selected" on it - we can't do a "Match Selected" if the field
has no value (e.g., FT_NULL) and has a length of 0.
If we unselect the current packet, we don't have a protocol tree, so we
don't have a currently selected field - clear the "Match Selected" menu
item and the display in the status line of information about the
currently selected field.
Move the low-level statusbar manipulation into "gtk/main.c", in routines
whose API doesn't expose anything GTK+-ish.
"close_cap_file()" calls one of those routines to clear out the status
bar, so it doesn't need to take a pointer to the statusbar widget as an
argument.
"clear_tree_and_hex_views()" is purely a display-manipulating routine;
move it to "gtk/proto_draw.c".
Extract from "tree_view_unselect_row_cb()" an "unselect_field()" routine
to do all the work that needs to be done if the currently selected
protocol tree row is unselected, and call it if the currently selected
packet list row is unselected (if it's unselected, there *is* no
protocol tree, so no row can be selected), as well as from
"tree_view_unselect_row_cb()".
Before pushing a new field-description message onto the statusbar, pop
the old one off.
Get rid of an unused variable (set, but not used).
svn path=/trunk/; revision=3513
2001-06-05 07:39:31 +00:00
|
|
|
/*
|
|
|
|
* Returns TRUE if we can do a "match selected" on the field, FALSE
|
|
|
|
* otherwise.
|
|
|
|
*/
|
|
|
|
gboolean
|
Rename "proto_alloc_dfilter_string()" to
"proto_construct_dfilter_string()", to more accurately reflect what it
does.
Give it, and "proto_can_match_selected()", an "epan_dissect_t *"
argument, which replaces the raw data pointer argument to
"proto_construct_dfilter_string()".
For fields that don't have a type we can directly filter on, we don't
support filtering on the field as raw data if:
the "epan_dissect_t *" argument is null;
the data source tvbuff for the field isn't the tvbuff for the
"epan_dissect_t" in question (i.e., it's in the result of a
reassembly, and "frame[N:M]" can't get at it).
Trim the length the raw data in the case of such a field to the length
of the tvbuff for the "epan_dissect_t" in question, so we don't go past
it. Fetch the raw data bytes to match from that tvbuff.
Have "proto_construct_dfilter_string()" return a null pointer if it
can't construct the filter string, and have "protocolinfo_packet()" in
the tap-protocolinfo tap ignore a field if
"proto_construct_dfilter_string()" can't construct a filter string for
it - and have it pass NULL as the "epan_dissect_t *", for now. If
somebody decides it makes sense to dump out a "frame[N:M] =" value for
non-registered fields, it can be changed to pass "edt".
svn path=/trunk/; revision=7635
2003-05-03 00:48:37 +00:00
|
|
|
proto_can_match_selected(field_info *finfo, epan_dissect_t *edt)
|
Enable "Match Selected" only if there's a field selected *and* we can do
a "Match Selected" on it - we can't do a "Match Selected" if the field
has no value (e.g., FT_NULL) and has a length of 0.
If we unselect the current packet, we don't have a protocol tree, so we
don't have a currently selected field - clear the "Match Selected" menu
item and the display in the status line of information about the
currently selected field.
Move the low-level statusbar manipulation into "gtk/main.c", in routines
whose API doesn't expose anything GTK+-ish.
"close_cap_file()" calls one of those routines to clear out the status
bar, so it doesn't need to take a pointer to the statusbar widget as an
argument.
"clear_tree_and_hex_views()" is purely a display-manipulating routine;
move it to "gtk/proto_draw.c".
Extract from "tree_view_unselect_row_cb()" an "unselect_field()" routine
to do all the work that needs to be done if the currently selected
protocol tree row is unselected, and call it if the currently selected
packet list row is unselected (if it's unselected, there *is* no
protocol tree, so no row can be selected), as well as from
"tree_view_unselect_row_cb()".
Before pushing a new field-description message onto the statusbar, pop
the old one off.
Get rid of an unused variable (set, but not used).
svn path=/trunk/; revision=3513
2001-06-05 07:39:31 +00:00
|
|
|
{
|
|
|
|
header_field_info *hfinfo;
|
Rename "proto_alloc_dfilter_string()" to
"proto_construct_dfilter_string()", to more accurately reflect what it
does.
Give it, and "proto_can_match_selected()", an "epan_dissect_t *"
argument, which replaces the raw data pointer argument to
"proto_construct_dfilter_string()".
For fields that don't have a type we can directly filter on, we don't
support filtering on the field as raw data if:
the "epan_dissect_t *" argument is null;
the data source tvbuff for the field isn't the tvbuff for the
"epan_dissect_t" in question (i.e., it's in the result of a
reassembly, and "frame[N:M]" can't get at it).
Trim the length the raw data in the case of such a field to the length
of the tvbuff for the "epan_dissect_t" in question, so we don't go past
it. Fetch the raw data bytes to match from that tvbuff.
Have "proto_construct_dfilter_string()" return a null pointer if it
can't construct the filter string, and have "protocolinfo_packet()" in
the tap-protocolinfo tap ignore a field if
"proto_construct_dfilter_string()" can't construct a filter string for
it - and have it pass NULL as the "epan_dissect_t *", for now. If
somebody decides it makes sense to dump out a "frame[N:M] =" value for
non-registered fields, it can be changed to pass "edt".
svn path=/trunk/; revision=7635
2003-05-03 00:48:37 +00:00
|
|
|
gint length;
|
Enable "Match Selected" only if there's a field selected *and* we can do
a "Match Selected" on it - we can't do a "Match Selected" if the field
has no value (e.g., FT_NULL) and has a length of 0.
If we unselect the current packet, we don't have a protocol tree, so we
don't have a currently selected field - clear the "Match Selected" menu
item and the display in the status line of information about the
currently selected field.
Move the low-level statusbar manipulation into "gtk/main.c", in routines
whose API doesn't expose anything GTK+-ish.
"close_cap_file()" calls one of those routines to clear out the status
bar, so it doesn't need to take a pointer to the statusbar widget as an
argument.
"clear_tree_and_hex_views()" is purely a display-manipulating routine;
move it to "gtk/proto_draw.c".
Extract from "tree_view_unselect_row_cb()" an "unselect_field()" routine
to do all the work that needs to be done if the currently selected
protocol tree row is unselected, and call it if the currently selected
packet list row is unselected (if it's unselected, there *is* no
protocol tree, so no row can be selected), as well as from
"tree_view_unselect_row_cb()".
Before pushing a new field-description message onto the statusbar, pop
the old one off.
Get rid of an unused variable (set, but not used).
svn path=/trunk/; revision=3513
2001-06-05 07:39:31 +00:00
|
|
|
|
2003-12-03 09:28:26 +00:00
|
|
|
hfinfo = finfo->hfinfo;
|
2005-03-23 00:09:12 +00:00
|
|
|
DISSECTOR_ASSERT(hfinfo);
|
Enable "Match Selected" only if there's a field selected *and* we can do
a "Match Selected" on it - we can't do a "Match Selected" if the field
has no value (e.g., FT_NULL) and has a length of 0.
If we unselect the current packet, we don't have a protocol tree, so we
don't have a currently selected field - clear the "Match Selected" menu
item and the display in the status line of information about the
currently selected field.
Move the low-level statusbar manipulation into "gtk/main.c", in routines
whose API doesn't expose anything GTK+-ish.
"close_cap_file()" calls one of those routines to clear out the status
bar, so it doesn't need to take a pointer to the statusbar widget as an
argument.
"clear_tree_and_hex_views()" is purely a display-manipulating routine;
move it to "gtk/proto_draw.c".
Extract from "tree_view_unselect_row_cb()" an "unselect_field()" routine
to do all the work that needs to be done if the currently selected
protocol tree row is unselected, and call it if the currently selected
packet list row is unselected (if it's unselected, there *is* no
protocol tree, so no row can be selected), as well as from
"tree_view_unselect_row_cb()".
Before pushing a new field-description message onto the statusbar, pop
the old one off.
Get rid of an unused variable (set, but not used).
svn path=/trunk/; revision=3513
2001-06-05 07:39:31 +00:00
|
|
|
|
|
|
|
switch(hfinfo->type) {
|
|
|
|
|
|
|
|
case FT_BOOLEAN:
|
|
|
|
case FT_UINT8:
|
|
|
|
case FT_UINT16:
|
|
|
|
case FT_UINT24:
|
|
|
|
case FT_UINT32:
|
|
|
|
case FT_INT8:
|
|
|
|
case FT_INT16:
|
|
|
|
case FT_INT24:
|
|
|
|
case FT_INT32:
|
Rename "proto_alloc_dfilter_string()" to
"proto_construct_dfilter_string()", to more accurately reflect what it
does.
Give it, and "proto_can_match_selected()", an "epan_dissect_t *"
argument, which replaces the raw data pointer argument to
"proto_construct_dfilter_string()".
For fields that don't have a type we can directly filter on, we don't
support filtering on the field as raw data if:
the "epan_dissect_t *" argument is null;
the data source tvbuff for the field isn't the tvbuff for the
"epan_dissect_t" in question (i.e., it's in the result of a
reassembly, and "frame[N:M]" can't get at it).
Trim the length the raw data in the case of such a field to the length
of the tvbuff for the "epan_dissect_t" in question, so we don't go past
it. Fetch the raw data bytes to match from that tvbuff.
Have "proto_construct_dfilter_string()" return a null pointer if it
can't construct the filter string, and have "protocolinfo_packet()" in
the tap-protocolinfo tap ignore a field if
"proto_construct_dfilter_string()" can't construct a filter string for
it - and have it pass NULL as the "epan_dissect_t *", for now. If
somebody decides it makes sense to dump out a "frame[N:M] =" value for
non-registered fields, it can be changed to pass "edt".
svn path=/trunk/; revision=7635
2003-05-03 00:48:37 +00:00
|
|
|
case FT_FRAMENUM:
|
|
|
|
case FT_UINT64:
|
2001-11-02 10:09:51 +00:00
|
|
|
case FT_INT64:
|
Enable "Match Selected" only if there's a field selected *and* we can do
a "Match Selected" on it - we can't do a "Match Selected" if the field
has no value (e.g., FT_NULL) and has a length of 0.
If we unselect the current packet, we don't have a protocol tree, so we
don't have a currently selected field - clear the "Match Selected" menu
item and the display in the status line of information about the
currently selected field.
Move the low-level statusbar manipulation into "gtk/main.c", in routines
whose API doesn't expose anything GTK+-ish.
"close_cap_file()" calls one of those routines to clear out the status
bar, so it doesn't need to take a pointer to the statusbar widget as an
argument.
"clear_tree_and_hex_views()" is purely a display-manipulating routine;
move it to "gtk/proto_draw.c".
Extract from "tree_view_unselect_row_cb()" an "unselect_field()" routine
to do all the work that needs to be done if the currently selected
protocol tree row is unselected, and call it if the currently selected
packet list row is unselected (if it's unselected, there *is* no
protocol tree, so no row can be selected), as well as from
"tree_view_unselect_row_cb()".
Before pushing a new field-description message onto the statusbar, pop
the old one off.
Get rid of an unused variable (set, but not used).
svn path=/trunk/; revision=3513
2001-06-05 07:39:31 +00:00
|
|
|
case FT_IPv4:
|
|
|
|
case FT_IPXNET:
|
|
|
|
case FT_IPv6:
|
2002-08-24 19:45:28 +00:00
|
|
|
case FT_FLOAT:
|
Enable "Match Selected" only if there's a field selected *and* we can do
a "Match Selected" on it - we can't do a "Match Selected" if the field
has no value (e.g., FT_NULL) and has a length of 0.
If we unselect the current packet, we don't have a protocol tree, so we
don't have a currently selected field - clear the "Match Selected" menu
item and the display in the status line of information about the
currently selected field.
Move the low-level statusbar manipulation into "gtk/main.c", in routines
whose API doesn't expose anything GTK+-ish.
"close_cap_file()" calls one of those routines to clear out the status
bar, so it doesn't need to take a pointer to the statusbar widget as an
argument.
"clear_tree_and_hex_views()" is purely a display-manipulating routine;
move it to "gtk/proto_draw.c".
Extract from "tree_view_unselect_row_cb()" an "unselect_field()" routine
to do all the work that needs to be done if the currently selected
protocol tree row is unselected, and call it if the currently selected
packet list row is unselected (if it's unselected, there *is* no
protocol tree, so no row can be selected), as well as from
"tree_view_unselect_row_cb()".
Before pushing a new field-description message onto the statusbar, pop
the old one off.
Get rid of an unused variable (set, but not used).
svn path=/trunk/; revision=3513
2001-06-05 07:39:31 +00:00
|
|
|
case FT_DOUBLE:
|
|
|
|
case FT_ABSOLUTE_TIME:
|
|
|
|
case FT_RELATIVE_TIME:
|
|
|
|
case FT_STRING:
|
2002-05-09 23:50:34 +00:00
|
|
|
case FT_STRINGZ:
|
|
|
|
case FT_UINT_STRING:
|
Rename "proto_alloc_dfilter_string()" to
"proto_construct_dfilter_string()", to more accurately reflect what it
does.
Give it, and "proto_can_match_selected()", an "epan_dissect_t *"
argument, which replaces the raw data pointer argument to
"proto_construct_dfilter_string()".
For fields that don't have a type we can directly filter on, we don't
support filtering on the field as raw data if:
the "epan_dissect_t *" argument is null;
the data source tvbuff for the field isn't the tvbuff for the
"epan_dissect_t" in question (i.e., it's in the result of a
reassembly, and "frame[N:M]" can't get at it).
Trim the length the raw data in the case of such a field to the length
of the tvbuff for the "epan_dissect_t" in question, so we don't go past
it. Fetch the raw data bytes to match from that tvbuff.
Have "proto_construct_dfilter_string()" return a null pointer if it
can't construct the filter string, and have "protocolinfo_packet()" in
the tap-protocolinfo tap ignore a field if
"proto_construct_dfilter_string()" can't construct a filter string for
it - and have it pass NULL as the "epan_dissect_t *", for now. If
somebody decides it makes sense to dump out a "frame[N:M] =" value for
non-registered fields, it can be changed to pass "edt".
svn path=/trunk/; revision=7635
2003-05-03 00:48:37 +00:00
|
|
|
case FT_ETHER:
|
Enable "Match Selected" only if there's a field selected *and* we can do
a "Match Selected" on it - we can't do a "Match Selected" if the field
has no value (e.g., FT_NULL) and has a length of 0.
If we unselect the current packet, we don't have a protocol tree, so we
don't have a currently selected field - clear the "Match Selected" menu
item and the display in the status line of information about the
currently selected field.
Move the low-level statusbar manipulation into "gtk/main.c", in routines
whose API doesn't expose anything GTK+-ish.
"close_cap_file()" calls one of those routines to clear out the status
bar, so it doesn't need to take a pointer to the statusbar widget as an
argument.
"clear_tree_and_hex_views()" is purely a display-manipulating routine;
move it to "gtk/proto_draw.c".
Extract from "tree_view_unselect_row_cb()" an "unselect_field()" routine
to do all the work that needs to be done if the currently selected
protocol tree row is unselected, and call it if the currently selected
packet list row is unselected (if it's unselected, there *is* no
protocol tree, so no row can be selected), as well as from
"tree_view_unselect_row_cb()".
Before pushing a new field-description message onto the statusbar, pop
the old one off.
Get rid of an unused variable (set, but not used).
svn path=/trunk/; revision=3513
2001-06-05 07:39:31 +00:00
|
|
|
case FT_BYTES:
|
2002-05-09 23:50:34 +00:00
|
|
|
case FT_UINT_BYTES:
|
2003-06-11 21:24:54 +00:00
|
|
|
case FT_PROTOCOL:
|
2005-07-04 13:04:53 +00:00
|
|
|
case FT_GUID:
|
2005-12-02 13:16:58 +00:00
|
|
|
case FT_OID:
|
Enable "Match Selected" only if there's a field selected *and* we can do
a "Match Selected" on it - we can't do a "Match Selected" if the field
has no value (e.g., FT_NULL) and has a length of 0.
If we unselect the current packet, we don't have a protocol tree, so we
don't have a currently selected field - clear the "Match Selected" menu
item and the display in the status line of information about the
currently selected field.
Move the low-level statusbar manipulation into "gtk/main.c", in routines
whose API doesn't expose anything GTK+-ish.
"close_cap_file()" calls one of those routines to clear out the status
bar, so it doesn't need to take a pointer to the statusbar widget as an
argument.
"clear_tree_and_hex_views()" is purely a display-manipulating routine;
move it to "gtk/proto_draw.c".
Extract from "tree_view_unselect_row_cb()" an "unselect_field()" routine
to do all the work that needs to be done if the currently selected
protocol tree row is unselected, and call it if the currently selected
packet list row is unselected (if it's unselected, there *is* no
protocol tree, so no row can be selected), as well as from
"tree_view_unselect_row_cb()".
Before pushing a new field-description message onto the statusbar, pop
the old one off.
Get rid of an unused variable (set, but not used).
svn path=/trunk/; revision=3513
2001-06-05 07:39:31 +00:00
|
|
|
/*
|
|
|
|
* These all have values, so we can match.
|
|
|
|
*/
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
default:
|
|
|
|
/*
|
|
|
|
* This doesn't have a value, so we'd match
|
Rename "proto_alloc_dfilter_string()" to
"proto_construct_dfilter_string()", to more accurately reflect what it
does.
Give it, and "proto_can_match_selected()", an "epan_dissect_t *"
argument, which replaces the raw data pointer argument to
"proto_construct_dfilter_string()".
For fields that don't have a type we can directly filter on, we don't
support filtering on the field as raw data if:
the "epan_dissect_t *" argument is null;
the data source tvbuff for the field isn't the tvbuff for the
"epan_dissect_t" in question (i.e., it's in the result of a
reassembly, and "frame[N:M]" can't get at it).
Trim the length the raw data in the case of such a field to the length
of the tvbuff for the "epan_dissect_t" in question, so we don't go past
it. Fetch the raw data bytes to match from that tvbuff.
Have "proto_construct_dfilter_string()" return a null pointer if it
can't construct the filter string, and have "protocolinfo_packet()" in
the tap-protocolinfo tap ignore a field if
"proto_construct_dfilter_string()" can't construct a filter string for
it - and have it pass NULL as the "epan_dissect_t *", for now. If
somebody decides it makes sense to dump out a "frame[N:M] =" value for
non-registered fields, it can be changed to pass "edt".
svn path=/trunk/; revision=7635
2003-05-03 00:48:37 +00:00
|
|
|
* on the raw bytes at this address.
|
|
|
|
*
|
|
|
|
* Should we be allowed to access to the raw bytes?
|
|
|
|
* If "edt" is NULL, the answer is "no".
|
Enable "Match Selected" only if there's a field selected *and* we can do
a "Match Selected" on it - we can't do a "Match Selected" if the field
has no value (e.g., FT_NULL) and has a length of 0.
If we unselect the current packet, we don't have a protocol tree, so we
don't have a currently selected field - clear the "Match Selected" menu
item and the display in the status line of information about the
currently selected field.
Move the low-level statusbar manipulation into "gtk/main.c", in routines
whose API doesn't expose anything GTK+-ish.
"close_cap_file()" calls one of those routines to clear out the status
bar, so it doesn't need to take a pointer to the statusbar widget as an
argument.
"clear_tree_and_hex_views()" is purely a display-manipulating routine;
move it to "gtk/proto_draw.c".
Extract from "tree_view_unselect_row_cb()" an "unselect_field()" routine
to do all the work that needs to be done if the currently selected
protocol tree row is unselected, and call it if the currently selected
packet list row is unselected (if it's unselected, there *is* no
protocol tree, so no row can be selected), as well as from
"tree_view_unselect_row_cb()".
Before pushing a new field-description message onto the statusbar, pop
the old one off.
Get rid of an unused variable (set, but not used).
svn path=/trunk/; revision=3513
2001-06-05 07:39:31 +00:00
|
|
|
*/
|
Rename "proto_alloc_dfilter_string()" to
"proto_construct_dfilter_string()", to more accurately reflect what it
does.
Give it, and "proto_can_match_selected()", an "epan_dissect_t *"
argument, which replaces the raw data pointer argument to
"proto_construct_dfilter_string()".
For fields that don't have a type we can directly filter on, we don't
support filtering on the field as raw data if:
the "epan_dissect_t *" argument is null;
the data source tvbuff for the field isn't the tvbuff for the
"epan_dissect_t" in question (i.e., it's in the result of a
reassembly, and "frame[N:M]" can't get at it).
Trim the length the raw data in the case of such a field to the length
of the tvbuff for the "epan_dissect_t" in question, so we don't go past
it. Fetch the raw data bytes to match from that tvbuff.
Have "proto_construct_dfilter_string()" return a null pointer if it
can't construct the filter string, and have "protocolinfo_packet()" in
the tap-protocolinfo tap ignore a field if
"proto_construct_dfilter_string()" can't construct a filter string for
it - and have it pass NULL as the "epan_dissect_t *", for now. If
somebody decides it makes sense to dump out a "frame[N:M] =" value for
non-registered fields, it can be changed to pass "edt".
svn path=/trunk/; revision=7635
2003-05-03 00:48:37 +00:00
|
|
|
if (edt == NULL)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Is this field part of the raw frame tvbuff?
|
|
|
|
* If not, we can't use "frame[N:M]" to match
|
|
|
|
* it.
|
|
|
|
*
|
|
|
|
* XXX - should this be frame-relative, or
|
|
|
|
* protocol-relative?
|
|
|
|
*
|
|
|
|
* XXX - does this fallback for non-registered
|
|
|
|
* fields even make sense?
|
|
|
|
*/
|
|
|
|
if (finfo->ds_tvb != edt->tvb)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If the length is 0, there's nothing to match, so
|
|
|
|
* we can't match. (Also check for negative values,
|
|
|
|
* just in case, as we'll cast it to an unsigned
|
|
|
|
* value later.)
|
|
|
|
*/
|
|
|
|
length = finfo->length;
|
|
|
|
if (length <= 0)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Don't go past the end of that tvbuff.
|
|
|
|
*/
|
|
|
|
if ((guint)length > tvb_length(finfo->ds_tvb))
|
|
|
|
length = tvb_length(finfo->ds_tvb);
|
|
|
|
if (length <= 0)
|
|
|
|
return FALSE;
|
|
|
|
return TRUE;
|
Enable "Match Selected" only if there's a field selected *and* we can do
a "Match Selected" on it - we can't do a "Match Selected" if the field
has no value (e.g., FT_NULL) and has a length of 0.
If we unselect the current packet, we don't have a protocol tree, so we
don't have a currently selected field - clear the "Match Selected" menu
item and the display in the status line of information about the
currently selected field.
Move the low-level statusbar manipulation into "gtk/main.c", in routines
whose API doesn't expose anything GTK+-ish.
"close_cap_file()" calls one of those routines to clear out the status
bar, so it doesn't need to take a pointer to the statusbar widget as an
argument.
"clear_tree_and_hex_views()" is purely a display-manipulating routine;
move it to "gtk/proto_draw.c".
Extract from "tree_view_unselect_row_cb()" an "unselect_field()" routine
to do all the work that needs to be done if the currently selected
protocol tree row is unselected, and call it if the currently selected
packet list row is unselected (if it's unselected, there *is* no
protocol tree, so no row can be selected), as well as from
"tree_view_unselect_row_cb()".
Before pushing a new field-description message onto the statusbar, pop
the old one off.
Get rid of an unused variable (set, but not used).
svn path=/trunk/; revision=3513
2001-06-05 07:39:31 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-09-01 09:03:29 +00:00
|
|
|
/* This function returns a string allocated with packet lifetime scope.
|
2005-10-31 02:42:22 +00:00
|
|
|
* You do not need to [g_]free() this string since it will be automatically
|
2005-09-01 09:03:29 +00:00
|
|
|
* freed once the next packet is dissected.
|
|
|
|
*/
|
2001-02-01 20:21:25 +00:00
|
|
|
char*
|
Rename "proto_alloc_dfilter_string()" to
"proto_construct_dfilter_string()", to more accurately reflect what it
does.
Give it, and "proto_can_match_selected()", an "epan_dissect_t *"
argument, which replaces the raw data pointer argument to
"proto_construct_dfilter_string()".
For fields that don't have a type we can directly filter on, we don't
support filtering on the field as raw data if:
the "epan_dissect_t *" argument is null;
the data source tvbuff for the field isn't the tvbuff for the
"epan_dissect_t" in question (i.e., it's in the result of a
reassembly, and "frame[N:M]" can't get at it).
Trim the length the raw data in the case of such a field to the length
of the tvbuff for the "epan_dissect_t" in question, so we don't go past
it. Fetch the raw data bytes to match from that tvbuff.
Have "proto_construct_dfilter_string()" return a null pointer if it
can't construct the filter string, and have "protocolinfo_packet()" in
the tap-protocolinfo tap ignore a field if
"proto_construct_dfilter_string()" can't construct a filter string for
it - and have it pass NULL as the "epan_dissect_t *", for now. If
somebody decides it makes sense to dump out a "frame[N:M] =" value for
non-registered fields, it can be changed to pass "edt".
svn path=/trunk/; revision=7635
2003-05-03 00:48:37 +00:00
|
|
|
proto_construct_dfilter_string(field_info *finfo, epan_dissect_t *edt)
|
2001-02-01 20:21:25 +00:00
|
|
|
{
|
|
|
|
header_field_info *hfinfo;
|
|
|
|
int abbrev_len;
|
2005-11-02 20:50:54 +00:00
|
|
|
char *buf, *ptr;
|
2005-09-01 09:29:21 +00:00
|
|
|
int buf_len;
|
2005-08-05 13:23:47 +00:00
|
|
|
const char *format;
|
2001-02-01 20:21:25 +00:00
|
|
|
int dfilter_len, i;
|
2004-07-09 21:52:03 +00:00
|
|
|
gint start, length, length_remaining;
|
Rename "proto_alloc_dfilter_string()" to
"proto_construct_dfilter_string()", to more accurately reflect what it
does.
Give it, and "proto_can_match_selected()", an "epan_dissect_t *"
argument, which replaces the raw data pointer argument to
"proto_construct_dfilter_string()".
For fields that don't have a type we can directly filter on, we don't
support filtering on the field as raw data if:
the "epan_dissect_t *" argument is null;
the data source tvbuff for the field isn't the tvbuff for the
"epan_dissect_t" in question (i.e., it's in the result of a
reassembly, and "frame[N:M]" can't get at it).
Trim the length the raw data in the case of such a field to the length
of the tvbuff for the "epan_dissect_t" in question, so we don't go past
it. Fetch the raw data bytes to match from that tvbuff.
Have "proto_construct_dfilter_string()" return a null pointer if it
can't construct the filter string, and have "protocolinfo_packet()" in
the tap-protocolinfo tap ignore a field if
"proto_construct_dfilter_string()" can't construct a filter string for
it - and have it pass NULL as the "epan_dissect_t *", for now. If
somebody decides it makes sense to dump out a "frame[N:M] =" value for
non-registered fields, it can be changed to pass "edt".
svn path=/trunk/; revision=7635
2003-05-03 00:48:37 +00:00
|
|
|
guint8 c;
|
2001-02-01 20:21:25 +00:00
|
|
|
|
2003-12-03 09:28:26 +00:00
|
|
|
hfinfo = finfo->hfinfo;
|
2005-03-23 00:09:12 +00:00
|
|
|
DISSECTOR_ASSERT(hfinfo);
|
2001-02-01 20:21:25 +00:00
|
|
|
abbrev_len = strlen(hfinfo->abbrev);
|
|
|
|
|
2003-05-03 01:11:29 +00:00
|
|
|
/*
|
2005-10-31 02:42:22 +00:00
|
|
|
* XXX - we can't use the "val_to_string_repr" and "string_repr_len"
|
|
|
|
* functions for FT_UINT and FT_INT types, as we choose the base in
|
|
|
|
* the string expression based on the display base of the field.
|
2003-05-03 01:11:29 +00:00
|
|
|
*
|
|
|
|
* Note that the base does matter, as this is also used for
|
|
|
|
* the protocolinfo tap.
|
|
|
|
*
|
2005-10-31 02:42:22 +00:00
|
|
|
* It might be nice to use them in "proto_item_fill_label()"
|
2003-05-03 01:11:29 +00:00
|
|
|
* as well, although, there, you'd have to deal with the base
|
|
|
|
* *and* with resolved values for addresses.
|
|
|
|
*
|
|
|
|
* Perhaps we need two different val_to_string routines, one
|
|
|
|
* to generate items for display filters and one to generate
|
|
|
|
* strings for display, and pass to both of them the
|
|
|
|
* "display" and "strings" values in the header_field_info
|
|
|
|
* structure for the field, so they can get the base and,
|
|
|
|
* if the field is Boolean or an enumerated integer type,
|
|
|
|
* the tables used to generate human-readable values.
|
|
|
|
*/
|
2001-02-01 20:21:25 +00:00
|
|
|
switch(hfinfo->type) {
|
|
|
|
|
2000-08-30 02:50:18 +00:00
|
|
|
case FT_UINT8:
|
|
|
|
case FT_UINT16:
|
|
|
|
case FT_UINT24:
|
|
|
|
case FT_UINT32:
|
|
|
|
case FT_INT8:
|
|
|
|
case FT_INT16:
|
|
|
|
case FT_INT24:
|
|
|
|
case FT_INT32:
|
2002-12-19 02:58:53 +00:00
|
|
|
case FT_FRAMENUM:
|
2002-08-24 19:45:28 +00:00
|
|
|
/*
|
|
|
|
* 4 bytes for " == ".
|
|
|
|
* 11 bytes for:
|
|
|
|
*
|
|
|
|
* a sign + up to 10 digits of 32-bit integer,
|
|
|
|
* in decimal;
|
|
|
|
*
|
|
|
|
* "0x" + 8 digits of 32-bit integer, in hex;
|
|
|
|
*
|
|
|
|
* 11 digits of 32-bit integer, in octal.
|
|
|
|
* (No, we don't do octal, but this way,
|
|
|
|
* we know that if we do, this will still
|
|
|
|
* work.)
|
|
|
|
*
|
|
|
|
* 1 byte for the trailing '\0'.
|
|
|
|
*/
|
|
|
|
dfilter_len = abbrev_len + 4 + 11 + 1;
|
2005-09-01 09:03:29 +00:00
|
|
|
buf = ep_alloc0(dfilter_len);
|
2001-02-01 20:21:25 +00:00
|
|
|
format = hfinfo_numeric_format(hfinfo);
|
2005-08-17 23:10:28 +00:00
|
|
|
g_snprintf(buf, dfilter_len, format, hfinfo->abbrev, fvalue_get_integer(&finfo->value));
|
2000-08-30 02:50:18 +00:00
|
|
|
break;
|
2001-02-01 20:21:25 +00:00
|
|
|
|
2001-11-02 10:09:51 +00:00
|
|
|
case FT_INT64:
|
2004-08-22 00:31:58 +00:00
|
|
|
case FT_UINT64:
|
2002-08-24 19:45:28 +00:00
|
|
|
/*
|
|
|
|
* 4 bytes for " == ".
|
2004-08-22 00:31:58 +00:00
|
|
|
* 22 bytes for:
|
|
|
|
*
|
|
|
|
* a sign + up to 20 digits of 32-bit integer,
|
|
|
|
* in decimal;
|
|
|
|
*
|
|
|
|
* "0x" + 16 digits of 32-bit integer, in hex;
|
|
|
|
*
|
|
|
|
* 22 digits of 32-bit integer, in octal.
|
|
|
|
* (No, we don't do octal, but this way,
|
|
|
|
* we know that if we do, this will still
|
|
|
|
* work.)
|
|
|
|
*
|
2002-08-24 19:45:28 +00:00
|
|
|
* 1 byte for the trailing '\0'.
|
|
|
|
*/
|
2004-08-22 00:31:58 +00:00
|
|
|
dfilter_len = abbrev_len + 4 + 22 + 1;
|
2005-09-01 09:03:29 +00:00
|
|
|
buf = ep_alloc0(dfilter_len);
|
2004-08-22 00:31:58 +00:00
|
|
|
format = hfinfo_numeric_format(hfinfo);
|
2005-08-17 23:10:28 +00:00
|
|
|
g_snprintf(buf, dfilter_len, format, hfinfo->abbrev, fvalue_get_integer64(&finfo->value));
|
2001-11-02 10:09:51 +00:00
|
|
|
break;
|
|
|
|
|
2003-06-11 21:24:54 +00:00
|
|
|
/* These use the fvalue's "to_string_repr" method. */
|
2005-10-31 02:42:22 +00:00
|
|
|
case FT_IPXNET:
|
2003-06-11 21:24:54 +00:00
|
|
|
case FT_BOOLEAN:
|
|
|
|
case FT_STRING:
|
2003-02-08 04:22:37 +00:00
|
|
|
case FT_ETHER:
|
2001-05-09 01:22:46 +00:00
|
|
|
case FT_BYTES:
|
2002-05-09 23:50:34 +00:00
|
|
|
case FT_UINT_BYTES:
|
2003-07-31 03:52:43 +00:00
|
|
|
case FT_FLOAT:
|
|
|
|
case FT_DOUBLE:
|
2003-07-30 22:50:39 +00:00
|
|
|
case FT_ABSOLUTE_TIME:
|
|
|
|
case FT_RELATIVE_TIME:
|
2003-07-31 04:18:01 +00:00
|
|
|
case FT_IPv4:
|
2005-10-31 02:42:22 +00:00
|
|
|
case FT_IPv6:
|
2005-07-04 13:04:53 +00:00
|
|
|
case FT_GUID:
|
2005-12-02 13:16:58 +00:00
|
|
|
case FT_OID:
|
2003-06-11 21:24:54 +00:00
|
|
|
/* Figure out the string length needed.
|
|
|
|
* The ft_repr length.
|
|
|
|
* 4 bytes for " == ".
|
|
|
|
* 1 byte for trailing NUL.
|
2002-08-24 19:45:28 +00:00
|
|
|
*/
|
2003-12-02 21:15:49 +00:00
|
|
|
dfilter_len = fvalue_string_repr_len(&finfo->value,
|
2003-06-11 21:24:54 +00:00
|
|
|
FTREPR_DFILTER);
|
2003-02-08 04:22:37 +00:00
|
|
|
dfilter_len += abbrev_len + 4 + 1;
|
2005-09-01 09:03:29 +00:00
|
|
|
buf = ep_alloc0(dfilter_len);
|
2003-06-11 21:24:54 +00:00
|
|
|
|
|
|
|
/* Create the string */
|
2005-08-17 23:10:28 +00:00
|
|
|
g_snprintf(buf, dfilter_len, "%s == ", hfinfo->abbrev);
|
2003-12-02 21:15:49 +00:00
|
|
|
fvalue_to_string_repr(&finfo->value,
|
2003-06-11 21:24:54 +00:00
|
|
|
FTREPR_DFILTER,
|
|
|
|
&buf[abbrev_len + 4]);
|
2002-08-28 20:41:00 +00:00
|
|
|
break;
|
2001-05-31 07:15:23 +00:00
|
|
|
|
2003-06-11 21:24:54 +00:00
|
|
|
case FT_PROTOCOL:
|
2005-09-01 09:03:29 +00:00
|
|
|
buf = ep_strdup(finfo->hfinfo->abbrev);
|
2003-06-11 21:48:39 +00:00
|
|
|
break;
|
2003-06-11 21:24:54 +00:00
|
|
|
|
2001-02-01 20:21:25 +00:00
|
|
|
default:
|
Rename "proto_alloc_dfilter_string()" to
"proto_construct_dfilter_string()", to more accurately reflect what it
does.
Give it, and "proto_can_match_selected()", an "epan_dissect_t *"
argument, which replaces the raw data pointer argument to
"proto_construct_dfilter_string()".
For fields that don't have a type we can directly filter on, we don't
support filtering on the field as raw data if:
the "epan_dissect_t *" argument is null;
the data source tvbuff for the field isn't the tvbuff for the
"epan_dissect_t" in question (i.e., it's in the result of a
reassembly, and "frame[N:M]" can't get at it).
Trim the length the raw data in the case of such a field to the length
of the tvbuff for the "epan_dissect_t" in question, so we don't go past
it. Fetch the raw data bytes to match from that tvbuff.
Have "proto_construct_dfilter_string()" return a null pointer if it
can't construct the filter string, and have "protocolinfo_packet()" in
the tap-protocolinfo tap ignore a field if
"proto_construct_dfilter_string()" can't construct a filter string for
it - and have it pass NULL as the "epan_dissect_t *", for now. If
somebody decides it makes sense to dump out a "frame[N:M] =" value for
non-registered fields, it can be changed to pass "edt".
svn path=/trunk/; revision=7635
2003-05-03 00:48:37 +00:00
|
|
|
/*
|
|
|
|
* This doesn't have a value, so we'd match
|
|
|
|
* on the raw bytes at this address.
|
|
|
|
*
|
|
|
|
* Should we be allowed to access to the raw bytes?
|
|
|
|
* If "edt" is NULL, the answer is "no".
|
|
|
|
*/
|
|
|
|
if (edt == NULL)
|
2005-09-01 09:03:29 +00:00
|
|
|
return NULL;
|
Rename "proto_alloc_dfilter_string()" to
"proto_construct_dfilter_string()", to more accurately reflect what it
does.
Give it, and "proto_can_match_selected()", an "epan_dissect_t *"
argument, which replaces the raw data pointer argument to
"proto_construct_dfilter_string()".
For fields that don't have a type we can directly filter on, we don't
support filtering on the field as raw data if:
the "epan_dissect_t *" argument is null;
the data source tvbuff for the field isn't the tvbuff for the
"epan_dissect_t" in question (i.e., it's in the result of a
reassembly, and "frame[N:M]" can't get at it).
Trim the length the raw data in the case of such a field to the length
of the tvbuff for the "epan_dissect_t" in question, so we don't go past
it. Fetch the raw data bytes to match from that tvbuff.
Have "proto_construct_dfilter_string()" return a null pointer if it
can't construct the filter string, and have "protocolinfo_packet()" in
the tap-protocolinfo tap ignore a field if
"proto_construct_dfilter_string()" can't construct a filter string for
it - and have it pass NULL as the "epan_dissect_t *", for now. If
somebody decides it makes sense to dump out a "frame[N:M] =" value for
non-registered fields, it can be changed to pass "edt".
svn path=/trunk/; revision=7635
2003-05-03 00:48:37 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Is this field part of the raw frame tvbuff?
|
|
|
|
* If not, we can't use "frame[N:M]" to match
|
|
|
|
* it.
|
|
|
|
*
|
|
|
|
* XXX - should this be frame-relative, or
|
|
|
|
* protocol-relative?
|
|
|
|
*
|
|
|
|
* XXX - does this fallback for non-registered
|
|
|
|
* fields even make sense?
|
|
|
|
*/
|
|
|
|
if (finfo->ds_tvb != edt->tvb)
|
|
|
|
return NULL; /* you lose */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If the length is 0, there's nothing to match, so
|
|
|
|
* we can't match. (Also check for negative values,
|
|
|
|
* just in case, as we'll cast it to an unsigned
|
|
|
|
* value later.)
|
|
|
|
*/
|
|
|
|
length = finfo->length;
|
|
|
|
if (length <= 0)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Don't go past the end of that tvbuff.
|
|
|
|
*/
|
2004-07-09 21:52:03 +00:00
|
|
|
length_remaining = tvb_length_remaining(finfo->ds_tvb, finfo->start);
|
|
|
|
if (length > length_remaining)
|
|
|
|
length = length_remaining;
|
Rename "proto_alloc_dfilter_string()" to
"proto_construct_dfilter_string()", to more accurately reflect what it
does.
Give it, and "proto_can_match_selected()", an "epan_dissect_t *"
argument, which replaces the raw data pointer argument to
"proto_construct_dfilter_string()".
For fields that don't have a type we can directly filter on, we don't
support filtering on the field as raw data if:
the "epan_dissect_t *" argument is null;
the data source tvbuff for the field isn't the tvbuff for the
"epan_dissect_t" in question (i.e., it's in the result of a
reassembly, and "frame[N:M]" can't get at it).
Trim the length the raw data in the case of such a field to the length
of the tvbuff for the "epan_dissect_t" in question, so we don't go past
it. Fetch the raw data bytes to match from that tvbuff.
Have "proto_construct_dfilter_string()" return a null pointer if it
can't construct the filter string, and have "protocolinfo_packet()" in
the tap-protocolinfo tap ignore a field if
"proto_construct_dfilter_string()" can't construct a filter string for
it - and have it pass NULL as the "epan_dissect_t *", for now. If
somebody decides it makes sense to dump out a "frame[N:M] =" value for
non-registered fields, it can be changed to pass "edt".
svn path=/trunk/; revision=7635
2003-05-03 00:48:37 +00:00
|
|
|
if (length <= 0)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
start = finfo->start;
|
2005-09-01 09:29:21 +00:00
|
|
|
buf_len = 32 + length * 3;
|
|
|
|
buf = ep_alloc0(buf_len);
|
2001-05-09 01:22:46 +00:00
|
|
|
ptr = buf;
|
|
|
|
|
2005-09-01 09:29:21 +00:00
|
|
|
ptr += g_snprintf(ptr, buf_len-(ptr-buf), "frame[%d:%d] == ", finfo->start, length);
|
2004-07-09 21:52:03 +00:00
|
|
|
for (i=0;i<length; i++) {
|
Rename "proto_alloc_dfilter_string()" to
"proto_construct_dfilter_string()", to more accurately reflect what it
does.
Give it, and "proto_can_match_selected()", an "epan_dissect_t *"
argument, which replaces the raw data pointer argument to
"proto_construct_dfilter_string()".
For fields that don't have a type we can directly filter on, we don't
support filtering on the field as raw data if:
the "epan_dissect_t *" argument is null;
the data source tvbuff for the field isn't the tvbuff for the
"epan_dissect_t" in question (i.e., it's in the result of a
reassembly, and "frame[N:M]" can't get at it).
Trim the length the raw data in the case of such a field to the length
of the tvbuff for the "epan_dissect_t" in question, so we don't go past
it. Fetch the raw data bytes to match from that tvbuff.
Have "proto_construct_dfilter_string()" return a null pointer if it
can't construct the filter string, and have "protocolinfo_packet()" in
the tap-protocolinfo tap ignore a field if
"proto_construct_dfilter_string()" can't construct a filter string for
it - and have it pass NULL as the "epan_dissect_t *", for now. If
somebody decides it makes sense to dump out a "frame[N:M] =" value for
non-registered fields, it can be changed to pass "edt".
svn path=/trunk/; revision=7635
2003-05-03 00:48:37 +00:00
|
|
|
c = tvb_get_guint8(finfo->ds_tvb, start);
|
|
|
|
start++;
|
2001-02-01 20:21:25 +00:00
|
|
|
if (i == 0 ) {
|
2005-09-01 09:29:21 +00:00
|
|
|
ptr += g_snprintf(ptr, buf_len-(ptr-buf), "%02x", c);
|
2001-02-01 20:21:25 +00:00
|
|
|
}
|
|
|
|
else {
|
2005-09-01 09:29:21 +00:00
|
|
|
ptr += snprintf(ptr, buf_len-(ptr-buf), ":%02x", c);
|
2001-02-01 20:21:25 +00:00
|
|
|
}
|
2001-05-09 01:22:46 +00:00
|
|
|
}
|
|
|
|
break;
|
2000-08-30 02:50:18 +00:00
|
|
|
}
|
2001-02-01 20:21:25 +00:00
|
|
|
|
|
|
|
return buf;
|
2000-08-30 02:50:18 +00:00
|
|
|
}
|