Repository navigation
Releases: EONRaider/RootWire
Release list
RootWire 6.0.0
RootWire's own dependency, NETProtocols,
is bumped to its latest release (2.2.1); no source changes were needed
— the only breaking change since RootWire's 1.3 floor (removal of
Packet.payload) is a name RootWire never called.
Changed
- BREAKING: Capture timestamps are now kernel-sourced nanoseconds
end-to-end instead of a userspacetime.time()reading. Live capture
enablesSO_TIMESTAMPNSand reads the kernel's own arrival timestamp
viarecvmsg's ancillary data instead of atime.time()call after
recvreturns, which included scheduler and interpreter latency
between the frame's arrival and Python observing it.DecodedFrame.timestamp
is now anint(nanoseconds since epoch), not afloat(seconds).
This changes two on-the-wire contracts: the NDJSONtimestampfield
is now an integer nanosecond value rather than a float epoch-seconds
value, and-wnow writes nanosecond-precision classic pcap files
(magic0xA1B23C4D) instead of microsecond-precision (0xA1B2C3D4)
— a long-established pcap variant every major tool (Wireshark,
tcpdump, tshark) already reads, and the only way the improved
capture precision survives to disk. Replay (-r) still reads both
precisions losslessly (#59). - BREAKING (library API):
-i/--interfaceis now repeatable —
-i eth0 -i wlan0captures on both interfaces concurrently, merged
into one decoded stream, each frame tagged with the interface it
actually arrived on. Existing single-use invocations (-i eth0) are
unaffected. Live capture is now backed by an asyncio event loop
internally (one raw socket per requested interface, multiplexed via
add_reader); the publicrootwire.capture.capture()sync generator
is replaced byrootwire.capture.capture_async(), an async
generator with a different signature — a break only for code
embedding RootWire as a library and callingcapture()directly,
not for any CLI usage (#61).
Added
--filternow also accepts arbitrary filter expressions
(tcp and port 80,host 1.2.3.4,not arp, ...), compiled to cBPF
by a small hand-rolled compiler — no libpcap dependency, keeping
RootWire's zero-dependency, from-scratch posture. Supported grammar:
protocolstcp/udp/icmp/arp/ip/ip6;host/port, each
optionally prefixed withsrc/dst;and/or/not; parentheses
— anything outside that grammar is a clear compile-time error, never
a best-effort guess. Correctness is validated by interpreting both
this compiler's output and realtcpdump -ddbytecode against the
project's captured-frame corpus and asserting they always agree on
accept/reject for every frame — not by matching tcpdump's exact
instruction sequence, which its own decades-old peephole optimizer
makes impractical to reproduce by hand past a single bare primitive
(#63).--filter {tcp,udp,arp,ip6}: attach a kernel-side classic-BPF
(cBPF) filter to the capture socket (SO_ATTACH_FILTER), the same
mechanismtcpdumpitself uses, so non-matching frames are dropped
in the kernel and never copied to userspace. This release ships a
small, canned set of pre-compiled programs, each verified
byte-for-byte againsttcpdump -dd <expression>. Mutually exclusive
with-r— replay has no socket to attach a kernel filter to (#62).- Diagnose IPv4 frames whose
total_lengthis smaller than the header
itself — a length field that cannot be correct. The frame is flagged
[!] Malformedon screen, carries amalformed_lengthfield in NDJSON
output, and counts toward the statisticsmalformedtally; upper layers
are still decoded and shown. Atotal_lengthof 0 is exempt, being the
large-send offload (TSO) sentinel found in locally captured frames
rather than corruption (#56). - Handle
SIGTERMas a clean shutdown, the same as Ctrl-C: flush every
output, print the stats summary, and exit 0. Previously onlySIGINT
was handled — a service manager's stop (or plainkill) hit Python's
default disposition, which terminates immediately and skips output
flushing entirely, losing the tail of a-wcapture and the run
summary (#60).
Security
- Payload display (
-d) now neutralizes terminal control characters.
Packet payloads are attacker-controlled, and the previous rendering
passed ESC and other control bytes straight to the terminal, allowing a
crafted frame to inject ANSI escape sequences. Non-printable characters
(C0/C1 controls,DEL, and Unicode format characters such as the
bidirectional overrides) are now shown as visible\xNN/\uXXXX
escapes; printable text and newlines are unchanged (#53).
Fixed
- Refuse
-r FILE -w FILEwhen both refer to the same file. The writer
truncated its target before the lazy replay reader had read a byte, so
replaying and writing the same path destroyed the capture; it is now
rejected up front, before anything is opened (#52). - A
-wtarget that cannot be opened (bad directory, permission denied)
now reports a clear write-specific error instead of a raw traceback,
and no longer risks being misreported as a capture-privilege problem
(#54). - The end-of-run statistics summary is no longer printed while an
unexpected exception is propagating, where it made a crash look like a
clean run (#54).
RootWire 5.0.0
Packet-Sniffer is now RootWire — same engine, new name, and its first release on PyPI:
pipx install rootwire
Everything 4.1 could do, under the new identity: live capture (sudo rootwire -i eth0), byte-exact pcap output (-w), root-free pcap replay (-r), NDJSON streaming (--json | jq .), capture statistics, options-aware decoding through IPv6 extension headers, and a decode chain hardened against crafted input — powered by netprotocols.
The module and console script are renamed (rootwire, python -m rootwire) — the breaking change behind the major version. Full details in CHANGELOG.md; the version continues the Packet-Sniffer lineage.
packet-sniffer 4.1.0
Milestone v4.1. Full details in CHANGELOG.md.
Highlights
- pcap:
-w FILEwrites captures Wireshark opens cleanly;-r FILEreplays any classic pcap through the full pipeline — no root required - NDJSON:
--json | jq .— one JSON object per frame on stdout, everything informational on stderr - Statistics on exit: frames, bytes, frames/s, malformed/truncated, per-protocol tallies
- IPv6 extension headers render (netprotocols 1.1): MLD shows its full Hop-by-Hop chain; fragments labeled
- Decode chain capped at 16 layers against crafted extension-header amplification
Install: pipx install "git+https://github.com/EONRaider/Packet-Sniffer.git"
packet-sniffer 4.0.0
Complete rebuild on netprotocols 1.0. Full details in CHANGELOG.md and the new ARCHITECTURE.md.
Highlights
- Pure decoder producing an immutable
DecodedFrame; capture, decoding, and rendering are separate and testable without root - Type-dispatched renderers; IPv6 frames no longer crash the display; malformed/truncated frames are diagnosed and the capture survives
- Full-size capture buffer (loopback traffic no longer silently truncates); flat memory over long captures (benchmarked)
- Proper entry points:
packet-snifferandpython -m packet_sniffer - Install:
pipx install "git+https://github.com/EONRaider/Packet-Sniffer.git"
Version note: tags 3.1.0/3.1.2 shipped in 2022, so the rebuild releases as 4.0.0.