13.7. Adding Information To The Dissection Tree
Prev | Chapter 13. Wireshark’s Lua API Reference Manual | Next

## 13.7. Adding Information To The Dissection Tree

### 13.7.1. TreeItem

`TreeItem`s represent information in the packet details pane of Wireshark, and the packet details view of TShark. A `TreeItem` represents a node in the tree, which might also be a subtree and have a list of children. The children of a subtree have zero or more siblings which are other children of the same `TreeItem` subtree.

During dissection, heuristic-dissection, and post-dissection, a root `TreeItem` is passed to dissectors as the third argument of the function callback (e.g., `myproto.dissector(tvbuf,pktinfo,root)`).

In some cases the tree is not truly added to, in order to improve performance. For example for packets not currently displayed/selected in Wireshark’s visible window pane, or if TShark isn’t invoked with the `-V` switch. However the "add" type `TreeItem` functions can still be called, and still return `TreeItem` objects - but the info isn’t really added to the tree. Therefore you do not typically need to worry about whether there’s a real tree or not. If, for some reason, you need to know it, you can use the `TreeItem.visible` attribute getter to retrieve the state.

#### 13.7.1.1. treeitem:add_packet_field(protofield, [tvbrange], encoding, [label])

Adds a new child tree for the given `ProtoField` object to this tree item, returning the new child `TreeItem`.

Unlike `TreeItem:add()` and `TreeItem:add_le()`, the `ProtoField` argument is not optional, and cannot be a `Proto` object. Instead, this function always uses the `ProtoField` to determine the type of field to extract from the passed-in `TvbRange`, highlighting the relevant bytes in the Packet Bytes pane of the GUI (if there is a GUI), etc. If no `TvbRange`is given, no bytes are highlighted and the field’s value cannot be determined; the `ProtoField` must have been defined/created not to have a length in such a case, or an error will occur. For backwards-compatibility reasons the `encoding` argument, however, must still be given.

Unlike `TreeItem:add()` and `TreeItem:add_le()`, this function performs both big-endian and little-endian decoding, by setting the `encoding` argument to be `ENC_BIG_ENDIAN` or `ENC_LITTLE_ENDIAN`.

The signature of this function:

         tree_item:add_packet_field(proto_field [,tvbrange], encoding, ...)

This function returns more than just the new child `TreeItem`. The child is the first return value, so that function chaining will still work; but it also returns more information. The second return is the value of the extracted field (i.e., a number, `UInt64`, `Address`, etc.). The third return is is the offset where data should be read next. This is useful when the length of the field is not known in advance. The additional return values may be null if the field type is not well supported in the Lua API.

This function can extract a `ProtoField` of type `ftypes.BYTES` or `ftypes.ABSOLUTE_TIME` from a string in the `TvbRange` in ASCII-based and similar encodings. For example, a `ProtoField` of `ftypes.BYTES` can be extracted from a `TvbRange` containing the ASCII string "a1b2c3d4e5f6", and it will correctly decode the ASCII both in the tree as well as for the second return value, which will be a `ByteArray`. To do so, you must set the `encoding` argument of this function to the appropriate string `ENC_*` value, bitwise-or’d (or added) with the `ENC_STR_HEX` value and one or more `ENC_SEP_XXX` values indicating which encodings are allowed. For `ftypes.ABSOLUTE_TIME`, one of the `ENC_ISO_8601_*` encodings or `ENC_IMF_DATE_TIME` must be used, and the second return value is a `NSTime`. Only single-byte ASCII digit string encodings such as `ENC_ASCII` and `ENC_UTF_8` can be used for this.

For example, assuming the `Tvb` named “tvb” contains the string "abcdef" (61 62 63 64 65 66 in hex):

         -- this is done earlier in the script
         local myfield = ProtoField.new("Transaction ID", "myproto.trans_id", ftypes.BYTES)
         myproto.fields = { myfield }

         -- this is done inside a dissector, post-dissector, or heuristic function
         -- child will be the created child tree, and value will be the ByteArray "abcdef" or nil on failure
         local child, value = tree:add_packet_field(myfield, tvb:range(0,6), ENC_UTF_8 + ENC_STR_HEX + ENC_SEP_NONE)

##### Arguments

protofield
  The ProtoField field object to add to the tree.

tvbrange (optional)
  The `TvbRange` of bytes in the packet this tree item covers/represents.

encoding
  The field’s encoding in the `TvbRange`.

label (optional)
  One or more strings to append to the created `TreeItem`.

##### Returns

The new child `TreeItem`, the field’s extracted value or nil, and offset or nil.

#### 13.7.1.2. treeitem:add([protofield], [tvbrange], [value], [label])

Adds a child item to this tree item, returning the new child `TreeItem`.

If the `ProtoField` represents a numeric value (int, uint or float), then it’s treated as a Big Endian (network order) value.

This function has a complicated form: 'treeitem:add([protofield,] [tvbrange,] value], label)', such that if the first argument is a `ProtoField` or a `Proto`, the second argument is a `TvbRange`, and a third argument is given, it’s a value; but if the second argument is a non-`TvbRange`, then it’s the value (as opposed to filling that argument with 'nil', which is invalid for this function). If the first argument is a non-`ProtoField` and a non-`Proto` then this argument can be either a `TvbRange` or a label, and the value is not in use.

###### Example

        local proto_foo = Proto("foo", "Foo Protocol")
        proto_foo.fields.bytes = ProtoField.bytes("foo.bytes", "Byte array")
        proto_foo.fields.u16 = ProtoField.uint16("foo.u16", "Unsigned short", base.HEX)

        function proto_foo.dissector(buf, pinfo, tree)
                -- ignore packets less than 4 bytes long
                if buf:len() < 4 then return end

                -- ##############################################
                -- # Assume buf(0,4) == {0x00, 0x01, 0x00, 0x02}
                -- ##############################################

                local t = tree:add( proto_foo, buf() )

                -- Adds a byte array that shows as: "Byte array: 00010002"
                t:add( proto_foo.fields.bytes, buf(0,4) )

                -- Adds a byte array that shows as "Byte array: 313233"
                -- (the ASCII char code of each character in "123")
                t:add( proto_foo.fields.bytes, buf(0,4), "123" )

                -- Adds a tree item that shows as: "Unsigned short: 0x0001"
                t:add( proto_foo.fields.u16, buf(0,2) )

                -- Adds a tree item that shows as: "Unsigned short: 0x0064"
                t:add( proto_foo.fields.u16, buf(0,2), 100 )

                -- Adds a tree item that shows as: "Unsigned short: 0x0064 ( big endian )"
                t:add( proto_foo.fields.u16, buf(1,2), 100, nil, "(", nil, "big", 999, nil, "endian", nil, ")" )

                -- LITTLE ENDIAN: Adds a tree item that shows as: "Unsigned short: 0x0100"
                t:add_le( proto_foo.fields.u16, buf(0,2) )

                -- LITTLE ENDIAN: Adds a tree item that shows as: "Unsigned short: 0x6400"
                t:add_le( proto_foo.fields.u16, buf(0,2), 100 )

                -- LITTLE ENDIAN: Adds a tree item that shows as: "Unsigned short: 0x6400 ( little endian )"
                t:add_le( proto_foo.fields.u16, buf(1,2), 100, nil, "(", nil, "little", 999, nil, "endian", nil, ")" )
        end

        udp_table = DissectorTable.get("udp.port")
        udp_table:add(7777, proto_foo)

##### Arguments

protofield (optional)
  The `ProtoField` field or `Proto` protocol object to add to the tree.

tvbrange (optional)
  The `TvbRange` of bytes in the packet this tree item covers/represents.

value (optional)
  The field’s value, instead of the ProtoField/Proto one.

label (optional)
  One or more strings to use for the tree item label, instead of the ProtoField/Proto one.

##### Returns

The new child TreeItem.

#### 13.7.1.3. treeitem:add_le([protofield], [tvbrange], [value], [label])

