Ask Your Question
0

Chaining two custom dissectors Lua - no such dissector table

asked 2021-10-14 19:34:13 +0000

I'm attempting to create two Lua dissector files to read a TCP message header and subsequent messages. I would like for the main lua dissector to call a message dissector multiple times based on the number of messages present. I can't seem to get the two to work together without a "no such dissector table" when attempting to reference the other file.

I found the following link, but I'm having trouble determining what goes where in the code. I tried various combinations unsuccessfully, but I'm new to Lua Dissectors. I haven't had much success. https://stackoverflow.com/questions/5...

Any guidance is greatly appreciated.

myHeaderProtocol = Proto("customHeader", "customHeader")
headerId = ProtoField.uint("headerId","headerId", base.DEC)
numMessages = ProtoField.uint("numMessages", "numMessages", base.DEC)
myHeaderProtocol.fields = {headerId, numMessages}

function myHeaderProtocol.dissector(buffer, pinfo, tree)
    length = buffer:len();
    pinfo.cols.protocol = myHeaderProtocol.name

local subtree = tree:add(myHeaderProtocol,buffer(), "Header Tree")
subtree:add( headerId, buffer(0,1))
    subtree:add( numMessages, buffer(1,1))

--How can I make sure mySubDissector is registered
--And recognized here?
mySubDissector(buffer(2,4):tvb(), pinfo, tree)
mySubDissector(buffer(6,4):tvb(), pinfo, tree)
--Two messages shown for simplicity
end

tcp_table = DissectorTable.get("tcp.port")
tcp_table:add(5678, myHeaderProtocol)

--Where should this go?
        DissectorTable.new("MyCustomTable")

subDissector.lua

mySubDissector = Proto("customHeader", "customHeader")
myMessage = ProtoField.uint("myMessage","myMessage", base.HEX)
mySubDissector.fields = {myMessage}

--Where should this go, or how should I do the equivalent?
function mySubDissector.init()
    DissectorTable.get("MyCustomTable"):add(5678, mySubDissector)
end
function mySubDissector.dissector(buffer, pinfo, tree)
    length = buffer:len();
    pinfo.cols.protocol = mySubDissector.name

    local subtree = tree:add(mySubDissector,buffer(), "Message SubTree")
    subtree:add( myMessage, buffer(0,4))
end

--I'm not sure about what is below
tcp_table = DissectorTable.get("myHeaderProtocol")
tcp_table:add(5678, mySubDissector)
edit retag flag offensive close merge delete

1 Answer

Sort by ยป oldest newest most voted
0

answered 2021-10-15 19:43:15 +0000

cmaynard gravatar image

For the header protocol, you're creating the DissectorTable but you're not saving the return value or doing anything with it. Your dissector table also appears to be based on a port number, which is a 16-bit value, so you should explicitly specify that as the type. If it is in fact a port number, then I find myself questioning why there are 2 different protocols involved here at all, but I'll assume there's a good reason you're doing this. Besides the problems with the subdissector table:

  • The filter names aren't following the <protocol>.<field> naming convention.
  • There is no ProtoField.uint function. Since both fields of the header are 1 byte, you should be using ProtoField.uint8 instead.

As for the subdissector, apart from the same problems with filter names and ProtoField.uint, which should be ProtoField.uint32 in this case, there's nothing else that needs to change.

Below are some modified code samples that should help.


First, the header: There are at least 2 ways to call the subdissector and I've illustrated both. You can even try out either method by changing the "Subdissection Method" preference.

myHeaderProtocol = Proto.new("myHeader", "My Custom Header Protocol")

-- Define protocol fields
local pf = {
    headerId = ProtoField.uint8("myHeader.headerId", "headerId", base.DEC),
    numMessages = ProtoField.uint8("myHeader.numMessages", "numMessages", base.DEC)
}
myHeaderProtocol.fields = pf

local myCustomTable = DissectorTable.new("MyCustomTable", "MyCustomTable", ftypes.UINT16, base.DEC)

-- Preferences
local METHOD_TRY    = 1
local METHOD_CALL   = 2
local methods_table = {
    {1, "Try", METHOD_TRY},
    {2, "Call", METHOD_CALL}
}
local default_prefs = {
    subdissectionMethod = METHOD_TRY
}
myHeaderProtocol.prefs.subdissection_method = Pref.enum("Subdissection Method",
    default_prefs.subdissectionMethod,
    "The subdissection method as \"try\" or \"call\".",
    methods_table,
    false
    )

function myHeaderProtocol.dissector(buffer, pinfo, tree)

    pinfo.cols.protocol = myHeaderProtocol.name

    local subtree = tree:add(myHeaderProtocol,buffer(), "Header Tree")
    subtree:add(pf.headerId, buffer(0, 1))
    subtree:add(pf.numMessages, buffer(1, 1))

    local numMessages = buffer(1, 1):uint()
    local offset = 2

    if myHeaderProtocol.prefs.subdissection_method == METHOD_TRY then
        --[[
            This method will use dissectortable:try().
            Note that we must still check if there's a subdissector
            registered; otherwise the data dissector will be called for us
            automatically if there isn't a registered dissector, and we don't
            want that.
        --]]
        local port

        if myCustomTable:get_dissector(pinfo.src_port) ~= nil then
            port = pinfo.src_port
            --pinfo.cols.info:append(" Source Port Match")
        elseif myCustomTable:get_dissector(pinfo.dst_port) ~= nil then
            port = pinfo.dst_port
            --pinfo.cols.info:append(" Destination Port Match")
        else
            return
        end

        while numMessages > 0 do
            myCustomTable:try(port, buffer(offset, 4):tvb(), pinfo, tree)
            offset = offset + 4
            numMessages = numMessages - 1
        end
    elseif myHeaderProtocol.prefs.subdissection_method == METHOD_CALL then
        --[[
            This method will call the subdissector directly if a handle is
            successfully found in the subdissector table.
        --]]
        local subdissector_handle = myCustomTable:get_dissector(pinfo.src_port)

        if subdissector_handle == nil then
            subdissector_handle = myCustomTable:get_dissector(pinfo.dst_port)
        end

        if subdissector_handle ~= nil then
            while numMessages > 0 do
                subdissector_handle:call(buffer(offset, 4):tvb(), pinfo, tree)
                offset = offset + 4
                numMessages = numMessages - 1
            end
        end
    end
end

tcp_table = DissectorTable.get("tcp.port")
tcp_table:add(5678, myHeaderProtocol)

And the ... (more)

edit flag offensive delete link more

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools

1 follower

Stats

Asked: 2021-10-14 19:34:13 +0000

Seen: 20 times

Last updated: Oct 15