forked from osmocom/wireshark
Add Lua heuristic dissector support
This adds the ability for Lua scripts to register heuristic dissectors for any protocol that has registered a heuristic dissector list, such as UDP, TCP, and ~50 others. The Lua function can also establish a conversation tied to its Proto dissector, to avoid having to check the heuristics for the same flow. The example dissector in the testsuite has also been enhanced to include a heuristic dissector, to verify the functionality and provide an example implementation. Change-Id: Ie232602779f43d3418fe8db09c61d5fc0b59597a Reviewed-on: https://code.wireshark.org/review/576 Reviewed-by: Anders Broman <a.broman58@gmail.com>
This commit is contained in:
parent
a59ac1bd10
commit
04c39bb097
|
@ -103,7 +103,7 @@ Heuristic Code Example
|
|||
----------------------
|
||||
You can find a lot of code examples in the Wireshark sources, e.g.:
|
||||
grep -l heur_dissector_add epan/dissectors/*.c
|
||||
returns 132 files (Feb 2013).
|
||||
returns 150 files (March 2014).
|
||||
|
||||
For the above example criteria, the following code example might do the work
|
||||
(combine this with the dissector skeleton in README.developer):
|
||||
|
@ -150,7 +150,10 @@ dissect_PROTOABBREV_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, vo
|
|||
|
||||
/* Assume it's your packet ... */
|
||||
|
||||
/* specify that dissect_PROTOABBREV is to be called directly from now on for packets for this "connection" ... */
|
||||
/* specify that dissect_PROTOABBREV is to be called directly from now on for packets for this "connection" ...
|
||||
* but ONLY do this if your heuristic sits directly on top of UDP or TCP (ie, you did heur_dissector_add("tcp",...)),
|
||||
* otherwise you'll be overriding the dissector that called your heuristic dissector.
|
||||
*/
|
||||
conversation = find_or_create_conversation(pinfo);
|
||||
conversation_set_dissector(conversation, PROTOABBREV_handle);
|
||||
|
||||
|
@ -188,5 +191,4 @@ tendency to reuse known port numbers for new protocols. But TCP and UDP are
|
|||
not the only dissectors that provide support for HDs. You can find more
|
||||
examples by searching the Wireshark sources as follows:
|
||||
grep -l register_heur_dissector_list epan/dissectors/packet-*.c
|
||||
returns 38 files (Feb 2013).
|
||||
|
||||
returns 43 files (March 2014).
|
||||
|
|
|
@ -1831,6 +1831,11 @@ find_heur_dissector_list(const char *name)
|
|||
return (heur_dissector_list_t *)g_hash_table_lookup(heur_dissector_lists, name);
|
||||
}
|
||||
|
||||
gboolean
|
||||
has_heur_dissector_list(const gchar *name) {
|
||||
return (find_heur_dissector_list(name) != NULL);
|
||||
}
|
||||
|
||||
void
|
||||
heur_dissector_add(const char *name, heur_dissector_t dissector, const int proto)
|
||||
{
|
||||
|
@ -1859,6 +1864,7 @@ heur_dissector_add(const char *name, heur_dissector_t dissector, const int proto
|
|||
hdtbl_entry = g_slice_new(heur_dtbl_entry_t);
|
||||
hdtbl_entry->dissector = dissector;
|
||||
hdtbl_entry->protocol = find_protocol_by_id(proto);
|
||||
hdtbl_entry->list_name = g_strdup(name);
|
||||
hdtbl_entry->enabled = TRUE;
|
||||
|
||||
/* do the table insertion */
|
||||
|
@ -1892,6 +1898,7 @@ heur_dissector_delete(const char *name, heur_dissector_t dissector, const int pr
|
|||
found_entry = g_slist_find_custom(*sub_dissectors, (gpointer) &hdtbl_entry, find_matching_heur_dissector);
|
||||
|
||||
if (found_entry) {
|
||||
g_free(((heur_dtbl_entry_t *)(found_entry->data))->list_name);
|
||||
g_slice_free(heur_dtbl_entry_t, found_entry->data);
|
||||
*sub_dissectors = g_slist_delete_link(*sub_dissectors, found_entry);
|
||||
}
|
||||
|
@ -1924,7 +1931,8 @@ dissector_try_heuristic(heur_dissector_list_t sub_dissectors, tvbuff_t *tvb,
|
|||
packet_info *pinfo, proto_tree *tree, void *data)
|
||||
{
|
||||
gboolean status;
|
||||
const char *saved_proto;
|
||||
const char *saved_curr_proto;
|
||||
const char *saved_heur_list_name;
|
||||
GSList *entry;
|
||||
heur_dtbl_entry_t *hdtbl_entry;
|
||||
guint16 saved_can_desegment;
|
||||
|
@ -1944,7 +1952,8 @@ dissector_try_heuristic(heur_dissector_list_t sub_dissectors, tvbuff_t *tvb,
|
|||
pinfo->can_desegment = saved_can_desegment-(saved_can_desegment>0);
|
||||
|
||||
status = FALSE;
|
||||
saved_proto = pinfo->current_proto;
|
||||
saved_curr_proto = pinfo->current_proto;
|
||||
saved_heur_list_name = pinfo->heur_list_name;
|
||||
|
||||
saved_layers_len = wmem_list_count(pinfo->layers);
|
||||
|
||||
|
@ -1962,6 +1971,8 @@ dissector_try_heuristic(heur_dissector_list_t sub_dissectors, tvbuff_t *tvb,
|
|||
}
|
||||
|
||||
if (hdtbl_entry->protocol != NULL) {
|
||||
/* do NOT change this behavior - wslua uses the protocol short name set here in order
|
||||
to determine which Lua-based heurisitc dissector to call */
|
||||
pinfo->current_proto =
|
||||
proto_get_protocol_short_name(hdtbl_entry->protocol);
|
||||
|
||||
|
@ -1971,6 +1982,9 @@ dissector_try_heuristic(heur_dissector_list_t sub_dissectors, tvbuff_t *tvb,
|
|||
*/
|
||||
wmem_list_append(pinfo->layers, GINT_TO_POINTER(proto_get_id(hdtbl_entry->protocol)));
|
||||
}
|
||||
|
||||
pinfo->heur_list_name = hdtbl_entry->list_name;
|
||||
|
||||
EP_CHECK_CANARY(("before calling heuristic dissector for protocol: %s",
|
||||
proto_get_protocol_filter_name(proto_get_id(hdtbl_entry->protocol))));
|
||||
if ((*hdtbl_entry->dissector)(tvb, pinfo, tree, data)) {
|
||||
|
@ -1992,8 +2006,10 @@ dissector_try_heuristic(heur_dissector_list_t sub_dissectors, tvbuff_t *tvb,
|
|||
}
|
||||
}
|
||||
}
|
||||
pinfo->current_proto = saved_proto;
|
||||
pinfo->can_desegment=saved_can_desegment;
|
||||
|
||||
pinfo->current_proto = saved_curr_proto;
|
||||
pinfo->heur_list_name = saved_heur_list_name;
|
||||
pinfo->can_desegment = saved_can_desegment;
|
||||
return status;
|
||||
}
|
||||
|
||||
|
|
|
@ -338,7 +338,8 @@ typedef GSList *heur_dissector_list_t;
|
|||
|
||||
typedef struct {
|
||||
heur_dissector_t dissector;
|
||||
protocol_t *protocol;
|
||||
protocol_t *protocol; /* this entry's protocol */
|
||||
gchar *list_name; /* the list name this entry is in the list of */
|
||||
gboolean enabled;
|
||||
} heur_dtbl_entry_t;
|
||||
|
||||
|
@ -354,6 +355,9 @@ WS_DLL_PUBLIC void register_heur_dissector_list(const char *name,
|
|||
WS_DLL_PUBLIC void dissector_all_heur_tables_foreach_table (DATFunc_heur_table func,
|
||||
gpointer user_data);
|
||||
|
||||
/* true if a heur_dissector list of that anme exists to be registered into */
|
||||
WS_DLL_PUBLIC gboolean has_heur_dissector_list(const gchar *name);
|
||||
|
||||
/** Try all the dissectors in a given heuristic dissector list. This is done,
|
||||
* until we find one that recognizes the protocol.
|
||||
* Call this while the parent dissector running.
|
||||
|
|
|
@ -179,6 +179,7 @@ typedef struct _packet_info {
|
|||
struct epan_session *epan;
|
||||
nstime_t rel_ts; /**< Relative timestamp (yes, it can be negative) */
|
||||
const gchar *pkt_comment; /**< NULL if not available */
|
||||
const gchar *heur_list_name; /**< name of heur list if this packet is being heuristically dissected */
|
||||
} packet_info;
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -47,10 +47,13 @@ static wslua_plugin *wslua_plugin_list = NULL;
|
|||
|
||||
static lua_State* L = NULL;
|
||||
|
||||
/* XXX: global variables? Really?? Yuck. These could be done differently,
|
||||
using the Lua registry */
|
||||
packet_info* lua_pinfo;
|
||||
struct _wslua_treeitem* lua_tree;
|
||||
tvbuff_t* lua_tvb;
|
||||
int lua_dissectors_table_ref;
|
||||
int lua_dissectors_table_ref = LUA_NOREF;
|
||||
int lua_heur_dissectors_table_ref = LUA_NOREF;
|
||||
|
||||
static int proto_lua = -1;
|
||||
static expert_field ei_lua_error = EI_INIT;
|
||||
|
@ -133,6 +136,95 @@ int dissect_lua(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, void* data
|
|||
|
||||
}
|
||||
|
||||
/** Type of a heuristic dissector, used in heur_dissector_add().
|
||||
*
|
||||
* @param tvb the tvbuff with the (remaining) packet data
|
||||
* @param pinfo the packet info of this packet (additional info)
|
||||
* @param tree the protocol tree to be build or NULL
|
||||
* @return TRUE if the packet was recognized by the sub-dissector (stop dissection here)
|
||||
*/
|
||||
gboolean heur_dissect_lua(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, void* data _U_) {
|
||||
gboolean result = FALSE;
|
||||
lua_tvb = tvb;
|
||||
lua_pinfo = pinfo;
|
||||
|
||||
if (!tvb || !pinfo || !pinfo->heur_list_name || !pinfo->current_proto) {
|
||||
report_failure("internal error in heur_dissect_lua: NULL packet info");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* heuristic functions are stored in a table in the registry; the registry has a
|
||||
* table at reference lua_heur_dissectors_table_ref, and that table has keys for
|
||||
* the heuristic listname (e.g., "udp", "tcp", etc.), and that key's value is a
|
||||
* table of keys of the Proto->name, and their value is the function.
|
||||
* So it's like registry[table_ref][heur_list_name][proto_name] = func
|
||||
*/
|
||||
|
||||
lua_settop(L,0);
|
||||
|
||||
/* get the table of all lua heuristic dissector lists */
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, lua_heur_dissectors_table_ref);
|
||||
|
||||
/* get the table inside that, for the lua heuristic dissectors of the requested heur list */
|
||||
if (!wslua_get_table(L, -1, pinfo->heur_list_name)) {
|
||||
/* this shouldn't happen */
|
||||
lua_settop(L,0);
|
||||
report_failure("internal error in heur_dissect_lua: no %s heur list table", pinfo->heur_list_name);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* get the table inside that, for the specific lua heuristic dissector */
|
||||
if (!wslua_get_field(L,-1,pinfo->current_proto)) {
|
||||
/* this shouldn't happen */
|
||||
lua_settop(L,0);
|
||||
report_failure("internal error in heur_dissect_lua: no %s heuristic dissector for list %s",
|
||||
pinfo->current_proto, pinfo->heur_list_name);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* remove the table of all lists (the one in the registry) */
|
||||
lua_remove(L,1);
|
||||
/* remove the heur_list_name heur list table */
|
||||
lua_remove(L,1);
|
||||
|
||||
if (!lua_isfunction(L,-1)) {
|
||||
/* this shouldn't happen */
|
||||
lua_settop(L,0);
|
||||
report_failure("internal error in heur_dissect_lua: %s heuristic dissector is not a function", pinfo->current_proto);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
lua_tree = (struct _wslua_treeitem *)g_malloc(sizeof(struct _wslua_treeitem));
|
||||
lua_tree->tree = tree;
|
||||
lua_tree->item = proto_tree_add_text(tree,tvb,0,0,"lua fake item");
|
||||
lua_tree->expired = FALSE;
|
||||
PROTO_ITEM_SET_HIDDEN(lua_tree->item);
|
||||
|
||||
push_Tvb(L,tvb);
|
||||
push_Pinfo(L,pinfo);
|
||||
push_TreeItem(L,lua_tree);
|
||||
|
||||
if ( lua_pcall(L,3,1,0) ) {
|
||||
report_failure(" error calling %s heuristic dissector: %s", pinfo->current_proto, lua_tostring(L,-1));
|
||||
lua_settop(L,0);
|
||||
} else {
|
||||
if (lua_isboolean(L, -1) || lua_isnil(L, -1)) {
|
||||
result = lua_toboolean(L, -1);
|
||||
} else {
|
||||
report_failure(" invalid return value from Lua %s heuristic dissector", pinfo->current_proto);
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
register_frame_end_routine(pinfo, lua_frame_end);
|
||||
|
||||
lua_pinfo = NULL;
|
||||
lua_tree = NULL;
|
||||
lua_tvb = NULL;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void iter_table_and_call(lua_State* LS, const gchar* table_name, lua_CFunction error_handler) {
|
||||
lua_settop(LS,0);
|
||||
|
||||
|
@ -454,6 +546,8 @@ int wslua_init(register_cb cb, gpointer client_data) {
|
|||
/* the dissectors table goes in the registry (not accessible) */
|
||||
lua_newtable (L);
|
||||
lua_dissectors_table_ref = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||
lua_newtable (L);
|
||||
lua_heur_dissectors_table_ref = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||
|
||||
/* the preferences apply_cb table (accessible by the user) */
|
||||
lua_newtable (L);
|
||||
|
|
|
@ -552,6 +552,7 @@ extern tvbuff_t* lua_tvb;
|
|||
extern dissector_handle_t lua_data_handle;
|
||||
extern gboolean lua_initialized;
|
||||
extern int lua_dissectors_table_ref;
|
||||
extern int lua_heur_dissectors_table_ref;
|
||||
|
||||
WSLUA_DECLARE_CLASSES()
|
||||
WSLUA_DECLARE_FUNCTIONS()
|
||||
|
@ -565,8 +566,11 @@ extern const gchar* lua_shiftstring(lua_State* L,int idx);
|
|||
extern void wslua_setfuncs(lua_State *L, const luaL_Reg *l, int nup);
|
||||
extern const gchar* wslua_typeof_unknown;
|
||||
extern const gchar* wslua_typeof(lua_State *L, int idx);
|
||||
extern gboolean wslua_get_table(lua_State *L, int idx, const gchar *name);
|
||||
extern gboolean wslua_get_field(lua_State *L, int idx, const gchar *name);
|
||||
extern void wslua_assert_table_field_new(lua_State *L, int idx, const gchar *name);
|
||||
extern int dissect_lua(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, void* data);
|
||||
extern int heur_dissect_lua(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, void* data);
|
||||
extern void wslua_prefs_changed(void);
|
||||
extern void proto_register_lua(void);
|
||||
extern GString* lua_register_all_taps(void);
|
||||
|
|
|
@ -99,13 +99,17 @@ WSLUA_API void wslua_setfuncs(lua_State *L, const luaL_Reg *l, int nup) {
|
|||
lua_pop(L, nup); /* remove upvalues */
|
||||
}
|
||||
|
||||
/* identical to lua_getfield but without triggering metamethods */
|
||||
/* identical to lua_getfield but without triggering metamethods
|
||||
warning: cannot be used directly with negative index (and shouldn't be changed to)
|
||||
decrement your negative index if you want to use this */
|
||||
static void lua_rawgetfield(lua_State *L, int idx, const char *k) {
|
||||
lua_pushstring(L, k);
|
||||
lua_rawget(L, idx);
|
||||
}
|
||||
|
||||
/* identical to lua_setfield but without triggering metamethods */
|
||||
/* identical to lua_setfield but without triggering metamethods
|
||||
warning: cannot be used with negative index (and shouldn't be changed to)
|
||||
decrement your negative index if you want to use this */
|
||||
static void lua_rawsetfield (lua_State *L, int idx, const char *k) {
|
||||
lua_pushstring(L, k);
|
||||
lua_insert(L, -2);
|
||||
|
@ -140,6 +144,38 @@ const gchar* wslua_typeof(lua_State *L, int idx) {
|
|||
return classname;
|
||||
}
|
||||
|
||||
/* this gets a Lua table of the given name, from the table at the given
|
||||
* location idx. If it does not get a table, it pops whatever it got
|
||||
* and returns false.
|
||||
* warning: cannot be used with pseudo-indeces like LUA_REGISTRYINDEX
|
||||
*/
|
||||
gboolean wslua_get_table(lua_State *L, int idx, const gchar *name) {
|
||||
gboolean result = TRUE;
|
||||
if (idx < 0) idx--;
|
||||
lua_rawgetfield(L, idx, name);
|
||||
if (!lua_istable(L,-1)) {
|
||||
lua_pop(L,1);
|
||||
result = FALSE;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/* this gets a table field of the given name, from the table at the given
|
||||
* location idx. If it does not get a field, it pops whatever it got
|
||||
* and returns false.
|
||||
* warning: cannot be used with pseudo-indeces like LUA_REGISTRYINDEX
|
||||
*/
|
||||
gboolean wslua_get_field(lua_State *L, int idx, const gchar *name) {
|
||||
gboolean result = TRUE;
|
||||
if (idx < 0) idx--;
|
||||
lua_rawgetfield(L, idx, name);
|
||||
if (lua_isnil(L,-1)) {
|
||||
lua_pop(L,1);
|
||||
result = FALSE;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/* This verifies/asserts that field 'name' doesn't already exist in table at location idx.
|
||||
* If it does, this EXITS wireshark, because this is a fundamental programming error.
|
||||
* As such, this function is only useful for special circumstances, notably
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include "wslua.h"
|
||||
|
||||
#include <epan/addr_resolv.h>
|
||||
#include <epan/conversation.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
|
@ -1128,6 +1129,23 @@ static int Pinfo_get_lo(lua_State *L) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
/* WSLUA_ATTRIBUTE Pinfo_conversation WO sets the packet conversation to the given Proto object */
|
||||
static int Pinfo_set_conversation(lua_State *L) {
|
||||
Pinfo pinfo = checkPinfo(L,1);
|
||||
Proto proto = checkProto(L,2);
|
||||
conversation_t *conversation;
|
||||
|
||||
if (!proto->handle) {
|
||||
luaL_error(L,"Proto %s has no registered dissector", proto->name? proto->name:"<UKNOWN>");
|
||||
return 0;
|
||||
}
|
||||
|
||||
conversation = find_or_create_conversation(pinfo->ws_pinfo);
|
||||
conversation_set_dissector(conversation,proto->handle);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Gets registered as metamethod automatically by WSLUA_REGISTER_CLASS/META */
|
||||
static int Pinfo__gc(lua_State* L) {
|
||||
Pinfo pinfo = toPinfo(L,1);
|
||||
|
@ -1183,6 +1201,7 @@ WSLUA_ATTRIBUTES Pinfo_attributes[] = {
|
|||
WSLUA_ATTRIBUTE_ROREG(Pinfo,fragmented),
|
||||
WSLUA_ATTRIBUTE_ROREG(Pinfo,match_uint),
|
||||
WSLUA_ATTRIBUTE_ROREG(Pinfo,match_string),
|
||||
WSLUA_ATTRIBUTE_WOREG(Pinfo,conversation),
|
||||
{ NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
|
|
|
@ -1458,6 +1458,76 @@ WSLUA_FUNCTION wslua_register_postdissector(lua_State* L) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
WSLUA_METHOD Proto_register_heuristic(lua_State* L) {
|
||||
/* Registers a heristic dissector function for this protocol, for the given heristic list name.
|
||||
When later called, the passed-in function will be given (1) a Tvb object, (2) a Pinfo object,
|
||||
and (3) a TreeItem object. The function must return true if the payload is for it, else false.
|
||||
The function should perform as much verification as possible to ensure the payload is for it,
|
||||
and dissect the packet (including setting TreeItem info and such) only if the payload is for it,
|
||||
before returning true or false.*/
|
||||
#define WSLUA_ARG_Proto_register_heuristic_LISTNAME 2 /* the heristic list name this function is a heuristic for (e.g., "udp" or "infiniband.payload") */
|
||||
#define WSLUA_ARG_Proto_register_heuristic_FUNC 3 /* a Lua function that will be invoked for heuristic dissection */
|
||||
Proto proto = checkProto(L,1);
|
||||
const gchar *listname = luaL_checkstring(L, WSLUA_ARG_Proto_register_heuristic_LISTNAME);
|
||||
const gchar *proto_name = proto->name;
|
||||
const int top = lua_gettop(L);
|
||||
|
||||
if (!proto_name || proto->hfid == -1) {
|
||||
/* this shouldn't happen - internal bug if it does */
|
||||
luaL_error(L,"Proto_register_heuristic: got NULL proto name or invalid hfid");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* verify listname has a heuristic list */
|
||||
if (!has_heur_dissector_list(listname)) {
|
||||
luaL_error(L, "there is no heuristic list for '%s'", listname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* heuristic functions are stored in a table in the registry; the registry has a
|
||||
* table at reference lua_heur_dissectors_table_ref, and that table has keys for
|
||||
* the heuristic listname (e.g., "udp", "tcp", etc.), and that key's value is a
|
||||
* table of keys of the Proto->name, and their value is the function.
|
||||
* So it's like registry[table_ref][heur_list_name][proto_name] = func
|
||||
*/
|
||||
if (lua_isfunction(L,WSLUA_ARG_Proto_register_heuristic_FUNC)) {
|
||||
/* insert the heur dissector into the heur dissectors table */
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, lua_heur_dissectors_table_ref);
|
||||
/* the heuristic lists table is now at -1 */
|
||||
if (!lua_istable(L,-1)) {
|
||||
/* this shouldn't be possible */
|
||||
luaL_error(L,"Proto_register_heuristic: could not get lua_heur_dissectors table from registry");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!wslua_get_table(L,-1,listname)) {
|
||||
/* no one's registered a lua heuristic for this list, so make a new list table */
|
||||
lua_newtable(L);
|
||||
lua_pushvalue(L,-1); /* duplicate the table so we can set it as a field */
|
||||
lua_setfield(L,-3,listname); /* sets this new list table into the lists table */
|
||||
}
|
||||
else if (wslua_get_field(L,-1,proto_name)) {
|
||||
luaL_error(L,"A heuristic dissector for Proto '%s' is already registered for the '%s' list", proto_name, listname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* copy the func, set it as the value for key proto_name in listname's table */
|
||||
lua_pushvalue(L,WSLUA_ARG_Proto_register_heuristic_FUNC);
|
||||
lua_setfield(L,-2,proto_name);
|
||||
|
||||
/* ok, we're done with lua stuff, pop what we added to the stack */
|
||||
lua_pop(L,2); /* pop the lists table and the listname table */
|
||||
g_assert(top == lua_gettop(L));
|
||||
|
||||
/* now register the single/common heur_dissect_lua function */
|
||||
heur_dissector_add(listname, heur_dissect_lua, proto->hfid);
|
||||
|
||||
} else {
|
||||
luaL_argerror(L,3,"The heuristic dissector must be a function");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* WSLUA_ATTRIBUTE Proto_dissector RW The protocol's dissector, a function you define.
|
||||
The called dissector function will be given three arguments of (1) a Tvb object, (2) a Pinfo object, and (3) a TreeItem object. */
|
||||
static int Proto_get_dissector(lua_State* L) {
|
||||
|
@ -1602,6 +1672,7 @@ WSLUA_ATTRIBUTES Proto_attributes[] = {
|
|||
|
||||
WSLUA_METHODS Proto_methods[] = {
|
||||
WSLUA_CLASS_FNREG(Proto,new),
|
||||
WSLUA_CLASS_FNREG(Proto,register_heuristic),
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
|
@ -1780,6 +1851,14 @@ WSLUA_METHOD Dissector_call(lua_State* L) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
WSLUA_METAMETHOD Dissector__call(lua_State* L) {
|
||||
/* Calls a dissector against a given packet (or part of it) */
|
||||
#define WSLUA_ARG_Dissector__call_TVB 2 /* The buffer to dissect */
|
||||
#define WSLUA_ARG_Dissector__call_PINFO 3 /* The packet info */
|
||||
#define WSLUA_ARG_Dissector__call_TREE 4 /* The tree on which to add the protocol items */
|
||||
return Dissector_call(L);
|
||||
}
|
||||
|
||||
WSLUA_METAMETHOD Dissector__tostring(lua_State* L) {
|
||||
/* Gets the Dissector's protocol short name */
|
||||
Dissector d = checkDissector(L,1);
|
||||
|
@ -1803,6 +1882,7 @@ WSLUA_METHODS Dissector_methods[] = {
|
|||
|
||||
WSLUA_META Dissector_meta[] = {
|
||||
WSLUA_CLASS_MTREG(Dissector,tostring),
|
||||
WSLUA_CLASS_MTREG(Dissector,call),
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
|
@ -1856,6 +1936,58 @@ WSLUA_CONSTRUCTOR DissectorTable_new (lua_State *L) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* this struct is used for passing ourselves user_data through dissector_all_tables_foreach_table() */
|
||||
typedef struct dissector_tables_foreach_table_info {
|
||||
int num;
|
||||
lua_State *L;
|
||||
} dissector_tables_foreach_table_info_t;
|
||||
|
||||
/* this is the DATFunc_table function used for dissector_all_tables_foreach_table()
|
||||
so we can get all dissector_table names. This pushes the name into a table at stack index 1 */
|
||||
static void
|
||||
dissector_tables_list_func(const gchar *table_name, const gchar *ui_name _U_, gpointer user_data) {
|
||||
dissector_tables_foreach_table_info_t *data = (dissector_tables_foreach_table_info_t*) user_data;
|
||||
lua_pushstring(data->L, table_name);
|
||||
lua_rawseti(data->L, 1, data->num);
|
||||
data->num = data->num + 1;
|
||||
}
|
||||
|
||||
WSLUA_CONSTRUCTOR DissectorTable_list (lua_State *L) {
|
||||
/* Gets a Lua array table of all DissectorTable names - i.e., the string names you can
|
||||
use for the first argument to DissectorTable.get().
|
||||
NOTE: this is an expensive operation, and should only be used for troubleshooting. */
|
||||
dissector_tables_foreach_table_info_t data = { 1, L };
|
||||
|
||||
lua_newtable(L);
|
||||
|
||||
dissector_all_tables_foreach_table(dissector_tables_list_func, (gpointer)&data, (GCompareFunc)compare_dissector_key_name);
|
||||
|
||||
WSLUA_RETURN(1); /* The array table of registered DissectorTable names */
|
||||
}
|
||||
|
||||
/* this is the DATFunc_heur_table function used for dissector_all_heur_tables_foreach_table()
|
||||
so we can get all heuristic dissector list names. This pushes the name into a table at stack index 1 */
|
||||
static void
|
||||
heur_dissector_tables_list_func(const gchar *table_name, gpointer table _U_, gpointer user_data) {
|
||||
dissector_tables_foreach_table_info_t *data = (dissector_tables_foreach_table_info_t*) user_data;
|
||||
lua_pushstring(data->L, table_name);
|
||||
lua_rawseti(data->L, 1, data->num);
|
||||
data->num = data->num + 1;
|
||||
}
|
||||
|
||||
WSLUA_CONSTRUCTOR DissectorTable_heuristic_list (lua_State *L) {
|
||||
/* Gets a Lua array table of all heuristic list names - i.e., the string names you can
|
||||
use for the first argument in Proto:register_heuristic().
|
||||
NOTE: this is an expensive operation, and should only be used for troubleshooting. */
|
||||
dissector_tables_foreach_table_info_t data = { 1, L };
|
||||
|
||||
lua_newtable(L);
|
||||
|
||||
dissector_all_heur_tables_foreach_table(heur_dissector_tables_list_func, (gpointer)&data);
|
||||
|
||||
WSLUA_RETURN(1); /* The array table of registered heuristic list names */
|
||||
}
|
||||
|
||||
WSLUA_CONSTRUCTOR DissectorTable_get (lua_State *L) {
|
||||
/*
|
||||
Obtain a reference to an existing dissector table.
|
||||
|
@ -2218,6 +2350,8 @@ static int DissectorTable__gc(lua_State* L _U_) {
|
|||
WSLUA_METHODS DissectorTable_methods[] = {
|
||||
WSLUA_CLASS_FNREG(DissectorTable,new),
|
||||
WSLUA_CLASS_FNREG(DissectorTable,get),
|
||||
WSLUA_CLASS_FNREG(DissectorTable,list),
|
||||
WSLUA_CLASS_FNREG(DissectorTable,heuristic_list),
|
||||
WSLUA_CLASS_FNREG(DissectorTable,add),
|
||||
WSLUA_CLASS_FNREG(DissectorTable,set),
|
||||
WSLUA_CLASS_FNREG(DissectorTable,remove),
|
||||
|
|
|
@ -495,7 +495,7 @@ static int Tvb__gc(lua_State* L) {
|
|||
}
|
||||
|
||||
WSLUA_METHOD Tvb_reported_len(lua_State* L) {
|
||||
/* Obtain the reported length of a TVB */
|
||||
/* Obtain the reported (not captured) length of a TVB */
|
||||
Tvb tvb = checkTvb(L,1);
|
||||
|
||||
lua_pushnumber(L,tvb_reported_length(tvb->ws_tvb));
|
||||
|
@ -503,7 +503,7 @@ WSLUA_METHOD Tvb_reported_len(lua_State* L) {
|
|||
}
|
||||
|
||||
WSLUA_METHOD Tvb_len(lua_State* L) {
|
||||
/* Obtain the length of a TVB */
|
||||
/* Obtain the actual (captured) length of a TVB */
|
||||
Tvb tvb = checkTvb(L,1);
|
||||
|
||||
lua_pushnumber(L,tvb_length(tvb->ws_tvb));
|
||||
|
@ -511,7 +511,7 @@ WSLUA_METHOD Tvb_len(lua_State* L) {
|
|||
}
|
||||
|
||||
WSLUA_METHOD Tvb_reported_length_remaining(lua_State* L) {
|
||||
/* Obtain the reported length of packet data to end of a TVB or -1 if the offset is beyond the end of the TVB */
|
||||
/* Obtain the reported (not captured) length of packet data to end of a TVB or -1 if the offset is beyond the end of the TVB */
|
||||
#define Tvb_reported_length_remaining_OFFSET 2 /* offset */
|
||||
Tvb tvb = checkTvb(L,1);
|
||||
int offset = luaL_optint(L, Tvb_reported_length_remaining_OFFSET, 0);
|
||||
|
|
Binary file not shown.
|
@ -35,8 +35,24 @@
|
|||
-- automagically do it without doing "Decode As ...".
|
||||
--
|
||||
----------------------------------------
|
||||
--print("Wireshark version = "..get_version())
|
||||
--print("Lua version = ".._VERSION)
|
||||
-- debug printer, set DEBUG to true to enable printing debug info
|
||||
-- set DEBUG2 to true to enable really verbose printing
|
||||
local DEBUG, DEBUG2 = false, false
|
||||
|
||||
local dprint = function() end
|
||||
local dprint2 = function() end
|
||||
if DEBUG or DEBUG2 then
|
||||
dprint = function(...)
|
||||
print(table.concat({"Lua:", ...}," "))
|
||||
end
|
||||
|
||||
if DEBUG2 then
|
||||
dprint2 = dprint
|
||||
end
|
||||
end
|
||||
|
||||
dprint2("Wireshark version = ", get_version())
|
||||
dprint2("Lua version = ", _VERSION)
|
||||
|
||||
----------------------------------------
|
||||
-- Unfortunately, the older Wireshark/Tshark versions have bugs, and part of the point
|
||||
|
@ -177,6 +193,10 @@ local getQueryName
|
|||
-- Whenever Wireshark dissects a packet that our Proto is hooked into, it will call
|
||||
-- this function and pass it these arguments for the packet it's dissecting.
|
||||
function dns.dissector(tvbuf,pktinfo,root)
|
||||
dprint2("dns.dissector called")
|
||||
|
||||
-- set the protocol column to show our protocol name
|
||||
pktinfo.cols.protocol:set("MYDNS")
|
||||
|
||||
-- We want to check that the packet size is rational during dissection, so let's get the length of the
|
||||
-- packet buffer (Tvb).
|
||||
|
@ -195,6 +215,7 @@ function dns.dissector(tvbuf,pktinfo,root)
|
|||
-- since we're going to add this protocol to a specific UDP port, we're going to
|
||||
-- assume packets in this port are our protocol, so the packet being too short is an error
|
||||
tree:add_expert_info(PI_MALFORMED, PI_ERROR, "packet too short")
|
||||
dprint("packet length",pktlen,"too short")
|
||||
return
|
||||
end
|
||||
|
||||
|
@ -216,7 +237,7 @@ function dns.dissector(tvbuf,pktinfo,root)
|
|||
|
||||
-- for our flags field, we want a sub-tree
|
||||
local flag_tree = tree:add(pf_flags, flagrange)
|
||||
-- I'm indenting this for calarity, because it's adding to the flag's child-tree
|
||||
-- I'm indenting this for clarity, because it's adding to the flag's child-tree
|
||||
-- let's add the type of message (query vs. response)
|
||||
flag_tree:add(pf_flag_response, flagrange)
|
||||
|
||||
|
@ -312,16 +333,101 @@ function dns.dissector(tvbuf,pktinfo,root)
|
|||
end
|
||||
end
|
||||
|
||||
dprint2("dns.dissector returning",pos)
|
||||
|
||||
-- tell wireshark how much of tvbuff we dissected
|
||||
return pos
|
||||
end
|
||||
|
||||
----------------------------------------
|
||||
-- we want to have our protocol disseciton invoked for a specific UDP port,
|
||||
-- so get the udp dissecotr table and add our protocol to it
|
||||
-- we want to have our protocol dissection invoked for a specific UDP port,
|
||||
-- so get the udp dissector table and add our protocol to it
|
||||
local udp_encap_table = DissectorTable.get("udp.port")
|
||||
udp_encap_table:add(MYDNS_PROTO_UDP_PORT, dns)
|
||||
|
||||
----------------------------------------
|
||||
-- we also want to add the heuristic dissector, for any UDP protocol
|
||||
-- first we need a heuristic dissection function
|
||||
-- this is that function - when wireshark invokes this, it will pass in the same
|
||||
-- things it passes in to the "dissector" function, but we only want to actually
|
||||
-- dissect it if it's for us, and we need to return true if it's for us, or else false
|
||||
-- figuring out if it's for us or not is not easy
|
||||
-- we need to try as hard as possible, or else we'll think it's for us when it's
|
||||
-- not and block other heuristic dissectors from getting their chanc
|
||||
--
|
||||
-- in practice, you'd never set a dissector like this to be heuristic, because there
|
||||
-- just isn't enough information to safely detect if it's DNS or not
|
||||
-- but I'm doing it to show how it would be done
|
||||
--
|
||||
-- Note: this heuristic stuff is new in 1.11.3
|
||||
local function heur_dissect_dns(tvbuf,pktinfo,root)
|
||||
dprint2("heur_dissect_dns called")
|
||||
|
||||
if tvbuf:len() < DNS_HDR_LEN then
|
||||
dprint("heur_dissect_dns: tvb shorter than DNS_HDR_LEN of:",DNS_HDR_LEN)
|
||||
return false
|
||||
end
|
||||
|
||||
local tvbr = tvbuf:range(0,DNS_HDR_LEN)
|
||||
|
||||
-- the first 2 bytes are tansaction id, which can be anything so no point in checking those
|
||||
-- the next 2 bytes contain flags, a couple of which have some values we can check against
|
||||
|
||||
-- the opcode has to be 0, 1, 2, 4 or 5
|
||||
-- the opcode field starts at bit offset 17 (in C-indexing), for 4 bits in length
|
||||
local check = tvbr:bitfield(17,4)
|
||||
if check == 3 or check > 5 then
|
||||
dprint("heur_dissect_dns: invalid opcode:",check)
|
||||
return false
|
||||
end
|
||||
|
||||
-- the rcode has to be 0-10, 16-22 (we're ignoring private use rcodes here)
|
||||
-- the rcode field starts at bit offset 28 (in C-indexing), for 4 bits in length
|
||||
check = tvbr:bitfield(28,4)
|
||||
if check > 22 or (check > 10 and check < 16) then
|
||||
dprint("heur_dissect_dns: invalid rcode:",check)
|
||||
return false
|
||||
end
|
||||
|
||||
dprint2("heur_dissect_dns checking questions/answers")
|
||||
|
||||
-- now let's verify the number of questions/answers are reasonable
|
||||
check = tvbr:range(4,2):uint() -- num questions
|
||||
if check > 100 then return false end
|
||||
check = tvbr:range(6,2):uint() -- num answers
|
||||
if check > 100 then return false end
|
||||
check = tvbr:range(8,2):uint() -- num authority
|
||||
if check > 100 then return false end
|
||||
check = tvbr:range(10,2):uint() -- num additional
|
||||
if check > 100 then return false end
|
||||
|
||||
dprint2("heur_dissect_dns: everything looks good calling the real dissector")
|
||||
|
||||
-- don't do this line in your script - I'm just doing it so our testsuite can
|
||||
-- verify this script
|
||||
root:add("Heuristic dissector used"):set_generated()
|
||||
|
||||
-- ok, looks like it's ours, so go dissect it
|
||||
-- note: calling the dissector directly like this is new in 1.11.3
|
||||
-- also note that calling a Dissector objkect, as this does, means we don't
|
||||
-- get back the return value of the dissector function we created previously
|
||||
-- so it might be better to just call the function directly instead of doing
|
||||
-- this, but this script is used for testing and this tests the call() function
|
||||
dns.dissector(tvbuf,pktinfo,root)
|
||||
|
||||
-- since this is over a transport protocol, such as UDP, we can set the
|
||||
-- conversation to make it sticky for our dissector, so that all future
|
||||
-- packets to/from the same address:port pair will just call our dissector
|
||||
-- function directly instead of this heuristic function
|
||||
-- this is a new attribute of pinfo in 1.11.3
|
||||
pktinfo.conversation = dns
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
-- now register that heuristic dissector into the udp heuristic list
|
||||
dns:register_heuristic("udp",heur_dissect_dns)
|
||||
|
||||
-- We're done!
|
||||
-- our protocol (Proto) gets automatically registered after this script finishes loading
|
||||
----------------------------------------
|
||||
|
@ -361,6 +467,7 @@ getQueryName = function (tvbr)
|
|||
end
|
||||
pos = pos + 1 -- move past label length octet
|
||||
-- append the label and a dot to name string
|
||||
-- note: this uses the new method of ByteArray:raw(), added in 1.11.3
|
||||
name = name .. barray:raw(pos, label_len) .. "."
|
||||
len_remaining = len_remaining - (label_len + 1) -- subtract label and its length octet
|
||||
label_count = label_count + 1
|
||||
|
|
|
@ -47,7 +47,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]=2, [OTHER]=48 }
|
||||
local taptests = { [FRAME]=4, [OTHER]=48 }
|
||||
local function getResults()
|
||||
print("\n-----------------------------\n")
|
||||
for k,v in pairs(taptests) do
|
||||
|
@ -497,6 +497,81 @@ end
|
|||
local udp_encap_table = DissectorTable.get("udp.port")
|
||||
udp_encap_table:add(MYDNS_PROTO_UDP_PORT, dns)
|
||||
|
||||
----------------------------------------
|
||||
-- we also want to add the heuristic dissector, for any UDP protocol
|
||||
-- first we need a heuristic dissection function
|
||||
-- this is that function - when wireshark invokes this, it will pass in the same
|
||||
-- things it passes in to the "dissector" function, but we only want to actually
|
||||
-- dissect it if it's for us, and we need to return true if it's for us, or else false
|
||||
-- figuring out if it's for us or not is not easy
|
||||
-- we need to try as hard as possible, or else we'll think it's for us when it's
|
||||
-- not and block other heuristic dissectors from getting their chanc
|
||||
--
|
||||
-- in practice, you'd never set a dissector like this to be heuristic, because there
|
||||
-- just isn't enough information to safely detect if it's DNS or not
|
||||
-- but I'm doing it to show how it would be done
|
||||
--
|
||||
-- Note: this heuristic stuff is new in 1.11.3
|
||||
local function heur_dissect_dns(tvbuf,pktinfo,root)
|
||||
|
||||
if tvbuf:len() < DNS_HDR_LEN then
|
||||
return false
|
||||
end
|
||||
|
||||
local tvbr = tvbuf:range(0,DNS_HDR_LEN)
|
||||
|
||||
-- the first 2 bytes are tansaction id, which can be anything so no point in checking those
|
||||
-- the next 2 bytes contain flags, a couple of which have some values we can check against
|
||||
|
||||
-- the opcode has to be 0, 1, 2, 4 or 5
|
||||
-- the opcode field starts at bit offset 17 (in C-indexing), for 4 bits in length
|
||||
local check = tvbr:bitfield(17,4)
|
||||
if check == 3 or check > 5 then
|
||||
return false
|
||||
end
|
||||
|
||||
-- the rcode has to be 0-10, 16-22 (we're ignoring private use rcodes here)
|
||||
-- the rcode field starts at bit offset 28 (in C-indexing), for 4 bits in length
|
||||
check = tvbr:bitfield(28,4)
|
||||
if check > 22 or (check > 10 and check < 16) then
|
||||
return false
|
||||
end
|
||||
|
||||
-- now let's verify the number of questions/answers are reasonable
|
||||
check = tvbr:range(4,2):uint() -- num questions
|
||||
if check > 100 then return false end
|
||||
check = tvbr:range(6,2):uint() -- num answers
|
||||
if check > 100 then return false end
|
||||
check = tvbr:range(8,2):uint() -- num authority
|
||||
if check > 100 then return false end
|
||||
check = tvbr:range(10,2):uint() -- num additional
|
||||
if check > 100 then return false end
|
||||
|
||||
-- don't do this line in your script - I'm just doing it so our testsuite can
|
||||
-- verify this script
|
||||
root:add("Heuristic dissector used"):set_generated()
|
||||
|
||||
-- ok, looks like it's ours, so go dissect it
|
||||
-- note: calling the dissector directly like this is new in 1.11.3
|
||||
-- also note that calling a Dissector objkect, as this does, means we don't
|
||||
-- get back the return value of the dissector function we created previously
|
||||
-- so it might be better to just call the function directly instead of doing
|
||||
-- this, but this script is used for testing and this tests the call() function
|
||||
dns.dissector(tvbuf,pktinfo,root)
|
||||
|
||||
-- since this is over a transport protocol, such as UDP, we can set the
|
||||
-- conversation to make it sticky for our dissector, so that all future
|
||||
-- packets to/from the same address:port pair will just call our dissector
|
||||
-- function directly instead of this heuristic function
|
||||
-- this is a new attribute of pinfo in 1.11.3
|
||||
pktinfo.conversation = dns
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
-- now register that heuristic dissector into the udp heuristic list
|
||||
dns:register_heuristic("udp",heur_dissect_dns)
|
||||
|
||||
-- We're done!
|
||||
-- our protocol (Proto) gets automatically registered after this script finishes loading
|
||||
----------------------------------------
|
||||
|
|
|
@ -61,7 +61,10 @@ local lines = {
|
|||
}
|
||||
}
|
||||
|
||||
local numtests = #lines[1] + #lines[2]
|
||||
-- we're going to see those two sets of output twice: both by the normal
|
||||
-- dissector, then the first one by the heuristic, then the second one by
|
||||
-- a conversation match
|
||||
local numtests = 1 + (2 * (#lines[1] + #lines[2]))
|
||||
print("going to run "..numtests.." tests")
|
||||
|
||||
-- for an example of what we're reading through to verify, look at end of this file
|
||||
|
@ -71,6 +74,7 @@ local line = file:read()
|
|||
|
||||
local pktidx = 1
|
||||
local total = 0
|
||||
local found = false
|
||||
|
||||
while line do
|
||||
-- eat beginning whitespace
|
||||
|
@ -79,6 +83,18 @@ while line do
|
|||
pktidx = line:match("^Frame (%d+):")
|
||||
testing("Frame "..pktidx)
|
||||
pktidx = tonumber(pktidx)
|
||||
if pktidx > 2 then pktidx = pktidx - 2 end
|
||||
line = file:read()
|
||||
elseif line:find("%[Heuristic dissector used%]") then
|
||||
-- start again, because it now repeats
|
||||
-- but we should not see this [Heuristic dissector used] line again
|
||||
-- or it's an error in setting the conversation
|
||||
if found then
|
||||
error("Heuristic dissector ran twice - conversation setting not working?")
|
||||
return
|
||||
end
|
||||
found = true
|
||||
total = total + 1
|
||||
line = file:read()
|
||||
elseif line == lines[pktidx][1] then
|
||||
-- we've matched the first line of our section
|
||||
|
|
|
@ -39,7 +39,7 @@ wslua_step_dissector_test() {
|
|||
fi
|
||||
|
||||
# then run tshark again with the verification script. (it internally reads in testin.txt)
|
||||
$TSHARK -r $CAPTURE_DIR/dns_port.pcap -X lua_script:$TESTS_DIR/lua/verify_dissector.lua > testout.txt 2>&1
|
||||
$TSHARK -r $CAPTURE_DIR/empty.pcap -X lua_script:$TESTS_DIR/lua/verify_dissector.lua > testout.txt 2>&1
|
||||
if grep -q "All tests passed!" testout.txt; then
|
||||
test_step_ok
|
||||
else
|
||||
|
@ -121,7 +121,7 @@ wslua_step_proto_test() {
|
|||
return
|
||||
fi
|
||||
|
||||
# First run tshark with the dissector script.
|
||||
# First run tshark with the proto script.
|
||||
$TSHARK -r $CAPTURE_DIR/dns_port.pcap -V -X lua_script:$TESTS_DIR/lua/proto.lua > testin.txt 2>&1
|
||||
grep -q "All tests passed!" testin.txt
|
||||
if [ $? -ne 0 ]; then
|
||||
|
@ -130,7 +130,7 @@ wslua_step_proto_test() {
|
|||
fi
|
||||
|
||||
# then run tshark again with the verification script. (it internally reads in testin.txt)
|
||||
$TSHARK -r $CAPTURE_DIR/dns_port.pcap -X lua_script:$TESTS_DIR/lua/verify_dissector.lua > testout.txt 2>&1
|
||||
$TSHARK -r $CAPTURE_DIR/empty.pcap -X lua_script:$TESTS_DIR/lua/verify_dissector.lua > testout.txt 2>&1
|
||||
if grep -q "All tests passed!" testout.txt; then
|
||||
test_step_ok
|
||||
else
|
||||
|
@ -148,7 +148,7 @@ wslua_step_int64_test() {
|
|||
fi
|
||||
|
||||
# Tshark catches lua script failures, so we have to parse the output.
|
||||
$TSHARK -r $CAPTURE_DIR/dhcp.pcap -X lua_script:$TESTS_DIR/lua/int64.lua > testout.txt 2>&1
|
||||
$TSHARK -r $CAPTURE_DIR/empty.pcap -X lua_script:$TESTS_DIR/lua/int64.lua > testout.txt 2>&1
|
||||
if grep -q "All tests passed!" testout.txt; then
|
||||
test_step_ok
|
||||
else
|
||||
|
@ -165,30 +165,30 @@ wslua_step_args_test() {
|
|||
fi
|
||||
|
||||
# Tshark catches lua script failures, so we have to parse the output.
|
||||
$TSHARK -r $CAPTURE_DIR/dhcp.pcap -X lua_script:$TESTS_DIR/lua/script_args.lua -X lua_script1:1 > testout.txt 2>&1
|
||||
$TSHARK -r $CAPTURE_DIR/empty.pcap -X lua_script:$TESTS_DIR/lua/script_args.lua -X lua_script1:1 > testout.txt 2>&1
|
||||
grep -q "All tests passed!" testout.txt
|
||||
if [ $? -ne 0 ]; then
|
||||
cat testout.txt
|
||||
test_step_failed "lua_args_test test 1 failed"
|
||||
fi
|
||||
$TSHARK -r $CAPTURE_DIR/dhcp.pcap -X lua_script:$TESTS_DIR/lua/script_args.lua -X lua_script1:3 -X lua_script1:foo -X lua_script1:bar > testout.txt 2>&1
|
||||
$TSHARK -r $CAPTURE_DIR/empty.pcap -X lua_script:$TESTS_DIR/lua/script_args.lua -X lua_script1:3 -X lua_script1:foo -X lua_script1:bar > testout.txt 2>&1
|
||||
grep -q "All tests passed!" testout.txt
|
||||
if [ $? -ne 0 ]; then
|
||||
cat testout.txt
|
||||
test_step_failed "lua_args_test test 2 failed"
|
||||
fi
|
||||
$TSHARK -r $CAPTURE_DIR/dhcp.pcap -X lua_script:$TESTS_DIR/lua/script_args.lua -X lua_script:$TESTS_DIR/lua/script_args.lua -X lua_script1:3 -X lua_script2:1 -X lua_script1:foo -X lua_script1:bar > testout.txt 2>&1
|
||||
$TSHARK -r $CAPTURE_DIR/empty.pcap -X lua_script:$TESTS_DIR/lua/script_args.lua -X lua_script:$TESTS_DIR/lua/script_args.lua -X lua_script1:3 -X lua_script2:1 -X lua_script1:foo -X lua_script1:bar > testout.txt 2>&1
|
||||
grep -q "All tests passed!" testout.txt
|
||||
if [ $? -ne 0 ]; then
|
||||
cat testout.txt
|
||||
test_step_failed "lua_args_test test 3 failed"
|
||||
fi
|
||||
$TSHARK -r $CAPTURE_DIR/dhcp.pcap -X lua_script:$TESTS_DIR/lua/script_args.lua > testout.txt 2>&1
|
||||
$TSHARK -r $CAPTURE_DIR/empty.pcap -X lua_script:$TESTS_DIR/lua/script_args.lua > testout.txt 2>&1
|
||||
if grep -q "All tests passed!" testout.txt; then
|
||||
cat testout.txt
|
||||
test_step_failed "lua_args_test negative test 4 failed"
|
||||
fi
|
||||
$TSHARK -r $CAPTURE_DIR/dhcp.pcap -X lua_script:$TESTS_DIR/lua/script_args.lua -X lua_script1:3 > testout.txt 2>&1
|
||||
$TSHARK -r $CAPTURE_DIR/empty.pcap -X lua_script:$TESTS_DIR/lua/script_args.lua -X lua_script1:3 > testout.txt 2>&1
|
||||
if grep -q "All tests passed!" testout.txt; then
|
||||
cat testout.txt
|
||||
test_step_failed "lua_args_test negative test 5 failed"
|
||||
|
@ -241,7 +241,7 @@ wslua_step_struct_test() {
|
|||
fi
|
||||
|
||||
# Tshark catches lua script failures, so we have to parse the output.
|
||||
$TSHARK -r $CAPTURE_DIR/dhcp.pcap -X lua_script:$TESTS_DIR/lua/struct.lua > testout.txt 2>&1
|
||||
$TSHARK -r $CAPTURE_DIR/empty.pcap -X lua_script:$TESTS_DIR/lua/struct.lua > testout.txt 2>&1
|
||||
if grep -q "All tests passed!" testout.txt; then
|
||||
test_step_ok
|
||||
else
|
||||
|
|
Loading…
Reference in New Issue