1 /*
2 * init_wslua.c
3 *
4 * Wireshark's interface to the Lua Programming Language
5 *
6 * (c) 2006, Luis E. Garcia Ontanon <luis@ontanon.org>
7 *
8 * Wireshark - Network traffic analyzer
9 * By Gerald Combs <gerald@wireshark.org>
10 * Copyright 1998 Gerald Combs
11 *
12 * SPDX-License-Identifier: GPL-2.0-or-later
13 */
14
15 #include "config.h"
16
17 #include "wslua.h"
18 #include "init_wslua.h"
19 #include <epan/dissectors/packet-frame.h>
20 #include <math.h>
21 #include <stdio.h>
22 #include <epan/expert.h>
23 #include <epan/ex-opt.h>
24 #include <wsutil/privileges.h>
25 #include <wsutil/file_util.h>
26 #include <wsutil/wslog.h>
27
28 /* linked list of Lua plugins */
29 typedef struct _wslua_plugin {
30 gchar *name; /**< plugin name */
31 gchar *version; /**< plugin version */
32 gchar *filename; /**< plugin filename */
33 struct _wslua_plugin *next;
34 } wslua_plugin;
35
36 static wslua_plugin *wslua_plugin_list = NULL;
37
38 static lua_State* L = NULL;
39
40 /* XXX: global variables? Really?? Yuck. These could be done differently,
41 using the Lua registry */
42 packet_info* lua_pinfo;
43 struct _wslua_treeitem* lua_tree;
44 tvbuff_t* lua_tvb;
45 wslua_logger_t wslua_logger;
46 int lua_dissectors_table_ref = LUA_NOREF;
47 int lua_heur_dissectors_table_ref = LUA_NOREF;
48
49 static int proto_lua = -1;
50
51 static int hf_wslua_fake = -1;
52 static int hf_wslua_text = -1;
53
54 static expert_field ei_lua_error = EI_INIT;
55
56 static expert_field ei_lua_proto_checksum_comment = EI_INIT;
57 static expert_field ei_lua_proto_checksum_chat = EI_INIT;
58 static expert_field ei_lua_proto_checksum_note = EI_INIT;
59 static expert_field ei_lua_proto_checksum_warn = EI_INIT;
60 static expert_field ei_lua_proto_checksum_error = EI_INIT;
61
62 static expert_field ei_lua_proto_sequence_comment = EI_INIT;
63 static expert_field ei_lua_proto_sequence_chat = EI_INIT;
64 static expert_field ei_lua_proto_sequence_note = EI_INIT;
65 static expert_field ei_lua_proto_sequence_warn = EI_INIT;
66 static expert_field ei_lua_proto_sequence_error = EI_INIT;
67
68 static expert_field ei_lua_proto_response_comment = EI_INIT;
69 static expert_field ei_lua_proto_response_chat = EI_INIT;
70 static expert_field ei_lua_proto_response_note = EI_INIT;
71 static expert_field ei_lua_proto_response_warn = EI_INIT;
72 static expert_field ei_lua_proto_response_error = EI_INIT;
73
74 static expert_field ei_lua_proto_request_comment = EI_INIT;
75 static expert_field ei_lua_proto_request_chat = EI_INIT;
76 static expert_field ei_lua_proto_request_note = EI_INIT;
77 static expert_field ei_lua_proto_request_warn = EI_INIT;
78 static expert_field ei_lua_proto_request_error = EI_INIT;
79
80 static expert_field ei_lua_proto_undecoded_comment = EI_INIT;
81 static expert_field ei_lua_proto_undecoded_chat = EI_INIT;
82 static expert_field ei_lua_proto_undecoded_note = EI_INIT;
83 static expert_field ei_lua_proto_undecoded_warn = EI_INIT;
84 static expert_field ei_lua_proto_undecoded_error = EI_INIT;
85
86 static expert_field ei_lua_proto_reassemble_comment = EI_INIT;
87 static expert_field ei_lua_proto_reassemble_chat = EI_INIT;
88 static expert_field ei_lua_proto_reassemble_note = EI_INIT;
89 static expert_field ei_lua_proto_reassemble_warn = EI_INIT;
90 static expert_field ei_lua_proto_reassemble_error = EI_INIT;
91
92 static expert_field ei_lua_proto_malformed_comment = EI_INIT;
93 static expert_field ei_lua_proto_malformed_chat = EI_INIT;
94 static expert_field ei_lua_proto_malformed_note = EI_INIT;
95 static expert_field ei_lua_proto_malformed_warn = EI_INIT;
96 static expert_field ei_lua_proto_malformed_error = EI_INIT;
97
98 static expert_field ei_lua_proto_debug_comment = EI_INIT;
99 static expert_field ei_lua_proto_debug_chat = EI_INIT;
100 static expert_field ei_lua_proto_debug_note = EI_INIT;
101 static expert_field ei_lua_proto_debug_warn = EI_INIT;
102 static expert_field ei_lua_proto_debug_error = EI_INIT;
103
104 static expert_field ei_lua_proto_protocol_comment = EI_INIT;
105 static expert_field ei_lua_proto_protocol_chat = EI_INIT;
106 static expert_field ei_lua_proto_protocol_note = EI_INIT;
107 static expert_field ei_lua_proto_protocol_warn = EI_INIT;
108 static expert_field ei_lua_proto_protocol_error = EI_INIT;
109
110 static expert_field ei_lua_proto_security_comment = EI_INIT;
111 static expert_field ei_lua_proto_security_chat = EI_INIT;
112 static expert_field ei_lua_proto_security_note = EI_INIT;
113 static expert_field ei_lua_proto_security_warn = EI_INIT;
114 static expert_field ei_lua_proto_security_error = EI_INIT;
115
116 static expert_field ei_lua_proto_comments_comment = EI_INIT;
117 static expert_field ei_lua_proto_comments_chat = EI_INIT;
118 static expert_field ei_lua_proto_comments_note = EI_INIT;
119 static expert_field ei_lua_proto_comments_warn = EI_INIT;
120 static expert_field ei_lua_proto_comments_error = EI_INIT;
121
122 static expert_field ei_lua_proto_decryption_comment = EI_INIT;
123 static expert_field ei_lua_proto_decryption_chat = EI_INIT;
124 static expert_field ei_lua_proto_decryption_note = EI_INIT;
125 static expert_field ei_lua_proto_decryption_warn = EI_INIT;
126 static expert_field ei_lua_proto_decryption_error = EI_INIT;
127
128 static expert_field ei_lua_proto_assumption_comment = EI_INIT;
129 static expert_field ei_lua_proto_assumption_chat = EI_INIT;
130 static expert_field ei_lua_proto_assumption_note = EI_INIT;
131 static expert_field ei_lua_proto_assumption_warn = EI_INIT;
132 static expert_field ei_lua_proto_assumption_error = EI_INIT;
133
134 static expert_field ei_lua_proto_deprecated_comment = EI_INIT;
135 static expert_field ei_lua_proto_deprecated_chat = EI_INIT;
136 static expert_field ei_lua_proto_deprecated_note = EI_INIT;
137 static expert_field ei_lua_proto_deprecated_warn = EI_INIT;
138 static expert_field ei_lua_proto_deprecated_error = EI_INIT;
139
140 static gboolean
lua_pinfo_end(wmem_allocator_t * allocator _U_,wmem_cb_event_t event _U_,void * user_data _U_)141 lua_pinfo_end(wmem_allocator_t *allocator _U_, wmem_cb_event_t event _U_,
142 void *user_data _U_)
143 {
144 clear_outstanding_Tvb();
145 clear_outstanding_TvbRange();
146 clear_outstanding_Pinfo();
147 clear_outstanding_Column();
148 clear_outstanding_Columns();
149 clear_outstanding_PrivateTable();
150 clear_outstanding_TreeItem();
151 clear_outstanding_FieldInfo();
152 clear_outstanding_FuncSavers();
153
154 /* keep invoking this callback later? */
155 return FALSE;
156 }
157
wslua_not_register_menu(lua_State * LS)158 static int wslua_not_register_menu(lua_State* LS) {
159 luaL_error(LS,"too late to register a menu");
160 return 0;
161 }
162
163 /* a getter for wslua_tree.c's TreeItem_add_item_any() to use */
get_hf_wslua_text(void)164 int get_hf_wslua_text(void) {
165 return hf_wslua_text;
166 }
167
dissect_lua(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)168 int dissect_lua(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, void* data _U_) {
169 int consumed_bytes = tvb_captured_length(tvb);
170 tvbuff_t *saved_lua_tvb = lua_tvb;
171 packet_info *saved_lua_pinfo = lua_pinfo;
172 struct _wslua_treeitem *saved_lua_tree = lua_tree;
173 lua_pinfo = pinfo;
174 lua_tvb = tvb;
175
176 /*
177 * almost equivalent to Lua:
178 * dissectors[current_proto](tvb,pinfo,tree)
179 */
180
181 lua_settop(L,0);
182
183 lua_rawgeti(L, LUA_REGISTRYINDEX, lua_dissectors_table_ref);
184
185 lua_pushstring(L, pinfo->current_proto);
186 lua_gettable(L, -2);
187
188 lua_remove(L,1);
189
190
191 if (lua_isfunction(L,1)) {
192
193 push_Tvb(L,tvb);
194 push_Pinfo(L,pinfo);
195 lua_tree = push_TreeItem(L, tree, proto_tree_add_item(tree, hf_wslua_fake, tvb, 0, 0, ENC_NA));
196 proto_item_set_hidden(lua_tree->item);
197
198 if ( lua_pcall(L,3,1,0) ) {
199 proto_tree_add_expert_format(tree, pinfo, &ei_lua_error, tvb, 0, 0, "Lua Error: %s", lua_tostring(L,-1));
200 } else {
201
202 /* if the Lua dissector reported the consumed bytes, pass it to our caller */
203 if (lua_isnumber(L, -1)) {
204 /* we got the consumed bytes or the missing bytes as a negative number */
205 consumed_bytes = wslua_togint(L, -1);
206 lua_pop(L, 1);
207 }
208 }
209
210 } else {
211 proto_tree_add_expert_format(tree, pinfo, &ei_lua_error, tvb, 0, 0,
212 "Lua Error: did not find the %s dissector in the dissectors table", pinfo->current_proto);
213 }
214
215 wmem_register_callback(pinfo->pool, lua_pinfo_end, NULL);
216
217 lua_pinfo = saved_lua_pinfo;
218 lua_tree = saved_lua_tree;
219 lua_tvb = saved_lua_tvb;
220
221 return consumed_bytes;
222
223 }
224
225 /** Type of a heuristic dissector, used in heur_dissector_add().
226 *
227 * @param tvb the tvbuff with the (remaining) packet data
228 * @param pinfo the packet info of this packet (additional info)
229 * @param tree the protocol tree to be build or NULL
230 * @return TRUE if the packet was recognized by the sub-dissector (stop dissection here)
231 */
heur_dissect_lua(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)232 gboolean heur_dissect_lua(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, void* data _U_) {
233 gboolean result = FALSE;
234 tvbuff_t *saved_lua_tvb = lua_tvb;
235 packet_info *saved_lua_pinfo = lua_pinfo;
236 struct _wslua_treeitem *saved_lua_tree = lua_tree;
237 lua_tvb = tvb;
238 lua_pinfo = pinfo;
239
240 ws_assert(tvb && pinfo);
241
242 if (!pinfo->heur_list_name || !pinfo->current_proto) {
243 proto_tree_add_expert_format(tree, pinfo, &ei_lua_error, tvb, 0, 0,
244 "internal error in heur_dissect_lua: NULL list name or current proto");
245 return FALSE;
246 }
247
248 /* heuristic functions are stored in a table in the registry; the registry has a
249 * table at reference lua_heur_dissectors_table_ref, and that table has keys for
250 * the heuristic listname (e.g., "udp", "tcp", etc.), and that key's value is a
251 * table of keys of the Proto->name, and their value is the function.
252 * So it's like registry[table_ref][heur_list_name][proto_name] = func
253 */
254
255 lua_settop(L,0);
256
257 /* get the table of all lua heuristic dissector lists */
258 lua_rawgeti(L, LUA_REGISTRYINDEX, lua_heur_dissectors_table_ref);
259
260 /* get the table inside that, for the lua heuristic dissectors of the requested heur list */
261 if (!wslua_get_table(L, -1, pinfo->heur_list_name)) {
262 /* this shouldn't happen */
263 lua_settop(L,0);
264 proto_tree_add_expert_format(tree, pinfo, &ei_lua_error, tvb, 0, 0,
265 "internal error in heur_dissect_lua: no %s heur list table", pinfo->heur_list_name);
266 return FALSE;
267 }
268
269 /* get the table inside that, for the specific lua heuristic dissector */
270 if (!wslua_get_field(L,-1,pinfo->current_proto)) {
271 /* this shouldn't happen */
272 lua_settop(L,0);
273 proto_tree_add_expert_format(tree, pinfo, &ei_lua_error, tvb, 0, 0,
274 "internal error in heur_dissect_lua: no %s heuristic dissector for list %s",
275 pinfo->current_proto, pinfo->heur_list_name);
276 return FALSE;
277 }
278
279 /* remove the table of all lists (the one in the registry) */
280 lua_remove(L,1);
281 /* remove the heur_list_name heur list table */
282 lua_remove(L,1);
283
284 if (!lua_isfunction(L,-1)) {
285 /* this shouldn't happen */
286 lua_settop(L,0);
287 proto_tree_add_expert_format(tree, pinfo, &ei_lua_error, tvb, 0, 0,
288 "internal error in heur_dissect_lua: %s heuristic dissector is not a function", pinfo->current_proto);
289 return FALSE;
290 }
291
292 push_Tvb(L,tvb);
293 push_Pinfo(L,pinfo);
294 lua_tree = push_TreeItem(L, tree, proto_tree_add_item(tree, hf_wslua_fake, tvb, 0, 0, ENC_NA));
295 proto_item_set_hidden(lua_tree->item);
296
297 if ( lua_pcall(L,3,1,0) ) {
298 proto_tree_add_expert_format(tree, pinfo, &ei_lua_error, tvb, 0, 0,
299 "Lua Error: error calling %s heuristic dissector: %s", pinfo->current_proto, lua_tostring(L,-1));
300 lua_settop(L,0);
301 } else {
302 if (lua_isboolean(L, -1) || lua_isnil(L, -1)) {
303 result = lua_toboolean(L, -1);
304 } else if (lua_type(L, -1) == LUA_TNUMBER) {
305 result = lua_tointeger(L,-1) != 0 ? TRUE : FALSE;
306 } else {
307 proto_tree_add_expert_format(tree, pinfo, &ei_lua_error, tvb, 0, 0,
308 "Lua Error: invalid return value from Lua %s heuristic dissector", pinfo->current_proto);
309 }
310 lua_pop(L, 1);
311 }
312
313 wmem_register_callback(pinfo->pool, lua_pinfo_end, NULL);
314
315 lua_pinfo = saved_lua_pinfo;
316 lua_tree = saved_lua_tree;
317 lua_tvb = saved_lua_tvb;
318
319 return result;
320 }
321
iter_table_and_call(lua_State * LS,const gchar * table_name,lua_CFunction error_handler)322 static void iter_table_and_call(lua_State* LS, const gchar* table_name, lua_CFunction error_handler) {
323 lua_settop(LS,0);
324
325 lua_pushcfunction(LS,error_handler);
326 lua_getglobal(LS, table_name);
327
328 if (!lua_istable(LS, 2)) {
329 report_failure("Lua: either `%s' does not exist or it is not a table!\n",table_name);
330 lua_close(LS);
331 L = NULL;
332 return;
333 }
334
335 lua_pushnil(LS);
336
337 while (lua_next(LS, 2)) {
338 const gchar* name = lua_tostring(L,-2);
339
340 if (lua_isfunction(LS,-1)) {
341
342 if ( lua_pcall(LS,0,0,1) ) {
343 lua_pop(LS,1);
344 }
345
346 } else {
347 report_failure("Lua: Something not a function got its way into the %s.%s",table_name,name);
348 lua_close(LS);
349 L = NULL;
350 return;
351 }
352 }
353
354 lua_settop(LS,0);
355 }
356
357
init_error_handler(lua_State * LS)358 static int init_error_handler(lua_State* LS) {
359 const gchar* error = lua_tostring(LS,1);
360 report_failure("Lua: Error during execution of initialization:\n %s",error);
361 return 0;
362 }
363
364
365 static gboolean init_routine_initialized = FALSE;
wslua_init_routine(void)366 static void wslua_init_routine(void) {
367
368 if ( ! init_routine_initialized ) {
369 /*
370 * This must be done only once during the entire life of
371 * tshark/wireshark, because it must be done only once per the life of
372 * the Lua state/engine, so we guard this with the boolean above;
373 * otherwise it would occur every time a file is opened (every time
374 * epan_new() is called).
375 *
376 * If we ever allow the Lua state to be restarted, or to have multiple
377 * Lua states, we'll need to change this.
378 */
379 lua_prime_all_fields(NULL);
380 init_routine_initialized = TRUE;
381 }
382
383 if (L) {
384 iter_table_and_call(L, WSLUA_INIT_ROUTINES,init_error_handler);
385 }
386
387 }
388
wslua_cleanup_routine(void)389 static void wslua_cleanup_routine(void) {
390 if (L) {
391 iter_table_and_call(L, WSLUA_INIT_ROUTINES,init_error_handler);
392 }
393 }
394
prefs_changed_error_handler(lua_State * LS)395 static int prefs_changed_error_handler(lua_State* LS) {
396 const gchar* error = lua_tostring(LS,1);
397 report_failure("Lua: Error during execution of prefs apply callback:\n %s",error);
398 return 0;
399 }
400
wslua_prefs_changed(void)401 void wslua_prefs_changed(void) {
402 if (L) {
403 iter_table_and_call(L, WSLUA_PREFS_CHANGED,prefs_changed_error_handler);
404 }
405 }
406
getF(lua_State * LS _U_,void * ud,size_t * size)407 static const char *getF(lua_State *LS _U_, void *ud, size_t *size)
408 {
409 FILE *f=(FILE *)ud;
410 static char buff[512];
411 if (feof(f)) return NULL;
412 *size=fread(buff,1,sizeof(buff),f);
413 return (*size>0) ? buff : NULL;
414 }
415
error_handler_with_callback(lua_State * LS)416 static int error_handler_with_callback(lua_State *LS) {
417 #if LUA_VERSION_NUM >= 502
418 const char *msg = lua_tostring(LS, 1);
419 luaL_traceback(LS, LS, msg, 1); /* push message with traceback. */
420 lua_remove(LS, -2); /* remove original msg */
421 #else
422 /* Return error message, unmodified */
423 (void)LS;
424 #endif
425 return 1;
426 }
427
wslua_add_plugin(const gchar * name,const gchar * version,const gchar * filename)428 static void wslua_add_plugin(const gchar *name, const gchar *version, const gchar *filename)
429 {
430 wslua_plugin *new_plug, *lua_plug;
431
432 lua_plug = wslua_plugin_list;
433 new_plug = g_new(wslua_plugin, 1);
434
435 if (!lua_plug) { /* the list is empty */
436 wslua_plugin_list = new_plug;
437 } else {
438 while (lua_plug->next != NULL) {
439 lua_plug = lua_plug->next;
440 }
441 lua_plug->next = new_plug;
442 }
443
444 new_plug->name = g_strdup(name);
445 new_plug->version = g_strdup(version);
446 new_plug->filename = g_strdup(filename);
447 new_plug->next = NULL;
448 }
449
wslua_clear_plugin_list(void)450 static void wslua_clear_plugin_list(void)
451 {
452 wslua_plugin *lua_plug;
453
454 while (wslua_plugin_list) {
455 lua_plug = wslua_plugin_list;
456 wslua_plugin_list = wslua_plugin_list->next;
457 g_free (lua_plug->name);
458 g_free (lua_plug->version);
459 g_free (lua_plug->filename);
460 g_free (lua_plug);
461 }
462 }
463
lua_script_push_args(const int script_num)464 static int lua_script_push_args(const int script_num) {
465 gchar* argname = g_strdup_printf("lua_script%d", script_num);
466 const gchar* argvalue = NULL;
467 int i, count = ex_opt_count(argname);
468
469 for (i = 0; i < count; i++) {
470 argvalue = ex_opt_get_nth(argname, i);
471 lua_pushstring(L,argvalue);
472 }
473
474 g_free(argname);
475 return count;
476 }
477
478 #define FILE_NAME_KEY "__FILE__"
479 #define DIR_NAME_KEY "__DIR__"
480 #define DIR_SEP_NAME_KEY "__DIR_SEPARATOR__"
481 /* assumes a loaded chunk's function is on top of stack */
set_file_environment(const gchar * filename,const gchar * dirname)482 static void set_file_environment(const gchar* filename, const gchar* dirname) {
483 const char* path;
484
485 lua_newtable(L); /* environment for script (index 3) */
486
487 lua_pushstring(L, filename); /* tell the script about its filename */
488 lua_setfield(L, -2, FILE_NAME_KEY); /* make it accessible at __FILE__ */
489
490 lua_pushstring(L, dirname); /* tell the script about its dirname */
491 lua_setfield(L, -2, DIR_NAME_KEY); /* make it accessible at __DIR__ */
492
493 lua_pushstring(L, G_DIR_SEPARATOR_S); /* tell the script the directory separator */
494 lua_setfield(L, -2, DIR_SEP_NAME_KEY); /* make it accessible at __DIR__ */
495
496 lua_newtable(L); /* new metatable */
497
498 #if LUA_VERSION_NUM >= 502
499 lua_pushglobaltable(L);
500 #else
501 lua_pushvalue(L, LUA_GLOBALSINDEX);
502 #endif
503 /* prepend the directory name to _G.package.path */
504 lua_getfield(L, -1, "package"); /* get the package table from the global table */
505 lua_getfield(L, -1, "path"); /* get the path field from the package table */
506 path = luaL_checkstring(L, -1); /* get the path string */
507 lua_pop(L, 1); /* pop the path string */
508 /* prepend the various paths */
509 lua_pushfstring(L, "%s" G_DIR_SEPARATOR_S "?.lua;%s" G_DIR_SEPARATOR_S "?.lua;%s" G_DIR_SEPARATOR_S "?.lua;%s",
510 dirname, get_plugins_pers_dir(), get_plugins_dir(), path);
511 lua_setfield(L, -2, "path"); /* set the new string to be the path field of the package table */
512 lua_setfield(L, -2, "package"); /* set the package table to be the package field of the global */
513
514 lua_setfield(L, -2, "__index"); /* make metatable's __index point to global table */
515
516 lua_setmetatable(L, -2); /* pop metatable, set it as metatable of environment */
517
518 #if LUA_VERSION_NUM >= 502
519 lua_setupvalue(L, -2, 1); /* pop environment and assign it to upvalue 1 */
520 #else
521 lua_setfenv(L, -2); /* pop environment and set it as the func's environment */
522 #endif
523 }
524
525
526 /* If file_count > 0 then it's a command-line-added user script, and the count
527 * represents which user script it is (first=1, second=2, etc.).
528 * If dirname != NULL, then it's a user script and the dirname will get put in a file environment
529 * If dirname == NULL then it's a wireshark script and no file environment is created
530 */
lua_load_script(const gchar * filename,const gchar * dirname,const int file_count)531 static gboolean lua_load_script(const gchar* filename, const gchar* dirname, const int file_count) {
532 FILE* file;
533 int error;
534 int numargs = 0;
535
536 if (! ( file = ws_fopen(filename,"r")) ) {
537 report_open_failure(filename,errno,FALSE);
538 return FALSE;
539 }
540
541 lua_settop(L,0);
542
543 lua_pushcfunction(L, error_handler_with_callback);
544 /* The source argument should start with '@' to indicate a file. */
545 lua_pushfstring(L, "@%s", filename);
546
547 #if LUA_VERSION_NUM >= 502
548 error = lua_load(L, getF, file, lua_tostring(L, -1), NULL);
549 #else
550 error = lua_load(L, getF, file, lua_tostring(L, -1));
551 #endif
552
553 switch (error) {
554 case 0: /* LUA_OK */
555 if (dirname) {
556 set_file_environment(filename, dirname);
557 }
558 if (file_count > 0) {
559 numargs = lua_script_push_args(file_count);
560 }
561 error = lua_pcall(L, numargs, 0, 1);
562 if (error) {
563 switch (error) {
564 case LUA_ERRRUN:
565 report_failure("Lua: Error during loading:\n%s", lua_tostring(L, -1));
566 break;
567 case LUA_ERRMEM:
568 report_failure("Lua: Error during loading: out of memory");
569 break;
570 case LUA_ERRERR:
571 report_failure("Lua: Error during loading: error while retrieving error message");
572 break;
573 default:
574 report_failure("Lua: Error during loading: unknown error %d", error);
575 break;
576 }
577 }
578 break;
579
580 case LUA_ERRSYNTAX:
581 report_failure("Lua: syntax error: %s", lua_tostring(L, -1));
582 break;
583
584 case LUA_ERRMEM:
585 report_failure("Lua: memory allocation error during precompilation of %s", filename);
586 break;
587
588 default:
589 report_failure("Lua: unknown error during precompilation of %s: %d", filename, error);
590 break;
591 }
592 fclose(file);
593 lua_pop(L, 2); /* pop the filename and error handler */
594 return error == 0;
595 }
596
597 /* This one is used to load the init.lua scripts, or anything else
598 * that shouldn't really be considered a real plugin.
599 */
lua_load_internal_script(const gchar * filename)600 static gboolean lua_load_internal_script(const gchar* filename) {
601 return lua_load_script(filename, NULL, 0);
602 }
603
604 /* This one is used to load plugins: either from the plugin directories,
605 * or from the command line.
606 */
lua_load_plugin_script(const gchar * name,const gchar * filename,const gchar * dirname,const int file_count)607 static gboolean lua_load_plugin_script(const gchar* name,
608 const gchar* filename,
609 const gchar* dirname,
610 const int file_count)
611 {
612 if (lua_load_script(filename, dirname, file_count)) {
613 wslua_add_plugin(name, get_current_plugin_version(), filename);
614 clear_current_plugin_version();
615 return TRUE;
616 }
617 return FALSE;
618 }
619
620
basic_logger(const gchar * log_domain,enum ws_log_level log_level,const gchar * message,gpointer user_data _U_)621 static void basic_logger(const gchar *log_domain,
622 enum ws_log_level log_level,
623 const gchar *message,
624 gpointer user_data _U_) {
625 ws_log(log_domain, log_level, "%s", message);
626 }
627
wslua_panic(lua_State * LS)628 static int wslua_panic(lua_State* LS) {
629 ws_error("LUA PANIC: %s",lua_tostring(LS,-1));
630 /** ws_error() does an abort() and thus never returns **/
631 return 0; /* keep gcc happy */
632 }
633
string_compare(gconstpointer a,gconstpointer b)634 static gint string_compare(gconstpointer a, gconstpointer b) {
635 return strcmp((const char*)a, (const char*)b);
636 }
637
lua_load_plugins(const char * dirname,register_cb cb,gpointer client_data,gboolean count_only,const gboolean is_user,GHashTable * loaded_files)638 static int lua_load_plugins(const char *dirname, register_cb cb, gpointer client_data,
639 gboolean count_only, const gboolean is_user, GHashTable *loaded_files)
640 {
641 WS_DIR *dir; /* scanned directory */
642 WS_DIRENT *file; /* current file */
643 gchar *filename, *dot;
644 const gchar *name;
645 int plugins_counter = 0;
646 GList *sorted_dirnames = NULL;
647 GList *sorted_filenames = NULL;
648 GList *l = NULL;
649
650 if ((dir = ws_dir_open(dirname, 0, NULL)) != NULL) {
651 while ((file = ws_dir_read_name(dir)) != NULL) {
652 name = ws_dir_get_name(file);
653
654 if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0)
655 continue; /* skip "." and ".." */
656
657 filename = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s", dirname, name);
658 if (test_for_directory(filename) == EISDIR) {
659 sorted_dirnames = g_list_prepend(sorted_dirnames, (gpointer)filename);
660 continue;
661 }
662
663 /* skip files starting wih . */
664 if (name[0] == '.') {
665 g_free(filename);
666 continue;
667 }
668
669 /* skip anything but files with .lua suffix */
670 dot = strrchr(name, '.');
671 if (dot == NULL || g_ascii_strcasecmp(dot+1, "lua") != 0) {
672 g_free(filename);
673 continue;
674 }
675
676 if (file_exists(filename)) {
677 sorted_filenames = g_list_prepend(sorted_filenames, (gpointer)filename);
678 }
679 else {
680 g_free(filename);
681 }
682 }
683 ws_dir_close(dir);
684 }
685
686 /* Depth first; ie, process subdirectories (in ASCIIbetical order) before files */
687 if (sorted_dirnames != NULL) {
688 sorted_dirnames = g_list_sort(sorted_dirnames, string_compare);
689 for (l = sorted_dirnames; l != NULL; l = l->next) {
690 plugins_counter += lua_load_plugins((const char *)l->data, cb, client_data, count_only, is_user, loaded_files);
691 }
692 g_list_free_full(sorted_dirnames, g_free);
693 }
694
695 /* Process files in ASCIIbetical order */
696 if (sorted_filenames != NULL) {
697 sorted_filenames = g_list_sort(sorted_filenames, string_compare);
698 for (l = sorted_filenames; l != NULL; l = l->next) {
699 filename = (gchar *)l->data;
700 name = strrchr(filename, G_DIR_SEPARATOR) + 1;
701
702 /* Check if we have already loaded this file name, if provided with a set */
703 if (loaded_files && g_hash_table_lookup_extended(loaded_files, name, NULL, NULL)) {
704 continue;
705 }
706
707 if (!count_only) {
708 if (cb)
709 (*cb)(RA_LUA_PLUGINS, name, client_data);
710 lua_load_plugin_script(name, filename, is_user ? dirname : NULL, 0);
711
712 if (loaded_files) {
713 g_hash_table_insert(loaded_files, g_strdup(name), NULL);
714 }
715 }
716 plugins_counter++;
717 }
718 g_list_free_full(sorted_filenames, g_free);
719 }
720
721 return plugins_counter;
722 }
723
lua_load_global_plugins(register_cb cb,gpointer client_data,gboolean count_only)724 static int lua_load_global_plugins(register_cb cb, gpointer client_data,
725 gboolean count_only)
726 {
727 return lua_load_plugins(get_plugins_dir(), cb, client_data, count_only, FALSE, NULL);
728 }
729
lua_load_pers_plugins(register_cb cb,gpointer client_data,gboolean count_only)730 static int lua_load_pers_plugins(register_cb cb, gpointer client_data,
731 gboolean count_only)
732 {
733 int plugins_counter = 0;
734
735 /* aux table (set) to make sure we only load each file once (by name) */
736 GHashTable *loaded_user_scripts = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
737
738 /* load user scripts */
739 plugins_counter += lua_load_plugins(get_plugins_pers_dir(), cb, client_data, count_only, TRUE, loaded_user_scripts);
740
741 /* for backward compatibility check old plugin directory */
742 char *old_path = get_persconffile_path("plugins", FALSE);
743 if (strcmp(get_plugins_pers_dir(), old_path) != 0) {
744 plugins_counter += lua_load_plugins(old_path, cb, client_data, count_only, TRUE, loaded_user_scripts);
745 }
746 g_free(old_path);
747
748 g_hash_table_destroy(loaded_user_scripts);
749
750 return plugins_counter;
751 }
752
wslua_count_plugins(void)753 int wslua_count_plugins(void) {
754 gchar* filename;
755 int plugins_counter;
756
757 /* count global scripts */
758 plugins_counter = lua_load_global_plugins(NULL, NULL, TRUE);
759
760 /* count users init.lua */
761 filename = get_persconffile_path("init.lua", FALSE);
762 if ((file_exists(filename))) {
763 plugins_counter++;
764 }
765 g_free(filename);
766
767 /* count user scripts */
768 plugins_counter += lua_load_pers_plugins(NULL, NULL, TRUE);
769
770 /* count scripts from command line */
771 plugins_counter += ex_opt_count("lua_script");
772
773 return plugins_counter;
774 }
775
wslua_plugins_get_descriptions(wslua_plugin_description_callback callback,void * user_data)776 void wslua_plugins_get_descriptions(wslua_plugin_description_callback callback, void *user_data) {
777 wslua_plugin *lua_plug;
778
779 for (lua_plug = wslua_plugin_list; lua_plug != NULL; lua_plug = lua_plug->next)
780 {
781 callback(lua_plug->name, lua_plug->version, wslua_plugin_type_name(),
782 lua_plug->filename, user_data);
783 }
784 }
785
786 static void
print_wslua_plugin_description(const char * name,const char * version,const char * description,const char * filename,void * user_data _U_)787 print_wslua_plugin_description(const char *name, const char *version,
788 const char *description, const char *filename,
789 void *user_data _U_)
790 {
791 printf("%s\t%s\t%s\t%s\n", name, version, description, filename);
792 }
793
794 void
wslua_plugins_dump_all(void)795 wslua_plugins_dump_all(void)
796 {
797 wslua_plugins_get_descriptions(print_wslua_plugin_description, NULL);
798 }
799
wslua_plugin_type_name(void)800 const char *wslua_plugin_type_name(void) {
801 return "lua script";
802 }
803
804 static ei_register_info* ws_lua_ei = NULL;
805 static int ws_lua_ei_len = 0;
806
807 expert_field*
wslua_get_expert_field(const int group,const int severity)808 wslua_get_expert_field(const int group, const int severity)
809 {
810 int i;
811 const ei_register_info *ei = ws_lua_ei;
812
813 ws_assert(ei);
814
815 for (i=0; i < ws_lua_ei_len; i++, ei++) {
816 if (ei->eiinfo.group == group && ei->eiinfo.severity == severity)
817 return ei->ids;
818 }
819
820 return &ei_lua_error;
821 }
822
823 static void *
wslua_allocf(void * ud _U_,void * ptr,size_t osize _U_,size_t nsize)824 wslua_allocf(void *ud _U_, void *ptr, size_t osize _U_, size_t nsize)
825 {
826 /* g_realloc frees ptr if nsize==0 and returns NULL (as desired).
827 * Furthermore it simplifies error handling by aborting on OOM */
828 return g_realloc(ptr, nsize);
829 }
830
wslua_init(register_cb cb,gpointer client_data)831 void wslua_init(register_cb cb, gpointer client_data) {
832 gchar* filename;
833 const funnel_ops_t* ops = funnel_get_funnel_ops();
834 gboolean enable_lua = TRUE;
835 gboolean run_anyway = FALSE;
836 expert_module_t* expert_lua;
837 int file_count = 1;
838 static gboolean first_time = TRUE;
839 int i;
840
841 static hf_register_info hf[] = {
842 { &hf_wslua_fake,
843 { "Wireshark Lua fake item", "_ws.lua.fake",
844 FT_NONE, BASE_NONE, NULL, 0x0,
845 "Fake internal item for Wireshark Lua", HFILL }},
846 { &hf_wslua_text,
847 { "Wireshark Lua text", "_ws.lua.text",
848 FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
849 };
850
851 static ei_register_info ei[] = {
852 /* the following are created so we can continue to support the TreeItem_add_expert_info()
853 function to Lua scripts. That function doesn't know what registered protocol to use,
854 so it uses the "_ws.lua" one. */
855 /* XXX: it seems to me we should not be offering PI_GROUP_MASK nor PI_SEVERITY_MASK since
856 they are not real settings, so I'm not adding them below (should they also not be exported
857 into Lua? they are right now.) */
858 /* NOTE: do not add expert entries at the top of this array - only at the bottom. This array
859 is not only used by expert.c, but also by wslua_get_expert_field() to find the appropriate
860 "dummy" entry. So this array's ordering matters. */
861 { &ei_lua_proto_checksum_comment, { "_ws.lua.proto.comment", PI_CHECKSUM, PI_COMMENT ,"Protocol Comment", EXPFILL }},
862 { &ei_lua_proto_checksum_chat, { "_ws.lua.proto.chat", PI_CHECKSUM, PI_CHAT ,"Protocol Chat", EXPFILL }},
863 { &ei_lua_proto_checksum_note, { "_ws.lua.proto.note", PI_CHECKSUM, PI_NOTE ,"Protocol Note", EXPFILL }},
864 { &ei_lua_proto_checksum_warn, { "_ws.lua.proto.warning", PI_CHECKSUM, PI_WARN ,"Protocol Warning", EXPFILL }},
865 { &ei_lua_proto_checksum_error, { "_ws.lua.proto.error", PI_CHECKSUM, PI_ERROR ,"Protocol Error", EXPFILL }},
866
867 { &ei_lua_proto_sequence_comment, { "_ws.lua.proto.comment", PI_SEQUENCE, PI_COMMENT ,"Protocol Comment", EXPFILL }},
868 { &ei_lua_proto_sequence_chat, { "_ws.lua.proto.chat", PI_SEQUENCE, PI_CHAT ,"Protocol Chat", EXPFILL }},
869 { &ei_lua_proto_sequence_note, { "_ws.lua.proto.note", PI_SEQUENCE, PI_NOTE ,"Protocol Note", EXPFILL }},
870 { &ei_lua_proto_sequence_warn, { "_ws.lua.proto.warning", PI_SEQUENCE, PI_WARN ,"Protocol Warning", EXPFILL }},
871 { &ei_lua_proto_sequence_error, { "_ws.lua.proto.error", PI_SEQUENCE, PI_ERROR ,"Protocol Error", EXPFILL }},
872
873 { &ei_lua_proto_response_comment, { "_ws.lua.proto.comment", PI_RESPONSE_CODE, PI_COMMENT ,"Protocol Comment", EXPFILL }},
874 { &ei_lua_proto_response_chat, { "_ws.lua.proto.chat", PI_RESPONSE_CODE, PI_CHAT ,"Protocol Chat", EXPFILL }},
875 { &ei_lua_proto_response_note, { "_ws.lua.proto.note", PI_RESPONSE_CODE, PI_NOTE ,"Protocol Note", EXPFILL }},
876 { &ei_lua_proto_response_warn, { "_ws.lua.proto.warning", PI_RESPONSE_CODE, PI_WARN ,"Protocol Warning", EXPFILL }},
877 { &ei_lua_proto_response_error, { "_ws.lua.proto.error", PI_RESPONSE_CODE, PI_ERROR ,"Protocol Error", EXPFILL }},
878
879 { &ei_lua_proto_request_comment, { "_ws.lua.proto.comment", PI_REQUEST_CODE, PI_COMMENT ,"Protocol Comment", EXPFILL }},
880 { &ei_lua_proto_request_chat, { "_ws.lua.proto.chat", PI_REQUEST_CODE, PI_CHAT ,"Protocol Chat", EXPFILL }},
881 { &ei_lua_proto_request_note, { "_ws.lua.proto.note", PI_REQUEST_CODE, PI_NOTE ,"Protocol Note", EXPFILL }},
882 { &ei_lua_proto_request_warn, { "_ws.lua.proto.warning", PI_REQUEST_CODE, PI_WARN ,"Protocol Warning", EXPFILL }},
883 { &ei_lua_proto_request_error, { "_ws.lua.proto.error", PI_REQUEST_CODE, PI_ERROR ,"Protocol Error", EXPFILL }},
884
885 { &ei_lua_proto_undecoded_comment, { "_ws.lua.proto.comment", PI_UNDECODED, PI_COMMENT ,"Protocol Comment", EXPFILL }},
886 { &ei_lua_proto_undecoded_chat, { "_ws.lua.proto.chat", PI_UNDECODED, PI_CHAT ,"Protocol Chat", EXPFILL }},
887 { &ei_lua_proto_undecoded_note, { "_ws.lua.proto.note", PI_UNDECODED, PI_NOTE ,"Protocol Note", EXPFILL }},
888 { &ei_lua_proto_undecoded_warn, { "_ws.lua.proto.warning", PI_UNDECODED, PI_WARN ,"Protocol Warning", EXPFILL }},
889 { &ei_lua_proto_undecoded_error, { "_ws.lua.proto.error", PI_UNDECODED, PI_ERROR ,"Protocol Error", EXPFILL }},
890
891 { &ei_lua_proto_reassemble_comment, { "_ws.lua.proto.comment", PI_REASSEMBLE, PI_COMMENT ,"Protocol Comment", EXPFILL }},
892 { &ei_lua_proto_reassemble_chat, { "_ws.lua.proto.chat", PI_REASSEMBLE, PI_CHAT ,"Protocol Chat", EXPFILL }},
893 { &ei_lua_proto_reassemble_note, { "_ws.lua.proto.note", PI_REASSEMBLE, PI_NOTE ,"Protocol Note", EXPFILL }},
894 { &ei_lua_proto_reassemble_warn, { "_ws.lua.proto.warning", PI_REASSEMBLE, PI_WARN ,"Protocol Warning", EXPFILL }},
895 { &ei_lua_proto_reassemble_error, { "_ws.lua.proto.error", PI_REASSEMBLE, PI_ERROR ,"Protocol Error", EXPFILL }},
896
897 { &ei_lua_proto_malformed_comment, { "_ws.lua.proto.comment", PI_MALFORMED, PI_COMMENT ,"Protocol Comment", EXPFILL }},
898 { &ei_lua_proto_malformed_chat, { "_ws.lua.proto.chat", PI_MALFORMED, PI_CHAT ,"Protocol Chat", EXPFILL }},
899 { &ei_lua_proto_malformed_note, { "_ws.lua.proto.note", PI_MALFORMED, PI_NOTE ,"Protocol Note", EXPFILL }},
900 { &ei_lua_proto_malformed_warn, { "_ws.lua.proto.warning", PI_MALFORMED, PI_WARN ,"Protocol Warning", EXPFILL }},
901 { &ei_lua_proto_malformed_error, { "_ws.lua.proto.error", PI_MALFORMED, PI_ERROR ,"Protocol Error", EXPFILL }},
902
903 { &ei_lua_proto_debug_comment, { "_ws.lua.proto.comment", PI_DEBUG, PI_COMMENT ,"Protocol Comment", EXPFILL }},
904 { &ei_lua_proto_debug_chat, { "_ws.lua.proto.chat", PI_DEBUG, PI_CHAT ,"Protocol Chat", EXPFILL }},
905 { &ei_lua_proto_debug_note, { "_ws.lua.proto.note", PI_DEBUG, PI_NOTE ,"Protocol Note", EXPFILL }},
906 { &ei_lua_proto_debug_warn, { "_ws.lua.proto.warning", PI_DEBUG, PI_WARN ,"Protocol Warning", EXPFILL }},
907 { &ei_lua_proto_debug_error, { "_ws.lua.proto.error", PI_DEBUG, PI_ERROR ,"Protocol Error", EXPFILL }},
908
909 { &ei_lua_proto_protocol_comment, { "_ws.lua.proto.comment", PI_PROTOCOL, PI_COMMENT ,"Protocol Comment", EXPFILL }},
910 { &ei_lua_proto_protocol_chat, { "_ws.lua.proto.chat", PI_PROTOCOL, PI_CHAT ,"Protocol Chat", EXPFILL }},
911 { &ei_lua_proto_protocol_note, { "_ws.lua.proto.note", PI_PROTOCOL, PI_NOTE ,"Protocol Note", EXPFILL }},
912 { &ei_lua_proto_protocol_warn, { "_ws.lua.proto.warning", PI_PROTOCOL, PI_WARN ,"Protocol Warning", EXPFILL }},
913 { &ei_lua_proto_protocol_error, { "_ws.lua.proto.error", PI_PROTOCOL, PI_ERROR ,"Protocol Error", EXPFILL }},
914
915 { &ei_lua_proto_security_comment, { "_ws.lua.proto.comment", PI_SECURITY, PI_COMMENT ,"Protocol Comment", EXPFILL }},
916 { &ei_lua_proto_security_chat, { "_ws.lua.proto.chat", PI_SECURITY, PI_CHAT ,"Protocol Chat", EXPFILL }},
917 { &ei_lua_proto_security_note, { "_ws.lua.proto.note", PI_SECURITY, PI_NOTE ,"Protocol Note", EXPFILL }},
918 { &ei_lua_proto_security_warn, { "_ws.lua.proto.warning", PI_SECURITY, PI_WARN ,"Protocol Warning", EXPFILL }},
919 { &ei_lua_proto_security_error, { "_ws.lua.proto.error", PI_SECURITY, PI_ERROR ,"Protocol Error", EXPFILL }},
920
921 { &ei_lua_proto_comments_comment, { "_ws.lua.proto.comment", PI_COMMENTS_GROUP, PI_COMMENT ,"Protocol Comment", EXPFILL }},
922 { &ei_lua_proto_comments_chat, { "_ws.lua.proto.chat", PI_COMMENTS_GROUP, PI_CHAT ,"Protocol Chat", EXPFILL }},
923 { &ei_lua_proto_comments_note, { "_ws.lua.proto.note", PI_COMMENTS_GROUP, PI_NOTE ,"Protocol Note", EXPFILL }},
924 { &ei_lua_proto_comments_warn, { "_ws.lua.proto.warning", PI_COMMENTS_GROUP, PI_WARN ,"Protocol Warning", EXPFILL }},
925 { &ei_lua_proto_comments_error, { "_ws.lua.proto.error", PI_COMMENTS_GROUP, PI_ERROR ,"Protocol Error", EXPFILL }},
926
927 { &ei_lua_proto_decryption_comment, { "_ws.lua.proto.comment", PI_DECRYPTION, PI_COMMENT ,"Protocol Comment", EXPFILL }},
928 { &ei_lua_proto_decryption_chat, { "_ws.lua.proto.chat", PI_DECRYPTION, PI_CHAT ,"Protocol Chat", EXPFILL }},
929 { &ei_lua_proto_decryption_note, { "_ws.lua.proto.note", PI_DECRYPTION, PI_NOTE ,"Protocol Note", EXPFILL }},
930 { &ei_lua_proto_decryption_warn, { "_ws.lua.proto.warning", PI_DECRYPTION, PI_WARN ,"Protocol Warning", EXPFILL }},
931 { &ei_lua_proto_decryption_error, { "_ws.lua.proto.error", PI_DECRYPTION, PI_ERROR ,"Protocol Error", EXPFILL }},
932
933 { &ei_lua_proto_assumption_comment, { "_ws.lua.proto.comment", PI_ASSUMPTION, PI_COMMENT ,"Protocol Comment", EXPFILL }},
934 { &ei_lua_proto_assumption_chat, { "_ws.lua.proto.chat", PI_ASSUMPTION, PI_CHAT ,"Protocol Chat", EXPFILL }},
935 { &ei_lua_proto_assumption_note, { "_ws.lua.proto.note", PI_ASSUMPTION, PI_NOTE ,"Protocol Note", EXPFILL }},
936 { &ei_lua_proto_assumption_warn, { "_ws.lua.proto.warning", PI_ASSUMPTION, PI_WARN ,"Protocol Warning", EXPFILL }},
937 { &ei_lua_proto_assumption_error, { "_ws.lua.proto.error", PI_ASSUMPTION, PI_ERROR ,"Protocol Error", EXPFILL }},
938
939 { &ei_lua_proto_deprecated_comment, { "_ws.lua.proto.comment", PI_DEPRECATED, PI_COMMENT ,"Protocol Comment", EXPFILL }},
940 { &ei_lua_proto_deprecated_chat, { "_ws.lua.proto.chat", PI_DEPRECATED, PI_CHAT ,"Protocol Chat", EXPFILL }},
941 { &ei_lua_proto_deprecated_note, { "_ws.lua.proto.note", PI_DEPRECATED, PI_NOTE ,"Protocol Note", EXPFILL }},
942 { &ei_lua_proto_deprecated_warn, { "_ws.lua.proto.warning", PI_DEPRECATED, PI_WARN ,"Protocol Warning", EXPFILL }},
943 { &ei_lua_proto_deprecated_error, { "_ws.lua.proto.error", PI_DEPRECATED, PI_ERROR ,"Protocol Error", EXPFILL }},
944
945 /* this one is for reporting errors executing Lua code */
946 { &ei_lua_error, { "_ws.lua.error", PI_UNDECODED, PI_ERROR ,"Lua Error", EXPFILL }},
947 };
948
949 if (first_time) {
950 ws_lua_ei = ei;
951 ws_lua_ei_len = array_length(ei);
952 }
953
954 /* set up the logger */
955 wslua_logger = ops ? ops->logger : basic_logger;
956
957 if (!L) {
958 L = lua_newstate(wslua_allocf, NULL);
959 }
960
961 WSLUA_INIT(L);
962
963 #if LUA_VERSION_NUM == 501
964 /* table.unpack was introduced with Lua 5.2, alias it to unpack. */
965 lua_getglobal(L, "table");
966 lua_getglobal(L, "unpack");
967 lua_setfield(L, -2, "unpack");
968 lua_pop(L, 1);
969 #endif
970
971 if (first_time) {
972 proto_lua = proto_register_protocol("Lua Dissection", "Lua Dissection", "_ws.lua");
973 proto_register_field_array(proto_lua, hf, array_length(hf));
974 expert_lua = expert_register_protocol(proto_lua);
975 expert_register_field_array(expert_lua, ei, array_length(ei));
976 }
977
978 lua_atpanic(L,wslua_panic);
979
980 /*
981 * The init_routines table (accessible by the user).
982 *
983 * For a table a, a.init is syntactic sugar for a["init"], and
984 *
985 * function t.a.b.c.f () body end
986 *
987 * is syntactic sugar for
988 *
989 * t.a.b.c.f = function () body end
990 *
991 * so
992 *
993 * function proto.init () body end
994 *
995 * means
996 *
997 * proto["init"] = function () body end
998 *
999 * and the Proto class has an "init" method, with Proto_set_init()
1000 * being the setter for that method; that routine adds the Lua
1001 * function passed to it as a Lua argument to the WSLUA_INIT_ROUTINES
1002 * table - i.e., "init_routines".
1003 */
1004 lua_newtable (L);
1005 lua_setglobal(L, WSLUA_INIT_ROUTINES);
1006
1007 /* the dissectors table goes in the registry (not accessible) */
1008 lua_newtable (L);
1009 lua_dissectors_table_ref = luaL_ref(L, LUA_REGISTRYINDEX);
1010 lua_newtable (L);
1011 lua_heur_dissectors_table_ref = luaL_ref(L, LUA_REGISTRYINDEX);
1012
1013 /* the preferences apply_cb table (accessible by the user) */
1014 lua_newtable (L);
1015 lua_setglobal(L, WSLUA_PREFS_CHANGED);
1016
1017 /* set running_superuser variable to its proper value */
1018 WSLUA_REG_GLOBAL_BOOL(L,"running_superuser",started_with_special_privs());
1019
1020 /* special constant used by PDU reassembly handling */
1021 /* see dissect_lua() for notes */
1022 WSLUA_REG_GLOBAL_NUMBER(L,"DESEGMENT_ONE_MORE_SEGMENT",DESEGMENT_ONE_MORE_SEGMENT);
1023
1024 /* load system's init.lua */
1025 filename = get_datafile_path("init.lua");
1026 if (( file_exists(filename))) {
1027 lua_load_internal_script(filename);
1028 }
1029
1030 g_free(filename);
1031 filename = NULL;
1032
1033 /* check if lua is to be disabled */
1034 lua_getglobal(L, "disable_lua"); // 2.6 and earlier, deprecated
1035 if (lua_isboolean(L,-1)) {
1036 enable_lua = ! lua_toboolean(L,-1);
1037 }
1038 lua_pop(L,1); /* pop the getglobal result */
1039
1040 lua_getglobal(L, "enable_lua"); // 3.0 and later
1041 if (lua_isboolean(L,-1)) {
1042 enable_lua = lua_toboolean(L,-1);
1043 }
1044 lua_pop(L,1); /* pop the getglobal result */
1045
1046 if (!enable_lua) {
1047 /* disable lua */
1048 lua_close(L);
1049 L = NULL;
1050 first_time = FALSE;
1051 return;
1052 }
1053
1054 /* load global scripts */
1055 lua_load_global_plugins(cb, client_data, FALSE);
1056
1057 /* check whether we should run other scripts even if running superuser */
1058 lua_getglobal(L,"run_user_scripts_when_superuser");
1059
1060 if (lua_isboolean(L,-1) && lua_toboolean(L,-1)) {
1061 run_anyway = TRUE;
1062 }
1063 lua_pop(L,1); /* pop the getglobal result */
1064
1065 /* if we are indeed superuser run user scripts only if told to do so */
1066 if ( (!started_with_special_privs()) || run_anyway ) {
1067 /* load users init.lua */
1068 filename = get_persconffile_path("init.lua", FALSE);
1069 if ((file_exists(filename))) {
1070 if (cb)
1071 (*cb)(RA_LUA_PLUGINS, get_basename(filename), client_data);
1072 lua_load_internal_script(filename);
1073 }
1074 g_free(filename);
1075
1076 /* load user scripts */
1077 lua_load_pers_plugins(cb, client_data, FALSE);
1078
1079 /* load scripts from command line */
1080 for (i = 0; i < ex_opt_count("lua_script"); i++) {
1081 const gchar *script_filename = ex_opt_get_nth("lua_script", i);
1082 char* dirname = g_strdup(script_filename);
1083 char* dname = get_dirname(dirname);
1084
1085 if (cb)
1086 (*cb)(RA_LUA_PLUGINS, get_basename(script_filename), client_data);
1087
1088 lua_load_plugin_script(ws_dir_get_name(script_filename),
1089 script_filename,
1090 dname ? dname : "",
1091 file_count);
1092 file_count++;
1093 g_free(dirname);
1094 }
1095 }
1096
1097 if (first_time) {
1098 /* at this point we're set up so register the init and cleanup routines */
1099 register_init_routine(wslua_init_routine);
1100 register_cleanup_routine(wslua_cleanup_routine);
1101 }
1102
1103 /*
1104 * after this point it is too late to register a menu
1105 * disable the function to avoid weirdness
1106 */
1107 lua_pushcfunction(L, wslua_not_register_menu);
1108 lua_setglobal(L, "register_menu");
1109
1110 /* set up some essential globals */
1111 lua_pinfo = NULL;
1112 lua_tree = NULL;
1113 lua_tvb = NULL;
1114
1115 Proto_commit(L);
1116
1117 first_time = FALSE;
1118 }
1119
wslua_early_cleanup(void)1120 void wslua_early_cleanup(void) {
1121 wslua_deregister_protocols(L);
1122 }
1123
wslua_reload_plugins(register_cb cb,gpointer client_data)1124 void wslua_reload_plugins (register_cb cb, gpointer client_data) {
1125 const funnel_ops_t* ops = funnel_get_funnel_ops();
1126
1127 if (cb)
1128 (*cb)(RA_LUA_DEREGISTER, NULL, client_data);
1129
1130 if (ops->close_dialogs)
1131 ops->close_dialogs();
1132
1133 wslua_deregister_heur_dissectors(L);
1134 wslua_deregister_protocols(L);
1135 wslua_deregister_dissector_tables(L);
1136 wslua_deregister_listeners(L);
1137 wslua_deregister_fields(L);
1138 wslua_deregister_filehandlers(L);
1139 wslua_deregister_menus();
1140 wslua_clear_plugin_list();
1141
1142 wslua_cleanup();
1143 wslua_init(cb, client_data); /* reinitialize */
1144 }
1145
wslua_cleanup(void)1146 void wslua_cleanup(void) {
1147 /* cleanup lua */
1148 if (L) {
1149 lua_close(L);
1150 L = NULL;
1151 }
1152 init_routine_initialized = FALSE;
1153 }
1154
wslua_state(void)1155 lua_State* wslua_state(void) { return L; }
1156
1157 /*
1158 * Editor modelines - https://www.wireshark.org/tools/modelines.html
1159 *
1160 * Local variables:
1161 * c-basic-offset: 4
1162 * tab-width: 8
1163 * indent-tabs-mode: nil
1164 * End:
1165 *
1166 * vi: set shiftwidth=4 tabstop=8 expandtab:
1167 * :indentSize=4:tabSize=8:noTabs=true:
1168 */
1169