VPN: Bring up the tunnel

The app figures out all settings and passes them in the
'options' parameter of startTunnel().

The network extension just takes them as is and just plugs the supplied
values into the right places.

Signed-off-by: Roopesh Chander <roop@roopc.net>
This commit is contained in:
Roopesh Chander 2018-10-27 15:02:32 +05:30
parent a08e08fe2e
commit 793bf63989
5 changed files with 306 additions and 71 deletions

View File

@ -0,0 +1,30 @@
// SPDX-License-Identifier: MIT
// Copyright © 2018 WireGuard LLC. All rights reserved.
import Foundation
enum PacketTunnelOptionKey: String {
case interfaceName, wireguardSettings, remoteAddress, dnsServers, mtu,
// IPv4 settings
ipv4Addresses, ipv4SubnetMasks,
ipv4IncludedRouteAddresses, ipv4IncludedRouteSubnetMasks,
ipv4ExcludedRouteAddresses, ipv4ExcludedRouteSubnetMasks,
// IPv6 settings
ipv6Addresses, ipv6NetworkPrefixLengths,
ipv6IncludedRouteAddresses, ipv6IncludedRouteNetworkPrefixLengths,
ipv6ExcludedRouteAddresses, ipv6ExcludedRouteNetworkPrefixLengths
}
extension Dictionary where Key == String {
subscript(key: PacketTunnelOptionKey) -> Value? {
get {
return self[key.rawValue]
}
set(value) {
self[key.rawValue] = value
}
}
}

View File

