A small postdissector is enough to exercise everything the
debugger does. Save the following as printer.lua:
local printer = Proto("printer", "Demo Postdissector")
local sessions = {} -- frame number -> {src, dst}
local last_seen = {} -- Address -> frame number
local opcode_names = { [0x10] = "ack", [0x11] = "syn-ack" }
local handshake = { syn = true, fin = false }
local ip_src_F = Field.new("ip.src")
local tcp_flags_F = Field.new("tcp.flags")
function printer.dissector(tvb, pinfo, tree)
local offset = 0
sessions[pinfo.number] = { src = pinfo.src, dst = pinfo.dst }
last_seen[tostring(pinfo.src)] = pinfo.number
-- Reference each file-scope local at least once so Lua keeps
-- them as upvalues of this closure (otherwise the watch
-- examples below can't reach them).
local _captured = { printer, opcode_names, handshake,
ip_src_F, tcp_flags_F }
print(pinfo.number, tostring(pinfo.src), tostring(pinfo.dst))
end
register_postdissector(printer)
Every example later in this chapter resolves against names this
script defines, so you can paste any of them into the Watch
panel without setting up extra state. What’s in scope while
printer.dissector is paused:
printer, sessions, last_seen, opcode_names, handshake,
ip_src_F, tcp_flags_F.
tvb, pinfo, tree, offset.
print, tostring, assert, string,
type, getmetatable, Field, Proto, register_postdissector,
get_version.
The local _captured = { … } line in the dissector body is
demo-only: Lua captures file-scope locals as upvalues only if the
closure references them, so each name has to be mentioned at least
once for it to show up under Upvalues. A real postdissector’s
protocol logic does the same work organically. opcode_names and
handshake are otherwise unused — they exist solely to seed
hex-keyed and boolean-keyed tables for the path-watch examples
below.
Field.new(…) is called at file scope on purpose: extractors
can only be constructed at script load, before any dissector or tap
callback runs. Inside the dissector callback the script references
ip_src_F / tcp_flags_F (and so do the watch examples below), but
never calls Field.new again.
Drop it into your personal plugins directory (the exact path on your install is also shown under → → → ). The canonical locations are:
~/.local/lib/wireshark/plugins/
%APPDATA%\Wireshark\plugins\
Then:
Ctrl+Shift+L) so
Wireshark picks up the new file. The same shortcut also works
from the Reload Lua Plugins toolbar action inside the Lua
Debugger dialog once it’s open.
printer.lua to open
it in the editor.
printer.dissector to toggle
a breakpoint (a red circle appears).
Inspect the paused state:
tvb, pinfo, tree), Upvalues, and
Globals for the current frame.
pinfo.src (via the Variables context menu
or the + button in the Watch section header,
Ctrl+Shift+W).
F10), Step Into (F11), or
Continue (F5) to advance. The Watch tree updates on every
pause; values that changed since the previous pause are drawn in a
bold accent color and briefly flash.