Adds a child item to this tree item, returning the new child `TreeItem`.

If the `ProtoField` represents a numeric value (int, uint or float), then it’s treated as a Little Endian value.

This function has a complicated form: 'treeitem:add_le([protofield,] [tvbrange,] value], label)', such that if the first argument is a `ProtoField` or a `Proto`, the second argument is a `TvbRange`, and a third argument is given, it’s a value; but if the second argument is a non-`TvbRange`, then it’s the value (as opposed to filling that argument with 'nil', which is invalid for this function). If the first argument is a non-`ProtoField` and a non-`Proto` then this argument can be either a `TvbRange` or a label, and the value is not in use.

##### Arguments

protofield (optional)
  The ProtoField field or Proto protocol object to add to the tree.

tvbrange (optional)
  The TvbRange of bytes in the packet this tree item covers/represents.

value (optional)
  The field’s value, instead of the ProtoField/Proto one.

label (optional)
  One or more strings to use for the tree item label, instead of the ProtoField/Proto one.

##### Returns

The new child TreeItem.

#### 13.7.1.4. treeitem:set_text(text)

Sets the text of the label.

This used to return nothing, but as of 1.11.3 it returns the same tree item to allow chained calls.

##### Arguments

text
  The text to be used.

##### Returns

The same TreeItem.

#### 13.7.1.5. treeitem:append_text(text)

Appends text to the label.

This used to return nothing, but as of 1.11.3 it returns the same tree item to allow chained calls.

##### Arguments

text
  The text to be appended.

##### Returns

The same TreeItem.

#### 13.7.1.6. treeitem:prepend_text(text)

Prepends text to the label.

This used to return nothing, but as of 1.11.3 it returns the same tree item to allow chained calls.

##### Arguments

text
  The text to be prepended.

##### Returns

The same TreeItem.

#### 13.7.1.7. treeitem:add_expert_info([group], [severity], [text])

Sets the expert flags of the item and adds expert info to the packet.

This function does not create a truly filterable expert info for a protocol. Instead you should use `TreeItem.add_proto_expert_info()`.

Note: This function is provided for backwards compatibility only, and should not be used in new Lua code. It may be removed in the future. You should only use `TreeItem.add_proto_expert_info()`.

##### Arguments

group (optional)
  One of: `PI_CHECKSUM`, `PI_SEQUENCE`, `PI_RESPONSE_CODE`, `PI_REQUEST_CODE`, `PI_UNDECODED`, `PI_REASSEMBLE`, `PI_MALFORMED`, `PI_DEBUG`, `PI_PROTOCOL`, `PI_SECURITY`, `PI_COMMENTS_GROUP`, `PI_DECRYPTION`, `PI_ASSUMPTION`, `PI_DEPRECATED`, `PI_RECEIVE`, `PI_INTERFACE`, or `PI_DISSECTOR_BUG`.

severity (optional)
  One of: `PI_COMMENT`, `PI_CHAT`, `PI_NOTE`, `PI_WARN`, or `PI_ERROR`.

text (optional)
  The text for the expert info display.

##### Returns

The same TreeItem.

#### 13.7.1.8. treeitem:add_proto_expert_info(expert, [text])

Sets the expert flags of the tree item and adds expert info to the packet.

##### Arguments

expert
  The `ProtoExpert` object to add to the tree.

text (optional)
  Text for the expert info display (default is to use the registered text).

##### Returns

The same TreeItem.

#### 13.7.1.9. treeitem:add_tvb_expert_info(expert, tvb, [text])

Sets the expert flags of the tree item and adds expert info to the packet associated with the `Tvb` or `TvbRange` bytes in the packet.

##### Arguments

expert
  The `ProtoExpert` object to add to the tree.

tvb
  The `Tvb` or `TvbRange` object bytes to associate the expert info with.

text (optional)
  Text for the expert info display (default is to use the registered text).

##### Returns

The same TreeItem.

#### 13.7.1.10. treeitem:set_generated([bool])

Marks the `TreeItem` as a generated field (with data inferred but not contained in the packet).

