The gateway now runs the actual frame bridge after relay admission. It registers
the AF_PACKET socket with Tokio using AsyncFd, reads valid LAN Ethernet frames
and forwards them as relay datagrams, and writes valid relay Ethernet datagrams
back to the LAN socket.
The packet socket is opened nonblocking so the bridge can shut down cleanly on
Ctrl-C without leaving a blocking recv thread behind. Existing send_ethernet and
recv_ethernet helpers now share the same validation and encoding helpers used by
the bridge.
This still needs a privileged LAN-host smoke test with a real wired interface,
but the compile-time and loopback coverage now include the gateway relay side of
the bridge and the non-root-safe packet-socket validation.
Test Plan:
- cargo fmt --check
- cargo test --workspace
- cargo clippy --workspace --all-targets -- -D warnings
Refs: PLAN.md gateway AF_PACKET to relay bridge loop
GatewayConnection can now send and receive Ethernet frames over the admitted
relay QUIC connection. Outgoing frames are wrapped in the shared overlay format
with the gateway's assigned room id and peer id; incoming datagrams are ignored
unless they are Ethernet frames for the assigned room from another peer.
The receive helper also parses the payload as an Ethernet frame before exposing
it, which keeps the future AF_PACKET bridge from injecting malformed runt
payloads if the relay path ever misbehaves.
The loopback connector test now verifies the full post-handshake datagram path:
the gateway sends a frame to the test relay, the relay validates the overlay
metadata, and the gateway receives a relay-sent Ethernet frame back.
Test Plan:
- cargo fmt --check
- cargo test --workspace
- cargo clippy --workspace --all-targets -- -D warnings
Refs: PLAN.md gateway relay datagram send/receive
The gateway now has a small Linux PacketSocket wrapper for raw Ethernet frame
I/O. It resolves the configured interface with if_nametoindex, opens an
AF_PACKET/SOCK_RAW socket for ETH_P_ALL, binds it to the interface, and exposes
thin send_frame and recv_frame helpers around the owned file descriptor.
The gateway binary opens this socket after completing the relay control
handshake. The frame bridge loop is still intentionally left for a later slice,
but the process now proves the two required resources are available: relay
admission and raw L2 access on the LAN interface.
Tests cover interface-name validation and missing-interface lookup without
requiring root or CAP_NET_RAW.
Test Plan:
- cargo fmt --check
- cargo test --workspace
- cargo clippy --workspace --all-targets -- -D warnings
Refs: PLAN.md Linux AF_PACKET gateway socket
The gateway binary now has a real relay-facing configuration and QUIC control
handshake. It accepts a relay socket address, expected TLS server name, pinned
DER relay certificate, room code, LAN interface name, and advertised datagram
budget, then connects as role = gateway and waits for a welcome response.
The ALPN token moved into lanparty-ctrl so relay and gateway share the same
protocol identifier instead of carrying duplicate private constants. The gateway
still stops after the control-plane connection; AF_PACKET capture and injection
remain a later slice.
The connector test spins up a local Quinn server with a self-signed certificate,
trusts that certificate explicitly, verifies the outgoing gateway hello, and
checks the received welcome metadata.
Test Plan:
- cargo fmt --check
- cargo test --workspace
- cargo clippy --workspace --all-targets -- -D warnings
Refs: PLAN.md Linux gateway outbound relay connection