]> git.ipfire.org Git - thirdparty/wireguard-apple.git/commitdiff
Move logic to extension: Bring up the tunnel from the stored providerConfiguration
authorRoopesh Chander <roop@roopc.net>
Thu, 8 Nov 2018 12:20:47 +0000 (17:50 +0530)
committerRoopesh Chander <roop@roopc.net>
Thu, 8 Nov 2018 13:29:16 +0000 (18:59 +0530)
Signed-off-by: Roopesh Chander <roop@roopc.net>
WireGuard/WireGuardNetworkExtension/PacketTunnelProvider.swift

index 087eec3d0920359c47e1ef6a9db8193838896541..02c087d965317f6363a97d14146a0c3741704e0c 100644 (file)
@@ -6,6 +6,8 @@ import os.log
 
 enum PacketTunnelProviderError: Error {
     case invalidOptions
+    case savedProtocolConfigurationIsInvalid
+    case dnsResolutionFailure(hostnames: [String])
     case couldNotStartWireGuard
     case coultNotSetNetworkSettings
 }
@@ -24,42 +26,35 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
                               completionHandler startTunnelCompletionHandler: @escaping (Error?) -> Void) {
         os_log("Starting tunnel", log: OSLog.default, type: .info)
 
-        guard let options = options else {
-            os_log("Starting tunnel failed: No options passed. Possible connection request from preferences", log: OSLog.default, type: .error)
-            // displayMessage is deprecated API
-            displayMessage("Please use the WireGuard app to start WireGuard tunnels") { (_) in
-                startTunnelCompletionHandler(PacketTunnelProviderError.invalidOptions)
-            }
-            return
+        guard let tunnelProviderProtocol = self.protocolConfiguration as? NETunnelProviderProtocol,
+            let tunnelConfiguration = tunnelProviderProtocol.tunnelConfiguration() else {
+                startTunnelCompletionHandler(PacketTunnelProviderError.savedProtocolConfigurationIsInvalid)
+                return
         }
 
-        guard let interfaceName = options[.interfaceName] as? String,
-            let wireguardSettings = options[.wireguardSettings] as? String,
-            let remoteAddress = options[.remoteAddress] as? String,
-            let dnsServers = options[.dnsServers] as? [String],
-            let mtu = options[.mtu] as? NSNumber,
-
-            // IPv4 settings
-            let ipv4Addresses = options[.ipv4Addresses] as? [String],
-            let ipv4SubnetMasks = options[.ipv4SubnetMasks] as? [String],
-            let ipv4IncludedRouteAddresses = options[.ipv4IncludedRouteAddresses] as? [String],
-            let ipv4IncludedRouteSubnetMasks = options[.ipv4IncludedRouteSubnetMasks] as? [String],
-            let ipv4ExcludedRouteAddresses = options[.ipv4ExcludedRouteAddresses] as? [String],
-            let ipv4ExcludedRouteSubnetMasks = options[.ipv4ExcludedRouteSubnetMasks] as? [String],
-
-            // IPv6 settings
-            let ipv6Addresses = options[.ipv6Addresses] as? [String],
-            let ipv6NetworkPrefixLengths = options[.ipv6NetworkPrefixLengths] as? [NSNumber],
-            let ipv6IncludedRouteAddresses = options[.ipv6IncludedRouteAddresses] as? [String],
-            let ipv6IncludedRouteNetworkPrefixLengths = options[.ipv6IncludedRouteNetworkPrefixLengths] as? [NSNumber],
-            let ipv6ExcludedRouteAddresses = options[.ipv6ExcludedRouteAddresses] as? [String],
-            let ipv6ExcludedRouteNetworkPrefixLengths = options[.ipv6ExcludedRouteNetworkPrefixLengths] as? [NSNumber]
-
-            else {
-                os_log("Starting tunnel failed: Invalid options passed", log: OSLog.default, type: .error)
-                startTunnelCompletionHandler(PacketTunnelProviderError.invalidOptions)
-                return
+        // Resolve endpoint domains
+
+        let endpoints = tunnelConfiguration.peers.map { $0.endpoint }
+        var resolvedEndpoints: [Endpoint?] = []
+        do {
+            resolvedEndpoints = try DNSResolver.resolveSync(endpoints: endpoints)
+        } catch DNSResolverError.dnsResolutionFailed(let hostnames) {
+            os_log("Starting tunnel failed: DNS resolution failure for %{public}d hostnames (%{public}s)", log: OSLog.default,
+                   type: .error, hostnames.count, hostnames.joined(separator: ", "))
+            startTunnelCompletionHandler(PacketTunnelProviderError.dnsResolutionFailure(hostnames: hostnames))
+            return
+        } catch {
+            // There can be no other errors from DNSResolver.resolveSync()
+            fatalError()
         }
+        assert(endpoints.count == resolvedEndpoints.count)
+
+        // Setup packetTunnelSettingsGenerator
+
+        let packetTunnelSettingsGenerator = PacketTunnelSettingsGenerator(tunnelConfiguration: tunnelConfiguration,
+                                                                          resolvedEndpoints: resolvedEndpoints)
+
+        // Bring up wireguard-go backend
 
         configureLogger()
 
@@ -69,7 +64,9 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
             startTunnelCompletionHandler(PacketTunnelProviderError.couldNotStartWireGuard)
             return
         }
-        let handle = connect(interfaceName: interfaceName, settings: wireguardSettings, fd: fd)
+
+        let wireguardSettings = packetTunnelSettingsGenerator.generateWireGuardSettings()
+        let handle = connect(interfaceName: tunnelConfiguration.interface.name, settings: wireguardSettings, fd: fd)
 
         if handle < 0 {
             os_log("Starting tunnel failed: Could not start WireGuard", log: OSLog.default, type: .error)
@@ -79,50 +76,9 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
 
         wgHandle = handle
 
-        // Network settings
-        let networkSettings = NEPacketTunnelNetworkSettings(tunnelRemoteAddress: remoteAddress)
-
-        // IPv4 settings
-        let ipv4Settings = NEIPv4Settings(addresses: ipv4Addresses, subnetMasks: ipv4SubnetMasks)
-        assert(ipv4IncludedRouteAddresses.count == ipv4IncludedRouteSubnetMasks.count)
-        ipv4Settings.includedRoutes = zip(ipv4IncludedRouteAddresses, ipv4IncludedRouteSubnetMasks).map {
-            NEIPv4Route(destinationAddress: $0.0, subnetMask: $0.1)
-        }
-        assert(ipv4ExcludedRouteAddresses.count == ipv4ExcludedRouteSubnetMasks.count)
-        ipv4Settings.excludedRoutes = zip(ipv4ExcludedRouteAddresses, ipv4ExcludedRouteSubnetMasks).map {
-            NEIPv4Route(destinationAddress: $0.0, subnetMask: $0.1)
-        }
-        networkSettings.ipv4Settings = ipv4Settings
-
-        // IPv6 settings
-
-        /* Big fat ugly hack for broken iOS networking stack: the smallest prefix that will have
-         * any effect on iOS is a /120, so we clamp everything above to /120. This is potentially
-         * very bad, if various network parameters were actually relying on that subnet being
-         * intentionally small. TODO: talk about this with upstream iOS devs.
-         */
-        let ipv6Settings = NEIPv6Settings(addresses: ipv6Addresses, networkPrefixLengths: ipv6NetworkPrefixLengths.map { NSNumber(value: min(120, $0.intValue)) })
-        assert(ipv6IncludedRouteAddresses.count == ipv6IncludedRouteNetworkPrefixLengths.count)
-        ipv6Settings.includedRoutes = zip(ipv6IncludedRouteAddresses, ipv6IncludedRouteNetworkPrefixLengths).map {
-            NEIPv6Route(destinationAddress: $0.0, networkPrefixLength: $0.1)
-        }
-        assert(ipv6ExcludedRouteAddresses.count == ipv6ExcludedRouteNetworkPrefixLengths.count)
-        ipv6Settings.excludedRoutes = zip(ipv6ExcludedRouteAddresses, ipv6ExcludedRouteNetworkPrefixLengths).map {
-            NEIPv6Route(destinationAddress: $0.0, networkPrefixLength: $0.1)
-        }
-        networkSettings.ipv6Settings = ipv6Settings
-
-        // DNS
-        networkSettings.dnsSettings = NEDNSSettings(servers: dnsServers)
-
-        // MTU
-        if (mtu == 0) {
-            // 0 imples automatic MTU, where we set overhead as 80 bytes, which is the worst case for WireGuard
-            networkSettings.tunnelOverheadBytes = 80
-        } else {
-            networkSettings.mtu = mtu
-        }
+        // Apply network settings
 
+        let networkSettings: NEPacketTunnelNetworkSettings = packetTunnelSettingsGenerator.generateNetworkSettings()
         setTunnelNetworkSettings(networkSettings) { (error) in
             if let error = error {
                 os_log("Starting tunnel failed: Error setting network settings: %s", log: OSLog.default, type: .error, error.localizedDescription)