Creating a Wireshark dissector in Lua - part 4 (separate subtrees)
This post continues where the third post left off. A reader told me it would be nice to have the header and the payload separated into two different subtrees, so in this post I’ll explain how we can do that.
Subtrees
I’m using the dissector from part three. I will only look at the OP_QUERY and OP_REPLY messages. Otherwise, the
dissector gets too big for a blog post.
I should first explain what a subtree is. Subtrees are the drop-down menus you see in the packet details pane in Wireshark:

At the moment the dissector has one main subtree for the entire MongoDB protocol. We want to add two new subtrees as children of the MongoDB subtree: one for the header and one for the payload. Let’s just call them Header and Payload.
The two new subtrees are basically sub-subtrees, but I’ll call them child subtrees.
Add new child subtrees
A new subtree under another subtree called subtree is created with subtree:add(proto_obj_name, buffer(), "Title").
The two new child subtrees are therefore made like this:
local subtree = tree:add(mongodb_protocol, buffer(), "MongoDB Protocol Data")
local headerSubtree = subtree:add(mongodb_protocol, buffer(), "Header")
local payloadSubtree = subtree:add(mongodb_protocol, buffer(), "Payload")
The first line was there before. That’s the main subtree. It is added to the main tree object that is a parameter of the
dissector function. We add two new subtrees as children of the main subtree, and have two variables, headerSubtree and
payloadSubtree that we can use to refer to those subtrees. It should look like this now:

The child subtrees are empty because the fields are still pointing to the main subtree.
Make the fields point to the child subtrees
We have to change the subtree that the various fields are added to. For example, for some of the header variables:
Change from:
-- Header
subtree:add_le(message_length, buffer(0,4))
subtree:add_le(request_id, buffer(4,4))
subtree:add_le(response_to, buffer(8,4))
To:
-- Header
headerSubtree:add_le(message_length, buffer(0,4))
headerSubtree:add_le(request_id, buffer(4,4))
headerSubtree:add_le(response_to, buffer(8,4))
And the payload variables:
Change from:
subtree:add_le(full_coll_name, buffer(20,string_length))
To:
payloadSubtree:add_le(full_coll_name, buffer(20,string_length))
This has to be done for all fields. Eventually, it will look like this:

You can also find the final code here.
If you want to find out how you can split the dissector into several files you can take a look at the fifth post in this series.