tpt-fathom
RustMemory-safe, declarative network protocol analyzer and packet inspection engine written in Rust — a spiritual successor to Wireshark. Protocols are defined as YAML schemas and compiled into safe parsers at runtime, eliminating the C-dissector buffer overflows that plague traditional packet analyzers.
Languages
TPT Fathom
A memory-safe, highly extensible, and declarative network protocol analyzer and packet inspection engine — a spiritual successor to Wireshark.
Why
Wireshark's C dissectors parse untrusted, malformed network packets. A single buffer overflow in a C dissector can let a maliciously crafted packet execute arbitrary code on a security analyst's machine, and writing a new dissector in C takes days of boilerplate.
TPT Fathom's dissectors are described by a Declarative Schema (YAML), compiled into a
safe parser at runtime by a Rust engine built on zerocopy. Adding a new protocol is a
matter of writing (or AI-generating) a schema file, not writing unsafe C.
Status
Core v1 feature set is implemented — see todo.md for the full checklist.
Shipped: schema format + validator, decode engine, fifteen protocol schemas (Ethernet,
IPv4, IPv6, TCP, UDP, DNS, DHCP, DHCPv6, HTTP/2, SMB2, ARP, ICMP, HTTP/1.x, TLS, VLAN),
CLI (file + live, display filter, BPF capture filter, packet limit, pcap export), egui GUI
(search filter, export JSON, recent files, sortable columns, keyboard nav, error log),
fuzz corpus with zero panics across 2158 malformed packets, and an AI schema-extraction
tool.
Reachability from Ethernet captures: IPv4 → ICMP/TCP/UDP → DNS (UDP/53), DHCP
(UDP/67-68), SMB2 (TCP/445), HTTP (TCP/80), TLS (TCP/443); IPv6 → TCP/UDP/DHCPv6
(UDP/546-547); ARP; VLAN (802.1Q + QinQ) → inner IPv4/IPv6/ARP are all wired
end-to-end via protocol_ref port/protocol dispatch.
HTTP/2 remains schema-select/test-only until a TLS payload dissector lands (TLS record
layer is now present but HTTP/2-over-TLS needs handshake parsing). Release/publishing is
deferred (Phase 15). Schema format reference: docs/SCHEMA.md.
Architecture
schemas/*.yaml ──► fathom-schema ──► fathom-engine ◄── raw frame bytes
(YAML schemas) (parse + (zerocopy decode (from fathom-capture
validate at to a field tree; or a pcap file)
load time) panic-free)
│
┌─────────────────────┼─────────────────────┐
▼ ▼ ▼
fathom-cli fathom-gui serde export
(tree / JSON out) (list + hex + tree) (JSON / YAML)
fathom-schema— parses YAML schemas and statically validates them (danglinglength_refs, zero-length fields, overlapping bitfields, …) at load time. No decoding.fathom-engine— interprets a validated schema against raw bytes into aDecodedFieldtree. Panic-free: every malformed input yields anEngineError.fathom-capture— reads.pcap/.pcapngfiles (pure Rust, no external deps) and does live capture via Npcap (Windows) / libpcap, exposed as a tokio-friendly stream.fathom-cli/fathom-gui— two frontends over the same decode path. Schemas are embedded at compile time withinclude_str!.
Protocol layering is data-driven: a schema's protocol_ref field dispatches to another
schema by name (Ethernet → IPv4 → TCP/UDP → DNS), resolved by a SchemaRegistry at
decode time. No Rust code changes are needed to add a protocol.
Building
pwsh tools/fetch-npcap-sdk.ps1 # Windows only, once: fetch Npcap SDK headers + import libs
cargo build --workspace
The Npcap SDK fetch is build-time only (fathom-capture links against it on Windows);
the output lands in gitignored vendor/npcap-sdk/. Plain file-mode decoding works with
nothing else installed. On Linux, install libpcap-dev instead (CI does this
automatically).
Running the CLI
cargo run -p fathom-cli -- tests/fixtures/sample.pcap # decoded field tree
cargo run -p fathom-cli -- tests/fixtures/sample.pcap --json # one JSON array
cargo run -p fathom-cli -- tests/fixtures/sample.pcap --yaml # one YAML document
cargo run -p fathom-cli -- --list-schemas # bundled schema names
cargo run -p fathom-cli -- --list-interfaces # live-capture interfaces
cargo run -p fathom-cli -- --interface eth0 # live capture (Ctrl+C to stop)
cargo run -p fathom-cli -- --interface eth0 --json # live: JSON Lines (one object/line)
cargo run -p fathom-cli -- tests/fixtures/sample.pcap \
--filter 'protocol==TCP and dst_port==80' # display filter
cargo run -p fathom-cli -- --interface eth0 -f 'port 53' # BPF capture filter
cargo run -p fathom-cli -- tests/fixtures/sample.pcap -c 10 -w out.pcap # limit + export
File mode wraps all packets in a single JSON array; live mode streams JSON Lines, since a
live capture has no fixed end. Decode errors on individual packets are reported per-packet
(decode error: … / an "error" field in JSON) and do not fail the process. Display
filters affect printed/JSON output only; -w still exports every packet read (respecting
-c). Invalid checksums and decode errors are colored red only when the target stream is
a terminal.
Live capture setup
Live capture needs the Npcap runtime installed separately from the SDK:
https://npcap.com/#download (admin rights required). The SDK fetch above only provides
headers/import libraries so the binary links. wpcap.dll/Packet.dll are delay-loaded,
so file-mode decoding keeps working even with no Npcap install; requesting
--interface/--list-interfaces without the runtime fails with a clean error message
rather than a crash.
Running the GUI
cargo run -p fathom-gui
An egui desktop app with a packet list (protocol-chain summary), a hex dump pane, and a
field-tree detail pane synced to selection (clicking a leaf highlights its bytes in the
hex dump). Use Open (native file dialog) for .pcap/.pcapng, or the live-capture
action to pick an interface and stream decoded frames into the list.
Development
cargo fmt --all -- --check
cargo clippy --workspace --all-targets -- -D warnings
cargo test --workspace
CI (.github/workflows/ci.yml) runs the same four steps (fmt, clippy, build, test) plus
fixture-drift, fuzz-corpus, and cargo doc smoke checks on both Ubuntu and Windows.
Integration tests load schemas from schemas/ via relative paths — run them from the
workspace root.
Fixtures are raw frame bytes regenerated by Python (stdlib struct only, no scapy):
py -3 tests/fixtures/gen_fixtures.py # regenerate .bin frames after schema changes
py -3 tests/fixtures/gen_pcap_fixture.py # rebuild sample.pcap from those frames
Fuzz corpus + manual procedure: tools/fuzz/README.md.
Adding a protocol
Start from schemas/_template.yaml. See
CONTRIBUTING.md for the full walkthrough — by hand, or drafted
from an RFC via tools/ai-extractor (with a mandatory human-review step).
Tech stack
Rust, zerocopy, tokio, serde, egui, pcap (Npcap on Windows); Python (stdlib
only) for fixture/fuzz generation and the AI schema-extraction tool.
License
Apache-2.0 — see LICENSE.