I am trying to write a Lua dissector for some data that comes in the payload of some protocol. Each packet contains some serial data. The data needs to be processed as CR-delimited (0x0D
/\r
) packets, but these don't necessarily line up with the protocol packets.
I'm having a problem where the dissector function does not get called with the left over data from last time if I report that I don't have enough data to parse.
For example, say I have the following protocol packets:
1: 01 02 03 0D
2: 11 12 13
3: 21 22 23 24 0D
Then I have two dissectable sequences: 01 02 03 0D
(the first packet), 11 12 13 21 22 23 24 0D
(packet 2 and packet 3).
My strategy for this is to:
- Work though each packet, looking for the offset of
\r
- If not found:
- Set
desegment_offset = 0
- Set
desegment_len = DESEGMENT_ONE_MORE_SEGMENT
(since I don't know how much data is left) - Return
nil
and try again next packet
- Set
- If found in the middle:
- Set
desegment_offset
to the offset of the newline, so the next packet can get the tail data - Set
desegment_len = DESEGMENT_ONE_MORE_SEGMENT
(since I don't know how much data is left) - Don't return
- Set
- If found at end, leave the desegmentation params alone and carry on - the whole line is one line of data
- If we didn't return, the buffer from 0 to the offset is a whole line of data - parse this
Example:
function myproto.dissector(tvbuf, pinfo, treeitem)
original_dissector:call(tvbuf, pinfo, treeitem)
local endOffset = 0
-- find out if we have any complete chunks
while endOffset < tvbuf:len() do
if tvbuf(endOffset, 1):uint() == 0x0D then
break
end
endOffset = endOffset + 1
end
-- didn't find a complete line in the payload
-- ask for more
if endOffset == tvbuf:len() then
pinfo.desegment_len = DESEGMENT_ONE_MORE_SEGMENT
pinfo.desegment_offset = 0
print(' Incomplete, ask for more')
return
end
-- have more than needed so set offset for next dissection
if tvbuf:len() - 1 > endOffset then
pinfo.desegment_len = DESEGMENT_ONE_MORE_SEGMENT
pinfo.desegment_offset = offset
print(' Too much, leave some for later')
end
print("Whole line dissector:", tvbuf:len())
end
In the example above (payload lengths 4, 3, 5), I get the dissector called with tvbuf
lengths of 4, 3, 5, when I actually expected 4, 3, 8, with the last call containing left-over data from previous packets.
I do hit the "incomplete, return" branch on the second packet, but the third packet never changes.
This isn't happening, what am I doing wrong?
Side note: I am aware the method above won't work in cases like multiple \r
per line, but I think it's simpler to lay it out like this for this question.