Added per-network LAN broadcast relay
LAN game discovery previously dropped IPv4 broadcasts at TUN ingress. Carry limited and subnet-directed UDP broadcasts to authenticated, opted-in members of the source network, including destinations reached through mesh relays. Preserve the original IP/UDP bytes and deliver received broadcasts only to the local TUN; never reflood them or expose another pair's plaintext at transit. Build immutable recipient snapshots on address and participation changes. The origin sends one ordinary end-to-end encrypted copy per recipient; the existing fast, bounded-hop transport router remains unchanged. Validate UDP framing, source ownership and destination admission without game-specific port rules. Keep network domains isolated and refuse implicit gateways to physical LANs. The separate broadcast policy/domain layer is the extension point for future authorized subnet exports; physical capture, bridging and LAN deduplication are deliberately not implemented yet. Persist default-on participation independently for each local network. Add join --no-broadcast/--broadcast and network broadcast <id> [on|off], including live updates and authenticated announcements. Joining without a flag preserves the saved choice. Opt-out stops local origination and delivery, while opaque unicast transit for other members keeps working. Migrate SQLite schema 3 to 4 without replacing identities or signed state. Use control ALPN 3 and local IPC protocol 14 for the new announcement/request shapes; update peers and restart running agents together. The data ALPN 4 envelope remains unchanged. No release version bump, tag or push is included. Document agent-owned commits in AGENTS.md: short English subjects, explanatory bodies, scoped staging, honest validation, and repository-local fallback author AB <ab@hexor.cy> only when an effective name/email is missing. Release actions remain the user's responsibility. Validation on Windows: cargo fmt --all -- --check; cargo check --locked --workspace --all-targets; cargo clippy --locked --workspace --all-targets -- -D warnings; release workspace/all-target tests: 313 passed. The two existing SQLite wipe failures (a_wipe_removes_everything_and_the_next_start_is_a_stranger and wiping_twice_is_as_ordinary_as_wiping_once) were explicitly skipped; the public-DHT smoke test and forwarding benchmark remain ignored by default. New coverage exercises real iroh/WireGuard multihop fanout, single delivery, runtime opt-out, unicast replies, domain isolation, malformed input and schema migration. TUNs are in-memory; actual games and OS adapter selection were not tested.
This commit is contained in:
@@ -0,0 +1,91 @@
|
||||
# LAN discovery broadcasts
|
||||
|
||||
Broadcast participation is a **local setting of each network**, enabled by
|
||||
default. Different networks on the same agent can have different settings;
|
||||
each member advertises whether it accepts broadcasts over its authenticated
|
||||
control session. It is not a network-wide vote or signed shared configuration.
|
||||
|
||||
```sh
|
||||
tsunagi join -n games --no-broadcast
|
||||
tsunagi join -n games --broadcast
|
||||
tsunagi network broadcast <network-id-or-prefix> off
|
||||
tsunagi network broadcast <network-id-or-prefix> on
|
||||
tsunagi network broadcast <network-id-or-prefix>
|
||||
```
|
||||
|
||||
Joining without either flag preserves the saved choice. The `network broadcast`
|
||||
command can change a running network immediately or configure it while the
|
||||
agent is stopped. `status` reports the local setting. There is no global `up`
|
||||
override: starting the agent preserves every network's independent policy.
|
||||
|
||||
## Delivery
|
||||
|
||||
At local TUN ingress, the IP router recognizes IPv4 UDP addressed to the limited
|
||||
broadcast `255.255.255.255` or the configured overlay subnet's directed broadcast
|
||||
(for example `10.13.37.255` for `/24`). These address forms follow
|
||||
[RFC 1122 section 3.3.6](https://www.rfc-editor.org/rfc/rfc1122#section-3.3.6).
|
||||
There is no port allowlist: discovery requests and server announcements on
|
||||
game-specific UDP ports use the same mechanism. IPv4/UDP lengths are checked
|
||||
before fanout, including handling IP fragments. IPv6 multicast, mDNS, DHCP
|
||||
bridging, Ethernet/IPX and physical LAN capture are outside this feature.
|
||||
|
||||
The local source address selects exactly one broadcast domain. A limited
|
||||
broadcast is never copied into all networks merely because they share a TUN.
|
||||
A directed broadcast must belong to that source's network. Unspecified sources
|
||||
and physical LAN sources have no authorized domain yet. Recipients are live,
|
||||
authenticated, opted-in members with signed overlay address ownership. The
|
||||
immutable recipient list is rebuilt with address/policy changes, not per packet.
|
||||
|
||||
The origin creates **one encrypted unicast copy per eligible peer** and hands it
|
||||
to the existing shortest-path router. Each can travel through several transport
|
||||
links. Transit handles opaque ciphertext with the existing hop limit and does
|
||||
not create another fanout. The original IP source, destination, TTL, UDP ports,
|
||||
checksum and payload remain unchanged. Reply packets use ordinary unicast.
|
||||
There is no broadcast retransmission timer or application-payload deduplication:
|
||||
games may legitimately repeat the same discovery query. WireGuard replay checks
|
||||
reject duplicated encrypted packets delivered by the transport.
|
||||
|
||||
At the destination, the usual authenticated-source ownership check still runs.
|
||||
Broadcast admission also checks the receiving network's setting, the sender's
|
||||
announced participation, the destination domain and UDP framing. Disabling it
|
||||
takes effect locally even while a remote sender still has an older announcement.
|
||||
Received broadcasts terminate in the local TUN and never enter the fanout path.
|
||||
An ordinary decrypted packet must target this host's address in that network;
|
||||
the TUN is not a transit gateway to another overlay or physical subnet.
|
||||
|
||||
Opt-out disables originating and accepting broadcasts on that host/network.
|
||||
It does not disable opaque unicast transit for other members: intermediate
|
||||
routers cannot inspect another pair's encrypted IP payload.
|
||||
|
||||
## Host behavior and verification
|
||||
|
||||
The game must send discovery through the Tsunagi interface. Traffic bound to a
|
||||
physical adapter never reaches this TUN, and this feature does not capture it.
|
||||
The suite tests real agents, authenticated iroh links and WireGuard encryption
|
||||
with memory TUNs: limited/directed UDP discovery, multihop fanout, single-copy
|
||||
delivery, opt-out, unicast replies, malformed input, source validation and
|
||||
network isolation. It does not launch CS 1.6 or Warcraft III or establish that
|
||||
every game/host chooses the virtual adapter automatically.
|
||||
|
||||
## Future exported LANs
|
||||
|
||||
`overlay::broadcast` owns domain selection and recipient policy separately from
|
||||
IP parsing, encryption and encrypted transit. A future LAN adapter should feed
|
||||
an explicitly authorized ingress domain into this layer, and export routes
|
||||
through the corresponding source/destination admission policy. It must not
|
||||
relax address checks globally or reinterpret all `.255` addresses as broadcasts.
|
||||
Multiple gateways to the same LAN will need origin identifiers and bounded
|
||||
duplicate suppression at LAN ingress/egress before physical rebroadcast is
|
||||
enabled. No subnet export or host forwarding configuration is added here.
|
||||
|
||||
## Compatibility
|
||||
|
||||
Control ALPN is `tsunagi/ctrl/3` because `Announce` now carries participation.
|
||||
The encrypted transit envelope and data ALPN `tsunagi/data/4` stay unchanged.
|
||||
Local control protocol 14 rejects commands from mismatched running binaries
|
||||
with a restart message instead of decoding a different request shape.
|
||||
Upgrade all members and restart the agent before using the new CLI.
|
||||
|
||||
SQLite schema 4 adds `networks.broadcast` with default `1`. Existing network
|
||||
names, secrets, identity keys and signed records are retained. The old binary
|
||||
does not understand schema 4; the migration is not a downgrade mechanism.
|
||||
Reference in New Issue
Block a user