mirror of
https://github.com/passepartoutvpn/wireguard-apple.git
synced 2025-02-14 20:02:02 +00:00
Tunnel: support getting runtime configuration
This commit is contained in:
parent
8203a322c1
commit
fef3e80472
@ -17,6 +17,9 @@ struct PeerConfiguration {
|
|||||||
var allowedIPs = [IPAddressRange]()
|
var allowedIPs = [IPAddressRange]()
|
||||||
var endpoint: Endpoint?
|
var endpoint: Endpoint?
|
||||||
var persistentKeepAlive: UInt16?
|
var persistentKeepAlive: UInt16?
|
||||||
|
var rxBytes: UInt64?
|
||||||
|
var txBytes: UInt64?
|
||||||
|
var lastHandshakeTime: Date?
|
||||||
|
|
||||||
init(publicKey: Data) {
|
init(publicKey: Data) {
|
||||||
self.publicKey = publicKey
|
self.publicKey = publicKey
|
||||||
|
@ -28,6 +28,8 @@ extension TunnelConfiguration {
|
|||||||
case peerHasInvalidAllowedIP(String)
|
case peerHasInvalidAllowedIP(String)
|
||||||
case peerHasInvalidEndpoint(String)
|
case peerHasInvalidEndpoint(String)
|
||||||
case peerHasInvalidPersistentKeepAlive(String)
|
case peerHasInvalidPersistentKeepAlive(String)
|
||||||
|
case peerHasInvalidTransferBytes(String)
|
||||||
|
case peerHasInvalidLastHandshakeTime(String)
|
||||||
case peerHasUnrecognizedKey(String)
|
case peerHasUnrecognizedKey(String)
|
||||||
case multiplePeersWithSamePublicKey
|
case multiplePeersWithSamePublicKey
|
||||||
case multipleEntriesForKey(String)
|
case multipleEntriesForKey(String)
|
||||||
|
@ -30,6 +30,8 @@
|
|||||||
5FF7B96321CC95DE00A7DD74 /* InterfaceConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5FF7B96121CC95DE00A7DD74 /* InterfaceConfiguration.swift */; };
|
5FF7B96321CC95DE00A7DD74 /* InterfaceConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5FF7B96121CC95DE00A7DD74 /* InterfaceConfiguration.swift */; };
|
||||||
5FF7B96521CC95FA00A7DD74 /* PeerConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5FF7B96421CC95FA00A7DD74 /* PeerConfiguration.swift */; };
|
5FF7B96521CC95FA00A7DD74 /* PeerConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5FF7B96421CC95FA00A7DD74 /* PeerConfiguration.swift */; };
|
||||||
5FF7B96621CC95FA00A7DD74 /* PeerConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5FF7B96421CC95FA00A7DD74 /* PeerConfiguration.swift */; };
|
5FF7B96621CC95FA00A7DD74 /* PeerConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5FF7B96421CC95FA00A7DD74 /* PeerConfiguration.swift */; };
|
||||||
|
6B707D8421F918D4000A8F73 /* TunnelConfiguration+UapiConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6B707D8321F918D4000A8F73 /* TunnelConfiguration+UapiConfig.swift */; };
|
||||||
|
6B707D8621F918D4000A8F73 /* TunnelConfiguration+UapiConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6B707D8321F918D4000A8F73 /* TunnelConfiguration+UapiConfig.swift */; };
|
||||||
6F4DD16B21DA558800690EAE /* TunnelListRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F4DD16A21DA558800690EAE /* TunnelListRow.swift */; };
|
6F4DD16B21DA558800690EAE /* TunnelListRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F4DD16A21DA558800690EAE /* TunnelListRow.swift */; };
|
||||||
6F4DD16C21DA558F00690EAE /* NSTableView+Reuse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F4DD16721DA552B00690EAE /* NSTableView+Reuse.swift */; };
|
6F4DD16C21DA558F00690EAE /* NSTableView+Reuse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F4DD16721DA552B00690EAE /* NSTableView+Reuse.swift */; };
|
||||||
6F4DD16E21DBEA0700690EAE /* ManageTunnelsRootViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F4DD16D21DBEA0700690EAE /* ManageTunnelsRootViewController.swift */; };
|
6F4DD16E21DBEA0700690EAE /* ManageTunnelsRootViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F4DD16D21DBEA0700690EAE /* ManageTunnelsRootViewController.swift */; };
|
||||||
@ -236,6 +238,7 @@
|
|||||||
5F9696AF21CD7128008063FE /* TunnelConfiguration+WgQuickConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TunnelConfiguration+WgQuickConfig.swift"; sourceTree = "<group>"; };
|
5F9696AF21CD7128008063FE /* TunnelConfiguration+WgQuickConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TunnelConfiguration+WgQuickConfig.swift"; sourceTree = "<group>"; };
|
||||||
5FF7B96121CC95DE00A7DD74 /* InterfaceConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InterfaceConfiguration.swift; sourceTree = "<group>"; };
|
5FF7B96121CC95DE00A7DD74 /* InterfaceConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InterfaceConfiguration.swift; sourceTree = "<group>"; };
|
||||||
5FF7B96421CC95FA00A7DD74 /* PeerConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PeerConfiguration.swift; sourceTree = "<group>"; };
|
5FF7B96421CC95FA00A7DD74 /* PeerConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PeerConfiguration.swift; sourceTree = "<group>"; };
|
||||||
|
6B707D8321F918D4000A8F73 /* TunnelConfiguration+UapiConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TunnelConfiguration+UapiConfig.swift"; sourceTree = "<group>"; };
|
||||||
6F4DD16721DA552B00690EAE /* NSTableView+Reuse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSTableView+Reuse.swift"; sourceTree = "<group>"; };
|
6F4DD16721DA552B00690EAE /* NSTableView+Reuse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSTableView+Reuse.swift"; sourceTree = "<group>"; };
|
||||||
6F4DD16A21DA558800690EAE /* TunnelListRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelListRow.swift; sourceTree = "<group>"; };
|
6F4DD16A21DA558800690EAE /* TunnelListRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelListRow.swift; sourceTree = "<group>"; };
|
||||||
6F4DD16D21DBEA0700690EAE /* ManageTunnelsRootViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ManageTunnelsRootViewController.swift; sourceTree = "<group>"; };
|
6F4DD16D21DBEA0700690EAE /* ManageTunnelsRootViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ManageTunnelsRootViewController.swift; sourceTree = "<group>"; };
|
||||||
@ -487,6 +490,7 @@
|
|||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
6F7774EE21722D97006A79B3 /* TunnelsManager.swift */,
|
6F7774EE21722D97006A79B3 /* TunnelsManager.swift */,
|
||||||
|
6B707D8321F918D4000A8F73 /* TunnelConfiguration+UapiConfig.swift */,
|
||||||
6FFA5DA32197085D0001E2F7 /* ActivateOnDemandSetting.swift */,
|
6FFA5DA32197085D0001E2F7 /* ActivateOnDemandSetting.swift */,
|
||||||
5F4541A821C451D100994C13 /* TunnelStatus.swift */,
|
5F4541A821C451D100994C13 /* TunnelStatus.swift */,
|
||||||
6FB1017821C57DE600766195 /* MockTunnels.swift */,
|
6FB1017821C57DE600766195 /* MockTunnels.swift */,
|
||||||
@ -1111,6 +1115,7 @@
|
|||||||
6F4DD16E21DBEA0700690EAE /* ManageTunnelsRootViewController.swift in Sources */,
|
6F4DD16E21DBEA0700690EAE /* ManageTunnelsRootViewController.swift in Sources */,
|
||||||
6F4DD16C21DA558F00690EAE /* NSTableView+Reuse.swift in Sources */,
|
6F4DD16C21DA558F00690EAE /* NSTableView+Reuse.swift in Sources */,
|
||||||
6FB1BDD821D50F5300A991BF /* WireGuardResult.swift in Sources */,
|
6FB1BDD821D50F5300A991BF /* WireGuardResult.swift in Sources */,
|
||||||
|
6B707D8621F918D4000A8F73 /* TunnelConfiguration+UapiConfig.swift in Sources */,
|
||||||
6FB1BDD921D50F5300A991BF /* LocalizationHelper.swift in Sources */,
|
6FB1BDD921D50F5300A991BF /* LocalizationHelper.swift in Sources */,
|
||||||
6F89E17C21F090CC00C97BB9 /* TunnelsTracker.swift in Sources */,
|
6F89E17C21F090CC00C97BB9 /* TunnelsTracker.swift in Sources */,
|
||||||
6FCD99B121E0EDA900BA4C82 /* TunnelEditViewController.swift in Sources */,
|
6FCD99B121E0EDA900BA4C82 /* TunnelEditViewController.swift in Sources */,
|
||||||
@ -1218,6 +1223,7 @@
|
|||||||
6FDEF802218646BA00D8FBF6 /* ZipArchive.swift in Sources */,
|
6FDEF802218646BA00D8FBF6 /* ZipArchive.swift in Sources */,
|
||||||
5F45419021C2D53800994C13 /* SwitchCell.swift in Sources */,
|
5F45419021C2D53800994C13 /* SwitchCell.swift in Sources */,
|
||||||
6FB1017921C57DE600766195 /* MockTunnels.swift in Sources */,
|
6FB1017921C57DE600766195 /* MockTunnels.swift in Sources */,
|
||||||
|
6B707D8421F918D4000A8F73 /* TunnelConfiguration+UapiConfig.swift in Sources */,
|
||||||
6FDEF806218725D200D8FBF6 /* SettingsTableViewController.swift in Sources */,
|
6FDEF806218725D200D8FBF6 /* SettingsTableViewController.swift in Sources */,
|
||||||
5F4541A221C2D6DF00994C13 /* BorderedTextButton.swift in Sources */,
|
5F4541A221C2D6DF00994C13 /* BorderedTextButton.swift in Sources */,
|
||||||
5FF7B96521CC95FA00A7DD74 /* PeerConfiguration.swift in Sources */,
|
5FF7B96521CC95FA00A7DD74 /* PeerConfiguration.swift in Sources */,
|
||||||
|
@ -62,6 +62,9 @@
|
|||||||
"tunnelPeerEndpoint" = "Endpoint";
|
"tunnelPeerEndpoint" = "Endpoint";
|
||||||
"tunnelPeerPersistentKeepalive" = "Persistent keepalive";
|
"tunnelPeerPersistentKeepalive" = "Persistent keepalive";
|
||||||
"tunnelPeerAllowedIPs" = "Allowed IPs";
|
"tunnelPeerAllowedIPs" = "Allowed IPs";
|
||||||
|
"tunnelPeerRxBytes" = "Data received";
|
||||||
|
"tunnelPeerTxBytes" = "Data sent";
|
||||||
|
"tunnelPeerLastHandshakeTime" = "Latest handshake";
|
||||||
"tunnelPeerExcludePrivateIPs" = "Exclude private IPs";
|
"tunnelPeerExcludePrivateIPs" = "Exclude private IPs";
|
||||||
|
|
||||||
"tunnelSectionTitleOnDemand" = "On-Demand Activation";
|
"tunnelSectionTitleOnDemand" = "On-Demand Activation";
|
||||||
|
207
WireGuard/WireGuard/Tunnel/TunnelConfiguration+UapiConfig.swift
Normal file
207
WireGuard/WireGuard/Tunnel/TunnelConfiguration+UapiConfig.swift
Normal file
@ -0,0 +1,207 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
extension TunnelConfiguration {
|
||||||
|
//swiftlint:disable:next function_body_length cyclomatic_complexity
|
||||||
|
convenience init(fromUapiConfig uapiConfig: String, basedOn base: TunnelConfiguration? = nil) throws {
|
||||||
|
var interfaceConfiguration: InterfaceConfiguration?
|
||||||
|
var peerConfigurations = [PeerConfiguration]()
|
||||||
|
|
||||||
|
var lines = uapiConfig.split(separator: "\n")
|
||||||
|
lines.append("")
|
||||||
|
|
||||||
|
var parserState = ParserState.inInterfaceSection
|
||||||
|
var attributes = [String: String]()
|
||||||
|
|
||||||
|
for line in lines {
|
||||||
|
var key = ""
|
||||||
|
var value = ""
|
||||||
|
|
||||||
|
if !line.isEmpty {
|
||||||
|
guard let equalsIndex = line.firstIndex(of: "=") else { throw ParseError.invalidLine(line) }
|
||||||
|
key = String(line[..<equalsIndex])
|
||||||
|
value = String(line[line.index(equalsIndex, offsetBy: 1)...])
|
||||||
|
}
|
||||||
|
|
||||||
|
if line.isEmpty || key == "public_key" {
|
||||||
|
// Previous section has ended; process the attributes collected so far
|
||||||
|
if parserState == .inInterfaceSection {
|
||||||
|
let interface = try TunnelConfiguration.collate(interfaceAttributes: attributes)
|
||||||
|
guard interfaceConfiguration == nil else { throw ParseError.multipleInterfaces }
|
||||||
|
interfaceConfiguration = interface
|
||||||
|
parserState = .inPeerSection
|
||||||
|
} else if parserState == .inPeerSection {
|
||||||
|
let peer = try TunnelConfiguration.collate(peerAttributes: attributes)
|
||||||
|
peerConfigurations.append(peer)
|
||||||
|
}
|
||||||
|
attributes.removeAll()
|
||||||
|
if line.isEmpty {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let presentValue = attributes[key] {
|
||||||
|
if key == "allowed_ip" {
|
||||||
|
attributes[key] = presentValue + "," + value
|
||||||
|
} else {
|
||||||
|
throw ParseError.multipleEntriesForKey(key)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
attributes[key] = value
|
||||||
|
}
|
||||||
|
|
||||||
|
let interfaceSectionKeys: Set<String> = ["private_key", "listen_port", "fwmark"]
|
||||||
|
let peerSectionKeys: Set<String> = ["public_key", "preshared_key", "allowed_ip", "endpoint", "persistent_keepalive_interval", "last_handshake_time_sec", "last_handshake_time_nsec", "rx_bytes", "tx_bytes", "protocol_version"]
|
||||||
|
|
||||||
|
if parserState == .inInterfaceSection {
|
||||||
|
guard interfaceSectionKeys.contains(key) else {
|
||||||
|
throw ParseError.interfaceHasUnrecognizedKey(key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if parserState == .inPeerSection {
|
||||||
|
guard peerSectionKeys.contains(key) else {
|
||||||
|
throw ParseError.peerHasUnrecognizedKey(key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let peerPublicKeysArray = peerConfigurations.map { $0.publicKey }
|
||||||
|
let peerPublicKeysSet = Set<Data>(peerPublicKeysArray)
|
||||||
|
if peerPublicKeysArray.count != peerPublicKeysSet.count {
|
||||||
|
throw ParseError.multiplePeersWithSamePublicKey
|
||||||
|
}
|
||||||
|
|
||||||
|
interfaceConfiguration?.addresses = base?.interface.addresses ?? []
|
||||||
|
interfaceConfiguration?.dns = base?.interface.dns ?? []
|
||||||
|
interfaceConfiguration?.mtu = base?.interface.mtu
|
||||||
|
|
||||||
|
if let interfaceConfiguration = interfaceConfiguration {
|
||||||
|
self.init(name: base?.name, interface: interfaceConfiguration, peers: peerConfigurations)
|
||||||
|
} else {
|
||||||
|
throw ParseError.noInterface
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static func collate(interfaceAttributes attributes: [String: String]) throws -> InterfaceConfiguration {
|
||||||
|
guard let privateKeyString = attributes["private_key"] else {
|
||||||
|
throw ParseError.interfaceHasNoPrivateKey
|
||||||
|
}
|
||||||
|
guard let privateKey = Data(hexEncoded: privateKeyString), privateKey.count == TunnelConfiguration.keyLength else {
|
||||||
|
throw ParseError.interfaceHasInvalidPrivateKey(privateKeyString)
|
||||||
|
}
|
||||||
|
var interface = InterfaceConfiguration(privateKey: privateKey)
|
||||||
|
if let listenPortString = attributes["listen_port"] {
|
||||||
|
guard let listenPort = UInt16(listenPortString) else {
|
||||||
|
throw ParseError.interfaceHasInvalidListenPort(listenPortString)
|
||||||
|
}
|
||||||
|
if listenPort != 0 {
|
||||||
|
interface.listenPort = listenPort
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return interface
|
||||||
|
}
|
||||||
|
|
||||||
|
//swiftlint:disable:next cyclomatic_complexity
|
||||||
|
private static func collate(peerAttributes attributes: [String: String]) throws -> PeerConfiguration {
|
||||||
|
guard let publicKeyString = attributes["public_key"] else {
|
||||||
|
throw ParseError.peerHasNoPublicKey
|
||||||
|
}
|
||||||
|
guard let publicKey = Data(hexEncoded: publicKeyString), publicKey.count == TunnelConfiguration.keyLength else {
|
||||||
|
throw ParseError.peerHasInvalidPublicKey(publicKeyString)
|
||||||
|
}
|
||||||
|
var peer = PeerConfiguration(publicKey: publicKey)
|
||||||
|
if let preSharedKeyString = attributes["preshared_key"] {
|
||||||
|
guard let preSharedKey = Data(hexEncoded: preSharedKeyString), preSharedKey.count == TunnelConfiguration.keyLength else {
|
||||||
|
throw ParseError.peerHasInvalidPreSharedKey(preSharedKeyString)
|
||||||
|
}
|
||||||
|
// TODO(zx2c4): does the compiler optimize this away?
|
||||||
|
var accumulator: UInt8 = 0
|
||||||
|
for index in 0..<preSharedKey.count {
|
||||||
|
accumulator |= preSharedKey[index]
|
||||||
|
}
|
||||||
|
if accumulator != 0 {
|
||||||
|
peer.preSharedKey = preSharedKey
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let allowedIPsString = attributes["allowed_ip"] {
|
||||||
|
var allowedIPs = [IPAddressRange]()
|
||||||
|
for allowedIPString in allowedIPsString.splitToArray(trimmingCharacters: .whitespacesAndNewlines) {
|
||||||
|
guard let allowedIP = IPAddressRange(from: allowedIPString) else {
|
||||||
|
throw ParseError.peerHasInvalidAllowedIP(allowedIPString)
|
||||||
|
}
|
||||||
|
allowedIPs.append(allowedIP)
|
||||||
|
}
|
||||||
|
peer.allowedIPs = allowedIPs
|
||||||
|
}
|
||||||
|
if let endpointString = attributes["endpoint"] {
|
||||||
|
guard let endpoint = Endpoint(from: endpointString) else {
|
||||||
|
throw ParseError.peerHasInvalidEndpoint(endpointString)
|
||||||
|
}
|
||||||
|
peer.endpoint = endpoint
|
||||||
|
}
|
||||||
|
if let persistentKeepAliveString = attributes["persistent_keepalive_interval"] {
|
||||||
|
guard let persistentKeepAlive = UInt16(persistentKeepAliveString) else {
|
||||||
|
throw ParseError.peerHasInvalidPersistentKeepAlive(persistentKeepAliveString)
|
||||||
|
}
|
||||||
|
if persistentKeepAlive != 0 {
|
||||||
|
peer.persistentKeepAlive = persistentKeepAlive
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let rxBytesString = attributes["rx_bytes"] {
|
||||||
|
guard let rxBytes = UInt64(rxBytesString) else {
|
||||||
|
throw ParseError.peerHasInvalidTransferBytes(rxBytesString)
|
||||||
|
}
|
||||||
|
if rxBytes != 0 {
|
||||||
|
peer.rxBytes = rxBytes
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let txBytesString = attributes["tx_bytes"] {
|
||||||
|
guard let txBytes = UInt64(txBytesString) else {
|
||||||
|
throw ParseError.peerHasInvalidTransferBytes(txBytesString)
|
||||||
|
}
|
||||||
|
if txBytes != 0 {
|
||||||
|
peer.txBytes = txBytes
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let lastHandshakeTimeSecString = attributes["last_handshake_time_sec"] {
|
||||||
|
var lastHandshakeTimeSince1970: TimeInterval = 0
|
||||||
|
guard let lastHandshakeTimeSec = UInt64(lastHandshakeTimeSecString) else {
|
||||||
|
throw ParseError.peerHasInvalidLastHandshakeTime(lastHandshakeTimeSecString)
|
||||||
|
}
|
||||||
|
if lastHandshakeTimeSec != 0 {
|
||||||
|
lastHandshakeTimeSince1970 += Double(lastHandshakeTimeSec)
|
||||||
|
if let lastHandshakeTimeNsecString = attributes["last_handshake_time_nsec"] {
|
||||||
|
guard let lastHandshakeTimeNsec = UInt64(lastHandshakeTimeNsecString) else {
|
||||||
|
throw ParseError.peerHasInvalidLastHandshakeTime(lastHandshakeTimeNsecString)
|
||||||
|
}
|
||||||
|
lastHandshakeTimeSince1970 += Double(lastHandshakeTimeNsec) / 1000000000.0
|
||||||
|
}
|
||||||
|
peer.lastHandshakeTime = Date(timeIntervalSince1970: lastHandshakeTimeSince1970)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return peer
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Data {
|
||||||
|
//swiftlint:disable identifier_name
|
||||||
|
init?(hexEncoded hexString: String) {
|
||||||
|
if hexString.count % 2 != 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
let len = hexString.count / 2
|
||||||
|
self.init(capacity: len)
|
||||||
|
for i in 0..<len {
|
||||||
|
let j = hexString.index(hexString.startIndex, offsetBy: i * 2)
|
||||||
|
let k = hexString.index(j, offsetBy: 2)
|
||||||
|
let bytes = hexString[j..<k]
|
||||||
|
if var num = UInt8(bytes, radix: 16) {
|
||||||
|
append(&num, count: 1)
|
||||||
|
} else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -397,6 +397,23 @@ class TunnelContainer: NSObject {
|
|||||||
super.init()
|
super.init()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getRuntimeTunnelConfiguration(completionHandler: @escaping ((TunnelConfiguration?) -> Void)) {
|
||||||
|
guard status != .inactive, let session = tunnelProvider.connection as? NETunnelProviderSession else {
|
||||||
|
completionHandler(tunnelConfiguration)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
guard nil != (try? session.sendProviderMessage(Data(bytes: [ 0 ]), responseHandler: {
|
||||||
|
guard self.status != .inactive, let data = $0, let base = self.tunnelConfiguration, let settings = String(data: data, encoding: .utf8) else {
|
||||||
|
completionHandler(self.tunnelConfiguration)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
completionHandler((try? TunnelConfiguration(fromUapiConfig: settings, basedOn: base)) ?? self.tunnelConfiguration)
|
||||||
|
})) else {
|
||||||
|
completionHandler(tunnelConfiguration)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func refreshStatus() {
|
func refreshStatus() {
|
||||||
let status = TunnelStatus(from: tunnelProvider.connection.status)
|
let status = TunnelStatus(from: tunnelProvider.connection.status)
|
||||||
self.status = status
|
self.status = status
|
||||||
|
@ -40,6 +40,9 @@ class TunnelViewModel {
|
|||||||
case endpoint
|
case endpoint
|
||||||
case persistentKeepAlive
|
case persistentKeepAlive
|
||||||
case allowedIPs
|
case allowedIPs
|
||||||
|
case rxBytes
|
||||||
|
case txBytes
|
||||||
|
case lastHandshakeTime
|
||||||
case excludePrivateIPs
|
case excludePrivateIPs
|
||||||
case deletePeer
|
case deletePeer
|
||||||
|
|
||||||
@ -50,6 +53,9 @@ class TunnelViewModel {
|
|||||||
case .endpoint: return tr("tunnelPeerEndpoint")
|
case .endpoint: return tr("tunnelPeerEndpoint")
|
||||||
case .persistentKeepAlive: return tr("tunnelPeerPersistentKeepalive")
|
case .persistentKeepAlive: return tr("tunnelPeerPersistentKeepalive")
|
||||||
case .allowedIPs: return tr("tunnelPeerAllowedIPs")
|
case .allowedIPs: return tr("tunnelPeerAllowedIPs")
|
||||||
|
case .rxBytes: return tr("tunnelPeerRxBytes")
|
||||||
|
case .txBytes: return tr("tunnelPeerTxBytes")
|
||||||
|
case .lastHandshakeTime: return tr("tunnelPeerLastHandshakeTime")
|
||||||
case .excludePrivateIPs: return tr("tunnelPeerExcludePrivateIPs")
|
case .excludePrivateIPs: return tr("tunnelPeerExcludePrivateIPs")
|
||||||
case .deletePeer: return tr("deletePeerButtonTitle")
|
case .deletePeer: return tr("deletePeerButtonTitle")
|
||||||
}
|
}
|
||||||
@ -248,6 +254,18 @@ class TunnelViewModel {
|
|||||||
if let persistentKeepAlive = config.persistentKeepAlive {
|
if let persistentKeepAlive = config.persistentKeepAlive {
|
||||||
scratchpad[.persistentKeepAlive] = String(persistentKeepAlive)
|
scratchpad[.persistentKeepAlive] = String(persistentKeepAlive)
|
||||||
}
|
}
|
||||||
|
// TODO(roopc): These next 3 fields should be prettier
|
||||||
|
// - bytes() in https://git.zx2c4.com/WireGuard/tree/src/tools/show.c#n185
|
||||||
|
// - ago() in https://git.zx2c4.com/WireGuard/tree/src/tools/show.c#n158
|
||||||
|
if let rxBytes = config.rxBytes {
|
||||||
|
scratchpad[.rxBytes] = String(rxBytes)
|
||||||
|
}
|
||||||
|
if let txBytes = config.txBytes {
|
||||||
|
scratchpad[.txBytes] = String(txBytes)
|
||||||
|
}
|
||||||
|
if let lastHandshakeTime = config.lastHandshakeTime {
|
||||||
|
scratchpad[.lastHandshakeTime] = lastHandshakeTime.description
|
||||||
|
}
|
||||||
updateExcludePrivateIPsFieldState()
|
updateExcludePrivateIPsFieldState()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,6 +43,10 @@ extension TunnelConfiguration.ParseError: WireGuardAppError {
|
|||||||
return (tr(format: "macAlertPersistentKeepliveInvalid (%@)", value), tr("alertInvalidPeerMessagePersistentKeepaliveInvalid"))
|
return (tr(format: "macAlertPersistentKeepliveInvalid (%@)", value), tr("alertInvalidPeerMessagePersistentKeepaliveInvalid"))
|
||||||
case .peerHasUnrecognizedKey(let value):
|
case .peerHasUnrecognizedKey(let value):
|
||||||
return (tr(format: "macAlertUnrecognizedPeerKey (%@)", value), tr("macAlertInfoUnrecognizedPeerKey"))
|
return (tr(format: "macAlertUnrecognizedPeerKey (%@)", value), tr("macAlertInfoUnrecognizedPeerKey"))
|
||||||
|
case .peerHasInvalidTransferBytes(let line):
|
||||||
|
return (tr(format: "macAlertInvalidLine (%@)", String(line)), "")
|
||||||
|
case .peerHasInvalidLastHandshakeTime(let line):
|
||||||
|
return (tr(format: "macAlertInvalidLine (%@)", String(line)), "")
|
||||||
case .multiplePeersWithSamePublicKey:
|
case .multiplePeersWithSamePublicKey:
|
||||||
return (tr("alertInvalidPeerMessagePublicKeyDuplicated"), "")
|
return (tr("alertInvalidPeerMessagePublicKeyDuplicated"), "")
|
||||||
case .multipleEntriesForKey(let value):
|
case .multipleEntriesForKey(let value):
|
||||||
|
@ -97,6 +97,24 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
|
|||||||
completionHandler()
|
completionHandler()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override func handleAppMessage(_ messageData: Data, completionHandler: ((Data?) -> Void)? = nil) {
|
||||||
|
guard let completionHandler = completionHandler else { return }
|
||||||
|
guard let handle = handle else {
|
||||||
|
completionHandler(nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if messageData.count == 1 && messageData[0] == 0 {
|
||||||
|
guard let settings = wgGetConfig(handle) else {
|
||||||
|
completionHandler(nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
completionHandler(String(cString: settings).data(using: .utf8)!)
|
||||||
|
free(settings)
|
||||||
|
} else {
|
||||||
|
completionHandler(nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private func configureLogger() {
|
private func configureLogger() {
|
||||||
Logger.configureGlobal(withFilePath: FileManager.networkExtensionLogFileURL?.path)
|
Logger.configureGlobal(withFilePath: FileManager.networkExtensionLogFileURL?.path)
|
||||||
wgSetLogger { level, msgC in
|
wgSetLogger { level, msgC in
|
||||||
|
Loading…
Reference in New Issue
Block a user