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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
31 /* WSLUA_MODULE Listener Post-dissection packet analysis */
35 WSLUA_CLASS_DEFINE(Listener,NOP,NOP);
37 A Listener, is called once for every packet that matches a certain filter or has a certain tap.
38 It can read the tree, the packet's Tvb eventually the tapped data but it cannot
39 add elements to the tree.
42 int tap_packet_cb_error_handler(lua_State* L) {
43 const gchar* error = lua_tostring(L,1);
44 static gchar* last_error = NULL;
45 static int repeated = 0;
47 const gchar* where = (lua_pinfo) ?
49 ep_strdup_printf("Lua: on packet %i Error During execution of Listener Packet Callback",lua_pinfo->fd->num) :
50 ep_strdup_printf("Lua: Error During execution of Listener Packet Callback") ;
52 /* show the error the 1st, 3rd, 5th, 9th, 17th, 33th... time it appears to avoid window flooding */
53 /* XXX the last series of identical errors won't be shown (the user however gets at least one message) */
56 report_failure("%s:\n%s",where,error);
57 last_error = g_strdup(error);
63 if (g_str_equal(last_error,error) ) {
65 if ( repeated == next ) {
66 report_failure("%s happened %i times:\n %s",where,repeated,error);
70 report_failure("%s happened %i times:\n %s",where,repeated,last_error);
72 last_error = g_strdup(error);
75 report_failure("%s:\n %s",where,error);
82 int lua_tap_packet(void *tapdata, packet_info *pinfo, epan_dissect_t *edt, const void *data) {
83 Listener tap = tapdata;
86 if (tap->packet_ref == LUA_NOREF) return 0;
90 lua_pushcfunction(tap->L,tap_packet_cb_error_handler);
91 lua_rawgeti(tap->L, LUA_REGISTRYINDEX, tap->packet_ref);
93 push_Pinfo(tap->L, pinfo);
94 push_Tvb(tap->L, edt->tvb);
97 tap->extractor(tap->L,data);
104 lua_tree = g_malloc(sizeof(struct _wslua_treeitem));
105 lua_tree->tree = edt->tree;
106 lua_tree->item = NULL;
107 lua_tree->expired = FALSE;
109 switch ( lua_pcall(tap->L,3,1,1) ) {
111 retval = luaL_optint(tap->L,-1,1);
116 g_warning("Memory alloc error while calling listenet tap callback packet");
119 g_assert_not_reached();
123 clear_outstanding_Pinfo();
124 clear_outstanding_Tvb();
133 int tap_reset_cb_error_handler(lua_State* L) {
134 const gchar* error = lua_tostring(L,1);
135 report_failure("Lua: Error During execution of Listener init Callback:\n %s",error);
139 void lua_tap_reset(void *tapdata) {
140 Listener tap = tapdata;
142 if (tap->init_ref == LUA_NOREF) return;
144 lua_pushcfunction(tap->L,tap_reset_cb_error_handler);
145 lua_rawgeti(tap->L, LUA_REGISTRYINDEX, tap->init_ref);
147 switch ( lua_pcall(tap->L,0,0,1) ) {
151 g_warning("Runtime error while calling a listener's init()");
154 g_warning("Memory alloc error while calling a listener's init()");
157 g_assert_not_reached();
162 int tap_draw_cb_error_handler(lua_State* L) {
163 const gchar* error = lua_tostring(L,1);
164 report_failure("Lua: Error During execution of Listener Draw Callback:\n %s",error);
168 void lua_tap_draw(void *tapdata) {
169 Listener tap = tapdata;
171 if (tap->draw_ref == LUA_NOREF) return;
173 lua_pushcfunction(tap->L,tap_reset_cb_error_handler);
174 lua_rawgeti(tap->L, LUA_REGISTRYINDEX, tap->draw_ref);
176 switch ( lua_pcall(tap->L,0,0,1) ) {
181 error = lua_tostring(tap->L,-1);
182 g_warning("Runtime error while calling a listener's draw(): %s",error);
185 g_warning("Memory alloc error while calling a listener's draw()");
188 g_assert_not_reached();
193 WSLUA_CONSTRUCTOR Listener_new(lua_State* L) {
194 /* Creates a new Listener listener */
195 #define WSLUA_OPTARG_Listener_new_TAP 1 /* The name of this tap */
196 #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) */
198 const gchar* tap_type = luaL_optstring(L,WSLUA_OPTARG_Listener_new_TAP,"frame");
199 const gchar* filter = luaL_optstring(L,WSLUA_OPTARG_Listener_new_FILTER,NULL);
203 tap = g_malloc(sizeof(struct _wslua_tap));
205 tap->name = g_strdup(tap_type);
206 tap->filter = filter ? g_strdup(filter) : NULL;
207 tap->extractor = wslua_get_tap_extractor(tap_type);
209 tap->packet_ref = LUA_NOREF;
210 tap->draw_ref = LUA_NOREF;
211 tap->init_ref = LUA_NOREF;
214 * XXX - do all Lua taps require the protocol tree? If not, it might
215 * be useful to have a way to indicate whether any do.
217 * XXX - do any Lua taps require the columns? If so, we either need
218 * to request them for this tap, or do so if any Lua taps require them.
220 error = register_tap_listener(tap_type, tap, tap->filter, TL_REQUIRES_PROTO_TREE, lua_tap_reset, lua_tap_packet, lua_tap_draw);
226 /* WSLUA_ERROR(new_tap,"tap registration error"); */
227 luaL_error(L,"Error while registering tap:\n%s",error->str);
228 g_string_free(error,TRUE); /* XXX LEAK? */
232 WSLUA_RETURN(1); /* The newly created Listener listener object */
235 WSLUA_METHOD Listener_remove(lua_State* L) {
236 /* Removes a tap listener */
237 Listener tap = checkListener(L,1);
241 remove_tap_listener(tap);
246 WSLUA_METAMETHOD Listener_tostring(lua_State* L) {
247 Listener tap = checkListener(L,1);
252 str = g_strdup_printf("Listener(%s) filter: %s",tap->name, tap->filter ? tap->filter : "NONE");
253 lua_pushstring(L,str);
260 static int Listener_newindex(lua_State* L) {
261 /* WSLUA_ATTRIBUTE Listener_packet WO A function that will be called once every packet matches the Listener listener filter.
263 function tap.packet(pinfo,tvb,userdata) ... end
265 /* WSLUA_ATTRIBUTE Listener_draw WO A function that will be called once every few seconds to redraw the gui objects
266 in tshark this funtion is called oly at the very end of the capture file.
268 function tap.draw(userdata) ... end
270 /* WSLUA_ATTRIBUTE Listener_reset WO A function that will be called at the end of the capture run.
272 function tap.reset(userdata) ... end
274 Listener tap = shiftListener(L,1);
275 const gchar* index = lua_shiftstring(L,1);
278 if (!index) return 0;
280 if (g_str_equal(index,"packet")) {
281 refp = &(tap->packet_ref);
282 } else if (g_str_equal(index,"draw")) {
283 refp = &(tap->draw_ref);
284 } else if (g_str_equal(index,"reset")) {
285 refp = &(tap->init_ref);
287 luaL_error(L,"No such attribute `%s' for a tap",index);
291 if (! lua_isfunction(L,1)) {
292 luaL_error(L,"Listener's attribute `%s' must be a function");
297 *refp = luaL_ref(L, LUA_REGISTRYINDEX);
303 static const luaL_reg Listener_methods[] = {
304 {"new", Listener_new},
305 {"remove", Listener_remove},
309 static const luaL_reg Listener_meta[] = {
310 {"__tostring", Listener_tostring},
311 {"__newindex", Listener_newindex},
315 int Listener_register(lua_State* L) {
316 wslua_set_tap_enums(L);
317 WSLUA_REGISTER_CLASS(Listener);