HACK: pinfo->private_data points to smb_info again
[wireshark-wip.git] / epan / wslua / init_wslua.c
blobafee46d91cccd4dd871224c659cb55eb70e64deb
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 * $Id$
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.
29 #include "config.h"
31 #include "wslua.h"
32 #include "init_wslua.h"
33 #include <epan/dissectors/packet-frame.h>
34 #include <math.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;
45 tvbuff_t* lua_tvb;
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");
66 return 0;
69 int dissect_lua(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, void* data _U_) {
70 int consumed_bytes = tvb_length(tvb);
71 lua_pinfo = pinfo;
72 lua_tvb = 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)
85 lua_settop(L,0);
87 lua_rawgeti(L, LUA_REGISTRYINDEX, lua_dissectors_table_ref);
89 lua_pushstring(L, pinfo->current_proto);
90 lua_gettable(L, -2);
92 lua_remove(L,1);
95 if (lua_isfunction(L,1)) {
97 push_Tvb(L,tvb);
98 push_Pinfo(L,pinfo);
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));
103 } else {
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);
109 lua_pop(L, 1);
113 } else {
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);
120 lua_pinfo = NULL;
121 lua_tree = NULL;
122 lua_tvb = NULL;
124 return consumed_bytes;
128 static void iter_table_and_call(lua_State* LS, const gchar* table_name, lua_CFunction error_handler) {
129 lua_settop(LS,0);
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);
136 lua_close(LS);
137 L = NULL;
138 return;
141 lua_pushnil(LS);
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) ) {
149 lua_pop(LS,1);
152 } else {
153 report_failure("Lua: Something not a function got its way into the %s.%s",table_name,name);
154 lua_close(LS);
155 L = NULL;
156 return;
160 lua_settop(LS,0);
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);
167 return 0;
171 static void wslua_init_routine(void) {
172 static gboolean initialized = FALSE;
174 if ( ! initialized ) {
175 lua_prime_all_fields(NULL);
176 initialized = TRUE;
179 if (L) {
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);
188 return 0;
191 void wslua_prefs_changed(void) {
192 if (L) {
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)
199 FILE *f=(FILE *)ud;
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);
209 return 0;
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;
221 } else {
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) {
235 FILE* file;
236 int error;
238 if (! ( file = ws_fopen(filename,"r")) ) {
239 report_open_failure(filename,errno,FALSE);
240 return FALSE;
243 lua_settop(L,0);
245 lua_pushcfunction(L,lua_main_error_handler);
247 #if LUA_VERSION_NUM >= 502
248 error = lua_load(L,getF,file,filename,NULL);
249 #else
250 error = lua_load(L,getF,file,filename);
251 #endif
252 switch (error) {
253 case 0:
254 lua_pcall(L,0,0,1);
255 fclose(file);
256 return TRUE;
257 case LUA_ERRSYNTAX: {
258 report_failure("Lua: syntax error during precompilation of `%s':\n%s",filename,lua_tostring(L,-1));
259 fclose(file);
260 return FALSE;
262 case LUA_ERRMEM:
263 report_failure("Lua: memory allocation error during execution of %s",filename);
264 fclose(file);
265 return FALSE;
266 default:
267 report_failure("Lua: unknown error during execution of %s: %d",filename,error);
268 fclose(file);
269 return FALSE;
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;
290 const gchar *name;
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);
303 g_free(filename);
304 continue;
307 /* skip files starting wih . */
308 if (name[0] == '.') {
309 g_free(filename);
310 continue;
313 /* skip anything but files with .lua suffix */
314 dot = strrchr(name, '.');
315 if (dot == NULL || g_ascii_strcasecmp(dot+1, "lua") != 0) {
316 g_free(filename);
317 continue;
320 if (file_exists(filename)) {
321 if (!count_only) {
322 if (cb)
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));
328 plugins_counter++;
330 g_free(filename);
332 ws_dir_close(dir);
335 return plugins_counter;
338 int wslua_count_plugins(void) {
339 gchar* filename;
340 int plugins_counter;
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))) {
348 plugins_counter++;
350 g_free(filename);
352 /* count user scripts */
353 filename = get_plugins_pers_dir();
354 plugins_counter += lua_load_plugins(filename, NULL, NULL, TRUE);
355 g_free(filename);
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) {
364 gchar* filename;
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|
375 G_LOG_LEVEL_WARNING|
376 G_LOG_LEVEL_MESSAGE|
377 G_LOG_LEVEL_INFO|
378 G_LOG_LEVEL_DEBUG),
379 ops ? ops->logger : basic_logger,
380 NULL);
382 if (!L) {
383 L = luaL_newstate();
386 WSLUA_INIT(L);
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) */
395 lua_newtable (L);
396 lua_setglobal(L, WSLUA_INIT_ROUTINES);
398 /* the dissectors table goes in the registry (not accessible) */
399 lua_newtable (L);
400 lua_dissectors_table_ref = luaL_ref(L, LUA_REGISTRYINDEX);
402 /* the preferences apply_cb table (accessible by the user) */
403 lua_newtable (L);
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);
420 g_free(filename);
421 filename = NULL;
423 /* check if lua is to be disabled */
424 lua_getglobal(L,"disable_lua");
426 if (lua_isboolean(L,-1) && lua_toboolean(L,-1)) {
427 /* disable lua */
428 lua_close(L);
429 L = NULL;
430 return 0;
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)) {
440 run_anyway = TRUE;
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))) {
448 if (cb)
449 (*cb)(RA_LUA_PLUGINS, get_basename(filename), client_data);
450 lua_load_script(filename);
452 g_free(filename);
454 /* load user scripts */
455 filename = get_plugins_pers_dir();
456 lua_load_plugins(filename, cb, client_data, FALSE);
457 g_free(filename);
459 /* load scripts from command line */
460 while((filename = (gchar *)ex_opt_get_next("lua_script"))) {
461 if (cb)
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 */
478 lua_pinfo = NULL;
479 lua_tree = NULL;
480 lua_tvb = NULL;
482 lua_data_handle = find_dissector("data");
484 Proto_commit(L);
486 return 0;
489 int wslua_cleanup(void) {
490 /* cleanup lua */
491 lua_close(L);
492 L = NULL;
493 return 0;
496 lua_State* wslua_state(void) { return L; }
499 * Editor modelines - http://www.wireshark.org/tools/modelines.html
501 * Local variables:
502 * c-basic-offset: 4
503 * tab-width: 4
504 * indent-tabs-mode: nil
505 * End:
507 * vi: set shiftwidth=4 tabstop=4 expandtab:
508 * :indentSize=4:tabSize=4:noTabs=true: