Lua: populate a field from DissectorTable

asked 2020-10-18 14:28:55 +0000

dottedmag gravatar image

updated 2020-10-18 14:29:19 +0000

I'm dissecting a protocol where one of fields specifies the request kind. Dissectors for request kinds are registered in a DissectorTable:

-- proto.lua
local kinds_table = DissectorTable.new("proto.request_kind", "Proto Requests", ftypes.UINT8)

-- proto_kindA.lua
local kindA = Proto("PROTO-A", "Protocol Request Kind A")
func kindA.init()
    DissectorTable.get("proto.request_kind"):set(0x55, kindA)
end

Main dissector then uses

kinds_table:try(kind, cmd:tvb(), pinfo, tree)

to render the subprotocol.

Everything is fine except the "kind" field in the protocol: it would be very useful to populate it with the name of the protocol. How do I get it from kinds_table or in some other way?

I could keep a map of kinds in the main file, though it's error-prone: there are 6 tables for kinds, each containing ~200 entries, so I hope there is a better way to do so.

edit retag flag offensive close merge delete

Comments

I'm struggling to understand exactly what you're hoping to do. Could you elaborate a bit more and maybe even provide some sample code of what you'd like to do?

cmaynard gravatar imagecmaynard ( 2020-10-23 04:15:31 +0000 )edit

I'm trying to do what Wireshark does in dissecting, say, decoding Protocol field in IP. IP dissector delegates to a ip.proto table.

Is it possible to fill a field similar to IP Protocol without having a list of all possible protocols hardcoded in the parent dissector? The name of the protocol is in the DissectorTable, the only question is how to get it out.

dottedmag gravatar imagedottedmag ( 2020-10-23 11:33:36 +0000 )edit

I think I understand now.

I'm not sure how you could get the name from the proto; however, it might be possible to do something like so? (NOTE: This is all untested.)

  • Create a new file such as kind_name.lua that initially has an empty kind_name_vals lookup table, as in:

    kind_name_vals = {}
  • In each subdissector file, add a line to pull in that file:

    require("kind_name")
  • During each subdissector initialization, add the particular kind entry to the table:

    kind_name_vals[0x55] = "PROTO-A"
  • Abuse the return value of the subdissector and instead of each subdissector returning the number of bytes dissected, it could return the kind value, e.g., 0x55 for "PROTO-A".

  • Finally, in the main dissector, if the kinds_table:try() returns a value greater than 0, use it to look up the name in the kind_name_vals table and add it or append it to the kind tree item.

This approach wouldn ...(more)

cmaynard gravatar imagecmaynard ( 2020-10-23 15:39:00 +0000 )edit

Actually, it seems pinfo.private isn't read-only at all. I guess I don't understand what affect WSLUA_ATTRIBUTE_ROREG() does, but perhaps it should be changed to WSLUA_ATTRIBUTE_RWREG() for this field. See wslua_pinfo.c.

Ref: https://ask.wireshark.org/question/10...

In any case, I just tried it in my own Lua dissectors and it seems to work just fine. In the subdissector, I set pinfo.private.name = "FOO", and then in the calling dissector, I just added a quick block of code to test it:

    if pinfo.private.name ~= nil then
        print("pinfo.private.name = " .. pinfo.private.name)
    end

In the Lua console, the following was printed:

10/23/2020 1:11:22 PM pinfo.private.name = FOO

I still don't know if this helps in your particular case but this might be an easier way to pass the kind name information from the subdissector back to the calling dissector.

cmaynard gravatar imagecmaynard ( 2020-10-23 17:21:55 +0000 )edit

Wait, all scripts have a shared global namespace? Then I'll figure it out.

I thought every script is loaded in a separate Lua VM.

dottedmag gravatar imagedottedmag ( 2020-10-23 17:27:05 +0000 )edit