| Name | Modified | Size | Downloads / Week |
|---|---|---|---|
| Parent folder | |||
| README.md | 2026-09-09 | 5.4 kB | |
| RootWire 6.0.0 source code.tar.gz | 2026-09-09 | 117.1 kB | |
| RootWire 6.0.0 source code.zip | 2026-09-09 | 137.1 kB | |
| Totals: 3 Items | 259.7 kB | 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 userspace
time.time()reading. Live capture enablesSO_TIMESTAMPNSand reads the kernel's own arrival timestamp viarecvmsg's ancillary data instead of atime.time()call afterrecvreturns, which included scheduler and interpreter latency between the frame's arrival and Python observing it.DecodedFrame.timestampis 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 viaadd_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 onlySIGINTwas 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/\uXXXXescapes; 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).