Wireshark-users: [Wireshark-users] A Working Lua Tap Example
From: Leonard Nielsen <
leonard.nielsen@xxxxxxxxxxxx>
Date: Wed, 1 Nov 2006 08:58:34 -0600
This is my first functional Lua script. Many of the examples on this site
do not work with the current version so I hope this will help others who
want to try Lua. This script creates a CSV file with any HTTP or TDS-RPC
request that takes over x seconds (x is currently set to 20 seconds). I am
using this to identify which MS-SQL stored procedure is causing which web
page to time-out.
The http tap was fairly straight forward but the tds tap is a real hack.
tds_type extractor was returning a "userdata" value instead of an integer
and the TDS dissector does not create fields with the RPC name or
parameters. I need to find out how to access the reassembled PDU with the
tvb function instead of the packet data.
One feature I would like see added to Wireshark's Lua is Unicode string
support. Here is a link to a web page where Lua Unicode support is working
http://www.workspacewhiz.com/Other/LuaState/LuaState.html
Is anyone working on improving the tds dissector? It seems like freetds.org
has all of the information needed to decode the parameters.
Thanks for making Lua available. It really enhances the functionality of
Wireshark.
-- Lua Response Time Monitor
--
-- Logs slow response times for HTTP and MS-SQL RPCs
-- Turn off TCP reassembly of pdu for the TDS tap
trigger = 20 -- log requests that take more that trigger seconds
logfile = "wb"..os.date("%Y%m%d")..".csv"
io.output(logfile)
io.write("Timestamp,Protocol,Session,Request,Info,Duration\n")
-- Define the field extractors that will be used
ip_addr_extractor = Field.new("ip.addr")
tcp_port_extractor = Field.new("tcp.port")
http_request_extractor = Field.new("http.request")
http_uri_extractor = Field.new("http.request.uri")
http_method_extractor = Field.new("http.request.method")
http_code_extractor = Field.new("http.response.code")
-- HTTP Processing
http = Tap.new("http","http.request || http.response");
http_reqs = {} -- outstanding http requests
http_start = {} -- http request timestamp
function http.reset()
http_reqs = {}
http_start = {}
end
function http.packet(pinfo)
local ip_src, ip_dst = ip_addr_extractor()
local tcp_src, tcp_dst = tcp_port_extractor()
local http_request = http_request_extractor()
local http_method = http_method_extractor()
local http_uri = http_uri_extractor()
local http_code = http_code_extractor()
local conv_key, timestamp
if http_request then
conv_key = tostring(ip_dst) .. ":" .. tostring(tcp_dst) .. " " ..
tostring(ip_src) .. ":" .. tostring(tcp_src)
http_reqs[conv_key] = tostring(http_method).."
"..tostring(http_uri)
http_start[conv_key] = pinfo.abs_ts
else
conv_key = tostring(ip_src) .. ":" .. tostring(tcp_src) .. " " ..
tostring(ip_dst) .. ":" .. tostring(tcp_dst)
if http_reqs[conv_key] then
if pinfo.abs_ts - http_start[conv_key]>trigger then
timestamp = os.date("%c",http_start[conv_key]) .. "." ..
string.sub(tostring(http_start[conv_key] -
math.floor(http_start[conv_key])),3,5)
io.write(timestamp,",HTTP,",conv_key,",",http_reqs[conv_key],",",tostring(http_code),",",tostring(pinfo.abs_ts
- http_start[conv_key]),"\n")
end
if tostring(http_code) ~= "100" then
http_reqs[conv_key] = nil
http_start[conv_key] = nil
end
end
end
return true
end
-- TDS (MS-SQL RPC) Processing
tds = Tap.new("tds","tds.type == 0x03 || tds.type == 0x04");
tds_reqs = {} -- outstanding tds requests
tds_start = {} -- tds request timestamp
function tds.reset()
tds_reqs = {}
tds_start = {}
end
function tds.packet(pinfo,tvb)
local ip_src, ip_dst = ip_addr_extractor()
local tcp_src, tcp_dst = tcp_port_extractor()
local conv_key, timestamp
local tds_rpclen, tds_rpcname
local i
tds_type = tvb(54,1):uint()
if tds_type == 3 then
tds_rpclen = 64 + 2 * tvb(62,2):le_uint()
tds_rpcname = ""
for i = 64, tds_rpclen, 2 do
tds_rpcname = tds_rpcname .. tvb(i,1):string()
end
conv_key = tostring(ip_dst) .. ":" .. tostring(tcp_dst) .. " " ..
tostring(ip_src) .. ":" .. tostring(tcp_src)
tds_reqs[conv_key] = tds_rpcname
tds_start[conv_key] = pinfo.abs_ts
else
conv_key = tostring(ip_src) .. ":" .. tostring(tcp_src) .. " " ..
tostring(ip_dst) .. ":" .. tostring(tcp_dst)
if tds_reqs[conv_key] then
if pinfo.abs_ts - tds_start[conv_key]>trigger then
timestamp = os.date("%c",tds_start[conv_key]) .. "." ..
string.sub(tostring(tds_start[conv_key] -
math.floor(tds_start[conv_key])),3,5)
io.write(timestamp,",TDS,",conv_key,",",tds_reqs[conv_key],",Parms,",tostring(pinfo.abs_ts
- tds_start[conv_key]),"\n")
end
tds_reqs[conv_key] = nil
tds_start[conv_key] = nil
end
end
return true
end
******************* PLEASE NOTE *******************
This E-Mail/telefax message and any documents accompanying this
transmission may contain privileged and/or confidential information and is
intended solely for the addressee(s) named above. If you are not the
intended addressee/recipient, you are hereby notified that any use of,
disclosure, copying, distribution, or reliance on the contents of this
E-Mail/telefax information is strictly prohibited and may result in legal
action against you. Please reply to the sender advising of the error in
transmission and immediately delete/destroy the message and any
accompanying documents. Thank you.