This used to return nothing, but as of 1.11.3 it returns the same tree item to allow chained calls.

##### Arguments

bool (optional)
  A Lua boolean, which if `true` sets the `TreeItem` generated flag, else clears it (default=true)

##### Returns

The same TreeItem.

#### 13.7.1.11. treeitem:set_hidden([bool])

Marks the `TreeItem` as a hidden field (neither displayed nor used in filters). Deprecated

This used to return nothing, but as of 1.11.3 it returns the same tree item to allow chained calls.

##### Arguments

bool (optional)
  A Lua boolean, which if `true` sets the `TreeItem` hidden flag, else clears it. Default is `true`.

##### Returns

The same TreeItem.

#### 13.7.1.12. treeitem:set_len(len)

Set `TreeItem`'s length inside tvb, after it has already been created.

This used to return nothing, but as of 1.11.3 it returns the same tree item to allow chained calls.

##### Arguments

len
  The length to be used.

##### Returns

The same TreeItem.

#### 13.7.1.13. treeitem:referenced(protofield)

Checks if a `ProtoField` or `Dissector` is referenced by a filter/tap/UI.

If this function returns `false`, it means that the field (or dissector) does not need to be dissected and can be safely skipped. By skipping a field rather than dissecting it, the dissector will usually run faster since Wireshark will not do extra dissection work when it doesn’t need the field.

You can use this in conjunction with the TreeItem.visible attribute. This function will always return true when the TreeItem is visible. When it is not visible and the field is not referenced, you can speed up the dissection by not dissecting the field as it is not needed for display or filtering.

This function takes one parameter that can be a `ProtoField` or `Dissector`. The `Dissector` form is useful when you need to decide whether to call a sub-dissector.

##### Arguments

protofield
  The `ProtoField` or `Dissector` to check if referenced.

##### Returns

A boolean indicating if the ProtoField/Dissector is referenced

#### 13.7.1.14. treeitem:get_child_count()

Returns the number of direct child tree items.

This method counts and returns the number of direct children of this tree item. Only immediate children are counted; grandchildren and deeper descendants are not included.

        local tree = root:add(myproto, tvbuf())
        tree:add("Child 1")
        tree:add("Child 2")

        local count = tree:get_child_count()
        -- count is now 2

Since: 4.7.0

##### Returns

The number of child tree items.

#### 13.7.1.15. treeitem:get_parent()

Returns the parent tree item.

Returns the parent tree item of this item, or nil if this is a root item (i.e., a top-level tree item added directly to the protocol tree).

        local parent_tree = root:add(myproto, tvbuf())
        local child_tree = parent_tree:add("Child")

        local parent = child_tree:get_parent()
        -- parent is the same as parent_tree

        local root_parent = parent_tree:get_parent()
        -- root_parent is nil (assuming parent_tree is a root item)

Since: 4.7.0

##### Returns

The parent TreeItem, or nil if this is a root item.

#### 13.7.1.16. treeitem:get_child(index)

Returns the child tree item at the specified index.

Returns the direct child TreeItem at the given index using 0-based indexing. This provides random access to child items by their position.

        local tree = root:add(myproto, tvbuf())
        tree:add("First child")   -- index 0
        tree:add("Second child")  -- index 1
        tree:add("Third child")   -- index 2

        local first = tree:get_child(0)   -- Returns first child
        local second = tree:get_child(1)  -- Returns second child
        local invalid = tree:get_child(5) -- Returns nil (out of range)

Since: 4.7.0

##### Arguments

index
  The index of the child (0-based).

##### Returns

The child TreeItem at the specified index, or nil if out of range.

#### 13.7.1.17. treeitem:children([field_filter], [recursive])

Returns an iterator function to iterate over child tree items.

Returns an iterator function that can be used in a Lua for loop to iterate over children of this tree item. Supports optional filtering and recursive traversal.

The basic usage iterates over direct children only:

        for child in tree:children() do
            print("Child: " .. tostring(child))
        end

