R-66: the box's own address becomes visible (v0.159.0)

Leg A: „Hálózat" card on Beállítások → Rendszer — Helyi cím (LAN),
Hálózati név (only while Megosztás is enabled), Átjáró; live per render,
stored nowhere (S-5), „—" on unavailable.
Leg B: network section in the Debug system dump (interfaces/route/DNS/
lan_address), best-effort per item via the samba-netns door.
Leg C: NetBIOS trap named — Szerver field helper text + a purely lexical
hint on unreachable failures for single-label non-IP names.

Design note: all guest-net reads go through docker exec into the
host-networked felhom-samba container (stacks/guestnet.go, one seam) —
the controller's own netns is the docker bridge, so /proc/net/route etc.
would answer 172.x (the S-2 trap). Red-proofs: A2 gate-drop and C2
lexical-invert both failed as required.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UuFPHmHNrCJj1VhY6QdDMU
This commit is contained in:
2026-07-22 13:49:57 +02:00
parent 4aa2ce4b61
commit 7013a5fd2e
14 changed files with 779 additions and 2 deletions
+36
View File
@@ -214,6 +214,42 @@ func (s *Server) debugDump(w http.ResponseWriter, r *http.Request) {
dump["backup"] = map[string]interface{}{"enabled": false}
}
// Network (R-66) — the guest's netns view, read through the samba-container door
// (stacks/guestnet.go: the controller's OWN netns is the docker bridge — the S-2 wrong
// answer). Best-effort per item, the dump's tolerance style: a failed read yields that
// item's error string in place and never aborts the dump. lan_address is the SAME live
// value the Hálózat card shows, so a support session can cross-check the two.
netSnap := s.guestNetSnapshot()
network := map[string]interface{}{}
if e := netSnap.Errors["interfaces"]; e != "" {
network["interfaces"] = "error: " + e
} else {
ifaces := make([]map[string]interface{}, 0, len(netSnap.Interfaces))
for _, gi := range netSnap.Interfaces {
ifaces = append(ifaces, map[string]interface{}{
"name": gi.Name,
"up": gi.Up,
"addresses": gi.Addresses,
})
}
network["interfaces"] = ifaces
}
if e := netSnap.Errors["route"]; e != "" {
network["default_route"] = "error: " + e
} else {
network["default_route"] = map[string]interface{}{
"gateway": netSnap.Gateway,
"interface": netSnap.RouteInterface,
}
}
if e := netSnap.Errors["dns"]; e != "" {
network["dns_servers"] = "error: " + e
} else {
network["dns_servers"] = netSnap.DNSServers
}
network["lan_address"] = netSnap.LANAddress
dump["network"] = network
// Hub
hubInfo := map[string]interface{}{
"url": s.cfg.Hub.URL,