]> git.ipfire.org Git - thirdparty/wireguard-apple.git/commitdiff
TunnelsManager: account for no or many endpoints
authorJason A. Donenfeld <Jason@zx2c4.com>
Mon, 5 Nov 2018 05:23:26 +0000 (06:23 +0100)
committerJason A. Donenfeld <Jason@zx2c4.com>
Mon, 5 Nov 2018 05:23:26 +0000 (06:23 +0100)
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
WireGuard/WireGuard/UI/iOS/ErrorPresenter.swift
WireGuard/WireGuard/VPN/PacketTunnelOptionsGenerator.swift
WireGuard/WireGuard/VPN/TunnelsManager.swift

index 95b5503181140c1c5c61400725586ccee96366fc..d9a66dd2e2e631e02f12c818f3e66230822a14e5 100644 (file)
@@ -21,8 +21,6 @@ class ErrorPresenter {
             return ("Unable to remove tunnel", "Internal error")
 
         // TunnelActivationError
-        case TunnelActivationError.noEndpoint:
-            return ("Endpoint missing", "There must be at least one peer with an endpoint")
         case TunnelActivationError.dnsResolutionFailed:
             return ("DNS resolution failure", "One or more endpoint domains could not be resolved")
         case TunnelActivationError.tunnelActivationFailed:
index 35d4bb7c4c81951e9b4ec88df7c69cede95c8d03..3eabde717546b810a4ce04772add21a23b81b2f1 100644 (file)
@@ -48,19 +48,23 @@ class PacketTunnelOptionsGenerator {
 
         // Remote address
 
-        let remoteAddress: String
-        if let firstEndpoint = resolvedEndpoints.compactMap({ $0 }).first {
-            switch (firstEndpoint.host) {
+        /* iOS requires a tunnel endpoint, whereas in WireGuard it's valid for
+         * a tunnel to have no endpoint, or for there to be many endpoints, in
+         * which case, displaying a single one in settings doesn't really
+         * make sense. So, we fill it in with this placeholder, which is not
+         * a valid IP address that will actually route over the Internet.
+         */
+        var remoteAddress: String = "0.0.0.0"
+        let endpointsCompact = resolvedEndpoints.compactMap({ $0 })
+        if endpointsCompact.count == 1 {
+            switch (endpointsCompact.first!.host) {
             case .ipv4(let address):
                 remoteAddress = "\(address)"
             case .ipv6(let address):
                 remoteAddress = "\(address)"
             default:
-                fatalError("Endpoint must be resolved")
+                break
             }
-        } else {
-            // We don't have any peer with an endpoint
-            remoteAddress = ""
         }
 
         options[.remoteAddress] = remoteAddress as NSObject
index f2d02d4ddfd8d82faaa66ae9878b12e422865835..d0c0dc18bc4a1b864e3d7a6565c6c721198dfd6a 100644 (file)
@@ -13,7 +13,6 @@ protocol TunnelsManagerDelegate: class {
 }
 
 enum TunnelActivationError: Error {
-    case noEndpoint
     case dnsResolutionFailed
     case tunnelActivationFailed
     case attemptingActivationWhenAnotherTunnelIsBusy(otherTunnelStatus: TunnelStatus)
@@ -214,14 +213,20 @@ extension NETunnelProviderProtocol {
         self.init()
 
         let appId = Bundle.main.bundleIdentifier!
-        let firstValidEndpoint = tunnelConfiguration.peers.first(where: { $0.endpoint != nil })?.endpoint
-
         providerBundleIdentifier = "\(appId).network-extension"
         providerConfiguration = [
             "tunnelConfiguration": serializedTunnelConfiguration,
             "tunnelConfigurationVersion": 1
         ]
-        serverAddress = firstValidEndpoint?.stringRepresentation() ?? "Unspecified"
+
+        let endpoints = tunnelConfiguration.peers.compactMap({$0.endpoint})
+        if endpoints.count == 1 {
+            serverAddress = endpoints.first!.stringRepresentation()
+        } else if endpoints.isEmpty {
+            serverAddress = "Unspecified"
+        } else {
+            serverAddress = "Multiple endpoints"
+        }
         username = tunnelConfiguration.interface.name
     }
 
@@ -262,15 +267,6 @@ class TunnelContainer: NSObject {
         guard let tunnelConfiguration = tunnelConfiguration() else { fatalError() }
         let endpoints = tunnelConfiguration.peers.map { $0.endpoint }
 
-        // Ensure there's a tunner server address we can give to iOS
-        guard (endpoints.contains(where: { $0 != nil })) else {
-            DispatchQueue.main.async { [weak self] in
-                self?.status = .inactive
-                completionHandler(TunnelActivationError.noEndpoint)
-            }
-            return
-        }
-
         // Resolve DNS and start the tunnel
         let dnsResolver = DNSResolver(endpoints: endpoints)
         let resolvedEndpoints = dnsResolver.resolveWithoutNetworkRequests()