First time here? Check out the FAQ!
THIS IS A TEST INSTANCE. Feel free to ask and answer questions, but take care to avoid triggering too many notifications.
0

How to handle 6 byte unsigned integer field in lua dissector?

  • retag add tags

Certain exchange protocols have started sending their timestamp fields as a 6 byte unsigned integer. The field data contains nanoseconds since midnight. If I promote this value to a uint64 via:

local range = buffer(offset, 6)
local value = range:uint64()
local display = "Timestamp"..value

parent:add(fields.timestamp, range, value, display)

I get:

Lua Error: [...]:370: calling 'add' on bad self (string expected, got userdata)

Is there a way to use the internal field parsers to handle 6 bytes as an integer? Do I need to write a custom function for this data?

Omi's avatar
3
Omi
asked 2019-01-07 04:56:59 +0000, updated 2019-01-07 18:59:02 +0000
edit flag offensive 0 remove flag close merge delete

Comments

Note: this displays the correct value but converts to a string:

local range = buffer(offset, 6)
local value = tostring(UInt64.fromhex("0000"..range))
local display = "Timestamp"..value

parent:add(fields.timestamp, range, value, display)
Omi's avatar Omi (2019-01-07 05:20:08 +0000) edit

Caution, I only know enough Lua to be dangerous, but can't you use a tvbrange:uint64() with the 6 byte range, to retrieve the value into a uint64 variable. e.g.

local timeRange = buffer(offset, 6)
local nanosecs = timeRange:uint64()
grahamb's avatar grahamb (2019-01-07 14:10:40 +0000) edit

Thanks for taking a look, I added the original script that caused the error. Your suggestion was my original line of thought.

Omi's avatar Omi (2019-01-07 16:45:39 +0000) edit

You have a "::" on the range object, have you tried a single ":"?

grahamb's avatar grahamb (2019-01-07 18:39:35 +0000) edit

I was copying from memory since this source is on a branch on my home cpu. :: was because my fingers know c++. I updated the example. Thanks.

Omi's avatar Omi (2019-01-07 19:00:42 +0000) edit
add a comment see more comments

1 Answer

0

Below is a working example of adding a 64-bit value to a tree, as well as grabbing the 64-bit value to do something else with it - in this case, adding it to the Info column:

-- Protocol
local p_foo = Proto("foo", "FOO Protocol")

-- Fields
local f_foo_val8 = ProtoField.uint8("foo.val8", "Value 8", base.OCT)
local f_foo_val64 = ProtoField.uint64("foo.val16", "Value 64", base.DEC)

p_foo.fields = { f_foo_val8, f_foo_val64 }

-- Dissection
function p_foo.dissector(buf, pinfo, tree)
    local foo_tree = tree:add(p_foo, buf(0,-1))
    local val64

    pinfo.cols.protocol:set("FOO")

    foo_tree:add(f_foo_val8, buf(0, 1))
    foo_tree:add(f_foo_val64, buf(1, 6))
    val64 = buf(1, 6):uint64()
    pinfo.cols.info:set("Value 64: " .. val64)
end

-- Registration
local udp_table = DissectorTable.get("udp.port")
udp_table:add(33333, p_foo)

You can use the foo.pcapng file I uploaded to cloudshark long ago to test this if you wish.

cmaynard's avatar
11.1k
cmaynard
answered 2019-01-07 19:57:50 +0000
edit flag offensive 0 remove flag delete link

Comments

Thanks. My script example might already be right... hardest bug to find. Your example reminded me that parent:add is using a declared ProtoField. The issue might be there.

 fields.timestamp = ProtoField.new("Timestamp", "timestamp", ftypes.BYTES)

I will take another swing tonight.

Omi's avatar Omi (2019-01-07 20:11:58 +0000) edit

So it appears your issue wasn't with extracting the 6 byte value as a uint64, but rather adding it to the tree.

grahamb's avatar grahamb (2019-01-08 07:50:58 +0000) edit
add a comment see more comments

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account. This space is reserved only for answers. If you would like to engage in a discussion, please instead post a comment under the question or an answer that you would like to discuss.

Add Answer