diff --git a/FORK_PRS.md b/FORK_PRS.md index 9891c57..8068edd 100644 --- a/FORK_PRS.md +++ b/FORK_PRS.md @@ -29,17 +29,17 @@ become its own scoped PR. Issue numbers filled in once created. | 9 | ✅ [#28](https://github.com/fugo101/microlink/issues/28) (done) | [`antmanler/microlink`](https://github.com/antmanler/microlink) | `2a7ba328` | WG netif MTU 1420→1280 (Tailscale-standard). Verified still needed: despite `CLAUDE.md` documenting `CONFIG_LWIP_IP4_REASSEMBLY=y` as required, no example's `sdkconfig.defaults` actually sets it, and ESP-IDF's own Kconfig default for `LWIP_IP4_REASSEMBLY` is `n` — so on a stock build, reassembly really is off and 1420-byte inner packets over a 1500-byte WiFi MTU silently fragment-and-drop. Landed together with issue #26 (same commit, same files). | 1 | | 10 | ✅ [#29](https://github.com/fugo101/microlink/issues/29) (done) | [`liestrela/microlink`](https://github.com/liestrela/microlink) | `1649d987` | Gate ESP32 temp-sensor feature behind `CONFIG_SOC_TEMP_SENSOR_SUPPORTED` — `esp_driver_tsens` was an unconditional `REQUIRES`, breaks build on SoC variants without a temp sensor. Cherry-picked verbatim, no adaptation needed. | 1 | | 11 | ✅ [#30](https://github.com/fugo101/microlink/issues/30) (done) | `cplewes` vs `Csontikka` (conflict) | `cplewes` `83a102be`/`01d51697` vs [`Csontikka/microlink`](https://github.com/Csontikka/microlink) `dd5714c4`→`2e68e546` | `ip_input()` vs `netif->input`/`tcpip_input` threading fix for decrypted WG RX pbufs — cplewes fixes a UAF this way, Csontikka's own branch later reverted the equivalent fix citing a throughput regression (~30pps cap). **Resolved by verification, not a port**: `git blame` shows `components/wireguard_lwip/src/wireguardif.c`'s RX hand-off has called `device->netif->input(pbuf, device->netif)` since the submodule's very first commit (`193aac6`, 2026-08-14, predates this survey), with its own comment citing a double-free at `pbuf.c:753` as the reason. `ml_wg_mgr.c:320` sets `netif->input = tcpip_input` unconditionally, so this call always dispatches to `tcpip_input` — both `cplewes`'s and Csontikka's first fix (`dd5714c4`) independently arrive at the same place we already were. Csontikka's later revert (`2e68e546`) only makes sense in a codebase where `netif->input` gets reconfigured back to raw `ip_input` elsewhere; ours never does, so the ~30pps throughput-ceiling tradeoff they measured is a separate, real, but *architectural* question (would need something like `ml_zerocopy.c`'s raw-PCB pattern extended to WG RX) — not in scope for this issue, and not something our own testing docs currently flag as a problem. No code change needed. | 2 | -| 12 | [#31](https://github.com/fugo101/microlink/issues/31) | `Csontikka/microlink` | `647c2ab0` | `LOCK_TCPIP_CORE` around `netif_set_link_up/down` — compare against our documented `netif->state` NULL-and-restore workaround in `ESP_IDF_6X_COMPAT.md` before adopting | 2 | +| 12 | [#31](https://github.com/fugo101/microlink/issues/31) | `Csontikka/microlink` | `647c2ab0` | `LOCK_TCPIP_CORE` around `netif_set_link_up/down` — compare against our documented `netif->state` NULL-and-restore workaround in `ESP_IDF_6X_COMPAT.md` before adopting. **Investigated, not needed**: `LOCK_TCPIP_CORE()`/`UNLOCK_TCPIP_CORE()` expand to nothing when `LWIP_TCPIP_CORE_LOCKING` is disabled (this fork's default in every example — confirmed in `lwip/tcpip.h`), so the fix is a no-op here. Its `ip_input()`→`tcpip_input()` change also duplicates what this fork already does independently (see issue #30's resolution). The rest of the commit disables WireGuard's cryptokey-routing source-IP validation entirely ("accept all source IPs") plus scattered debug `printf`s — a security-relevant scope change contradicting the `GrieferPig/microlink` "not worth pursuing" entry below (praised for having *correct* src-IP validation), not something to fold in silently. No port planned. | 2 | | 13 | ✅ [#32](https://github.com/fugo101/microlink/issues/32) (done) | `Csontikka/microlink` | `5bda1783` | Peer direct-handshake init was one-shot; peers with dropped/unanswered handshakes stayed permanently blackholed — retry every 30s via timestamp instead of boolean latch. Adapted, not literal cherry-pick: the source commit's diff still cleared `peer->active` after `wireguardif_connect()`, which issue #26/#28's PR #53 (same session) proved permanently blocks a peer's handshake — kept that fix removed while porting the retry-timestamp logic. | 2 | | 14 | [#33](https://github.com/fugo101/microlink/issues/33) | `Csontikka/microlink` | `2e68e546`, `f1de3143` | DISCO trust-expiry gate (15s→60s, checks `last_rx` first), NAT-rebind handshake-skip when data path still alive, SPIRAM pbuf headroom fix for `wg_udp_output_cb`. **2/3 done**: the trust-expiry gate and NAT-rebind handshake-skip landed (both self-contained to `ml_wg_mgr.c`/`microlink_internal.h`, no submodule involvement). The SPIRAM pbuf change deliberately deferred — it rewrites `wg_udp_output_cb`'s allocation (the same function PR #53 just changed for thread safety), uses a hand-computed `LWIP_MEM_ALIGN_SIZE` header offset the source fork's own history shows they got wrong once already (shipped corrupted data), and can't be verified without real hardware. Not worth the risk in this sandbox; issue stays open for that piece. The bundled diagnostic-dump function (`dump_wg_state_snapshot`) was skipped as debug cruft, same as prior sessions' extractions. | 2 | -| 15 | [#34](https://github.com/fugo101/microlink/issues/34) | `Csontikka/microlink` | `b7442d0f` | Handshake retries throttled to 1/tick round-robin instead of firing to every eligible peer in one tick (was blocking the caller ~280ms with 7 peers) | 2 | +| 15 | [#34](https://github.com/fugo101/microlink/issues/34) | `Csontikka/microlink` | `b7442d0f` | Handshake retries throttled to 1/tick round-robin instead of firing to every eligible peer in one tick (was blocking the caller ~280ms with 7 peers). **Adapted, landed in the `wireguard_lwip` submodule** (not this repo — the fix lives entirely in `wireguardif.c`): [`fugo101/wireguard-lwip#15`](https://github.com/fugo101/wireguard-lwip/pull/15), merged. Awaiting the submodule's release-please PR ([`#16`](https://github.com/fugo101/wireguard-lwip/pull/16), "release 1.0.2") to merge, then a follow-up PR here bumping the submodule pointer (same two-step flow as issue #43's TAI64N fix, `#46`). | 2 | | 16 | [#35](https://github.com/fugo101/microlink/issues/35) | `Csontikka/microlink` | `7a24a9b3`, `4d3b3add` | DERP client backpressure/reconnect-storm fixes: don't tear down on TLS write backpressure, TCP_NODELAY + coalesced writes, fix a hot-spinning I/O loop, split into concurrent reader/writer tasks — check overlap against cplewes's DERP session-resumption fix (#6) before scoping. **Investigated, needs a dedicated session**: the reader/writer task split is a real architectural conflict, not just a diff to adapt — `ml_derp.c`'s own file header documents this fork's `derp_tx` as a deliberate single task specifically so no TLS mutex is needed ("eliminates the need for a TLS mutex since only one task touches the SSL context"). Splitting it would need real synchronization design, not a surgical port. The backpressure/TCP_NODELAY/hot-spin fixes are smaller and probably extractable independently, but weren't triaged individually this pass — do that first next time rather than trying to take the whole bundle. Also touches `components/wireguard_lwip/` (submodule boundary, same as #31/#34/#42). | 2 | | 17 | [#36](https://github.com/fugo101/microlink/issues/36) | `Csontikka/microlink` | `27806be3` | `microlink_stop()` never closed `derp.sockfd`/`coord_sock`, letting `derp_tx` outlive the teardown wait → UAF — reconcile against cplewes's teardown UAF fix (#2), may be the same root cause. **Investigated, not needed here**: this fork's `microlink_stop()` (from issue #21/#22's PR #47) never frees context until `ml_join_tasks()` proves every worker exited, and `ml_derp.c`'s blocking loops already call `ml_shutdown_pending()` on every SO_RCVTIMEO-bounded iteration (100-200ms) to bail out cooperatively — the source commit's "shutdown() the socket to force-wake a blocked task" fixes a UAF that doesn't exist here. Leaving open in case future review disagrees, but no port planned. | 2 | | 18 | [#37](https://github.com/fugo101/microlink/issues/37) | `Csontikka/microlink` | `cbdf1603`, `aad403af`, `533f1f88`, `46e34917`, `017b3588`, `372ca277` | H2 frame reassembly across `noise_recv()` read boundaries — large MapResponses spanning reads deterministically corrupt the stream ("implausible message size"); genuine protocol-correctness bug independent of control-plane backend. **Triaged into 4 pieces — 1/4 landed**: (1) `cbdf1603` (`https://` login_server + Headscale Noise key fetch), `aad403af` ("deliver the netmap from the long-poll stream, Headscale ≥0.26"), and `372ca277` (Headscale v0.28 single-stream compat) are all pure Headscale-control-plane compatibility, out of scope per `CLAUDE.md` (Tailscale-only) — excluded, no port. (2) `533f1f88` bundles two fixes: its stream-liveness watchdog (a second clock fed only by genuine stream-5 DATA frames, so a front end that keeps ACKing our PINGs can't hide a dead server-side mapSession) is real, backend-independent, and **landed** — this fork's existing watchdog (`last_activity_ms`) resets on any inbound *or even outbound-send* activity, so it had exactly this blind spot. Its second half (reorder `ML_EVT_COORD_REGISTERED` to fire after the streamed netmap, not before) is **not applicable**: that race only exists on Csontikka's Headscale ≥0.26 empty-initial-fetch path; this fork's `do_fetch_peers()` always populates `ml->vpn_ip` synchronously before returning, so `ML_EVT_COORD_REGISTERED` already fires after the VPN IP is known — skipped. (3) `46e34917` (DERP relay liveness + peer sweep) needs reconciliation against issue #14's already-landed DERP TLS leak fix (PR #44) before scoping — likely partial overlap, not yet investigated in detail. (4) `017b3588`, the actual H2-reassembly fix this row was originally filed for, is large (287+/-101 lines) and rewrites `do_map_exchange()` — the same hottest, most failure-sensitive control-plane parsing path already flagged as needing hardware to verify for issue #38 — deferred to a dedicated session with real testing. | 2 | | 19 | [#38](https://github.com/fugo101/microlink/issues/38), [#39](https://github.com/fugo101/microlink/issues/39) | [`djorr5/microlink`](https://github.com/djorr5/microlink) | `67b230b2` | Two independent changes, split into two issues: (a) dynamic H2 RX window sizing based on free heap for RAM-constrained boards, roughly halving MapResponse-parsing PSRAM footprint; (b) `ip4_route_src_hook` to force tailnet-range traffic onto the WG netif directly. **Investigated**: no submodule involvement, both fully in-repo (`ml_h2.c`/`ml_coord.c` for (a), new `ml_lwip_hooks.c` for (b)). (a) is real and reasonably self-contained but rewrites the hottest control-plane parsing path (`do_fetch_peers()`'s buffer allocation and read loop) without hardware to verify it — needs a dedicated session with real testing, not a quick port. (b) is likely **redundant**: lwIP's own `ip4_route()` already scans `netif_list` for a netmask match *before* ever consulting `LWIP_HOOK_IP4_ROUTE_SRC` (confirmed by reading `ip4.c`), and `wg_init_interface()` already registers the WG netif directly into `netif_list` with the correct `/10` netmask — so the hook's netmask-match logic duplicates what already happens. Might still matter in a narrow edge case (netif up/link-up flapping during rebind) but not clearly worth the new file + build wiring for that alone. | 2 | | 20 | [#40](https://github.com/fugo101/microlink/issues/40) | [`AELovelace/LAIN-MicrolinkRouter`](https://github.com/AELovelace/LAIN-MicrolinkRouter) | `e1239460` | `microlink_set_exit_node()` — default-route exit-node support while preserving per-peer `/32` routes, with routing-loop and liveness fixes. New capability, not a bugfix — needs a product decision (does any current/future downstream want SoftAP/NAPT exit-node routing?) before it's worth the review cost | 2 | | 21 | [#41](https://github.com/fugo101/microlink/issues/41) | [`caslavskola/microlink`](https://github.com/caslavskola/microlink) | `0265718e` | PSA crypto init migration for mbedTLS 4.x. **Investigated, not needed**: ESP-IDF 6.x's own `mbedtls` component already calls `psa_crypto_init()` automatically at boot (`ESP_SYSTEM_INIT_FN`, priority 104, `components/mbedtls/port/esp_psa_crypto_init.c`) — an explicit call in `microlink_init()` would be pure redundancy. The commit also rewrites `ml_noise.c`'s ChaCha20-Poly1305 from `mbedtls_chachapoly_*` to raw PSA `psa_aead_encrypt/decrypt` calls, but this fork already has a working, cleaner solution via `mbedtls/private/chachapoly.h` (documented in `ESP_IDF_6X_COMPAT.md`) — the source commit's version is messier (leftover `//to remove` debug logging, commented-out ChatGPT-added diagnostics) and fixes nothing we're missing. No port planned. | 2 | -| 22 | [#42](https://github.com/fugo101/microlink/issues/42) | `caslavskola/microlink` | `9ac49212` | Peer endpoint tracking dropped the "packet arrived via DERP" signal after the first packet, causing replies to attempt bad direct routing — genuine bug, but the commit bundles debug cruft and a divergent netif-flag rewrite; extract just the DERP-routing-flag fix | 2 | +| 22 | [#42](https://github.com/fugo101/microlink/issues/42) | `caslavskola/microlink` | `9ac49212` | Peer endpoint tracking dropped the "packet arrived via DERP" signal after the first packet, causing replies to attempt bad direct routing — genuine bug, but the commit bundles debug cruft and a divergent netif-flag rewrite; extract just the DERP-routing-flag fix. **Adapted, landed in the `wireguard_lwip` submodule** (extracted just the `last_rx_via_derp` flag, skipped the `netif_set_link_up/down` rewrite and debug logging): [`fugo101/wireguard-lwip#15`](https://github.com/fugo101/wireguard-lwip/pull/15) (same PR as issue #34, both fixes are small and independent), merged. Awaiting the submodule's release-please PR ([`#16`](https://github.com/fugo101/wireguard-lwip/pull/16), "release 1.0.2") to merge, then a follow-up PR here bumping the submodule pointer. | 2 | | 23 | [#43](https://github.com/fugo101/microlink/issues/43) | [`dj-oyu/microlink`](https://github.com/dj-oyu/microlink) | multiple (different/pre-refactor file naming) | Bundle of fixes needing adaptation to our `ml_*.c` layout: ~~TAI64N via `gettimeofday()` (fixes replay-rejection after reboot)~~ **superseded — see `UPSTREAM_PRS.md`'s upstream PR #22 (partial) absorption, commit `6a4447c5`: cleaner source, no pre-refactor adaptation needed, don't redo this from dj-oyu**; DERP→direct re-handshake trilogy (`a30160a8`, `eb3dce06`, `c505539d`), `LOCK_TCPIP_CORE` no-op bug fixed via `tcpip_try_callback` (check `ml_net_io.c`/`ml_zerocopy.c` exposure), DISCO PONG rate-limiting (1/5s per peer once direct path established) | 2 | ## Investigated, not worth pursuing