Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

The MongoDB Lua dissector you provided a link to doesn't behave the way your code sample does. Rather, the header.lua file simply contains header-specific dissection of the MongoDB protocol, whereas it appears you're looking to stack 2 separate protocols, those being (1) the "base" or "parent" dissector, and (2), one of a number of different "child" dissectors. Assuming that's the case, then you'll need the parent dissector to register for all known ports and then call the appropriate child dissector based on the specific port number, either through a static table lookup or through a registered table. For example:

1. Static Table:

Parent:

local data_dissector = Dissector.get("data")
local child_dissector_table = {}
local udp_ports = {PORT1, PORT2, ... PORTN}

local parent = Proto("Parent", "Parent Protocol")

function parent.init()
    child_dissector_table[PORT1] = Dissector.get("child1")
    child_dissector_table[PORT2] = Dissector.get("child2")
    ...
    child_dissector_table[PORTN] = Dissector.get("childN")
end

function parent.dissector(tvbuf, pinfo, tree)

    -- Dissect parent stuff here.

    -- Hand off remainder to child, like so:
    local tvb_sub = tvbuf:range(offset_to_child_data, length_of_child_data):tvb()
    if child_dissector_table[pinfo.src_port] ~= nil then
        child_dissector_table[pinfo.src_port]:call(tvb_sub, pinfo, tree)
    elseif child_dissector_table[pinfo.dst_port] ~= nil then
        child_dissector_table[pinfo.dst_port]:call(tvb_sub, pinfo, tree)
    else
        data_dissector:call(tvb_sub, pinfo, tree)
    end
end

local function register_udp_ports(ports)
    local udp_port_table = DissectorTable.get("udp.port")

    for k, v in next, ports do
        udp_port_table:add(v, parent)
    end
end

register_udp_ports(udp_ports)

2. Child Registration:

Parent:

local data_dissector = Dissector.get("data")
local port_table = DissectorTable.new("parent.port", "parent.port", ftypes.UINT16, base.DEC)
local udp_ports = {PORT1, PORT2, ... PORTN}

local parent = Proto("Parent", "Parent Protocol")

function parent.dissector(tvbuf, pinfo, tree)

    -- Dissect parent stuff here.

    -- Hand off remainder to child, like so:
    local tvb_sub = tvbuf:range(offset_to_child_data, length_of_child_data):tvb()
    local child

    child = port_table.get_dissector(pinfo.src_port)
    if child ~= nil then
        child:call(tvb_sub, pinfo, tree)
    else
        child = port_table.get_dissector(pinfo.dst_port)
        if child ~= nil then
            child:call(tvb_sub, pinfo, tree)
        else
            data_dissector:call(tvb_sub, pinfo, tree)
        end
    end
end

local function register_udp_ports(ports)
    local udp_port_table = DissectorTable.get("udp.port")

    for k, v in next, ports do
        udp_port_table:add(v, parent)
    end
end

register_udp_ports(udp_ports)

Child1:

DissectorTable.get("parent.port"):add(PORT1, child1)

Child2:

DissectorTable.get("parent.port"):add(PORT2, child2)

...

ChildN:

DissectorTable.get("parent.port"):add(PORTN, childN)

DISCLAIMER: This is all pseudocode of course, but this is the general idea.