feat(fls): import DHCP, port forwarding and modem settings

importProject carries the DHCP client switch and server settings (hosts
and home routers), a home router's port forwarding rows and a modem's
pairing into the model; the core gains the types, ported from Swift.
The Swift oracle writes them too, and they match on the 13 files Swift
reads completely. Configuration text is now trimmed throughout, as Swift
trims every value it reads (routes and firewall rules included).

Outside those files Swift switches every DHCP server of the Internet
examples off: their "aktiv" refers to a shared Boolean it cannot follow.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-09-29 21:09:08 +00:00
co-authored by Claude Opus 5.5
parent 4dcc7e09fc
commit cf47cf8f9d
6 changed files with 406 additions and 30 deletions
@@ -366,6 +366,29 @@ func describeSystem(_ state: TopologyEditorState, _ node: TopologyNode) -> JSON
json["manualRoutes"] = routes.map { [$0.destinationNetwork, $0.subnetMask, $0.gateway, $0.interfaceIPAddress] }
}
if let rip = state.runtimeRIPEnabledByNodeID[node.id] { json["ripEnabled"] = rip }
if let client = state.runtimeDHCPClientConfigurationsByNodeID[node.id] { json["dhcpClient"] = client.isEnabled }
if let server = state.runtimeDHCPServerConfigurationsByNodeID[node.id] {
json["dhcpServer"] = [
"isActive": server.isActive,
"lowerBoundIPAddress": server.lowerBoundIPAddress,
"upperBoundIPAddress": server.upperBoundIPAddress,
"gatewayIPAddress": server.gatewayIPAddress,
"dnsServerIPAddress": server.dnsServerIPAddress,
"useOwnSettings": server.useOwnSettings,
// The assignments' ids are random.
"staticAssignments": server.staticAssignments.map { [$0.macAddress, $0.ipAddress] },
] as JSON
}
if let rows = state.runtimePortForwardingRowsByNodeID[node.id] {
json["portForwarding"] = rows.map { [$0.protocolValue, $0.publicPortValue, $0.lanIPAddress, $0.lanPortValue] }
}
if let link = state.remoteLinkConfigurationsByNodeID[node.id] {
json["remoteLink"] = [
"pairIdentifier": link.pairIdentifier,
"latencyMilliseconds": Int(link.latencyMilliseconds),
"isEnabled": link.isEnabled,
] as JSON
}
if let firewall = state.runtimeFirewallConfigurationsByNodeID[node.id] {
json["firewall"] = [
"isActive": firewall.isActive,