ulfius: client_address carries the whole peer sockaddr; forgectrl.auth asserts the loopback report is accepted

The dual-stack listener reports every peer as a sockaddr_in6; ulfius
2.7.15 copied sixteen bytes of it, so forgectrl's loopback-only cooling
channel refused the controller's every report (403 loopback only) and
the engine never saw a run or an armed window. The recipe carries the
patch: a sockaddr_storage allocation and a copy of the family's length,
in the dispatcher and in ulfius_copy_request.

forgetest: forgectrl.auth asserts POST /cool/state from loopback -> 200
beside the LAN 403, and covers src/peer.*. BRINGUP item 21 and the
campaign log record how the campaign on dev 20260824215906 found it.
This commit is contained in:
ScottW514
2026-08-24 19:02:52 -04:00
parent 4d3d173445
commit 243320f65d
5 changed files with 147 additions and 5 deletions
+14 -3
View File
@@ -6,7 +6,7 @@ import time
from ..catalog import test
from .. import hw
_COVERS_AUTH = [("forgectrl", "src/auth.*"), ("forgectrl", "src/main.c")]
_COVERS_AUTH = [("forgectrl", "src/auth.*"), ("forgectrl", "src/peer.*"), ("forgectrl", "src/main.c")]
def lan_ip():
@@ -29,7 +29,8 @@ def lan_ip():
covers=_COVERS_AUTH,
description="Every state-changing endpoint refuses an unauthenticated write; a non-literal "
"Host, a non-literal Origin and a cross-site Sec-Fetch-Site are refused; the "
"cooling report channel refuses a non-loopback peer; the fuse view is two-factor "
"cooling report channel accepts the loopback peer and refuses a non-loopback "
"one; the fuse view is two-factor "
"(token and the physical button) and refused without either; "
"the flash and factory-restore chain is refused unauthenticated.")
def auth(ctx):
@@ -93,7 +94,17 @@ def auth(ctx):
"GET /fuse-identity with the token but no button -> %s %r (expected the two-factor refusal)",
st, body)
# the cooling report channel: loopback only, even with a token
# the cooling report channel: the loopback peer is accepted. An idle
# report is what the controller sends every period; the engine is idle
# here, so it changes nothing. A dual-stack listener reports this peer
# as ::ffff:127.0.0.1, which the check must recognize in full.
st, body = fc.post("/cool/state", params={"mode": "idle", "armed": "0"})
ev["cool_state_from_loopback"] = st
ctx.log("POST /cool/state from loopback -> %s %s", st, body if isinstance(body, dict) else "")
ctx.check(st == 200, "/cool/state refused the loopback peer (%s %r): the controller's "
"reports never reach the engine", st, body)
# ...and a non-loopback peer is refused, even with a token
ip = lan_ip()
ev["lan_ip"] = ip
ctx.check(ip, "cannot determine the board's LAN address")