Npcap in promiscuous mode loops back our own sent frames to the
capture callback. Without filtering, every DATA frame the client
sent was also processed as an incoming frame, duplicating the data
stream. This corrupted SSH sessions (Bad packet length 0x5353482D
= 'SSH-' — the version banner received twice).
Fix: compare source MAC in captured frames against our own MAC and
skip matches. Mirrors the PACKET_OUTGOING check on the Rust side.
Ethernet pads frames to 60 bytes minimum; without an explicit length
field the receiver cannot distinguish real payload from zero padding
(e.g. a 6-byte DISCOVER becomes 46 bytes after padding, failing the
'payload must be empty' check).
Header is now 8 bytes: [ver:1][type:1][session_id:4][payload_len:2]
(both multi-byte fields big-endian). The receiver slices exactly
payload_len bytes and ignores trailing padding.
Updated PROTOCOL.md, Rust frame.rs, and C# Frame.cs.
- io::last_os_error() -> io::Error::last_os_error()
- MacAddr(mac.0) -> MacAddr(mac.octets()) for pnet 0.35
- cast htons() result to c_int for libc::socket protocol arg
- mark read as mut in spawn_pump