[LUA] How to get a field from a decoded protobuf to decode the next protobuf
I'm trying to create a protocol dissector in lua, but I can't find a way to get the data from a previously decoded protobuf to decode the next one within the same request.
I have a TCP protocol where a request contains the following data:
- total length -> 32bit int, total length of the message
- src -> 16bytes, identifier of sender
- dst -> 16bytes, identifier of destination
- header length -> 16bit, length of header message
- header -> header message (protobuf)
- message -> message (protobuf)
The operation
message is always of the same message-type. This contains a type
field that I have to read to know the type of the message
message.
Is there a way to fetch the type from the first disector call so i can map this type to the correct version that I can then put in the pinfo.private["pb_msg_type"]
field?
The lua code is based on the protobuf example.
do
local protobuf_dissector = Dissector.get("protobuf")
local function create_protobuf_dissector(name, desc)
local proto = Proto(name, desc)
local f_len = ProtoField.uint32(name .. ".length", "Message length", base.DEC)
local f_src = ProtoField.bytes(name .. ".src", "Source", base.NONE)
local f_dst = ProtoField.bytes(name .. ".dst", "Destination", base.NONE)
local f_oplen = ProtoField.uint32(name .. ".oplength", "Operation length", base.DEC)
proto.fields = { f_len, f_src, f_dst, f_oplen }
proto.dissector = function(tvb, pinfo, tree)
local subtree = tree:add(proto, tvb())
-- Only process TCP packets
if pinfo.port_type == 2 then
local offset = 0
local remaining_len = tvb:len()
while remaining_len > 0 do
if remaining_len < 4 then
-- head not enough
pinfo.desegment_offset = offset
pinfo.desegment_len = DESEGMENT_ONE_MORE_SEGMENT
return -1
end
local data_len = tvb(offset, 4):uint()
if remaining_len - 4 < data_len then
-- data not enough
pinfo.desegment_offset = offset
pinfo.desegment_len = data_len - (remaining_len - 4)
return -1
end
subtree:add(f_len, tvb(offset, 4))
subtree:add(f_src, tvb(offset + 4, 16))
subtree:add(f_dst, tvb(offset + 20, 16))
-- Process header
pinfo.private["pb_msg_type"] = "message,GatewayOperation"
subtree:add(f_oplen, tvb(offset + 36, 2))
local op_len = tvb(offset + 36, 2):uint()
pcall(Dissector.call, protobuf_dissector, tvb(offset + 38, op_len):tvb(), pinfo, subtree)
-- todo: extract type from 1st message and apply mapping to define the type of the 2nd message
-- Process message
pinfo.private["pb_msg_type"] = "message,VersionConfirm"
pcall(Dissector.call, protobuf_dissector, tvb(offset + 38 + op_len):tvb(), pinfo, subtree)
offset = offset + 40 + data_len
remaining_len = remaining_len - 4 - data_len
end
end
pinfo.columns.protocol:set(name)
end
DissectorTable.get("tcp.port"):add(0, proto)
return proto
end
create_protobuf_dissector("Zehnder", "Zehnder Comfoconnect")
end