Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

Final answer - matches protobuf described in answer 2 comments:

-- 240313_33954_nested_pb_table.lua
-- "Am looking for working example for below case where data is serialized as bytes to another protobuf."
-- https://ask.wireshark.org/question/33954/lua-example-for-protobuf-dissector-which-has-protobuf-encoded-within-protobuf/

-- Step 1 - document as you go. See header above and set_plugin_info().
local nested_pb_table_info =
{
    version = "1.0.0",
    author = "Good Coder",
    description = "Decode nested protobufs",
    repository = "Floppy in top drawer"
}

set_plugin_info(nested_pb_table_info)

do
    local protobuf_field_table = DissectorTable.get("protobuf_field") 
    local protobuf_dissector = Dissector.get("protobuf")

    -- This could probably be one dissector with more control logic
    -- It is easier (IM"not so"HO) to read split out into two dissectors
    encoded_pb_p = Proto("encoded_pb_dissector", "Encoded Protobuf")
    encoded_pb_p.dissector = function(tvb, pinfo, subtree)
        pinfo.private["pb_msg_type"] = "message,encoded_data.encodeData"
        local subsubtree = subtree:add(encoded_pb_p, tvb())
        pcall(Dissector.call, protobuf_dissector, tvb, pinfo, subsubtree)
    end

    pbf_encodeDataInfo_name_f = Field.new("pbf.encoded_data.encodeDataInfo.name")
    pbf_encodeDataInfo_val_f = Field.new("pbf.encoded_data.encodeDataInfo.val")

    netdata_pb_p = Proto("netdata_pb_dissector", "Network Data Protobuf")
    netdata_pb_p.dissector = function(tvb, pinfo, subtree)

        -- What is the message type for the nested protobufs
        local message_type = {
            ["macData.proto"] = "message,mac_data.macDataInfo",
            ["ipData.proto"] = "message,ip_data.ipDataInfo"
        }

        finfo_names = { pbf_encodeDataInfo_name_f() }
        finfo_vals = { pbf_encodeDataInfo_val_f() }

        -- the current last pbf.encoded_data.encodeDataInfo.name contains the .proto
        -- filename matching the pbf.encoded_data.encodeDataInfo.val passed in tvb
        -- use message_type table to map it message type
        if (#finfo_names > 0 and #finfo_vals >0) then
            v_string = string.format("%s", finfo_names[#finfo_names])
            pinfo.private["pb_msg_type"] = message_type[v_string]
            local subsubtree = subtree:add(netdata_pb_p, tvb())
            pcall(Dissector.call, protobuf_dissector, tvb, pinfo, subsubtree)
        end
    end

    -- What fields are the encoded protobufs in
    protobuf_field_table:add("export_data.streamDataArgs.data", encoded_pb_p) 
    protobuf_field_table:add("encoded_data.encodeDataInfo.val", netdata_pb_p) 
end