/* * init_wslua.c * * Wireshark's interface to the Lua Programming Language * * (c) 2006, Luis E. Garcia Ontanon * * Wireshark - Network traffic analyzer * By Gerald Combs * Copyright 1998 Gerald Combs * * SPDX-License-Identifier: GPL-2.0-or-later */ #include "config.h" #include "wslua.h" #include "init_wslua.h" #include #include #include #include #include #include #include #include #include #include /* linked list of Lua plugins */ typedef struct _wslua_plugin { gchar *name; /**< plugin name */ gchar *version; /**< plugin version */ gchar *filename; /**< plugin filename */ struct _wslua_plugin *next; } wslua_plugin; 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; wslua_logger_t wslua_logger; 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 gboolean lua_pinfo_end(wmem_allocator_t *allocator _U_, wmem_cb_event_t event _U_, void *user_data _U_) { clear_outstanding_Tvb(); clear_outstanding_TvbRange(); clear_outstanding_Pinfo(); clear_outstanding_Column(); clear_outstanding_Columns(); clear_outstanding_PrivateTable(); clear_outstanding_TreeItem(); clear_outstanding_FieldInfo(); clear_outstanding_FuncSavers(); /* keep invoking this callback later? */ return FALSE; } static int wslua_not_register_menu(lua_State* LS) { luaL_error(LS,"too late to register a menu"); return 0; } /* a getter for wslua_tree.c's TreeItem_add_item_any() to use */ int get_hf_wslua_text(void) { return hf_wslua_text; } int dissect_lua(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, void* data _U_) { int consumed_bytes = tvb_captured_length(tvb); tvbuff_t *saved_lua_tvb = lua_tvb; packet_info *saved_lua_pinfo = lua_pinfo; struct _wslua_treeitem *saved_lua_tree = lua_tree; lua_pinfo = pinfo; lua_tvb = tvb; /* * almost equivalent to Lua: * dissectors[current_proto](tvb,pinfo,tree) */ lua_settop(L,0); lua_rawgeti(L, LUA_REGISTRYINDEX, lua_dissectors_table_ref); lua_pushstring(L, pinfo->current_proto); lua_gettable(L, -2); lua_remove(L,1); if (lua_isfunction(L,1)) { push_Tvb(L,tvb); push_Pinfo(L,pinfo); lua_tree = push_TreeItem(L, tree, proto_tree_add_item(tree, hf_wslua_fake, tvb, 0, 0, ENC_NA)); proto_item_set_hidden(lua_tree->item); if ( lua_pcall(L,3,1,0) ) { proto_tree_add_expert_format(tree, pinfo, &ei_lua_error, tvb, 0, 0, "Lua Error: %s", lua_tostring(L,-1)); } else { /* 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); lua_pop(L, 1); } } } else { proto_tree_add_expert_format(tree, pinfo, &ei_lua_error, tvb, 0, 0, "Lua Error: did not find the %s dissector in the dissectors table", pinfo->current_proto); } wmem_register_callback(pinfo->pool, lua_pinfo_end, NULL); lua_pinfo = saved_lua_pinfo; lua_tree = saved_lua_tree; lua_tvb = saved_lua_tvb; return consumed_bytes; } /** 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; tvbuff_t *saved_lua_tvb = lua_tvb; packet_info *saved_lua_pinfo = lua_pinfo; struct _wslua_treeitem *saved_lua_tree = lua_tree; lua_tvb = tvb; lua_pinfo = pinfo; ws_assert(tvb && pinfo); 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; } /* 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); 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; } /* 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); 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; } /* 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); 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; } push_Tvb(L,tvb); push_Pinfo(L,pinfo); lua_tree = push_TreeItem(L, tree, proto_tree_add_item(tree, hf_wslua_fake, tvb, 0, 0, ENC_NA)); proto_item_set_hidden(lua_tree->item); if ( lua_pcall(L,3,1,0) ) { proto_tree_add_expert_format(tree, pinfo, &ei_lua_error, tvb, 0, 0, "Lua Error: 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 if (lua_type(L, -1) == LUA_TNUMBER) { 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); } lua_pop(L, 1); } wmem_register_callback(pinfo->pool, lua_pinfo_end, NULL); lua_pinfo = saved_lua_pinfo; lua_tree = saved_lua_tree; lua_tvb = saved_lua_tvb; return result; } static void iter_table_and_call(lua_State* LS, const gchar* table_name, lua_CFunction error_handler) { lua_settop(LS,0); lua_pushcfunction(LS,error_handler); lua_getglobal(LS, table_name); if (!lua_istable(LS, 2)) { report_failure("Lua: either `%s' does not exist or it is not a table!\n",table_name); lua_close(LS); L = NULL; return; } lua_pushnil(LS); while (lua_next(LS, 2)) { const gchar* name = lua_tostring(L,-2); if (lua_isfunction(LS,-1)) { if ( lua_pcall(LS,0,0,1) ) { lua_pop(LS,1); } } else { report_failure("Lua: Something not a function got its way into the %s.%s",table_name,name); lua_close(LS); L = NULL; return; } } lua_settop(LS,0); } static int init_error_handler(lua_State* LS) { const gchar* 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 void wslua_init_routine(void) { if ( ! init_routine_initialized ) { /* * This must be done only once during the entire life of * tshark/wireshark, because it must be done only once per the life of * the Lua state/engine, so we guard this with the boolean above; * otherwise it would occur every time a file is opened (every time * epan_new() is called). * * If we ever allow the Lua state to be restarted, or to have multiple * Lua states, we'll need to change this. */ lua_prime_all_fields(NULL); init_routine_initialized = TRUE; } if (L) { iter_table_and_call(L, WSLUA_INIT_ROUTINES,init_error_handler); } } static void wslua_cleanup_routine(void) { if (L) { iter_table_and_call(L, WSLUA_INIT_ROUTINES,init_error_handler); } } static int prefs_changed_error_handler(lua_State* LS) { const gchar* error = lua_tostring(LS,1); report_failure("Lua: Error during execution of prefs apply callback:\n %s",error); return 0; } void wslua_prefs_changed(void) { if (L) { iter_table_and_call(L, WSLUA_PREFS_CHANGED,prefs_changed_error_handler); } } static const char *getF(lua_State *LS _U_, void *ud, size_t *size) { FILE *f=(FILE *)ud; static char buff[512]; if (feof(f)) return NULL; *size=fread(buff,1,sizeof(buff),f); return (*size>0) ? buff : NULL; } 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) { wslua_plugin *new_plug, *lua_plug; lua_plug = wslua_plugin_list; new_plug = g_new(wslua_plugin, 1); if (!lua_plug) { /* the list is empty */ wslua_plugin_list = new_plug; } else { while (lua_plug->next != NULL) { lua_plug = lua_plug->next; } lua_plug->next = new_plug; } new_plug->name = g_strdup(name); new_plug->version = g_strdup(version); new_plug->filename = g_strdup(filename); new_plug->next = NULL; } static void wslua_clear_plugin_list(void) { wslua_plugin *lua_plug; while (wslua_plugin_list) { lua_plug = wslua_plugin_list; wslua_plugin_list = wslua_plugin_list->next; g_free (lua_plug->name); g_free (lua_plug->version); g_free (lua_plug->filename); g_free (lua_plug); } } static int lua_script_push_args(const int script_num) { gchar* argname = ws_strdup_printf("lua_script%d", script_num); const gchar* argvalue = NULL; int i, count = ex_opt_count(argname); for (i = 0; i < count; i++) { argvalue = ex_opt_get_nth(argname, i); lua_pushstring(L,argvalue); } g_free(argname); return count; } #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; lua_newtable(L); /* environment for script (index 3) */ 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__ */ 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_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 } /* 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) { FILE* file; int error; int numargs = 0; if (! ( file = ws_fopen(filename,"r")) ) { report_open_failure(filename,errno,FALSE); return FALSE; } lua_settop(L,0); lua_pushcfunction(L, error_handler_with_callback); /* 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 */ if (dirname) { set_file_environment(filename, dirname); } if (file_count > 0) { numargs = lua_script_push_args(file_count); } error = lua_pcall(L, numargs, 0, 1); if (error) { switch (error) { 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", error); break; } } break; case LUA_ERRSYNTAX: report_failure("Lua: syntax error: %s", lua_tostring(L, -1)); break; case LUA_ERRMEM: report_failure("Lua: memory allocation error during precompilation of %s", filename); break; default: report_failure("Lua: unknown error during precompilation of %s: %d", filename, error); break; } fclose(file); lua_pop(L, 2); /* pop the filename and error handler */ return error == 0; } /* 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) { return lua_load_script(filename, NULL, 0); } /* This one is used to load plugins: either from the plugin directories, * or from the command line. */ static gboolean lua_load_plugin_script(const gchar* name, const gchar* filename, const gchar* dirname, const int file_count) { if (lua_load_script(filename, dirname, file_count)) { wslua_add_plugin(name, get_current_plugin_version(), filename); clear_current_plugin_version(); return TRUE; } return FALSE; } static void basic_logger(const gchar *log_domain, enum ws_log_level log_level, const gchar *message, gpointer user_data _U_) { ws_log(log_domain, log_level, "%s", message); } static int wslua_panic(lua_State* LS) { ws_error("LUA PANIC: %s",lua_tostring(LS,-1)); /** ws_error() does an abort() and thus never returns **/ return 0; /* keep gcc happy */ } static gint string_compare(gconstpointer a, gconstpointer 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) { WS_DIR *dir; /* scanned directory */ WS_DIRENT *file; /* current file */ gchar *filename, *dot; const gchar *name; int plugins_counter = 0; GList *sorted_dirnames = NULL; GList *sorted_filenames = NULL; GList *l = NULL; if ((dir = ws_dir_open(dirname, 0, NULL)) != NULL) { while ((file = ws_dir_read_name(dir)) != NULL) { name = ws_dir_get_name(file); if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) continue; /* skip "." and ".." */ 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); continue; } /* skip files starting wih . */ if (name[0] == '.') { g_free(filename); continue; } /* skip anything but files with .lua suffix */ dot = strrchr(name, '.'); if (dot == NULL || g_ascii_strcasecmp(dot+1, "lua") != 0) { g_free(filename); continue; } if (file_exists(filename)) { sorted_filenames = g_list_prepend(sorted_filenames, (gpointer)filename); } else { g_free(filename); } } ws_dir_close(dir); } /* Depth first; ie, process subdirectories (in ASCIIbetical order) before files */ if (sorted_dirnames != NULL) { sorted_dirnames = g_list_sort(sorted_dirnames, string_compare); for (l = sorted_dirnames; l != NULL; l = l->next) { plugins_counter += lua_load_plugins((const char *)l->data, cb, client_data, count_only, is_user, loaded_files); } g_list_free_full(sorted_dirnames, g_free); } /* Process files in ASCIIbetical order */ if (sorted_filenames != NULL) { sorted_filenames = g_list_sort(sorted_filenames, string_compare); for (l = sorted_filenames; l != NULL; l = l->next) { filename = (gchar *)l->data; name = strrchr(filename, G_DIR_SEPARATOR) + 1; /* Check if we have already loaded this file name, if provided with a set */ if (loaded_files && g_hash_table_lookup_extended(loaded_files, name, NULL, NULL)) { continue; } if (!count_only) { if (cb) (*cb)(RA_LUA_PLUGINS, name, client_data); lua_load_plugin_script(name, filename, is_user ? dirname : NULL, 0); if (loaded_files) { g_hash_table_insert(loaded_files, g_strdup(name), NULL); } } plugins_counter++; } g_list_free_full(sorted_filenames, g_free); } return plugins_counter; } static int lua_load_global_plugins(register_cb cb, gpointer client_data, gboolean count_only) { return lua_load_plugins(get_plugins_dir(), cb, client_data, count_only, FALSE, NULL); } static int lua_load_pers_plugins(register_cb cb, gpointer client_data, gboolean count_only) { int plugins_counter = 0; /* aux table (set) to make sure we only load each file once (by name) */ 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); /* for backward compatibility check old plugin directory */ 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); } g_free(old_path); g_hash_table_destroy(loaded_user_scripts); return plugins_counter; } int wslua_count_plugins(void) { gchar* filename; int plugins_counter; /* count global scripts */ plugins_counter = lua_load_global_plugins(NULL, NULL, TRUE); /* count users init.lua */ filename = get_persconffile_path("init.lua", FALSE); if ((file_exists(filename))) { plugins_counter++; } g_free(filename); /* count user scripts */ plugins_counter += lua_load_pers_plugins(NULL, NULL, TRUE); /* count scripts from command line */ plugins_counter += ex_opt_count("lua_script"); return plugins_counter; } void wslua_plugins_get_descriptions(wslua_plugin_description_callback callback, void *user_data) { wslua_plugin *lua_plug; for (lua_plug = wslua_plugin_list; lua_plug != NULL; lua_plug = lua_plug->next) { callback(lua_plug->name, lua_plug->version, wslua_plugin_type_name(), lua_plug->filename, user_data); } } static void print_wslua_plugin_description(const char *name, const char *version, const char *description, const char *filename, void *user_data _U_) { printf("%s\t%s\t%s\t%s\n", name, version, description, filename); } void wslua_plugins_dump_all(void) { wslua_plugins_get_descriptions(print_wslua_plugin_description, NULL); } 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; expert_field* wslua_get_expert_field(const int group, const int severity) { int i; const ei_register_info *ei = ws_lua_ei; ws_assert(ei); for (i=0; i < ws_lua_ei_len; i++, ei++) { if (ei->eiinfo.group == group && ei->eiinfo.severity == severity) return ei->ids; } return &ei_lua_error; } static void * wslua_allocf(void *ud _U_, void *ptr, size_t osize _U_, size_t nsize) { /* g_realloc frees ptr if nsize==0 and returns NULL (as desired). * Furthermore it simplifies error handling by aborting on OOM */ return g_realloc(ptr, nsize); } #define WSLUA_BASE_TABLE "base" #define WSLUA_FTYPE_TABLE "ftypes" #define WSLUA_FRAMETYPE_TABLE "frametype" #define WSLUA_EXPERT_TABLE "expert" #define WSLUA_EXPERT_GROUP_TABLE "group" #define WSLUA_EXPERT_SEVERITY_TABLE "severity" #define WSLUA_WTAP_ENCAPS_TABLE "wtap_encaps" #define WSLUA_WTAP_TSPREC_TABLE "wtap_tsprecs" #define WSLUA_WTAP_COMMENTS_TABLE "wtap_comments" #define WSLUA_WTAP_RECTYPES_TABLE "wtap_rec_types" #define WSLUA_WTAP_PRESENCE_FLAGS_TABLE "wtap_presence_flags" static void add_table_symbol(const char *table, const char *name, int value) { /* Get table from the global environment. */ lua_getglobal(L, table); /* Set symbol in table. */ lua_pushstring(L, name); lua_pushnumber(L, value); lua_settable(L, -3); /* Pop table from stack. */ lua_pop(L, 1); } static void add_global_symbol(const char *name, int value) { /* Set symbol in global environment. */ lua_pushnumber(L, value); lua_setglobal(L, name); } static void 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_setfield(L, -2, name); lua_pop(L, 2); } static void 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_setfield(L, -2, name); lua_pop(L, 2); } static void add_menu_group_symbol(const char *name, int value) { /* Set symbol in global environment. */ lua_pushnumber(L, value); char *str = g_strdup(name); char *s = strstr(str, "_GROUP_"); if (s == NULL) return; *s = '\0'; s += strlen("_GROUP_"); char *str2 = ws_strdup_printf("MENU_%s_%s", str, s); lua_setglobal(L, str2); g_free(str); g_free(str2); } /* * Read introspection constants and add them according to the historical * (sometimes arbitrary) rules of make-init-lua.py. For efficiency reasons * we only loop the enums array once. */ static void wslua_add_introspection(void) { const ws_enum_t *ep; /* Add empty tables to be populated. */ lua_newtable(L); lua_setglobal(L, WSLUA_BASE_TABLE); lua_newtable(L); lua_setglobal(L, WSLUA_FTYPE_TABLE); lua_newtable(L); lua_setglobal(L, WSLUA_FRAMETYPE_TABLE); lua_newtable(L); lua_pushstring(L, WSLUA_EXPERT_GROUP_TABLE); lua_newtable(L); lua_settable(L, -3); lua_pushstring(L, WSLUA_EXPERT_SEVERITY_TABLE); lua_newtable(L); lua_settable(L, -3); lua_setglobal(L, WSLUA_EXPERT_TABLE); for (ep = epan_inspect_enums(); ep->symbol != NULL; ep++) { if (g_str_has_prefix(ep->symbol, "BASE_")) { add_table_symbol(WSLUA_BASE_TABLE, ep->symbol + strlen("BASE_"), ep->value); } else if (g_str_has_prefix(ep->symbol, "SEP_")) { add_table_symbol(WSLUA_BASE_TABLE, ep->symbol + strlen("SEP_"), ep->value); } else if (g_str_has_prefix(ep->symbol, "ABSOLUTE_TIME_")) { add_table_symbol(WSLUA_BASE_TABLE, ep->symbol + strlen("ABSOLUTE_TIME_"), ep->value); } else if (g_str_has_prefix(ep->symbol, "ENC_")) { add_global_symbol(ep->symbol, ep->value); } else if (g_str_has_prefix(ep->symbol, "FT_FRAMENUM_")) { add_table_symbol(WSLUA_FRAMETYPE_TABLE, ep->symbol + strlen("FT_FRAMENUM_"), ep->value); } else if (g_str_has_prefix(ep->symbol, "FT_")) { add_table_symbol(WSLUA_FTYPE_TABLE, ep->symbol + strlen("FT_"), ep->value); } else if (g_str_has_prefix(ep->symbol, "PI_")) { if (ep->value & PI_SEVERITY_MASK) { add_pi_severity_symbol(ep->symbol + strlen("PI_"), ep->value); } else { add_pi_group_symbol(ep->symbol + strlen("PI_"), ep->value); } /* For backward compatibility. */ add_global_symbol(ep->symbol, ep->value); } else if (g_str_has_prefix(ep->symbol, "REGISTER_")) { add_menu_group_symbol(ep->symbol + strlen("REGISTER_"), ep->value); } } /* Add empty tables to be populated. */ lua_newtable(L); lua_setglobal(L, WSLUA_WTAP_ENCAPS_TABLE); lua_newtable(L); lua_setglobal(L, WSLUA_WTAP_TSPREC_TABLE); lua_newtable(L); lua_setglobal(L, WSLUA_WTAP_COMMENTS_TABLE); lua_newtable(L); lua_setglobal(L, WSLUA_WTAP_RECTYPES_TABLE); lua_newtable(L); lua_setglobal(L, WSLUA_WTAP_PRESENCE_FLAGS_TABLE); for (ep = wtap_inspect_enums(); ep->symbol != NULL; ep++) { if (g_str_has_prefix(ep->symbol, "WTAP_ENCAP_")) { add_table_symbol(WSLUA_WTAP_ENCAPS_TABLE, ep->symbol + strlen("WTAP_ENCAP_"), ep->value); } else if (g_str_has_prefix(ep->symbol, "WTAP_TSPREC_")) { add_table_symbol(WSLUA_WTAP_TSPREC_TABLE, ep->symbol + strlen("WTAP_TSPREC_"), ep->value); } else if (g_str_has_prefix(ep->symbol, "WTAP_COMMENT_")) { add_table_symbol(WSLUA_WTAP_COMMENTS_TABLE, ep->symbol + strlen("WTAP_COMMENT_"), ep->value); } else if (g_str_has_prefix(ep->symbol, "REC_TYPE_")) { add_table_symbol(WSLUA_WTAP_RECTYPES_TABLE, ep->symbol + strlen("REC_TYPE_"), ep->value); } else if (g_str_has_prefix(ep->symbol, "WTAP_HAS_")) { add_table_symbol(WSLUA_WTAP_PRESENCE_FLAGS_TABLE, ep->symbol + strlen("WTAP_HAS_"), ep->value); } } } void wslua_init(register_cb cb, gpointer client_data) { gchar* filename; const funnel_ops_t* ops = funnel_get_funnel_ops(); gboolean enable_lua = TRUE; gboolean run_anyway = FALSE; expert_module_t* expert_lua; int file_count = 1; static gboolean first_time = TRUE; int i; static hf_register_info hf[] = { { &hf_wslua_fake, { "Wireshark Lua fake item", "_ws.lua.fake", FT_NONE, BASE_NONE, NULL, 0x0, "Fake internal item for Wireshark Lua", HFILL }}, { &hf_wslua_text, { "Wireshark Lua text", "_ws.lua.text", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }}, }; static ei_register_info ei[] = { /* the following are created so we can continue to support the TreeItem_add_expert_info() function to Lua scripts. That function doesn't know what registered protocol to use, so it uses the "_ws.lua" one. */ /* XXX: it seems to me we should not be offering PI_GROUP_MASK nor PI_SEVERITY_MASK since they are not real settings, so I'm not adding them below (should they also not be exported into Lua? they are right now.) */ /* NOTE: do not add expert entries at the top of this array - only at the bottom. This array is not only used by expert.c, but also by wslua_get_expert_field() to find the appropriate "dummy" entry. So this array's ordering matters. */ { &ei_lua_proto_checksum_comment, { "_ws.lua.proto.comment", PI_CHECKSUM, PI_COMMENT ,"Protocol Comment", EXPFILL }}, { &ei_lua_proto_checksum_chat, { "_ws.lua.proto.chat", PI_CHECKSUM, PI_CHAT ,"Protocol Chat", EXPFILL }}, { &ei_lua_proto_checksum_note, { "_ws.lua.proto.note", PI_CHECKSUM, PI_NOTE ,"Protocol Note", EXPFILL }}, { &ei_lua_proto_checksum_warn, { "_ws.lua.proto.warning", PI_CHECKSUM, PI_WARN ,"Protocol Warning", EXPFILL }}, { &ei_lua_proto_checksum_error, { "_ws.lua.proto.error", PI_CHECKSUM, PI_ERROR ,"Protocol Error", EXPFILL }}, { &ei_lua_proto_sequence_comment, { "_ws.lua.proto.comment", PI_SEQUENCE, PI_COMMENT ,"Protocol Comment", EXPFILL }}, { &ei_lua_proto_sequence_chat, { "_ws.lua.proto.chat", PI_SEQUENCE, PI_CHAT ,"Protocol Chat", EXPFILL }}, { &ei_lua_proto_sequence_note, { "_ws.lua.proto.note", PI_SEQUENCE, PI_NOTE ,"Protocol Note", EXPFILL }}, { &ei_lua_proto_sequence_warn, { "_ws.lua.proto.warning", PI_SEQUENCE, PI_WARN ,"Protocol Warning", EXPFILL }}, { &ei_lua_proto_sequence_error, { "_ws.lua.proto.error", PI_SEQUENCE, PI_ERROR ,"Protocol Error", EXPFILL }}, { &ei_lua_proto_response_comment, { "_ws.lua.proto.comment", PI_RESPONSE_CODE, PI_COMMENT ,"Protocol Comment", EXPFILL }}, { &ei_lua_proto_response_chat, { "_ws.lua.proto.chat", PI_RESPONSE_CODE, PI_CHAT ,"Protocol Chat", EXPFILL }}, { &ei_lua_proto_response_note, { "_ws.lua.proto.note", PI_RESPONSE_CODE, PI_NOTE ,"Protocol Note", EXPFILL }}, { &ei_lua_proto_response_warn, { "_ws.lua.proto.warning", PI_RESPONSE_CODE, PI_WARN ,"Protocol Warning", EXPFILL }}, { &ei_lua_proto_response_error, { "_ws.lua.proto.error", PI_RESPONSE_CODE, PI_ERROR ,"Protocol Error", EXPFILL }}, { &ei_lua_proto_request_comment, { "_ws.lua.proto.comment", PI_REQUEST_CODE, PI_COMMENT ,"Protocol Comment", EXPFILL }}, { &ei_lua_proto_request_chat, { "_ws.lua.proto.chat", PI_REQUEST_CODE, PI_CHAT ,"Protocol Chat", EXPFILL }}, { &ei_lua_proto_request_note, { "_ws.lua.proto.note", PI_REQUEST_CODE, PI_NOTE ,"Protocol Note", EXPFILL }}, { &ei_lua_proto_request_warn, { "_ws.lua.proto.warning", PI_REQUEST_CODE, PI_WARN ,"Protocol Warning", EXPFILL }}, { &ei_lua_proto_request_error, { "_ws.lua.proto.error", PI_REQUEST_CODE, PI_ERROR ,"Protocol Error", EXPFILL }}, { &ei_lua_proto_undecoded_comment, { "_ws.lua.proto.comment", PI_UNDECODED, PI_COMMENT ,"Protocol Comment", EXPFILL }}, { &ei_lua_proto_undecoded_chat, { "_ws.lua.proto.chat", PI_UNDECODED, PI_CHAT ,"Protocol Chat", EXPFILL }}, { &ei_lua_proto_undecoded_note, { "_ws.lua.proto.note", PI_UNDECODED, PI_NOTE ,"Protocol Note", EXPFILL }}, { &ei_lua_proto_undecoded_warn, { "_ws.lua.proto.warning", PI_UNDECODED, PI_WARN ,"Protocol Warning", EXPFILL }}, { &ei_lua_proto_undecoded_error, { "_ws.lua.proto.error", PI_UNDECODED, PI_ERROR ,"Protocol Error", EXPFILL }}, { &ei_lua_proto_reassemble_comment, { "_ws.lua.proto.comment", PI_REASSEMBLE, PI_COMMENT ,"Protocol Comment", EXPFILL }}, { &ei_lua_proto_reassemble_chat, { "_ws.lua.proto.chat", PI_REASSEMBLE, PI_CHAT ,"Protocol Chat", EXPFILL }}, { &ei_lua_proto_reassemble_note, { "_ws.lua.proto.note", PI_REASSEMBLE, PI_NOTE ,"Protocol Note", EXPFILL }}, { &ei_lua_proto_reassemble_warn, { "_ws.lua.proto.warning", PI_REASSEMBLE, PI_WARN ,"Protocol Warning", EXPFILL }}, { &ei_lua_proto_reassemble_error, { "_ws.lua.proto.error", PI_REASSEMBLE, PI_ERROR ,"Protocol Error", EXPFILL }}, { &ei_lua_proto_malformed_comment, { "_ws.lua.proto.comment", PI_MALFORMED, PI_COMMENT ,"Protocol Comment", EXPFILL }}, { &ei_lua_proto_malformed_chat, { "_ws.lua.proto.chat", PI_MALFORMED, PI_CHAT ,"Protocol Chat", EXPFILL }}, { &ei_lua_proto_malformed_note, { "_ws.lua.proto.note", PI_MALFORMED, PI_NOTE ,"Protocol Note", EXPFILL }}, { &ei_lua_proto_malformed_warn, { "_ws.lua.proto.warning", PI_MALFORMED, PI_WARN ,"Protocol Warning", EXPFILL }}, { &ei_lua_proto_malformed_error, { "_ws.lua.proto.error", PI_MALFORMED, PI_ERROR ,"Protocol Error", EXPFILL }}, { &ei_lua_proto_debug_comment, { "_ws.lua.proto.comment", PI_DEBUG, PI_COMMENT ,"Protocol Comment", EXPFILL }}, { &ei_lua_proto_debug_chat, { "_ws.lua.proto.chat", PI_DEBUG, PI_CHAT ,"Protocol Chat", EXPFILL }}, { &ei_lua_proto_debug_note, { "_ws.lua.proto.note", PI_DEBUG, PI_NOTE ,"Protocol Note", EXPFILL }}, { &ei_lua_proto_debug_warn, { "_ws.lua.proto.warning", PI_DEBUG, PI_WARN ,"Protocol Warning", EXPFILL }}, { &ei_lua_proto_debug_error, { "_ws.lua.proto.error", PI_DEBUG, PI_ERROR ,"Protocol Error", EXPFILL }}, { &ei_lua_proto_protocol_comment, { "_ws.lua.proto.comment", PI_PROTOCOL, PI_COMMENT ,"Protocol Comment", EXPFILL }}, { &ei_lua_proto_protocol_chat, { "_ws.lua.proto.chat", PI_PROTOCOL, PI_CHAT ,"Protocol Chat", EXPFILL }}, { &ei_lua_proto_protocol_note, { "_ws.lua.proto.note", PI_PROTOCOL, PI_NOTE ,"Protocol Note", EXPFILL }}, { &ei_lua_proto_protocol_warn, { "_ws.lua.proto.warning", PI_PROTOCOL, PI_WARN ,"Protocol Warning", EXPFILL }}, { &ei_lua_proto_protocol_error, { "_ws.lua.proto.error", PI_PROTOCOL, PI_ERROR ,"Protocol Error", EXPFILL }}, { &ei_lua_proto_security_comment, { "_ws.lua.proto.comment", PI_SECURITY, PI_COMMENT ,"Protocol Comment", EXPFILL }}, { &ei_lua_proto_security_chat, { "_ws.lua.proto.chat", PI_SECURITY, PI_CHAT ,"Protocol Chat", EXPFILL }}, { &ei_lua_proto_security_note, { "_ws.lua.proto.note", PI_SECURITY, PI_NOTE ,"Protocol Note", EXPFILL }}, { &ei_lua_proto_security_warn, { "_ws.lua.proto.warning", PI_SECURITY, PI_WARN ,"Protocol Warning", EXPFILL }}, { &ei_lua_proto_security_error, { "_ws.lua.proto.error", PI_SECURITY, PI_ERROR ,"Protocol Error", EXPFILL }}, { &ei_lua_proto_comments_comment, { "_ws.lua.proto.comment", PI_COMMENTS_GROUP, PI_COMMENT ,"Protocol Comment", EXPFILL }}, { &ei_lua_proto_comments_chat, { "_ws.lua.proto.chat", PI_COMMENTS_GROUP, PI_CHAT ,"Protocol Chat", EXPFILL }}, { &ei_lua_proto_comments_note, { "_ws.lua.proto.note", PI_COMMENTS_GROUP, PI_NOTE ,"Protocol Note", EXPFILL }}, { &ei_lua_proto_comments_warn, { "_ws.lua.proto.warning", PI_COMMENTS_GROUP, PI_WARN ,"Protocol Warning", EXPFILL }}, { &ei_lua_proto_comments_error, { "_ws.lua.proto.error", PI_COMMENTS_GROUP, PI_ERROR ,"Protocol Error", EXPFILL }}, { &ei_lua_proto_decryption_comment, { "_ws.lua.proto.comment", PI_DECRYPTION, PI_COMMENT ,"Protocol Comment", EXPFILL }}, { &ei_lua_proto_decryption_chat, { "_ws.lua.proto.chat", PI_DECRYPTION, PI_CHAT ,"Protocol Chat", EXPFILL }}, { &ei_lua_proto_decryption_note, { "_ws.lua.proto.note", PI_DECRYPTION, PI_NOTE ,"Protocol Note", EXPFILL }}, { &ei_lua_proto_decryption_warn, { "_ws.lua.proto.warning", PI_DECRYPTION, PI_WARN ,"Protocol Warning", EXPFILL }}, { &ei_lua_proto_decryption_error, { "_ws.lua.proto.error", PI_DECRYPTION, PI_ERROR ,"Protocol Error", EXPFILL }}, { &ei_lua_proto_assumption_comment, { "_ws.lua.proto.comment", PI_ASSUMPTION, PI_COMMENT ,"Protocol Comment", EXPFILL }}, { &ei_lua_proto_assumption_chat, { "_ws.lua.proto.chat", PI_ASSUMPTION, PI_CHAT ,"Protocol Chat", EXPFILL }}, { &ei_lua_proto_assumption_note, { "_ws.lua.proto.note", PI_ASSUMPTION, PI_NOTE ,"Protocol Note", EXPFILL }}, { &ei_lua_proto_assumption_warn, { "_ws.lua.proto.warning", PI_ASSUMPTION, PI_WARN ,"Protocol Warning", EXPFILL }}, { &ei_lua_proto_assumption_error, { "_ws.lua.proto.error", PI_ASSUMPTION, PI_ERROR ,"Protocol Error", EXPFILL }}, { &ei_lua_proto_deprecated_comment, { "_ws.lua.proto.comment", PI_DEPRECATED, PI_COMMENT ,"Protocol Comment", EXPFILL }}, { &ei_lua_proto_deprecated_chat, { "_ws.lua.proto.chat", PI_DEPRECATED, PI_CHAT ,"Protocol Chat", EXPFILL }}, { &ei_lua_proto_deprecated_note, { "_ws.lua.proto.note", PI_DEPRECATED, PI_NOTE ,"Protocol Note", EXPFILL }}, { &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 }}, /* this one is for reporting errors executing Lua code */ { &ei_lua_error, { "_ws.lua.error", PI_UNDECODED, PI_ERROR ,"Lua Error", EXPFILL }}, }; if (first_time) { ws_lua_ei = ei; ws_lua_ei_len = array_length(ei); } /* set up the logger */ wslua_logger = ops ? ops->logger : basic_logger; if (!L) { L = lua_newstate(wslua_allocf, NULL); } 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)); expert_lua = expert_register_protocol(proto_lua); expert_register_field_array(expert_lua, ei, array_length(ei)); } lua_atpanic(L,wslua_panic); /* * The init_routines table (accessible by the user). * * For a table a, a.init is syntactic sugar for a["init"], and * * function t.a.b.c.f () body end * * is syntactic sugar for * * t.a.b.c.f = function () body end * * so * * function proto.init () body end * * means * * proto["init"] = function () body end * * and the Proto class has an "init" method, with Proto_set_init() * being the setter for that method; that routine adds the Lua * function passed to it as a Lua argument to the WSLUA_INIT_ROUTINES * table - i.e., "init_routines". */ lua_newtable (L); lua_setglobal(L, WSLUA_INIT_ROUTINES); /* 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); lua_setglobal(L, WSLUA_PREFS_CHANGED); /* set running_superuser variable to its proper value */ WSLUA_REG_GLOBAL_BOOL(L,"running_superuser",started_with_special_privs()); /* 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_add_introspection(); /* load system's init.lua */ filename = get_datafile_path("init.lua"); if (( file_exists(filename))) { lua_load_internal_script(filename); } g_free(filename); filename = NULL; /* check if lua is to be disabled */ lua_getglobal(L, "disable_lua"); // 2.6 and earlier, deprecated if (lua_isboolean(L,-1)) { enable_lua = ! lua_toboolean(L,-1); } lua_pop(L,1); /* pop the getglobal result */ lua_getglobal(L, "enable_lua"); // 3.0 and later if (lua_isboolean(L,-1)) { enable_lua = lua_toboolean(L,-1); } lua_pop(L,1); /* pop the getglobal result */ if (!enable_lua) { /* disable lua */ lua_close(L); L = NULL; first_time = FALSE; return; } /* load global scripts */ 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; } lua_pop(L,1); /* pop the getglobal result */ /* if we are indeed superuser run user scripts only if told to do so */ if ( (!started_with_special_privs()) || run_anyway ) { /* load users init.lua */ filename = get_persconffile_path("init.lua", FALSE); if ((file_exists(filename))) { if (cb) (*cb)(RA_LUA_PLUGINS, get_basename(filename), client_data); lua_load_internal_script(filename); } g_free(filename); /* load user scripts */ 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); char* dirname = g_strdup(script_filename); char* dname = get_dirname(dirname); if (cb) (*cb)(RA_LUA_PLUGINS, get_basename(script_filename), client_data); lua_load_plugin_script(ws_dir_get_name(script_filename), script_filename, dname ? dname : "", file_count); file_count++; g_free(dirname); } } if (first_time) { /* at this point we're set up so register the init and cleanup routines */ register_init_routine(wslua_init_routine); register_cleanup_routine(wslua_cleanup_routine); } /* * after this point it is too late to register a menu * disable the function to avoid weirdness */ lua_pushcfunction(L, wslua_not_register_menu); lua_setglobal(L, "register_menu"); /* set up some essential globals */ lua_pinfo = NULL; lua_tree = NULL; lua_tvb = NULL; Proto_commit(L); first_time = FALSE; } void wslua_early_cleanup(void) { wslua_deregister_protocols(L); } void wslua_reload_plugins (register_cb cb, gpointer client_data) { const funnel_ops_t* ops = funnel_get_funnel_ops(); if (cb) (*cb)(RA_LUA_DEREGISTER, NULL, client_data); if (ops->close_dialogs) ops->close_dialogs(); wslua_deregister_heur_dissectors(L); wslua_deregister_protocols(L); wslua_deregister_dissector_tables(L); wslua_deregister_listeners(L); wslua_deregister_fields(L); wslua_deregister_filehandlers(L); wslua_deregister_menus(); wslua_clear_plugin_list(); wslua_cleanup(); wslua_init(cb, client_data); /* reinitialize */ } void wslua_cleanup(void) { /* cleanup lua */ if (L) { lua_close(L); L = NULL; } init_routine_initialized = FALSE; } lua_State* wslua_state(void) { return L; } /* * Editor modelines - https://www.wireshark.org/tools/modelines.html * * Local variables: * c-basic-offset: 4 * tab-width: 8 * indent-tabs-mode: nil * End: * * vi: set shiftwidth=4 tabstop=8 expandtab: * :indentSize=4:tabSize=8:noTabs=true: */