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) ?
48 ep_strdup_printf("Lua: on packet %i Error During execution of Listener Packet Callback",lua_pinfo->fd->num) :
49 ep_strdup_printf("Lua: Error During execution of Listener Packet Callback") ;
51 /* show the error the 1st, 3rd, 5th, 9th, 17th, 33th... time it appears to avoid window flooding */
52 /* XXX the last series of identical errors won't be shown (the user however gets at least one message) */
55 report_failure("%s:\n%s",where,error);
56 last_error = g_strdup(error);
62 if (g_str_equal(last_error,error) ) {
64 if ( repeated == next ) {
65 report_failure("%s happened %i times:\n %s",where,repeated,error);
69 report_failure("%s happened %i times:\n %s",where,repeated,last_error);
71 last_error = g_strdup(error);
74 report_failure("%s:\n %s",where,error);
81 int lua_tap_packet(void *tapdata, packet_info *pinfo, epan_dissect_t *edt, const void *data) {
82 Listener tap = tapdata;
85 if (tap->packet_ref == LUA_NOREF) return 0;
89 lua_pushcfunction(tap->L,tap_packet_cb_error_handler);
90 lua_rawgeti(tap->L, LUA_REGISTRYINDEX, tap->packet_ref);
92 push_Pinfo(tap->L, pinfo);
93 push_Tvb(tap->L, edt->tvb);
96 tap->extractor(tap->L,data);
103 lua_tree = g_malloc(sizeof(struct _wslua_treeitem));
104 lua_tree->tree = edt->tree;
105 lua_tree->item = NULL;
106 lua_tree->expired = FALSE;
108 switch ( lua_pcall(tap->L,3,1,1) ) {
110 retval = luaL_optint(tap->L,-1,1);
115 g_warning("Memory alloc error while calling listenet tap callback packet");
118 g_assert_not_reached();
122 clear_outstanding_Pinfo();
123 clear_outstanding_Tvb();
132 int tap_reset_cb_error_handler(lua_State* L) {
133 const gchar* error = lua_tostring(L,1);
134 report_failure("Lua: Error During execution of Listener init Callback:\n %s",error);
138 void lua_tap_reset(void *tapdata) {
139 Listener tap = tapdata;
141 if (tap->init_ref == LUA_NOREF) return;
143 lua_pushcfunction(tap->L,tap_reset_cb_error_handler);
144 lua_rawgeti(tap->L, LUA_REGISTRYINDEX, tap->init_ref);
146 switch ( lua_pcall(tap->L,0,0,1) ) {
150 g_warning("Runtime error while calling a listener's init()");
153 g_warning("Memory alloc error while calling a listener's init()");
156 g_assert_not_reached();
161 int tap_draw_cb_error_handler(lua_State* L) {
162 const gchar* error = lua_tostring(L,1);
163 report_failure("Lua: Error During execution of Listener Draw Callback:\n %s",error);
167 void lua_tap_draw(void *tapdata) {
168 Listener tap = tapdata;
170 if (tap->draw_ref == LUA_NOREF) return;
172 lua_pushcfunction(tap->L,tap_reset_cb_error_handler);
173 lua_rawgeti(tap->L, LUA_REGISTRYINDEX, tap->draw_ref);
175 switch ( lua_pcall(tap->L,0,0,1) ) {
180 error = lua_tostring(tap->L,-1);
181 g_warning("Runtime error while calling a listener's draw(): %s",error);
184 g_warning("Memory alloc error while calling a listener's draw()");
187 g_assert_not_reached();
192 WSLUA_CONSTRUCTOR Listener_new(lua_State* L) {
193 /* Creates a new Listener listener */
194 #define WSLUA_OPTARG_Listener_new_TAP 1 /* The name of this tap */
195 #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) */
197 const gchar* tap_type = luaL_optstring(L,WSLUA_OPTARG_Listener_new_TAP,"frame");
198 const gchar* filter = luaL_optstring(L,WSLUA_OPTARG_Listener_new_FILTER,NULL);
202 tap = g_malloc(sizeof(struct _wslua_tap));
204 tap->name = g_strdup(tap_type);
205 tap->filter = filter ? g_strdup(filter) : NULL;
206 tap->extractor = wslua_get_tap_extractor(tap_type);
208 tap->packet_ref = LUA_NOREF;
209 tap->draw_ref = LUA_NOREF;
210 tap->init_ref = LUA_NOREF;
212 error = register_tap_listener(tap_type, tap, tap->filter, lua_tap_reset, lua_tap_packet, lua_tap_draw);
218 /* WSLUA_ERROR(new_tap,"tap registration error"); */
219 luaL_error(L,"Error while registering tap:\n%s",error->str);
220 g_string_free(error,TRUE); /* XXX LEAK? */
224 WSLUA_RETURN(1); /* The newly created Listener listener object */
227 WSLUA_METHOD Listener_remove(lua_State* L) {
228 /* Removes a tap listener */
229 Listener tap = checkListener(L,1);
233 remove_tap_listener(tap);
238 WSLUA_METAMETHOD Listener_tostring(lua_State* L) {
239 Listener tap = checkListener(L,1);
244 str = g_strdup_printf("Listener(%s) filter: %s",tap->name, tap->filter ? tap->filter : "NONE");
245 lua_pushstring(L,str);
252 static int Listener_newindex(lua_State* L) {
253 /* WSLUA_ATTRIBUTE Listener_packet WO A function that will be called once every packet matches the Listener listener filter.
255 function tap.packet(pinfo,tvb,userdata) ... end
257 /* WSLUA_ATTRIBUTE Listener_draw WO A function that will be called once every few seconds to redraw the gui objects
258 in tshark this funtion is called oly at the very end of the capture file.
260 function tap.draw(userdata) ... end
262 /* WSLUA_ATTRIBUTE Listener_reset WO A function that will be called at the end of the capture run.
264 function tap.reset(userdata) ... end
266 Listener tap = shiftListener(L,1);
267 const gchar* index = lua_shiftstring(L,1);
270 if (!index) return 0;
272 if (g_str_equal(index,"packet")) {
273 refp = &(tap->packet_ref);
274 } else if (g_str_equal(index,"draw")) {
275 refp = &(tap->draw_ref);
276 } else if (g_str_equal(index,"reset")) {
277 refp = &(tap->init_ref);
279 luaL_error(L,"No such attribute `%s' for a tap",index);
283 if (! lua_isfunction(L,1)) {
284 luaL_error(L,"Listener's attribute `%s' must be a function");
289 *refp = luaL_ref(L, LUA_REGISTRYINDEX);
295 static const luaL_reg Listener_methods[] = {
296 {"new", Listener_new},
297 {"remove", Listener_remove},
301 static const luaL_reg Listener_meta[] = {
302 {"__tostring", Listener_tostring},
303 {"__newindex", Listener_newindex},
307 int Listener_register(lua_State* L) {
308 wslua_set_tap_enums(L);
309 WSLUA_REGISTER_CLASS(Listener);