From 9a23f367481858e3c33c1fb80ad492131e4d3136 Mon Sep 17 00:00:00 2001 From: Leadaxe <247031499+Leadaxe@users.noreply.github.com> Date: Sat, 18 Jul 2026 11:26:09 +0200 Subject: [PATCH] lx: re-graft egress-provider API onto AWG2 base (upstream 6f5e8b1947ae) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Upstream wireguard-go added an EgressProvider hook to StdNetBind (egress anchoring for TUN auto-redirect): EgressProvider interface, egressProvider field, SetEgressProvider, plus egress branches in Open/Send/Close and a standardEndpoint cast hoist in Send. sing-box's endpoint-listen refactor now calls StdNetBind.SetEgressProvider, so our AWG2 fork (which was one wireguard-go revision behind) failed to build. Applied the upstream delta to conn/bind_std.go verbatim, then re-applied SPEC 026: gate BOTH reserved-clear sites behind hasReserved() — - main receiveIP path (msg.N > 3 && s.hasReserved()) [existing] - NEW egress receive path (dataLength > 3 && s.hasReserved()) Upstream's egress hook re-introduced an UNCONDITIONAL common.ClearArray( bufs[0][1:4]) — the exact anti-pattern SPEC 026 fixed. Gating it keeps a small-padding AmneziaWG magic (bytes 1-3) intact when no WARP reserved value is set, and STILL fires for WARP-over-egress: the egress bind is only created on the isUDPListener path, where SetReservedForEndpoint is called for every peer, so hasReserved() is true in that scenario. Verified: WARP egress unaffected, AWG magic survives, conn tests green. reservedForEndpoint is populated before receive goroutines start and never mutated after (same lock-free invariant SPEC 026 already relies on). --- conn/bind_std.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conn/bind_std.go b/conn/bind_std.go index c3a11a0..eb27e10 100644 --- a/conn/bind_std.go +++ b/conn/bind_std.go @@ -272,7 +272,7 @@ again: return 0, err } sizes[0] = dataLength - if dataLength > 3 { + if dataLength > 3 && s.hasReserved() { // lx: SPEC 026 — gate reserved-clear on the egress receive path too, so a small-padding AmneziaWG magic in bytes 1-3 survives when no WARP reserved value is set common.ClearArray(bufs[0][1:4]) } endpoints[0] = &StdNetEndpoint{AddrPort: source}