Kritischer Fund beim M6-Live-Test: RouterOSCliParser.parseInterfaces
splittete nur auf "\n", aber die SSH-Ausgabe eines echten hEX-Routers
trennt Zeilen anders -- alle Interface-Zeilen wurden zu EINER Zeile
zusammengefasst. Beim key=value-Parsen dieser einen Riesenzeile
überschrieb jedes Feld (name=, type=, ...) den vorherigen Wert, sodass
am Ende nur das letzte Interface im Text ("lo", Loopback) übrig blieb
-- mit den Feldwerten aller anderen Interfaces vermischt.
Folge: WAN-Schritt zeigte nur "lo" zur Auswahl, wodurch alle
WAN-Interface-Referenzen (NAT-Masquerade, ICMP-Regel, WAN-Block-Regel,
finale Anti-Spoofing-Regel) fälschlich auf "lo" statt den echten
WAN-Port zeigten. Auf diesem Testgerät blieb es folgenlos, weil RouterOS
schon eine vollständige eigene Standard-Firewall (defconf) mitbrachte,
die den echten Schutz weiterhin übernahm -- auf einem Gerät ohne
bestehende Firewall hätte das eine wirkungslose Firewall bedeutet, die
sich als aktiv ausgegeben hätte.
Fix: split(whereSeparator: \.isNewline) statt split(separator: "\n"),
robust gegen \n/\r/\r\n. Zusätzliches Sicherheitsnetz in SetupView:
Loopback-Interfaces werden aus allen WAN/LAN/VLAN-Auswahllisten
gefiltert, damit ein ähnlicher Parser-Fehler künftig nicht erneut zu
einer sinnlosen Interface-Auswahl führen kann. Regressionstest mit
realen \r\n-getrennten hEX-Daten ergänzt.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HReLXMbmPvtQ23p1iWiJNW
56 lines
2.3 KiB
Swift
56 lines
2.3 KiB
Swift
import SwiftUI
|
|
|
|
struct SetupView: View {
|
|
@ObservedObject var connectionService: ConnectionService
|
|
@StateObject private var viewModel: SetupViewModel
|
|
|
|
init(connectionService: ConnectionService) {
|
|
self.connectionService = connectionService
|
|
_viewModel = StateObject(wrappedValue: SetupViewModel(connectionService: connectionService))
|
|
}
|
|
|
|
var body: some View {
|
|
NavigationStack {
|
|
Group {
|
|
if connectionService.credentials == nil {
|
|
ContentUnavailableView(
|
|
"Nicht verbunden",
|
|
systemImage: "network.slash",
|
|
description: Text("Verbinde dich zuerst im Tab \"Verbinden\" mit deinem Router.")
|
|
)
|
|
} else {
|
|
switch viewModel.step {
|
|
case .wan:
|
|
WanStepView(viewModel: viewModel, availableInterfaces: configurableInterfaces)
|
|
case .lan:
|
|
LanStepView(viewModel: viewModel, availableInterfaces: configurableInterfaces)
|
|
case .vlan:
|
|
VlanStepView(viewModel: viewModel, availableInterfaces: configurableInterfaces)
|
|
case .wifi:
|
|
WifiStepView(viewModel: viewModel)
|
|
case .firewall:
|
|
FirewallStepView(viewModel: viewModel)
|
|
case .review:
|
|
ReviewApplyView(viewModel: viewModel, credentials: connectionService.credentials)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
.onAppear {
|
|
viewModel.prepareDefaults(from: configurableInterfaces)
|
|
}
|
|
}
|
|
|
|
/// Loopback is never something a person should pick as WAN/LAN/VLAN base interface —
|
|
/// excluded here (not just via defaults) so a parsing hiccup elsewhere can't offer it as
|
|
/// a selectable option, which on a real hEX device caused every WAN/firewall command to
|
|
/// silently reference "lo" instead of the real WAN port. Found via live testing.
|
|
private var configurableInterfaces: [NetworkInterface] {
|
|
connectionService.interfaces.filter { $0.type.lowercased() != "loopback" }
|
|
}
|
|
}
|
|
|
|
#Preview {
|
|
SetupView(connectionService: ConnectionService())
|
|
}
|