aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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
-rw-r--r--test/lua/listener.lua73
6 files changed, 118 insertions, 7 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;
}
diff --git a/test/lua/listener.lua b/test/lua/listener.lua
index ecb1a52a3f..55873fbbab 100644
--- a/test/lua/listener.lua
+++ b/test/lua/listener.lua
@@ -8,6 +8,7 @@ local ETH = "eth"
local IP = "ip"
local BOOTP = "bootp"
local OTHER = "other"
+local PDISS = "postdissector"
local packet_counts = {}
local function incPktCount(name)
@@ -34,7 +35,7 @@ end
-- note ip only runs 3 times because it gets removed
-- and bootp only runs twice because the filter makes it run
-- once and then it gets replaced with a different one for the second time
-local taptests = { [FRAME]=4, [ETH]=4, [IP]=3, [BOOTP]=2, [OTHER]=15 }
+local taptests = { [FRAME]=4, [ETH]=4, [IP]=3, [BOOTP]=2, [OTHER]=16 }
local function getResults()
print("\n-----------------------------\n")
for k,v in pairs(taptests) do
@@ -64,6 +65,49 @@ local function test(type,name, ...)
end
end
+local pkt_fields = { [FRAME] = {}, [PDISS] = {} }
+local function getAllFieldInfos(type)
+ local fields = { all_field_infos() }
+ local fieldnames = {}
+ for i,v in ipairs(fields) do
+ fieldnames[i] = v.name
+ end
+ local pktnum = getPktCount(type)
+ pkt_fields[type][pktnum] = { ["num"] = #fields, ["fields"] = fieldnames }
+end
+
+local function dumpAllFieldInfos()
+ for i,v in ipairs(pkt_fields[FRAME]) do
+ print("In frame tap for packet ".. i ..":")
+ print(" number of fields = ".. v.num)
+ for _,name in ipairs(v.fields) do
+ print(" field = ".. name)
+ end
+ local w = pkt_fields[PDISS][i]
+ print("In postdissector for packet ".. i ..":")
+ print(" number of fields = ".. w.num)
+ for _,name in ipairs(w.fields) do
+ print(" field = ".. name)
+ end
+ end
+end
+
+local function checkAllFieldInfos()
+ for i,v in ipairs(pkt_fields[FRAME]) do
+ local numfields = v.num
+ if numfields ~= pkt_fields[PDISS][i].num then
+ print("Tap and postdissector do not have same number of fields!")
+ return false
+ end
+ if numfields < 100 then
+ print("Too few fields!")
+ return false
+ end
+ end
+ return true
+end
+
+
---------
-- the following are so we can use pcall (which needs a function to call)
local function makeListener(...)
@@ -124,7 +168,7 @@ local f_ip_dst = Field.new("ip.dst")
local f_bootp_hw = Field.new("bootp.hw.mac_addr")
local f_bootp_opt = Field.new("bootp.option.type")
-local tap_frame = Listener.new()
+local tap_frame = Listener.new(nil,nil,true)
local tap_eth = Listener.new("eth")
local tap_ip = Listener.new("ip","bootp")
local tap_bootp = Listener.new("bootp","bootp.option.dhcp == 1")
@@ -146,6 +190,8 @@ function tap_frame.packet(pinfo,tvb,frame)
local eth_src2 = tostring(tvb:range(6,6))
test(FRAME,"FieldInfo.range-1", eth_src1 == eth_src2)
+ getAllFieldInfos(FRAME)
+
setPassed(FRAME)
end
@@ -221,13 +267,34 @@ tap_bootp.packet = bootp_packet
function tap_frame.reset()
-- reset never gets called in tshark (sadly)
- error("reset called!!")
+ if not GUI_ENABLED then
+ error("reset called!!")
+ end
end
function tap_frame.draw()
+ test(OTHER,"all_field_infos", checkAllFieldInfos())
+ setPassed(OTHER)
getResults()
end
+-- max_gap.lua
+-- create a gap.max field containing the maximum gap between two packets between two ip nodes
+
+-- we create a "protocol" for our tree
+local max_gap_p = Proto("gap","Gap in IP conversations")
+
+-- we create our fields
+local max_gap_field = ProtoField.float("gap.max")
+-- we add our fields to the protocol
+max_gap_p.fields = { max_gap_field }
+
+-- then we register max_gap_p as a postdissector
+register_postdissector(max_gap_p,true)
+function max_gap_p.dissector(tvb,pinfo,tree)
+ incPktCount(PDISS)
+ getAllFieldInfos(PDISS)
+end