diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-09-19 04:14:26 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-09-19 04:14:26 +0000 |
commit | c4e8a3222648fcf22ca207f1815ebbf7cd144eeb (patch) | |
tree | 93d5c6aa93d9987680dd1adad5685e2ad698f223 /epan/wslua/init_wslua.c | |
parent | Adding upstream version 4.2.6. (diff) | |
download | wireshark-upstream.tar.xz wireshark-upstream.zip |
Adding upstream version 4.4.0.upstream/4.4.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | epan/wslua/init_wslua.c | 621 |
1 files changed, 361 insertions, 260 deletions
diff --git a/epan/wslua/init_wslua.c b/epan/wslua/init_wslua.c index 3e701ffc..065eaf38 100644 --- a/epan/wslua/init_wslua.c +++ b/epan/wslua/init_wslua.c @@ -18,9 +18,7 @@ #include "wslua.h" #include "init_wslua.h" -#include <epan/dissectors/packet-frame.h> #include <errno.h> -#include <math.h> #include <stdio.h> #include <epan/expert.h> #include <epan/ex-opt.h> @@ -29,21 +27,22 @@ #include <wsutil/privileges.h> #include <wsutil/file_util.h> #include <wsutil/wslog.h> +#include <wsutil/array.h> /* linked list of Lua plugins */ typedef struct _wslua_plugin { - gchar *name; /**< plugin name */ - gchar *version; /**< plugin version */ - gchar *filename; /**< plugin filename */ + char *name; /**< plugin name */ + char *version; /**< plugin version */ + char *filename; /**< plugin filename */ struct _wslua_plugin *next; } wslua_plugin; -static wslua_plugin *wslua_plugin_list = NULL; +static wslua_plugin *wslua_plugin_list; -static lua_State* L = NULL; +static lua_State* L; -static void (*wslua_gui_print_func_ptr)(const char *, void *) = NULL; -static void *wslua_gui_print_data_ptr = NULL; +static void (*wslua_gui_print_func_ptr)(const char *, void *); +static void *wslua_gui_print_data_ptr; static int wslua_lua_print_func_ref = LUA_NOREF; /* XXX: global variables? Really?? Yuck. These could be done differently, @@ -54,98 +53,110 @@ tvbuff_t* lua_tvb; int lua_dissectors_table_ref = LUA_NOREF; int lua_heur_dissectors_table_ref = LUA_NOREF; -static int proto_lua = -1; - -static int hf_wslua_fake = -1; -static int hf_wslua_text = -1; - -static expert_field ei_lua_error = EI_INIT; - -static expert_field ei_lua_proto_checksum_comment = EI_INIT; -static expert_field ei_lua_proto_checksum_chat = EI_INIT; -static expert_field ei_lua_proto_checksum_note = EI_INIT; -static expert_field ei_lua_proto_checksum_warn = EI_INIT; -static expert_field ei_lua_proto_checksum_error = EI_INIT; - -static expert_field ei_lua_proto_sequence_comment = EI_INIT; -static expert_field ei_lua_proto_sequence_chat = EI_INIT; -static expert_field ei_lua_proto_sequence_note = EI_INIT; -static expert_field ei_lua_proto_sequence_warn = EI_INIT; -static expert_field ei_lua_proto_sequence_error = EI_INIT; - -static expert_field ei_lua_proto_response_comment = EI_INIT; -static expert_field ei_lua_proto_response_chat = EI_INIT; -static expert_field ei_lua_proto_response_note = EI_INIT; -static expert_field ei_lua_proto_response_warn = EI_INIT; -static expert_field ei_lua_proto_response_error = EI_INIT; - -static expert_field ei_lua_proto_request_comment = EI_INIT; -static expert_field ei_lua_proto_request_chat = EI_INIT; -static expert_field ei_lua_proto_request_note = EI_INIT; -static expert_field ei_lua_proto_request_warn = EI_INIT; -static expert_field ei_lua_proto_request_error = EI_INIT; - -static expert_field ei_lua_proto_undecoded_comment = EI_INIT; -static expert_field ei_lua_proto_undecoded_chat = EI_INIT; -static expert_field ei_lua_proto_undecoded_note = EI_INIT; -static expert_field ei_lua_proto_undecoded_warn = EI_INIT; -static expert_field ei_lua_proto_undecoded_error = EI_INIT; - -static expert_field ei_lua_proto_reassemble_comment = EI_INIT; -static expert_field ei_lua_proto_reassemble_chat = EI_INIT; -static expert_field ei_lua_proto_reassemble_note = EI_INIT; -static expert_field ei_lua_proto_reassemble_warn = EI_INIT; -static expert_field ei_lua_proto_reassemble_error = EI_INIT; - -static expert_field ei_lua_proto_malformed_comment = EI_INIT; -static expert_field ei_lua_proto_malformed_chat = EI_INIT; -static expert_field ei_lua_proto_malformed_note = EI_INIT; -static expert_field ei_lua_proto_malformed_warn = EI_INIT; -static expert_field ei_lua_proto_malformed_error = EI_INIT; - -static expert_field ei_lua_proto_debug_comment = EI_INIT; -static expert_field ei_lua_proto_debug_chat = EI_INIT; -static expert_field ei_lua_proto_debug_note = EI_INIT; -static expert_field ei_lua_proto_debug_warn = EI_INIT; -static expert_field ei_lua_proto_debug_error = EI_INIT; - -static expert_field ei_lua_proto_protocol_comment = EI_INIT; -static expert_field ei_lua_proto_protocol_chat = EI_INIT; -static expert_field ei_lua_proto_protocol_note = EI_INIT; -static expert_field ei_lua_proto_protocol_warn = EI_INIT; -static expert_field ei_lua_proto_protocol_error = EI_INIT; - -static expert_field ei_lua_proto_security_comment = EI_INIT; -static expert_field ei_lua_proto_security_chat = EI_INIT; -static expert_field ei_lua_proto_security_note = EI_INIT; -static expert_field ei_lua_proto_security_warn = EI_INIT; -static expert_field ei_lua_proto_security_error = EI_INIT; - -static expert_field ei_lua_proto_comments_comment = EI_INIT; -static expert_field ei_lua_proto_comments_chat = EI_INIT; -static expert_field ei_lua_proto_comments_note = EI_INIT; -static expert_field ei_lua_proto_comments_warn = EI_INIT; -static expert_field ei_lua_proto_comments_error = EI_INIT; - -static expert_field ei_lua_proto_decryption_comment = EI_INIT; -static expert_field ei_lua_proto_decryption_chat = EI_INIT; -static expert_field ei_lua_proto_decryption_note = EI_INIT; -static expert_field ei_lua_proto_decryption_warn = EI_INIT; -static expert_field ei_lua_proto_decryption_error = EI_INIT; - -static expert_field ei_lua_proto_assumption_comment = EI_INIT; -static expert_field ei_lua_proto_assumption_chat = EI_INIT; -static expert_field ei_lua_proto_assumption_note = EI_INIT; -static expert_field ei_lua_proto_assumption_warn = EI_INIT; -static expert_field ei_lua_proto_assumption_error = EI_INIT; - -static expert_field ei_lua_proto_deprecated_comment = EI_INIT; -static expert_field ei_lua_proto_deprecated_chat = EI_INIT; -static expert_field ei_lua_proto_deprecated_note = EI_INIT; -static expert_field ei_lua_proto_deprecated_warn = EI_INIT; -static expert_field ei_lua_proto_deprecated_error = EI_INIT; - -static gint ett_wslua_traceback = -1; +static int proto_lua; + +static int hf_wslua_fake; +static int hf_wslua_text; + +static expert_field ei_lua_error; + +static expert_field ei_lua_proto_checksum_comment; +static expert_field ei_lua_proto_checksum_chat; +static expert_field ei_lua_proto_checksum_note; +static expert_field ei_lua_proto_checksum_warn; +static expert_field ei_lua_proto_checksum_error; + +static expert_field ei_lua_proto_sequence_comment; +static expert_field ei_lua_proto_sequence_chat; +static expert_field ei_lua_proto_sequence_note; +static expert_field ei_lua_proto_sequence_warn; +static expert_field ei_lua_proto_sequence_error; + +static expert_field ei_lua_proto_response_comment; +static expert_field ei_lua_proto_response_chat; +static expert_field ei_lua_proto_response_note; +static expert_field ei_lua_proto_response_warn; +static expert_field ei_lua_proto_response_error; + +static expert_field ei_lua_proto_request_comment; +static expert_field ei_lua_proto_request_chat; +static expert_field ei_lua_proto_request_note; +static expert_field ei_lua_proto_request_warn; +static expert_field ei_lua_proto_request_error; + +static expert_field ei_lua_proto_undecoded_comment; +static expert_field ei_lua_proto_undecoded_chat; +static expert_field ei_lua_proto_undecoded_note; +static expert_field ei_lua_proto_undecoded_warn; +static expert_field ei_lua_proto_undecoded_error; + +static expert_field ei_lua_proto_reassemble_comment; +static expert_field ei_lua_proto_reassemble_chat; +static expert_field ei_lua_proto_reassemble_note; +static expert_field ei_lua_proto_reassemble_warn; +static expert_field ei_lua_proto_reassemble_error; + +static expert_field ei_lua_proto_malformed_comment; +static expert_field ei_lua_proto_malformed_chat; +static expert_field ei_lua_proto_malformed_note; +static expert_field ei_lua_proto_malformed_warn; +static expert_field ei_lua_proto_malformed_error; + +static expert_field ei_lua_proto_debug_comment; +static expert_field ei_lua_proto_debug_chat; +static expert_field ei_lua_proto_debug_note; +static expert_field ei_lua_proto_debug_warn; +static expert_field ei_lua_proto_debug_error; + +static expert_field ei_lua_proto_protocol_comment; +static expert_field ei_lua_proto_protocol_chat; +static expert_field ei_lua_proto_protocol_note; +static expert_field ei_lua_proto_protocol_warn; +static expert_field ei_lua_proto_protocol_error; + +static expert_field ei_lua_proto_security_comment; +static expert_field ei_lua_proto_security_chat; +static expert_field ei_lua_proto_security_note; +static expert_field ei_lua_proto_security_warn; +static expert_field ei_lua_proto_security_error; + +static expert_field ei_lua_proto_comments_comment; +static expert_field ei_lua_proto_comments_chat; +static expert_field ei_lua_proto_comments_note; +static expert_field ei_lua_proto_comments_warn; +static expert_field ei_lua_proto_comments_error; + +static expert_field ei_lua_proto_decryption_comment; +static expert_field ei_lua_proto_decryption_chat; +static expert_field ei_lua_proto_decryption_note; +static expert_field ei_lua_proto_decryption_warn; +static expert_field ei_lua_proto_decryption_error; + +static expert_field ei_lua_proto_assumption_comment; +static expert_field ei_lua_proto_assumption_chat; +static expert_field ei_lua_proto_assumption_note; +static expert_field ei_lua_proto_assumption_warn; +static expert_field ei_lua_proto_assumption_error; + +static expert_field ei_lua_proto_deprecated_comment; +static expert_field ei_lua_proto_deprecated_chat; +static expert_field ei_lua_proto_deprecated_note; +static expert_field ei_lua_proto_deprecated_warn; +static expert_field ei_lua_proto_deprecated_error; + +static expert_field ei_lua_proto_receive_comment; +static expert_field ei_lua_proto_receive_chat; +static expert_field ei_lua_proto_receive_note; +static expert_field ei_lua_proto_receive_warn; +static expert_field ei_lua_proto_receive_error; + +static expert_field ei_lua_proto_interface_comment; +static expert_field ei_lua_proto_interface_chat; +static expert_field ei_lua_proto_interface_note; +static expert_field ei_lua_proto_interface_warn; +static expert_field ei_lua_proto_interface_error; + +static int ett_wslua_traceback; static bool lua_pinfo_end(wmem_allocator_t *allocator _U_, wmem_cb_event_t event _U_, @@ -162,7 +173,7 @@ lua_pinfo_end(wmem_allocator_t *allocator _U_, wmem_cb_event_t event _U_, clear_outstanding_FuncSavers(); /* keep invoking this callback later? */ - return FALSE; + return false; } static int wslua_not_register_menu(lua_State* LS) { @@ -175,7 +186,7 @@ int get_hf_wslua_text(void) { return hf_wslua_text; } -#if LUA_VERSION_NUM >= 502 + // Attach the lua traceback to the proto_tree static int dissector_error_handler(lua_State *LS) { // Entering, stack: [ error_handler, dissector, errmsg ] @@ -259,18 +270,6 @@ static int dissector_error_handler(lua_State *LS) { return -2; } -#else - -static int dissector_error_handler(lua_State *LS) { - // Entering, stack: [ error_handler, dissector, errmsg ] - proto_tree_add_expert_format(lua_tree->tree, lua_pinfo, &ei_lua_error, lua_tvb, 0, 0, - "Lua Error: %s", lua_tostring(LS,-1)); - - // Return the same error message - return -1; -} - -#endif int dissect_lua(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, void* data _U_) { int consumed_bytes = tvb_captured_length(tvb); @@ -326,7 +325,7 @@ int dissect_lua(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, void* data /* if the Lua dissector reported the consumed bytes, pass it to our caller */ if (lua_isnumber(L, -1)) { /* we got the consumed bytes or the missing bytes as a negative number */ - consumed_bytes = wslua_togint(L, -1); + consumed_bytes = wslua_toint(L, -1); lua_pop(L, 1); } } @@ -351,10 +350,10 @@ int dissect_lua(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, void* data * @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) + * @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; +bool heur_dissect_lua(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, void* data _U_) { + bool result = false; tvbuff_t *saved_lua_tvb = lua_tvb; packet_info *saved_lua_pinfo = lua_pinfo; struct _wslua_treeitem *saved_lua_tree = lua_tree; @@ -366,7 +365,7 @@ gboolean heur_dissect_lua(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, v if (!pinfo->heur_list_name || !pinfo->current_proto) { proto_tree_add_expert_format(tree, pinfo, &ei_lua_error, tvb, 0, 0, "internal error in heur_dissect_lua: NULL list name or current proto"); - return FALSE; + return false; } /* heuristic functions are stored in a table in the registry; the registry has a @@ -387,7 +386,7 @@ gboolean heur_dissect_lua(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, v lua_settop(L,0); proto_tree_add_expert_format(tree, pinfo, &ei_lua_error, tvb, 0, 0, "internal error in heur_dissect_lua: no %s heur list table", pinfo->heur_list_name); - return FALSE; + return false; } /* get the table inside that, for the specific lua heuristic dissector */ @@ -397,7 +396,7 @@ gboolean heur_dissect_lua(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, v proto_tree_add_expert_format(tree, pinfo, &ei_lua_error, tvb, 0, 0, "internal error in heur_dissect_lua: no %s heuristic dissector for list %s", pinfo->current_proto, pinfo->heur_list_name); - return FALSE; + return false; } /* remove the table of all lists (the one in the registry) */ @@ -410,7 +409,7 @@ gboolean heur_dissect_lua(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, v lua_settop(L,0); proto_tree_add_expert_format(tree, pinfo, &ei_lua_error, tvb, 0, 0, "internal error in heur_dissect_lua: %s heuristic dissector is not a function", pinfo->current_proto); - return FALSE; + return false; } push_Tvb(L,tvb); @@ -426,7 +425,7 @@ gboolean heur_dissect_lua(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, v if (lua_isboolean(L, -1) || lua_isnil(L, -1)) { result = lua_toboolean(L, -1); } else if (lua_type(L, -1) == LUA_TNUMBER) { - result = lua_tointeger(L,-1) != 0 ? TRUE : FALSE; + result = lua_tointeger(L,-1) != 0 ? true : false; } else { proto_tree_add_expert_format(tree, pinfo, &ei_lua_error, tvb, 0, 0, "Lua Error: invalid return value from Lua %s heuristic dissector", pinfo->current_proto); @@ -443,7 +442,7 @@ gboolean heur_dissect_lua(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, v return result; } -static void iter_table_and_call(lua_State* LS, const gchar* table_name, lua_CFunction error_handler) { +static void iter_table_and_call(lua_State* LS, const char* table_name, lua_CFunction error_handler) { lua_settop(LS,0); lua_pushcfunction(LS,error_handler); @@ -459,7 +458,7 @@ static void iter_table_and_call(lua_State* LS, const gchar* table_name, lua_CFun lua_pushnil(LS); while (lua_next(LS, 2)) { - const gchar* name = lua_tostring(L,-2); + const char* name = lua_tostring(L,-2); if (lua_isfunction(LS,-1)) { @@ -480,13 +479,13 @@ static void iter_table_and_call(lua_State* LS, const gchar* table_name, lua_CFun static int init_error_handler(lua_State* LS) { - const gchar* error = lua_tostring(LS,1); + const char* error = lua_tostring(LS,1); report_failure("Lua: Error during execution of initialization:\n %s",error); return 0; } -static gboolean init_routine_initialized = FALSE; +static bool init_routine_initialized; static void wslua_init_routine(void) { if ( ! init_routine_initialized ) { @@ -501,7 +500,7 @@ static void wslua_init_routine(void) { * Lua states, we'll need to change this. */ lua_prime_all_fields(NULL); - init_routine_initialized = TRUE; + init_routine_initialized = true; } if (L) { @@ -517,7 +516,7 @@ static void wslua_cleanup_routine(void) { } static int prefs_changed_error_handler(lua_State* LS) { - const gchar* error = lua_tostring(LS,1); + const char* error = lua_tostring(LS,1); report_failure("Lua: Error during execution of prefs apply callback:\n %s",error); return 0; } @@ -538,18 +537,13 @@ static const char *getF(lua_State *LS _U_, void *ud, size_t *size) } static int error_handler_with_callback(lua_State *LS) { -#if LUA_VERSION_NUM >= 502 const char *msg = lua_tostring(LS, 1); luaL_traceback(LS, LS, msg, 1); /* push message with traceback. */ lua_remove(LS, -2); /* remove original msg */ -#else - /* Return error message, unmodified */ - (void)LS; -#endif return 1; } -static void wslua_add_plugin(const gchar *name, const gchar *version, const gchar *filename) +static void wslua_add_plugin(const char *name, const char *version, const char *filename) { wslua_plugin *new_plug, *lua_plug; @@ -586,8 +580,8 @@ static void wslua_clear_plugin_list(void) } static int lua_script_push_args(const int script_num) { - gchar* argname = ws_strdup_printf("lua_script%d", script_num); - const gchar* argvalue = NULL; + char* argname = ws_strdup_printf("lua_script%d", script_num); + const char* argvalue = NULL; int i, count = ex_opt_count(argname); for (i = 0; i < count; i++) { @@ -599,67 +593,134 @@ static int lua_script_push_args(const int script_num) { return count; } +/* Prepends a path to the global package path (used by require) + * We could add a custom loader to package.searchers instead, which + * might be more useful in some way. We could also have some method of + * saving and restoring the path, instead of constantly adding to it. */ +static void prepend_path(const char* dirname) { + const char* path; + + /* prepend the directory name to _G.package.path */ + lua_getglobal(L, "package"); /* get the package table from the global table */ + lua_getfield(L, -1, "path"); /* get the path field from the package table */ + path = luaL_checkstring(L, -1); /* get the path string */ + lua_pop(L, 1); /* pop the path string */ + /* prepend the path */ + /* We could also add "?/init.lua" for packages. */ + lua_pushfstring(L, "%s" G_DIR_SEPARATOR_S "?.lua;%s", + dirname, path); + lua_setfield(L, -2, "path"); + lua_pop(L, 1); +} + #define FILE_NAME_KEY "__FILE__" #define DIR_NAME_KEY "__DIR__" #define DIR_SEP_NAME_KEY "__DIR_SEPARATOR__" /* assumes a loaded chunk's function is on top of stack */ -static void set_file_environment(const gchar* filename, const gchar* dirname) { - const char* path; - +static void set_file_environment(const char* filename, const char* dirname) { lua_newtable(L); /* environment for script (index 3) */ + /* XXX - Do we need this? A script can get the filename and path from + * debug.getinfo/lua_Debug source */ lua_pushstring(L, filename); /* tell the script about its filename */ lua_setfield(L, -2, FILE_NAME_KEY); /* make it accessible at __FILE__ */ lua_pushstring(L, dirname); /* tell the script about its dirname */ lua_setfield(L, -2, DIR_NAME_KEY); /* make it accessible at __DIR__ */ + /* XXX - Do we need this? package.config:sub(1,1) is the directory separator */ lua_pushstring(L, G_DIR_SEPARATOR_S); /* tell the script the directory separator */ - lua_setfield(L, -2, DIR_SEP_NAME_KEY); /* make it accessible at __DIR__ */ + lua_setfield(L, -2, DIR_SEP_NAME_KEY); /* make it accessible at __DIR_SEPARATOR__ */ lua_newtable(L); /* new metatable */ -#if LUA_VERSION_NUM >= 502 lua_pushglobaltable(L); -#else - lua_pushvalue(L, LUA_GLOBALSINDEX); -#endif - /* prepend the directory name to _G.package.path */ - lua_getfield(L, -1, "package"); /* get the package table from the global table */ - lua_getfield(L, -1, "path"); /* get the path field from the package table */ - path = luaL_checkstring(L, -1); /* get the path string */ - lua_pop(L, 1); /* pop the path string */ - /* prepend the various paths */ - lua_pushfstring(L, "%s" G_DIR_SEPARATOR_S "?.lua;%s" G_DIR_SEPARATOR_S "?.lua;%s" G_DIR_SEPARATOR_S "?.lua;%s", - dirname, get_plugins_pers_dir(), get_plugins_dir(), path); - lua_setfield(L, -2, "path"); /* set the new string to be the path field of the package table */ - lua_setfield(L, -2, "package"); /* set the package table to be the package field of the global */ lua_setfield(L, -2, "__index"); /* make metatable's __index point to global table */ lua_setmetatable(L, -2); /* pop metatable, set it as metatable of environment */ -#if LUA_VERSION_NUM >= 502 lua_setupvalue(L, -2, 1); /* pop environment and assign it to upvalue 1 */ -#else - lua_setfenv(L, -2); /* pop environment and set it as the func's environment */ -#endif + + /* The result of this is a new environment that falls back to reading from + * the global environment for any entry not in the new environment, but + * can't change the global environment while running. + * + * Unfortunately, while we could create a file-local package.path, it + * wouldn't have any effect on the path actually used by requires, since + * the requires function has as an upvalue the original package table; + * we can't change the behavior of requires without changing it for + * the global environment and for all scripts. + * + * For some of the same reasons, if the script itself calls require(), + * that actually affects the original global environment too, so this + * sandboxing doesn't completely work to keep the global environment + * unchanged. Is it worth it? + */ } +/* This loads plugins like Lua modules / libraries, using require(). + * It has the advantage that loaded files get add to the package.loaded + * table, so files aren't run again by require() either. + */ +static bool lua_load_plugin(const char* filename) { + int status; + char *trimmed; + + const char *basename = get_basename(filename); + char *dot = strrchr(basename, '.'); + if (dot) { + trimmed = g_strndup(basename, dot - basename); + } else { + trimmed = g_strdup(basename); + } + + lua_settop(L, 0); + + lua_pushcfunction(L, error_handler_with_callback); + + lua_getglobal(L, "require"); + + lua_pushstring(L, trimmed); + g_free(trimmed); + + /* Ignore the return from "require" by passing 0 as nresults to lua_pcall + * (we could add it to the global table using the name as dolibrary() does, + * but that is deprecated style in modern Lua.) + */ + status = lua_pcall(L, 1, 0, 1); + if (status != LUA_OK) { + switch (status) { + case LUA_ERRRUN: + report_failure("Lua: Error during loading:\n%s", lua_tostring(L, -1)); + break; + case LUA_ERRMEM: + report_failure("Lua: Error during loading: out of memory"); + break; + case LUA_ERRERR: + report_failure("Lua: Error during loading: error while retrieving error message"); + break; + default: + report_failure("Lua: Error during loading: unknown error %d", status); + break; + } + } + return status == LUA_OK; +} /* If file_count > 0 then it's a command-line-added user script, and the count * represents which user script it is (first=1, second=2, etc.). * If dirname != NULL, then it's a user script and the dirname will get put in a file environment * If dirname == NULL then it's a wireshark script and no file environment is created */ -static gboolean lua_load_script(const gchar* filename, const gchar* dirname, const int file_count) { +static bool lua_load_script(const char* filename, const char* dirname, const int file_count) { FILE* file; int error; int numargs = 0; if (! ( file = ws_fopen(filename,"r")) ) { - report_open_failure(filename,errno,FALSE); - return FALSE; + report_open_failure(filename,errno,false); + return false; } lua_settop(L,0); @@ -668,11 +729,7 @@ static gboolean lua_load_script(const gchar* filename, const gchar* dirname, con /* The source argument should start with '@' to indicate a file. */ lua_pushfstring(L, "@%s", filename); -#if LUA_VERSION_NUM >= 502 error = lua_load(L, getF, file, lua_tostring(L, -1), NULL); -#else - error = lua_load(L, getF, file, lua_tostring(L, -1)); -#endif switch (error) { case 0: /* LUA_OK */ @@ -721,25 +778,26 @@ static gboolean lua_load_script(const gchar* filename, const gchar* dirname, con /* This one is used to load the init.lua scripts, or anything else * that shouldn't really be considered a real plugin. */ -static gboolean lua_load_internal_script(const gchar* filename) { +static bool lua_load_internal_script(const char* filename) { return lua_load_script(filename, NULL, 0); } -/* This one is used to load plugins: either from the plugin directories, - * or from the command line. +/* This one is used to load plugins from the plugin directories, + * or scripts from the command line. The latter have file_count > 0. */ -static gboolean lua_load_plugin_script(const gchar* name, - const gchar* filename, - const gchar* dirname, - const int file_count) +static bool lua_load_plugin_script(const char* name, + const char* filename, + const char* dirname, + const int file_count) { ws_debug("Loading lua script: %s", filename); - if (lua_load_script(filename, dirname, file_count)) { + if (file_count > 0 ? lua_load_script(filename, dirname, file_count) : + lua_load_plugin(filename)) { wslua_add_plugin(name, get_current_plugin_version(), filename); clear_current_plugin_version(); - return TRUE; + return true; } - return FALSE; + return false; } static int wslua_panic(lua_State* LS) { @@ -748,18 +806,18 @@ static int wslua_panic(lua_State* LS) { return 0; /* keep gcc happy */ } -static gint string_compare(gconstpointer a, gconstpointer b) { +static int string_compare(const void *a, const void *b) { return strcmp((const char*)a, (const char*)b); } -static int lua_load_plugins(const char *dirname, register_cb cb, gpointer client_data, - gboolean count_only, const gboolean is_user, GHashTable *loaded_files, +static int lua_load_plugins(const char *dirname, register_cb cb, void *client_data, + bool count_only, const bool is_user, GHashTable *loaded_files, int depth) { WS_DIR *dir; /* scanned directory */ WS_DIRENT *file; /* current file */ - gchar *filename, *dot; - const gchar *name; + char *filename, *dot; + const char *name; int plugins_counter = 0; GList *sorted_dirnames = NULL; GList *sorted_filenames = NULL; @@ -783,11 +841,11 @@ static int lua_load_plugins(const char *dirname, register_cb cb, gpointer client filename = ws_strdup_printf("%s" G_DIR_SEPARATOR_S "%s", dirname, name); if (test_for_directory(filename) == EISDIR) { - sorted_dirnames = g_list_prepend(sorted_dirnames, (gpointer)filename); + sorted_dirnames = g_list_prepend(sorted_dirnames, (void *)filename); continue; } - /* skip files starting wih . */ + /* skip files starting with . */ if (name[0] == '.') { g_free(filename); continue; @@ -801,7 +859,7 @@ static int lua_load_plugins(const char *dirname, register_cb cb, gpointer client } if (file_exists(filename)) { - sorted_filenames = g_list_prepend(sorted_filenames, (gpointer)filename); + sorted_filenames = g_list_prepend(sorted_filenames, (void *)filename); } else { g_free(filename); @@ -821,9 +879,14 @@ static int lua_load_plugins(const char *dirname, register_cb cb, gpointer client /* Process files in ASCIIbetical order */ if (sorted_filenames != NULL) { + /* If this is not the root of the plugin directory, add it to the path. + * XXX - Should we remove it after we're done with this directory? */ + if (depth > 0) { + prepend_path(dirname); + } sorted_filenames = g_list_sort(sorted_filenames, string_compare); for (l = sorted_filenames; l != NULL; l = l->next) { - filename = (gchar *)l->data; + filename = (char *)l->data; name = strrchr(filename, G_DIR_SEPARATOR) + 1; /* Check if we have already loaded this file name, if provided with a set */ @@ -848,27 +911,32 @@ static int lua_load_plugins(const char *dirname, register_cb cb, gpointer client return plugins_counter; } -static int lua_load_global_plugins(register_cb cb, gpointer client_data, - gboolean count_only) +static int lua_load_global_plugins(register_cb cb, void *client_data, + bool count_only) { - return lua_load_plugins(get_plugins_dir(), cb, client_data, count_only, FALSE, NULL, 0); + return lua_load_plugins(get_plugins_dir(), cb, client_data, count_only, false, NULL, 0); } -static int lua_load_pers_plugins(register_cb cb, gpointer client_data, - gboolean count_only) +static int lua_load_pers_plugins(register_cb cb, void *client_data, + bool count_only) { int plugins_counter = 0; /* aux table (set) to make sure we only load each file once (by name) */ + /* XXX - This doesn't prevent users from loading a file a second time + * via a different method, e.g., require() or dofile(). + * + * It shouldn't be needed now that we're calling require for the plugins. + */ GHashTable *loaded_user_scripts = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL); /* load user scripts */ - plugins_counter += lua_load_plugins(get_plugins_pers_dir(), cb, client_data, count_only, TRUE, loaded_user_scripts, 0); + plugins_counter += lua_load_plugins(get_plugins_pers_dir(), cb, client_data, count_only, true, loaded_user_scripts, 0); /* for backward compatibility check old plugin directory */ - char *old_path = get_persconffile_path("plugins", FALSE); + char *old_path = get_persconffile_path("plugins", false); if (strcmp(get_plugins_pers_dir(), old_path) != 0) { - plugins_counter += lua_load_plugins(old_path, cb, client_data, count_only, TRUE, loaded_user_scripts, 0); + plugins_counter += lua_load_plugins(old_path, cb, client_data, count_only, true, loaded_user_scripts, 0); } g_free(old_path); @@ -881,10 +949,10 @@ int wslua_count_plugins(void) { int plugins_counter; /* count global scripts */ - plugins_counter = lua_load_global_plugins(NULL, NULL, TRUE); + plugins_counter = lua_load_global_plugins(NULL, NULL, true); /* count user scripts */ - plugins_counter += lua_load_pers_plugins(NULL, NULL, TRUE); + plugins_counter += lua_load_pers_plugins(NULL, NULL, true); /* count scripts from command line */ plugins_counter += ex_opt_count("lua_script"); @@ -920,8 +988,8 @@ const char *wslua_plugin_type_name(void) { return "lua script"; } -static ei_register_info* ws_lua_ei = NULL; -static int ws_lua_ei_len = 0; +static ei_register_info* ws_lua_ei; +static int ws_lua_ei_len; expert_field* wslua_get_expert_field(const int group, const int severity) @@ -969,7 +1037,7 @@ add_table_symbol(const char *table, const char *name, int value) lua_getglobal(L, table); /* Set symbol in table. */ lua_pushstring(L, name); - lua_pushnumber(L, value); + lua_pushinteger(L, value); lua_settable(L, -3); /* Pop table from stack. */ lua_pop(L, 1); @@ -979,7 +1047,7 @@ static void add_global_symbol(const char *name, int value) { /* Set symbol in global environment. */ - lua_pushnumber(L, value); + lua_pushinteger(L, value); lua_setglobal(L, name); } @@ -988,7 +1056,7 @@ add_pi_severity_symbol(const char *name, int value) { lua_getglobal(L, WSLUA_EXPERT_TABLE); lua_getfield(L, -1, WSLUA_EXPERT_SEVERITY_TABLE); - lua_pushnumber(L, value); + lua_pushinteger(L, value); lua_setfield(L, -2, name); lua_pop(L, 2); } @@ -998,7 +1066,7 @@ add_pi_group_symbol(const char *name, int value) { lua_getglobal(L, WSLUA_EXPERT_TABLE); lua_getfield(L, -1, WSLUA_EXPERT_GROUP_TABLE); - lua_pushnumber(L, value); + lua_pushinteger(L, value); lua_setfield(L, -2, name); lua_pop(L, 2); } @@ -1007,11 +1075,13 @@ static void add_menu_group_symbol(const char *name, int value) { /* Set symbol in global environment. */ - lua_pushnumber(L, value); + lua_pushinteger(L, value); char *str = g_strdup(name); char *s = strstr(str, "_GROUP_"); - if (s == NULL) + if (s == NULL) { + g_free(str); return; + } *s = '\0'; s += strlen("_GROUP_"); char *str2 = ws_strdup_printf("MENU_%s_%s", str, s); @@ -1152,6 +1222,18 @@ static void wslua_add_deprecated(void) lua_setglobal(L, "MENU_STAT_RESPONSE"); lua_getglobal(L, "MENU_PACKET_STAT_UNSORTED"); lua_setglobal(L, "MENU_STAT_UNSORTED"); + lua_getglobal(L, "MENU_TELEPHONY_UNSORTED"); + lua_setglobal(L, "MENU_STAT_TELEPHONY"); + lua_getglobal(L, "MENU_TELEPHONY_ANSI"); + lua_setglobal(L, "MENU_STAT_TELEPHONY_ANSI"); + lua_getglobal(L, "MENU_TELEPHONY_GSM"); + lua_setglobal(L, "MENU_STAT_TELEPHONY_GSM"); + lua_getglobal(L, "MENU_TELEPHONY_3GPP_UU"); + lua_setglobal(L, "MENU_STAT_TELEPHONY_3GPP_UU"); + lua_getglobal(L, "MENU_TELEPHONY_MTP3"); + lua_setglobal(L, "MENU_STAT_TELEPHONY_MTP3"); + lua_getglobal(L, "MENU_TELEPHONY_SCTP"); + lua_setglobal(L, "MENU_STAT_TELEPHONY_SCTP"); /* deprecated function names */ lua_getglobal(L, "Dir"); @@ -1179,10 +1261,6 @@ static const char *lua_error_msg(int code) return "unknown error"; } -#if LUA_VERSION_NUM == 501 -#define LUA_OK 0 -#endif - static int lua_funnel_console_eval(const char *console_input, char **error_ptr, char **error_hint, @@ -1246,6 +1324,20 @@ static int lua_funnel_console_eval(const char *console_input, } } + // For any new Protos, register their ProtoFields and ProtoExperts with epan + lua_pushcfunction(L, Proto_commit); + lcode = lua_pcall(L, 0, 0, 0); + if (lcode != LUA_OK) { + /* Error initializing new ProtoFields */ + if (error_hint) + *error_hint = ws_strdup_printf("error initialzing protocol fields: %s", lua_error_msg(lcode)); + /* If we have an error message return it. */ + if (error_ptr && !lua_isnil(L, -1)) { + *error_ptr = g_strdup(lua_tostring(L, -1)); + } + return 1; + } + // Maintain stack discipline if (lua_gettop(L) != curr_top) { ws_critical("Expected stack top == %d, have %d", curr_top, lua_gettop(L)); @@ -1255,30 +1347,6 @@ static int lua_funnel_console_eval(const char *console_input, return 0; } -#if LUA_VERSION_NUM == 501 -static const char *luaL_tolstring (lua_State *_L, int idx, size_t *len) { - if (!luaL_callmeta(_L, idx, "__tostring")) { /* no metafield? */ - switch (lua_type(_L, idx)) { - case LUA_TNUMBER: - case LUA_TSTRING: - lua_pushvalue(_L, idx); - break; - case LUA_TBOOLEAN: - lua_pushstring(_L, (lua_toboolean(_L, idx) ? "true" : "false")); - break; - case LUA_TNIL: - lua_pushliteral(_L, "nil"); - break; - default: - lua_pushfstring(_L, "%s: %p", luaL_typename(_L, idx), - lua_topointer(_L, idx)); - break; - } - } - return lua_tolstring(_L, -1, len); -} -#endif /* LUA_VERSION_NUM == 501 */ - /* Receives C print function pointer as first upvalue. */ /* Receives C print function data pointer as second upvalue. */ static int wslua_console_print(lua_State *_L) @@ -1372,7 +1440,7 @@ void wslua_add_useful_constants(void) lua_setglobal(L, "DATA_DIR"); /* USER_DIR has a trailing directory separator. */ - path = get_persconffile_path("", FALSE); + path = get_persconffile_path("", false); lua_pushfstring(L, "%s"G_DIR_SEPARATOR_S, path); g_free(path); lua_setglobal(L, "USER_DIR"); @@ -1384,13 +1452,13 @@ void wslua_add_useful_constants(void) lua_setglobal(L, "typeof"); } -void wslua_init(register_cb cb, gpointer client_data) { - gchar* filename; - gboolean enable_lua = TRUE; - gboolean run_anyway = FALSE; +void wslua_init(register_cb cb, void *client_data) { + char* filename; + bool enable_lua = true; + bool run_anyway = false; expert_module_t* expert_lua; int file_count = 1; - static gboolean first_time = TRUE; + static bool first_time = true; int i; int error; @@ -1403,7 +1471,7 @@ void wslua_init(register_cb cb, gpointer client_data) { { "Wireshark Lua text", "_ws.lua.text", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }}, }; - static gint *ett[] = { + static int *ett[] = { &ett_wslua_traceback, }; @@ -1501,6 +1569,18 @@ void wslua_init(register_cb cb, gpointer client_data) { { &ei_lua_proto_deprecated_warn, { "_ws.lua.proto.warning", PI_DEPRECATED, PI_WARN ,"Protocol Warning", EXPFILL }}, { &ei_lua_proto_deprecated_error, { "_ws.lua.proto.error", PI_DEPRECATED, PI_ERROR ,"Protocol Error", EXPFILL }}, + { &ei_lua_proto_receive_comment, { "_ws.lua.proto.comment", PI_RECEIVE, PI_COMMENT ,"Protocol Comment", EXPFILL }}, + { &ei_lua_proto_receive_chat, { "_ws.lua.proto.chat", PI_RECEIVE, PI_CHAT ,"Protocol Chat", EXPFILL }}, + { &ei_lua_proto_receive_note, { "_ws.lua.proto.note", PI_RECEIVE, PI_NOTE ,"Protocol Note", EXPFILL }}, + { &ei_lua_proto_receive_warn, { "_ws.lua.proto.warning", PI_RECEIVE, PI_WARN ,"Protocol Warning", EXPFILL }}, + { &ei_lua_proto_receive_error, { "_ws.lua.proto.error", PI_RECEIVE, PI_ERROR ,"Protocol Error", EXPFILL }}, + + { &ei_lua_proto_interface_comment, { "_ws.lua.proto.comment", PI_INTERFACE, PI_COMMENT ,"Protocol Comment", EXPFILL }}, + { &ei_lua_proto_interface_chat, { "_ws.lua.proto.chat", PI_INTERFACE, PI_CHAT ,"Protocol Chat", EXPFILL }}, + { &ei_lua_proto_interface_note, { "_ws.lua.proto.note", PI_INTERFACE, PI_NOTE ,"Protocol Note", EXPFILL }}, + { &ei_lua_proto_interface_warn, { "_ws.lua.proto.warning", PI_INTERFACE, PI_WARN ,"Protocol Warning", EXPFILL }}, + { &ei_lua_proto_interface_error, { "_ws.lua.proto.error", PI_INTERFACE, PI_ERROR ,"Protocol Error", EXPFILL }}, + /* this one is for reporting errors executing Lua code */ { &ei_lua_error, { "_ws.lua.error", PI_UNDECODED, PI_ERROR ,"Lua Error", EXPFILL }}, }; @@ -1516,14 +1596,6 @@ void wslua_init(register_cb cb, gpointer client_data) { WSLUA_INIT(L); -#if LUA_VERSION_NUM == 501 - /* table.unpack was introduced with Lua 5.2, alias it to unpack. */ - lua_getglobal(L, "table"); - lua_getglobal(L, "unpack"); - lua_setfield(L, -2, "unpack"); - lua_pop(L, 1); -#endif - if (first_time) { proto_lua = proto_register_protocol("Lua Dissection", "Lua Dissection", "_ws.lua"); proto_register_field_array(proto_lua, hf, array_length(hf)); @@ -1576,12 +1648,12 @@ void wslua_init(register_cb cb, gpointer client_data) { /* special constant used by PDU reassembly handling */ /* see dissect_lua() for notes */ - WSLUA_REG_GLOBAL_NUMBER(L,"DESEGMENT_ONE_MORE_SEGMENT",DESEGMENT_ONE_MORE_SEGMENT); + WSLUA_REG_GLOBAL_INTEGER(L,"DESEGMENT_ONE_MORE_SEGMENT",DESEGMENT_ONE_MORE_SEGMENT); /* the possible values for Pinfo's p2p_dir attribute */ - WSLUA_REG_GLOBAL_NUMBER(L,"P2P_DIR_UNKNOWN",-1); - WSLUA_REG_GLOBAL_NUMBER(L,"P2P_DIR_SENT",0); - WSLUA_REG_GLOBAL_NUMBER(L,"P2P_DIR_RECV",1); + WSLUA_REG_GLOBAL_INTEGER(L,"P2P_DIR_UNKNOWN",-1); + WSLUA_REG_GLOBAL_INTEGER(L,"P2P_DIR_SENT",0); + WSLUA_REG_GLOBAL_INTEGER(L,"P2P_DIR_RECV",1); wslua_add_introspection(); @@ -1603,6 +1675,14 @@ void wslua_init(register_cb cb, gpointer client_data) { } /* load system's init.lua */ +#if 0 + /* wslua_dofile / wslua_get_actual_filename look in the datafile dir. + * Should we add that to the path for require() as well, for consistency? + */ + prepend_path(get_datafile_dir()); +#endif + /* Add the global plugins path for require */ + prepend_path(get_plugins_dir()); filename = g_build_filename(get_plugins_dir(), "init.lua", (char *)NULL); if (file_exists(filename)) { ws_debug("Loading init.lua file: %s", filename); @@ -1613,6 +1693,21 @@ void wslua_init(register_cb cb, gpointer client_data) { /* load user's init.lua */ /* if we are indeed superuser run user scripts only if told to do so */ if (!started_with_special_privs() || run_anyway) { +#if 0 + /* wslua_dofile / wslua_get_actual_filename look in the personal configuration + * directory. Should we add that to the path for require() as well, for consistency? + */ + profile_dir = get_profile_dir(NULL, false); + prepend_path(profile_dir); + g_free(profile_dir); +#endif + /* Add the personal plugins path(s) for require() */ + char *old_path = get_persconffile_path("plugins", false); + if (strcmp(get_plugins_pers_dir(), old_path) != 0) { + prepend_path(old_path); + } + g_free(old_path); + prepend_path(get_plugins_pers_dir()); filename = g_build_filename(get_plugins_pers_dir(), "init.lua", (char *)NULL); if (file_exists(filename)) { ws_debug("Loading init.lua file: %s", filename); @@ -1621,7 +1716,7 @@ void wslua_init(register_cb cb, gpointer client_data) { g_free(filename); /* For backward compatibility also load it from the configuration directory. */ - filename = get_persconffile_path("init.lua", FALSE); + filename = get_persconffile_path("init.lua", false); if (file_exists(filename)) { ws_message("Loading init.lua file from deprecated path: %s", filename); lua_load_internal_script(filename); @@ -1648,18 +1743,18 @@ void wslua_init(register_cb cb, gpointer client_data) { /* disable lua */ lua_close(L); L = NULL; - first_time = FALSE; + first_time = false; return; } /* load global scripts */ - lua_load_global_plugins(cb, client_data, FALSE); + lua_load_global_plugins(cb, client_data, false); /* check whether we should run other scripts even if running superuser */ lua_getglobal(L,"run_user_scripts_when_superuser"); if (lua_isboolean(L,-1) && lua_toboolean(L,-1)) { - run_anyway = TRUE; + run_anyway = true; } lua_pop(L,1); /* pop the getglobal result */ @@ -1667,13 +1762,19 @@ void wslua_init(register_cb cb, gpointer client_data) { if (!started_with_special_privs() || run_anyway) { /* load user scripts */ - lua_load_pers_plugins(cb, client_data, FALSE); + lua_load_pers_plugins(cb, client_data, false); /* load scripts from command line */ for (i = 0; i < ex_opt_count("lua_script"); i++) { - const gchar *script_filename = ex_opt_get_nth("lua_script", i); + const char *script_filename = ex_opt_get_nth("lua_script", i); char* dirname = g_strdup(script_filename); char* dname = get_dirname(dirname); + /* Add the command line script directory to the path (unless it's + * the current directory, which should already be in the path by + * default). + * XXX - Should we remove it after we're done with this script? */ + if (dname) + prepend_path(dname); if (cb) (*cb)(RA_LUA_PLUGINS, get_basename(script_filename), client_data); @@ -1728,14 +1829,14 @@ void wslua_init(register_cb cb, gpointer client_data) { } } - first_time = FALSE; + first_time = false; } void wslua_early_cleanup(void) { wslua_deregister_protocols(L); } -void wslua_reload_plugins (register_cb cb, gpointer client_data) { +void wslua_reload_plugins (register_cb cb, void *client_data) { const funnel_ops_t* ops = funnel_get_funnel_ops(); if (cb) @@ -1763,7 +1864,7 @@ void wslua_cleanup(void) { lua_close(L); L = NULL; } - init_routine_initialized = FALSE; + init_routine_initialized = false; } lua_State* wslua_state(void) { return L; } |