| 1 | initial version |
For the header protocol, you're creating the DissectorTable but you're not saving the return value or doing anything with it. Your dissector table also appears to be based on a port number, which is a 16-bit value, so you should explicitly specify that as the type. If it is in fact a port number, then I find myself questioning why there are 2 different protocols involved here at all, but I'll assume there's a good reason you're doing this. Besides the problems with the subdissector table:
<protocol>.<field> naming convention.ProtoField.uint function. Since both fields of the header are 1 byte, you should be using ProtoField.uint8 instead.As for the subdissector, apart from the same problems with filter names and ProtoField.uint, which should be ProtoField.uint32 in this case, there's nothing else that needs to change.
Below are some modified code samples that should help.
First, the header: There are at least 2 ways to call the subdissector and I've illustrated both. You can even try out either method by changing the "Subdissection Method" preference.
myHeaderProtocol = Proto.new("myHeader", "My Custom Header Protocol")
-- Define protocol fields
local pf = {
headerId = ProtoField.uint8("myHeader.headerId", "headerId", base.DEC),
numMessages = ProtoField.uint8("myHeader.numMessages", "numMessages", base.DEC)
}
myHeaderProtocol.fields = pf
local myCustomTable = DissectorTable.new("MyCustomTable", "MyCustomTable", ftypes.UINT16, base.DEC)
-- Preferences
local METHOD_TRY = 1
local METHOD_CALL = 2
local methods_table = {
{1, "Try", METHOD_TRY},
{2, "Call", METHOD_CALL}
}
local default_prefs = {
subdissectionMethod = METHOD_TRY
}
myHeaderProtocol.prefs.subdissection_method = Pref.enum("Subdissection Method",
default_prefs.subdissectionMethod,
"The subdissection method as \"try\" or \"call\".",
methods_table,
false
)
function myHeaderProtocol.dissector(buffer, pinfo, tree)
pinfo.cols.protocol = myHeaderProtocol.name
local subtree = tree:add(myHeaderProtocol,buffer(), "Header Tree")
subtree:add(pf.headerId, buffer(0, 1))
subtree:add(pf.numMessages, buffer(1, 1))
local numMessages = buffer(1, 1):uint()
local offset = 2
if myHeaderProtocol.prefs.subdissection_method == METHOD_TRY then
--[[
This method will use dissectortable:try().
Note that we must still check if there's a subdissector
registered; otherwise the data dissector will be called for us
automatically if there isn't a registered dissector, and we don't
want that.
--]]
local port
if myCustomTable:get_dissector(pinfo.src_port) ~= nil then
port = pinfo.src_port
--pinfo.cols.info:append(" Source Port Match")
elseif myCustomTable:get_dissector(pinfo.dst_port) ~= nil then
port = pinfo.dst_port
--pinfo.cols.info:append(" Destination Port Match")
else
return
end
while numMessages > 0 do
myCustomTable:try(port, buffer(offset, 4):tvb(), pinfo, tree)
offset = offset + 4
numMessages = numMessages - 1
end
elseif myHeaderProtocol.prefs.subdissection_method == METHOD_CALL then
--[[
This method will call the subdissector directly if a handle is
successfully found in the subdissector table.
--]]
local subdissector_handle = myCustomTable:get_dissector(pinfo.src_port)
if subdissector_handle == nil then
subdissector_handle = myCustomTable:get_dissector(pinfo.dst_port)
end
if subdissector_handle ~= nil then
while numMessages > 0 do
subdissector_handle:call(buffer(offset, 4):tvb(), pinfo, tree)
offset = offset + 4
numMessages = numMessages - 1
end
end
end
end
tcp_table = DissectorTable.get("tcp.port")
tcp_table:add(5678, myHeaderProtocol)
And the subdissector:
mySubDissector = Proto.new("mySubDissector", "My Sub Dissector")
local pf = {
myMessage = ProtoField.uint32("mySubDissector.Message", "Message", base.HEX)
}
mySubDissector.fields = pf
function mySubDissector.init()
DissectorTable.get("MyCustomTable"):add(5678, mySubDissector)
end
function mySubDissector.dissector(buffer, pinfo, tree)
pinfo.cols.protocol = mySubDissector.name
local subtree = tree:add(mySubDissector, buffer(), "Message SubTree")
subtree:add(pf.myMessage, buffer(0, 4))
end