4 * Wireshark's interface to the Lua Programming Language
6 * (c) 2006, Luis E. Garcia Ontanon <luis@ontanon.org>
10 * Wireshark - Network traffic analyzer
11 * By Gerald Combs <gerald@wireshark.org>
12 * Copyright 1998 Gerald Combs
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
32 #include "init_wslua.h"
33 #include <epan/dissectors/packet-frame.h>
35 #include <epan/expert.h>
36 #include <epan/ex-opt.h>
37 #include <epan/plugins.h>
38 #include <wsutil/privileges.h>
39 #include <wsutil/file_util.h>
41 static lua_State
* L
= NULL
;
43 packet_info
* lua_pinfo
;
44 struct _wslua_treeitem
* lua_tree
;
46 int lua_dissectors_table_ref
;
48 static int proto_lua
= -1;
49 static expert_field ei_lua_error
= EI_INIT
;
51 dissector_handle_t lua_data_handle
;
53 static void lua_frame_end(void)
55 clear_outstanding_Tvb();
56 clear_outstanding_TvbRange();
57 clear_outstanding_Pinfo();
58 clear_outstanding_Column();
59 clear_outstanding_Columns();
60 clear_outstanding_PrivateTable();
61 clear_outstanding_TreeItem();
64 static int wslua_not_register_menu(lua_State
* LS
) {
65 luaL_error(LS
,"too late to register a menu");
69 int dissect_lua(tvbuff_t
* tvb
, packet_info
* pinfo
, proto_tree
* tree
, void* data _U_
) {
70 int consumed_bytes
= tvb_length(tvb
);
74 lua_tree
= (struct _wslua_treeitem
*)g_malloc(sizeof(struct _wslua_treeitem
));
75 lua_tree
->tree
= tree
;
76 lua_tree
->item
= proto_tree_add_text(tree
,tvb
,0,0,"lua fake item");
77 lua_tree
->expired
= FALSE
;
78 PROTO_ITEM_SET_HIDDEN(lua_tree
->item
);
81 * almost equivalent to Lua:
82 * dissectors[current_proto](tvb,pinfo,tree)
87 lua_rawgeti(L
, LUA_REGISTRYINDEX
, lua_dissectors_table_ref
);
89 lua_pushstring(L
, pinfo
->current_proto
);
95 if (lua_isfunction(L
,1)) {
99 push_TreeItem(L
,lua_tree
);
101 if ( lua_pcall(L
,3,1,0) ) {
102 proto_tree_add_expert_format(tree
, pinfo
, &ei_lua_error
, tvb
, 0, 0, "Lua Error: %s", lua_tostring(L
,-1));
105 /* if the Lua dissector reported the consumed bytes, pass it to our caller */
106 if (lua_isnumber(L
, -1)) {
107 /* we got the consumed bytes or the missing bytes as a negative number */
108 consumed_bytes
= (int) lua_tonumber(L
, -1);
114 proto_tree_add_expert_format(tree
, pinfo
, &ei_lua_error
, tvb
, 0, 0,
115 "Lua Error: did not find the %s dissector in the dissectors table", pinfo
->current_proto
);
118 register_frame_end_routine(pinfo
, lua_frame_end
);
124 return consumed_bytes
;
128 static void iter_table_and_call(lua_State
* LS
, const gchar
* table_name
, lua_CFunction error_handler
) {
131 lua_pushcfunction(LS
,error_handler
);
132 lua_getglobal(LS
, table_name
);
134 if (!lua_istable(LS
, 2)) {
135 report_failure("Lua: either `%s' does not exist or it is not a table!\n",table_name
);
143 while (lua_next(LS
, 2)) {
144 const gchar
* name
= lua_tostring(L
,-2);
146 if (lua_isfunction(LS
,-1)) {
148 if ( lua_pcall(LS
,0,0,1) ) {
153 report_failure("Lua: Something not a function got its way into the %s.%s",table_name
,name
);
164 static int init_error_handler(lua_State
* LS
) {
165 const gchar
* error
= lua_tostring(LS
,1);
166 report_failure("Lua: Error During execution of Initialization:\n %s",error
);
171 static void wslua_init_routine(void) {
172 static gboolean initialized
= FALSE
;
174 if ( ! initialized
) {
175 lua_prime_all_fields(NULL
);
180 iter_table_and_call(L
, WSLUA_INIT_ROUTINES
,init_error_handler
);
185 static int prefs_changed_error_handler(lua_State
* LS
) {
186 const gchar
* error
= lua_tostring(LS
,1);
187 report_failure("Lua: Error During execution of prefs apply callback:\n %s",error
);
191 void wslua_prefs_changed(void) {
193 iter_table_and_call(L
, WSLUA_PREFS_CHANGED
,prefs_changed_error_handler
);
197 static const char *getF(lua_State
*LS _U_
, void *ud
, size_t *size
)
200 static char buff
[512];
201 if (feof(f
)) return NULL
;
202 *size
=fread(buff
,1,sizeof(buff
),f
);
203 return (*size
>0) ? buff
: NULL
;
206 static int lua_main_error_handler(lua_State
* LS
) {
207 const gchar
* error
= lua_tostring(LS
,1);
208 report_failure("Lua: Error during loading:\n %s",error
);
212 static void wslua_add_plugin(gchar
*name
, gchar
*version
, gchar
*filename
)
214 wslua_plugin
*new_plug
, *lua_plug
;
216 lua_plug
= wslua_plugin_list
;
217 new_plug
= (wslua_plugin
*)g_malloc(sizeof(wslua_plugin
));
219 if (!lua_plug
) { /* the list is empty */
220 wslua_plugin_list
= new_plug
;
222 while (lua_plug
->next
!= NULL
) {
223 lua_plug
= lua_plug
->next
;
225 lua_plug
->next
= new_plug
;
228 new_plug
->name
= name
;
229 new_plug
->version
= version
;
230 new_plug
->filename
= filename
;
231 new_plug
->next
= NULL
;
234 static gboolean
lua_load_script(const gchar
* filename
) {
238 if (! ( file
= ws_fopen(filename
,"r")) ) {
239 report_open_failure(filename
,errno
,FALSE
);
245 lua_pushcfunction(L
,lua_main_error_handler
);
247 #if LUA_VERSION_NUM >= 502
248 error
= lua_load(L
,getF
,file
,filename
,NULL
);
250 error
= lua_load(L
,getF
,file
,filename
);
257 case LUA_ERRSYNTAX
: {
258 report_failure("Lua: syntax error during precompilation of `%s':\n%s",filename
,lua_tostring(L
,-1));
263 report_failure("Lua: memory allocation error during execution of %s",filename
);
267 report_failure("Lua: unknown error during execution of %s: %d",filename
,error
);
273 static void basic_logger(const gchar
*log_domain _U_
,
274 GLogLevelFlags log_level _U_
,
275 const gchar
*message
,
276 gpointer user_data _U_
) {
277 fputs(message
,stderr
);
280 static int wslua_panic(lua_State
* LS
) {
281 g_error("LUA PANIC: %s",lua_tostring(LS
,-1));
282 /** g_error() does an abort() and thus never returns **/
283 return 0; /* keep gcc happy */
286 static int lua_load_plugins(const char *dirname
, register_cb cb
, gpointer client_data
, gboolean count_only
) {
287 WS_DIR
*dir
; /* scanned directory */
288 WS_DIRENT
*file
; /* current file */
289 gchar
*filename
, *dot
;
291 int plugins_counter
= 0;
293 if ((dir
= ws_dir_open(dirname
, 0, NULL
)) != NULL
) {
294 while ((file
= ws_dir_read_name(dir
)) != NULL
) {
295 name
= ws_dir_get_name(file
);
297 if (strcmp(name
, ".") == 0 || strcmp(name
, "..") == 0)
298 continue; /* skip "." and ".." */
300 filename
= g_strdup_printf("%s" G_DIR_SEPARATOR_S
"%s", dirname
, name
);
301 if (test_for_directory(filename
) == EISDIR
) {
302 plugins_counter
+= lua_load_plugins(filename
, cb
, client_data
, count_only
);
307 /* skip files starting wih . */
308 if (name
[0] == '.') {
313 /* skip anything but files with .lua suffix */
314 dot
= strrchr(name
, '.');
315 if (dot
== NULL
|| g_ascii_strcasecmp(dot
+1, "lua") != 0) {
320 if (file_exists(filename
)) {
323 (*cb
)(RA_LUA_PLUGINS
, name
, client_data
);
324 if (lua_load_script(filename
)) {
325 wslua_add_plugin(g_strdup(name
), g_strdup(""), g_strdup(filename
));
335 return plugins_counter
;
338 int wslua_count_plugins(void) {
342 /* count global scripts */
343 plugins_counter
= lua_load_plugins(get_plugin_dir(), NULL
, NULL
, TRUE
);
345 /* count users init.lua */
346 filename
= get_persconffile_path("init.lua", FALSE
);
347 if ((file_exists(filename
))) {
352 /* count user scripts */
353 filename
= get_plugins_pers_dir();
354 plugins_counter
+= lua_load_plugins(filename
, NULL
, NULL
, TRUE
);
357 /* count scripts from command line */
358 plugins_counter
+= ex_opt_count("lua_script");
360 return plugins_counter
;
363 int wslua_init(register_cb cb
, gpointer client_data
) {
365 const funnel_ops_t
* ops
= funnel_get_funnel_ops();
366 gboolean run_anyway
= FALSE
;
367 expert_module_t
* expert_lua
;
369 static ei_register_info ei
[] = {
370 { &ei_lua_error
, { "_ws.lua.error", PI_UNDECODED
, PI_ERROR
,"Lua Error", EXPFILL
}},
373 /* set up the logger */
374 g_log_set_handler(LOG_DOMAIN_LUA
, (GLogLevelFlags
)(G_LOG_LEVEL_CRITICAL
|
379 ops
? ops
->logger
: basic_logger
,
388 proto_lua
= proto_register_protocol("Lua Dissection", "Lua Dissection", "_ws.lua");
389 expert_lua
= expert_register_protocol(proto_lua
);
390 expert_register_field_array(expert_lua
, ei
, array_length(ei
));
392 lua_atpanic(L
,wslua_panic
);
394 /* the init_routines table (accessible by the user) */
396 lua_setglobal(L
, WSLUA_INIT_ROUTINES
);
398 /* the dissectors table goes in the registry (not accessible) */
400 lua_dissectors_table_ref
= luaL_ref(L
, LUA_REGISTRYINDEX
);
402 /* the preferences apply_cb table (accessible by the user) */
404 lua_setglobal(L
, WSLUA_PREFS_CHANGED
);
406 /* set running_superuser variable to its proper value */
407 WSLUA_REG_GLOBAL_BOOL(L
,"running_superuser",started_with_special_privs());
409 /* special constant used by PDU reassembly handling */
410 /* see dissect_lua() for notes */
411 WSLUA_REG_GLOBAL_NUMBER(L
,"DESEGMENT_ONE_MORE_SEGMENT",DESEGMENT_ONE_MORE_SEGMENT
);
413 /* load system's init.lua */
414 filename
= get_datafile_path("init.lua");
416 if (( file_exists(filename
))) {
417 lua_load_script(filename
);
423 /* check if lua is to be disabled */
424 lua_getglobal(L
,"disable_lua");
426 if (lua_isboolean(L
,-1) && lua_toboolean(L
,-1)) {
433 /* load global scripts */
434 lua_load_plugins(get_plugin_dir(), cb
, client_data
, FALSE
);
436 /* check whether we should run other scripts even if running superuser */
437 lua_getglobal(L
,"run_user_scripts_when_superuser");
439 if (lua_isboolean(L
,-1) && lua_toboolean(L
,-1)) {
443 /* if we are indeed superuser run user scripts only if told to do so */
444 if ( (!started_with_special_privs()) || run_anyway
) {
445 /* load users init.lua */
446 filename
= get_persconffile_path("init.lua", FALSE
);
447 if ((file_exists(filename
))) {
449 (*cb
)(RA_LUA_PLUGINS
, get_basename(filename
), client_data
);
450 lua_load_script(filename
);
454 /* load user scripts */
455 filename
= get_plugins_pers_dir();
456 lua_load_plugins(filename
, cb
, client_data
, FALSE
);
459 /* load scripts from command line */
460 while((filename
= (gchar
*)ex_opt_get_next("lua_script"))) {
462 (*cb
)(RA_LUA_PLUGINS
, get_basename(filename
), client_data
);
463 lua_load_script(filename
);
467 /* at this point we're set up so register the init routine */
468 register_init_routine(wslua_init_routine
);
471 * after this point it is too late to register a menu
472 * disable the function to avoid weirdness
474 lua_pushcfunction(L
, wslua_not_register_menu
);
475 lua_setglobal(L
, "register_menu");
477 /* set up some essential globals */
482 lua_data_handle
= find_dissector("data");
489 int wslua_cleanup(void) {
496 lua_State
* wslua_state(void) { return L
; }
499 * Editor modelines - http://www.wireshark.org/tools/modelines.html
504 * indent-tabs-mode: nil
507 * vi: set shiftwidth=4 tabstop=4 expandtab:
508 * :indentSize=4:tabSize=4:noTabs=true: