aboutsummaryrefslogtreecommitdiffstats
path: root/epan
diff options
context:
space:
mode:
authorHadriel Kaplan <hadrielk@yahoo.com>2014-02-21 01:11:41 -0500
committerAlexis La Goutte <alexis.lagoutte@gmail.com>2014-02-25 21:06:50 +0000
commitbd36fe1bcbe19dd1b63836cc60d7351d7d8b4aa8 (patch)
treeb70a11dd3fc984900da52bd3bdfd1b40f56b29ac /epan
parent860747e1e78aefdaf31e77408ad590b9d759d1aa (diff)
Fix bug 6357: Lua all_field_infos() broken within tap/listener
The current API for Lua provides a global function "all_field_infos()" which returns all the populated field_info nodes in the current proto_tree. By default all_field_infos() "works", in the literal sense: it returns exactly the fields the previous dissectors of the packet have populated at that instant of time. But of course dissectors don't populate all the applicable fields most of the time, because of the TRY_TO_FAKE_THIS_ITEM optimization where they don't fill in things that aren't needed at the time by a display, color, or tap's dfilter. So this commit offers a way to force the dissectors to populate all the applicable field_infos in the tree, by setting the proto_tree to be visible. Obviously that is going to impact performance, since it basically bypasses the TRY_TO_FAKE_THIS_ITEM optimization; so the patch only does this if the Lua script author told it to explicitly, by adding an argument to Listener.new() and register_postdissector(). Change-Id: I11d3559fbe8c14fbadf1b51415a3701dc1200b7b Reviewed-on: https://code.wireshark.org/review/286 Reviewed-by: Alexis La Goutte <alexis.lagoutte@gmail.com>
Diffstat (limited to 'epan')
-rw-r--r--epan/epan.c17
-rw-r--r--epan/epan.h12
-rw-r--r--epan/wslua/wslua.h1
-rw-r--r--epan/wslua/wslua_listener.c12
-rw-r--r--epan/wslua/wslua_proto.c10
5 files changed, 48 insertions, 4 deletions
diff --git a/epan/epan.c b/epan/epan.c
index 2a9533fc89..85c09ab474 100644
--- a/epan/epan.c
+++ b/epan/epan.c
@@ -229,6 +229,21 @@ epan_circuit_cleanup(void)
circuit_cleanup();
}
+/* Overrides proto_tree_visible i epan_dissect_init to make all fields visible.
+ * This is > 0 if a Lua script wanted to see all fields all the time.
+ * This is ref-counted, so clearing it won't override other taps/scripts wanting it.
+ */
+static gint always_visible_refcount = 0;
+
+void
+epan_set_always_visible(gboolean force)
+{
+ if (force)
+ always_visible_refcount++;
+ else if (always_visible_refcount > 0)
+ always_visible_refcount--;
+}
+
epan_dissect_t*
epan_dissect_init(epan_dissect_t *edt, epan_t *session, const gboolean create_proto_tree, const gboolean proto_tree_visible)
{
@@ -247,7 +262,7 @@ epan_dissect_init(epan_dissect_t *edt, epan_t *session, const gboolean create_pr
if (create_proto_tree) {
edt->tree = proto_tree_create_root(&edt->pi);
- proto_tree_set_visible(edt->tree, proto_tree_visible);
+ proto_tree_set_visible(edt->tree, (always_visible_refcount > 0) ? TRUE : proto_tree_visible);
}
else {
edt->tree = NULL;
diff --git a/epan/epan.h b/epan/epan.h
index 5a9dbda019..a50ee8d548 100644
--- a/epan/epan.h
+++ b/epan/epan.h
@@ -145,6 +145,18 @@ WS_DLL_PUBLIC void epan_free(epan_t *session);
WS_DLL_PUBLIC const gchar*
epan_get_version(void);
+/**
+ * Set/unset the tree to always be visible when epan_dissect_init() is called.
+ * This state change sticks until cleared, rather than being done per function call.
+ * This is currently used when Lua scripts request all fields be generated.
+ * By default it only becomes visible if epan_dissect_init() makes it so, usually
+ * only when a packet is selected.
+ * Setting this overrides that so it's always visible, although it will still not be
+ * created if create_proto_tree is false in the call to epan_dissect_init().
+ * Clearing this reverts the decision to epan_dissect_init() and proto_tree_visible.
+ */
+void epan_set_always_visible(gboolean force);
+
/** initialize an existing single packet dissection */
WS_DLL_PUBLIC
epan_dissect_t*
diff --git a/epan/wslua/wslua.h b/epan/wslua/wslua.h
index 2f48ca3d34..05045e3a5f 100644
--- a/epan/wslua/wslua.h
+++ b/epan/wslua/wslua.h
@@ -199,6 +199,7 @@ struct _wslua_tap {
int packet_ref;
int draw_ref;
int reset_ref;
+ gboolean all_fields;
};
# define DIRECTORY_T GDir
diff --git a/epan/wslua/wslua_listener.c b/epan/wslua/wslua_listener.c
index d504f52e9d..14438631e2 100644
--- a/epan/wslua/wslua_listener.c
+++ b/epan/wslua/wslua_listener.c
@@ -192,9 +192,11 @@ WSLUA_CONSTRUCTOR Listener_new(lua_State* L) {
/* Creates a new Listener listener */
#define WSLUA_OPTARG_Listener_new_TAP 1 /* The name of this tap */
#define WSLUA_OPTARG_Listener_new_FILTER 2 /* A filter that when matches the tap.packet function gets called (use nil to be called for every packet) */
+#define WSLUA_OPTARG_Listener_new_ALLFIELDS 3 /* Whether to generate all fields. Note: this impacts performance (default=false) */
const gchar* tap_type = luaL_optstring(L,WSLUA_OPTARG_Listener_new_TAP,"frame");
const gchar* filter = luaL_optstring(L,WSLUA_OPTARG_Listener_new_FILTER,NULL);
+ const gboolean all_fields = wslua_optbool(L, WSLUA_OPTARG_Listener_new_ALLFIELDS, FALSE);
Listener tap;
GString* error;
@@ -207,6 +209,7 @@ WSLUA_CONSTRUCTOR Listener_new(lua_State* L) {
tap->packet_ref = LUA_NOREF;
tap->draw_ref = LUA_NOREF;
tap->reset_ref = LUA_NOREF;
+ tap->all_fields = all_fields;
/*
* XXX - do all Lua taps require the protocol tree? If not, it might
@@ -226,6 +229,10 @@ WSLUA_CONSTRUCTOR Listener_new(lua_State* L) {
g_string_free(error,TRUE); /* XXX LEAK? */
}
+ if (all_fields) {
+ epan_set_always_visible(TRUE);
+ }
+
pushListener(L,tap);
WSLUA_RETURN(1); /* The newly created Listener listener object */
}
@@ -263,6 +270,11 @@ WSLUA_METHOD Listener_remove(lua_State* L) {
/* Removes a tap listener */
Listener tap = checkListener(L,1);
+ if (tap->all_fields) {
+ epan_set_always_visible(FALSE);
+ tap->all_fields = FALSE;
+ }
+
remove_tap_listener(tap);
return 0;
diff --git a/epan/wslua/wslua_proto.c b/epan/wslua/wslua_proto.c
index 4069b846ea..573cd9740b 100644
--- a/epan/wslua/wslua_proto.c
+++ b/epan/wslua/wslua_proto.c
@@ -1403,8 +1403,6 @@ static int Proto__tostring(lua_State* L) {
Proto proto = checkProto(L,1);
gchar* s;
- if (!proto) return 0;
-
s = ep_strdup_printf("Proto: %s",proto->name);
lua_pushstring(L,s);
@@ -1414,8 +1412,10 @@ static int Proto__tostring(lua_State* L) {
WSLUA_FUNCTION wslua_register_postdissector(lua_State* L) {
/* Make a protocol (with a dissector) a postdissector. It will be called for every frame after dissection */
#define WSLUA_ARG_register_postdissector_PROTO 1 /* the protocol to be used as postdissector */
+#define WSLUA_OPTARG_register_postdissector_ALLFIELDS 2 /* Whether to generate all fields. Note: this impacts performance (default=false) */
+
Proto proto = checkProto(L,WSLUA_ARG_register_postdissector_PROTO);
- if (!proto) return 0;
+ const gboolean all_fields = wslua_optbool(L, WSLUA_OPTARG_register_postdissector_ALLFIELDS, FALSE);
if(!proto->is_postdissector) {
if (! proto->handle) {
@@ -1427,6 +1427,10 @@ WSLUA_FUNCTION wslua_register_postdissector(lua_State* L) {
luaL_argerror(L,1,"this protocol is already registered as postdissector");
}
+ if (all_fields) {
+ epan_set_always_visible(TRUE);
+ }
+
return 0;
}