4 * Wireshark's interface to the Lua Programming Language
6 * Implementation of tap Listeners
8 * (c) 2006, Luis E. Garcia Ontanon <luis@ontanon.org>
12 * Wireshark - Network traffic analyzer
13 * By Gerald Combs <gerald@wireshark.org>
14 * Copyright 1998 Gerald Combs
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License
18 * as published by the Free Software Foundation; either version 2
19 * of the License, or (at your option) any later version.
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
33 #include <epan/emem.h>
35 /* WSLUA_MODULE Listener Post-dissection packet analysis */
39 WSLUA_CLASS_DEFINE(Listener
,NOP
,NOP
);
41 A Listener, is called once for every packet that matches a certain filter or has a certain tap.
42 It can read the tree, the packet's Tvb eventually the tapped data but it cannot
43 add elements to the tree.
46 static int tap_packet_cb_error_handler(lua_State
* L
) {
47 const gchar
* error
= lua_tostring(L
,1);
48 static gchar
* last_error
= NULL
;
49 static int repeated
= 0;
51 const gchar
* where
= (lua_pinfo
) ?
53 ep_strdup_printf("Lua: on packet %i Error During execution of Listener Packet Callback",lua_pinfo
->fd
->num
) :
54 ep_strdup_printf("Lua: Error During execution of Listener Packet Callback") ;
56 /* show the error the 1st, 3rd, 5th, 9th, 17th, 33th... time it appears to avoid window flooding */
57 /* XXX the last series of identical errors won't be shown (the user however gets at least one message) */
60 report_failure("%s:\n%s",where
,error
);
61 last_error
= g_strdup(error
);
67 if (g_str_equal(last_error
,error
) ) {
69 if ( repeated
== next
) {
70 report_failure("%s happened %i times:\n %s",where
,repeated
,error
);
74 report_failure("%s happened %i times:\n %s",where
,repeated
,last_error
);
76 last_error
= g_strdup(error
);
79 report_failure("%s:\n %s",where
,error
);
86 static int lua_tap_packet(void *tapdata
, packet_info
*pinfo
, epan_dissect_t
*edt
, const void *data
) {
87 Listener tap
= (Listener
)tapdata
;
90 if (tap
->packet_ref
== LUA_NOREF
) return 0;
94 lua_pushcfunction(tap
->L
,tap_packet_cb_error_handler
);
95 lua_rawgeti(tap
->L
, LUA_REGISTRYINDEX
, tap
->packet_ref
);
97 push_Pinfo(tap
->L
, pinfo
);
98 push_Tvb(tap
->L
, edt
->tvb
);
100 if (tap
->extractor
) {
101 tap
->extractor(tap
->L
,data
);
108 lua_tree
= (struct _wslua_treeitem
*)g_malloc(sizeof(struct _wslua_treeitem
));
109 lua_tree
->tree
= edt
->tree
;
110 lua_tree
->item
= NULL
;
111 lua_tree
->expired
= FALSE
;
113 switch ( lua_pcall(tap
->L
,3,1,1) ) {
115 retval
= luaL_optint(tap
->L
,-1,1);
120 g_warning("Memory alloc error while calling listener tap callback packet");
123 g_assert_not_reached();
127 clear_outstanding_Pinfo();
128 clear_outstanding_Tvb();
137 static int tap_reset_cb_error_handler(lua_State
* L
) {
138 const gchar
* error
= lua_tostring(L
,1);
139 report_failure("Lua: Error During execution of Listener init Callback:\n %s",error
);
143 static void lua_tap_reset(void *tapdata
) {
144 Listener tap
= (Listener
)tapdata
;
146 if (tap
->init_ref
== LUA_NOREF
) return;
148 lua_pushcfunction(tap
->L
,tap_reset_cb_error_handler
);
149 lua_rawgeti(tap
->L
, LUA_REGISTRYINDEX
, tap
->init_ref
);
151 switch ( lua_pcall(tap
->L
,0,0,1) ) {
155 g_warning("Runtime error while calling a listener's init()");
158 g_warning("Memory alloc error while calling a listener's init()");
161 g_assert_not_reached();
166 static void lua_tap_draw(void *tapdata
) {
167 Listener tap
= (Listener
)tapdata
;
169 if (tap
->draw_ref
== LUA_NOREF
) return;
171 lua_pushcfunction(tap
->L
,tap_reset_cb_error_handler
);
172 lua_rawgeti(tap
->L
, LUA_REGISTRYINDEX
, tap
->draw_ref
);
174 switch ( lua_pcall(tap
->L
,0,0,1) ) {
179 error
= lua_tostring(tap
->L
,-1);
180 g_warning("Runtime error while calling a listener's draw(): %s",error
);
183 g_warning("Memory alloc error while calling a listener's draw()");
186 g_assert_not_reached();
191 WSLUA_CONSTRUCTOR
Listener_new(lua_State
* L
) {
192 /* Creates a new Listener listener */
193 #define WSLUA_OPTARG_Listener_new_TAP 1 /* The name of this tap */
194 #define WSLUA_OPTARG_Listener_new_FILTER 2 /* A filter that when matches the tap.packet function gets called (use nil to be called for every packet) */
196 const gchar
* tap_type
= luaL_optstring(L
,WSLUA_OPTARG_Listener_new_TAP
,"frame");
197 const gchar
* filter
= luaL_optstring(L
,WSLUA_OPTARG_Listener_new_FILTER
,NULL
);
201 tap
= (Listener
)g_malloc(sizeof(struct _wslua_tap
));
203 tap
->name
= g_strdup(tap_type
);
204 tap
->filter
= filter
? g_strdup(filter
) : NULL
;
205 tap
->extractor
= wslua_get_tap_extractor(tap_type
);
207 tap
->packet_ref
= LUA_NOREF
;
208 tap
->draw_ref
= LUA_NOREF
;
209 tap
->init_ref
= LUA_NOREF
;
212 * XXX - do all Lua taps require the protocol tree? If not, it might
213 * be useful to have a way to indicate whether any do.
215 * XXX - do any Lua taps require the columns? If so, we either need
216 * to request them for this tap, or do so if any Lua taps require them.
218 error
= register_tap_listener(tap_type
, tap
, tap
->filter
, TL_REQUIRES_PROTO_TREE
, lua_tap_reset
, lua_tap_packet
, lua_tap_draw
);
224 /* WSLUA_ERROR(new_tap,"tap registration error"); */
225 luaL_error(L
,"Error while registering tap:\n%s",error
->str
);
226 g_string_free(error
,TRUE
); /* XXX LEAK? */
230 WSLUA_RETURN(1); /* The newly created Listener listener object */
233 WSLUA_METHOD
Listener_remove(lua_State
* L
) {
234 /* Removes a tap listener */
235 Listener tap
= checkListener(L
,1);
239 remove_tap_listener(tap
);
244 WSLUA_METAMETHOD
Listener__tostring(lua_State
* L
) {
245 /* Generates a string of debug info for the tap listener */
246 Listener tap
= checkListener(L
,1);
251 str
= ep_strdup_printf("Listener(%s) filter: %s",tap
->name
, tap
->filter
? tap
->filter
: "NONE");
252 lua_pushstring(L
,str
);
258 static int Listener__newindex(lua_State
* L
) {
259 /* WSLUA_ATTRIBUTE Listener_packet WO A function that will be called once every packet matches the Listener listener filter.
261 function tap.packet(pinfo,tvb,tapinfo) ... end
262 Note: tapinfo is a table of info based on the Listener's type, or nil.
264 /* WSLUA_ATTRIBUTE Listener_draw WO A function that will be called once every few seconds to redraw the gui objects;
265 in tshark this funtion is called only at the very end of the capture file.
267 function tap.draw() ... end
269 /* WSLUA_ATTRIBUTE Listener_reset WO A function that will be called at the end of the capture run.
271 function tap.reset() ... end
273 Listener tap
= shiftListener(L
,1);
274 const gchar
* idx
= lua_shiftstring(L
,1);
279 if (g_str_equal(idx
,"packet")) {
280 refp
= &(tap
->packet_ref
);
281 } else if (g_str_equal(idx
,"draw")) {
282 refp
= &(tap
->draw_ref
);
283 } else if (g_str_equal(idx
,"reset")) {
284 refp
= &(tap
->init_ref
);
286 luaL_error(L
,"No such attribute `%s' for a tap",idx
);
290 if (! lua_isfunction(L
,1)) {
291 luaL_error(L
,"Listener's attribute `%s' must be a function");
296 *refp
= luaL_ref(L
, LUA_REGISTRYINDEX
);
301 static int Listener__gc(lua_State
* L _U_
) {
302 /* do NOT free Listener, it's never free'd */
306 static const luaL_Reg Listener_methods
[] = {
307 {"new", Listener_new
},
308 {"remove", Listener_remove
},
312 static const luaL_Reg Listener_meta
[] = {
313 {"__tostring", Listener__tostring
},
314 {"__newindex", Listener__newindex
},
318 int Listener_register(lua_State
* L
) {
319 wslua_set_tap_enums(L
);
320 WSLUA_REGISTER_CLASS(Listener
);