on-demand: Don't crash on encountering unexpected on-demand rules

Signed-off-by: Roopesh Chander <roop@roopc.net>
This commit is contained in:
Roopesh Chander 2019-06-09 16:37:20 +05:30
parent 207f82dd9d
commit 37f8500fe6
1 changed files with 33 additions and 20 deletions

View File

@ -46,46 +46,59 @@ extension ActivateOnDemandOption {
} }
init(from tunnelProviderManager: NETunnelProviderManager) { init(from tunnelProviderManager: NETunnelProviderManager) {
let rules = tunnelProviderManager.onDemandRules ?? [] if tunnelProviderManager.isOnDemandEnabled, let onDemandRules = tunnelProviderManager.onDemandRules {
let activateOnDemandOption: ActivateOnDemandOption self = ActivateOnDemandOption.create(from: onDemandRules)
} else {
self = .off
}
}
private static func create(from rules: [NEOnDemandRule]) -> ActivateOnDemandOption {
switch rules.count { switch rules.count {
case 0: case 0:
activateOnDemandOption = .off return .off
case 1: case 1:
let rule = rules[0] let rule = rules[0]
precondition(rule.action == .connect) guard rule.action == .connect else { return .off }
activateOnDemandOption = .anyInterface(.anySSID) return .anyInterface(.anySSID)
case 2: case 2:
let connectRule = rules.first(where: { $0.action == .connect })! guard let connectRule = rules.first(where: { $0.action == .connect }) else {
let disconnectRule = rules.first(where: { $0.action == .disconnect })! wg_log(.error, message: "Unexpected onDemandRules set on tunnel provider manager: \(rules.count) rules found but no connect rule.")
return .off
}
guard let disconnectRule = rules.first(where: { $0.action == .disconnect }) else {
wg_log(.error, message: "Unexpected onDemandRules set on tunnel provider manager: \(rules.count) rules found but no disconnect rule.")
return .off
}
if connectRule.interfaceTypeMatch == .wiFi && disconnectRule.interfaceTypeMatch == nonWiFiInterfaceType { if connectRule.interfaceTypeMatch == .wiFi && disconnectRule.interfaceTypeMatch == nonWiFiInterfaceType {
activateOnDemandOption = .wiFiInterfaceOnly(.anySSID) return .wiFiInterfaceOnly(.anySSID)
} else if connectRule.interfaceTypeMatch == nonWiFiInterfaceType && disconnectRule.interfaceTypeMatch == .wiFi { } else if connectRule.interfaceTypeMatch == nonWiFiInterfaceType && disconnectRule.interfaceTypeMatch == .wiFi {
activateOnDemandOption = .nonWiFiInterfaceOnly return .nonWiFiInterfaceOnly
} else { } else {
fatalError("Unexpected onDemandRules set on tunnel provider manager") wg_log(.error, message: "Unexpected onDemandRules set on tunnel provider manager: \(rules.count) rules found but interface types are inconsistent.")
return .off
} }
case 3: case 3:
let ssidRule = rules.first(where: { $0.interfaceTypeMatch == .wiFi && $0.ssidMatch != nil })! guard let ssidRule = rules.first(where: { $0.interfaceTypeMatch == .wiFi && $0.ssidMatch != nil }) else { return .off }
let nonWiFiRule = rules.first(where: { $0.interfaceTypeMatch == nonWiFiInterfaceType })! guard let nonWiFiRule = rules.first(where: { $0.interfaceTypeMatch == nonWiFiInterfaceType }) else { return .off }
let ssids = ssidRule.ssidMatch! let ssids = ssidRule.ssidMatch!
switch (ssidRule.action, nonWiFiRule.action) { switch (ssidRule.action, nonWiFiRule.action) {
case (.connect, .connect): case (.connect, .connect):
activateOnDemandOption = .anyInterface(.onlySpecificSSIDs(ssids)) return .anyInterface(.onlySpecificSSIDs(ssids))
case (.connect, .disconnect): case (.connect, .disconnect):
activateOnDemandOption = .wiFiInterfaceOnly(.onlySpecificSSIDs(ssids)) return .wiFiInterfaceOnly(.onlySpecificSSIDs(ssids))
case (.disconnect, .connect): case (.disconnect, .connect):
activateOnDemandOption = .anyInterface(.exceptSpecificSSIDs(ssids)) return .anyInterface(.exceptSpecificSSIDs(ssids))
case (.disconnect, .disconnect): case (.disconnect, .disconnect):
activateOnDemandOption = .wiFiInterfaceOnly(.exceptSpecificSSIDs(ssids)) return .wiFiInterfaceOnly(.exceptSpecificSSIDs(ssids))
default: default:
fatalError("Unexpected SSID onDemandRules set on tunnel provider manager") wg_log(.error, message: "Unexpected onDemandRules set on tunnel provider manager: \(rules.count) rules found")
return .off
} }
default: default:
fatalError("Unexpected number of onDemandRules set on tunnel provider manager") wg_log(.error, message: "Unexpected number of onDemandRules set on tunnel provider manager: \(rules.count) rules found")
return .off
} }
self = activateOnDemandOption
} }
} }