You can filter by field names to only get children with specific fields:

        -- Single field filter
        for child in tree:children("tcp.flags") do
            print("TCP flags child: " .. tostring(child))
        end

        -- Multiple field filters
        for child in tree:children({"tcp.port", "tcp.srcport", "tcp.dstport"}) do
            print("TCP port child: " .. tostring(child))
        end

Enable recursive iteration to traverse the entire subtree in depth-first order:

        -- Recursive iteration without filter
        for child in tree:children(nil, true) do
            print("Descendant: " .. tostring(child))
        end

        -- Recursive iteration with field filter
        for child in tree:children("tcp.flags", true) do
            print("TCP flags anywhere in subtree: " .. tostring(child))
        end

When using recursive mode with filters, the iterator searches through all descendants even if parent nodes don’t match the filter, ensuring no matching children are missed.

| Important
Field extractors must still be created for the fields you want to iterate over. Wireshark optimizes dissection by only creating tree items for fields that are explicitly requested through field extractors, display filters, or taps. Without proper field extractors, the fields may not exist in the dissection tree and will not be found by this iterator.

Example of proper field extractor setup:

        -- Define field extractors first
        local tcp_flags_extractor = Field.new("tcp.flags")
        local tcp_port_extractor = Field.new("tcp.port")

        -- Then use tree navigation (extractors ensure fields exist in tree)
        for child in tree:children("tcp.flags") do
            local field_info = child:get_field_info()
            print("TCP Flags:", field_info.value)
        end

Since: 4.7.0

##### Arguments

field_filter (optional)
  Optional field name(s) to filter by (string or table of strings).

recursive (optional)
  Optional boolean to enable recursive (depth-first) iteration. Default is false.

##### Returns

An iterator function for use in Lua for loops.

#### 13.7.1.18. treeitem:get_field_info()

Returns the FieldInfo object associated with this tree item.

Returns a FieldInfo object that provides access to the underlying field information including name, abbreviated name, type, value, data offset, length, and other protocol field properties.

This is particularly useful for extracting actual field values and metadata from tree items during packet analysis.

        for child in tree:children() do
            local field_info = child:get_field_info()
            if field_info then
                print("Field name: " .. field_info.name)
                print("Field abbrev: " .. field_info.abbrev)
                print("Field type: " .. field_info.type)
                print("Field value: " .. tostring(field_info.value))
                print("Field offset: " .. field_info.offset)
                print("Field len: " .. field_info.len)
            else
                print("No field info (text-only or generated item)")
            end
        end

| Note
Field extractors are still required to ensure fields exist in the dissection tree. This method only provides access to field information for tree items that already exist.

Since: 4.7.0

##### Returns

The FieldInfo object, or nil if not available.

#### 13.7.1.19. treeitem:__tostring()

Returns a short label of the form `TreeItem: <abbrev>` for an attached field, `TreeItem: (root)` for a text-only/root tree, or `TreeItem: (no item)` / `TreeItem: (expired)` / `TreeItem: (null)` for the degenerate cases. The previous form dumped only boolean flags (expired/item/tree/same), which were not very useful for identifying which TreeItem the debugger is looking at.

#### 13.7.1.20. treeitem.text

Mode: Retrieve or assign.

Set/get the `TreeItem`'s display string (string).

For the getter, if the TreeItem has no display string, then nil is returned.

#### 13.7.1.21. treeitem.visible

Mode: Retrieve only.

Get the `TreeItem`'s subtree visibility status (boolean).

#### 13.7.1.22. treeitem.generated

Mode: Retrieve or assign.

Set/get the `TreeItem`'s generated state (boolean).

#### 13.7.1.23. treeitem.hidden

Mode: Retrieve or assign.

Set/get `TreeItem`'s hidden state (boolean).

#### 13.7.1.24. treeitem.len

Mode: Retrieve or assign.

Set/get `TreeItem`'s length inside tvb, after it has already been created.

Prev | Up | Next
13.6. Functions For Handling Packet Data | Home | 13.8. Post-Dissection Packet Analysis