Rely on availability of fd only after setting network settings

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
This commit is contained in:
Jason A. Donenfeld 2018-12-22 18:29:05 +01:00
parent aaee3c5cbe
commit 129f94dccd
1 changed files with 24 additions and 29 deletions

View File

@ -8,7 +8,7 @@ import os.log
class PacketTunnelProvider: NEPacketTunnelProvider { class PacketTunnelProvider: NEPacketTunnelProvider {
private var wgHandle: Int32? private var handle: Int32?
private var networkMonitor: NWPathMonitor? private var networkMonitor: NWPathMonitor?
private var lastFirstInterface: NWInterface? private var lastFirstInterface: NWInterface?
private var packetTunnelSettingsGenerator: PacketTunnelSettingsGenerator? private var packetTunnelSettingsGenerator: PacketTunnelSettingsGenerator?
@ -42,37 +42,32 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
packetTunnelSettingsGenerator = PacketTunnelSettingsGenerator(tunnelConfiguration: tunnelConfiguration, resolvedEndpoints: resolvedEndpoints) packetTunnelSettingsGenerator = PacketTunnelSettingsGenerator(tunnelConfiguration: tunnelConfiguration, resolvedEndpoints: resolvedEndpoints)
let fileDescriptor = (packetFlow.value(forKeyPath: "socket.fileDescriptor") as? Int32) ?? -1 setTunnelNetworkSettings(packetTunnelSettingsGenerator!.generateNetworkSettings()) { error in
if let error = error {
wg_log(.error, message: "Starting tunnel failed with setTunnelNetworkSettings returning \(error.localizedDescription)")
errorNotifier.notify(PacketTunnelProviderError.couldNotSetNetworkSettings)
startTunnelCompletionHandler(PacketTunnelProviderError.couldNotSetNetworkSettings)
} else {
self.networkMonitor = NWPathMonitor()
self.lastFirstInterface = self.networkMonitor!.currentPath.availableInterfaces.first
self.networkMonitor!.pathUpdateHandler = self.pathUpdate
self.networkMonitor!.start(queue: DispatchQueue(label: "NetworkMonitor"))
let fileDescriptor = (self.packetFlow.value(forKeyPath: "socket.fileDescriptor") as? Int32) ?? -1
if fileDescriptor < 0 { if fileDescriptor < 0 {
wg_log(.error, staticMessage: "Starting tunnel failed: Could not determine file descriptor") wg_log(.error, staticMessage: "Starting tunnel failed: Could not determine file descriptor")
errorNotifier.notify(PacketTunnelProviderError.couldNotDetermineFileDescriptor) errorNotifier.notify(PacketTunnelProviderError.couldNotDetermineFileDescriptor)
startTunnelCompletionHandler(PacketTunnelProviderError.couldNotDetermineFileDescriptor) startTunnelCompletionHandler(PacketTunnelProviderError.couldNotDetermineFileDescriptor)
return return
} }
let handle = self.packetTunnelSettingsGenerator!.uapiConfiguration().withGoString { return wgTurnOn($0, fileDescriptor) }
let wireguardSettings = packetTunnelSettingsGenerator!.uapiConfiguration()
networkMonitor = NWPathMonitor()
lastFirstInterface = networkMonitor!.currentPath.availableInterfaces.first
networkMonitor!.pathUpdateHandler = pathUpdate
networkMonitor!.start(queue: DispatchQueue(label: "NetworkMonitor"))
let handle = wireguardSettings.withGoString { return wgTurnOn($0, fileDescriptor) }
if handle < 0 { if handle < 0 {
wg_log(.error, message: "Starting tunnel failed with wgTurnOn returning \(handle)") wg_log(.error, message: "Starting tunnel failed with wgTurnOn returning \(handle)")
errorNotifier.notify(PacketTunnelProviderError.couldNotStartBackend) errorNotifier.notify(PacketTunnelProviderError.couldNotStartBackend)
startTunnelCompletionHandler(PacketTunnelProviderError.couldNotStartBackend) startTunnelCompletionHandler(PacketTunnelProviderError.couldNotStartBackend)
return return
} }
wgHandle = handle self.handle = handle
let networkSettings: NEPacketTunnelNetworkSettings = packetTunnelSettingsGenerator!.generateNetworkSettings()
setTunnelNetworkSettings(networkSettings) { error in
if let error = error {
wg_log(.error, message: "Starting tunnel failed with setTunnelNetworkSettings returning \(error.localizedDescription)")
errorNotifier.notify(PacketTunnelProviderError.couldNotSetNetworkSettings)
startTunnelCompletionHandler(PacketTunnelProviderError.couldNotSetNetworkSettings)
} else {
startTunnelCompletionHandler(nil) startTunnelCompletionHandler(nil)
} }
} }
@ -85,7 +80,7 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
ErrorNotifier.removeLastErrorFile() ErrorNotifier.removeLastErrorFile()
wg_log(.info, staticMessage: "Stopping tunnel") wg_log(.info, staticMessage: "Stopping tunnel")
if let handle = wgHandle { if let handle = handle {
wgTurnOff(handle) wgTurnOff(handle)
} }
completionHandler() completionHandler()
@ -111,7 +106,7 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
} }
private func pathUpdate(path: Network.NWPath) { private func pathUpdate(path: Network.NWPath) {
guard let handle = wgHandle, let packetTunnelSettingsGenerator = packetTunnelSettingsGenerator else { return } guard let handle = handle, let packetTunnelSettingsGenerator = packetTunnelSettingsGenerator else { return }
var listenPort: UInt16? var listenPort: UInt16?
//TODO(zx2c4): Remove the `true` here after extensive testing with network/cell simulations. //TODO(zx2c4): Remove the `true` here after extensive testing with network/cell simulations.
if true || path.availableInterfaces.isEmpty || lastFirstInterface != path.availableInterfaces.first { if true || path.availableInterfaces.isEmpty || lastFirstInterface != path.availableInterfaces.first {