@ -10,6 +10,9 @@
6F5D0C1521832391000F85AD /* DNSResolver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F5D0C1421832391000F85AD /* DNSResolver.swift */; };
6F5D0C1D218352EF000F85AD /* PacketTunnelProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F5D0C1C218352EF000F85AD /* PacketTunnelProvider.swift */; };
6F5D0C22218352EF000F85AD /* WireGuardNetworkExtension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 6F5D0C1A218352EF000F85AD /* WireGuardNetworkExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
6F5D0C452183BCDA000F85AD /* PacketTunnelOptionKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F5D0C442183BCDA000F85AD /* PacketTunnelOptionKey.swift */; };
6F5D0C462183C0B4000F85AD /* PacketTunnelOptionKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F5D0C442183BCDA000F85AD /* PacketTunnelOptionKey.swift */; };
6F5D0C482183C6A3000F85AD /* PacketTunnelOptionsGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F5D0C472183C6A3000F85AD /* PacketTunnelOptionsGenerator.swift */; };
6F628C3D217F09E9003482A3 /* TunnelViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F628C3C217F09E9003482A3 /* TunnelViewModel.swift */; };
6F628C3F217F3413003482A3 /* DNSServer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F628C3E217F3413003482A3 /* DNSServer.swift */; };
6F628C41217F47DB003482A3 /* TunnelDetailTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F628C40217F47DB003482A3 /* TunnelDetailTableViewController.swift */; };
@ -69,6 +72,8 @@
6F5D0C1E218352EF000F85AD /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
6F5D0C1F218352EF000F85AD /* WireGuardNetworkExtension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = WireGuardNetworkExtension.entitlements; sourceTree = "<group>"; };
6F5D0C3421839E37000F85AD /* WireGuardNetworkExtension-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "WireGuardNetworkExtension-Bridging-Header.h"; sourceTree = "<group>"; };
6F5D0C442183BCDA000F85AD /* PacketTunnelOptionKey.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PacketTunnelOptionKey.swift; sourceTree = "<group>"; };
6F5D0C472183C6A3000F85AD /* PacketTunnelOptionsGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PacketTunnelOptionsGenerator.swift; sourceTree = "<group>"; };
6F628C3C217F09E9003482A3 /* TunnelViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelViewModel.swift; sourceTree = "<group>"; };
6F628C3E217F3413003482A3 /* DNSServer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DNSServer.swift; sourceTree = "<group>"; };
6F628C40217F47DB003482A3 /* TunnelDetailTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TunnelDetailTableViewController.swift; sourceTree = "<group>"; };
@ -127,6 +132,14 @@
path = WireGuardNetworkExtension;
sourceTree = "<group>";
};
6F5D0C432183B4A4000F85AD /* Shared */ = {
isa = PBXGroup;
children = (
6F5D0C442183BCDA000F85AD /* PacketTunnelOptionKey.swift */,
);
path = Shared;
sourceTree = "<group>";
};
6F6899A32180445A0012E523 /* Crypto */ = {
isa = PBXGroup;
children = (
@ -183,6 +196,7 @@
children = (
6F7774EE21722D97006A79B3 /* TunnelsManager.swift */,
6F5D0C1421832391000F85AD /* DNSResolver.swift */,
6F5D0C472183C6A3000F85AD /* PacketTunnelOptionsGenerator.swift */,
);
path = VPN;
sourceTree = "<group>";
@ -190,6 +204,7 @@
6FF4AC0B211EC46F002C96EB = {
isa = PBXGroup;
children = (
6F5D0C432183B4A4000F85AD /* Shared */,
6FF4AC16211EC46F002C96EB /* WireGuard */,
6F5D0C1B218352EF000F85AD /* WireGuardNetworkExtension */,
6FF4AC15211EC46F002C96EB /* Products */,
@ -362,6 +377,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
6F5D0C462183C0B4000F85AD /* PacketTunnelOptionKey.swift in Sources */,
6F5D0C1D218352EF000F85AD /* PacketTunnelProvider.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
@ -374,8 +390,10 @@
6F7774E421718281006A79B3 /* TunnelsListTableViewController.swift in Sources */,
6F7774EF21722D97006A79B3 /* TunnelsManager.swift in Sources */,
6F5D0C1521832391000F85AD /* DNSResolver.swift in Sources */,
6F5D0C482183C6A3000F85AD /* PacketTunnelOptionsGenerator.swift in Sources */,
6F693A562179E556008551C1 /* Endpoint.swift in Sources */,
6F6899A62180447E0012E523 /* x25519.c in Sources */,
6F5D0C452183BCDA000F85AD /* PacketTunnelOptionKey.swift in Sources */,
6F7774E2217181B1006A79B3 /* AppDelegate.swift in Sources */,
6F628C3F217F3413003482A3 /* DNSServer.swift in Sources */,
6F628C3D217F09E9003482A3 /* TunnelViewModel.swift in Sources */,

View File

@ -0,0 +1,180 @@
// SPDX-License-Identifier: MIT
// Copyright © 2018 WireGuard LLC. All rights reserved.
import Foundation
import Network
class PacketTunnelOptionsGenerator {
static func generateOptions(from tc: TunnelConfiguration,
withResolvedEndpoints resolvedEndpoints: [Endpoint?]) -> [String:NSObject] {
var options: [String:NSObject] = [:]
// Interface name
options[.interfaceName] = tc.interface.name as NSObject
// WireGuard settings
var wgSettings = ""
let privateKey = tc.interface.privateKey.hexEncodedString()
wgSettings.append("private_key=\(privateKey)\n")
if let listenPort = tc.interface.listenPort {
wgSettings.append("listen_port=\(listenPort)\n")
}
if (tc.peers.count > 0) {
wgSettings.append("replace_peers=true\n")
}
assert(tc.peers.count == resolvedEndpoints.count)
for (i, peer) in tc.peers.enumerated() {
wgSettings.append("public_key=\(peer.publicKey.hexEncodedString())\n")
if let preSharedKey = peer.preSharedKey {
wgSettings.append("preshared_key=\(preSharedKey.hexEncodedString())\n")
}
if let endpoint = resolvedEndpoints[i] {
if case .name(_, _) = endpoint.host { assert(false, "Endpoint is not resolved") }
wgSettings.append("endpoint=\(endpoint.stringRepresentation())\n")
}
let persistentKeepAlive = peer.persistentKeepAlive ?? 0
wgSettings.append("persistent_keepalive_interval=\(persistentKeepAlive)\n")
if (!peer.allowedIPs.isEmpty) {
wgSettings.append("replace_allowed_ips=true\n")
for ip in peer.allowedIPs {
wgSettings.append("allowed_ip=\(ip.stringRepresentation())\n")
}
}
}
options[.wireguardSettings] = wgSettings as NSObject
// Remote address
let remoteAddress: String
if let firstEndpoint = resolvedEndpoints.compactMap({ $0 }).first {
switch (firstEndpoint.host) {
case .ipv4(let address):
remoteAddress = "\(address)"
case .ipv6(let address):
remoteAddress = "\(address)"
default:
fatalError("Endpoint must be resolved")
}
} else {
// We don't have any peer with an endpoint
remoteAddress = ""
}
options[.remoteAddress] = remoteAddress as NSObject
// DNS
options[.dnsServers] = tc.interface.dns.map { $0.stringRepresentation() } as NSObject
// MTU
options[.mtu] = NSNumber(value: tc.interface.mtu ?? 0) // 0 implies auto-MTU
// Addresses from interface addresses
var ipv4Addresses: [String] = []
var ipv4SubnetMasks: [String] = []
var ipv6Addresses: [String] = []
var ipv6NetworkPrefixLengths: [NSNumber] = []
for addressRange in tc.interface.addresses {
if (addressRange.address is IPv4Address) {
ipv4Addresses.append("\(addressRange.address)")
ipv4SubnetMasks.append(ipv4SubnetMaskString(of: addressRange))
} else if (addressRange.address is IPv6Address) {
ipv6Addresses.append("\(addressRange.address)")
ipv6NetworkPrefixLengths.append(NSNumber(value: addressRange.networkPrefixLength))
}
}
options[.ipv4Addresses] = ipv4Addresses as NSObject
options[.ipv4SubnetMasks] = ipv4SubnetMasks as NSObject
options[.ipv6Addresses] = ipv6Addresses as NSObject
options[.ipv6NetworkPrefixLengths] = ipv6NetworkPrefixLengths as NSObject
// Included routes from AllowedIPs
var ipv4IncludedRouteAddresses: [String] = []
var ipv4IncludedRouteSubnetMasks: [String] = []
var ipv6IncludedRouteAddresses: [String] = []
var ipv6IncludedRouteNetworkPrefixLengths: [NSNumber] = []
for peer in tc.peers {
for addressRange in peer.allowedIPs {
if (addressRange.address is IPv4Address) {
ipv4IncludedRouteAddresses.append("\(addressRange.address)")
ipv4IncludedRouteSubnetMasks.append(ipv4SubnetMaskString(of: addressRange))
} else if (addressRange.address is IPv6Address) {
ipv6IncludedRouteAddresses.append("\(addressRange.address)")
ipv6IncludedRouteNetworkPrefixLengths.append(NSNumber(value: addressRange.networkPrefixLength))
}
}
}
options[.ipv4IncludedRouteAddresses] = ipv4IncludedRouteAddresses as NSObject
options[.ipv4IncludedRouteSubnetMasks] = ipv4IncludedRouteSubnetMasks as NSObject
options[.ipv6IncludedRouteAddresses] = ipv6IncludedRouteAddresses as NSObject
options[.ipv6IncludedRouteNetworkPrefixLengths] = ipv6IncludedRouteNetworkPrefixLengths as NSObject
// Excluded routes from endpoints
var ipv4ExcludedRouteAddresses: [String] = []
var ipv4ExcludedRouteSubnetMasks: [String] = []
var ipv6ExcludedRouteAddresses: [String] = []
var ipv6ExcludedRouteNetworkPrefixLengths: [NSNumber] = []
for endpoint in resolvedEndpoints {
guard let endpoint = endpoint else { continue }
switch (endpoint.host) {
case .ipv4(let address):
ipv4ExcludedRouteAddresses.append("\(address)")
ipv4ExcludedRouteSubnetMasks.append("255.255.255.255") // A single IPv4 address
case .ipv6(let address):
ipv6ExcludedRouteAddresses.append("\(address)")
ipv6ExcludedRouteNetworkPrefixLengths.append(NSNumber(value: UInt8(128))) // A single IPv6 address
default:
fatalError()
}
}
options[.ipv4ExcludedRouteAddresses] = ipv4ExcludedRouteAddresses as NSObject
options[.ipv4ExcludedRouteSubnetMasks] = ipv4ExcludedRouteSubnetMasks as NSObject
options[.ipv6ExcludedRouteAddresses] = ipv6ExcludedRouteAddresses as NSObject
options[.ipv6ExcludedRouteNetworkPrefixLengths] = ipv6ExcludedRouteNetworkPrefixLengths as NSObject
return options
}
static func ipv4SubnetMaskString(of addressRange: IPAddressRange) -> String {
var n: UInt8 = addressRange.networkPrefixLength
assert(n <= 32)
var components: [UInt8] = []
while (n >= 8) {
components.append(255)
n = n - 8
}
if (n > 0) {
components.append(((1 << n) - 1) << (8 - n))
}
while (components.count < 4) {
components.append(0)
}
assert(components.count == 4)
return components.map { String($0) }.joined(separator: ".")
}
}
private extension Data {
func hexEncodedString() -> String {
return self.map { String(format: "%02x", $0) }.joined()
}
}

View File

@ -277,7 +277,9 @@ class TunnelContainer: NSObject {
s.startObservingTunnelStatus()
let session = (s.tunnelProvider.connection as! NETunnelProviderSession)
do {
try session.startTunnel(options: [:]) // TODO: Provide options
let tunnelOptions = PacketTunnelOptionsGenerator.generateOptions(
from: tunnelConfiguration, withResolvedEndpoints: endpoints)
try session.startTunnel(options: tunnelOptions)
} catch (let error) {
os_log("Failed to activate tunnel: %{public}@", log: OSLog.default, type: .debug, "\(error)")
s.onActive = nil

View File

@ -6,7 +6,9 @@ import NetworkExtension
import os.log
enum PacketTunnelProviderError: Error {
case tunnelSetupFailed
case invalidOptions
case couldNotStartWireGuard
case coultNotSetNetworkSettings
}
/// A packet tunnel provider object.
@ -17,81 +19,100 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
private var wgHandle: Int32?
private var wgContext: WireGuardContext?
private var config: NETunnelProviderProtocol {
return self.protocolConfiguration as! NETunnelProviderProtocol // swiftlint:disable:this force_cast
}
private var interfaceName: String {
return config.providerConfiguration![PCKeys.title.rawValue]! as! String // swiftlint:disable:this force_cast
}
private var settings: String {
return config.providerConfiguration![PCKeys.settings.rawValue]! as! String // swiftlint:disable:this force_cast
}
// MARK: NEPacketTunnelProvider
/// Begin the process of establishing the tunnel.
override func startTunnel(options: [String: NSObject]?, completionHandler startTunnelCompletionHandler: @escaping (Error?) -> Void) {
os_log("Starting tunnel", log: Log.general, type: .info)
override func startTunnel(options: [String: NSObject]?,
completionHandler startTunnelCompletionHandler: @escaping (Error?) -> Void) {
os_log("Starting tunnel", log: OSLog.default, type: .info)
let validatedEndpoints = (config.providerConfiguration?[PCKeys.endpoints.rawValue] as? String ?? "").commaSeparatedToArray().compactMap { try? Endpoint(endpointString: String($0)) }.compactMap {$0}
let validatedAddresses = (config.providerConfiguration?[PCKeys.addresses.rawValue] as? String ?? "").commaSeparatedToArray().compactMap { try? CIDRAddress(stringRepresentation: String($0)) }.compactMap { $0 }
guard let firstEndpoint = validatedEndpoints.first else {
startTunnelCompletionHandler(PacketTunnelProviderError.tunnelSetupFailed)
guard let options = options else {
startTunnelCompletionHandler(PacketTunnelProviderError.invalidOptions)
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 {
startTunnelCompletionHandler(PacketTunnelProviderError.invalidOptions)
return
}
configureLogger()
wgContext = WireGuardContext(packetFlow: self.packetFlow)
let handle = connect(interfaceName: interfaceName, settings: settings)
let handle = connect(interfaceName: interfaceName, settings: wireguardSettings, mtu: mtu.uint16Value)
if handle < 0 {
startTunnelCompletionHandler(PacketTunnelProviderError.tunnelSetupFailed)
startTunnelCompletionHandler(PacketTunnelProviderError.couldNotStartWireGuard)
return
}
wgHandle = handle
// We use the first endpoint for the ipAddress
let newSettings = NEPacketTunnelNetworkSettings(tunnelRemoteAddress: firstEndpoint.ipAddress)
newSettings.tunnelOverheadBytes = 80
// Network settings
let networkSettings = NEPacketTunnelNetworkSettings(tunnelRemoteAddress: remoteAddress)
// IPv4 settings
let validatedIPv4Addresses = validatedAddresses.filter { $0.addressType == .IPv4}
if validatedIPv4Addresses.count > 0 {
let ipv4Settings = NEIPv4Settings(addresses: validatedIPv4Addresses.map { $0.ipAddress }, subnetMasks: validatedIPv4Addresses.map { $0.subnetString })
ipv4Settings.includedRoutes = [NEIPv4Route.default()]
ipv4Settings.excludedRoutes = validatedEndpoints.filter { $0.addressType == .IPv4}.map {
NEIPv4Route(destinationAddress: $0.ipAddress, subnetMask: "255.255.255.255")}
newSettings.ipv4Settings = ipv4Settings
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
let validatedIPv6Addresses = validatedAddresses.filter { $0.addressType == .IPv6}
if validatedIPv6Addresses.count > 0 {
let ipv6Settings = NEIPv6Settings(addresses: validatedIPv6Addresses.map { $0.ipAddress }, networkPrefixLengths: validatedIPv6Addresses.map { NSNumber(value: $0.subnet) })
ipv6Settings.includedRoutes = [NEIPv6Route.default()]
ipv6Settings.excludedRoutes = validatedEndpoints.filter { $0.addressType == .IPv6 }.map { NEIPv6Route(destinationAddress: $0.ipAddress, networkPrefixLength: 128) }
let ipv6Settings = NEIPv6Settings(addresses: ipv6Addresses, networkPrefixLengths: ipv6NetworkPrefixLengths)
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
newSettings.ipv6Settings = ipv6Settings
// DNS
networkSettings.dnsSettings = NEDNSSettings(servers: dnsServers)
// MTU
if (mtu == 0) {
// 0 imples automatic MTU, where we set overhead as 95 bytes,
// 80 for WireGuard and the 15 to make sure WireGuard's padding will work.
networkSettings.tunnelOverheadBytes = 95
} else {
networkSettings.mtu = mtu
}
if let dns = config.providerConfiguration?[PCKeys.dns.rawValue] as? String {
newSettings.dnsSettings = NEDNSSettings(servers: dns.commaSeparatedToArray())
}
if let mtu = config.providerConfiguration![PCKeys.mtu.rawValue] as? NSNumber, mtu.intValue > 0 {
newSettings.mtu = mtu
}
setTunnelNetworkSettings(newSettings) { (error) in
setTunnelNetworkSettings(networkSettings) { (error) in
if let error = error {
os_log("Error setting network settings: %s", log: Log.general, type: .error, error.localizedDescription)
startTunnelCompletionHandler(PacketTunnelProviderError.tunnelSetupFailed)
os_log("Error setting network settings: %s", log: OSLog.default, type: .error, error.localizedDescription)
startTunnelCompletionHandler(PacketTunnelProviderError.coultNotSetNetworkSettings)
} else {
startTunnelCompletionHandler(nil /* No errors */)
}
@ -100,7 +121,7 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
/// Begin the process of stopping the tunnel.
override func stopTunnel(with reason: NEProviderStopReason, completionHandler: @escaping () -> Void) {
os_log("Stopping tunnel", log: Log.general, type: .info)
os_log("Stopping tunnel", log: OSLog.default, type: .info)
if let handle = wgHandle {
wgTurnOff(handle)
}
@ -108,22 +129,6 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
completionHandler()
}
/// Handle IPC messages from the app.
override func handleAppMessage(_ messageData: Data, completionHandler: ((Data?) -> Void)?) {
let responseData: Data?
let message = ExtensionMessage(messageData)
switch message {
case ExtensionMessage.requestVersion:
responseData = (wgVersion().flatMap { String(cString: $0) } ?? "").data(using: .utf8)
default:
responseData = nil
}
completionHandler?(responseData)
}
private func configureLogger() {
wgSetLogger { (level, tagCStr, msgCStr) in
let logType: OSLogType
@ -139,14 +144,14 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
}
let tag = (tagCStr != nil) ? String(cString: tagCStr!) : ""
let msg = (msgCStr != nil) ? String(cString: msgCStr!) : ""
os_log("wg log: %{public}s: %{public}s", log: Log.general, type: logType, tag, msg)
os_log("wg log: %{public}s: %{public}s", log: OSLog.default, type: logType, tag, msg)
}
}
private func connect(interfaceName: String, settings: String) -> Int32 { // swiftlint:disable:this cyclomatic_complexity
private func connect(interfaceName: String, settings: String, mtu: UInt16) -> Int32 { // swiftlint:disable:this cyclomatic_complexity
return withStringsAsGoStrings(interfaceName, settings) { (nameGoStr, settingsGoStr) -> Int32 in
return withUnsafeMutablePointer(to: &wgContext) { (wgCtxPtr) -> Int32 in
return wgTurnOn(nameGoStr, settingsGoStr, { (wgCtxPtr, buf, len) -> Int in
return wgTurnOn(nameGoStr, settingsGoStr, mtu, { (wgCtxPtr, buf, len) -> Int in
autoreleasepool {
// read_fn: Read from the TUN interface and pass it on to WireGuard
guard let wgCtxPtr = wgCtxPtr else { return 0 }