2006-09-25 01:09:00 +00:00
/*
2006-10-17 18:20:44 +00:00
* wslua_listener . c
2006-09-25 01:09:00 +00:00
*
* Wireshark ' s interface to the Lua Programming Language
*
2006-10-17 18:20:44 +00:00
* Implementation of tap Listeners
*
2008-08-05 21:03:46 +00:00
* ( c ) 2006 , Luis E . Garcia Ontanon < luis @ ontanon . org >
2006-09-25 01:09:00 +00:00
*
2006-10-18 18:45:24 +00:00
* $ Id $
2006-09-25 01:09:00 +00:00
*
* Wireshark - Network traffic analyzer
* By Gerald Combs < gerald @ wireshark . org >
* Copyright 1998 Gerald Combs
*
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation ; either version 2
* of the License , or ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 59 Temple Place - Suite 330 , Boston , MA 02111 - 1307 , USA .
*/
2011-04-21 13:13:39 +00:00
# ifdef HAVE_CONFIG_H
# include "config.h"
# endif
2008-04-12 13:56:28 +00:00
/* WSLUA_MODULE Listener Post-dissection packet analysis */
2006-10-18 18:45:24 +00:00
2006-09-25 01:09:00 +00:00
# include "wslua.h"
2010-10-21 12:41:15 +00:00
WSLUA_CLASS_DEFINE ( Listener , NOP , NOP ) ;
2006-09-25 01:09:00 +00:00
/*
2010-10-21 12:41:15 +00:00
A Listener , is called once for every packet that matches a certain filter or has a certain tap .
It can read the tree , the packet ' s Tvb eventually the tapped data but it cannot
add elements to the tree .
2006-09-25 01:09:00 +00:00
*/
2010-10-21 12:41:15 +00:00
static int tap_packet_cb_error_handler ( lua_State * L ) {
2006-09-25 01:09:00 +00:00
const gchar * error = lua_tostring ( L , 1 ) ;
static gchar * last_error = NULL ;
static int repeated = 0 ;
static int next = 2 ;
2009-06-05 22:42:47 +00:00
const gchar * where = ( lua_pinfo ) ?
ep_strdup_printf ( " Lua: on packet %i Error During execution of Listener Packet Callback " , lua_pinfo - > fd - > num ) :
ep_strdup_printf ( " Lua: Error During execution of Listener Packet Callback " ) ;
2010-10-21 02:50:27 +00:00
/* show the error the 1st, 3rd, 5th, 9th, 17th, 33th... time it appears to avoid window flooding */
2006-09-25 01:09:00 +00:00
/* XXX the last series of identical errors won't be shown (the user however gets at least one message) */
2010-10-21 02:50:27 +00:00
2006-09-25 01:09:00 +00:00
if ( ! last_error ) {
report_failure ( " %s: \n %s " , where , error ) ;
last_error = g_strdup ( error ) ;
repeated = 0 ;
next = 2 ;
return 0 ;
}
2010-10-21 02:50:27 +00:00
2006-09-25 01:09:00 +00:00
if ( g_str_equal ( last_error , error ) ) {
repeated + + ;
if ( repeated = = next ) {
report_failure ( " %s happened %i times: \n %s " , where , repeated , error ) ;
next * = 2 ;
}
} else {
report_failure ( " %s happened %i times: \n %s " , where , repeated , last_error ) ;
g_free ( last_error ) ;
last_error = g_strdup ( error ) ;
repeated = 0 ;
next = 2 ;
report_failure ( " %s: \n %s " , where , error ) ;
}
2010-10-21 02:50:27 +00:00
return 0 ;
2006-09-25 01:09:00 +00:00
}
2010-10-21 12:41:15 +00:00
static int lua_tap_packet ( void * tapdata , packet_info * pinfo , epan_dissect_t * edt , const void * data ) {
2006-09-25 01:09:00 +00:00
Listener tap = tapdata ;
int retval = 0 ;
2010-10-21 02:50:27 +00:00
2006-09-25 01:09:00 +00:00
if ( tap - > packet_ref = = LUA_NOREF ) return 0 ;
lua_settop ( tap - > L , 0 ) ;
2010-10-21 02:50:27 +00:00
2006-09-25 01:09:00 +00:00
lua_pushcfunction ( tap - > L , tap_packet_cb_error_handler ) ;
lua_rawgeti ( tap - > L , LUA_REGISTRYINDEX , tap - > packet_ref ) ;
2010-10-21 02:50:27 +00:00
2006-09-25 01:09:00 +00:00
push_Pinfo ( tap - > L , pinfo ) ;
push_Tvb ( tap - > L , edt - > tvb ) ;
2010-10-21 02:50:27 +00:00
2009-06-05 22:42:47 +00:00
if ( tap - > extractor ) {
tap - > extractor ( tap - > L , data ) ;
} else {
lua_pushnil ( tap - > L ) ;
}
2010-10-21 02:50:27 +00:00
lua_pinfo = pinfo ;
2006-09-25 01:09:00 +00:00
lua_tvb = edt - > tvb ;
2008-07-26 23:41:31 +00:00
lua_tree = g_malloc ( sizeof ( struct _wslua_treeitem ) ) ;
2009-06-05 22:42:47 +00:00
lua_tree - > tree = edt - > tree ;
lua_tree - > item = NULL ;
lua_tree - > expired = FALSE ;
2010-10-21 02:50:27 +00:00
2006-09-25 01:09:00 +00:00
switch ( lua_pcall ( tap - > L , 3 , 1 , 1 ) ) {
case 0 :
2009-06-05 22:42:47 +00:00
retval = luaL_optint ( tap - > L , - 1 , 1 ) ;
2006-09-25 01:09:00 +00:00
break ;
case LUA_ERRRUN :
break ;
case LUA_ERRMEM :
g_warning ( " Memory alloc error while calling listenet tap callback packet " ) ;
break ;
default :
g_assert_not_reached ( ) ;
break ;
}
2010-10-21 02:50:27 +00:00
2008-07-26 23:41:31 +00:00
clear_outstanding_Pinfo ( ) ;
clear_outstanding_Tvb ( ) ;
2010-10-21 02:50:27 +00:00
lua_pinfo = NULL ;
2006-09-25 01:09:00 +00:00
lua_tvb = NULL ;
lua_tree = NULL ;
2010-10-21 02:50:27 +00:00
2006-09-25 01:09:00 +00:00
return retval ;
}
2010-10-21 12:41:15 +00:00
static int tap_reset_cb_error_handler ( lua_State * L ) {
2006-09-25 01:09:00 +00:00
const gchar * error = lua_tostring ( L , 1 ) ;
report_failure ( " Lua: Error During execution of Listener init Callback: \n %s " , error ) ;
return 1 ;
}
2010-10-21 12:41:15 +00:00
static void lua_tap_reset ( void * tapdata ) {
2006-09-25 01:09:00 +00:00
Listener tap = tapdata ;
2010-10-21 02:50:27 +00:00
2006-09-25 01:09:00 +00:00
if ( tap - > init_ref = = LUA_NOREF ) return ;
2010-10-21 02:50:27 +00:00
2006-09-25 01:09:00 +00:00
lua_pushcfunction ( tap - > L , tap_reset_cb_error_handler ) ;
lua_rawgeti ( tap - > L , LUA_REGISTRYINDEX , tap - > init_ref ) ;
2010-10-21 02:50:27 +00:00
2006-09-25 01:09:00 +00:00
switch ( lua_pcall ( tap - > L , 0 , 0 , 1 ) ) {
case 0 :
break ;
case LUA_ERRRUN :
g_warning ( " Runtime error while calling a listener's init() " ) ;
break ;
case LUA_ERRMEM :
g_warning ( " Memory alloc error while calling a listener's init() " ) ;
break ;
default :
g_assert_not_reached ( ) ;
break ;
}
}
2010-10-21 12:41:15 +00:00
static void lua_tap_draw ( void * tapdata ) {
2006-09-25 01:09:00 +00:00
Listener tap = tapdata ;
const gchar * error ;
if ( tap - > draw_ref = = LUA_NOREF ) return ;
2010-10-21 02:50:27 +00:00
2006-09-25 01:09:00 +00:00
lua_pushcfunction ( tap - > L , tap_reset_cb_error_handler ) ;
lua_rawgeti ( tap - > L , LUA_REGISTRYINDEX , tap - > draw_ref ) ;
2010-10-21 02:50:27 +00:00
2006-09-25 01:09:00 +00:00
switch ( lua_pcall ( tap - > L , 0 , 0 , 1 ) ) {
case 0 :
/* OK */
break ;
case LUA_ERRRUN :
error = lua_tostring ( tap - > L , - 1 ) ;
g_warning ( " Runtime error while calling a listener's draw(): %s " , error ) ;
break ;
case LUA_ERRMEM :
g_warning ( " Memory alloc error while calling a listener's draw() " ) ;
break ;
default :
g_assert_not_reached ( ) ;
break ;
}
}
2010-10-21 12:41:15 +00:00
WSLUA_CONSTRUCTOR Listener_new ( lua_State * L ) {
/* Creates a new Listener listener */
2009-05-08 16:40:38 +00:00
# define WSLUA_OPTARG_Listener_new_TAP 1 /* The name of this tap */
# 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) */
2006-09-25 01:09:00 +00:00
const gchar * tap_type = luaL_optstring ( L , WSLUA_OPTARG_Listener_new_TAP , " frame " ) ;
const gchar * filter = luaL_optstring ( L , WSLUA_OPTARG_Listener_new_FILTER , NULL ) ;
2009-06-05 22:42:47 +00:00
Listener tap ;
2006-09-25 01:09:00 +00:00
GString * error ;
tap = g_malloc ( sizeof ( struct _wslua_tap ) ) ;
2010-10-21 02:50:27 +00:00
2009-06-05 22:42:47 +00:00
tap - > name = g_strdup ( tap_type ) ;
2006-09-25 01:09:00 +00:00
tap - > filter = filter ? g_strdup ( filter ) : NULL ;
2006-10-17 18:20:44 +00:00
tap - > extractor = wslua_get_tap_extractor ( tap_type ) ;
2006-09-25 01:09:00 +00:00
tap - > L = L ;
tap - > packet_ref = LUA_NOREF ;
tap - > draw_ref = LUA_NOREF ;
tap - > init_ref = LUA_NOREF ;
2010-10-21 02:50:27 +00:00
2009-06-05 22:42:47 +00:00
/*
* XXX - do all Lua taps require the protocol tree ? If not , it might
* be useful to have a way to indicate whether any do .
*
* XXX - do any Lua taps require the columns ? If so , we either need
* to request them for this tap , or do so if any Lua taps require them .
*/
error = register_tap_listener ( tap_type , tap , tap - > filter , TL_REQUIRES_PROTO_TREE , lua_tap_reset , lua_tap_packet , lua_tap_draw ) ;
2006-09-25 01:09:00 +00:00
if ( error ) {
2009-03-13 22:06:48 +00:00
g_free ( tap - > filter ) ;
2006-09-25 01:09:00 +00:00
g_free ( tap - > name ) ;
g_free ( tap ) ;
2009-06-05 22:42:47 +00:00
/* WSLUA_ERROR(new_tap,"tap registration error"); */
2006-09-25 01:09:00 +00:00
luaL_error ( L , " Error while registering tap: \n %s " , error - > str ) ;
g_string_free ( error , TRUE ) ; /* XXX LEAK? */
}
2010-10-21 02:50:27 +00:00
2006-09-25 01:09:00 +00:00
pushListener ( L , tap ) ;
WSLUA_RETURN ( 1 ) ; /* The newly created Listener listener object */
}
2010-10-21 12:41:15 +00:00
WSLUA_METHOD Listener_remove ( lua_State * L ) {
/* Removes a tap listener */
2006-09-25 01:09:00 +00:00
Listener tap = checkListener ( L , 1 ) ;
2010-10-21 02:50:27 +00:00
2006-09-25 01:09:00 +00:00
if ( ! tap ) return 0 ;
2010-10-21 02:50:27 +00:00
2006-09-25 01:09:00 +00:00
remove_tap_listener ( tap ) ;
2010-10-21 02:50:27 +00:00
2006-09-25 01:09:00 +00:00
return 0 ;
}
2010-10-21 12:41:15 +00:00
WSLUA_METAMETHOD Listener_tostring ( lua_State * L ) {
2006-09-25 01:09:00 +00:00
Listener tap = checkListener ( L , 1 ) ;
gchar * str ;
2010-10-21 02:50:27 +00:00
2006-09-25 01:09:00 +00:00
if ( ! tap ) return 0 ;
2010-10-21 02:50:27 +00:00
2009-06-08 08:02:15 +00:00
str = ep_strdup_printf ( " Listener(%s) filter: %s " , tap - > name , tap - > filter ? tap - > filter : " NONE " ) ;
2006-09-25 01:09:00 +00:00
lua_pushstring ( L , str ) ;
2010-10-21 02:50:27 +00:00
2006-09-25 01:09:00 +00:00
return 1 ;
}
2010-10-21 12:41:15 +00:00
static int Listener_newindex ( lua_State * L ) {
2009-06-05 22:42:47 +00:00
/* WSLUA_ATTRIBUTE Listener_packet WO A function that will be called once every packet matches the Listener listener filter.
2010-10-21 12:41:15 +00:00
function tap . packet ( pinfo , tvb , userdata ) . . . end
*/
2009-06-05 22:42:47 +00:00
/* WSLUA_ATTRIBUTE Listener_draw WO A function that will be called once every few seconds to redraw the gui objects
2010-10-21 12:41:15 +00:00
in tshark this funtion is called oly at the very end of the capture file .
function tap . draw ( userdata ) . . . end
*/
2009-06-05 22:42:47 +00:00
/* WSLUA_ATTRIBUTE Listener_reset WO A function that will be called at the end of the capture run.
2010-10-21 12:41:15 +00:00
function tap . reset ( userdata ) . . . end
*/
2006-09-25 01:09:00 +00:00
Listener tap = shiftListener ( L , 1 ) ;
2010-01-28 15:39:15 +00:00
const gchar * idx = lua_shiftstring ( L , 1 ) ;
2006-09-25 01:09:00 +00:00
int * refp = NULL ;
2010-10-21 02:50:27 +00:00
2010-01-28 15:39:15 +00:00
if ( ! idx ) return 0 ;
2010-10-21 02:50:27 +00:00
2010-01-28 15:39:15 +00:00
if ( g_str_equal ( idx , " packet " ) ) {
2006-09-25 01:09:00 +00:00
refp = & ( tap - > packet_ref ) ;
2010-01-28 15:39:15 +00:00
} else if ( g_str_equal ( idx , " draw " ) ) {
2006-09-25 01:09:00 +00:00
refp = & ( tap - > draw_ref ) ;
2010-01-28 15:39:15 +00:00
} else if ( g_str_equal ( idx , " reset " ) ) {
2006-09-25 01:09:00 +00:00
refp = & ( tap - > init_ref ) ;
} else {
2010-01-28 15:39:15 +00:00
luaL_error ( L , " No such attribute `%s' for a tap " , idx ) ;
2006-09-25 01:09:00 +00:00
return 0 ;
}
2010-10-21 02:50:27 +00:00
2006-09-25 01:09:00 +00:00
if ( ! lua_isfunction ( L , 1 ) ) {
luaL_error ( L , " Listener's attribute `%s' must be a function " ) ;
return 0 ;
}
2010-10-21 02:50:27 +00:00
2006-09-25 01:09:00 +00:00
lua_pushvalue ( L , 1 ) ;
* refp = luaL_ref ( L , LUA_REGISTRYINDEX ) ;
return 0 ;
}
static const luaL_reg Listener_methods [ ] = {
{ " new " , Listener_new } ,
{ " remove " , Listener_remove } ,
2008-04-25 18:59:20 +00:00
{ NULL , NULL }
2006-09-25 01:09:00 +00:00
} ;
static const luaL_reg Listener_meta [ ] = {
{ " __tostring " , Listener_tostring } ,
{ " __newindex " , Listener_newindex } ,
2008-04-25 18:59:20 +00:00
{ NULL , NULL }
2006-09-25 01:09:00 +00:00
} ;
2010-10-21 12:41:15 +00:00
int Listener_register ( lua_State * L ) {
2009-06-05 22:42:47 +00:00
wslua_set_tap_enums ( L ) ;
2006-09-25 01:09:00 +00:00
WSLUA_REGISTER_CLASS ( Listener ) ;
2009-06-05 22:42:47 +00:00
return 1 ;
2006-09-25 01:09:00 +00:00
}