I have a Lua Wireshark dissector that is structured like so:
-- Initialize Protocol
-- Initialize Protocol Fields
-- Register Protocol Fields
-- DissectionFunction(tvbuf, pktinfo, root)
-- Initialize Protocol
-- Function definitions.
I have a function written that I'd like to use to calculate some values, and then use those values in the dissector. So I wrote my function outside the dissection function and in the function definitions section.
But the function call also works within the dissector function, if called outside the dissector function Wireshark does not recognize it. Calling it in the dissection function is very inefficient, as it only needs to be executed once and will be executed for every frame instead.
Is there a way to call it once outside the dissection function?
I'm not quite sure of what the question is, but you can do the following in Lua
local function calculate_constant_value()
return a * b + c
end
local my_constant_value = calculate_constant_value()
function proto.dissector()
-- use my_constant_value here
end
Related
I'm still ramping up in lua, and I am not quite familiar with this syntax. What is happening when you pass in a function as a parameter like below?
Comm.setRouting(function(url)
for i = 1,4 do
local portIndex = "Path"..i
if url:match(portConfig[portIndex]) ~= nil then
return Comm.slots()[1], Comm.groups()[i]
end
end
end)
The other answers are correct, but it might help you if you wrote your own function that calls another function:
function CallAFunction(func_to_call)
func_to_call()
end
You could pass a named function (an anonymous function assigned to a variable) or an anonymous function written on the fly.
function SayHello()
print("Hello!")
end
--[[
^This is equivalent to:
SayHello = function()
print("Hello!")
end
]]--
CallAFunction(SayHello)
CallAFunction(function()
print("Goodbye!")
end)
output:
Hello!
Goodbye!
and this can be done with parameters
function CallAFunction(func)
func("Bonjour")
end
CallAFunction(function(parameter)
print(parameter)
end)
Here, func is the anonymous function, which accepts 1 parameter parameter.
When you call func("Bonjour") you are passing Bonjour as parameter, like a normal function call.
Here you're passing an argument to setRouting that is an "anonymous function"
Functions are first-class values in Lua and can be stored in local variables, global variables and table fields. Here the function is being passed anonymously on the call stack to the setRouting function.
setRouting would be called a "higher-order function" because it accepts a function as its input.
The following page has some more information about functions in Lua:
https://www.lua.org/pil/6.html
A couple of things are happening in this example:
You're passing a function as a parameter. The callee (e.g. setRouting()) can invoke that function. This is often referred to as a callback function.
You're defining the function itself, on-the-fly. This is an example of an "anonymous function", or a lambda function.
I'm writing a chained dissector in Lua for the Ethercat protocol. I named my chained dissector littlecat.
For what I have so far, littlecat correctly dissects the fields I want it to. However, instead of executing after the built in ecat dissector, littlecat takes it over completely.
This is what the registration at the end of my Lua code looks like.
-- Initialize Protocol
function littlecat.init()
end
-- Register Chained Dissector Ethercat Port
local ethercat_dissector_table = DissectorTable.get("ecatf.type")
dissector = ethercat_dissector_table:get_dissector(1)
-- Dissector can be called from littlecat.dissector
-- So the previous dissector gets called
ethercat_dissector_table:add(1, littlecat)
How can I have my dissector execute after ecat has been executed?
I found a solution.
To ensure that the default dissector is called, and then the custom dissector:
Define the dissector table and original dissector before the dissection function.
Call original dissector within the dissection function.
Example
-- Initialize Protocol
-- Initialize Protocol Fields
-- Define dissector table and default dissector here
-- so they can be called within the dissection func.
local dissector_table = DissectorTable.get("shortname")
dissector = dissector_table:get_dissector(PORT)
-- Dissection Function
function dissectorname.dissector (tvbuf, pktinfo, root)
-- Call default dissector.
dissector(tvbuf, pktinfo, root)
-- Continue dissection....
end
-- Initialize Protocol
function dissectorname.init()
end
-- Dissector can be called from dissectorname.dissector
-- So the previous dissector gets called
dissector_table:add(PORT, dissectorname)
I found very useful example of heuristic tables usage in Lua.
a link
But it doesn't not cover my case.
I've written custom dissector in lua. Described custom protocol has many subprotos. So I create new subdissectors table DissectorTable.new() and register new subprotos.
But some of subprotocols doesn't have identification sign and their types must be found out dynamically.
I hoped to register heuristic dissector with proto:register_heuristic() method, but there is no my new table in DissectorTable.heuristic_list() list.
Creating new dissector table does not create heuristic dissectors table.
Is there a way to create new own heuristic dissectors table?
There is no way to create a real heuristic dissector table for your protocol in the current Lua API, but I'm not sure it makes a lot of sense to have such a thing. The purpose of having a protocol create a heuristic dissector table for itself is so that other protocols can register their heuristic dissectors into it - for example the UDP protocol creates a heuristic dissector table named "udp", so that other protocols like RTP, STUN, Skype, etc., can all register their heuristic dissectors into it, and UDP can try them all without knowing about them before-hand.
But when you create a new protocol in a Lua plugin, no other code is going to know about your new protocol or any heuristic dissector table you create. Only your own Lua code will know about it. Obviously your new protocol might have subprotocols that need to be tried heuristically, as you appear to need, but you don't need a heuristic dissector table to do that - just call your subprotocols's heuristic dissector functions directly in Lua.
For example:
local myProto = Proto("myproto", "My Main Protocol")
local mySubproto1 = Proto("mysubproto1", "My First Sub-Protocol")
local mySubproto2 = Proto("mysubproto2", "My Second Sub-Protocol")
-- the sub-prpotocol's heuristic function
-- returns true if the packet is its protocol and it dissected it
-- otherwise returns false
function heur_dissect_mySubproto1(tvbuf, pktinfo, root)
-- see if the passed in tvb is Subproto1 protocol
-- and if so then add tree items and such or
-- call mySubproto1's normal dissector function to do that stuff
return is_Subproto1
end
function heur_dissect_mySubproto2(tvbuf, pktinfo, root)
-- see if the passed in tvb is Subproto2 protocol
return is_Subproto2
end
function myProto.dissector(tvbuf, pktinfo, root)
-- do stuff for my main protocol
-- create a new sub-tvb of what has not been processed by the main protocol
local newTvb = tvbuf(bytes_parsed_by_myproto):tvb()
-- call the heuristic dissector functions of my sub protocols
-- with the portion of the tvb that belongs to them
if heur_dissect_mySubproto1(newTvb, pktinfo, root) then
-- do here anything you need to afterwards
elseif heur_dissect_mySubproto2(newTvb, pktinfo, root) then
-- do here anything you need to afterwards
end
end
or if you want to be fancier, use a table of your own...
local myProto = Proto("myproto", "My Main Protocol")
local mySubproto1 = Proto("mysubproto1", "My First Sub-Protocol")
local mySubproto2 = Proto("mysubproto2", "My Second Sub-Protocol")
-- a heuristic dissector table for myProto
local myProto_heuristic_table = {}
-- a function to register into myProto's heuristic table
local function register_heuristic(func)
myProto_heuristic_table[#myProto_heuristic_table + 1] = func
end
function heur_dissect_mySubproto1(tvbuf, pktinfo, root)
-- do stuff
return is_Subproto1
end
-- "register" the above function
register_heuristic(heur_dissect_mySubproto1)
function heur_dissect_mySubproto2(tvbuf, pktinfo, root)
-- do stuff
return is_Subproto2
end
register_heuristic(heur_dissect_mySubproto2)
function myProto.dissector(tvbuf, pktinfo, root)
-- do stuff for my main protocol
local newTvb = tvbuf(bytes_parsed_by_myproto):tvb()
-- call the heuristic dissector functions of my sub protocols
-- with the portion of the tvb that belongs to them
for _, func in ipairs(myProto_heuristic_table) do
-- call the heuristic
if func(newTvb, pktinfo, root) then
-- do here anything you need to afterwards
return
end
end
end
What is the syntax to create the function, but then add it's implementation further down in code?
So roughly like this:
Define function doX
Call doX (further down in the code)
doX implemention (i.e. all functions down at the bottom of the file)
You only need to have a variable to reference. local funcName is sufficient for your purposes with one caveat. This will work:
local funcName
function callIt()
print(funcName())
end
function defineIt()
funcName = function() return "My Function" end
end
defineIt()
callIt()
As long as you define it (defineIt) before you call it (callIt), it should work as expected. You can't do something like this though (and this is the caveat):
local funcName
print(funcName())
funcName = function() return "My Function" end
You will get an error: attempt to call local 'funcName' (a nil value).
oh...so there's really no way to call funcName prior to having actually defined the function then? i.e. you still need to make sure defineIt is called before your first call to funcName itself?
I wanted to clarify this point, and I felt that an answer would be the better way than a comment.
Lua is a much simpler language than C or C++. It is built on some simple foundations, with some syntactic sugar to make parts of it easier to swallow.
There is no such thing as a "function definition" in Lua. Functions are first-class objects. They are values in Lua, just like the number 28 or the string literal "foo" are values. A "function definition" simply sets a value (namely, the function) into a variable. Variables can contain any kind of value, including a function value.
All a "function call" is is taking the value from a variable and attempting to call it. If that value is a function, then the function gets called with the given parameters. If that value is not a function (or a table/userdata with a __call metamethod), then you get a runtime error.
You can no more call a function that hasn't been set in a variable yet than you can do this:
local number = nil
local addition = number + 5
number = 20
And expect addition to have 25 in it. That's not going to happen. And thus, for the same reason, you can't do this:
local func = nil
func(50)
func = function() ... end
As Paul pointed out, you can call a function from within another function you define. But you cannot execute the function that calls it until you've filled in that variable with what it needs to contain.
As others have written, you cannot call a function at runtime that has not been assigned prior to the call. You have to understand that:
function myFunc() print('Something') end
Is just a syntax sugar for this:
myFunc = function() print('Something') end
Now, it makes sense that this kind of code would not work the way you want it to:
print(greeter(io.read())) -- attempt to call global 'greeter' (a nil value)
function greeter(name) return 'Hello '..name end
When you use the greeter variable, its value is nil, because its value is set only on the next line.
But if you want to have your "main" program on the top and the functions at the bottom, there is simple way to achieve this: create a "main" function and call it as the last thing on the bottom. By the time the function is called, all the functions will be set to the corresponding global variables:
-- start of program, your main code at the top of source code
function main()
local name = readName()
local message = greeter(name)
print(message)
end
-- define the functions below main, but main is not called yet,
-- so there will be no errors
function readName() io.write('Your name? '); return io.read() end
function greeter(name) return 'Hello, ' .. name end
-- call main here, all the functions have been assigned,
-- so this will run without any problems
main()
How do I call a function that needs to be called from above its creation? I read something about forward declarations, but Google isn't being helpful in this case. What is the correct syntax for this?
Lua is a dynamic language and functions are just a kind of value that can be called with the () operator. So you don't really need to forward declare the function so much as make sure that the variable in scope when you call it is the variable you think it is.
This is not an issue at all for global variables containing functions, since the global environment is the default place to look to resolve a variable name. For local functions, however, you need to make sure the local variable is already in scope at the lexical point where you need to call the value it stores, and also make sure that at run time it is really holding a value that can be called.
For example, here is a pair of mutually recursive local functions:
local a,b
a = function() return b() end
b = function() return a() end
Of course, that is also an example of using tail calls to allow infinite recursion that does nothing, but the point here is the declarations. By declaring the variables with local before either has a function stored in it, those names are known to be local variables in lexical scope of the rest of the example. Then the two functions are stored, each referring to the other variable.
You can forward declare a function by declaring its name before declaring the actual function body:
local func1
local func2 = function()
func1()
end
func1 = function()
--do something
end
However forward declarations are only necessary when declaring functions with local scope. That is generally what you want to do, but Lua also supports a syntax more like C, in which case forward declaration is not necessary:
function func2()
func1()
end
function func1()
--do something
end
Testing under the embedded lua in Freeswitch, forward declaration does not work:
fmsg("CRIT", "It worked.")
function fmsg(infotype, msg)
freeswitch.consoleLog(infotype, msg .. "\n")
end
result:
[ERR] mod_lua.cpp:203 /usr/local/freeswitch/scripts/foo.lua:1: attempt to call global 'fmsg' (a nil value)
Reversing the order does (duh) work.
To comprehend how forward referencing in Lua works compared to C, you must understand the a fundamental difference between C compilation and the Lua execution.
In C, forward referencing is a compile time mechanism. Hence if you include a forward declaration template in a C module then any of your code following will employ this template in compiling the call. You may or may not include the function implementation in the same module, in which case both declarations must be semantically identical or the compiler will error. Since this is a compile time construct, the compiled code can be executed in any order.
In Lua, forward referencing is runtime mechanism, in that the compiled function generates a function prototype internally within the code, but this is only accessible as a runtime Lua variable or value after the execution has
passed over the declaration creating a Lua closure. Here the declaration order within the source is immaterial. It is the execution order that is important: if the closure hasn't been bound to the variable yet, then the execution will throw a "nil value" exception.If you are using a local variable to hold the function value, then normal local scoping rules still apply: the local declaration must precede its use in the source and must be within scope, otherwise the compiler will compile in the wrong global or outer local reference. So forward referencing using locals as discussed in other answer will work, but only if the Protos are bound to closures before the first call is executed.
Doesn't work for me if I try to call the function before definition. I am using this Lua script in nginx conf.
lua entry thread aborted: runtime error: lua_redirect.lua:109: attempt to call global 'throwErrorIfAny' (a nil value)
Code snippet -
...
throwErrorIfAny()
...
function throwErrorIfAny()
ngx.say("request not allowed")
ngx.exit(ngx.HTTP_OK)
end
Given some other answers have also pointed out that it didn't work for them either, it is possible that forward declaration of Lua doesn't work with other tools.
PS : It works fine if I put the function definition before and then call it after wards.
If you use OOP you can call any function member prior its "definition".
local myClass = {}
local myClass_mt = { __index = myClass }
local function f1 (self)
print("f1")
self:later() --not yet "delared" local function
end
local function f2 (self)
print("f2")
self:later() --not yet "declared" local function
end
--...
--later in your source declare the "later" function:
local function later (self)
print("later")
end
function myClass.new() -- constructor
local this = {}
this = {
f1 = f1,
f2 = f2,
later = later, --you can access the "later" function through "self"
}
setmetatable(this, myClass_mt)
return this
end
local instance = myClass.new()
instance:f1()
instance:f2()
Program output:
f1
later
f2
later