regen pidl all: rm epan/dissectors/pidl/*-stamp; pushd epan/dissectors/pidl/ && make...
[wireshark-sm.git] / epan / wslua / init_wslua.c
blob8131e1b558a7c4d9d006b0b2d65167c2397f09c3
1 /*
2 * init_wslua.c
4 * Wireshark's interface to the Lua Programming Language
6 * (c) 2006, Luis E. Garcia Ontanon <luis@ontanon.org>
8 * Wireshark - Network traffic analyzer
9 * By Gerald Combs <gerald@wireshark.org>
10 * Copyright 1998 Gerald Combs
12 * SPDX-License-Identifier: GPL-2.0-or-later
15 #include "config.h"
16 #define WS_LOG_DOMAIN LOG_DOMAIN_WSLUA
18 #include "wslua.h"
19 #include "init_wslua.h"
21 #include <errno.h>
22 #include <stdio.h>
23 #include <epan/expert.h>
24 #include <epan/ex-opt.h>
25 #include <epan/introspection.h>
26 #include <wiretap/introspection.h>
27 #include <wsutil/privileges.h>
28 #include <wsutil/file_util.h>
29 #include <wsutil/wslog.h>
30 #include <wsutil/array.h>
32 /* linked list of Lua plugins */
33 typedef struct _wslua_plugin {
34 char *name; /**< plugin name */
35 char *version; /**< plugin version */
36 char *filename; /**< plugin filename */
37 struct _wslua_plugin *next;
38 } wslua_plugin;
40 static wslua_plugin *wslua_plugin_list;
42 static lua_State* L;
44 static void (*wslua_gui_print_func_ptr)(const char *, void *);
45 static void *wslua_gui_print_data_ptr;
46 static int wslua_lua_print_func_ref = LUA_NOREF;
48 /* XXX: global variables? Really?? Yuck. These could be done differently,
49 using the Lua registry */
50 packet_info* lua_pinfo;
51 struct _wslua_treeitem* lua_tree;
52 tvbuff_t* lua_tvb;
53 int lua_dissectors_table_ref = LUA_NOREF;
54 int lua_heur_dissectors_table_ref = LUA_NOREF;
56 static int proto_lua;
58 static int hf_wslua_fake;
59 static int hf_wslua_text;
61 static expert_field ei_lua_error;
63 static expert_field ei_lua_proto_checksum_comment;
64 static expert_field ei_lua_proto_checksum_chat;
65 static expert_field ei_lua_proto_checksum_note;
66 static expert_field ei_lua_proto_checksum_warn;
67 static expert_field ei_lua_proto_checksum_error;
69 static expert_field ei_lua_proto_sequence_comment;
70 static expert_field ei_lua_proto_sequence_chat;
71 static expert_field ei_lua_proto_sequence_note;
72 static expert_field ei_lua_proto_sequence_warn;
73 static expert_field ei_lua_proto_sequence_error;
75 static expert_field ei_lua_proto_response_comment;
76 static expert_field ei_lua_proto_response_chat;
77 static expert_field ei_lua_proto_response_note;
78 static expert_field ei_lua_proto_response_warn;
79 static expert_field ei_lua_proto_response_error;
81 static expert_field ei_lua_proto_request_comment;
82 static expert_field ei_lua_proto_request_chat;
83 static expert_field ei_lua_proto_request_note;
84 static expert_field ei_lua_proto_request_warn;
85 static expert_field ei_lua_proto_request_error;
87 static expert_field ei_lua_proto_undecoded_comment;
88 static expert_field ei_lua_proto_undecoded_chat;
89 static expert_field ei_lua_proto_undecoded_note;
90 static expert_field ei_lua_proto_undecoded_warn;
91 static expert_field ei_lua_proto_undecoded_error;
93 static expert_field ei_lua_proto_reassemble_comment;
94 static expert_field ei_lua_proto_reassemble_chat;
95 static expert_field ei_lua_proto_reassemble_note;
96 static expert_field ei_lua_proto_reassemble_warn;
97 static expert_field ei_lua_proto_reassemble_error;
99 static expert_field ei_lua_proto_malformed_comment;
100 static expert_field ei_lua_proto_malformed_chat;
101 static expert_field ei_lua_proto_malformed_note;
102 static expert_field ei_lua_proto_malformed_warn;
103 static expert_field ei_lua_proto_malformed_error;
105 static expert_field ei_lua_proto_debug_comment;
106 static expert_field ei_lua_proto_debug_chat;
107 static expert_field ei_lua_proto_debug_note;
108 static expert_field ei_lua_proto_debug_warn;
109 static expert_field ei_lua_proto_debug_error;
111 static expert_field ei_lua_proto_protocol_comment;
112 static expert_field ei_lua_proto_protocol_chat;
113 static expert_field ei_lua_proto_protocol_note;
114 static expert_field ei_lua_proto_protocol_warn;
115 static expert_field ei_lua_proto_protocol_error;
117 static expert_field ei_lua_proto_security_comment;
118 static expert_field ei_lua_proto_security_chat;
119 static expert_field ei_lua_proto_security_note;
120 static expert_field ei_lua_proto_security_warn;
121 static expert_field ei_lua_proto_security_error;
123 static expert_field ei_lua_proto_comments_comment;
124 static expert_field ei_lua_proto_comments_chat;
125 static expert_field ei_lua_proto_comments_note;
126 static expert_field ei_lua_proto_comments_warn;
127 static expert_field ei_lua_proto_comments_error;
129 static expert_field ei_lua_proto_decryption_comment;
130 static expert_field ei_lua_proto_decryption_chat;
131 static expert_field ei_lua_proto_decryption_note;
132 static expert_field ei_lua_proto_decryption_warn;
133 static expert_field ei_lua_proto_decryption_error;
135 static expert_field ei_lua_proto_assumption_comment;
136 static expert_field ei_lua_proto_assumption_chat;
137 static expert_field ei_lua_proto_assumption_note;
138 static expert_field ei_lua_proto_assumption_warn;
139 static expert_field ei_lua_proto_assumption_error;
141 static expert_field ei_lua_proto_deprecated_comment;
142 static expert_field ei_lua_proto_deprecated_chat;
143 static expert_field ei_lua_proto_deprecated_note;
144 static expert_field ei_lua_proto_deprecated_warn;
145 static expert_field ei_lua_proto_deprecated_error;
147 static expert_field ei_lua_proto_receive_comment;
148 static expert_field ei_lua_proto_receive_chat;
149 static expert_field ei_lua_proto_receive_note;
150 static expert_field ei_lua_proto_receive_warn;
151 static expert_field ei_lua_proto_receive_error;
153 static expert_field ei_lua_proto_interface_comment;
154 static expert_field ei_lua_proto_interface_chat;
155 static expert_field ei_lua_proto_interface_note;
156 static expert_field ei_lua_proto_interface_warn;
157 static expert_field ei_lua_proto_interface_error;
159 static int ett_wslua_traceback;
161 static bool
162 lua_pinfo_end(wmem_allocator_t *allocator _U_, wmem_cb_event_t event _U_,
163 void *user_data _U_)
165 clear_outstanding_Tvb();
166 clear_outstanding_TvbRange();
167 clear_outstanding_Pinfo();
168 clear_outstanding_Column();
169 clear_outstanding_Columns();
170 clear_outstanding_PrivateTable();
171 clear_outstanding_TreeItem();
172 clear_outstanding_FieldInfo();
173 clear_outstanding_FuncSavers();
175 /* keep invoking this callback later? */
176 return false;
179 static int wslua_not_register_menu(lua_State* LS) {
180 luaL_error(LS,"too late to register a menu");
181 return 0;
184 /* a getter for wslua_tree.c's TreeItem_add_item_any() to use */
185 int get_hf_wslua_text(void) {
186 return hf_wslua_text;
190 // Attach the lua traceback to the proto_tree
191 static int dissector_error_handler(lua_State *LS) {
192 // Entering, stack: [ error_handler, dissector, errmsg ]
194 proto_item *tb_item;
195 proto_tree *tb_tree;
197 // Add the expert info Lua error message
198 // XXX - Should this add the current protocol to the message, and add to
199 // COL_INFO and the log, like DissectorError does?
200 proto_tree_add_expert_format(lua_tree->tree, lua_pinfo, &ei_lua_error, lua_tvb, 0, 0,
201 "Lua Error: %s", lua_tostring(LS,-1));
203 // Create a new proto sub_tree for the traceback
204 tb_item = proto_tree_add_text_internal(lua_tree->tree, lua_tvb, 0, 0, "Lua Traceback");
205 tb_tree = proto_item_add_subtree(tb_item, ett_wslua_traceback);
207 // Push the traceback onto the stack
208 // After call, stack: [ error_handler, dissector, errmsg, tb_string ]
209 luaL_traceback(LS, LS, NULL, 1);
211 // Get the string length of the traceback. Note that the string
212 // has a terminating NUL, but string_length doesn't include it.
213 // The lua docs say the string can have NULs in it too, but we
214 // ignore that because the traceback string shouldn't have them.
215 // This function does not own the string; it's still owned by lua.
216 size_t string_length;
217 const char *orig_tb_string = lua_tolstring(LS, -1, &string_length);
219 // We make the copy so we can modify the string. Don't forget the
220 // extra byte for the terminating NUL!
221 char *tb_string = (char*) g_memdup2(orig_tb_string, string_length+1);
223 // The string has tabs and new lines in it
224 // We will add proto_items for each new-line-delimited sub-string.
225 // We also convert tabs to spaces, because the Wireshark GUI
226 // shows tabs literally as "\t".
228 // 'beginning' is the beginning of the sub-string
229 char *beginning = tb_string;
231 // 'p' is the pointer to the byte as we iterate over the string
232 char *p = tb_string;
234 size_t i;
235 bool skip_initial_tabs = true;
236 size_t last_eol_i = 0;
237 for (i = 0 ; i < string_length ; i++) {
238 // At the beginning of a sub-string, we will convert tabs to spaces
239 if (skip_initial_tabs) {
240 if (*p == '\t') {
241 *p = ' ';
242 } else {
243 // Once we hit the first non-tab character in a substring,
244 // we won't convert tabs (until the next substring)
245 skip_initial_tabs = false;
248 // If we see a newline, we add the substring to the proto tree
249 if (*p == '\n') {
250 // Terminate the string.
251 *p = '\0';
252 proto_tree_add_text_internal(tb_tree, lua_tvb, 0, 0, "%s", beginning);
253 beginning = ++p;
254 skip_initial_tabs = true;
255 last_eol_i = i;
256 } else {
257 ++p;
261 // The last portion of the string doesn't have a newline, so add it here
262 // after the loop. But to be sure, check that we didn't just add it, in
263 // case lua decides to change it in the future.
264 if ( last_eol_i < i-1 ) {
265 proto_tree_add_text_internal(tb_tree, lua_tvb, 0, 0, "%s", beginning);
268 // Cleanup
269 g_free(tb_string);
271 // Return the same original error message
272 return -2;
276 int dissect_lua(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, void* data _U_) {
277 int consumed_bytes = tvb_captured_length(tvb);
278 tvbuff_t *saved_lua_tvb = lua_tvb;
279 packet_info *saved_lua_pinfo = lua_pinfo;
280 struct _wslua_treeitem *saved_lua_tree = lua_tree;
281 lua_pinfo = pinfo;
282 lua_tvb = tvb;
285 * almost equivalent to Lua:
286 * dissectors[current_proto](tvb,pinfo,tree)
289 // set the stack top be index 0
290 lua_settop(L,0);
292 // After call, stack: [ error_handler_func ]
293 lua_pushcfunction(L, dissector_error_handler);
295 // Push the dissectors table onto the the stack
296 // After call, stack: [ error_handler_func, dissectors_table ]
297 lua_rawgeti(L, LUA_REGISTRYINDEX, lua_dissectors_table_ref);
299 // Push a copy of the current_proto string onto the stack
300 // After call, stack: [ error_handler_func, dissectors_table, current_proto ]
301 lua_pushstring(L, pinfo->current_proto);
303 // dissectors_table[current_proto], a dissector, goes into the stack
304 // The key (current_proto) is popped off the stack.
305 // After call, stack: [ error_handler_func, dissectors_table, dissector ]
306 lua_gettable(L, -2);
308 // We don't need the dissectors_table in the stack
309 // After call, stack: [ error_handler_func, dissector ]
310 lua_remove(L,2);
312 // Is the dissector a function?
313 if (lua_isfunction(L,2)) {
315 // After call, stack: [ error_handler_func, dissector, tvb ]
316 push_Tvb(L,tvb);
317 // After call, stack: [ error_handler_func, dissector, tvb, pinfo ]
318 push_Pinfo(L,pinfo);
319 // After call, stack: [ error_handler_func, dissector, tvb, pinfo, TreeItem ]
320 lua_tree = push_TreeItem(L, tree, proto_tree_add_item(tree, hf_wslua_fake, tvb, 0, 0, ENC_NA));
321 proto_item_set_hidden(lua_tree->item);
323 if ( lua_pcall(L, /*num_args=*/3, /*num_results=*/1, /*error_handler_func_stack_position=*/1) ) {
324 // do nothing; the traceback error message handler function does everything
325 } else {
327 /* if the Lua dissector reported the consumed bytes, pass it to our caller */
328 if (lua_isnumber(L, -1)) {
329 /* we got the consumed bytes or the missing bytes as a negative number */
330 consumed_bytes = wslua_toint(L, -1);
331 lua_pop(L, 1);
335 } else {
336 proto_tree_add_expert_format(tree, pinfo, &ei_lua_error, tvb, 0, 0,
337 "Lua Error: did not find the %s dissector in the dissectors table", pinfo->current_proto);
340 wmem_register_callback(pinfo->pool, lua_pinfo_end, NULL);
342 lua_pinfo = saved_lua_pinfo;
343 lua_tree = saved_lua_tree;
344 lua_tvb = saved_lua_tvb;
346 return consumed_bytes;
350 /** Type of a heuristic dissector, used in heur_dissector_add().
352 * @param tvb the tvbuff with the (remaining) packet data
353 * @param pinfo the packet info of this packet (additional info)
354 * @param tree the protocol tree to be build or NULL
355 * @return true if the packet was recognized by the sub-dissector (stop dissection here)
357 bool heur_dissect_lua(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, void* data _U_) {
358 bool result = false;
359 tvbuff_t *saved_lua_tvb = lua_tvb;
360 packet_info *saved_lua_pinfo = lua_pinfo;
361 struct _wslua_treeitem *saved_lua_tree = lua_tree;
362 lua_tvb = tvb;
363 lua_pinfo = pinfo;
365 ws_assert(tvb && pinfo);
367 if (!pinfo->heur_list_name || !pinfo->current_proto) {
368 proto_tree_add_expert_format(tree, pinfo, &ei_lua_error, tvb, 0, 0,
369 "internal error in heur_dissect_lua: NULL list name or current proto");
370 return false;
373 /* heuristic functions are stored in a table in the registry; the registry has a
374 * table at reference lua_heur_dissectors_table_ref, and that table has keys for
375 * the heuristic listname (e.g., "udp", "tcp", etc.), and that key's value is a
376 * table of keys of the Proto->name, and their value is the function.
377 * So it's like registry[table_ref][heur_list_name][proto_name] = func
380 lua_settop(L,0);
382 /* get the table of all lua heuristic dissector lists */
383 lua_rawgeti(L, LUA_REGISTRYINDEX, lua_heur_dissectors_table_ref);
385 /* get the table inside that, for the lua heuristic dissectors of the requested heur list */
386 if (!wslua_get_table(L, -1, pinfo->heur_list_name)) {
387 /* this shouldn't happen */
388 lua_settop(L,0);
389 proto_tree_add_expert_format(tree, pinfo, &ei_lua_error, tvb, 0, 0,
390 "internal error in heur_dissect_lua: no %s heur list table", pinfo->heur_list_name);
391 return false;
394 /* get the table inside that, for the specific lua heuristic dissector */
395 if (!wslua_get_field(L,-1,pinfo->current_proto)) {
396 /* this shouldn't happen */
397 lua_settop(L,0);
398 proto_tree_add_expert_format(tree, pinfo, &ei_lua_error, tvb, 0, 0,
399 "internal error in heur_dissect_lua: no %s heuristic dissector for list %s",
400 pinfo->current_proto, pinfo->heur_list_name);
401 return false;
404 /* remove the table of all lists (the one in the registry) */
405 lua_remove(L,1);
406 /* remove the heur_list_name heur list table */
407 lua_remove(L,1);
409 if (!lua_isfunction(L,-1)) {
410 /* this shouldn't happen */
411 lua_settop(L,0);
412 proto_tree_add_expert_format(tree, pinfo, &ei_lua_error, tvb, 0, 0,
413 "internal error in heur_dissect_lua: %s heuristic dissector is not a function", pinfo->current_proto);
414 return false;
417 push_Tvb(L,tvb);
418 push_Pinfo(L,pinfo);
419 lua_tree = push_TreeItem(L, tree, proto_tree_add_item(tree, hf_wslua_fake, tvb, 0, 0, ENC_NA));
420 proto_item_set_hidden(lua_tree->item);
422 if ( lua_pcall(L,3,1,0) ) {
423 proto_tree_add_expert_format(tree, pinfo, &ei_lua_error, tvb, 0, 0,
424 "Lua Error: error calling %s heuristic dissector: %s", pinfo->current_proto, lua_tostring(L,-1));
425 lua_settop(L,0);
426 } else {
427 if (lua_isboolean(L, -1) || lua_isnil(L, -1)) {
428 result = lua_toboolean(L, -1);
429 } else if (lua_type(L, -1) == LUA_TNUMBER) {
430 result = lua_tointeger(L,-1) != 0 ? true : false;
431 } else {
432 proto_tree_add_expert_format(tree, pinfo, &ei_lua_error, tvb, 0, 0,
433 "Lua Error: invalid return value from Lua %s heuristic dissector", pinfo->current_proto);
435 lua_pop(L, 1);
438 wmem_register_callback(pinfo->pool, lua_pinfo_end, NULL);
440 lua_pinfo = saved_lua_pinfo;
441 lua_tree = saved_lua_tree;
442 lua_tvb = saved_lua_tvb;
444 return result;
447 static void iter_table_and_call(lua_State* LS, const char* table_name, lua_CFunction error_handler) {
448 lua_settop(LS,0);
450 lua_pushcfunction(LS,error_handler);
451 lua_getglobal(LS, table_name);
453 if (!lua_istable(LS, 2)) {
454 report_failure("Lua: either `%s' does not exist or it is not a table!\n",table_name);
455 lua_close(LS);
456 L = NULL;
457 return;
460 lua_pushnil(LS);
462 while (lua_next(LS, 2)) {
463 const char* name = lua_tostring(L,-2);
465 if (lua_isfunction(LS,-1)) {
467 if ( lua_pcall(LS,0,0,1) ) {
468 lua_pop(LS,1);
471 } else {
472 report_failure("Lua: Something not a function got its way into the %s.%s",table_name,name);
473 lua_close(LS);
474 L = NULL;
475 return;
479 lua_settop(LS,0);
483 static int init_error_handler(lua_State* LS) {
484 const char* error = lua_tostring(LS,1);
485 report_failure("Lua: Error during execution of initialization:\n %s",error);
486 return 0;
490 static bool init_routine_initialized;
491 static void wslua_init_routine(void) {
493 if ( ! init_routine_initialized ) {
495 * This must be done only once during the entire life of
496 * tshark/wireshark, because it must be done only once per the life of
497 * the Lua state/engine, so we guard this with the boolean above;
498 * otherwise it would occur every time a file is opened (every time
499 * epan_new() is called).
501 * If we ever allow the Lua state to be restarted, or to have multiple
502 * Lua states, we'll need to change this.
504 lua_prime_all_fields(NULL);
505 init_routine_initialized = true;
508 if (L) {
509 iter_table_and_call(L, WSLUA_INIT_ROUTINES,init_error_handler);
514 static void wslua_cleanup_routine(void) {
515 if (L) {
516 iter_table_and_call(L, WSLUA_INIT_ROUTINES,init_error_handler);
520 static int prefs_changed_error_handler(lua_State* LS) {
521 const char* error = lua_tostring(LS,1);
522 report_failure("Lua: Error during execution of prefs apply callback:\n %s",error);
523 return 0;
526 void wslua_prefs_changed(void) {
527 if (L) {
528 iter_table_and_call(L, WSLUA_PREFS_CHANGED,prefs_changed_error_handler);
532 static const char *getF(lua_State *LS _U_, void *ud, size_t *size)
534 FILE *f=(FILE *)ud;
535 static char buff[512];
536 if (feof(f)) return NULL;
537 *size=fread(buff,1,sizeof(buff),f);
538 return (*size>0) ? buff : NULL;
541 static int error_handler_with_callback(lua_State *LS) {
542 const char *msg = lua_tostring(LS, 1);
543 luaL_traceback(LS, LS, msg, 1); /* push message with traceback. */
544 lua_remove(LS, -2); /* remove original msg */
545 return 1;
548 static void wslua_add_plugin(const char *name, const char *version, const char *filename)
550 wslua_plugin *new_plug, *lua_plug;
552 lua_plug = wslua_plugin_list;
553 new_plug = g_new(wslua_plugin, 1);
555 if (!lua_plug) { /* the list is empty */
556 wslua_plugin_list = new_plug;
557 } else {
558 while (lua_plug->next != NULL) {
559 lua_plug = lua_plug->next;
561 lua_plug->next = new_plug;
564 new_plug->name = g_strdup(name);
565 new_plug->version = g_strdup(version);
566 new_plug->filename = g_strdup(filename);
567 new_plug->next = NULL;
570 static void wslua_clear_plugin_list(void)
572 wslua_plugin *lua_plug;
574 while (wslua_plugin_list) {
575 lua_plug = wslua_plugin_list;
576 wslua_plugin_list = wslua_plugin_list->next;
577 g_free (lua_plug->name);
578 g_free (lua_plug->version);
579 g_free (lua_plug->filename);
580 g_free (lua_plug);
584 static int lua_script_push_args(const int script_num) {
585 char* argname = ws_strdup_printf("lua_script%d", script_num);
586 const char* argvalue = NULL;
587 int i, count = ex_opt_count(argname);
589 for (i = 0; i < count; i++) {
590 argvalue = ex_opt_get_nth(argname, i);
591 lua_pushstring(L,argvalue);
594 g_free(argname);
595 return count;
598 /* Prepends a path to the global package path (used by require)
599 * We could add a custom loader to package.searchers instead, which
600 * might be more useful in some way. We could also have some method of
601 * saving and restoring the path, instead of constantly adding to it. */
602 static void prepend_path(const char* dirname) {
603 const char* path;
605 /* prepend the directory name to _G.package.path */
606 lua_getglobal(L, "package"); /* get the package table from the global table */
607 lua_getfield(L, -1, "path"); /* get the path field from the package table */
608 path = luaL_checkstring(L, -1); /* get the path string */
609 lua_pop(L, 1); /* pop the path string */
610 /* prepend the path */
611 /* We could also add "?/init.lua" for packages. */
612 lua_pushfstring(L, "%s" G_DIR_SEPARATOR_S "?.lua;%s",
613 dirname, path);
614 lua_setfield(L, -2, "path");
615 lua_pop(L, 1);
618 #define FILE_NAME_KEY "__FILE__"
619 #define DIR_NAME_KEY "__DIR__"
620 #define DIR_SEP_NAME_KEY "__DIR_SEPARATOR__"
621 /* assumes a loaded chunk's function is on top of stack */
622 static void set_file_environment(const char* filename, const char* dirname) {
623 lua_newtable(L); /* environment for script (index 3) */
625 /* XXX - Do we need this? A script can get the filename and path from
626 * debug.getinfo/lua_Debug source */
627 lua_pushstring(L, filename); /* tell the script about its filename */
628 lua_setfield(L, -2, FILE_NAME_KEY); /* make it accessible at __FILE__ */
630 lua_pushstring(L, dirname); /* tell the script about its dirname */
631 lua_setfield(L, -2, DIR_NAME_KEY); /* make it accessible at __DIR__ */
633 /* XXX - Do we need this? package.config:sub(1,1) is the directory separator */
634 lua_pushstring(L, G_DIR_SEPARATOR_S); /* tell the script the directory separator */
635 lua_setfield(L, -2, DIR_SEP_NAME_KEY); /* make it accessible at __DIR_SEPARATOR__ */
637 lua_newtable(L); /* new metatable */
639 lua_pushglobaltable(L);
641 lua_setfield(L, -2, "__index"); /* make metatable's __index point to global table */
643 lua_setmetatable(L, -2); /* pop metatable, set it as metatable of environment */
645 lua_setupvalue(L, -2, 1); /* pop environment and assign it to upvalue 1 */
647 /* The result of this is a new environment that falls back to reading from
648 * the global environment for any entry not in the new environment, but
649 * can't change the global environment while running.
651 * Unfortunately, while we could create a file-local package.path, it
652 * wouldn't have any effect on the path actually used by requires, since
653 * the requires function has as an upvalue the original package table;
654 * we can't change the behavior of requires without changing it for
655 * the global environment and for all scripts.
657 * For some of the same reasons, if the script itself calls require(),
658 * that actually affects the original global environment too, so this
659 * sandboxing doesn't completely work to keep the global environment
660 * unchanged. Is it worth it?
664 /* This loads plugins like Lua modules / libraries, using require().
665 * It has the advantage that loaded files get add to the package.loaded
666 * table, so files aren't run again by require() either.
668 static bool lua_load_plugin(const char* filename) {
669 int status;
670 char *trimmed;
672 const char *basename = get_basename(filename);
673 char *dot = strrchr(basename, '.');
674 if (dot) {
675 trimmed = g_strndup(basename, dot - basename);
676 } else {
677 trimmed = g_strdup(basename);
680 lua_settop(L, 0);
682 lua_pushcfunction(L, error_handler_with_callback);
684 lua_getglobal(L, "require");
686 lua_pushstring(L, trimmed);
687 g_free(trimmed);
689 /* Ignore the return from "require" by passing 0 as nresults to lua_pcall
690 * (we could add it to the global table using the name as dolibrary() does,
691 * but that is deprecated style in modern Lua.)
693 status = lua_pcall(L, 1, 0, 1);
694 if (status != LUA_OK) {
695 switch (status) {
696 case LUA_ERRRUN:
697 report_failure("Lua: Error during loading:\n%s", lua_tostring(L, -1));
698 break;
699 case LUA_ERRMEM:
700 report_failure("Lua: Error during loading: out of memory");
701 break;
702 case LUA_ERRERR:
703 report_failure("Lua: Error during loading: error while retrieving error message");
704 break;
705 default:
706 report_failure("Lua: Error during loading: unknown error %d", status);
707 break;
710 return status == LUA_OK;
713 /* If file_count > 0 then it's a command-line-added user script, and the count
714 * represents which user script it is (first=1, second=2, etc.).
715 * If dirname != NULL, then it's a user script and the dirname will get put in a file environment
716 * If dirname == NULL then it's a wireshark script and no file environment is created
718 static bool lua_load_script(const char* filename, const char* dirname, const int file_count) {
719 FILE* file;
720 int error;
721 int numargs = 0;
723 if (! ( file = ws_fopen(filename,"r")) ) {
724 report_open_failure(filename,errno,false);
725 return false;
728 lua_settop(L,0);
730 lua_pushcfunction(L, error_handler_with_callback);
731 /* The source argument should start with '@' to indicate a file. */
732 lua_pushfstring(L, "@%s", filename);
734 error = lua_load(L, getF, file, lua_tostring(L, -1), NULL);
736 switch (error) {
737 case 0: /* LUA_OK */
738 if (dirname) {
739 set_file_environment(filename, dirname);
741 if (file_count > 0) {
742 numargs = lua_script_push_args(file_count);
744 error = lua_pcall(L, numargs, 0, 1);
745 if (error) {
746 switch (error) {
747 case LUA_ERRRUN:
748 report_failure("Lua: Error during loading:\n%s", lua_tostring(L, -1));
749 break;
750 case LUA_ERRMEM:
751 report_failure("Lua: Error during loading: out of memory");
752 break;
753 case LUA_ERRERR:
754 report_failure("Lua: Error during loading: error while retrieving error message");
755 break;
756 default:
757 report_failure("Lua: Error during loading: unknown error %d", error);
758 break;
761 break;
763 case LUA_ERRSYNTAX:
764 report_failure("Lua: syntax error: %s", lua_tostring(L, -1));
765 break;
767 case LUA_ERRMEM:
768 report_failure("Lua: memory allocation error during precompilation of %s", filename);
769 break;
771 default:
772 report_failure("Lua: unknown error during precompilation of %s: %d", filename, error);
773 break;
775 fclose(file);
776 lua_pop(L, 2); /* pop the filename and error handler */
777 return error == 0;
780 /* This one is used to load the init.lua scripts, or anything else
781 * that shouldn't really be considered a real plugin.
783 static bool lua_load_internal_script(const char* filename) {
784 return lua_load_script(filename, NULL, 0);
787 /* This one is used to load plugins from the plugin directories,
788 * or scripts from the command line. The latter have file_count > 0.
790 static bool lua_load_plugin_script(const char* name,
791 const char* filename,
792 const char* dirname,
793 const int file_count)
795 ws_debug("Loading lua script: %s", filename);
796 if (file_count > 0 ? lua_load_script(filename, dirname, file_count) :
797 lua_load_plugin(filename)) {
798 wslua_add_plugin(name, get_current_plugin_version(), filename);
799 clear_current_plugin_version();
800 return true;
802 return false;
805 static int wslua_panic(lua_State* LS) {
806 ws_error("LUA PANIC: %s",lua_tostring(LS,-1));
807 /** ws_error() does an abort() and thus never returns **/
808 return 0; /* keep gcc happy */
811 static int string_compare(const void *a, const void *b) {
812 return strcmp((const char*)a, (const char*)b);
815 static int lua_load_plugins(const char *dirname, register_cb cb, void *client_data,
816 bool count_only, const bool is_user, GHashTable *loaded_files,
817 int depth)
819 WS_DIR *dir; /* scanned directory */
820 WS_DIRENT *file; /* current file */
821 char *filename, *dot;
822 const char *name;
823 int plugins_counter = 0;
824 GList *sorted_dirnames = NULL;
825 GList *sorted_filenames = NULL;
826 GList *l = NULL;
828 if ((dir = ws_dir_open(dirname, 0, NULL)) != NULL) {
829 while ((file = ws_dir_read_name(dir)) != NULL) {
830 name = ws_dir_get_name(file);
832 if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) {
833 /* skip "." and ".." */
834 continue;
836 if (depth == 0 && strcmp(name, "init.lua") == 0) {
837 /* If we are in the root directory skip the special "init.lua"
838 * file that was already loaded before every other user script.
839 * (If we are below the root script directory we just treat it like any other
840 * lua script.) */
841 continue;
844 filename = ws_strdup_printf("%s" G_DIR_SEPARATOR_S "%s", dirname, name);
845 if (test_for_directory(filename) == EISDIR) {
846 sorted_dirnames = g_list_prepend(sorted_dirnames, (void *)filename);
847 continue;
850 /* skip files starting with . */
851 if (name[0] == '.') {
852 g_free(filename);
853 continue;
856 /* skip anything but files with .lua suffix */
857 dot = strrchr(name, '.');
858 if (dot == NULL || g_ascii_strcasecmp(dot+1, "lua") != 0) {
859 g_free(filename);
860 continue;
863 if (file_exists(filename)) {
864 sorted_filenames = g_list_prepend(sorted_filenames, (void *)filename);
866 else {
867 g_free(filename);
870 ws_dir_close(dir);
873 /* Depth first; ie, process subdirectories (in ASCIIbetical order) before files */
874 if (sorted_dirnames != NULL) {
875 sorted_dirnames = g_list_sort(sorted_dirnames, string_compare);
876 for (l = sorted_dirnames; l != NULL; l = l->next) {
877 plugins_counter += lua_load_plugins((const char *)l->data, cb, client_data, count_only, is_user, loaded_files, depth + 1);
879 g_list_free_full(sorted_dirnames, g_free);
882 /* Process files in ASCIIbetical order */
883 if (sorted_filenames != NULL) {
884 /* If this is not the root of the plugin directory, add it to the path.
885 * XXX - Should we remove it after we're done with this directory? */
886 if (depth > 0) {
887 prepend_path(dirname);
889 sorted_filenames = g_list_sort(sorted_filenames, string_compare);
890 for (l = sorted_filenames; l != NULL; l = l->next) {
891 filename = (char *)l->data;
892 name = strrchr(filename, G_DIR_SEPARATOR) + 1;
894 /* Check if we have already loaded this file name, if provided with a set */
895 if (loaded_files && g_hash_table_lookup_extended(loaded_files, name, NULL, NULL)) {
896 continue;
899 if (!count_only) {
900 if (cb)
901 (*cb)(RA_LUA_PLUGINS, name, client_data);
902 lua_load_plugin_script(name, filename, is_user ? dirname : NULL, 0);
904 if (loaded_files) {
905 g_hash_table_insert(loaded_files, g_strdup(name), NULL);
908 plugins_counter++;
910 g_list_free_full(sorted_filenames, g_free);
913 return plugins_counter;
916 static int lua_load_global_plugins(register_cb cb, void *client_data,
917 bool count_only)
919 return lua_load_plugins(get_plugins_dir(), cb, client_data, count_only, false, NULL, 0);
922 static int lua_load_pers_plugins(register_cb cb, void *client_data,
923 bool count_only)
925 int plugins_counter = 0;
927 /* aux table (set) to make sure we only load each file once (by name) */
928 /* XXX - This doesn't prevent users from loading a file a second time
929 * via a different method, e.g., require() or dofile().
931 * It shouldn't be needed now that we're calling require for the plugins.
933 GHashTable *loaded_user_scripts = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
935 /* load user scripts */
936 plugins_counter += lua_load_plugins(get_plugins_pers_dir(), cb, client_data, count_only, true, loaded_user_scripts, 0);
938 /* for backward compatibility check old plugin directory */
939 char *old_path = get_persconffile_path("plugins", false);
940 if (strcmp(get_plugins_pers_dir(), old_path) != 0) {
941 plugins_counter += lua_load_plugins(old_path, cb, client_data, count_only, true, loaded_user_scripts, 0);
943 g_free(old_path);
945 g_hash_table_destroy(loaded_user_scripts);
947 return plugins_counter;
950 int wslua_count_plugins(void) {
951 int plugins_counter;
953 /* count global scripts */
954 plugins_counter = lua_load_global_plugins(NULL, NULL, true);
956 /* count user scripts */
957 plugins_counter += lua_load_pers_plugins(NULL, NULL, true);
959 /* count scripts from command line */
960 plugins_counter += ex_opt_count("lua_script");
962 return plugins_counter;
965 void wslua_plugins_get_descriptions(wslua_plugin_description_callback callback, void *user_data) {
966 wslua_plugin *lua_plug;
968 for (lua_plug = wslua_plugin_list; lua_plug != NULL; lua_plug = lua_plug->next)
970 callback(lua_plug->name, lua_plug->version, wslua_plugin_type_name(),
971 lua_plug->filename, user_data);
975 static void
976 print_wslua_plugin_description(const char *name, const char *version,
977 const char *description, const char *filename,
978 void *user_data _U_)
980 printf("%s\t%s\t%s\t%s\n", name, version, description, filename);
983 void
984 wslua_plugins_dump_all(void)
986 wslua_plugins_get_descriptions(print_wslua_plugin_description, NULL);
989 const char *wslua_plugin_type_name(void) {
990 return "lua script";
993 static ei_register_info* ws_lua_ei;
994 static int ws_lua_ei_len;
996 expert_field*
997 wslua_get_expert_field(const int group, const int severity)
999 int i;
1000 const ei_register_info *ei = ws_lua_ei;
1002 ws_assert(ei);
1004 for (i=0; i < ws_lua_ei_len; i++, ei++) {
1005 if (ei->eiinfo.group == group && ei->eiinfo.severity == severity)
1006 return ei->ids;
1009 return &ei_lua_error;
1012 static void *
1013 wslua_allocf(void *ud _U_, void *ptr, size_t osize _U_, size_t nsize)
1015 /* g_realloc frees ptr if nsize==0 and returns NULL (as desired).
1016 * Furthermore it simplifies error handling by aborting on OOM */
1017 return g_realloc(ptr, nsize);
1020 #define WSLUA_EPAN_ENUMS_TABLE "_EPAN"
1021 #define WSLUA_WTAP_ENUMS_TABLE "_WTAP"
1023 #define WSLUA_BASE_TABLE "base"
1024 #define WSLUA_FTYPE_TABLE "ftypes"
1025 #define WSLUA_FRAMETYPE_TABLE "frametype"
1026 #define WSLUA_EXPERT_TABLE "expert"
1027 #define WSLUA_EXPERT_GROUP_TABLE "group"
1028 #define WSLUA_EXPERT_SEVERITY_TABLE "severity"
1029 #define WSLUA_WTAP_ENCAPS_TABLE "wtap_encaps"
1030 #define WSLUA_WTAP_TSPREC_TABLE "wtap_tsprecs"
1031 #define WSLUA_WTAP_COMMENTS_TABLE "wtap_comments"
1032 #define WSLUA_WTAP_RECTYPES_TABLE "wtap_rec_types"
1033 #define WSLUA_WTAP_PRESENCE_FLAGS_TABLE "wtap_presence_flags"
1035 static void
1036 add_table_symbol(const char *table, const char *name, int value)
1038 /* Get table from the global environment. */
1039 lua_getglobal(L, table);
1040 /* Set symbol in table. */
1041 lua_pushstring(L, name);
1042 lua_pushinteger(L, value);
1043 lua_settable(L, -3);
1044 /* Pop table from stack. */
1045 lua_pop(L, 1);
1048 static void
1049 add_global_symbol(const char *name, int value)
1051 /* Set symbol in global environment. */
1052 lua_pushinteger(L, value);
1053 lua_setglobal(L, name);
1056 static void
1057 add_pi_severity_symbol(const char *name, int value)
1059 lua_getglobal(L, WSLUA_EXPERT_TABLE);
1060 lua_getfield(L, -1, WSLUA_EXPERT_SEVERITY_TABLE);
1061 lua_pushinteger(L, value);
1062 lua_setfield(L, -2, name);
1063 lua_pop(L, 2);
1066 static void
1067 add_pi_group_symbol(const char *name, int value)
1069 lua_getglobal(L, WSLUA_EXPERT_TABLE);
1070 lua_getfield(L, -1, WSLUA_EXPERT_GROUP_TABLE);
1071 lua_pushinteger(L, value);
1072 lua_setfield(L, -2, name);
1073 lua_pop(L, 2);
1076 static void
1077 add_menu_group_symbol(const char *name, int value)
1079 /* Set symbol in global environment. */
1080 lua_pushinteger(L, value);
1081 char *str = g_strdup(name);
1082 char *s = strstr(str, "_GROUP_");
1083 if (s == NULL) {
1084 g_free(str);
1085 return;
1087 *s = '\0';
1088 s += strlen("_GROUP_");
1089 char *str2 = ws_strdup_printf("MENU_%s_%s", str, s);
1090 lua_setglobal(L, str2);
1091 g_free(str);
1092 g_free(str2);
1096 * Read introspection constants and add them according to the historical
1097 * (sometimes arbitrary) rules of make-init-lua.py. For efficiency reasons
1098 * we only loop the enums array once.
1100 static void
1101 wslua_add_introspection(void)
1103 const ws_enum_t *ep;
1105 /* Add empty tables to be populated. */
1106 lua_newtable(L);
1107 lua_setglobal(L, WSLUA_BASE_TABLE);
1108 lua_newtable(L);
1109 lua_setglobal(L, WSLUA_FTYPE_TABLE);
1110 lua_newtable(L);
1111 lua_setglobal(L, WSLUA_FRAMETYPE_TABLE);
1112 lua_newtable(L);
1113 lua_pushstring(L, WSLUA_EXPERT_GROUP_TABLE);
1114 lua_newtable(L);
1115 lua_settable(L, -3);
1116 lua_pushstring(L, WSLUA_EXPERT_SEVERITY_TABLE);
1117 lua_newtable(L);
1118 lua_settable(L, -3);
1119 lua_setglobal(L, WSLUA_EXPERT_TABLE);
1120 /* Add catch-all _EPAN table. */
1121 lua_newtable(L);
1122 lua_setglobal(L, WSLUA_EPAN_ENUMS_TABLE);
1124 for (ep = epan_inspect_enums(); ep->symbol != NULL; ep++) {
1126 if (g_str_has_prefix(ep->symbol, "BASE_")) {
1127 add_table_symbol(WSLUA_BASE_TABLE, ep->symbol + strlen("BASE_"), ep->value);
1129 else if (g_str_has_prefix(ep->symbol, "SEP_")) {
1130 add_table_symbol(WSLUA_BASE_TABLE, ep->symbol + strlen("SEP_"), ep->value);
1132 else if (g_str_has_prefix(ep->symbol, "ABSOLUTE_TIME_")) {
1133 add_table_symbol(WSLUA_BASE_TABLE, ep->symbol + strlen("ABSOLUTE_TIME_"), ep->value);
1135 else if (g_str_has_prefix(ep->symbol, "ENC_")) {
1136 add_global_symbol(ep->symbol, ep->value);
1138 else if (g_str_has_prefix(ep->symbol, "FT_FRAMENUM_")) {
1139 add_table_symbol(WSLUA_FRAMETYPE_TABLE, ep->symbol + strlen("FT_FRAMENUM_"), ep->value);
1141 else if (g_str_has_prefix(ep->symbol, "FT_")) {
1142 add_table_symbol(WSLUA_FTYPE_TABLE, ep->symbol + strlen("FT_"), ep->value);
1144 else if (g_str_has_prefix(ep->symbol, "PI_")) {
1145 if (ep->value & PI_SEVERITY_MASK) {
1146 add_pi_severity_symbol(ep->symbol + strlen("PI_"), ep->value);
1148 else {
1149 add_pi_group_symbol(ep->symbol + strlen("PI_"), ep->value);
1151 /* For backward compatibility. */
1152 add_global_symbol(ep->symbol, ep->value);
1154 else if (g_str_has_prefix(ep->symbol, "REGISTER_")) {
1155 add_menu_group_symbol(ep->symbol + strlen("REGISTER_"), ep->value);
1157 add_table_symbol(WSLUA_EPAN_ENUMS_TABLE, ep->symbol, ep->value);
1160 /* Add empty tables to be populated. */
1161 lua_newtable(L);
1162 lua_setglobal(L, WSLUA_WTAP_ENCAPS_TABLE);
1163 lua_newtable(L);
1164 lua_setglobal(L, WSLUA_WTAP_TSPREC_TABLE);
1165 lua_newtable(L);
1166 lua_setglobal(L, WSLUA_WTAP_COMMENTS_TABLE);
1167 lua_newtable(L);
1168 lua_setglobal(L, WSLUA_WTAP_RECTYPES_TABLE);
1169 lua_newtable(L);
1170 lua_setglobal(L, WSLUA_WTAP_PRESENCE_FLAGS_TABLE);
1171 /* Add catch-all _WTAP table. */
1172 lua_newtable(L);
1173 lua_setglobal(L, WSLUA_WTAP_ENUMS_TABLE);
1175 for (ep = wtap_inspect_enums(); ep->symbol != NULL; ep++) {
1177 if (g_str_has_prefix(ep->symbol, "WTAP_ENCAP_")) {
1178 add_table_symbol(WSLUA_WTAP_ENCAPS_TABLE, ep->symbol + strlen("WTAP_ENCAP_"), ep->value);
1180 else if (g_str_has_prefix(ep->symbol, "WTAP_TSPREC_")) {
1181 add_table_symbol(WSLUA_WTAP_TSPREC_TABLE, ep->symbol + strlen("WTAP_TSPREC_"), ep->value);
1183 else if (g_str_has_prefix(ep->symbol, "WTAP_COMMENT_")) {
1184 add_table_symbol(WSLUA_WTAP_COMMENTS_TABLE, ep->symbol + strlen("WTAP_COMMENT_"), ep->value);
1186 else if (g_str_has_prefix(ep->symbol, "REC_TYPE_")) {
1187 add_table_symbol(WSLUA_WTAP_RECTYPES_TABLE, ep->symbol + strlen("REC_TYPE_"), ep->value);
1189 else if (g_str_has_prefix(ep->symbol, "WTAP_HAS_")) {
1190 add_table_symbol(WSLUA_WTAP_PRESENCE_FLAGS_TABLE, ep->symbol + strlen("WTAP_HAS_"), ep->value);
1192 add_table_symbol(WSLUA_WTAP_ENUMS_TABLE, ep->symbol, ep->value);
1196 static void wslua_add_deprecated(void)
1198 /* For backward compatibility. */
1199 lua_getglobal(L, "wtap_encaps");
1200 lua_setglobal(L, "wtap");
1203 * Generate the wtap_filetypes items for file types, for backwards
1204 * compatibility.
1205 * We no longer have WTAP_FILE_TYPE_SUBTYPE_ #defines;
1206 * built-in file types are registered the same way that
1207 * plugin file types are registered.
1209 * New code should use wtap_name_to_file_type_subtype to
1210 * look up file types by name.
1212 wslua_init_wtap_filetypes(L);
1214 /* Old / deprecated menu groups. These shoudn't be used in new code. */
1215 lua_getglobal(L, "MENU_PACKET_ANALYZE_UNSORTED");
1216 lua_setglobal(L, "MENU_ANALYZE_UNSORTED");
1217 lua_getglobal(L, "MENU_ANALYZE_CONVERSATION_FILTER");
1218 lua_setglobal(L, "MENU_ANALYZE_CONVERSATION");
1219 lua_getglobal(L, "MENU_STAT_CONVERSATION_LIST");
1220 lua_setglobal(L, "MENU_STAT_CONVERSATION");
1221 lua_getglobal(L, "MENU_STAT_ENDPOINT_LIST");
1222 lua_setglobal(L, "MENU_STAT_ENDPOINT");
1223 lua_getglobal(L, "MENU_STAT_RESPONSE_TIME");
1224 lua_setglobal(L, "MENU_STAT_RESPONSE");
1225 lua_getglobal(L, "MENU_PACKET_STAT_UNSORTED");
1226 lua_setglobal(L, "MENU_STAT_UNSORTED");
1227 lua_getglobal(L, "MENU_TELEPHONY_UNSORTED");
1228 lua_setglobal(L, "MENU_STAT_TELEPHONY");
1229 lua_getglobal(L, "MENU_TELEPHONY_ANSI");
1230 lua_setglobal(L, "MENU_STAT_TELEPHONY_ANSI");
1231 lua_getglobal(L, "MENU_TELEPHONY_GSM");
1232 lua_setglobal(L, "MENU_STAT_TELEPHONY_GSM");
1233 lua_getglobal(L, "MENU_TELEPHONY_3GPP_UU");
1234 lua_setglobal(L, "MENU_STAT_TELEPHONY_3GPP_UU");
1235 lua_getglobal(L, "MENU_TELEPHONY_MTP3");
1236 lua_setglobal(L, "MENU_STAT_TELEPHONY_MTP3");
1237 lua_getglobal(L, "MENU_TELEPHONY_SCTP");
1238 lua_setglobal(L, "MENU_STAT_TELEPHONY_SCTP");
1240 /* deprecated function names */
1241 lua_getglobal(L, "Dir");
1242 lua_getfield(L, -1, "global_config_path");
1243 lua_setglobal(L, "datafile_path");
1244 lua_getfield(L, -1, "personal_config_path");
1245 lua_setglobal(L, "persconffile_path");
1246 lua_pop(L, 1);
1249 static int wslua_console_print(lua_State *_L);
1251 static const char *lua_error_msg(int code)
1253 switch (code) {
1254 case LUA_ERRSYNTAX: return "syntax error during precompilation";
1255 case LUA_ERRMEM: return "memory allocation error";
1256 #if LUA_VERSION_NUM == 502
1257 case LUA_ERRGCMM: return "error while running a __gc metamethod";
1258 #endif
1259 case LUA_ERRRUN: return "runtime error";
1260 case LUA_ERRERR: return "error while running the message handler";
1261 default: break; /* Should not happen. */
1263 return "unknown error";
1266 static int lua_funnel_console_eval(const char *console_input,
1267 char **error_ptr,
1268 char **error_hint,
1269 void *callback_data _U_)
1271 int lcode;
1273 const int curr_top = lua_gettop(L);
1275 // If it starts with an equals sign replace it with "return"
1276 char *codestr;
1277 while (g_ascii_isspace(*console_input))
1278 console_input++;
1279 if (*console_input == '=')
1280 codestr = ws_strdup_printf("return %s", console_input+1);
1281 else
1282 codestr = (char *)console_input; /* Violate const safety to avoid a strdup() */
1284 ws_noisy("Console input: %s", codestr);
1285 lcode = luaL_loadstring(L, codestr);
1286 /* Free only if we called strdup(). */
1287 if (codestr != console_input)
1288 g_free(codestr);
1289 codestr = NULL;
1291 if (lcode != LUA_OK) {
1292 ws_debug("luaL_loadstring(): %s (%d)", lua_error_msg(lcode), lcode);
1293 if (error_hint) {
1294 *error_hint = g_strdup(lua_error_msg(lcode));
1296 /* If we have an error message return it. */
1297 if (error_ptr && !lua_isnil(L, -1)) {
1298 *error_ptr = g_strdup(lua_tostring(L, -1));
1300 return -1;
1303 lcode = lua_pcall(L, 0, LUA_MULTRET, 0);
1304 if (lcode != LUA_OK) {
1305 ws_debug("lua_pcall(): %s (%d)", lua_error_msg(lcode), lcode);
1306 if (error_hint) {
1307 *error_hint = g_strdup(lua_error_msg(lcode));
1309 /* If we have an error message return it. */
1310 if (error_ptr && !lua_isnil(L, -1)) {
1311 *error_ptr = g_strdup(lua_tostring(L, -1));
1313 return 1;
1316 // If we have values returned print them all
1317 if (lua_gettop(L) > curr_top) { /* any arguments? */
1318 lua_pushcfunction(L, wslua_console_print);
1319 lua_insert(L, curr_top+1);
1320 lcode = lua_pcall(L, lua_gettop(L)-curr_top-1, 0, 0);
1321 if (lcode != LUA_OK) {
1322 /* Error printing result */
1323 if (error_hint)
1324 *error_hint = ws_strdup_printf("error printing return values: %s", lua_error_msg(lcode));
1325 return 1;
1329 // For any new Protos, register their ProtoFields and ProtoExperts with epan
1330 lua_pushcfunction(L, Proto_commit);
1331 lcode = lua_pcall(L, 0, 0, 0);
1332 if (lcode != LUA_OK) {
1333 /* Error initializing new ProtoFields */
1334 if (error_hint)
1335 *error_hint = ws_strdup_printf("error initialzing protocol fields: %s", lua_error_msg(lcode));
1336 /* If we have an error message return it. */
1337 if (error_ptr && !lua_isnil(L, -1)) {
1338 *error_ptr = g_strdup(lua_tostring(L, -1));
1340 return 1;
1343 // Maintain stack discipline
1344 if (lua_gettop(L) != curr_top) {
1345 ws_critical("Expected stack top == %d, have %d", curr_top, lua_gettop(L));
1348 ws_noisy("Success");
1349 return 0;
1352 /* Receives C print function pointer as first upvalue. */
1353 /* Receives C print function data pointer as second upvalue. */
1354 static int wslua_console_print(lua_State *_L)
1356 GString *gstr = g_string_new(NULL);
1357 const char *repr;
1359 /* Print arguments. */
1360 for (int i = 1; i <= lua_gettop(_L); i++) {
1361 repr = luaL_tolstring(_L, i, NULL);
1362 if (i > 1)
1363 g_string_append_c(gstr, '\t');
1364 g_string_append(gstr, repr);
1365 lua_pop(_L, 1);
1367 g_string_append_c(gstr, '\n');
1369 if (wslua_gui_print_func_ptr == NULL) {
1370 ws_critical("GUI print function not registered; Trying to print: %s", gstr->str);
1372 else {
1373 wslua_gui_print_func_ptr(gstr->str, wslua_gui_print_data_ptr);
1375 g_string_free(gstr, TRUE);
1376 return 0;
1379 // Replace lua print function with a custom print function.
1380 // We will place the original function in the Lua registry and return the reference.
1381 static void lua_funnel_console_open(void (*print_func_ptr)(const char *, void *),
1382 void *print_data_ptr,
1383 void *callback_data _U_)
1385 /* Store original print value in the registry (even if it is nil). */
1386 lua_getglobal(L, "print");
1387 wslua_lua_print_func_ref = luaL_ref(L, LUA_REGISTRYINDEX);
1389 /* Set new "print" function (to output to the GUI) */
1390 lua_pushcfunction(L, wslua_console_print);
1391 lua_setglobal(L, "print");
1393 /* Save the globals */
1394 ws_assert(print_func_ptr);
1395 wslua_gui_print_func_ptr = print_func_ptr;
1396 wslua_gui_print_data_ptr = print_data_ptr;
1399 // Restore original Lua print function. Clean state.
1400 static void lua_funnel_console_close(void *callback_data _U_)
1402 /* Restore the original print function. */
1403 int ref = (int)wslua_lua_print_func_ref;
1404 /* push original function into stack */
1405 lua_rawgeti(L, LUA_REGISTRYINDEX, ref);
1406 lua_setglobal(L, "print");
1407 /* Release reference */
1408 luaL_unref(L, LUA_REGISTRYINDEX, ref);
1410 /* Clear the globals. */
1411 wslua_gui_print_func_ptr = NULL;
1412 wslua_gui_print_data_ptr = NULL;
1413 wslua_lua_print_func_ref = LUA_NOREF;
1416 static int wslua_file_exists(lua_State *_L)
1418 const char *path = luaL_checkstring(_L, 1);
1419 lua_pushboolean(_L, g_file_test(path, G_FILE_TEST_EXISTS));
1420 return 1;
1423 static int wslua_lua_typeof(lua_State *_L)
1425 const char *classname = wslua_typeof(_L, 1);
1426 lua_pushstring(_L, classname);
1427 return 1;
1430 /* Other useful constants */
1431 void wslua_add_useful_constants(void)
1433 const funnel_ops_t *ops = funnel_get_funnel_ops();
1434 char *path;
1436 WSLUA_REG_GLOBAL_BOOL(L,"GUI_ENABLED",ops && ops->new_dialog);
1438 /* DATA_DIR has a trailing directory separator. */
1439 path = get_datafile_path("");
1440 lua_pushfstring(L, "%s"G_DIR_SEPARATOR_S, path);
1441 g_free(path);
1442 lua_setglobal(L, "DATA_DIR");
1444 /* USER_DIR has a trailing directory separator. */
1445 path = get_persconffile_path("", false);
1446 lua_pushfstring(L, "%s"G_DIR_SEPARATOR_S, path);
1447 g_free(path);
1448 lua_setglobal(L, "USER_DIR");
1450 lua_pushcfunction(L, wslua_file_exists);
1451 lua_setglobal(L, "file_exists");
1453 lua_pushcfunction(L, wslua_lua_typeof);
1454 lua_setglobal(L, "typeof");
1457 void wslua_init(register_cb cb, void *client_data) {
1458 char* filename;
1459 bool enable_lua = true;
1460 bool run_anyway = false;
1461 expert_module_t* expert_lua;
1462 int file_count = 1;
1463 static bool first_time = true;
1464 int i;
1465 int error;
1467 static hf_register_info hf[] = {
1468 { &hf_wslua_fake,
1469 { "Wireshark Lua fake item", "_ws.lua.fake",
1470 FT_NONE, BASE_NONE, NULL, 0x0,
1471 "Fake internal item for Wireshark Lua", HFILL }},
1472 { &hf_wslua_text,
1473 { "Wireshark Lua text", "_ws.lua.text",
1474 FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1476 static int *ett[] = {
1477 &ett_wslua_traceback,
1480 static ei_register_info ei[] = {
1481 /* the following are created so we can continue to support the TreeItem_add_expert_info()
1482 function to Lua scripts. That function doesn't know what registered protocol to use,
1483 so it uses the "_ws.lua" one. */
1484 /* XXX: it seems to me we should not be offering PI_GROUP_MASK nor PI_SEVERITY_MASK since
1485 they are not real settings, so I'm not adding them below (should they also not be exported
1486 into Lua? they are right now.) */
1487 /* NOTE: do not add expert entries at the top of this array - only at the bottom. This array
1488 is not only used by expert.c, but also by wslua_get_expert_field() to find the appropriate
1489 "dummy" entry. So this array's ordering matters. */
1490 { &ei_lua_proto_checksum_comment, { "_ws.lua.proto.comment", PI_CHECKSUM, PI_COMMENT ,"Protocol Comment", EXPFILL }},
1491 { &ei_lua_proto_checksum_chat, { "_ws.lua.proto.chat", PI_CHECKSUM, PI_CHAT ,"Protocol Chat", EXPFILL }},
1492 { &ei_lua_proto_checksum_note, { "_ws.lua.proto.note", PI_CHECKSUM, PI_NOTE ,"Protocol Note", EXPFILL }},
1493 { &ei_lua_proto_checksum_warn, { "_ws.lua.proto.warning", PI_CHECKSUM, PI_WARN ,"Protocol Warning", EXPFILL }},
1494 { &ei_lua_proto_checksum_error, { "_ws.lua.proto.error", PI_CHECKSUM, PI_ERROR ,"Protocol Error", EXPFILL }},
1496 { &ei_lua_proto_sequence_comment, { "_ws.lua.proto.comment", PI_SEQUENCE, PI_COMMENT ,"Protocol Comment", EXPFILL }},
1497 { &ei_lua_proto_sequence_chat, { "_ws.lua.proto.chat", PI_SEQUENCE, PI_CHAT ,"Protocol Chat", EXPFILL }},
1498 { &ei_lua_proto_sequence_note, { "_ws.lua.proto.note", PI_SEQUENCE, PI_NOTE ,"Protocol Note", EXPFILL }},
1499 { &ei_lua_proto_sequence_warn, { "_ws.lua.proto.warning", PI_SEQUENCE, PI_WARN ,"Protocol Warning", EXPFILL }},
1500 { &ei_lua_proto_sequence_error, { "_ws.lua.proto.error", PI_SEQUENCE, PI_ERROR ,"Protocol Error", EXPFILL }},
1502 { &ei_lua_proto_response_comment, { "_ws.lua.proto.comment", PI_RESPONSE_CODE, PI_COMMENT ,"Protocol Comment", EXPFILL }},
1503 { &ei_lua_proto_response_chat, { "_ws.lua.proto.chat", PI_RESPONSE_CODE, PI_CHAT ,"Protocol Chat", EXPFILL }},
1504 { &ei_lua_proto_response_note, { "_ws.lua.proto.note", PI_RESPONSE_CODE, PI_NOTE ,"Protocol Note", EXPFILL }},
1505 { &ei_lua_proto_response_warn, { "_ws.lua.proto.warning", PI_RESPONSE_CODE, PI_WARN ,"Protocol Warning", EXPFILL }},
1506 { &ei_lua_proto_response_error, { "_ws.lua.proto.error", PI_RESPONSE_CODE, PI_ERROR ,"Protocol Error", EXPFILL }},
1508 { &ei_lua_proto_request_comment, { "_ws.lua.proto.comment", PI_REQUEST_CODE, PI_COMMENT ,"Protocol Comment", EXPFILL }},
1509 { &ei_lua_proto_request_chat, { "_ws.lua.proto.chat", PI_REQUEST_CODE, PI_CHAT ,"Protocol Chat", EXPFILL }},
1510 { &ei_lua_proto_request_note, { "_ws.lua.proto.note", PI_REQUEST_CODE, PI_NOTE ,"Protocol Note", EXPFILL }},
1511 { &ei_lua_proto_request_warn, { "_ws.lua.proto.warning", PI_REQUEST_CODE, PI_WARN ,"Protocol Warning", EXPFILL }},
1512 { &ei_lua_proto_request_error, { "_ws.lua.proto.error", PI_REQUEST_CODE, PI_ERROR ,"Protocol Error", EXPFILL }},
1514 { &ei_lua_proto_undecoded_comment, { "_ws.lua.proto.comment", PI_UNDECODED, PI_COMMENT ,"Protocol Comment", EXPFILL }},
1515 { &ei_lua_proto_undecoded_chat, { "_ws.lua.proto.chat", PI_UNDECODED, PI_CHAT ,"Protocol Chat", EXPFILL }},
1516 { &ei_lua_proto_undecoded_note, { "_ws.lua.proto.note", PI_UNDECODED, PI_NOTE ,"Protocol Note", EXPFILL }},
1517 { &ei_lua_proto_undecoded_warn, { "_ws.lua.proto.warning", PI_UNDECODED, PI_WARN ,"Protocol Warning", EXPFILL }},
1518 { &ei_lua_proto_undecoded_error, { "_ws.lua.proto.error", PI_UNDECODED, PI_ERROR ,"Protocol Error", EXPFILL }},
1520 { &ei_lua_proto_reassemble_comment, { "_ws.lua.proto.comment", PI_REASSEMBLE, PI_COMMENT ,"Protocol Comment", EXPFILL }},
1521 { &ei_lua_proto_reassemble_chat, { "_ws.lua.proto.chat", PI_REASSEMBLE, PI_CHAT ,"Protocol Chat", EXPFILL }},
1522 { &ei_lua_proto_reassemble_note, { "_ws.lua.proto.note", PI_REASSEMBLE, PI_NOTE ,"Protocol Note", EXPFILL }},
1523 { &ei_lua_proto_reassemble_warn, { "_ws.lua.proto.warning", PI_REASSEMBLE, PI_WARN ,"Protocol Warning", EXPFILL }},
1524 { &ei_lua_proto_reassemble_error, { "_ws.lua.proto.error", PI_REASSEMBLE, PI_ERROR ,"Protocol Error", EXPFILL }},
1526 { &ei_lua_proto_malformed_comment, { "_ws.lua.proto.comment", PI_MALFORMED, PI_COMMENT ,"Protocol Comment", EXPFILL }},
1527 { &ei_lua_proto_malformed_chat, { "_ws.lua.proto.chat", PI_MALFORMED, PI_CHAT ,"Protocol Chat", EXPFILL }},
1528 { &ei_lua_proto_malformed_note, { "_ws.lua.proto.note", PI_MALFORMED, PI_NOTE ,"Protocol Note", EXPFILL }},
1529 { &ei_lua_proto_malformed_warn, { "_ws.lua.proto.warning", PI_MALFORMED, PI_WARN ,"Protocol Warning", EXPFILL }},
1530 { &ei_lua_proto_malformed_error, { "_ws.lua.proto.error", PI_MALFORMED, PI_ERROR ,"Protocol Error", EXPFILL }},
1532 { &ei_lua_proto_debug_comment, { "_ws.lua.proto.comment", PI_DEBUG, PI_COMMENT ,"Protocol Comment", EXPFILL }},
1533 { &ei_lua_proto_debug_chat, { "_ws.lua.proto.chat", PI_DEBUG, PI_CHAT ,"Protocol Chat", EXPFILL }},
1534 { &ei_lua_proto_debug_note, { "_ws.lua.proto.note", PI_DEBUG, PI_NOTE ,"Protocol Note", EXPFILL }},
1535 { &ei_lua_proto_debug_warn, { "_ws.lua.proto.warning", PI_DEBUG, PI_WARN ,"Protocol Warning", EXPFILL }},
1536 { &ei_lua_proto_debug_error, { "_ws.lua.proto.error", PI_DEBUG, PI_ERROR ,"Protocol Error", EXPFILL }},
1538 { &ei_lua_proto_protocol_comment, { "_ws.lua.proto.comment", PI_PROTOCOL, PI_COMMENT ,"Protocol Comment", EXPFILL }},
1539 { &ei_lua_proto_protocol_chat, { "_ws.lua.proto.chat", PI_PROTOCOL, PI_CHAT ,"Protocol Chat", EXPFILL }},
1540 { &ei_lua_proto_protocol_note, { "_ws.lua.proto.note", PI_PROTOCOL, PI_NOTE ,"Protocol Note", EXPFILL }},
1541 { &ei_lua_proto_protocol_warn, { "_ws.lua.proto.warning", PI_PROTOCOL, PI_WARN ,"Protocol Warning", EXPFILL }},
1542 { &ei_lua_proto_protocol_error, { "_ws.lua.proto.error", PI_PROTOCOL, PI_ERROR ,"Protocol Error", EXPFILL }},
1544 { &ei_lua_proto_security_comment, { "_ws.lua.proto.comment", PI_SECURITY, PI_COMMENT ,"Protocol Comment", EXPFILL }},
1545 { &ei_lua_proto_security_chat, { "_ws.lua.proto.chat", PI_SECURITY, PI_CHAT ,"Protocol Chat", EXPFILL }},
1546 { &ei_lua_proto_security_note, { "_ws.lua.proto.note", PI_SECURITY, PI_NOTE ,"Protocol Note", EXPFILL }},
1547 { &ei_lua_proto_security_warn, { "_ws.lua.proto.warning", PI_SECURITY, PI_WARN ,"Protocol Warning", EXPFILL }},
1548 { &ei_lua_proto_security_error, { "_ws.lua.proto.error", PI_SECURITY, PI_ERROR ,"Protocol Error", EXPFILL }},
1550 { &ei_lua_proto_comments_comment, { "_ws.lua.proto.comment", PI_COMMENTS_GROUP, PI_COMMENT ,"Protocol Comment", EXPFILL }},
1551 { &ei_lua_proto_comments_chat, { "_ws.lua.proto.chat", PI_COMMENTS_GROUP, PI_CHAT ,"Protocol Chat", EXPFILL }},
1552 { &ei_lua_proto_comments_note, { "_ws.lua.proto.note", PI_COMMENTS_GROUP, PI_NOTE ,"Protocol Note", EXPFILL }},
1553 { &ei_lua_proto_comments_warn, { "_ws.lua.proto.warning", PI_COMMENTS_GROUP, PI_WARN ,"Protocol Warning", EXPFILL }},
1554 { &ei_lua_proto_comments_error, { "_ws.lua.proto.error", PI_COMMENTS_GROUP, PI_ERROR ,"Protocol Error", EXPFILL }},
1556 { &ei_lua_proto_decryption_comment, { "_ws.lua.proto.comment", PI_DECRYPTION, PI_COMMENT ,"Protocol Comment", EXPFILL }},
1557 { &ei_lua_proto_decryption_chat, { "_ws.lua.proto.chat", PI_DECRYPTION, PI_CHAT ,"Protocol Chat", EXPFILL }},
1558 { &ei_lua_proto_decryption_note, { "_ws.lua.proto.note", PI_DECRYPTION, PI_NOTE ,"Protocol Note", EXPFILL }},
1559 { &ei_lua_proto_decryption_warn, { "_ws.lua.proto.warning", PI_DECRYPTION, PI_WARN ,"Protocol Warning", EXPFILL }},
1560 { &ei_lua_proto_decryption_error, { "_ws.lua.proto.error", PI_DECRYPTION, PI_ERROR ,"Protocol Error", EXPFILL }},
1562 { &ei_lua_proto_assumption_comment, { "_ws.lua.proto.comment", PI_ASSUMPTION, PI_COMMENT ,"Protocol Comment", EXPFILL }},
1563 { &ei_lua_proto_assumption_chat, { "_ws.lua.proto.chat", PI_ASSUMPTION, PI_CHAT ,"Protocol Chat", EXPFILL }},
1564 { &ei_lua_proto_assumption_note, { "_ws.lua.proto.note", PI_ASSUMPTION, PI_NOTE ,"Protocol Note", EXPFILL }},
1565 { &ei_lua_proto_assumption_warn, { "_ws.lua.proto.warning", PI_ASSUMPTION, PI_WARN ,"Protocol Warning", EXPFILL }},
1566 { &ei_lua_proto_assumption_error, { "_ws.lua.proto.error", PI_ASSUMPTION, PI_ERROR ,"Protocol Error", EXPFILL }},
1568 { &ei_lua_proto_deprecated_comment, { "_ws.lua.proto.comment", PI_DEPRECATED, PI_COMMENT ,"Protocol Comment", EXPFILL }},
1569 { &ei_lua_proto_deprecated_chat, { "_ws.lua.proto.chat", PI_DEPRECATED, PI_CHAT ,"Protocol Chat", EXPFILL }},
1570 { &ei_lua_proto_deprecated_note, { "_ws.lua.proto.note", PI_DEPRECATED, PI_NOTE ,"Protocol Note", EXPFILL }},
1571 { &ei_lua_proto_deprecated_warn, { "_ws.lua.proto.warning", PI_DEPRECATED, PI_WARN ,"Protocol Warning", EXPFILL }},
1572 { &ei_lua_proto_deprecated_error, { "_ws.lua.proto.error", PI_DEPRECATED, PI_ERROR ,"Protocol Error", EXPFILL }},
1574 { &ei_lua_proto_receive_comment, { "_ws.lua.proto.comment", PI_RECEIVE, PI_COMMENT ,"Protocol Comment", EXPFILL }},
1575 { &ei_lua_proto_receive_chat, { "_ws.lua.proto.chat", PI_RECEIVE, PI_CHAT ,"Protocol Chat", EXPFILL }},
1576 { &ei_lua_proto_receive_note, { "_ws.lua.proto.note", PI_RECEIVE, PI_NOTE ,"Protocol Note", EXPFILL }},
1577 { &ei_lua_proto_receive_warn, { "_ws.lua.proto.warning", PI_RECEIVE, PI_WARN ,"Protocol Warning", EXPFILL }},
1578 { &ei_lua_proto_receive_error, { "_ws.lua.proto.error", PI_RECEIVE, PI_ERROR ,"Protocol Error", EXPFILL }},
1580 { &ei_lua_proto_interface_comment, { "_ws.lua.proto.comment", PI_INTERFACE, PI_COMMENT ,"Protocol Comment", EXPFILL }},
1581 { &ei_lua_proto_interface_chat, { "_ws.lua.proto.chat", PI_INTERFACE, PI_CHAT ,"Protocol Chat", EXPFILL }},
1582 { &ei_lua_proto_interface_note, { "_ws.lua.proto.note", PI_INTERFACE, PI_NOTE ,"Protocol Note", EXPFILL }},
1583 { &ei_lua_proto_interface_warn, { "_ws.lua.proto.warning", PI_INTERFACE, PI_WARN ,"Protocol Warning", EXPFILL }},
1584 { &ei_lua_proto_interface_error, { "_ws.lua.proto.error", PI_INTERFACE, PI_ERROR ,"Protocol Error", EXPFILL }},
1586 /* this one is for reporting errors executing Lua code */
1587 { &ei_lua_error, { "_ws.lua.error", PI_DISSECTOR_BUG, PI_ERROR ,"Lua Error", EXPFILL }},
1590 if (first_time) {
1591 ws_lua_ei = ei;
1592 ws_lua_ei_len = array_length(ei);
1595 if (!L) {
1596 L = lua_newstate(wslua_allocf, NULL);
1599 WSLUA_INIT(L);
1601 if (first_time) {
1602 proto_lua = proto_register_protocol("Lua Dissection", "Lua Dissection", "_ws.lua");
1603 proto_register_field_array(proto_lua, hf, array_length(hf));
1604 proto_register_subtree_array(ett, array_length(ett));
1605 expert_lua = expert_register_protocol(proto_lua);
1606 expert_register_field_array(expert_lua, ei, array_length(ei));
1609 lua_atpanic(L,wslua_panic);
1612 * The init_routines table (accessible by the user).
1614 * For a table a, a.init is syntactic sugar for a["init"], and
1616 * function t.a.b.c.f () body end
1618 * is syntactic sugar for
1620 * t.a.b.c.f = function () body end
1622 * so
1624 * function proto.init () body end
1626 * means
1628 * proto["init"] = function () body end
1630 * and the Proto class has an "init" method, with Proto_set_init()
1631 * being the setter for that method; that routine adds the Lua
1632 * function passed to it as a Lua argument to the WSLUA_INIT_ROUTINES
1633 * table - i.e., "init_routines".
1635 lua_newtable (L);
1636 lua_setglobal(L, WSLUA_INIT_ROUTINES);
1638 /* the dissectors table goes in the registry (not accessible) */
1639 lua_newtable (L);
1640 lua_dissectors_table_ref = luaL_ref(L, LUA_REGISTRYINDEX);
1641 lua_newtable (L);
1642 lua_heur_dissectors_table_ref = luaL_ref(L, LUA_REGISTRYINDEX);
1644 /* the preferences apply_cb table (accessible by the user) */
1645 lua_newtable (L);
1646 lua_setglobal(L, WSLUA_PREFS_CHANGED);
1648 /* set running_superuser variable to its proper value */
1649 WSLUA_REG_GLOBAL_BOOL(L,"running_superuser",started_with_special_privs());
1651 /* special constant used by PDU reassembly handling */
1652 /* see dissect_lua() for notes */
1653 WSLUA_REG_GLOBAL_INTEGER(L,"DESEGMENT_ONE_MORE_SEGMENT",DESEGMENT_ONE_MORE_SEGMENT);
1655 /* the possible values for Pinfo's p2p_dir attribute */
1656 WSLUA_REG_GLOBAL_INTEGER(L,"P2P_DIR_UNKNOWN",-1);
1657 WSLUA_REG_GLOBAL_INTEGER(L,"P2P_DIR_SENT",0);
1658 WSLUA_REG_GLOBAL_INTEGER(L,"P2P_DIR_RECV",1);
1660 wslua_add_introspection();
1662 wslua_add_useful_constants();
1664 wslua_add_deprecated();
1666 // Register Lua's console menu (in the GUI)
1667 if (first_time) {
1668 funnel_register_console_menu("Lua",
1669 lua_funnel_console_eval,
1670 lua_funnel_console_open,
1671 lua_funnel_console_close,
1672 NULL, NULL);
1674 else if (wslua_gui_print_func_ptr) {
1675 // If we we have an open GUI console dialog re-register the global "print to console" function
1676 lua_funnel_console_open(wslua_gui_print_func_ptr, wslua_gui_print_data_ptr, NULL);
1679 /* load system's init.lua */
1680 #if 0
1681 /* wslua_dofile / wslua_get_actual_filename look in the datafile dir.
1682 * Should we add that to the path for require() as well, for consistency?
1684 prepend_path(get_datafile_dir());
1685 #endif
1686 /* Add the global plugins path for require */
1687 prepend_path(get_plugins_dir());
1688 filename = g_build_filename(get_plugins_dir(), "init.lua", (char *)NULL);
1689 if (file_exists(filename)) {
1690 ws_debug("Loading init.lua file: %s", filename);
1691 lua_load_internal_script(filename);
1693 g_free(filename);
1695 /* load user's init.lua */
1696 /* if we are indeed superuser run user scripts only if told to do so */
1697 if (!started_with_special_privs() || run_anyway) {
1698 #if 0
1699 /* wslua_dofile / wslua_get_actual_filename look in the personal configuration
1700 * directory. Should we add that to the path for require() as well, for consistency?
1702 profile_dir = get_profile_dir(NULL, false);
1703 prepend_path(profile_dir);
1704 g_free(profile_dir);
1705 #endif
1706 /* Add the personal plugins path(s) for require() */
1707 char *old_path = get_persconffile_path("plugins", false);
1708 if (strcmp(get_plugins_pers_dir(), old_path) != 0) {
1709 prepend_path(old_path);
1711 g_free(old_path);
1712 prepend_path(get_plugins_pers_dir());
1713 filename = g_build_filename(get_plugins_pers_dir(), "init.lua", (char *)NULL);
1714 if (file_exists(filename)) {
1715 ws_debug("Loading init.lua file: %s", filename);
1716 lua_load_internal_script(filename);
1718 g_free(filename);
1720 /* For backward compatibility also load it from the configuration directory. */
1721 filename = get_persconffile_path("init.lua", false);
1722 if (file_exists(filename)) {
1723 ws_message("Loading init.lua file from deprecated path: %s", filename);
1724 lua_load_internal_script(filename);
1726 g_free(filename);
1729 filename = NULL;
1731 /* check if lua is to be disabled */
1732 lua_getglobal(L, "disable_lua"); // 2.6 and earlier, deprecated
1733 if (lua_isboolean(L,-1)) {
1734 enable_lua = ! lua_toboolean(L,-1);
1736 lua_pop(L,1); /* pop the getglobal result */
1738 lua_getglobal(L, "enable_lua"); // 3.0 and later
1739 if (lua_isboolean(L,-1)) {
1740 enable_lua = lua_toboolean(L,-1);
1742 lua_pop(L,1); /* pop the getglobal result */
1744 if (!enable_lua) {
1745 /* disable lua */
1746 lua_close(L);
1747 L = NULL;
1748 first_time = false;
1749 return;
1752 /* load global scripts */
1753 lua_load_global_plugins(cb, client_data, false);
1755 /* check whether we should run other scripts even if running superuser */
1756 lua_getglobal(L,"run_user_scripts_when_superuser");
1758 if (lua_isboolean(L,-1) && lua_toboolean(L,-1)) {
1759 run_anyway = true;
1761 lua_pop(L,1); /* pop the getglobal result */
1763 /* if we are indeed superuser run user scripts only if told to do so */
1764 if (!started_with_special_privs() || run_anyway) {
1766 /* load user scripts */
1767 lua_load_pers_plugins(cb, client_data, false);
1769 /* load scripts from command line */
1770 for (i = 0; i < ex_opt_count("lua_script"); i++) {
1771 const char *script_filename = ex_opt_get_nth("lua_script", i);
1772 char* dirname = g_strdup(script_filename);
1773 char* dname = get_dirname(dirname);
1774 /* Add the command line script directory to the path (unless it's
1775 * the current directory, which should already be in the path by
1776 * default).
1777 * XXX - Should we remove it after we're done with this script? */
1778 if (dname)
1779 prepend_path(dname);
1781 if (cb)
1782 (*cb)(RA_LUA_PLUGINS, get_basename(script_filename), client_data);
1784 lua_load_plugin_script(ws_dir_get_name(script_filename),
1785 script_filename,
1786 dname ? dname : "",
1787 file_count);
1788 file_count++;
1789 g_free(dirname);
1793 if (first_time) {
1794 /* at this point we're set up so register the init and cleanup routines */
1795 register_init_routine(wslua_init_routine);
1796 register_cleanup_routine(wslua_cleanup_routine);
1800 * after this point it is too late to register a menu
1801 * disable the function to avoid weirdness
1803 lua_pushcfunction(L, wslua_not_register_menu);
1804 lua_setglobal(L, "register_menu");
1806 /* set up some essential globals */
1807 lua_pinfo = NULL;
1808 lua_tree = NULL;
1809 lua_tvb = NULL;
1811 /* Unfortunately, by waiting to register the hfi and ei now, Lua
1812 * can't figure out which file had the error and provide a traceback,
1813 * so no special error handler.
1815 lua_pushcfunction(L, Proto_commit);
1816 error = lua_pcall(L, 0, 0, 0);
1817 if (error) {
1818 switch (error) {
1819 case LUA_ERRRUN:
1820 report_failure("Lua: Error initializing protocols:\n%s", lua_tostring(L, -1));
1821 break;
1822 case LUA_ERRMEM:
1823 report_failure("Lua: Error initializing protocols: out of memory");
1824 break;
1825 case LUA_ERRERR:
1826 report_failure("Lua: Error initializing protocols: error while retrieving error message");
1827 break;
1828 default:
1829 report_failure("Lua: Error initializing protocols: unknown error %d", error);
1830 break;
1834 first_time = false;
1837 void wslua_early_cleanup(void) {
1838 wslua_deregister_protocols(L);
1841 void wslua_reload_plugins (register_cb cb, void *client_data) {
1842 const funnel_ops_t* ops = funnel_get_funnel_ops();
1844 if (cb)
1845 (*cb)(RA_LUA_DEREGISTER, NULL, client_data);
1847 if (ops->close_dialogs)
1848 ops->close_dialogs();
1850 wslua_deregister_heur_dissectors(L);
1851 wslua_deregister_protocols(L);
1852 wslua_deregister_dissector_tables(L);
1853 wslua_deregister_listeners(L);
1854 wslua_deregister_fields(L);
1855 wslua_deregister_filehandlers(L);
1856 wslua_deregister_menus();
1857 wslua_clear_plugin_list();
1859 wslua_cleanup();
1860 wslua_init(cb, client_data); /* reinitialize */
1863 void wslua_cleanup(void) {
1864 /* cleanup lua */
1865 if (L) {
1866 lua_close(L);
1867 L = NULL;
1869 init_routine_initialized = false;
1872 lua_State* wslua_state(void) { return L; }
1875 * Editor modelines - https://www.wireshark.org/tools/modelines.html
1877 * Local variables:
1878 * c-basic-offset: 4
1879 * tab-width: 8
1880 * indent-tabs-mode: nil
1881 * End:
1883 * vi: set shiftwidth=4 tabstop=8 expandtab:
1884 * :indentSize=4:tabSize=8:noTabs=true: