]> git.ipfire.org Git - thirdparty/wireguard-apple.git/commitdiff
on-demand: Infrastructure for supporting SSID-based rules
authorRoopesh Chander <roop@roopc.net>
Sat, 23 Feb 2019 08:26:51 +0000 (13:56 +0530)
committerJason A. Donenfeld <Jason@zx2c4.com>
Mon, 18 Mar 2019 05:46:55 +0000 (06:46 +0100)
Signed-off-by: Roopesh Chander <roop@roopc.net>
WireGuard/WireGuard/Tunnel/ActivateOnDemandSetting.swift
WireGuard/WireGuard/UI/TunnelViewModel.swift
WireGuard/WireGuard/UI/iOS/ViewController/TunnelEditTableViewController.swift
WireGuard/WireGuard/UI/macOS/ViewController/TunnelEditViewController.swift

index 0cb3f981c8a11dbd7623cc8b87ad7236e60fef6c..28612c70780368b700b4c620412960d2980da21f 100644 (file)
@@ -8,11 +8,11 @@ struct ActivateOnDemandSetting {
     var activateOnDemandOption: ActivateOnDemandOption
 }
 
-enum ActivateOnDemandOption {
+enum ActivateOnDemandOption: Equatable {
     case none // Valid only when isActivateOnDemandEnabled is false
-    case wiFiInterfaceOnly
+    case wiFiInterfaceOnly(ActivateOnDemandSSIDOption)
     case nonWiFiInterfaceOnly
-    case anyInterface
+    case anyInterface(ActivateOnDemandSSIDOption)
 }
 
 #if os(iOS)
@@ -23,25 +23,29 @@ private let nonWiFiInterfaceType: NEOnDemandRuleInterfaceType = .ethernet
 #error("Unimplemented")
 #endif
 
+enum ActivateOnDemandSSIDOption: Equatable {
+    case anySSID
+    case onlySpecificSSIDs([String])
+    case exceptSpecificSSIDs([String])
+}
+
 extension ActivateOnDemandSetting {
     func apply(on tunnelProviderManager: NETunnelProviderManager) {
         tunnelProviderManager.isOnDemandEnabled = isActivateOnDemandEnabled
         let rules: [NEOnDemandRule]?
-        let connectRule = NEOnDemandRuleConnect()
-        let disconnectRule = NEOnDemandRuleDisconnect()
         switch activateOnDemandOption {
         case .none:
             rules = nil
-        case .wiFiInterfaceOnly:
-            connectRule.interfaceTypeMatch = .wiFi
-            disconnectRule.interfaceTypeMatch = nonWiFiInterfaceType
-            rules = [connectRule, disconnectRule]
+        case .wiFiInterfaceOnly(let ssidOption):
+            rules = ssidOnDemandRules(option: ssidOption) + [NEOnDemandRuleDisconnect(interfaceType: nonWiFiInterfaceType)]
         case .nonWiFiInterfaceOnly:
-            connectRule.interfaceTypeMatch = nonWiFiInterfaceType
-            disconnectRule.interfaceTypeMatch = .wiFi
-            rules = [connectRule, disconnectRule]
-        case .anyInterface:
-            rules = [connectRule]
+            rules = [NEOnDemandRuleConnect(interfaceType: nonWiFiInterfaceType), NEOnDemandRuleDisconnect(interfaceType: .wiFi)]
+        case .anyInterface(let ssidOption):
+            if case .anySSID = ssidOption {
+                rules = [NEOnDemandRuleConnect(interfaceType: .any)]
+            } else {
+                rules = ssidOnDemandRules(option: ssidOption) + [NEOnDemandRuleConnect(interfaceType: nonWiFiInterfaceType)]
+            }
         }
         tunnelProviderManager.onDemandRules = rules
     }
@@ -55,17 +59,33 @@ extension ActivateOnDemandSetting {
         case 1:
             let rule = rules[0]
             precondition(rule.action == .connect)
-            activateOnDemandOption = .anyInterface
+            activateOnDemandOption = .anyInterface(.anySSID)
         case 2:
             let connectRule = rules.first(where: { $0.action == .connect })!
             let disconnectRule = rules.first(where: { $0.action == .disconnect })!
             if connectRule.interfaceTypeMatch == .wiFi && disconnectRule.interfaceTypeMatch == nonWiFiInterfaceType {
-                activateOnDemandOption = .wiFiInterfaceOnly
+                activateOnDemandOption = .wiFiInterfaceOnly(.anySSID)
             } else if connectRule.interfaceTypeMatch == nonWiFiInterfaceType && disconnectRule.interfaceTypeMatch == .wiFi {
                 activateOnDemandOption = .nonWiFiInterfaceOnly
             } else {
                 fatalError("Unexpected onDemandRules set on tunnel provider manager")
             }
+        case 3:
+            let ssidRule = rules.first(where: { $0.interfaceTypeMatch == .wiFi && $0.ssidMatch != nil })!
+            let nonWiFiRule = rules.first(where: { $0.interfaceTypeMatch == nonWiFiInterfaceType })!
+            let ssids = ssidRule.ssidMatch!
+            switch (ssidRule.action, nonWiFiRule.action) {
+            case (.connect, .connect):
+                activateOnDemandOption = .anyInterface(.onlySpecificSSIDs(ssids))
+            case (.connect, .disconnect):
+                activateOnDemandOption = .wiFiInterfaceOnly(.onlySpecificSSIDs(ssids))
+            case (.disconnect, .connect):
+                activateOnDemandOption = .anyInterface(.exceptSpecificSSIDs(ssids))
+            case (.disconnect, .disconnect):
+                activateOnDemandOption = .wiFiInterfaceOnly(.exceptSpecificSSIDs(ssids))
+            default:
+                fatalError("Unexpected SSID onDemandRules set on tunnel provider manager")
+            }
         default:
             fatalError("Unexpected number of onDemandRules set on tunnel provider manager")
         }
@@ -82,3 +102,33 @@ extension ActivateOnDemandSetting {
 extension ActivateOnDemandSetting {
     static var defaultSetting = ActivateOnDemandSetting(isActivateOnDemandEnabled: false, activateOnDemandOption: .none)
 }
+
+private extension NEOnDemandRuleConnect {
+    convenience init(interfaceType: NEOnDemandRuleInterfaceType, ssids: [String]? = nil) {
+        self.init()
+        interfaceTypeMatch = interfaceType
+        ssidMatch = ssids
+    }
+}
+
+private extension NEOnDemandRuleDisconnect {
+    convenience init(interfaceType: NEOnDemandRuleInterfaceType, ssids: [String]? = nil) {
+        self.init()
+        interfaceTypeMatch = interfaceType
+        ssidMatch = ssids
+    }
+}
+
+private func ssidOnDemandRules(option: ActivateOnDemandSSIDOption) -> [NEOnDemandRule] {
+    switch option {
+    case .anySSID:
+        return [NEOnDemandRuleConnect(interfaceType: .wiFi)]
+    case .onlySpecificSSIDs(let ssids):
+        assert(!ssids.isEmpty)
+        return [NEOnDemandRuleConnect(interfaceType: .wiFi, ssids: ssids),
+                NEOnDemandRuleDisconnect(interfaceType: .wiFi)]
+    case .exceptSpecificSSIDs(let ssids):
+        return [NEOnDemandRuleDisconnect(interfaceType: .wiFi, ssids: ssids),
+                NEOnDemandRuleConnect(interfaceType: .wiFi)]
+    }
+}
index 8a9b007041ab1ae41064c91e705f35b68e00a715..956bfd1f0618458466e7c8ea33a4e56fb524c2ff 100644 (file)
@@ -661,7 +661,7 @@ extension TunnelViewModel {
     }
 
     static func defaultActivateOnDemandOption() -> ActivateOnDemandOption {
-        return .anyInterface
+        return .anyInterface(.anySSID)
     }
 }
 
index 1a20ffec2129de1b5b8e2bf4a6968599c84cdc5c..22c3ec45946a011deb8d92a3d747389838c199b9 100644 (file)
@@ -44,8 +44,8 @@ class TunnelEditTableViewController: UITableViewController {
     ]
 
     let activateOnDemandOptions: [ActivateOnDemandOption] = [
-        .anyInterface,
-        .wiFiInterfaceOnly,
+        .anyInterface(.anySSID),
+        .wiFiInterfaceOnly(.anySSID),
         .nonWiFiInterfaceOnly
     ]
 
index 2c1c53847084f2f505fc99e7332fe04cc2f1a3bf..1c1c05469f1c3215fc005f66d50581bd2e912138 100644 (file)
@@ -82,8 +82,8 @@ class TunnelEditViewController: NSViewController {
 
     let activateOnDemandOptions: [ActivateOnDemandOption] = [
         .none,
-        .anyInterface,
-        .wiFiInterfaceOnly,
+        .anyInterface(.anySSID),
+        .wiFiInterfaceOnly(.anySSID),
         .nonWiFiInterfaceOnly
     ]