1 | initial version |
Here I provide an alternate solution that:
"eth:ethertype:ip:udp:child:parent"
problemThis solution relies on the ability of the parent protocol to heuristically determine if the UDP payload handed to it is for the parent dissector or not.
Parent:
local p_parent = Proto("parent", "Parent Protocol")
local child_table = DissectorTable.new("parent.port", "parent.port", ftypes.UINT32, base.DEC, p_parent)
local data_dissector = Dissector.get("data")
-- Fields
local pf = {
field1 = ProtoField.foo("parent.field1", "Field1", base.FOO),
field2 = ProtoField.foo("parent.field2", "Field2", base.FOO),
...
fieldN = ProtoField.foo("parent.fieldN", "FieldN", base.FOO)
}
p_parent.fields = pf
-- Dissection
local function dissect_parent(tvbuf, pinfo, tree)
if tvbuf:len() < PARENT_LENGTH then
return false
end
if -- Any other parent criteria fails
return false
end
-- Assume this packet is for the parent
local parent_tree = tree:add(p_parent, tvbuf(0, PARENT_LENGTH))
local offset = 0
pinfo.cols.protocol:set("Parent")
parent_tree:add(pf.field1, tvbuf(offset, FIELD1_LENGTH))
offset = offset + FIELD1_LENGTH
parent_tree:add(pf.length, tvbuf(offset, FIELD2_LENGTH))
...
offset = offset + FIELD(N-1)_LENGTH
parent_tree:add(pf.length, tvbuf(offset, FIELDN_LENGTH))
-- Hand off remainder to child:
local tvb_sub = tvbuf:range(PARENT_LENGTH, -1):tvb()
local child
child = child_table:get_dissector(pinfo.src_port)
if child ~= nil then
child(tvb_sub, pinfo, tree)
else
child = child_table:get_dissector(pinfo.dst_port)
if child ~= nil then
child(tvb_sub, pinfo, tree)
else
-- No child registered for this port so hand off to generic data dissector
data_dissector:call(tvb_sub, pinfo, tree)
end
end
return true
end
function p_parent.dissector(tvbuf, pinfo, tree)
dissect_parent(tvbuf, pinfo, tree)
end
p_parent:register_heuristic("udp", dissect_parent)
end
Child1:
-- Protocol
local p_child1 = Proto("child1", "Child1 Protocol")
-- Fields
local pf = {
field1 = ProtoField.foo("child1.field1", "Field1", base.FOO),
field2 = ProtoField.foo("child1.field2", "Field2", base.FOO),
...
fieldN = ProtoField.foo("child1.fieldN", "FieldN", base.FOO)
}
p_child1.fields = pf
function p_child1.init()
DissectorTable.get("parent.port"):add(CHILD1_PORT, p_child1)
end
-- Dissection
function p_child1.dissector(tvbuf, pinfo, tree)
pinfo.cols.protocol:set("Child1")
local child1_tree = tree:add(p_child1, tvbuf(0, -1))
local offset = 0
child1_tree:add(pf.field1, tvbuf(offset, FIELD1_LENGTH))
offset = offset + FIELD1_LENGTH
child1_tree:add(pf.field2, tvbuf(offset, FIELD2_LENGTH))
...
offset = offset + FIELD(N-1)_LENGTH
child1_tree:add(pf.fieldN, tvbuf(offset, FIELDN_LENGTH))
end
And so on for Child2 ... ChildN.