From fb6f2c305c8ceffe0670378d48c9dec6ff962ea5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Damian=20K=C4=99ska?= <372403+keskad@users.noreply.github.com> Date: Sat, 22 Aug 2026 15:13:51 +0200 Subject: [PATCH] fix(longfred): use 192.168.4.0/24 Soft-AP commissioning addresses Align the driver with current LongFred firmware so hub programming no longer collides with the BigFred LAN. Co-authored-by: Cursor --- CHANGELOG.md | 7 ++++++ crates/wp-core/src/capabilities.rs | 4 ++-- crates/wp-drivers/src/longfred/constants.rs | 4 ++-- crates/wp-drivers/src/longfred/mod.rs | 2 +- crates/wp-link/src/http.rs | 7 +++--- crates/wp-link/src/netcfg.rs | 9 +++++--- docs/drivers/longfred.md | 25 +++++++++------------ docs/drivers/wifred.md | 2 +- 8 files changed, 33 insertions(+), 27 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a2fcfc7..7ffb3b5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Changed + +- LongFred Soft-AP commissioning addresses are now `192.168.4.1` / source + `192.168.4.2` (ESP-IDF default, same as WiFred). This no longer overlaps + the BigFred hub LAN (`192.168.0.0/24`). Requires matching LongFred + firmware; older devices at `192.168.0.1` will not program. + ## [v0.2] — 2026-08-22 Hub Soft-AP programming for LongFred (and WiFred) when the device AP shares the diff --git a/crates/wp-core/src/capabilities.rs b/crates/wp-core/src/capabilities.rs index 8ba3e42..41d24c5 100644 --- a/crates/wp-core/src/capabilities.rs +++ b/crates/wp-core/src/capabilities.rs @@ -43,11 +43,11 @@ impl From for CommissioningKindWire { /// daemon keeps its historical defaults (`192.168.4.1` / `192.168.4.2/24`). #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct CommissioningNet { - /// Device Soft-AP address (e.g. `192.168.0.1`). + /// Device Soft-AP address (e.g. `192.168.4.1`). pub host: Ipv4Addr, /// HTTP port on the Soft-AP (typically 80). pub port: u16, - /// Address the hub assigns on the wireless interface (e.g. `192.168.0.2`). + /// Address the hub assigns on the wireless interface (e.g. `192.168.4.2`). pub source: Ipv4Addr, /// Prefix length for the on-link route (typically 24). pub prefix: u8, diff --git a/crates/wp-drivers/src/longfred/constants.rs b/crates/wp-drivers/src/longfred/constants.rs index 3013fdc..d6ecc37 100644 --- a/crates/wp-drivers/src/longfred/constants.rs +++ b/crates/wp-drivers/src/longfred/constants.rs @@ -11,10 +11,10 @@ pub const WIFI_CONFIG_SSID_PREFIX: &str = "longfred_prog"; pub const CONFIG_AP_PORT: u16 = 80; /// Config AP address (firmware static Soft-AP IP). -pub const CONFIG_HOST: Ipv4Addr = Ipv4Addr::new(192, 168, 0, 1); +pub const CONFIG_HOST: Ipv4Addr = Ipv4Addr::new(192, 168, 4, 1); /// Source address the daemon assigns to the wireless interface. -pub const CONFIG_SOURCE: Ipv4Addr = Ipv4Addr::new(192, 168, 0, 2); +pub const CONFIG_SOURCE: Ipv4Addr = Ipv4Addr::new(192, 168, 4, 2); /// On-link prefix length for the config AP subnet. pub const CONFIG_PREFIX_LEN: u8 = 24; diff --git a/crates/wp-drivers/src/longfred/mod.rs b/crates/wp-drivers/src/longfred/mod.rs index dd368ac..603a21f 100644 --- a/crates/wp-drivers/src/longfred/mod.rs +++ b/crates/wp-drivers/src/longfred/mod.rs @@ -2,7 +2,7 @@ //! //! Implements [`wp_core::DeviceDriver`] for LongFred throttles in programming //! mode. The firmware raises an open Soft-AP named `longfred_prog_XXXXXX` with -//! a static address `192.168.0.1/24` and serves: +//! a static address `192.168.4.1/24` and serves: //! //! - `GET /api/v1/settings` //! - `PUT /api/v1/settings` diff --git a/crates/wp-link/src/http.rs b/crates/wp-link/src/http.rs index e2c8a7e..193fe29 100644 --- a/crates/wp-link/src/http.rs +++ b/crates/wp-link/src/http.rs @@ -2,7 +2,7 @@ //! //! Plain HTTP only — Soft-AP config pages serve on an on-link address with no //! TLS. The client binds to a caller-supplied source address (e.g. -//! `192.168.4.2` or `192.168.0.2`) so requests leave the wireless interface, +//! `192.168.4.2`) so requests leave the wireless interface, //! and enforces a deadline, a maximum response body size, and a bounded retry //! count. @@ -89,8 +89,9 @@ impl BoundedHttpClient { /// Remember the wireless interface name for diagnostics and for /// `SO_BINDTODEVICE` when the destination is **not** a local address. /// - /// When the Soft-AP IP is also assigned on another interface (LongFred - /// `192.168.0.1` vs hub LAN), `SO_BINDTODEVICE` must **not** be set: + /// When the Soft-AP IP is also assigned on another interface (e.g. a + /// device AP at `192.168.0.1` vs hub LAN), `SO_BINDTODEVICE` must **not** + /// be set: /// the SYN-ACK's source is a local address, so the kernel may deliver /// it with `skb->dev = lo`, and a socket bound to `wlan0` will not match /// — Linux then generates RST (`Connection reset by peer`). Output is diff --git a/crates/wp-link/src/netcfg.rs b/crates/wp-link/src/netcfg.rs index 1f6f1a6..64d3d31 100644 --- a/crates/wp-link/src/netcfg.rs +++ b/crates/wp-link/src/netcfg.rs @@ -1,10 +1,13 @@ //! Interface-scoped IPv4 settings needed when a device Soft-AP shares a //! subnet with the hub's own LAN. //! -//! The LongFred Soft-AP serves `192.168.0.1/24`, which is also the BigFred -//! hub's LAN address. Three kernel behaviours break the HTTP conversation: +//! Historically the LongFred Soft-AP served `192.168.0.1/24`, the same +//! address as the BigFred hub LAN. Current LongFred firmware uses +//! `192.168.4.1/24` (no overlap). The helpers below still apply whenever +//! `host` is a locally-owned address — three kernel behaviours then break +//! the HTTP conversation: //! -//! 1. **Outbound SYN** — a route lookup for `192.168.0.1` hits the `local` +//! 1. **Outbound SYN** — a route lookup for the Soft-AP IP hits the `local` //! table first (pref 0) and delivers to loopback. `SO_BINDTODEVICE` does //! **not** override that: `from all lookup local` has no oif filter. //! ICMP "success" with a local route is the hub answering its own address. diff --git a/docs/drivers/longfred.md b/docs/drivers/longfred.md index 4712407..a66101c 100644 --- a/docs/drivers/longfred.md +++ b/docs/drivers/longfred.md @@ -7,31 +7,26 @@ programming mode. In programming mode the firmware raises an **open** WiFi AP named `longfred_prog_XXXXXX` (6 hex characters derived from the MAC). The Soft-AP -uses a static address `192.168.0.1/24` (not the ESP-IDF Soft-AP default of -`192.168.4.1`) and a DHCP pool `192.168.0.50–200`. The wireless-programmer +uses a static address `192.168.4.1/24` (ESP-IDF Soft-AP default, same as +WiFred) and a DHCP pool `192.168.4.50–200`. The wireless-programmer source address `.2` is **outside** that pool. The driver advertises this via `capabilities.commissioningNet`: | Field | Value | |----------|----------------| -| `host` | `192.168.0.1` | +| `host` | `192.168.4.1` | | `port` | `80` | -| `source` | `192.168.0.2` | +| `source` | `192.168.4.2` | | `prefix` | `24` | -The daemon should associate to the open AP, assign `192.168.0.2/24` on the +The daemon should associate to the open AP, assign `192.168.4.2/24` on the wireless interface (**no default route**), hand a sync `HttpClient` to the driver, and release the radio on every exit path. -> **Address collision with hub LAN.** The BigFred hub serves its own LAN from -> `192.168.0.1/24`, so `192.168.0.1` is a local address on the hub's Ethernet. -> The daemon parks `lookup local` at pref 1 and installs -> `from 192.168.0.2 to 192.168.0.1 lookup 100` at pref 0, with -> `192.168.0.1/32 dev wlan0` in table 100. The HTTP client binds -> `192.168.0.2` but **does not** set `SO_BINDTODEVICE` for this destination -> (that made the kernel RST the SYN-ACK). Inbound still needs -> `accept_local=1` and `rp_filter=0` on `wlan0`. Restored on radio release; -> see `wp_link::netcfg`. +This subnet does **not** overlap the BigFred hub LAN (`192.168.0.0/24`), so +the `wp_link::netcfg` policy-route path for a locally-owned destination is +not needed for LongFred. The radio still installs the generic Soft-AP +sysctls; they are a no-op when `host` is not a local address. Candidate identity: SSID prefix `longfred_prog`, stable key = BSSID. @@ -45,7 +40,7 @@ Candidate identity: SSID prefix `longfred_prog`, stable key = BSSID. | `supportsThrottleServer` | true (field accepted, unused) | | `supportsFirmwareUpdate` | true | | `commissioning` | `SoftAp` | -| `commissioningNet` | `192.168.0.1` / source `.2` /24 | +| `commissioningNet` | `192.168.4.1` / source `.2` /24 | `identity` is written as `wifi.hostname`. BigFred authentication uses the optional `bigfred.login` / `bigfred.pin` fields on `ProgramRequest` (not the diff --git a/docs/drivers/wifred.md b/docs/drivers/wifred.md index 3f4d2aa..81b5392 100644 --- a/docs/drivers/wifred.md +++ b/docs/drivers/wifred.md @@ -26,7 +26,7 @@ The HTTP client is bound to the wireless device (`SO_BINDTODEVICE`) and the radio installs a policy route plus `accept_local` / `rp_filter` on that device, so commissioning works even when the Soft-AP subnet collides with a local interface. WiFred's `192.168.4.0/24` does not normally collide with the -hub LAN; see `docs/drivers/longfred.md` for the case where it does. +hub LAN; LongFred now uses the same `192.168.4.0/24` subnet. ## Capabilities