forked from kay/RouterOS
- WAN-Schritt: fehlenden "Zurück"-Button ergänzt (beide Modi) - "Abbrechen"/"Jetzt sichern" prominent gemacht (wie "Neu scannen") - LAN-/VLAN-Schritt: Adressfelder starten leer, nur Format-Beispiel im Feld sichtbar statt vorbelegter Werte. VlanStepView bekam dafür eine Validierungssperre auf "Weiter" (fehlte bisher, war ok solange Defaults immer gültig waren). Zwei Tests entsprechend angepasst. - SSH-Host-Key-Trust aus M24 hatte sich entgegen der Live-Bestätigung nie tatsächlich persistiert (defaults read zeigte leeren Schlüssel, Ursache ungeklärt) — betraf BackupServices dedizierte SSH-Verbindung beim ersten Experte-Tab-Schreibversuch pro Sitzung. Erneut über den bestehenden Trust-Dialog bestätigt, diesmal per defaults read verifiziert statt nur der UI-Bestätigung vertraut. Alles live bestätigt. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
65 lines
2.8 KiB
Swift
65 lines
2.8 KiB
Swift
import Foundation
|
|
|
|
/// One additional virtual network: a VLAN interface on top of an existing (typically LAN
|
|
/// bridge) interface, with its own IP range and DHCP server — e.g. a guest or IoT network.
|
|
/// Deliberately not port-based (no access/trunk assignment): that needs RouterOS bridge
|
|
/// VLAN filtering, which requires "set" operations our REST/SSH command model doesn't
|
|
/// support yet (it only ever creates new items). Someone who needs a VLAN on a specific
|
|
/// switch port still has to configure that port as a tagged trunk manually.
|
|
struct VlanEntry: Identifiable, Equatable {
|
|
var id = UUID()
|
|
var name: String
|
|
var vlanID: Int
|
|
var parentInterface: String
|
|
var networkAddress: String
|
|
var routerAddress: String
|
|
var poolRangeStart: String
|
|
var poolRangeEnd: String
|
|
var leaseTimeHours: Int = 24
|
|
var dnsServers: String
|
|
/// Blocks forward traffic to/from every other configured LAN/VLAN network — see
|
|
/// `FirewallConfig.NetworkSegment`. Internet access (WAN NAT) is unaffected.
|
|
var isolated: Bool = false
|
|
|
|
/// Fields start empty on purpose (Nutzerwunsch: "die auszufüllenden Felder leer lassen,
|
|
/// nur Beispiele zeigen ... so sieht man das Schema dahinter") — each TextField's label
|
|
/// (e.g. "Router-Adresse (z.B. 192.168.20.1/24)") doubles as its placeholder while empty,
|
|
/// so leaving these blank shows the format example instead of hiding it behind an
|
|
/// auto-derived value the user might not even notice, let alone check. `VlanStepView`'s
|
|
/// "Weiter" button is disabled until every VLAN's fields are actually filled in.
|
|
init(name: String = "Gäste", vlanID: Int, parentInterface: String) {
|
|
self.name = name
|
|
self.vlanID = vlanID
|
|
self.parentInterface = parentInterface
|
|
self.networkAddress = ""
|
|
self.routerAddress = ""
|
|
self.poolRangeStart = ""
|
|
self.poolRangeEnd = ""
|
|
self.dnsServers = ""
|
|
}
|
|
|
|
var interfaceName: String { "vlan\(vlanID)" }
|
|
|
|
func buildCommands() -> [RouterOSCommand] {
|
|
let createVlan = RouterOSCommand.add(
|
|
menuPath: "/interface vlan",
|
|
restPath: "interface/vlan",
|
|
arguments: ["name": interfaceName, "vlan-id": "\(vlanID)", "interface": parentInterface],
|
|
summary: "VLAN \"\(name)\" (ID \(vlanID)) auf \(parentInterface) anlegen"
|
|
)
|
|
|
|
let dhcpCommands = DhcpServerCommandBuilder.buildCommands(
|
|
interfaceName: interfaceName,
|
|
routerAddress: routerAddress,
|
|
networkAddress: networkAddress,
|
|
poolRangeStart: poolRangeStart,
|
|
poolRangeEnd: poolRangeEnd,
|
|
leaseTimeHours: leaseTimeHours,
|
|
dnsServers: dnsServers,
|
|
context: "für VLAN \"\(name)\""
|
|
)
|
|
|
|
return [createVlan] + dhcpCommands
|
|
}
|
|
}
|