mirror of
https://github.com/deneraraujo/OpenVPNAdapter.git
synced 2026-02-11 00:00:08 +08:00
Merge branch 'develop' into feature/documentation
* develop: (32 commits) Add header guards Update project settings Update tests Fix crash if empty data was provided Apply style guide rules to the remaining classes Update tracking property name regarding style guide Apply style guide rules to the openvpn configuration class Add missing import of reachability status header Apply style guide rules to certificate, key and reachability classes Refactor generation of mbedTLS errors Add Nullability Annotations to OpenVPNAdapterPacketFlow (#43) Refactor generation of OpenVPN adapter errors Refactor implementation of OpenVPNAdapter class Redefine networkSettings as method instead of property Return false if URL is nil Initializer shouldn't return nil, and return socket setup error during socket configuration Add socket setup error Rename a few delegate methods and fix memory warning Add extra spaces and empty lines Add pragma marks ...
This commit is contained in:
@@ -6,22 +6,15 @@
|
||||
//
|
||||
|
||||
import NetworkExtension
|
||||
@testable import OpenVPNAdapter
|
||||
|
||||
class CustomFlow: NEPacketTunnelFlow {
|
||||
|
||||
override func readPackets(completionHandler: @escaping ([Data], [NSNumber]) -> Void) {
|
||||
class CustomFlow: NSObject, OpenVPNAdapterPacketFlow {
|
||||
|
||||
func readPackets(completionHandler: @escaping ([Data], [NSNumber]) -> Void) {
|
||||
|
||||
}
|
||||
|
||||
override func writePackets(_ packets: [Data], withProtocols protocols: [NSNumber]) -> Bool {
|
||||
return true
|
||||
}
|
||||
|
||||
override func readPacketObjects(completionHandler: @escaping ([NEPacket]) -> Void) {
|
||||
|
||||
}
|
||||
|
||||
override func writePacketObjects(_ packets: [NEPacket]) -> Bool {
|
||||
func writePackets(_ packets: [Data], withProtocols protocols: [NSNumber]) -> Bool {
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
@@ -135,7 +135,7 @@ class OpenVPNAdapterTests: XCTestCase {
|
||||
|
||||
extension OpenVPNAdapterTests: OpenVPNAdapterDelegate {
|
||||
|
||||
func openVPNAdapter(_ openVPNAdapter: OpenVPNAdapter, configureTunnelWithNetworkSettings networkSettings: NEPacketTunnelNetworkSettings, completionHandler: @escaping (NEPacketTunnelFlow?) -> Void) {
|
||||
func openVPNAdapter(_ openVPNAdapter: OpenVPNAdapter, configureTunnelWithNetworkSettings networkSettings: NEPacketTunnelNetworkSettings, completionHandler: @escaping (OpenVPNAdapterPacketFlow?) -> Void) {
|
||||
completionHandler(customFlow)
|
||||
}
|
||||
|
||||
|
||||
@@ -124,12 +124,22 @@
|
||||
C9C1E4111FA47117006ECA7D /* remote_vpn_server.ovpn in Resources */ = {isa = PBXBuildFile; fileRef = C9C1E40F1FA47117006ECA7D /* remote_vpn_server.ovpn */; };
|
||||
C9C1E4141FA475B7006ECA7D /* CustomFlow.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9C1E4131FA475B7006ECA7D /* CustomFlow.swift */; };
|
||||
C9C1E4151FA475B7006ECA7D /* CustomFlow.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9C1E4131FA475B7006ECA7D /* CustomFlow.swift */; };
|
||||
C9C2B2B7200CB42F00CA0FF3 /* OpenVPNAdapterPacketFlow.h in Headers */ = {isa = PBXBuildFile; fileRef = C9C2B2B6200CB42F00CA0FF3 /* OpenVPNAdapterPacketFlow.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
C9C2B2B8200CB42F00CA0FF3 /* OpenVPNAdapterPacketFlow.h in Headers */ = {isa = PBXBuildFile; fileRef = C9C2B2B6200CB42F00CA0FF3 /* OpenVPNAdapterPacketFlow.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
C9C2B2BB200CC42A00CA0FF3 /* OpenVPNPacket.h in Headers */ = {isa = PBXBuildFile; fileRef = C9C2B2B9200CC42A00CA0FF3 /* OpenVPNPacket.h */; };
|
||||
C9C2B2BC200CC42A00CA0FF3 /* OpenVPNPacket.h in Headers */ = {isa = PBXBuildFile; fileRef = C9C2B2B9200CC42A00CA0FF3 /* OpenVPNPacket.h */; };
|
||||
C9C2B2BD200CC42A00CA0FF3 /* OpenVPNPacket.mm in Sources */ = {isa = PBXBuildFile; fileRef = C9C2B2BA200CC42A00CA0FF3 /* OpenVPNPacket.mm */; };
|
||||
C9C2B2BE200CC42A00CA0FF3 /* OpenVPNPacket.mm in Sources */ = {isa = PBXBuildFile; fileRef = C9C2B2BA200CC42A00CA0FF3 /* OpenVPNPacket.mm */; };
|
||||
C9CA4DD31F602F7B00C4F184 /* OpenVPNCertificate.h in Headers */ = {isa = PBXBuildFile; fileRef = C9CA4DD11F602F7B00C4F184 /* OpenVPNCertificate.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
C9CA4DD41F602F7B00C4F184 /* OpenVPNCertificate.h in Headers */ = {isa = PBXBuildFile; fileRef = C9CA4DD11F602F7B00C4F184 /* OpenVPNCertificate.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
C9CA4DD51F602F7B00C4F184 /* OpenVPNCertificate.m in Sources */ = {isa = PBXBuildFile; fileRef = C9CA4DD21F602F7B00C4F184 /* OpenVPNCertificate.m */; };
|
||||
C9CA4DD61F602F7B00C4F184 /* OpenVPNCertificate.m in Sources */ = {isa = PBXBuildFile; fileRef = C9CA4DD21F602F7B00C4F184 /* OpenVPNCertificate.m */; };
|
||||
C9CA4DE11F603A5300C4F184 /* OpenVPNCertificateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9CA4DE01F603A5300C4F184 /* OpenVPNCertificateTests.swift */; };
|
||||
C9CA4DE21F603A5300C4F184 /* OpenVPNCertificateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9CA4DE01F603A5300C4F184 /* OpenVPNCertificateTests.swift */; };
|
||||
C9CDFDDB200781AF00323B73 /* OpenVPNClient.h in Headers */ = {isa = PBXBuildFile; fileRef = C9CDFDD9200781AF00323B73 /* OpenVPNClient.h */; };
|
||||
C9CDFDDC200781AF00323B73 /* OpenVPNClient.h in Headers */ = {isa = PBXBuildFile; fileRef = C9CDFDD9200781AF00323B73 /* OpenVPNClient.h */; };
|
||||
C9CDFDDD200781AF00323B73 /* OpenVPNClient.mm in Sources */ = {isa = PBXBuildFile; fileRef = C9CDFDDA200781AF00323B73 /* OpenVPNClient.mm */; };
|
||||
C9CDFDDE200781AF00323B73 /* OpenVPNClient.mm in Sources */ = {isa = PBXBuildFile; fileRef = C9CDFDDA200781AF00323B73 /* OpenVPNClient.mm */; };
|
||||
C9D2ABDE1EA20F99007EDF9D /* ovpncli.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C9FD92191E9A667600374FC4 /* ovpncli.cpp */; };
|
||||
C9D2ABE01EA20F99007EDF9D /* NetworkExtension.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C912BB241E7C3339002B9414 /* NetworkExtension.framework */; };
|
||||
C9D2ABE11EA20F99007EDF9D /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C90BAD301E73FF6C00DEFB32 /* SystemConfiguration.framework */; };
|
||||
@@ -140,10 +150,10 @@
|
||||
C9D2ABF61EA212A3007EDF9D /* OpenVPNAdapterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9BB47901E71821A00F3F98C /* OpenVPNAdapterTests.swift */; };
|
||||
C9D2ABF71EA212A3007EDF9D /* Bundle.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9BB47A11E7183DB00F3F98C /* Bundle.swift */; };
|
||||
C9D2AC051EA214EA007EDF9D /* OpenVPNAdapter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C9D2ABF01EA20F99007EDF9D /* OpenVPNAdapter.framework */; };
|
||||
C9E4401D1F6086A1001D7C41 /* NSError+Message.h in Headers */ = {isa = PBXBuildFile; fileRef = C9E4401B1F6086A1001D7C41 /* NSError+Message.h */; };
|
||||
C9E4401E1F6086A1001D7C41 /* NSError+Message.h in Headers */ = {isa = PBXBuildFile; fileRef = C9E4401B1F6086A1001D7C41 /* NSError+Message.h */; };
|
||||
C9E4401F1F6086A1001D7C41 /* NSError+Message.m in Sources */ = {isa = PBXBuildFile; fileRef = C9E4401C1F6086A1001D7C41 /* NSError+Message.m */; };
|
||||
C9E440201F6086A1001D7C41 /* NSError+Message.m in Sources */ = {isa = PBXBuildFile; fileRef = C9E4401C1F6086A1001D7C41 /* NSError+Message.m */; };
|
||||
C9E350C1200F6EC0000820D9 /* NSError+OpenVPNError.h in Headers */ = {isa = PBXBuildFile; fileRef = C9E350BF200F6EC0000820D9 /* NSError+OpenVPNError.h */; };
|
||||
C9E350C2200F6EC0000820D9 /* NSError+OpenVPNError.h in Headers */ = {isa = PBXBuildFile; fileRef = C9E350BF200F6EC0000820D9 /* NSError+OpenVPNError.h */; };
|
||||
C9E350C3200F6EC0000820D9 /* NSError+OpenVPNError.m in Sources */ = {isa = PBXBuildFile; fileRef = C9E350C0200F6EC0000820D9 /* NSError+OpenVPNError.m */; };
|
||||
C9E350C4200F6EC0000820D9 /* NSError+OpenVPNError.m in Sources */ = {isa = PBXBuildFile; fileRef = C9E350C0200F6EC0000820D9 /* NSError+OpenVPNError.m */; };
|
||||
C9FD921A1E9A667600374FC4 /* ovpncli.hpp in Headers */ = {isa = PBXBuildFile; fileRef = C9FD92181E9A667600374FC4 /* ovpncli.hpp */; };
|
||||
C9FD921B1E9A667600374FC4 /* ovpncli.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C9FD92191E9A667600374FC4 /* ovpncli.cpp */; };
|
||||
/* End PBXBuildFile section */
|
||||
@@ -237,13 +247,18 @@
|
||||
C9BCE25C1EB3C201009D6AC1 /* OpenVPNSessionToken+Internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "OpenVPNSessionToken+Internal.h"; sourceTree = "<group>"; };
|
||||
C9C1E40F1FA47117006ECA7D /* remote_vpn_server.ovpn */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = remote_vpn_server.ovpn; sourceTree = "<group>"; };
|
||||
C9C1E4131FA475B7006ECA7D /* CustomFlow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomFlow.swift; sourceTree = "<group>"; };
|
||||
C9C2B2B6200CB42F00CA0FF3 /* OpenVPNAdapterPacketFlow.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OpenVPNAdapterPacketFlow.h; sourceTree = "<group>"; };
|
||||
C9C2B2B9200CC42A00CA0FF3 /* OpenVPNPacket.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OpenVPNPacket.h; sourceTree = "<group>"; };
|
||||
C9C2B2BA200CC42A00CA0FF3 /* OpenVPNPacket.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = OpenVPNPacket.mm; sourceTree = "<group>"; };
|
||||
C9CA4DD11F602F7B00C4F184 /* OpenVPNCertificate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OpenVPNCertificate.h; sourceTree = "<group>"; };
|
||||
C9CA4DD21F602F7B00C4F184 /* OpenVPNCertificate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OpenVPNCertificate.m; sourceTree = "<group>"; };
|
||||
C9CA4DE01F603A5300C4F184 /* OpenVPNCertificateTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OpenVPNCertificateTests.swift; sourceTree = "<group>"; };
|
||||
C9CDFDD9200781AF00323B73 /* OpenVPNClient.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OpenVPNClient.h; sourceTree = "<group>"; };
|
||||
C9CDFDDA200781AF00323B73 /* OpenVPNClient.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = OpenVPNClient.mm; sourceTree = "<group>"; };
|
||||
C9D2ABF01EA20F99007EDF9D /* OpenVPNAdapter.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = OpenVPNAdapter.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
C9D2ABFF1EA212A3007EDF9D /* OpenVPNAdapterTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = OpenVPNAdapterTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
C9E4401B1F6086A1001D7C41 /* NSError+Message.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSError+Message.h"; sourceTree = "<group>"; };
|
||||
C9E4401C1F6086A1001D7C41 /* NSError+Message.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSError+Message.m"; sourceTree = "<group>"; };
|
||||
C9E350BF200F6EC0000820D9 /* NSError+OpenVPNError.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSError+OpenVPNError.h"; sourceTree = "<group>"; };
|
||||
C9E350C0200F6EC0000820D9 /* NSError+OpenVPNError.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSError+OpenVPNError.m"; sourceTree = "<group>"; };
|
||||
C9FD92181E9A667600374FC4 /* ovpncli.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = ovpncli.hpp; path = Vendors/openvpn/client/ovpncli.hpp; sourceTree = "<group>"; };
|
||||
C9FD92191E9A667600374FC4 /* ovpncli.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ovpncli.cpp; path = Vendors/openvpn/client/ovpncli.cpp; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
@@ -334,6 +349,11 @@
|
||||
C9235AC41EB24F0100C7D303 /* Configuration */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C9657A5D1EB0D60700EFF210 /* OpenVPNTransportProtocol.h */,
|
||||
C9657A601EB0D64E00EFF210 /* OpenVPNIPv6Preference.h */,
|
||||
C9657A631EB0D6AD00EFF210 /* OpenVPNCompressionMode.h */,
|
||||
C9657A661EB0D73200EFF210 /* OpenVPNMinTLSVersion.h */,
|
||||
C9657A691EB0D75700EFF210 /* OpenVPNTLSCertProfile.h */,
|
||||
C98467A41EAA5B7700272A9A /* OpenVPNConfiguration.h */,
|
||||
C98467AA1EAA5BB500272A9A /* OpenVPNConfiguration+Internal.h */,
|
||||
C98467A51EAA5B7700272A9A /* OpenVPNConfiguration.mm */,
|
||||
@@ -369,26 +389,10 @@
|
||||
name = "Stats and Info";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
C9235AC61EB24F2A00C7D303 /* Types and Constants */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C9BB476F1E7171A100F3F98C /* OpenVPNError.h */,
|
||||
C93A4F611EE18009004DC561 /* OpenVPNError.m */,
|
||||
C9BB47701E7171A100F3F98C /* OpenVPNAdapterEvent.h */,
|
||||
C9657A5D1EB0D60700EFF210 /* OpenVPNTransportProtocol.h */,
|
||||
C9657A601EB0D64E00EFF210 /* OpenVPNIPv6Preference.h */,
|
||||
C9657A631EB0D6AD00EFF210 /* OpenVPNCompressionMode.h */,
|
||||
C9657A661EB0D73200EFF210 /* OpenVPNMinTLSVersion.h */,
|
||||
C9657A691EB0D75700EFF210 /* OpenVPNTLSCertProfile.h */,
|
||||
C915F1FD1F6164CF00B3DF23 /* OpenVPNKeyType.h */,
|
||||
C9B795681F1D219C00CF35FE /* OpenVPNReachabilityStatus.h */,
|
||||
);
|
||||
name = "Types and Constants";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
C9B7955B1F1D165700CF35FE /* Reachability */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C9B795681F1D219C00CF35FE /* OpenVPNReachabilityStatus.h */,
|
||||
C9B795621F1D182500CF35FE /* OpenVPNReachabilityTracker.h */,
|
||||
C9B795631F1D182500CF35FE /* OpenVPNReachabilityTracker.mm */,
|
||||
C9B7955C1F1D16AA00CF35FE /* OpenVPNReachability.h */,
|
||||
@@ -432,12 +436,20 @@
|
||||
C9BB47671E7169F000F3F98C /* Adapter */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
ABD6EF151F8F9C37007D3D90 /* OpenVPNAdapter.h */,
|
||||
ABD6EF161F8F9C38007D3D90 /* OpenVPNAdapter.mm */,
|
||||
C9BB47701E7171A100F3F98C /* OpenVPNAdapterEvent.h */,
|
||||
C9BB476F1E7171A100F3F98C /* OpenVPNError.h */,
|
||||
C93A4F611EE18009004DC561 /* OpenVPNError.m */,
|
||||
C9CDFDD9200781AF00323B73 /* OpenVPNClient.h */,
|
||||
C9CDFDDA200781AF00323B73 /* OpenVPNClient.mm */,
|
||||
ABD6EF071F8F8CCD007D3D90 /* OpenVPNNetworkSettingsBuilder.h */,
|
||||
ABD6EF081F8F8CCD007D3D90 /* OpenVPNNetworkSettingsBuilder.m */,
|
||||
C9C2B2B6200CB42F00CA0FF3 /* OpenVPNAdapterPacketFlow.h */,
|
||||
C9C2B2B9200CC42A00CA0FF3 /* OpenVPNPacket.h */,
|
||||
C9C2B2BA200CC42A00CA0FF3 /* OpenVPNPacket.mm */,
|
||||
ABD6EF0E1F8F93AB007D3D90 /* OpenVPNPacketFlowBridge.h */,
|
||||
ABD6EF0F1F8F93AB007D3D90 /* OpenVPNPacketFlowBridge.mm */,
|
||||
ABD6EF151F8F9C37007D3D90 /* OpenVPNAdapter.h */,
|
||||
ABD6EF161F8F9C38007D3D90 /* OpenVPNAdapter.mm */,
|
||||
);
|
||||
name = Adapter;
|
||||
sourceTree = "<group>";
|
||||
@@ -538,6 +550,7 @@
|
||||
C9CA4DD01F602D8300C4F184 /* Certificates and Keys */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C915F1FD1F6164CF00B3DF23 /* OpenVPNKeyType.h */,
|
||||
C9CA4DD11F602F7B00C4F184 /* OpenVPNCertificate.h */,
|
||||
C9CA4DD21F602F7B00C4F184 /* OpenVPNCertificate.m */,
|
||||
C915F1F21F612F3300B3DF23 /* OpenVPNPrivateKey.h */,
|
||||
@@ -546,20 +559,19 @@
|
||||
name = "Certificates and Keys";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
C9E4401A1F6081FF001D7C41 /* Utils */ = {
|
||||
C9E350C5200F70CA000820D9 /* Extensions */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C9E4401B1F6086A1001D7C41 /* NSError+Message.h */,
|
||||
C9E4401C1F6086A1001D7C41 /* NSError+Message.m */,
|
||||
C9E350BF200F6EC0000820D9 /* NSError+OpenVPNError.h */,
|
||||
C9E350C0200F6EC0000820D9 /* NSError+OpenVPNError.m */,
|
||||
);
|
||||
name = Utils;
|
||||
name = Extensions;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
C9FF73B71EB7421600E995AC /* Helpers */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C9235AC61EB24F2A00C7D303 /* Types and Constants */,
|
||||
C9E4401A1F6081FF001D7C41 /* Utils */,
|
||||
C9E350C5200F70CA000820D9 /* Extensions */,
|
||||
);
|
||||
name = Helpers;
|
||||
sourceTree = "<group>";
|
||||
@@ -572,6 +584,7 @@
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
C9CA4DD31F602F7B00C4F184 /* OpenVPNCertificate.h in Headers */,
|
||||
C9CDFDDB200781AF00323B73 /* OpenVPNClient.h in Headers */,
|
||||
C9657A3A1EB0BAAB00EFF210 /* OpenVPNInterfaceStats+Internal.h in Headers */,
|
||||
C9354F451F1E4A4500F4C935 /* OpenVPNReachabilityStatus.h in Headers */,
|
||||
C9BCE25E1EB3C201009D6AC1 /* OpenVPNSessionToken+Internal.h in Headers */,
|
||||
@@ -596,13 +609,15 @@
|
||||
C9657A171EB0A7F800EFF210 /* OpenVPNConnectionInfo.h in Headers */,
|
||||
C9BB47711E7171A100F3F98C /* OpenVPNError.h in Headers */,
|
||||
C9B795641F1D182500CF35FE /* OpenVPNReachabilityTracker.h in Headers */,
|
||||
C9E4401D1F6086A1001D7C41 /* NSError+Message.h in Headers */,
|
||||
ABD6EF091F8F8CCD007D3D90 /* OpenVPNNetworkSettingsBuilder.h in Headers */,
|
||||
C9657A611EB0D64E00EFF210 /* OpenVPNIPv6Preference.h in Headers */,
|
||||
C9657A671EB0D73200EFF210 /* OpenVPNMinTLSVersion.h in Headers */,
|
||||
C9C2B2BB200CC42A00CA0FF3 /* OpenVPNPacket.h in Headers */,
|
||||
C93779D51EAE32670030A362 /* OpenVPNCredentials.h in Headers */,
|
||||
C9657A641EB0D6C200EFF210 /* OpenVPNCompressionMode.h in Headers */,
|
||||
C9FD921A1E9A667600374FC4 /* ovpncli.hpp in Headers */,
|
||||
C9C2B2B7200CB42F00CA0FF3 /* OpenVPNAdapterPacketFlow.h in Headers */,
|
||||
C9E350C1200F6EC0000820D9 /* NSError+OpenVPNError.h in Headers */,
|
||||
C93779DB1EAE32880030A362 /* OpenVPNCredentials+Internal.h in Headers */,
|
||||
C9657A6A1EB0D75700EFF210 /* OpenVPNTLSCertProfile.h in Headers */,
|
||||
C9657A461EB0CB5900EFF210 /* OpenVPNServerEntry+Internal.h in Headers */,
|
||||
@@ -615,6 +630,7 @@
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
C9CA4DD41F602F7B00C4F184 /* OpenVPNCertificate.h in Headers */,
|
||||
C9CDFDDC200781AF00323B73 /* OpenVPNClient.h in Headers */,
|
||||
C9657A3B1EB0BAAB00EFF210 /* OpenVPNInterfaceStats+Internal.h in Headers */,
|
||||
C9354F461F1E4A4600F4C935 /* OpenVPNReachabilityStatus.h in Headers */,
|
||||
C9BCE25F1EB3C201009D6AC1 /* OpenVPNSessionToken+Internal.h in Headers */,
|
||||
@@ -639,13 +655,15 @@
|
||||
C9657A181EB0A7F800EFF210 /* OpenVPNConnectionInfo.h in Headers */,
|
||||
C9D2ABE81EA20F99007EDF9D /* OpenVPNError.h in Headers */,
|
||||
C9B795651F1D182500CF35FE /* OpenVPNReachabilityTracker.h in Headers */,
|
||||
C9E4401E1F6086A1001D7C41 /* NSError+Message.h in Headers */,
|
||||
ABD6EF0A1F8F8CCD007D3D90 /* OpenVPNNetworkSettingsBuilder.h in Headers */,
|
||||
C9657A621EB0D64E00EFF210 /* OpenVPNIPv6Preference.h in Headers */,
|
||||
C9657A681EB0D73200EFF210 /* OpenVPNMinTLSVersion.h in Headers */,
|
||||
C9C2B2BC200CC42A00CA0FF3 /* OpenVPNPacket.h in Headers */,
|
||||
C93779D61EAE32670030A362 /* OpenVPNCredentials.h in Headers */,
|
||||
C9657A651EB0D6C200EFF210 /* OpenVPNCompressionMode.h in Headers */,
|
||||
C9D2ABEA1EA20F99007EDF9D /* ovpncli.hpp in Headers */,
|
||||
C9C2B2B8200CB42F00CA0FF3 /* OpenVPNAdapterPacketFlow.h in Headers */,
|
||||
C9E350C2200F6EC0000820D9 /* NSError+OpenVPNError.h in Headers */,
|
||||
C93779DC1EAE32880030A362 /* OpenVPNCredentials+Internal.h in Headers */,
|
||||
C9657A6B1EB0D75700EFF210 /* OpenVPNTLSCertProfile.h in Headers */,
|
||||
C9657A471EB0CB5900EFF210 /* OpenVPNServerEntry+Internal.h in Headers */,
|
||||
@@ -860,18 +878,20 @@
|
||||
ABD6EF181F8F9C38007D3D90 /* OpenVPNAdapter.mm in Sources */,
|
||||
C9657A421EB0CAC200EFF210 /* OpenVPNServerEntry.mm in Sources */,
|
||||
C9BCE25A1EB3C0D9009D6AC1 /* OpenVPNSessionToken.mm in Sources */,
|
||||
C9E350C3200F6EC0000820D9 /* NSError+OpenVPNError.m in Sources */,
|
||||
ABD6EF0B1F8F8CCD007D3D90 /* OpenVPNNetworkSettingsBuilder.m in Sources */,
|
||||
C98467A81EAA5B7700272A9A /* OpenVPNConfiguration.mm in Sources */,
|
||||
ABD6EF121F8F93AB007D3D90 /* OpenVPNPacketFlowBridge.mm in Sources */,
|
||||
C9E4401F1F6086A1001D7C41 /* NSError+Message.m in Sources */,
|
||||
C9657A311EB0B7A900EFF210 /* OpenVPNTransportStats.mm in Sources */,
|
||||
C9B795661F1D182500CF35FE /* OpenVPNReachabilityTracker.mm in Sources */,
|
||||
C9657A581EB0CE1300EFF210 /* OpenVPNProperties.mm in Sources */,
|
||||
C9CA4DD51F602F7B00C4F184 /* OpenVPNCertificate.m in Sources */,
|
||||
C9CDFDDD200781AF00323B73 /* OpenVPNClient.mm in Sources */,
|
||||
C915F1F61F612F3300B3DF23 /* OpenVPNPrivateKey.m in Sources */,
|
||||
C9FD921B1E9A667600374FC4 /* ovpncli.cpp in Sources */,
|
||||
C9657A361EB0BA3900EFF210 /* OpenVPNInterfaceStats.mm in Sources */,
|
||||
C9657A211EB0ACAE00EFF210 /* OpenVPNConnectionInfo.mm in Sources */,
|
||||
C9C2B2BD200CC42A00CA0FF3 /* OpenVPNPacket.mm in Sources */,
|
||||
C93A4F621EE18009004DC561 /* OpenVPNError.m in Sources */,
|
||||
C93779D71EAE32670030A362 /* OpenVPNCredentials.mm in Sources */,
|
||||
C9B795601F1D16AA00CF35FE /* OpenVPNReachability.mm in Sources */,
|
||||
@@ -899,18 +919,20 @@
|
||||
ABD6EF1A1F8F9C3B007D3D90 /* OpenVPNAdapter.mm in Sources */,
|
||||
C9657A431EB0CAC200EFF210 /* OpenVPNServerEntry.mm in Sources */,
|
||||
C9BCE25B1EB3C0D9009D6AC1 /* OpenVPNSessionToken.mm in Sources */,
|
||||
C9E350C4200F6EC0000820D9 /* NSError+OpenVPNError.m in Sources */,
|
||||
ABD6EF0C1F8F8CCD007D3D90 /* OpenVPNNetworkSettingsBuilder.m in Sources */,
|
||||
C98467A91EAA5B7700272A9A /* OpenVPNConfiguration.mm in Sources */,
|
||||
ABD6EF131F8F93AB007D3D90 /* OpenVPNPacketFlowBridge.mm in Sources */,
|
||||
C9E440201F6086A1001D7C41 /* NSError+Message.m in Sources */,
|
||||
C9657A301EB0B7A600EFF210 /* OpenVPNTransportStats.mm in Sources */,
|
||||
C9B795671F1D182500CF35FE /* OpenVPNReachabilityTracker.mm in Sources */,
|
||||
C9657A591EB0CE1400EFF210 /* OpenVPNProperties.mm in Sources */,
|
||||
C9CA4DD61F602F7B00C4F184 /* OpenVPNCertificate.m in Sources */,
|
||||
C9CDFDDE200781AF00323B73 /* OpenVPNClient.mm in Sources */,
|
||||
C915F1F71F612F3300B3DF23 /* OpenVPNPrivateKey.m in Sources */,
|
||||
C9D2ABDE1EA20F99007EDF9D /* ovpncli.cpp in Sources */,
|
||||
C9657A371EB0BA3900EFF210 /* OpenVPNInterfaceStats.mm in Sources */,
|
||||
C9657A221EB0ACAE00EFF210 /* OpenVPNConnectionInfo.mm in Sources */,
|
||||
C9C2B2BE200CC42A00CA0FF3 /* OpenVPNPacket.mm in Sources */,
|
||||
C93A4F631EE18009004DC561 /* OpenVPNError.m in Sources */,
|
||||
C93779D81EAE32670030A362 /* OpenVPNCredentials.mm in Sources */,
|
||||
C9B795611F1D16AA00CF35FE /* OpenVPNReachability.mm in Sources */,
|
||||
@@ -1357,7 +1379,6 @@
|
||||
SUPPORTED_PLATFORMS = macosx;
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_SWIFT3_OBJC_INFERENCE = On;
|
||||
SWIFT_VERSION = 4.0;
|
||||
};
|
||||
name = Debug;
|
||||
@@ -1404,7 +1425,6 @@
|
||||
SDKROOT = macosx;
|
||||
SUPPORTED_PLATFORMS = macosx;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
|
||||
SWIFT_SWIFT3_OBJC_INFERENCE = On;
|
||||
SWIFT_VERSION = 4.0;
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
//
|
||||
// NSError+Message.h
|
||||
// OpenVPN Adapter
|
||||
//
|
||||
// Created by Sergey Abramchuk on 06.09.17.
|
||||
//
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface NSError (Message)
|
||||
|
||||
+ (NSString *)reasonFromResult:(NSInteger)result;
|
||||
|
||||
@end
|
||||
@@ -1,28 +0,0 @@
|
||||
//
|
||||
// NSError+Message.m
|
||||
// OpenVPN Adapter
|
||||
//
|
||||
// Created by Sergey Abramchuk on 06.09.17.
|
||||
//
|
||||
//
|
||||
|
||||
#import <mbedtls/error.h>
|
||||
|
||||
#import "NSError+Message.h"
|
||||
|
||||
@implementation NSError (Message)
|
||||
|
||||
+ (NSString *)reasonFromResult:(NSInteger)result {
|
||||
size_t length = 1024;
|
||||
char *buffer = malloc(length);
|
||||
|
||||
mbedtls_strerror(result, buffer, length);
|
||||
|
||||
NSString *reason = [NSString stringWithUTF8String:buffer];
|
||||
|
||||
free(buffer);
|
||||
|
||||
return reason;
|
||||
}
|
||||
|
||||
@end
|
||||
33
OpenVPN Adapter/NSError+OpenVPNError.h
Normal file
33
OpenVPN Adapter/NSError+OpenVPNError.h
Normal file
@@ -0,0 +1,33 @@
|
||||
//
|
||||
// NSError+OpenVPNError.h
|
||||
// OpenVPN Adapter
|
||||
//
|
||||
// Created by Sergey Abramchuk on 17.01.2018.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
FOUNDATION_EXPORT NSString *const OpenVPNAdapterErrorDomain;
|
||||
|
||||
typedef NS_ERROR_ENUM(OpenVPNAdapterErrorDomain, OpenVPNAdapterError);
|
||||
|
||||
@interface NSError (OpenVPNAdapterErrorGeneration)
|
||||
|
||||
+ (NSError *)ovpn_errorObjectForAdapterError:(OpenVPNAdapterError)adapterError
|
||||
description:(NSString *)description
|
||||
message:(nullable NSString *)message
|
||||
fatal:(BOOL)fatal;
|
||||
|
||||
+ (OpenVPNAdapterError)ovpn_adapterErrorByName:(NSString *)errorName;
|
||||
|
||||
@end
|
||||
|
||||
@interface NSError (OpenVPNMbedTLSErrorGeneration)
|
||||
|
||||
+ (NSError *)ovpn_errorObjectForMbedTLSError:(NSInteger)errorCode description:(NSString *)description;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
203
OpenVPN Adapter/NSError+OpenVPNError.m
Normal file
203
OpenVPN Adapter/NSError+OpenVPNError.m
Normal file
@@ -0,0 +1,203 @@
|
||||
//
|
||||
// NSError+OpenVPNError.m
|
||||
// OpenVPN Adapter
|
||||
//
|
||||
// Created by Sergey Abramchuk on 17.01.2018.
|
||||
//
|
||||
|
||||
#import "NSError+OpenVPNError.h"
|
||||
|
||||
#import <mbedtls/error.h>
|
||||
|
||||
#import "OpenVPNError.h"
|
||||
|
||||
@implementation NSError (OpenVPNAdapterErrorGeneration)
|
||||
|
||||
+ (NSError *)ovpn_errorObjectForAdapterError:(OpenVPNAdapterError)adapterError
|
||||
description:(NSString *)description
|
||||
message:(NSString *)message
|
||||
fatal:(BOOL)fatal
|
||||
{
|
||||
NSMutableDictionary *userInfo = [[NSMutableDictionary alloc] initWithDictionary:@{
|
||||
NSLocalizedDescriptionKey: description,
|
||||
OpenVPNAdapterErrorFatalKey: @(fatal)
|
||||
}];
|
||||
|
||||
NSString *errorReason = [NSError ovpn_reasonForAdapterError:adapterError];
|
||||
if (errorReason) {
|
||||
userInfo[NSLocalizedFailureReasonErrorKey] = errorReason;
|
||||
}
|
||||
|
||||
if (message.length) {
|
||||
userInfo[OpenVPNAdapterErrorMessageKey] = message;
|
||||
}
|
||||
|
||||
return [NSError errorWithDomain:OpenVPNAdapterErrorDomain code:adapterError userInfo:userInfo];
|
||||
}
|
||||
|
||||
+ (OpenVPNAdapterError)ovpn_adapterErrorByName:(NSString *)errorName {
|
||||
NSDictionary *errors = @{
|
||||
@"NETWORK_RECV_ERROR": @(OpenVPNAdapterErrorNetworkRecvError),
|
||||
@"NETWORK_EOF_ERROR": @(OpenVPNAdapterErrorNetworkEOFError),
|
||||
@"NETWORK_SEND_ERROR": @(OpenVPNAdapterErrorNetworkSendError),
|
||||
@"NETWORK_UNAVAILABLE": @(OpenVPNAdapterErrorNetworkUnavailable),
|
||||
@"DECRYPT_ERROR": @(OpenVPNAdapterErrorDecryptError),
|
||||
@"HMAC_ERROR": @(OpenVPNAdapterErrorDecryptError),
|
||||
@"REPLAY_ERROR": @(OpenVPNAdapterErrorReplayError),
|
||||
@"BUFFER_ERROR": @(OpenVPNAdapterErrorBufferError),
|
||||
@"CC_ERROR": @(OpenVPNAdapterErrorCCError),
|
||||
@"BAD_SRC_ADDR": @(OpenVPNAdapterErrorBadSrcAddr),
|
||||
@"COMPRESS_ERROR": @(OpenVPNAdapterErrorCompressError),
|
||||
@"RESOLVE_ERROR": @(OpenVPNAdapterErrorResolveError),
|
||||
@"SOCKET_PROTECT_ERROR": @(OpenVPNAdapterErrorSocketProtectError),
|
||||
@"TUN_READ_ERROR": @(OpenVPNAdapterErrorTUNReadError),
|
||||
@"TUN_WRITE_ERROR": @(OpenVPNAdapterErrorTUNWriteError),
|
||||
@"TUN_FRAMING_ERROR": @(OpenVPNAdapterErrorTUNFramingError),
|
||||
@"TUN_SETUP_FAILED": @(OpenVPNAdapterErrorTUNSetupFailed),
|
||||
@"TUN_IFACE_CREATE": @(OpenVPNAdapterErrorTUNIfaceCreate),
|
||||
@"TUN_IFACE_DISABLED": @(OpenVPNAdapterErrorTUNIfaceDisabled),
|
||||
@"TUN_ERROR": @(OpenVPNAdapterErrorTUNError),
|
||||
@"TAP_NOT_SUPPORTED": @(OpenVPNAdapterErrorTAPNotSupported),
|
||||
@"REROUTE_GW_NO_DNS": @(OpenVPNAdapterErrorRerouteGatewayNoDns),
|
||||
@"TRANSPORT_ERROR": @(OpenVPNAdapterErrorTransportError),
|
||||
@"TCP_OVERFLOW": @(OpenVPNAdapterErrorTCPOverflow),
|
||||
@"TCP_SIZE_ERROR": @(OpenVPNAdapterErrorTCPSizeError),
|
||||
@"TCP_CONNECT_ERROR": @(OpenVPNAdapterErrorTCPConnectError),
|
||||
@"UDP_CONNECT_ERROR": @(OpenVPNAdapterErrorUDPConnectError),
|
||||
@"SSL_ERROR": @(OpenVPNAdapterErrorSSLError),
|
||||
@"SSL_PARTIAL_WRITE": @(OpenVPNAdapterErrorSSLPartialWrite),
|
||||
@"ENCAPSULATION_ERROR": @(OpenVPNAdapterErrorEncapsulationError),
|
||||
@"EPKI_CERT_ERROR": @(OpenVPNAdapterErrorEPKICertError),
|
||||
@"EPKI_SIGN_ERROR": @(OpenVPNAdapterErrorEPKISignError),
|
||||
@"HANDSHAKE_TIMEOUT": @(OpenVPNAdapterErrorHandshakeTimeout),
|
||||
@"KEEPALIVE_TIMEOUT": @(OpenVPNAdapterErrorKeepaliveTimeout),
|
||||
@"INACTIVE_TIMEOUT": @(OpenVPNAdapterErrorInactiveTimeout),
|
||||
@"CONNECTION_TIMEOUT": @(OpenVPNAdapterErrorConnectionTimeout),
|
||||
@"PRIMARY_EXPIRE": @(OpenVPNAdapterErrorPrimaryExpire),
|
||||
@"TLS_VERSION_MIN": @(OpenVPNAdapterErrorTLSVersionMin),
|
||||
@"TLS_AUTH_FAIL": @(OpenVPNAdapterErrorTLSAuthFail),
|
||||
@"CERT_VERIFY_FAIL": @(OpenVPNAdapterErrorCertVerifyFail),
|
||||
@"PEM_PASSWORD_FAIL": @(OpenVPNAdapterErrorPEMPasswordFail),
|
||||
@"AUTH_FAILED": @(OpenVPNAdapterErrorAuthFailed),
|
||||
@"CLIENT_HALT": @(OpenVPNAdapterErrorClientHalt),
|
||||
@"CLIENT_RESTART": @(OpenVPNAdapterErrorClientRestart),
|
||||
@"RELAY": @(OpenVPNAdapterErrorRelay),
|
||||
@"RELAY_ERROR": @(OpenVPNAdapterErrorRelayError),
|
||||
@"N_PAUSE": @(OpenVPNAdapterErrorPauseNumber),
|
||||
@"N_RECONNECT": @(OpenVPNAdapterErrorReconnectNumber),
|
||||
@"N_KEY_LIMIT_RENEG": @(OpenVPNAdapterErrorKeyLimitRenegNumber),
|
||||
@"KEY_STATE_ERROR": @(OpenVPNAdapterErrorKeyStateError),
|
||||
@"PROXY_ERROR": @(OpenVPNAdapterErrorProxyError),
|
||||
@"PROXY_NEED_CREDS": @(OpenVPNAdapterErrorProxyNeedCreds),
|
||||
@"KEV_NEGOTIATE_ERROR": @(OpenVPNAdapterErrorKevNegotiateError),
|
||||
@"KEV_PENDING_ERROR": @(OpenVPNAdapterErrorKevPendingError),
|
||||
@"N_KEV_EXPIRE": @(OpenVPNAdapterErrorKevExpireNumber),
|
||||
@"PKTID_INVALID": @(OpenVPNAdapterErrorPKTIDInvalid),
|
||||
@"PKTID_BACKTRACK": @(OpenVPNAdapterErrorPKTIDBacktrack),
|
||||
@"PKTID_EXPIRE": @(OpenVPNAdapterErrorPKTIDExpire),
|
||||
@"PKTID_REPLAY": @(OpenVPNAdapterErrorPKTIDReplay),
|
||||
@"PKTID_TIME_BACKTRACK": @(OpenVPNAdapterErrorPKTIDTimeBacktrack),
|
||||
@"DYNAMIC_CHALLENGE": @(OpenVPNAdapterErrorDynamicChallenge),
|
||||
@"EPKI_ERROR": @(OpenVPNAdapterErrorEPKIError),
|
||||
@"EPKI_INVALID_ALIAS": @(OpenVPNAdapterErrorEPKIInvalidAlias)
|
||||
};
|
||||
|
||||
OpenVPNAdapterError error = errors[errorName] != nil ?
|
||||
(OpenVPNAdapterError)[errors[errorName] integerValue] : OpenVPNAdapterErrorUnknown;
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
+ (NSString *)ovpn_reasonForAdapterError:(OpenVPNAdapterError)error {
|
||||
switch (error) {
|
||||
case OpenVPNAdapterErrorConfigurationFailure: return @"See OpenVPN error message for more details.";
|
||||
case OpenVPNAdapterErrorCredentialsFailure: return @"See OpenVPN error message for more details.";
|
||||
case OpenVPNAdapterErrorNetworkRecvError: return @"Errors receiving on network socket.";
|
||||
case OpenVPNAdapterErrorNetworkEOFError: return @"EOF received on TCP network socket.";
|
||||
case OpenVPNAdapterErrorNetworkSendError: return @"Errors sending on network socket";
|
||||
case OpenVPNAdapterErrorNetworkUnavailable: return @"Network unavailable.";
|
||||
case OpenVPNAdapterErrorDecryptError: return @"Data channel encrypt/decrypt error.";
|
||||
case OpenVPNAdapterErrorHMACError: return @"HMAC verification failure.";
|
||||
case OpenVPNAdapterErrorReplayError: return @"Error from PacketIDReceive.";
|
||||
case OpenVPNAdapterErrorBufferError: return @"Exception thrown in Buffer methods.";
|
||||
case OpenVPNAdapterErrorCCError: return @"General control channel errors.";
|
||||
case OpenVPNAdapterErrorBadSrcAddr: return @"Packet from unknown source address.";
|
||||
case OpenVPNAdapterErrorCompressError: return @"Compress/Decompress errors on data channel.";
|
||||
case OpenVPNAdapterErrorResolveError: return @"DNS resolution error.";
|
||||
case OpenVPNAdapterErrorSocketSetupFailed: return nil;
|
||||
case OpenVPNAdapterErrorSocketProtectError: return @"Error calling protect() method on socket.";
|
||||
case OpenVPNAdapterErrorTUNReadError: return @"Read errors on TUN/TAP interface.";
|
||||
case OpenVPNAdapterErrorTUNWriteError: return @"Write errors on TUN/TAP interface.";
|
||||
case OpenVPNAdapterErrorTUNFramingError: return @"Error with tun PF_INET/PF_INET6 prefix.";
|
||||
case OpenVPNAdapterErrorTUNSetupFailed: return @"Error setting up TUN/TAP interface.";
|
||||
case OpenVPNAdapterErrorTUNIfaceCreate: return @"Error creating TUN/TAP interface.";
|
||||
case OpenVPNAdapterErrorTUNIfaceDisabled: return @"TUN/TAP interface is disabled.";
|
||||
case OpenVPNAdapterErrorTUNError: return @"General tun error.";
|
||||
case OpenVPNAdapterErrorTAPNotSupported: return @"Dev TAP is present in profile but not supported.";
|
||||
case OpenVPNAdapterErrorRerouteGatewayNoDns: return @"redirect-gateway specified without alt DNS servers.";
|
||||
case OpenVPNAdapterErrorTransportError: return @"General transport error";
|
||||
case OpenVPNAdapterErrorTCPOverflow: return @"TCP output queue overflow.";
|
||||
case OpenVPNAdapterErrorTCPSizeError: return @"Bad embedded uint16_t TCP packet size.";
|
||||
case OpenVPNAdapterErrorTCPConnectError: return @"Client error on TCP connect.";
|
||||
case OpenVPNAdapterErrorUDPConnectError: return @"Client error on UDP connect.";
|
||||
case OpenVPNAdapterErrorSSLError: return @"Errors resulting from read/write on SSL object.";
|
||||
case OpenVPNAdapterErrorSSLPartialWrite: return @"SSL object did not process all written cleartext.";
|
||||
case OpenVPNAdapterErrorEncapsulationError: return @"Exceptions thrown during packet encapsulation.";
|
||||
case OpenVPNAdapterErrorEPKICertError: return @"Error obtaining certificate from External PKI provider.";
|
||||
case OpenVPNAdapterErrorEPKISignError: return @"Error obtaining RSA signature from External PKI provider.";
|
||||
case OpenVPNAdapterErrorHandshakeTimeout: return @"Handshake failed to complete within given time frame.";
|
||||
case OpenVPNAdapterErrorKeepaliveTimeout: return @"Lost contact with peer.";
|
||||
case OpenVPNAdapterErrorInactiveTimeout: return @"Disconnected due to inactive timer.";
|
||||
case OpenVPNAdapterErrorConnectionTimeout: return @"Connection failed to establish within given time.";
|
||||
case OpenVPNAdapterErrorPrimaryExpire: return @"Primary key context expired.";
|
||||
case OpenVPNAdapterErrorTLSVersionMin: return @"Peer cannot handshake at our minimum required TLS version.";
|
||||
case OpenVPNAdapterErrorTLSAuthFail: return @"tls-auth HMAC verification failed.";
|
||||
case OpenVPNAdapterErrorCertVerifyFail: return @"Peer certificate verification failure.";
|
||||
case OpenVPNAdapterErrorPEMPasswordFail: return @"Incorrect or missing PEM private key decryption password.";
|
||||
case OpenVPNAdapterErrorAuthFailed: return @"General authentication failure";
|
||||
case OpenVPNAdapterErrorClientHalt: return @"HALT message from server received.";
|
||||
case OpenVPNAdapterErrorClientRestart: return @"RESTART message from server received.";
|
||||
case OpenVPNAdapterErrorRelay: return @"RELAY message from server received.";
|
||||
case OpenVPNAdapterErrorRelayError: return @"RELAY error.";
|
||||
case OpenVPNAdapterErrorPauseNumber: return nil;
|
||||
case OpenVPNAdapterErrorReconnectNumber: return nil;
|
||||
case OpenVPNAdapterErrorKeyLimitRenegNumber: return nil;
|
||||
case OpenVPNAdapterErrorKeyStateError: return @"Received packet didn't match expected key state.";
|
||||
case OpenVPNAdapterErrorProxyError: return @"HTTP proxy error.";
|
||||
case OpenVPNAdapterErrorProxyNeedCreds: return @"HTTP proxy needs credentials.";
|
||||
case OpenVPNAdapterErrorKevNegotiateError: return nil;
|
||||
case OpenVPNAdapterErrorKevPendingError: return nil;
|
||||
case OpenVPNAdapterErrorKevExpireNumber: return nil;
|
||||
case OpenVPNAdapterErrorPKTIDInvalid: return nil;
|
||||
case OpenVPNAdapterErrorPKTIDBacktrack: return nil;
|
||||
case OpenVPNAdapterErrorPKTIDExpire: return nil;
|
||||
case OpenVPNAdapterErrorPKTIDReplay: return nil;
|
||||
case OpenVPNAdapterErrorPKTIDTimeBacktrack: return nil;
|
||||
case OpenVPNAdapterErrorDynamicChallenge: return nil;
|
||||
case OpenVPNAdapterErrorEPKIError: return nil;
|
||||
case OpenVPNAdapterErrorEPKIInvalidAlias: return nil;
|
||||
case OpenVPNAdapterErrorUnknown: return @"Unknown error.";
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation NSError (OpenVPNMbedTLSErrorGeneration)
|
||||
|
||||
+ (NSError *)ovpn_errorObjectForMbedTLSError:(NSInteger)errorCode description:(NSString *)description {
|
||||
size_t length = 1024;
|
||||
char *buffer = malloc(length);
|
||||
|
||||
mbedtls_strerror(errorCode, buffer, length);
|
||||
|
||||
NSString *reason = [NSString stringWithUTF8String:buffer];
|
||||
|
||||
free(buffer);
|
||||
|
||||
return [NSError errorWithDomain:OpenVPNIdentityErrorDomain code:errorCode userInfo:@{
|
||||
NSLocalizedDescriptionKey: description,
|
||||
NSLocalizedFailureReasonErrorKey: reason
|
||||
}];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -7,12 +7,16 @@
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "OpenVPNAdapterEvent.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
typedef NS_ENUM(NSInteger, OpenVPNAdapterEvent);
|
||||
|
||||
@class NEPacketTunnelFlow;
|
||||
@class NEPacketTunnelNetworkSettings;
|
||||
|
||||
@protocol OpenVPNAdapterPacketFlow;
|
||||
|
||||
@class OpenVPNAdapter;
|
||||
@class OpenVPNConfiguration;
|
||||
@class OpenVPNConnectionInfo;
|
||||
@@ -26,17 +30,22 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
This method is called once the network settings to be used have been established.
|
||||
The receiver should call the completion handler once these settings have been set, returning a NEPacketTunnelFlow object for the TUN interface, or nil if an error occurred.
|
||||
The receiver should call the completion handler once these settings have been set, returning a NEPacketTunnelFlow object for
|
||||
the TUN interface, or nil if an error occurred.
|
||||
|
||||
@param openVPNAdapter The OpenVPNAdapter instance requesting this information.
|
||||
@param networkSettings The NEPacketTunnelNetworkSettings to be used for the tunnel.
|
||||
@param completionHandler The completion handler to be called with a NEPacketTunnelFlow object, or nil if an error occurred.
|
||||
*/
|
||||
- (void)openVPNAdapter:(OpenVPNAdapter *)openVPNAdapter configureTunnelWithNetworkSettings:(NEPacketTunnelNetworkSettings *)networkSettings completionHandler:(void (^)(NEPacketTunnelFlow * _Nullable packetFlow))completionHandler NS_SWIFT_NAME(openVPNAdapter(_:configureTunnelWithNetworkSettings:completionHandler:));
|
||||
- (void)openVPNAdapter:(OpenVPNAdapter *)openVPNAdapter
|
||||
configureTunnelWithNetworkSettings:(NEPacketTunnelNetworkSettings *)networkSettings
|
||||
completionHandler:(void (^)(id<OpenVPNAdapterPacketFlow> _Nullable packetFlow))completionHandler
|
||||
NS_SWIFT_NAME(openVPNAdapter(_:configureTunnelWithNetworkSettings:completionHandler:));
|
||||
|
||||
/**
|
||||
Informs the receiver that an OpenVPN error has occurred.
|
||||
Some errors are fatal and should trigger the diconnection of the tunnel, check for fatal errors with the OpenVPNAdapterErrorFatalKey.
|
||||
Some errors are fatal and should trigger the diconnection of the tunnel, check for fatal errors with the
|
||||
OpenVPNAdapterErrorFatalKey.
|
||||
|
||||
@param openVPNAdapter The OpenVPNAdapter instance which encountered the error.
|
||||
@param error The error which has occurred.
|
||||
@@ -50,7 +59,10 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
@param event The event which has occurred.
|
||||
@param message An accompanying message, may be nil.
|
||||
*/
|
||||
- (void)openVPNAdapter:(OpenVPNAdapter *)openVPNAdapter handleEvent:(OpenVPNAdapterEvent)event message:(nullable NSString *)message NS_SWIFT_NAME(openVPNAdapter(_:handleEvent:message:));
|
||||
- (void)openVPNAdapter:(OpenVPNAdapter *)openVPNAdapter
|
||||
handleEvent:(OpenVPNAdapterEvent)event
|
||||
message:(nullable NSString *)message
|
||||
NS_SWIFT_NAME(openVPNAdapter(_:handleEvent:message:));
|
||||
|
||||
@optional
|
||||
|
||||
@@ -122,7 +134,9 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
@param error If there is an error applying the configuration, upon return contains an error object that describes the problem.
|
||||
@return A properties object describing the configuration which has been applied.
|
||||
*/
|
||||
- (nullable OpenVPNProperties *)applyConfiguration:(OpenVPNConfiguration *)configuration error:(NSError **)error NS_SWIFT_NAME(apply(configuration:));
|
||||
- (nullable OpenVPNProperties *)applyConfiguration:(OpenVPNConfiguration *)configuration
|
||||
error:(NSError **)error
|
||||
NS_SWIFT_NAME(apply(configuration:));
|
||||
|
||||
/**
|
||||
Provides credentials to the receiver.
|
||||
|
||||
@@ -8,265 +8,39 @@
|
||||
|
||||
#define OPENVPN_EXTERN extern
|
||||
|
||||
#import "OpenVPNAdapter.h"
|
||||
|
||||
#import <NetworkExtension/NetworkExtension.h>
|
||||
#import <client/ovpncli.hpp>
|
||||
#import <openvpn/tun/client/tunbase.hpp>
|
||||
|
||||
#import "OpenVPNClient.h"
|
||||
#import "OpenVPNError.h"
|
||||
#import "OpenVPNAdapterEvent.h"
|
||||
#import "OpenVPNPacketFlowBridge.h"
|
||||
#import "OpenVPNNetworkSettingsBuilder.h"
|
||||
#import "OpenVPNAdapterPacketFlow.h"
|
||||
#import "OpenVPNCredentials+Internal.h"
|
||||
#import "OpenVPNConfiguration+Internal.h"
|
||||
#import "OpenVPNConnectionInfo+Internal.h"
|
||||
#import "OpenVPNError.h"
|
||||
#import "OpenVPNInterfaceStats+Internal.h"
|
||||
#import "OpenVPNNetworkSettingsBuilder.h"
|
||||
#import "OpenVPNPacketFlowBridge.h"
|
||||
#import "OpenVPNProperties+Internal.h"
|
||||
#import "OpenVPNSessionToken+Internal.h"
|
||||
#import "OpenVPNTransportStats+Internal.h"
|
||||
#import "OpenVPNAdapter.h"
|
||||
#import "NSError+OpenVPNError.h"
|
||||
|
||||
class Client;
|
||||
@interface OpenVPNAdapter () <OpenVPNClientDelegate>
|
||||
|
||||
@interface OpenVPNAdapter ()
|
||||
|
||||
@property (nonatomic) Client *client;
|
||||
|
||||
@property (nonatomic) NSString *sessionName;
|
||||
|
||||
@property (nonatomic) OpenVPNNetworkSettingsBuilder *networkSettingsBuilder;
|
||||
@property (nonatomic) OpenVPNClient *vpnClient;
|
||||
|
||||
@property (nonatomic) OpenVPNPacketFlowBridge *packetFlowBridge;
|
||||
|
||||
- (OpenVPNAdapterError)errorByName:(NSString *)errorName;
|
||||
- (OpenVPNAdapterEvent)eventByName:(NSString *)errorName;
|
||||
- (NSString *)reasonForError:(OpenVPNAdapterError)error;
|
||||
@property (nonatomic) OpenVPNNetworkSettingsBuilder *networkSettingsBuilder;
|
||||
|
||||
@end
|
||||
|
||||
using namespace openvpn;
|
||||
|
||||
class Client : public ClientAPI::OpenVPNClient {
|
||||
public:
|
||||
Client(OpenVPNAdapter *adapter) {
|
||||
this->adapter = adapter;
|
||||
}
|
||||
|
||||
bool tun_builder_set_remote_address(const std::string& address, bool ipv6) override {
|
||||
NSString *remoteAddress = [[NSString alloc] initWithUTF8String:address.c_str()];
|
||||
adapter.networkSettingsBuilder.remoteAddress = remoteAddress;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool tun_builder_add_address(const std::string& address, int prefix_length, const std::string& gateway, bool ipv6, bool net30) override {
|
||||
NSString *localAddress = [[NSString alloc] initWithUTF8String:address.c_str()];
|
||||
NSString *gatewayAddress = [[NSString alloc] initWithUTF8String:gateway.c_str()];
|
||||
NSString *defaultGateway = gatewayAddress.length == 0 || [gatewayAddress isEqualToString:@"UNSPEC"] ? nil : gatewayAddress;
|
||||
if (ipv6) {
|
||||
adapter.networkSettingsBuilder.ipv6DefaultGateway = defaultGateway;
|
||||
[adapter.networkSettingsBuilder.ipv6LocalAddresses addObject:localAddress];
|
||||
[adapter.networkSettingsBuilder.ipv6NetworkPrefixLengths addObject:@(prefix_length)];
|
||||
} else {
|
||||
NSString *subnetMask = [[NSString alloc] initWithUTF8String:IPv4::Addr::netmask_from_prefix_len(prefix_length).to_string().c_str()];
|
||||
adapter.networkSettingsBuilder.ipv4DefaultGateway = defaultGateway;
|
||||
[adapter.networkSettingsBuilder.ipv4LocalAddresses addObject:localAddress];
|
||||
[adapter.networkSettingsBuilder.ipv4SubnetMasks addObject:subnetMask];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool tun_builder_reroute_gw(bool ipv4, bool ipv6, unsigned int flags) override {
|
||||
if (ipv4) {
|
||||
NEIPv4Route *includedRoute = [NEIPv4Route defaultRoute];
|
||||
includedRoute.gatewayAddress = adapter.networkSettingsBuilder.ipv4DefaultGateway;
|
||||
[adapter.networkSettingsBuilder.ipv4IncludedRoutes addObject:includedRoute];
|
||||
}
|
||||
if (ipv6) {
|
||||
NEIPv6Route *includedRoute = [NEIPv6Route defaultRoute];
|
||||
includedRoute.gatewayAddress = adapter.networkSettingsBuilder.ipv6DefaultGateway;
|
||||
[adapter.networkSettingsBuilder.ipv6IncludedRoutes addObject:includedRoute];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool tun_builder_add_route(const std::string& address, int prefix_length, int metric, bool ipv6) override {
|
||||
NSString *route = [[NSString alloc] initWithUTF8String:address.c_str()];
|
||||
if (ipv6) {
|
||||
NEIPv6Route *includedRoute = [[NEIPv6Route alloc] initWithDestinationAddress:route networkPrefixLength:@(prefix_length)];
|
||||
includedRoute.gatewayAddress = adapter.networkSettingsBuilder.ipv6DefaultGateway;
|
||||
[adapter.networkSettingsBuilder.ipv6IncludedRoutes addObject:includedRoute];
|
||||
} else {
|
||||
NSString *subnetMask = [[NSString alloc] initWithUTF8String:IPv4::Addr::netmask_from_prefix_len(prefix_length).to_string().c_str()];
|
||||
NEIPv4Route *includedRoute = [[NEIPv4Route alloc] initWithDestinationAddress:route subnetMask:subnetMask];
|
||||
includedRoute.gatewayAddress = adapter.networkSettingsBuilder.ipv4DefaultGateway;
|
||||
[adapter.networkSettingsBuilder.ipv4IncludedRoutes addObject:includedRoute];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool tun_builder_exclude_route(const std::string& address, int prefix_length, int metric, bool ipv6) override {
|
||||
NSString *route = [[NSString alloc] initWithUTF8String:address.c_str()];
|
||||
if (ipv6) {
|
||||
NEIPv6Route *excludedRoute = [[NEIPv6Route alloc] initWithDestinationAddress:route networkPrefixLength:@(prefix_length)];
|
||||
[adapter.networkSettingsBuilder.ipv6ExcludedRoutes addObject:excludedRoute];
|
||||
} else {
|
||||
NSString *subnetMask = [[NSString alloc] initWithUTF8String:IPv4::Addr::netmask_from_prefix_len(prefix_length).to_string().c_str()];
|
||||
NEIPv4Route *excludedRoute = [[NEIPv4Route alloc] initWithDestinationAddress:route subnetMask:subnetMask];
|
||||
[adapter.networkSettingsBuilder.ipv4ExcludedRoutes addObject:excludedRoute];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool tun_builder_add_dns_server(const std::string& address, bool ipv6) override {
|
||||
NSString *dnsAddress = [[NSString alloc] initWithUTF8String:address.c_str()];
|
||||
[adapter.networkSettingsBuilder.dnsServers addObject:dnsAddress];
|
||||
return true;
|
||||
}
|
||||
|
||||
bool tun_builder_add_search_domain(const std::string& domain) override {
|
||||
NSString *searchDomain = [[NSString alloc] initWithUTF8String:domain.c_str()];
|
||||
[adapter.networkSettingsBuilder.searchDomains addObject:searchDomain];
|
||||
return true;
|
||||
}
|
||||
|
||||
bool tun_builder_set_mtu(int mtu) override {
|
||||
adapter.networkSettingsBuilder.mtu = @(mtu);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool tun_builder_set_session_name(const std::string& name) override {
|
||||
adapter.sessionName = [[NSString alloc] initWithUTF8String:name.c_str()];
|
||||
return true;
|
||||
}
|
||||
|
||||
bool tun_builder_add_proxy_bypass(const std::string& bypass_host) override {
|
||||
NSString *bypassHost = [[NSString alloc] initWithUTF8String:bypass_host.c_str()];
|
||||
[adapter.networkSettingsBuilder.proxyExceptionList addObject:bypassHost];
|
||||
return true;
|
||||
}
|
||||
|
||||
bool tun_builder_set_proxy_auto_config_url(const std::string& urlString) override {
|
||||
NSURL *url = [[NSURL alloc] initWithString:[[NSString alloc] initWithUTF8String:urlString.c_str()]];
|
||||
adapter.networkSettingsBuilder.autoProxyConfigurationEnabled = url != nil;
|
||||
adapter.networkSettingsBuilder.proxyAutoConfigurationURL = url;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool tun_builder_set_proxy_http(const std::string& host, int port) override {
|
||||
NSString *address = [[NSString alloc] initWithUTF8String:host.c_str()];
|
||||
adapter.networkSettingsBuilder.httpProxyServerEnabled = YES;
|
||||
adapter.networkSettingsBuilder.httpProxyServer = [[NEProxyServer alloc] initWithAddress:address port:port];
|
||||
return true;
|
||||
}
|
||||
|
||||
bool tun_builder_set_proxy_https(const std::string& host, int port) override {
|
||||
NSString *address = [[NSString alloc] initWithUTF8String:host.c_str()];
|
||||
adapter.networkSettingsBuilder.httpsProxyServerEnabled = YES;
|
||||
adapter.networkSettingsBuilder.httpsProxyServer = [[NEProxyServer alloc] initWithAddress:address port:port];
|
||||
return true;
|
||||
}
|
||||
|
||||
bool tun_builder_set_block_ipv6(bool block_ipv6) override {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool tun_builder_new() override {
|
||||
reset_tun();
|
||||
return true;
|
||||
}
|
||||
|
||||
int tun_builder_establish() override {
|
||||
NEPacketTunnelNetworkSettings *networkSettings = adapter.networkSettingsBuilder.networkSettings;
|
||||
if (!networkSettings) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
|
||||
[adapter.delegate openVPNAdapter:adapter configureTunnelWithNetworkSettings:networkSettings completionHandler:^(NEPacketTunnelFlow * _Nullable flow) {
|
||||
adapter.packetFlowBridge = [[OpenVPNPacketFlowBridge alloc] initWithPacketFlow:flow];
|
||||
dispatch_semaphore_signal(semaphore);
|
||||
}];
|
||||
dispatch_semaphore_wait(semaphore, dispatch_time(DISPATCH_TIME_NOW, 30 * NSEC_PER_SEC));
|
||||
|
||||
if (adapter.packetFlowBridge) {
|
||||
return adapter.packetFlowBridge.socketHandle;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
void tun_builder_teardown(bool disconnect) override {
|
||||
reset_tun();
|
||||
}
|
||||
|
||||
bool tun_builder_persist() override {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool socket_protect(int socket) override {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool pause_on_connection_timeout() override {
|
||||
return false;
|
||||
}
|
||||
|
||||
void external_pki_cert_request(ClientAPI::ExternalPKICertRequest& certreq) override {
|
||||
|
||||
}
|
||||
|
||||
void external_pki_sign_request(ClientAPI::ExternalPKISignRequest& signreq) override {
|
||||
|
||||
}
|
||||
|
||||
void event(const ClientAPI::Event& event) override {
|
||||
NSString *name = [[NSString alloc] initWithUTF8String:event.name.c_str()];
|
||||
NSString *message = [[NSString alloc] initWithUTF8String:event.info.c_str()];
|
||||
|
||||
if (event.error) {
|
||||
OpenVPNAdapterError errorCode = [adapter errorByName:name];
|
||||
NSString *errorReason = [adapter reasonForError:errorCode];
|
||||
|
||||
NSDictionary *userInfo = @{ NSLocalizedDescriptionKey: @"OpenVPN error occured.",
|
||||
NSLocalizedFailureReasonErrorKey: errorReason,
|
||||
OpenVPNAdapterErrorMessageKey: message != nil ? message : @"",
|
||||
OpenVPNAdapterErrorFatalKey: @(event.fatal) };
|
||||
|
||||
NSError *error = [NSError errorWithDomain:OpenVPNAdapterErrorDomain code:errorCode userInfo:userInfo];
|
||||
[adapter.delegate openVPNAdapter:adapter handleError:error];
|
||||
} else {
|
||||
OpenVPNAdapterEvent eventIdentifier = [adapter eventByName:name];
|
||||
[adapter.delegate openVPNAdapter:adapter handleEvent:eventIdentifier message:message.length ? message : nil];
|
||||
}
|
||||
}
|
||||
|
||||
void log(const ClientAPI::LogInfo& log) override {
|
||||
if ([adapter.delegate respondsToSelector:@selector(openVPNAdapter:handleLogMessage:)]) {
|
||||
[adapter.delegate openVPNAdapter:adapter handleLogMessage:[[NSString alloc] initWithUTF8String:log.text.c_str()]];
|
||||
}
|
||||
}
|
||||
|
||||
void clock_tick() override {
|
||||
if ([adapter.delegate respondsToSelector:@selector(openVPNAdapterDidReceiveClockTick:)]) {
|
||||
[adapter.delegate openVPNAdapterDidReceiveClockTick:adapter];
|
||||
}
|
||||
}
|
||||
|
||||
void reset_tun() {
|
||||
adapter.packetFlowBridge = nil;
|
||||
adapter.networkSettingsBuilder = nil;
|
||||
adapter.sessionName = nil;
|
||||
}
|
||||
|
||||
private:
|
||||
OpenVPNAdapter *adapter;
|
||||
};
|
||||
|
||||
@implementation OpenVPNAdapter
|
||||
|
||||
#pragma mark - Initialization
|
||||
|
||||
- (instancetype)init {
|
||||
if ((self = [super init])) {
|
||||
self.client = new Client(self);
|
||||
if (self = [super init]) {
|
||||
_vpnClient = new OpenVPNClient(self);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
@@ -274,19 +48,17 @@ private:
|
||||
#pragma mark - OpenVPNClient Lifecycle
|
||||
|
||||
- (OpenVPNProperties *)applyConfiguration:(OpenVPNConfiguration *)configuration error:(NSError * _Nullable __autoreleasing *)error {
|
||||
ClientAPI::EvalConfig eval = self.client->eval_config(configuration.config);
|
||||
ClientAPI::EvalConfig eval = self.vpnClient->eval_config(configuration.config);
|
||||
|
||||
if (eval.error) {
|
||||
if (error) {
|
||||
NSString *errorReason = [self reasonForError:OpenVPNAdapterErrorConfigurationFailure];
|
||||
|
||||
NSDictionary *userInfo = @{ NSLocalizedDescriptionKey: @"Failed to apply OpenVPN configuration.",
|
||||
NSLocalizedFailureReasonErrorKey: errorReason,
|
||||
OpenVPNAdapterErrorMessageKey: [[NSString alloc] initWithUTF8String:eval.message.c_str()],
|
||||
OpenVPNAdapterErrorFatalKey: @YES };
|
||||
|
||||
*error = [NSError errorWithDomain:OpenVPNAdapterErrorDomain code:OpenVPNAdapterErrorConfigurationFailure userInfo: userInfo];
|
||||
NSString *message = [NSString stringWithUTF8String:eval.message.c_str()];
|
||||
*error = [NSError ovpn_errorObjectForAdapterError:OpenVPNAdapterErrorConfigurationFailure
|
||||
description:@"Failed to apply OpenVPN configuration"
|
||||
message:message
|
||||
fatal:YES];
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
@@ -294,22 +66,15 @@ private:
|
||||
}
|
||||
|
||||
- (BOOL)provideCredentials:(OpenVPNCredentials *)credentials error:(NSError * _Nullable __autoreleasing *)error {
|
||||
ClientAPI::Status status = self.client->provide_creds(credentials.credentials);
|
||||
ClientAPI::Status status = self.vpnClient->provide_creds(credentials.credentials);
|
||||
|
||||
if (status.error) {
|
||||
if (error) {
|
||||
OpenVPNAdapterError errorCode = !status.status.empty() ?
|
||||
[self errorByName:[[NSString alloc] initWithUTF8String:status.status.c_str()]] :
|
||||
OpenVPNAdapterErrorCredentialsFailure;
|
||||
|
||||
NSString *errorReason = [self reasonForError:errorCode];
|
||||
|
||||
NSDictionary *userInfo = @{ NSLocalizedDescriptionKey: @"Failed to provide OpenVPN credentials.",
|
||||
NSLocalizedFailureReasonErrorKey: errorReason,
|
||||
OpenVPNAdapterErrorMessageKey: [[NSString alloc] initWithUTF8String:status.message.c_str()],
|
||||
OpenVPNAdapterErrorFatalKey: @YES };
|
||||
|
||||
*error = [NSError errorWithDomain:OpenVPNAdapterErrorDomain code:errorCode userInfo:userInfo];
|
||||
NSString *message = [NSString stringWithUTF8String:status.message.c_str()];
|
||||
*error = [NSError ovpn_errorObjectForAdapterError:OpenVPNAdapterErrorCredentialsFailure
|
||||
description:@"Failed to provide OpenVPN credentials"
|
||||
message:message
|
||||
fatal:YES];
|
||||
}
|
||||
|
||||
return NO;
|
||||
@@ -320,255 +85,273 @@ private:
|
||||
|
||||
- (void)connect {
|
||||
dispatch_queue_attr_t attributes = dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_UTILITY, 0);
|
||||
dispatch_queue_t connectQueue = dispatch_queue_create("com.openvpnadapter.connection", attributes);
|
||||
dispatch_queue_t connectQueue = dispatch_queue_create("me.ss-abramchuk.openvpn-adapter.connection", attributes);
|
||||
dispatch_async(connectQueue, ^{
|
||||
Client::init_process();
|
||||
ClientAPI::Status status = self.client->connect();
|
||||
OpenVPNClient::init_process();
|
||||
|
||||
ClientAPI::Status status = self.vpnClient->connect();
|
||||
[self handleConnectionStatus:status];
|
||||
Client::uninit_process();
|
||||
|
||||
OpenVPNClient::uninit_process();
|
||||
});
|
||||
}
|
||||
|
||||
- (void)reconnectAfterTimeInterval:(NSTimeInterval)timeInterval {
|
||||
self.client->reconnect(timeInterval);
|
||||
self.vpnClient->reconnect(timeInterval);
|
||||
}
|
||||
|
||||
- (void)disconnect {
|
||||
self.client->stop();
|
||||
self.vpnClient->stop();
|
||||
}
|
||||
|
||||
- (void)pauseWithReason:(NSString *)reason {
|
||||
self.client->pause(std::string(reason.UTF8String));
|
||||
self.vpnClient->pause(std::string(reason.UTF8String));
|
||||
}
|
||||
|
||||
- (void)resume {
|
||||
self.client->resume();
|
||||
self.vpnClient->resume();
|
||||
}
|
||||
|
||||
- (void)handleConnectionStatus:(ClientAPI::Status)status {
|
||||
if (!status.error) {
|
||||
return;
|
||||
}
|
||||
if (!status.error) { return; }
|
||||
|
||||
OpenVPNAdapterError errorCode = !status.status.empty() ? [self errorByName:[[NSString alloc] initWithUTF8String:status.status.c_str()]] : OpenVPNAdapterErrorUnknown;
|
||||
NSString *errorReason = [self reasonForError:errorCode];
|
||||
OpenVPNAdapterError adapterError = !status.status.empty() ?
|
||||
[NSError ovpn_adapterErrorByName:[NSString stringWithUTF8String:status.status.c_str()]] :
|
||||
OpenVPNAdapterErrorUnknown;
|
||||
|
||||
NSDictionary *userInfo = @{ NSLocalizedDescriptionKey: @"Failed to establish connection with OpenVPN server.",
|
||||
NSLocalizedFailureReasonErrorKey: errorReason,
|
||||
OpenVPNAdapterErrorMessageKey: [[NSString alloc] initWithUTF8String:status.message.c_str()],
|
||||
OpenVPNAdapterErrorFatalKey: @YES };
|
||||
|
||||
NSError *error = [NSError errorWithDomain:OpenVPNAdapterErrorDomain code:errorCode userInfo:userInfo];
|
||||
NSString *message = [NSString stringWithUTF8String:status.message.c_str()];
|
||||
NSError *error = [NSError ovpn_errorObjectForAdapterError:adapterError
|
||||
description:@"Failed to establish connection with OpenVPN server"
|
||||
message:message
|
||||
fatal:YES];
|
||||
|
||||
[self.delegate openVPNAdapter:self handleError:error];
|
||||
}
|
||||
|
||||
#pragma mark - OpenVPNClient Information
|
||||
|
||||
+ (NSString *)copyright {
|
||||
return [[NSString alloc] initWithUTF8String:Client::copyright().c_str()];
|
||||
return [NSString stringWithUTF8String:OpenVPNClient::copyright().c_str()];
|
||||
}
|
||||
|
||||
+ (NSString *)platform {
|
||||
return [[NSString alloc] initWithUTF8String:Client::platform().c_str()];
|
||||
return [NSString stringWithUTF8String:OpenVPNClient::platform().c_str()];
|
||||
}
|
||||
|
||||
- (OpenVPNConnectionInfo *)connectionInformation {
|
||||
ClientAPI::ConnectionInfo information = self.client->connection_info();
|
||||
ClientAPI::ConnectionInfo information = self.vpnClient->connection_info();
|
||||
return information.defined ? [[OpenVPNConnectionInfo alloc] initWithConnectionInfo:information] : nil;
|
||||
}
|
||||
|
||||
- (OpenVPNInterfaceStats *)interfaceStatistics {
|
||||
return [[OpenVPNInterfaceStats alloc] initWithInterfaceStats:self.client->tun_stats()];
|
||||
return [[OpenVPNInterfaceStats alloc] initWithInterfaceStats:self.vpnClient->tun_stats()];
|
||||
}
|
||||
|
||||
- (OpenVPNSessionToken *)sessionToken {
|
||||
ClientAPI::SessionToken token;
|
||||
return self.client->session_token(token) ? [[OpenVPNSessionToken alloc] initWithSessionToken:token] : nil;
|
||||
return self.vpnClient->session_token(token) ? [[OpenVPNSessionToken alloc] initWithSessionToken:token] : nil;
|
||||
}
|
||||
|
||||
- (OpenVPNTransportStats *)transportStatistics {
|
||||
return [[OpenVPNTransportStats alloc] initWithTransportStats:self.client->transport_stats()];
|
||||
}
|
||||
|
||||
#pragma mark - OpenVPNAdapterEvent Helpers
|
||||
|
||||
- (OpenVPNAdapterEvent)eventByName:(NSString *)eventName {
|
||||
NSDictionary *events = @{@"DISCONNECTED": @(OpenVPNAdapterEventDisconnected),
|
||||
@"CONNECTED": @(OpenVPNAdapterEventConnected),
|
||||
@"RECONNECTING": @(OpenVPNAdapterEventReconnecting),
|
||||
@"RESOLVE": @(OpenVPNAdapterEventResolve),
|
||||
@"WAIT": @(OpenVPNAdapterEventWait),
|
||||
@"WAIT_PROXY": @(OpenVPNAdapterEventWaitProxy),
|
||||
@"CONNECTING": @(OpenVPNAdapterEventConnecting),
|
||||
@"GET_CONFIG": @(OpenVPNAdapterEventGetConfig),
|
||||
@"ASSIGN_IP": @(OpenVPNAdapterEventAssignIP),
|
||||
@"ADD_ROUTES": @(OpenVPNAdapterEventAddRoutes),
|
||||
@"ECHO": @(OpenVPNAdapterEventEcho),
|
||||
@"INFO": @(OpenVPNAdapterEventInfo),
|
||||
@"PAUSE": @(OpenVPNAdapterEventPause),
|
||||
@"RESUME": @(OpenVPNAdapterEventResume),
|
||||
@"RELAY": @(OpenVPNAdapterEventRelay)};
|
||||
|
||||
OpenVPNAdapterEvent event = events[eventName] != nil ? (OpenVPNAdapterEvent)[events[eventName] integerValue] : OpenVPNAdapterEventUnknown;
|
||||
return event;
|
||||
}
|
||||
|
||||
#pragma mark - OpenVPNAdapterError Helpers
|
||||
|
||||
- (OpenVPNAdapterError)errorByName:(NSString *)errorName {
|
||||
NSDictionary *errors = @{@"NETWORK_RECV_ERROR": @(OpenVPNAdapterErrorNetworkRecvError),
|
||||
@"NETWORK_EOF_ERROR": @(OpenVPNAdapterErrorNetworkEOFError),
|
||||
@"NETWORK_SEND_ERROR": @(OpenVPNAdapterErrorNetworkSendError),
|
||||
@"NETWORK_UNAVAILABLE": @(OpenVPNAdapterErrorNetworkUnavailable),
|
||||
@"DECRYPT_ERROR": @(OpenVPNAdapterErrorDecryptError),
|
||||
@"HMAC_ERROR": @(OpenVPNAdapterErrorDecryptError),
|
||||
@"REPLAY_ERROR": @(OpenVPNAdapterErrorReplayError),
|
||||
@"BUFFER_ERROR": @(OpenVPNAdapterErrorBufferError),
|
||||
@"CC_ERROR": @(OpenVPNAdapterErrorCCError),
|
||||
@"BAD_SRC_ADDR": @(OpenVPNAdapterErrorBadSrcAddr),
|
||||
@"COMPRESS_ERROR": @(OpenVPNAdapterErrorCompressError),
|
||||
@"RESOLVE_ERROR": @(OpenVPNAdapterErrorResolveError),
|
||||
@"SOCKET_PROTECT_ERROR": @(OpenVPNAdapterErrorSocketProtectError),
|
||||
@"TUN_READ_ERROR": @(OpenVPNAdapterErrorTUNReadError),
|
||||
@"TUN_WRITE_ERROR": @(OpenVPNAdapterErrorTUNWriteError),
|
||||
@"TUN_FRAMING_ERROR": @(OpenVPNAdapterErrorTUNFramingError),
|
||||
@"TUN_SETUP_FAILED": @(OpenVPNAdapterErrorTUNSetupFailed),
|
||||
@"TUN_IFACE_CREATE": @(OpenVPNAdapterErrorTUNIfaceCreate),
|
||||
@"TUN_IFACE_DISABLED": @(OpenVPNAdapterErrorTUNIfaceDisabled),
|
||||
@"TUN_ERROR": @(OpenVPNAdapterErrorTUNError),
|
||||
@"TAP_NOT_SUPPORTED": @(OpenVPNAdapterErrorTAPNotSupported),
|
||||
@"REROUTE_GW_NO_DNS": @(OpenVPNAdapterErrorRerouteGatewayNoDns),
|
||||
@"TRANSPORT_ERROR": @(OpenVPNAdapterErrorTransportError),
|
||||
@"TCP_OVERFLOW": @(OpenVPNAdapterErrorTCPOverflow),
|
||||
@"TCP_SIZE_ERROR": @(OpenVPNAdapterErrorTCPSizeError),
|
||||
@"TCP_CONNECT_ERROR": @(OpenVPNAdapterErrorTCPConnectError),
|
||||
@"UDP_CONNECT_ERROR": @(OpenVPNAdapterErrorUDPConnectError),
|
||||
@"SSL_ERROR": @(OpenVPNAdapterErrorSSLError),
|
||||
@"SSL_PARTIAL_WRITE": @(OpenVPNAdapterErrorSSLPartialWrite),
|
||||
@"ENCAPSULATION_ERROR": @(OpenVPNAdapterErrorEncapsulationError),
|
||||
@"EPKI_CERT_ERROR": @(OpenVPNAdapterErrorEPKICertError),
|
||||
@"EPKI_SIGN_ERROR": @(OpenVPNAdapterErrorEPKISignError),
|
||||
@"HANDSHAKE_TIMEOUT": @(OpenVPNAdapterErrorHandshakeTimeout),
|
||||
@"KEEPALIVE_TIMEOUT": @(OpenVPNAdapterErrorKeepaliveTimeout),
|
||||
@"INACTIVE_TIMEOUT": @(OpenVPNAdapterErrorInactiveTimeout),
|
||||
@"CONNECTION_TIMEOUT": @(OpenVPNAdapterErrorConnectionTimeout),
|
||||
@"PRIMARY_EXPIRE": @(OpenVPNAdapterErrorPrimaryExpire),
|
||||
@"TLS_VERSION_MIN": @(OpenVPNAdapterErrorTLSVersionMin),
|
||||
@"TLS_AUTH_FAIL": @(OpenVPNAdapterErrorTLSAuthFail),
|
||||
@"CERT_VERIFY_FAIL": @(OpenVPNAdapterErrorCertVerifyFail),
|
||||
@"PEM_PASSWORD_FAIL": @(OpenVPNAdapterErrorPEMPasswordFail),
|
||||
@"AUTH_FAILED": @(OpenVPNAdapterErrorAuthFailed),
|
||||
@"CLIENT_HALT": @(OpenVPNAdapterErrorClientHalt),
|
||||
@"CLIENT_RESTART": @(OpenVPNAdapterErrorClientRestart),
|
||||
@"RELAY": @(OpenVPNAdapterErrorRelay),
|
||||
@"RELAY_ERROR": @(OpenVPNAdapterErrorRelayError),
|
||||
@"N_PAUSE": @(OpenVPNAdapterErrorPauseNumber),
|
||||
@"N_RECONNECT": @(OpenVPNAdapterErrorReconnectNumber),
|
||||
@"N_KEY_LIMIT_RENEG": @(OpenVPNAdapterErrorKeyLimitRenegNumber),
|
||||
@"KEY_STATE_ERROR": @(OpenVPNAdapterErrorKeyStateError),
|
||||
@"PROXY_ERROR": @(OpenVPNAdapterErrorProxyError),
|
||||
@"PROXY_NEED_CREDS": @(OpenVPNAdapterErrorProxyNeedCreds),
|
||||
@"KEV_NEGOTIATE_ERROR": @(OpenVPNAdapterErrorKevNegotiateError),
|
||||
@"KEV_PENDING_ERROR": @(OpenVPNAdapterErrorKevPendingError),
|
||||
@"N_KEV_EXPIRE": @(OpenVPNAdapterErrorKevExpireNumber),
|
||||
@"PKTID_INVALID": @(OpenVPNAdapterErrorPKTIDInvalid),
|
||||
@"PKTID_BACKTRACK": @(OpenVPNAdapterErrorPKTIDBacktrack),
|
||||
@"PKTID_EXPIRE": @(OpenVPNAdapterErrorPKTIDExpire),
|
||||
@"PKTID_REPLAY": @(OpenVPNAdapterErrorPKTIDReplay),
|
||||
@"PKTID_TIME_BACKTRACK": @(OpenVPNAdapterErrorPKTIDTimeBacktrack),
|
||||
@"DYNAMIC_CHALLENGE": @(OpenVPNAdapterErrorDynamicChallenge),
|
||||
@"EPKI_ERROR": @(OpenVPNAdapterErrorEPKIError),
|
||||
@"EPKI_INVALID_ALIAS": @(OpenVPNAdapterErrorEPKIInvalidAlias)};
|
||||
|
||||
OpenVPNAdapterError error = errors[errorName] != nil ? (OpenVPNAdapterError)[errors[errorName] integerValue] : OpenVPNAdapterErrorUnknown;
|
||||
return error;
|
||||
}
|
||||
|
||||
- (NSString *)reasonForError:(OpenVPNAdapterError)error {
|
||||
// TODO: Add missing error reasons
|
||||
switch (error) {
|
||||
case OpenVPNAdapterErrorConfigurationFailure: return @"See OpenVPN error message for more details.";
|
||||
case OpenVPNAdapterErrorCredentialsFailure: return @"See OpenVPN error message for more details.";
|
||||
case OpenVPNAdapterErrorNetworkRecvError: return @"Errors receiving on network socket.";
|
||||
case OpenVPNAdapterErrorNetworkEOFError: return @"EOF received on TCP network socket.";
|
||||
case OpenVPNAdapterErrorNetworkSendError: return @"Errors sending on network socket";
|
||||
case OpenVPNAdapterErrorNetworkUnavailable: return @"Network unavailable.";
|
||||
case OpenVPNAdapterErrorDecryptError: return @"Data channel encrypt/decrypt error.";
|
||||
case OpenVPNAdapterErrorHMACError: return @"HMAC verification failure.";
|
||||
case OpenVPNAdapterErrorReplayError: return @"Error from PacketIDReceive.";
|
||||
case OpenVPNAdapterErrorBufferError: return @"Exception thrown in Buffer methods.";
|
||||
case OpenVPNAdapterErrorCCError: return @"General control channel errors.";
|
||||
case OpenVPNAdapterErrorBadSrcAddr: return @"Packet from unknown source address.";
|
||||
case OpenVPNAdapterErrorCompressError: return @"Compress/Decompress errors on data channel.";
|
||||
case OpenVPNAdapterErrorResolveError: return @"DNS resolution error.";
|
||||
case OpenVPNAdapterErrorSocketProtectError: return @"Error calling protect() method on socket.";
|
||||
case OpenVPNAdapterErrorTUNReadError: return @"Read errors on TUN/TAP interface.";
|
||||
case OpenVPNAdapterErrorTUNWriteError: return @"Write errors on TUN/TAP interface.";
|
||||
case OpenVPNAdapterErrorTUNFramingError: return @"Error with tun PF_INET/PF_INET6 prefix.";
|
||||
case OpenVPNAdapterErrorTUNSetupFailed: return @"Error setting up TUN/TAP interface.";
|
||||
case OpenVPNAdapterErrorTUNIfaceCreate: return @"Error creating TUN/TAP interface.";
|
||||
case OpenVPNAdapterErrorTUNIfaceDisabled: return @"TUN/TAP interface is disabled.";
|
||||
case OpenVPNAdapterErrorTUNError: return @"General tun error.";
|
||||
case OpenVPNAdapterErrorTAPNotSupported: return @"Dev TAP is present in profile but not supported.";
|
||||
case OpenVPNAdapterErrorRerouteGatewayNoDns: return @"redirect-gateway specified without alt DNS servers.";
|
||||
case OpenVPNAdapterErrorTransportError: return @"General transport error";
|
||||
case OpenVPNAdapterErrorTCPOverflow: return @"TCP output queue overflow.";
|
||||
case OpenVPNAdapterErrorTCPSizeError: return @"Bad embedded uint16_t TCP packet size.";
|
||||
case OpenVPNAdapterErrorTCPConnectError: return @"Client error on TCP connect.";
|
||||
case OpenVPNAdapterErrorUDPConnectError: return @"Client error on UDP connect.";
|
||||
case OpenVPNAdapterErrorSSLError: return @"Errors resulting from read/write on SSL object.";
|
||||
case OpenVPNAdapterErrorSSLPartialWrite: return @"SSL object did not process all written cleartext.";
|
||||
case OpenVPNAdapterErrorEncapsulationError: return @"Exceptions thrown during packet encapsulation.";
|
||||
case OpenVPNAdapterErrorEPKICertError: return @"Error obtaining certificate from External PKI provider.";
|
||||
case OpenVPNAdapterErrorEPKISignError: return @"Error obtaining RSA signature from External PKI provider.";
|
||||
case OpenVPNAdapterErrorHandshakeTimeout: return @"Handshake failed to complete within given time frame.";
|
||||
case OpenVPNAdapterErrorKeepaliveTimeout: return @"Lost contact with peer.";
|
||||
case OpenVPNAdapterErrorInactiveTimeout: return @"Disconnected due to inactive timer.";
|
||||
case OpenVPNAdapterErrorConnectionTimeout: return @"Connection failed to establish within given time.";
|
||||
case OpenVPNAdapterErrorPrimaryExpire: return @"Primary key context expired.";
|
||||
case OpenVPNAdapterErrorTLSVersionMin: return @"Peer cannot handshake at our minimum required TLS version.";
|
||||
case OpenVPNAdapterErrorTLSAuthFail: return @"tls-auth HMAC verification failed.";
|
||||
case OpenVPNAdapterErrorCertVerifyFail: return @"Peer certificate verification failure.";
|
||||
case OpenVPNAdapterErrorPEMPasswordFail: return @"Incorrect or missing PEM private key decryption password.";
|
||||
case OpenVPNAdapterErrorAuthFailed: return @"General authentication failure";
|
||||
case OpenVPNAdapterErrorClientHalt: return @"HALT message from server received.";
|
||||
case OpenVPNAdapterErrorClientRestart: return @"RESTART message from server received.";
|
||||
case OpenVPNAdapterErrorRelay: return @"RELAY message from server received.";
|
||||
case OpenVPNAdapterErrorRelayError: return @"RELAY error.";
|
||||
case OpenVPNAdapterErrorPauseNumber: return @"";
|
||||
case OpenVPNAdapterErrorReconnectNumber: return @"";
|
||||
case OpenVPNAdapterErrorKeyLimitRenegNumber: return @"";
|
||||
case OpenVPNAdapterErrorKeyStateError: return @"Received packet didn't match expected key state.";
|
||||
case OpenVPNAdapterErrorProxyError: return @"HTTP proxy error.";
|
||||
case OpenVPNAdapterErrorProxyNeedCreds: return @"HTTP proxy needs credentials.";
|
||||
case OpenVPNAdapterErrorKevNegotiateError: return @"";
|
||||
case OpenVPNAdapterErrorKevPendingError: return @"";
|
||||
case OpenVPNAdapterErrorKevExpireNumber: return @"";
|
||||
case OpenVPNAdapterErrorPKTIDInvalid: return @"";
|
||||
case OpenVPNAdapterErrorPKTIDBacktrack: return @"";
|
||||
case OpenVPNAdapterErrorPKTIDExpire: return @"";
|
||||
case OpenVPNAdapterErrorPKTIDReplay: return @"";
|
||||
case OpenVPNAdapterErrorPKTIDTimeBacktrack: return @"";
|
||||
case OpenVPNAdapterErrorDynamicChallenge: return @"";
|
||||
case OpenVPNAdapterErrorEPKIError: return @"";
|
||||
case OpenVPNAdapterErrorEPKIInvalidAlias: return @"";
|
||||
case OpenVPNAdapterErrorUnknown: return @"Unknown error.";
|
||||
}
|
||||
return [[OpenVPNTransportStats alloc] initWithTransportStats:self.vpnClient->transport_stats()];
|
||||
}
|
||||
|
||||
#pragma mark - Lazy Initialization
|
||||
|
||||
- (OpenVPNNetworkSettingsBuilder *)networkSettingsBuilder {
|
||||
if (!_networkSettingsBuilder) {
|
||||
_networkSettingsBuilder = [[OpenVPNNetworkSettingsBuilder alloc] init];
|
||||
}
|
||||
if (!_networkSettingsBuilder) { _networkSettingsBuilder = [[OpenVPNNetworkSettingsBuilder alloc] init]; }
|
||||
return _networkSettingsBuilder;
|
||||
}
|
||||
|
||||
#pragma mark - Dealloc
|
||||
#pragma mark - OpenVPNClientDelegate
|
||||
|
||||
- (BOOL)setRemoteAddress:(NSString *)address {
|
||||
self.networkSettingsBuilder.remoteAddress = address;
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)addIPV4Address:(NSString *)address subnetMask:(NSString *)subnetMask gateway:(NSString *)gateway {
|
||||
self.networkSettingsBuilder.ipv4DefaultGateway = gateway;
|
||||
[self.networkSettingsBuilder.ipv4LocalAddresses addObject:address];
|
||||
[self.networkSettingsBuilder.ipv4SubnetMasks addObject:subnetMask];
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)addIPV6Address:(NSString *)address prefixLength:(NSNumber *)prefixLength gateway:(NSString *)gateway {
|
||||
self.networkSettingsBuilder.ipv6DefaultGateway = gateway;
|
||||
[self.networkSettingsBuilder.ipv6LocalAddresses addObject:address];
|
||||
[self.networkSettingsBuilder.ipv6NetworkPrefixLengths addObject:prefixLength];
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)addIPV4Route:(NEIPv4Route *)route {
|
||||
route.gatewayAddress = self.networkSettingsBuilder.ipv4DefaultGateway;
|
||||
[self.networkSettingsBuilder.ipv4IncludedRoutes addObject:route];
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)addIPV6Route:(NEIPv6Route *)route {
|
||||
route.gatewayAddress = self.networkSettingsBuilder.ipv6DefaultGateway;
|
||||
[self.networkSettingsBuilder.ipv6IncludedRoutes addObject:route];
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)excludeIPV4Route:(NEIPv4Route *)route {
|
||||
[self.networkSettingsBuilder.ipv4ExcludedRoutes addObject:route];
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)excludeIPV6Route:(NEIPv6Route *)route {
|
||||
[self.networkSettingsBuilder.ipv6ExcludedRoutes addObject:route];
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)addDNS:(NSString *)dns {
|
||||
[self.networkSettingsBuilder.dnsServers addObject:dns];
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)addSearchDomain:(NSString *)domain {
|
||||
[self.networkSettingsBuilder.searchDomains addObject:domain];
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)setMTU:(NSNumber *)mtu {
|
||||
self.networkSettingsBuilder.mtu = mtu;
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)setSessionName:(NSString *)name {
|
||||
_sessionName = name;
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)addProxyBypassHost:(NSString *)bypassHost {
|
||||
[self.networkSettingsBuilder.proxyExceptionList addObject:bypassHost];
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)setProxyAutoConfigurationURL:(NSURL *)url {
|
||||
self.networkSettingsBuilder.autoProxyConfigurationEnabled = YES;
|
||||
self.networkSettingsBuilder.proxyAutoConfigurationURL = url;
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)setProxyServer:(NEProxyServer *)server protocol:(OpenVPNProxyServerProtocol)protocol {
|
||||
switch (protocol) {
|
||||
case OpenVPNProxyServerProtocolHTTP:
|
||||
self.networkSettingsBuilder.httpProxyServerEnabled = YES;
|
||||
self.networkSettingsBuilder.httpProxyServer = server;
|
||||
break;
|
||||
|
||||
case OpenVPNProxyServerProtocolHTTPS:
|
||||
self.networkSettingsBuilder.httpsProxyServerEnabled = YES;
|
||||
self.networkSettingsBuilder.httpsProxyServer = server;
|
||||
break;
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)establishTunnel {
|
||||
NEPacketTunnelNetworkSettings *networkSettings = [self.networkSettingsBuilder networkSettings];
|
||||
if (!networkSettings) { return NO; }
|
||||
|
||||
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
|
||||
|
||||
__weak typeof(self) weakSelf = self;
|
||||
void (^completionHandler)(id<OpenVPNAdapterPacketFlow> _Nullable) = ^(id<OpenVPNAdapterPacketFlow> flow) {
|
||||
__strong typeof(self) self = weakSelf;
|
||||
|
||||
if (flow) {
|
||||
self.packetFlowBridge = [[OpenVPNPacketFlowBridge alloc] initWithPacketFlow:flow];
|
||||
}
|
||||
|
||||
dispatch_semaphore_signal(semaphore);
|
||||
};
|
||||
|
||||
[self.delegate openVPNAdapter:self configureTunnelWithNetworkSettings:networkSettings completionHandler:completionHandler];
|
||||
|
||||
dispatch_semaphore_wait(semaphore, dispatch_time(DISPATCH_TIME_NOW, 30 * NSEC_PER_SEC));
|
||||
|
||||
NSError *socketError;
|
||||
if (self.packetFlowBridge && [self.packetFlowBridge configureSocketsWithError:&socketError]) {
|
||||
[self.packetFlowBridge startReading];
|
||||
return YES;
|
||||
} else {
|
||||
if (socketError) { [self.delegate openVPNAdapter:self handleError:socketError]; }
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
|
||||
- (CFSocketNativeHandle)socketHandle {
|
||||
return CFSocketGetNative(self.packetFlowBridge.openVPNSocket);
|
||||
}
|
||||
|
||||
- (void)clientEventName:(NSString *)eventName message:(NSString *)message {
|
||||
NSDictionary *events = @{
|
||||
@"DISCONNECTED": @(OpenVPNAdapterEventDisconnected),
|
||||
@"CONNECTED": @(OpenVPNAdapterEventConnected),
|
||||
@"RECONNECTING": @(OpenVPNAdapterEventReconnecting),
|
||||
@"RESOLVE": @(OpenVPNAdapterEventResolve),
|
||||
@"WAIT": @(OpenVPNAdapterEventWait),
|
||||
@"WAIT_PROXY": @(OpenVPNAdapterEventWaitProxy),
|
||||
@"CONNECTING": @(OpenVPNAdapterEventConnecting),
|
||||
@"GET_CONFIG": @(OpenVPNAdapterEventGetConfig),
|
||||
@"ASSIGN_IP": @(OpenVPNAdapterEventAssignIP),
|
||||
@"ADD_ROUTES": @(OpenVPNAdapterEventAddRoutes),
|
||||
@"ECHO": @(OpenVPNAdapterEventEcho),
|
||||
@"INFO": @(OpenVPNAdapterEventInfo),
|
||||
@"PAUSE": @(OpenVPNAdapterEventPause),
|
||||
@"RESUME": @(OpenVPNAdapterEventResume),
|
||||
@"RELAY": @(OpenVPNAdapterEventRelay)
|
||||
};
|
||||
|
||||
OpenVPNAdapterEvent event = events[eventName] != nil ?
|
||||
(OpenVPNAdapterEvent)[events[eventName] integerValue] : OpenVPNAdapterEventUnknown;
|
||||
|
||||
[self.delegate openVPNAdapter:self handleEvent:event message:message];
|
||||
}
|
||||
|
||||
- (void)clientErrorName:(NSString *)errorName fatal:(BOOL)fatal message:(NSString *)message {
|
||||
OpenVPNAdapterError adapterError = [NSError ovpn_adapterErrorByName:errorName];
|
||||
NSString *description = fatal ? @"OpenVPN fatal error occured" : @"OpenVPN error occured";
|
||||
|
||||
NSError *error = [NSError ovpn_errorObjectForAdapterError:adapterError
|
||||
description:description
|
||||
message:message
|
||||
fatal:YES];
|
||||
|
||||
[self.delegate openVPNAdapter:self handleError:error];
|
||||
}
|
||||
|
||||
- (void)clientLogMessage:(NSString *)logMessage {
|
||||
if ([self.delegate respondsToSelector:@selector(openVPNAdapter:handleLogMessage:)]) {
|
||||
[self.delegate openVPNAdapter:self handleLogMessage:logMessage];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)tick {
|
||||
if ([self.delegate respondsToSelector:@selector(openVPNAdapterDidReceiveClockTick:)]) {
|
||||
[self.delegate openVPNAdapterDidReceiveClockTick:self];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)resetSettings {
|
||||
_sessionName = nil;
|
||||
_packetFlowBridge = nil;
|
||||
_networkSettingsBuilder = nil;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
- (void)dealloc {
|
||||
delete _client;
|
||||
delete _vpnClient;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
39
OpenVPN Adapter/OpenVPNAdapterPacketFlow.h
Normal file
39
OpenVPN Adapter/OpenVPNAdapterPacketFlow.h
Normal file
@@ -0,0 +1,39 @@
|
||||
//
|
||||
// OpenVPNAdapterPacketFlow.h
|
||||
// OpenVPN Adapter
|
||||
//
|
||||
// Created by Sergey Abramchuk on 15.01.2018.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@protocol OpenVPNAdapterPacketFlow <NSObject>
|
||||
|
||||
/**
|
||||
Read IP packets from the TUN interface.
|
||||
|
||||
@param completionHandler A block that is executed when some packets are read from the TUN interface. The packets that were
|
||||
read are passed to this block in the packets array. The protocol numbers of the packets that were read are passed to this
|
||||
block in the protocols array. Each packet has a protocol number in the corresponding index in the protocols array. The
|
||||
protocol numbers are given in host byte order. Valid protocol numbers include PF_INET and PF_INET6. See /usr/include/sys/socket.h.
|
||||
*/
|
||||
- (void)readPacketsWithCompletionHandler:(void (^)(NSArray<NSData *> *packets, NSArray<NSNumber *> *protocols))completionHandler;
|
||||
|
||||
/**
|
||||
Write IP packets to the TUN interface
|
||||
|
||||
@param packets An array of NSData objects containing the IP packets to the written.
|
||||
@param protocols An array of NSNumber objects containing the protocol numbers (e.g. PF_INET or PF_INET6) of the IP packets
|
||||
in packets in host byte order.
|
||||
|
||||
@discussion The number of NSData objects in packets must be exactly equal to the number of NSNumber objects in protocols.
|
||||
|
||||
@return YES on success, otherwise NO.
|
||||
*/
|
||||
- (BOOL)writePackets:(NSArray<NSData *> *)packets withProtocols:(NSArray<NSNumber *> *)protocols;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -11,14 +11,14 @@
|
||||
@interface OpenVPNCertificate : NSObject
|
||||
|
||||
+ (nullable OpenVPNCertificate *)certificateWithPEM:(nonnull NSData *)pemData
|
||||
error:(out NSError * __nullable * __nullable)error;
|
||||
error:(out NSError * _Nullable * _Nullable)error;
|
||||
|
||||
+ (nullable OpenVPNCertificate *)certificateWithDER:(nonnull NSData *)derData
|
||||
error:(out NSError * __nullable * __nullable)error;
|
||||
error:(out NSError * _Nullable * _Nullable)error;
|
||||
|
||||
- (nonnull instancetype) __unavailable init;
|
||||
- (nonnull instancetype) init NS_UNAVAILABLE;
|
||||
|
||||
- (nullable NSData *)pemData:(out NSError * __nullable * __nullable)error;
|
||||
- (nullable NSData *)derData:(out NSError * __nullable * __nullable)error;
|
||||
- (nullable NSData *)pemData:(out NSError * _Nullable * _Nullable)error;
|
||||
- (nullable NSData *)derData:(out NSError * _Nullable * _Nullable)error;
|
||||
|
||||
@end
|
||||
|
||||
@@ -5,14 +5,13 @@
|
||||
// Created by Sergey Abramchuk on 06.09.17.
|
||||
//
|
||||
//
|
||||
|
||||
#import <mbedtls/x509_crt.h>
|
||||
#import <mbedtls/pem.h>
|
||||
|
||||
#import "NSError+Message.h"
|
||||
#import "OpenVPNError.h"
|
||||
#import "OpenVPNCertificate.h"
|
||||
|
||||
#include <mbedtls/x509_crt.h>
|
||||
#include <mbedtls/pem.h>
|
||||
|
||||
#import "NSError+OpenVPNError.h"
|
||||
|
||||
@interface OpenVPNCertificate ()
|
||||
|
||||
@property (nonatomic, assign) mbedtls_x509_crt *crt;
|
||||
@@ -21,16 +20,6 @@
|
||||
|
||||
@implementation OpenVPNCertificate
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
self.crt = malloc(sizeof(mbedtls_x509_crt));
|
||||
mbedtls_x509_crt_init(self.crt);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (OpenVPNCertificate *)certificateWithPEM:(NSData *)pemData error:(out NSError **)error {
|
||||
OpenVPNCertificate *certificate = [OpenVPNCertificate new];
|
||||
|
||||
@@ -39,11 +28,7 @@
|
||||
int result = mbedtls_x509_crt_parse(certificate.crt, (const unsigned char *)pemString.UTF8String, pemData.length + 1);
|
||||
if (result < 0) {
|
||||
if (error) {
|
||||
NSString *reason = [NSError reasonFromResult:result];
|
||||
*error = [NSError errorWithDomain:OpenVPNIdentityErrorDomain code:result userInfo:@{
|
||||
NSLocalizedDescriptionKey: @"Failed to read PEM data.",
|
||||
NSLocalizedFailureReasonErrorKey: reason
|
||||
}];
|
||||
*error = [NSError ovpn_errorObjectForMbedTLSError:result description:@"Failed to read PEM data"];
|
||||
}
|
||||
|
||||
return nil;
|
||||
@@ -58,11 +43,7 @@
|
||||
int result = mbedtls_x509_crt_parse_der(certificate.crt, derData.bytes, derData.length);
|
||||
if (result < 0) {
|
||||
if (error) {
|
||||
NSString *reason = [NSError reasonFromResult:result];
|
||||
*error = [NSError errorWithDomain:OpenVPNIdentityErrorDomain code:result userInfo:@{
|
||||
NSLocalizedDescriptionKey: @"Failed to read DER data.",
|
||||
NSLocalizedFailureReasonErrorKey: reason
|
||||
}];
|
||||
*error = [NSError ovpn_errorObjectForMbedTLSError:result description:@"Failed to read DER data"];
|
||||
}
|
||||
|
||||
return nil;
|
||||
@@ -71,6 +52,15 @@
|
||||
return certificate;
|
||||
}
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
if (self = [super init]) {
|
||||
_crt = malloc(sizeof(mbedtls_x509_crt));
|
||||
mbedtls_x509_crt_init(_crt);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSData *)pemData:(out NSError **)error {
|
||||
NSString *header = @"-----BEGIN CERTIFICATE-----\n";
|
||||
NSString *footer = @"-----END CERTIFICATE-----\n";
|
||||
@@ -80,14 +70,11 @@
|
||||
|
||||
size_t output_length = 0;
|
||||
|
||||
int result = mbedtls_pem_write_buffer(header.UTF8String, footer.UTF8String, self.crt->raw.p, self.crt->raw.len, pem_buffer, buffer_length, &output_length);
|
||||
int result = mbedtls_pem_write_buffer(header.UTF8String, footer.UTF8String, self.crt->raw.p,
|
||||
self.crt->raw.len, pem_buffer, buffer_length, &output_length);
|
||||
if (result < 0) {
|
||||
if (error) {
|
||||
NSString *reason = [NSError reasonFromResult:result];
|
||||
*error = [NSError errorWithDomain:OpenVPNIdentityErrorDomain code:result userInfo:@{
|
||||
NSLocalizedDescriptionKey: @"Failed to write PEM data.",
|
||||
NSLocalizedFailureReasonErrorKey: reason
|
||||
}];
|
||||
*error = [NSError ovpn_errorObjectForMbedTLSError:result description: @"Failed to write PEM data"];
|
||||
}
|
||||
|
||||
free(pem_buffer);
|
||||
@@ -103,11 +90,8 @@
|
||||
- (NSData *)derData:(out NSError **)error {
|
||||
if (self.crt->raw.p == NULL || self.crt->raw.len == 0) {
|
||||
if (error) {
|
||||
NSString *reason = [NSError reasonFromResult:MBEDTLS_ERR_X509_BAD_INPUT_DATA];
|
||||
*error = [NSError errorWithDomain:OpenVPNIdentityErrorDomain code:MBEDTLS_ERR_X509_BAD_INPUT_DATA userInfo:@{
|
||||
NSLocalizedDescriptionKey: @"Failed to write DER data.",
|
||||
NSLocalizedFailureReasonErrorKey:reason
|
||||
}];
|
||||
*error = [NSError ovpn_errorObjectForMbedTLSError:MBEDTLS_ERR_X509_BAD_INPUT_DATA
|
||||
description: @"Failed to write DER data"];
|
||||
}
|
||||
|
||||
return nil;
|
||||
@@ -117,8 +101,8 @@
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
mbedtls_x509_crt_free(self.crt);
|
||||
free(self.crt);
|
||||
mbedtls_x509_crt_free(_crt);
|
||||
free(_crt);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
101
OpenVPN Adapter/OpenVPNClient.h
Normal file
101
OpenVPN Adapter/OpenVPNClient.h
Normal file
@@ -0,0 +1,101 @@
|
||||
//
|
||||
// OpenVPNClient.h
|
||||
// OpenVPN Adapter
|
||||
//
|
||||
// Created by Sergey Abramchuk on 11.01.2018.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#include <client/ovpncli.hpp>
|
||||
|
||||
@class NEIPv4Route;
|
||||
@class NEIPv6Route;
|
||||
@class NEProxyServer;
|
||||
|
||||
typedef NS_ENUM(NSInteger, OpenVPNProxyServerProtocol) {
|
||||
OpenVPNProxyServerProtocolHTTP,
|
||||
OpenVPNProxyServerProtocolHTTPS
|
||||
};
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@protocol OpenVPNClientDelegate <NSObject>
|
||||
- (BOOL)setRemoteAddress:(NSString *)address;
|
||||
|
||||
- (BOOL)addIPV4Address:(NSString *)address subnetMask:(NSString *)subnetMask gateway:(nullable NSString *)gateway;
|
||||
- (BOOL)addIPV6Address:(NSString *)address prefixLength:(NSNumber *)prefixLength gateway:(nullable NSString *)gateway;
|
||||
|
||||
- (BOOL)addIPV4Route:(NEIPv4Route *)route;
|
||||
- (BOOL)addIPV6Route:(NEIPv6Route *)route;
|
||||
- (BOOL)excludeIPV4Route:(NEIPv4Route *)route;
|
||||
- (BOOL)excludeIPV6Route:(NEIPv6Route *)route;
|
||||
|
||||
- (BOOL)addDNS:(NSString *)dns;
|
||||
- (BOOL)addSearchDomain:(NSString *)domain;
|
||||
|
||||
- (BOOL)setMTU:(NSNumber *)mtu;
|
||||
- (BOOL)setSessionName:(NSString *)name;
|
||||
|
||||
- (BOOL)addProxyBypassHost:(NSString *)bypassHost;
|
||||
- (BOOL)setProxyAutoConfigurationURL:(NSURL *)url;
|
||||
- (BOOL)setProxyServer:(NEProxyServer *)server protocol:(OpenVPNProxyServerProtocol)protocol;
|
||||
|
||||
- (BOOL)establishTunnel;
|
||||
- (CFSocketNativeHandle)socketHandle;
|
||||
|
||||
- (void)clientEventName:(NSString *)eventName message:(nullable NSString *)message;
|
||||
- (void)clientErrorName:(NSString *)errorName fatal:(BOOL)fatal message:(nullable NSString *)message;
|
||||
- (void)clientLogMessage:(NSString *)logMessage;
|
||||
|
||||
- (void)tick;
|
||||
|
||||
- (void)resetSettings;
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
using namespace openvpn;
|
||||
|
||||
class OpenVPNClient : public ClientAPI::OpenVPNClient {
|
||||
public:
|
||||
OpenVPNClient(id<OpenVPNClientDelegate> _Nonnull delegate);
|
||||
|
||||
bool tun_builder_new() override;
|
||||
|
||||
bool tun_builder_set_remote_address(const std::string& address, bool ipv6) override;
|
||||
bool tun_builder_add_address(const std::string& address, int prefix_length, const std::string& gateway,
|
||||
bool ipv6, bool net30) override;
|
||||
bool tun_builder_reroute_gw(bool ipv4, bool ipv6, unsigned int flags) override;
|
||||
bool tun_builder_add_route(const std::string& address, int prefix_length, int metric, bool ipv6) override;
|
||||
bool tun_builder_exclude_route(const std::string& address, int prefix_length, int metric, bool ipv6) override;
|
||||
bool tun_builder_add_dns_server(const std::string& address, bool ipv6) override;
|
||||
bool tun_builder_add_search_domain(const std::string& domain) override;
|
||||
bool tun_builder_set_mtu(int mtu) override;
|
||||
bool tun_builder_set_session_name(const std::string& name) override;
|
||||
bool tun_builder_add_proxy_bypass(const std::string& bypass_host) override;
|
||||
bool tun_builder_set_proxy_auto_config_url(const std::string& urlString) override;
|
||||
bool tun_builder_set_proxy_http(const std::string& host, int port) override;
|
||||
bool tun_builder_set_proxy_https(const std::string& host, int port) override;
|
||||
bool tun_builder_set_block_ipv6(bool block_ipv6) override;
|
||||
|
||||
int tun_builder_establish() override;
|
||||
bool tun_builder_persist() override;
|
||||
void tun_builder_teardown(bool disconnect) override;
|
||||
|
||||
bool socket_protect(int socket) override;
|
||||
bool pause_on_connection_timeout() override;
|
||||
|
||||
void external_pki_cert_request(ClientAPI::ExternalPKICertRequest& certreq) override;
|
||||
void external_pki_sign_request(ClientAPI::ExternalPKISignRequest& signreq) override;
|
||||
|
||||
void event(const ClientAPI::Event& event) override;
|
||||
void log(const ClientAPI::LogInfo& log) override;
|
||||
|
||||
void clock_tick() override;
|
||||
|
||||
private:
|
||||
__weak id<OpenVPNClientDelegate> _Nonnull delegate;
|
||||
};
|
||||
|
||||
|
||||
173
OpenVPN Adapter/OpenVPNClient.mm
Normal file
173
OpenVPN Adapter/OpenVPNClient.mm
Normal file
@@ -0,0 +1,173 @@
|
||||
//
|
||||
// OpenVPNClient.m
|
||||
// OpenVPN Adapter
|
||||
//
|
||||
// Created by Sergey Abramchuk on 11.01.2018.
|
||||
//
|
||||
|
||||
#define INVALID_SOCKET -1
|
||||
|
||||
#import "OpenVPNClient.h"
|
||||
|
||||
#import <NetworkExtension/NetworkExtension.h>
|
||||
|
||||
#include <openvpn/addr/ipv4.hpp>
|
||||
|
||||
using ::IPv4::Addr;
|
||||
|
||||
OpenVPNClient::OpenVPNClient(id<OpenVPNClientDelegate> delegate): ClientAPI::OpenVPNClient() {
|
||||
this->delegate = delegate;
|
||||
}
|
||||
|
||||
bool OpenVPNClient::tun_builder_new() {
|
||||
[this->delegate resetSettings];
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OpenVPNClient::tun_builder_set_remote_address(const std::string &address, bool ipv6) {
|
||||
NSString *remoteAddress = [NSString stringWithUTF8String:address.c_str()];
|
||||
return [this->delegate setRemoteAddress:remoteAddress];
|
||||
}
|
||||
|
||||
bool OpenVPNClient::tun_builder_add_address(const std::string &address, int prefix_length, const std::string &gateway, bool ipv6, bool net30) {
|
||||
NSString *localAddress = [NSString stringWithUTF8String:address.c_str()];
|
||||
NSString *gatewayAddress = gateway.length() == 0 || gateway.compare("UNSPEC") == 0 ? nil :
|
||||
[NSString stringWithUTF8String:gateway.c_str()];
|
||||
|
||||
if (ipv6) {
|
||||
return [this->delegate addIPV6Address:localAddress prefixLength:@(prefix_length) gateway:gatewayAddress];
|
||||
} else {
|
||||
NSString *subnetMask = [NSString stringWithUTF8String:Addr::netmask_from_prefix_len(prefix_length).to_string().c_str()];
|
||||
return [this->delegate addIPV4Address:localAddress subnetMask:subnetMask gateway:gatewayAddress];
|
||||
}
|
||||
}
|
||||
|
||||
bool OpenVPNClient::tun_builder_reroute_gw(bool ipv4, bool ipv6, unsigned int flags) {
|
||||
if (ipv4 && ![this->delegate addIPV4Route:[NEIPv4Route defaultRoute]]) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ipv6 && ![this->delegate addIPV6Route:[NEIPv6Route defaultRoute]]) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OpenVPNClient::tun_builder_add_route(const std::string& address, int prefix_length, int metric, bool ipv6) {
|
||||
NSString *routeAddress = [NSString stringWithUTF8String:address.c_str()];
|
||||
|
||||
if (ipv6) {
|
||||
NEIPv6Route *route = [[NEIPv6Route alloc] initWithDestinationAddress:routeAddress networkPrefixLength:@(prefix_length)];
|
||||
return [this->delegate addIPV6Route:route];
|
||||
} else {
|
||||
NSString *subnetMask = [NSString stringWithUTF8String:Addr::netmask_from_prefix_len(prefix_length).to_string().c_str()];
|
||||
NEIPv4Route *route = [[NEIPv4Route alloc] initWithDestinationAddress:routeAddress subnetMask:subnetMask];
|
||||
return [this->delegate addIPV4Route:route];
|
||||
}
|
||||
}
|
||||
|
||||
bool OpenVPNClient::tun_builder_exclude_route(const std::string& address, int prefix_length, int metric, bool ipv6) {
|
||||
NSString *routeAddress = [NSString stringWithUTF8String:address.c_str()];
|
||||
|
||||
if (ipv6) {
|
||||
NEIPv6Route *route = [[NEIPv6Route alloc] initWithDestinationAddress:routeAddress networkPrefixLength:@(prefix_length)];
|
||||
return [this->delegate excludeIPV6Route:route];
|
||||
} else {
|
||||
NSString *subnetMask = [NSString stringWithUTF8String:Addr::netmask_from_prefix_len(prefix_length).to_string().c_str()];
|
||||
NEIPv4Route *route = [[NEIPv4Route alloc] initWithDestinationAddress:routeAddress subnetMask:subnetMask];
|
||||
return [this->delegate excludeIPV4Route:route];
|
||||
}
|
||||
}
|
||||
|
||||
bool OpenVPNClient::tun_builder_add_dns_server(const std::string& address, bool ipv6) {
|
||||
NSString *dns = [NSString stringWithUTF8String:address.c_str()];
|
||||
return [this->delegate addDNS:dns];
|
||||
}
|
||||
|
||||
bool OpenVPNClient::tun_builder_add_search_domain(const std::string& domain) {
|
||||
NSString *searchDomain = [NSString stringWithUTF8String:domain.c_str()];
|
||||
return [this->delegate addSearchDomain:searchDomain];
|
||||
}
|
||||
|
||||
bool OpenVPNClient::tun_builder_set_mtu(int mtu) {
|
||||
return [this->delegate setMTU:@(mtu)];
|
||||
}
|
||||
|
||||
bool OpenVPNClient::tun_builder_set_session_name(const std::string& name) {
|
||||
NSString *sessionName = [NSString stringWithUTF8String:name.c_str()];
|
||||
return [this->delegate setSessionName:sessionName];
|
||||
}
|
||||
|
||||
bool OpenVPNClient::tun_builder_add_proxy_bypass(const std::string& bypass_host) {
|
||||
NSString *bypassHost = [NSString stringWithUTF8String:bypass_host.c_str()];
|
||||
return [this->delegate addProxyBypassHost:bypassHost];
|
||||
}
|
||||
|
||||
bool OpenVPNClient::tun_builder_set_proxy_auto_config_url(const std::string& url) {
|
||||
NSURL *configURL = [[NSURL alloc] initWithString:[NSString stringWithUTF8String:url.c_str()]];
|
||||
if (configURL) {
|
||||
return [this->delegate setProxyAutoConfigurationURL:configURL];
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool OpenVPNClient::tun_builder_set_proxy_http(const std::string& host, int port) {
|
||||
NSString *proxyHost = [NSString stringWithUTF8String:host.c_str()];
|
||||
NEProxyServer *proxyServer = [[NEProxyServer alloc] initWithAddress:proxyHost port:port];
|
||||
return [this->delegate setProxyServer:proxyServer protocol:OpenVPNProxyServerProtocolHTTP];
|
||||
}
|
||||
|
||||
bool OpenVPNClient::tun_builder_set_proxy_https(const std::string& host, int port) {
|
||||
NSString *proxyHost = [NSString stringWithUTF8String:host.c_str()];
|
||||
NEProxyServer *proxyServer = [[NEProxyServer alloc] initWithAddress:proxyHost port:port];
|
||||
return [this->delegate setProxyServer:proxyServer protocol:OpenVPNProxyServerProtocolHTTPS];
|
||||
}
|
||||
|
||||
bool OpenVPNClient::tun_builder_set_block_ipv6(bool block_ipv6) {
|
||||
return block_ipv6;
|
||||
}
|
||||
|
||||
int OpenVPNClient::tun_builder_establish() {
|
||||
return [this->delegate establishTunnel] ? [this->delegate socketHandle] : INVALID_SOCKET;
|
||||
}
|
||||
|
||||
bool OpenVPNClient::tun_builder_persist() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void OpenVPNClient::tun_builder_teardown(bool disconnect) {
|
||||
[this->delegate resetSettings];
|
||||
}
|
||||
|
||||
bool OpenVPNClient::socket_protect(int socket) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OpenVPNClient::pause_on_connection_timeout() {
|
||||
return false;
|
||||
}
|
||||
|
||||
void OpenVPNClient::external_pki_cert_request(ClientAPI::ExternalPKICertRequest& certreq) { }
|
||||
void OpenVPNClient::external_pki_sign_request(ClientAPI::ExternalPKISignRequest& signreq) { }
|
||||
|
||||
void OpenVPNClient::event(const ClientAPI::Event& ev) {
|
||||
NSString *name = [NSString stringWithUTF8String:ev.name.c_str()];
|
||||
NSString *message = [NSString stringWithUTF8String:ev.info.c_str()];
|
||||
|
||||
if (ev.error) {
|
||||
[this->delegate clientErrorName:name fatal:ev.fatal message:message.length ? message : nil];
|
||||
} else {
|
||||
[this->delegate clientEventName:name message:message.length ? message : nil];
|
||||
}
|
||||
}
|
||||
|
||||
void OpenVPNClient::log(const ClientAPI::LogInfo& log) {
|
||||
NSString *logMessage = [NSString stringWithUTF8String:log.text.c_str()];
|
||||
[this->delegate clientLogMessage:logMessage];
|
||||
}
|
||||
|
||||
void OpenVPNClient::clock_tick() {
|
||||
[this->delegate tick];
|
||||
}
|
||||
@@ -6,29 +6,33 @@
|
||||
//
|
||||
//
|
||||
|
||||
#import <client/ovpncli.hpp>
|
||||
|
||||
#import "OpenVPNConfiguration.h"
|
||||
|
||||
#include <client/ovpncli.hpp>
|
||||
|
||||
using namespace openvpn;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface OpenVPNConfiguration (Internal)
|
||||
|
||||
@property (readonly) ClientAPI::Config config;
|
||||
|
||||
+ (OpenVPNTransportProtocol)getTransportProtocolFromValue:(nullable NSString *)value;
|
||||
+ (nonnull NSString *)getValueFromTransportProtocol:(OpenVPNTransportProtocol)protocol;
|
||||
+ (NSString *)getValueFromTransportProtocol:(OpenVPNTransportProtocol)protocol;
|
||||
|
||||
+ (OpenVPNIPv6Preference)getIPv6PreferenceFromValue:(nullable NSString *)value;
|
||||
+ (nonnull NSString *)getValueFromIPv6Preference:(OpenVPNIPv6Preference)preference;
|
||||
+ (NSString *)getValueFromIPv6Preference:(OpenVPNIPv6Preference)preference;
|
||||
|
||||
+ (OpenVPNCompressionMode)getCompressionModeFromValue:(nullable NSString *)value;
|
||||
+ (nonnull NSString *)getValueFromCompressionMode:(OpenVPNCompressionMode)compressionMode;
|
||||
+ (NSString *)getValueFromCompressionMode:(OpenVPNCompressionMode)compressionMode;
|
||||
|
||||
+ (OpenVPNMinTLSVersion)getMinTLSFromValue:(nullable NSString *)value;
|
||||
+ (nonnull NSString *)getValueFromMinTLS:(OpenVPNMinTLSVersion)minTLS;
|
||||
+ (NSString *)getValueFromMinTLS:(OpenVPNMinTLSVersion)minTLS;
|
||||
|
||||
+ (OpenVPNTLSCertProfile)getTLSCertProfileFromValue:(nullable NSString *)value;
|
||||
+ (nonnull NSString *)getValueFromTLSCertProfile:(OpenVPNTLSCertProfile)tlsCertProfile;
|
||||
+ (NSString *)getValueFromTLSCertProfile:(OpenVPNTLSCertProfile)tlsCertProfile;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@@ -8,11 +8,11 @@
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "OpenVPNTransportProtocol.h"
|
||||
#import "OpenVPNIPv6Preference.h"
|
||||
#import "OpenVPNCompressionMode.h"
|
||||
#import "OpenVPNMinTLSVersion.h"
|
||||
#import "OpenVPNTLSCertProfile.h"
|
||||
typedef NS_ENUM(NSInteger, OpenVPNTransportProtocol);
|
||||
typedef NS_ENUM(NSInteger, OpenVPNIPv6Preference);
|
||||
typedef NS_ENUM(NSInteger, OpenVPNCompressionMode);
|
||||
typedef NS_ENUM(NSInteger, OpenVPNMinTLSVersion);
|
||||
typedef NS_ENUM(NSInteger, OpenVPNTLSCertProfile);
|
||||
|
||||
/**
|
||||
Class used to pass configuration
|
||||
|
||||
@@ -6,8 +6,15 @@
|
||||
//
|
||||
//
|
||||
|
||||
#import "OpenVPNConfiguration.h"
|
||||
#import "OpenVPNConfiguration+Internal.h"
|
||||
|
||||
#import "OpenVPNTransportProtocol.h"
|
||||
#import "OpenVPNIPv6Preference.h"
|
||||
#import "OpenVPNCompressionMode.h"
|
||||
#import "OpenVPNMinTLSVersion.h"
|
||||
#import "OpenVPNTLSCertProfile.h"
|
||||
|
||||
using namespace openvpn;
|
||||
|
||||
NSString *const OpenVPNTransportProtocolUDPValue = @"udp";
|
||||
@@ -212,7 +219,7 @@ NSString *const OpenVPNTLSCertProfileDefaultValue = @"default";
|
||||
}
|
||||
|
||||
- (void)setFileContent:(NSData *)fileContent {
|
||||
_config.content = fileContent ? std::string((const char *)fileContent.bytes) : "";
|
||||
_config.content = fileContent.length ? std::string((const char *)fileContent.bytes) : "";
|
||||
}
|
||||
|
||||
- (NSDictionary<NSString *,NSString *> *)settings {
|
||||
@@ -494,7 +501,7 @@ NSString *const OpenVPNTLSCertProfileDefaultValue = @"default";
|
||||
}
|
||||
|
||||
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
|
||||
if ((self = [self init])) {
|
||||
if (self = [self init]) {
|
||||
self.fileContent = [aDecoder decodeObjectOfClass:[NSData class] forKey:NSStringFromSelector(@selector(fileContent))];
|
||||
self.settings = [aDecoder decodeObjectOfClass:[NSDictionary class] forKey:NSStringFromSelector(@selector(settings))];
|
||||
self.guiVersion = [aDecoder decodeObjectOfClass:[NSString class] forKey:NSStringFromSelector(@selector(guiVersion))];
|
||||
|
||||
@@ -6,10 +6,10 @@
|
||||
//
|
||||
//
|
||||
|
||||
#import <client/ovpncli.hpp>
|
||||
|
||||
#import "OpenVPNConnectionInfo.h"
|
||||
|
||||
#include <client/ovpncli.hpp>
|
||||
|
||||
using namespace openvpn;
|
||||
|
||||
@interface OpenVPNConnectionInfo (Internal)
|
||||
|
||||
@@ -28,7 +28,7 @@ using namespace openvpn;
|
||||
@implementation OpenVPNConnectionInfo
|
||||
|
||||
- (instancetype)initWithConnectionInfo:(ClientAPI::ConnectionInfo)info {
|
||||
if ((self = [super init])) {
|
||||
if (self = [super init]) {
|
||||
self.user = !info.user.empty() ? [NSString stringWithUTF8String:info.user.c_str()] : nil;
|
||||
self.serverHost = !info.serverHost.empty() ? [NSString stringWithUTF8String:info.serverHost.c_str()] : nil;
|
||||
self.serverPort = !info.serverPort.empty() ? [NSString stringWithUTF8String:info.serverPort.c_str()] : nil;
|
||||
@@ -75,7 +75,7 @@ using namespace openvpn;
|
||||
}
|
||||
|
||||
- (nullable instancetype)initWithCoder:(nonnull NSCoder *)aDecoder {
|
||||
if ((self = [self init])) {
|
||||
if (self = [self init]) {
|
||||
self.user = [aDecoder decodeObjectOfClass:[NSString class] forKey:NSStringFromSelector(@selector(user))];
|
||||
self.serverHost = [aDecoder decodeObjectOfClass:[NSString class] forKey:NSStringFromSelector(@selector(serverHost))];
|
||||
self.serverPort = [aDecoder decodeObjectOfClass:[NSString class] forKey:NSStringFromSelector(@selector(serverPort))];
|
||||
|
||||
@@ -5,11 +5,10 @@
|
||||
// Created by Sergey Abramchuk on 24.04.17.
|
||||
//
|
||||
//
|
||||
|
||||
#import <client/ovpncli.hpp>
|
||||
|
||||
#import "OpenVPNCredentials.h"
|
||||
|
||||
#include <client/ovpncli.hpp>
|
||||
|
||||
using namespace openvpn;
|
||||
|
||||
@interface OpenVPNCredentials (Internal)
|
||||
|
||||
@@ -52,7 +52,8 @@ using namespace openvpn;
|
||||
}
|
||||
|
||||
- (NSString *)dynamicChallengeCookie {
|
||||
return !_credentials.dynamicChallengeCookie.empty() ? [NSString stringWithUTF8String:_credentials.dynamicChallengeCookie.c_str()] : nil;
|
||||
return !_credentials.dynamicChallengeCookie.empty() ?
|
||||
[NSString stringWithUTF8String:_credentials.dynamicChallengeCookie.c_str()] : nil;
|
||||
}
|
||||
|
||||
- (void)setDynamicChallengeCookie:(NSString *)dynamicChallengeCookie {
|
||||
|
||||
@@ -8,11 +8,15 @@
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
FOUNDATION_EXPORT NSString * __nonnull const OpenVPNAdapterErrorDomain;
|
||||
FOUNDATION_EXPORT NSString * __nonnull const OpenVPNIdentityErrorDomain;
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
FOUNDATION_EXPORT NSString * __nonnull const OpenVPNAdapterErrorFatalKey;
|
||||
FOUNDATION_EXPORT NSString * __nonnull const OpenVPNAdapterErrorMessageKey;
|
||||
FOUNDATION_EXPORT NSString *const OpenVPNAdapterErrorDomain;
|
||||
FOUNDATION_EXPORT NSString *const OpenVPNIdentityErrorDomain;
|
||||
|
||||
FOUNDATION_EXPORT NSString *const OpenVPNAdapterErrorFatalKey;
|
||||
FOUNDATION_EXPORT NSString *const OpenVPNAdapterErrorMessageKey;
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
/**
|
||||
OpenVPN error codes
|
||||
@@ -32,6 +36,7 @@ typedef NS_ERROR_ENUM(OpenVPNAdapterErrorDomain, OpenVPNAdapterError) {
|
||||
OpenVPNAdapterErrorBadSrcAddr,
|
||||
OpenVPNAdapterErrorCompressError,
|
||||
OpenVPNAdapterErrorResolveError,
|
||||
OpenVPNAdapterErrorSocketSetupFailed,
|
||||
OpenVPNAdapterErrorSocketProtectError,
|
||||
OpenVPNAdapterErrorTUNReadError,
|
||||
OpenVPNAdapterErrorTUNWriteError,
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
|
||||
#import <OpenVPNError.h>
|
||||
|
||||
NSString * const OpenVPNAdapterErrorDomain = @"me.ss-abramchuk.openvpn-adapter.error-domain";
|
||||
NSString * const OpenVPNIdentityErrorDomain = @"me.ss-abramchuk.openvpn-identity.error-domain";
|
||||
NSString *const OpenVPNAdapterErrorDomain = @"me.ss-abramchuk.openvpn-adapter.error-domain";
|
||||
NSString *const OpenVPNIdentityErrorDomain = @"me.ss-abramchuk.openvpn-identity.error-domain";
|
||||
|
||||
NSString * const OpenVPNAdapterErrorFatalKey = @"me.ss-abramchuk.openvpn-adapter.error-key.fatal";
|
||||
NSString * const OpenVPNAdapterErrorMessageKey = @"me.ss-abramchuk.openvpn-adapter.error-key.message";
|
||||
NSString *const OpenVPNAdapterErrorFatalKey = @"me.ss-abramchuk.openvpn-adapter.error-key.fatal";
|
||||
NSString *const OpenVPNAdapterErrorMessageKey = @"me.ss-abramchuk.openvpn-adapter.error-key.message";
|
||||
|
||||
@@ -6,10 +6,10 @@
|
||||
//
|
||||
//
|
||||
|
||||
#import <client/ovpncli.hpp>
|
||||
|
||||
#import "OpenVPNInterfaceStats.h"
|
||||
|
||||
#include <client/ovpncli.hpp>
|
||||
|
||||
using namespace openvpn;
|
||||
|
||||
@interface OpenVPNInterfaceStats (Internal)
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
@implementation OpenVPNInterfaceStats
|
||||
|
||||
- (instancetype)initWithInterfaceStats:(ClientAPI::InterfaceStats)stats {
|
||||
if ((self = [super init])) {
|
||||
if (self = [super init]) {
|
||||
self.bytesIn = stats.bytesIn;
|
||||
self.bytesOut = stats.bytesOut;
|
||||
self.packetsIn = stats.packetsIn;
|
||||
@@ -53,7 +53,7 @@
|
||||
}
|
||||
|
||||
- (nullable instancetype)initWithCoder:(nonnull NSCoder *)aDecoder {
|
||||
if ((self = [self init])) {
|
||||
if (self = [self init]) {
|
||||
self.bytesIn = [aDecoder decodeIntegerForKey:NSStringFromSelector(@selector(bytesIn))];
|
||||
self.bytesOut = [aDecoder decodeIntegerForKey:NSStringFromSelector(@selector(bytesOut))];
|
||||
self.packetsIn = [aDecoder decodeIntegerForKey:NSStringFromSelector(@selector(packetsIn))];
|
||||
|
||||
@@ -11,8 +11,8 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@class NEIPv4Route;
|
||||
@class NEIPv6Route;
|
||||
@class NEPacketTunnelNetworkSettings;
|
||||
@class NEProxyServer;
|
||||
@class NEPacketTunnelNetworkSettings;
|
||||
|
||||
@interface OpenVPNNetworkSettingsBuilder : NSObject
|
||||
|
||||
@@ -45,7 +45,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
@property (nonatomic) BOOL httpsProxyServerEnabled;
|
||||
@property (nonatomic, copy, nullable) NEProxyServer *httpsProxyServer;
|
||||
|
||||
@property (nonatomic, readonly, nullable) NEPacketTunnelNetworkSettings *networkSettings;
|
||||
- (nullable NEPacketTunnelNetworkSettings *)networkSettings;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@@ -5,21 +5,27 @@
|
||||
// Created by Jonathan Downing on 12/10/2017.
|
||||
//
|
||||
|
||||
#import <NetworkExtension/NetworkExtension.h>
|
||||
#import "OpenVPNNetworkSettingsBuilder.h"
|
||||
|
||||
#import <NetworkExtension/NetworkExtension.h>
|
||||
|
||||
@interface OpenVPNNetworkSettingsBuilder ()
|
||||
|
||||
@property (nonatomic) NSMutableArray<NSString *> *ipv4LocalAddresses;
|
||||
@property (nonatomic) NSMutableArray<NSString *> *ipv4SubnetMasks;
|
||||
@property (nonatomic) NSMutableArray<NEIPv4Route *> *ipv4IncludedRoutes;
|
||||
@property (nonatomic) NSMutableArray<NEIPv4Route *> *ipv4ExcludedRoutes;
|
||||
|
||||
@property (nonatomic) NSMutableArray<NSString *> *ipv6LocalAddresses;
|
||||
@property (nonatomic) NSMutableArray<NSNumber *> *ipv6NetworkPrefixLengths;
|
||||
@property (nonatomic) NSMutableArray<NEIPv6Route *> *ipv6IncludedRoutes;
|
||||
@property (nonatomic) NSMutableArray<NEIPv6Route *> *ipv6ExcludedRoutes;
|
||||
|
||||
@property (nonatomic) NSMutableArray<NSString *> *dnsServers;
|
||||
@property (nonatomic) NSMutableArray<NSString *> *searchDomains;
|
||||
|
||||
@property (nonatomic) NSMutableArray<NSString *> *proxyExceptionList;
|
||||
|
||||
@end
|
||||
|
||||
@implementation OpenVPNNetworkSettingsBuilder
|
||||
@@ -27,23 +33,27 @@
|
||||
#pragma mark - NEPacketTunnelNetworkSettings Generation
|
||||
|
||||
- (NEPacketTunnelNetworkSettings *)networkSettings {
|
||||
if (!self.remoteAddress.length) {
|
||||
return nil;
|
||||
}
|
||||
if (!self.remoteAddress.length) { return nil; }
|
||||
|
||||
NEPacketTunnelNetworkSettings *networkSettings = [[NEPacketTunnelNetworkSettings alloc] initWithTunnelRemoteAddress:self.remoteAddress];
|
||||
|
||||
if (self.ipv4LocalAddresses.count && (self.ipv4LocalAddresses.count == self.ipv4SubnetMasks.count)) {
|
||||
NEIPv4Settings *ipv4Settings = [[NEIPv4Settings alloc] initWithAddresses:self.ipv4LocalAddresses subnetMasks:self.ipv4SubnetMasks];
|
||||
NEIPv4Settings *ipv4Settings = [[NEIPv4Settings alloc] initWithAddresses:self.ipv4LocalAddresses
|
||||
subnetMasks:self.ipv4SubnetMasks];
|
||||
|
||||
ipv4Settings.includedRoutes = self.ipv4IncludedRoutes;
|
||||
ipv4Settings.excludedRoutes = self.ipv4ExcludedRoutes;
|
||||
|
||||
networkSettings.IPv4Settings = ipv4Settings;
|
||||
}
|
||||
|
||||
if (self.ipv6LocalAddresses.count && (self.ipv6LocalAddresses.count == self.ipv6NetworkPrefixLengths.count)) {
|
||||
NEIPv6Settings *ipv6Settings = [[NEIPv6Settings alloc] initWithAddresses:self.ipv6LocalAddresses networkPrefixLengths:self.ipv6NetworkPrefixLengths];
|
||||
NEIPv6Settings *ipv6Settings = [[NEIPv6Settings alloc] initWithAddresses:self.ipv6LocalAddresses
|
||||
networkPrefixLengths:self.ipv6NetworkPrefixLengths];
|
||||
|
||||
ipv6Settings.includedRoutes = self.ipv6IncludedRoutes;
|
||||
ipv6Settings.excludedRoutes = self.ipv6ExcludedRoutes;
|
||||
|
||||
networkSettings.IPv6Settings = ipv6Settings;
|
||||
}
|
||||
|
||||
@@ -55,6 +65,7 @@
|
||||
|
||||
if (self.autoProxyConfigurationEnabled || self.httpProxyServerEnabled || self.httpsProxyServerEnabled) {
|
||||
NEProxySettings *proxySettings = [[NEProxySettings alloc] init];
|
||||
|
||||
proxySettings.autoProxyConfigurationEnabled = self.autoProxyConfigurationEnabled;
|
||||
proxySettings.proxyAutoConfigurationURL = self.proxyAutoConfigurationURL;
|
||||
proxySettings.exceptionList = self.proxyExceptionList;
|
||||
@@ -62,6 +73,7 @@
|
||||
proxySettings.HTTPEnabled = self.httpProxyServerEnabled;
|
||||
proxySettings.HTTPSServer = self.httpsProxyServer;
|
||||
proxySettings.HTTPSEnabled = self.httpsProxyServerEnabled;
|
||||
|
||||
networkSettings.proxySettings = proxySettings;
|
||||
}
|
||||
|
||||
@@ -73,79 +85,57 @@
|
||||
#pragma mark - Lazy Initializers
|
||||
|
||||
- (NSMutableArray<NSString *> *)ipv4LocalAddresses {
|
||||
if (!_ipv4LocalAddresses) {
|
||||
_ipv4LocalAddresses = [[NSMutableArray alloc] init];
|
||||
}
|
||||
if (!_ipv4LocalAddresses) { _ipv4LocalAddresses = [[NSMutableArray alloc] init]; }
|
||||
return _ipv4LocalAddresses;
|
||||
}
|
||||
|
||||
- (NSMutableArray<NSString *> *)ipv4SubnetMasks {
|
||||
if (!_ipv4SubnetMasks) {
|
||||
_ipv4SubnetMasks = [[NSMutableArray alloc] init];
|
||||
}
|
||||
if (!_ipv4SubnetMasks) { _ipv4SubnetMasks = [[NSMutableArray alloc] init]; }
|
||||
return _ipv4SubnetMasks;
|
||||
}
|
||||
|
||||
- (NSMutableArray<NEIPv4Route *> *)ipv4IncludedRoutes {
|
||||
if (!_ipv4IncludedRoutes) {
|
||||
_ipv4IncludedRoutes = [[NSMutableArray alloc] init];
|
||||
}
|
||||
if (!_ipv4IncludedRoutes) { _ipv4IncludedRoutes = [[NSMutableArray alloc] init]; }
|
||||
return _ipv4IncludedRoutes;
|
||||
}
|
||||
|
||||
- (NSMutableArray<NEIPv4Route *> *)ipv4ExcludedRoutes {
|
||||
if (!_ipv4ExcludedRoutes) {
|
||||
_ipv4ExcludedRoutes = [[NSMutableArray alloc] init];
|
||||
}
|
||||
if (!_ipv4ExcludedRoutes) { _ipv4ExcludedRoutes = [[NSMutableArray alloc] init]; }
|
||||
return _ipv4ExcludedRoutes;
|
||||
}
|
||||
|
||||
- (NSMutableArray<NSString *> *)ipv6LocalAddresses {
|
||||
if (!_ipv6LocalAddresses) {
|
||||
_ipv6LocalAddresses = [[NSMutableArray alloc] init];
|
||||
}
|
||||
if (!_ipv6LocalAddresses) { _ipv6LocalAddresses = [[NSMutableArray alloc] init]; }
|
||||
return _ipv6LocalAddresses;
|
||||
}
|
||||
|
||||
- (NSMutableArray<NSNumber *> *)ipv6NetworkPrefixLengths {
|
||||
if (!_ipv6NetworkPrefixLengths) {
|
||||
_ipv6NetworkPrefixLengths = [[NSMutableArray alloc] init];
|
||||
}
|
||||
if (!_ipv6NetworkPrefixLengths) { _ipv6NetworkPrefixLengths = [[NSMutableArray alloc] init]; }
|
||||
return _ipv6NetworkPrefixLengths;
|
||||
}
|
||||
|
||||
- (NSMutableArray<NEIPv6Route *> *)ipv6IncludedRoutes {
|
||||
if (!_ipv6IncludedRoutes) {
|
||||
_ipv6IncludedRoutes = [[NSMutableArray alloc] init];
|
||||
}
|
||||
if (!_ipv6IncludedRoutes) { _ipv6IncludedRoutes = [[NSMutableArray alloc] init]; }
|
||||
return _ipv6IncludedRoutes;
|
||||
}
|
||||
|
||||
- (NSMutableArray<NEIPv6Route *> *)ipv6ExcludedRoutes {
|
||||
if (!_ipv6ExcludedRoutes) {
|
||||
_ipv6ExcludedRoutes = [[NSMutableArray alloc] init];
|
||||
}
|
||||
if (!_ipv6ExcludedRoutes) { _ipv6ExcludedRoutes = [[NSMutableArray alloc] init]; }
|
||||
return _ipv6ExcludedRoutes;
|
||||
}
|
||||
|
||||
- (NSMutableArray<NSString *> *)dnsServers {
|
||||
if (!_dnsServers) {
|
||||
_dnsServers = [[NSMutableArray alloc] init];
|
||||
}
|
||||
if (!_dnsServers) { _dnsServers = [[NSMutableArray alloc] init]; }
|
||||
return _dnsServers;
|
||||
}
|
||||
|
||||
- (NSMutableArray<NSString *> *)searchDomains {
|
||||
if (!_searchDomains) {
|
||||
_searchDomains = [[NSMutableArray alloc] init];
|
||||
}
|
||||
if (!_searchDomains) { _searchDomains = [[NSMutableArray alloc] init]; }
|
||||
return _searchDomains;
|
||||
}
|
||||
|
||||
- (NSMutableArray<NSString *> *)proxyExceptionList {
|
||||
if (!_proxyExceptionList) {
|
||||
_proxyExceptionList = [[NSMutableArray alloc] init];
|
||||
}
|
||||
if (!_proxyExceptionList) { _proxyExceptionList = [[NSMutableArray alloc] init]; }
|
||||
return _proxyExceptionList;
|
||||
}
|
||||
|
||||
|
||||
35
OpenVPN Adapter/OpenVPNPacket.h
Normal file
35
OpenVPN Adapter/OpenVPNPacket.h
Normal file
@@ -0,0 +1,35 @@
|
||||
//
|
||||
// OpenVPNPacket.h
|
||||
// OpenVPN Adapter
|
||||
//
|
||||
// Created by Sergey Abramchuk on 15.01.2018.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface OpenVPNPacket : NSObject
|
||||
|
||||
/**
|
||||
Data that can be written to the VPN socket.
|
||||
*/
|
||||
@property (readonly, nonatomic) NSData *vpnData;
|
||||
|
||||
/**
|
||||
Data that can be written to the packet flow.
|
||||
*/
|
||||
@property (readonly, nonatomic) NSData *packetFlowData;
|
||||
|
||||
/**
|
||||
Protocol number (e.g. PF_INET or PF_INET6) of the packet.
|
||||
*/
|
||||
@property (readonly, nonatomic) NSNumber *protocolFamily;
|
||||
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
- (instancetype)initWithVPNData:(NSData *)data NS_DESIGNATED_INITIALIZER;
|
||||
- (instancetype)initWithPacketFlowData:(NSData *)data protocolFamily:(NSNumber *)protocolFamily NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
95
OpenVPN Adapter/OpenVPNPacket.mm
Normal file
95
OpenVPN Adapter/OpenVPNPacket.mm
Normal file
@@ -0,0 +1,95 @@
|
||||
//
|
||||
// OpenVPNPacket.m
|
||||
// OpenVPN Adapter
|
||||
//
|
||||
// Created by Sergey Abramchuk on 15.01.2018.
|
||||
//
|
||||
|
||||
#import "OpenVPNPacket.h"
|
||||
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <openvpn/ip/ip.hpp>
|
||||
|
||||
@interface OpenVPNPacket () {
|
||||
NSData *_data;
|
||||
NSNumber *_protocolFamily;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation OpenVPNPacket
|
||||
|
||||
- (instancetype)initWithVPNData:(NSData *)data {
|
||||
if (self = [super init]) {
|
||||
#if TARGET_OS_IPHONE
|
||||
// Get network protocol family from data prefix
|
||||
NSUInteger prefix_size = sizeof(uint32_t);
|
||||
|
||||
uint32_t protocol = PF_UNSPEC;
|
||||
[data getBytes:&protocol length:prefix_size];
|
||||
protocol = CFSwapInt32BigToHost(protocol);
|
||||
|
||||
NSRange range = NSMakeRange(prefix_size, data.length - prefix_size);
|
||||
NSData *packetData = [data subdataWithRange:range];
|
||||
#else
|
||||
// Get network protocol family from packet header
|
||||
uint8_t header = 0;
|
||||
[data getBytes:&header length:1];
|
||||
|
||||
uint32_t protocol = PF_UNSPEC;
|
||||
|
||||
uint32_t version = openvpn::IPHeader::version(header);
|
||||
switch (version) {
|
||||
case 4:
|
||||
protocol = PF_INET;
|
||||
break;
|
||||
case 6:
|
||||
protocol = PF_INET6;
|
||||
break;
|
||||
}
|
||||
|
||||
NSData *packetData = data;
|
||||
#endif
|
||||
|
||||
_data = packetData;
|
||||
_protocolFamily = @(protocol);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initWithPacketFlowData:(NSData *)data protocolFamily:(NSNumber *)protocolFamily {
|
||||
if (self = [super init]) {
|
||||
_data = data;
|
||||
_protocolFamily = protocolFamily;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSData *)vpnData {
|
||||
#if TARGET_OS_IPHONE
|
||||
// Prepend data with network protocol. It should be done because OpenVPN on iOS uses uint32_t prefixes containing network
|
||||
// protocol.
|
||||
uint32_t prefix = CFSwapInt32HostToBig(_protocolFamily.unsignedIntegerValue);
|
||||
NSUInteger prefix_size = sizeof(uint32_t);
|
||||
|
||||
NSMutableData *data = [NSMutableData dataWithCapacity:prefix_size + _data.length];
|
||||
|
||||
[data appendBytes:&prefix length:prefix_size];
|
||||
[data appendData:_data];
|
||||
|
||||
return data;
|
||||
#else
|
||||
return _data;
|
||||
#endif
|
||||
}
|
||||
|
||||
- (NSData *)packetFlowData {
|
||||
return _data;
|
||||
}
|
||||
|
||||
- (NSNumber *)protocolFamily {
|
||||
return _protocolFamily;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -3,21 +3,25 @@
|
||||
// OpenVPN Adapter
|
||||
//
|
||||
// Created by Jonathan Downing on 12/10/2017.
|
||||
// Modified by Sergey Abramchuk on 15/01/2018.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@class NEPacketTunnelFlow;
|
||||
@protocol OpenVPNAdapterPacketFlow;
|
||||
|
||||
@interface OpenVPNPacketFlowBridge : NSObject
|
||||
@interface OpenVPNPacketFlowBridge: NSObject
|
||||
|
||||
@property (nonatomic, readonly) CFSocketNativeHandle socketHandle;
|
||||
@property (nonatomic, readonly) CFSocketRef openVPNSocket;
|
||||
@property (nonatomic, readonly) CFSocketRef packetFlowSocket;
|
||||
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
- (instancetype)initWithPacketFlow:(id<OpenVPNAdapterPacketFlow>)packetFlow NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
- (nullable instancetype)initWithPacketFlow:(NEPacketTunnelFlow *)packetFlow NS_DESIGNATED_INITIALIZER;
|
||||
- (BOOL)configureSocketsWithError:(NSError **)error;
|
||||
- (void)startReading;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@@ -3,65 +3,85 @@
|
||||
// OpenVPN Adapter
|
||||
//
|
||||
// Created by Jonathan Downing on 12/10/2017.
|
||||
// Modified by Sergey Abramchuk on 15/01/2018.
|
||||
//
|
||||
|
||||
#import <NetworkExtension/NetworkExtension.h>
|
||||
#import <openvpn/ip/ip.hpp>
|
||||
#import "OpenVPNPacketFlowBridge.h"
|
||||
|
||||
@interface OpenVPNPacketFlowBridge () {
|
||||
CFSocketRef _openVPNClientSocket;
|
||||
CFSocketRef _packetFlowSocket;
|
||||
}
|
||||
#include <sys/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
@property (nonatomic) NEPacketTunnelFlow *packetFlow;
|
||||
#import "OpenVPNError.h"
|
||||
#import "OpenVPNPacket.h"
|
||||
#import "OpenVPNAdapterPacketFlow.h"
|
||||
|
||||
@interface OpenVPNPacketFlowBridge ()
|
||||
|
||||
@property (nonatomic) id<OpenVPNAdapterPacketFlow> packetFlow;
|
||||
|
||||
@end
|
||||
|
||||
@implementation OpenVPNPacketFlowBridge
|
||||
|
||||
- (CFSocketNativeHandle)socketHandle {
|
||||
return CFSocketGetNative(_openVPNClientSocket);
|
||||
}
|
||||
|
||||
- (instancetype)initWithPacketFlow:(NEPacketTunnelFlow *)packetFlow {
|
||||
if ((self = [super init])) {
|
||||
self.packetFlow = packetFlow;
|
||||
|
||||
if (![self configureSockets]) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
[self readPacketFlowPackets];
|
||||
- (instancetype)initWithPacketFlow:(id<OpenVPNAdapterPacketFlow>)packetFlow {
|
||||
if (self = [super init]) {
|
||||
_packetFlow = packetFlow;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
static inline void PacketFlowSocketCallback(CFSocketRef socket, CFSocketCallBackType type, CFDataRef address, const void *data, void *adapter) {
|
||||
[(__bridge OpenVPNPacketFlowBridge *)adapter writeDataToPacketFlow:(__bridge NSData *)data];
|
||||
#pragma mark - Sockets Configuration
|
||||
|
||||
static void SocketCallback(CFSocketRef socket, CFSocketCallBackType type, CFDataRef address, const void *data, void *obj) {
|
||||
if (type != kCFSocketDataCallBack) { return; }
|
||||
|
||||
OpenVPNPacket *packet = [[OpenVPNPacket alloc] initWithVPNData:(__bridge NSData *)data];
|
||||
|
||||
OpenVPNPacketFlowBridge *bridge = (__bridge OpenVPNPacketFlowBridge *)obj;
|
||||
[bridge writePackets:@[packet] toPacketFlow:bridge.packetFlow];
|
||||
}
|
||||
|
||||
- (BOOL)configureSockets {
|
||||
- (BOOL)configureSocketsWithError:(NSError **)error {
|
||||
int sockets[2];
|
||||
if (socketpair(PF_LOCAL, SOCK_DGRAM, IPPROTO_IP, sockets) == -1) {
|
||||
NSLog(@"Failed to create a pair of connected sockets: %@", [NSString stringWithUTF8String:strerror(errno)]);
|
||||
if (error) {
|
||||
NSDictionary *userInfo = @{
|
||||
NSLocalizedDescriptionKey: @"Failed to create a pair of connected sockets",
|
||||
NSLocalizedFailureReasonErrorKey: [NSString stringWithUTF8String:strerror(errno)],
|
||||
OpenVPNAdapterErrorFatalKey: @(YES)
|
||||
};
|
||||
|
||||
*error = [NSError errorWithDomain:OpenVPNAdapterErrorDomain
|
||||
code:OpenVPNAdapterErrorSocketSetupFailed
|
||||
userInfo:userInfo];
|
||||
}
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
CFSocketContext socketCtxt = {0, (__bridge void *)self, NULL, NULL, NULL};
|
||||
|
||||
_packetFlowSocket = CFSocketCreateWithNative(kCFAllocatorDefault, sockets[0], kCFSocketDataCallBack, PacketFlowSocketCallback, &socketCtxt);
|
||||
_openVPNClientSocket = CFSocketCreateWithNative(kCFAllocatorDefault, sockets[1], kCFSocketNoCallBack, NULL, NULL);
|
||||
_packetFlowSocket = CFSocketCreateWithNative(kCFAllocatorDefault, sockets[0], kCFSocketDataCallBack,
|
||||
SocketCallback, &socketCtxt);
|
||||
_openVPNSocket = CFSocketCreateWithNative(kCFAllocatorDefault, sockets[1], kCFSocketNoCallBack, NULL, NULL);
|
||||
|
||||
if (!(_packetFlowSocket && _openVPNClientSocket)) {
|
||||
NSLog(@"Failed to create core foundation sockets from native sockets");
|
||||
if (!(_packetFlowSocket && _openVPNSocket)) {
|
||||
if (error) {
|
||||
NSDictionary *userInfo = @{
|
||||
NSLocalizedDescriptionKey: @"Failed to create core foundation sockets from native sockets",
|
||||
OpenVPNAdapterErrorFatalKey: @(YES)
|
||||
};
|
||||
|
||||
*error = [NSError errorWithDomain:OpenVPNAdapterErrorDomain
|
||||
code:OpenVPNAdapterErrorSocketSetupFailed
|
||||
userInfo:userInfo];
|
||||
}
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
if (!([self configureOptionsForSocket:_packetFlowSocket] && [self configureOptionsForSocket:_openVPNClientSocket])) {
|
||||
NSLog(@"Failed to configure buffer size of the sockets");
|
||||
return NO;
|
||||
}
|
||||
if (!([self configureOptionsForSocket:_packetFlowSocket error:error] &&
|
||||
[self configureOptionsForSocket:_openVPNSocket error:error])) { return NO; }
|
||||
|
||||
CFRunLoopSourceRef packetFlowSocketSource = CFSocketCreateRunLoopSource(kCFAllocatorDefault, _packetFlowSocket, 0);
|
||||
CFRunLoopAddSource(CFRunLoopGetMain(), packetFlowSocketSource, kCFRunLoopDefaultMode);
|
||||
@@ -70,104 +90,88 @@ static inline void PacketFlowSocketCallback(CFSocketRef socket, CFSocketCallBack
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)configureOptionsForSocket:(CFSocketRef)socket {
|
||||
- (BOOL)configureOptionsForSocket:(CFSocketRef)socket error:(NSError **)error {
|
||||
CFSocketNativeHandle socketHandle = CFSocketGetNative(socket);
|
||||
|
||||
int buf_value = 65536;
|
||||
socklen_t buf_len = sizeof(buf_value);
|
||||
|
||||
if (setsockopt(socketHandle, SOL_SOCKET, SO_RCVBUF, &buf_value, buf_len) == -1) {
|
||||
NSLog(@"Failed to setup buffer size for input: %@", [NSString stringWithUTF8String:strerror(errno)]);
|
||||
if (error) {
|
||||
NSDictionary *userInfo = @{
|
||||
NSLocalizedDescriptionKey: @"Failed to setup buffer size for input",
|
||||
NSLocalizedFailureReasonErrorKey: [NSString stringWithUTF8String:strerror(errno)],
|
||||
OpenVPNAdapterErrorFatalKey: @(YES)
|
||||
};
|
||||
|
||||
*error = [NSError errorWithDomain:OpenVPNAdapterErrorDomain
|
||||
code:OpenVPNAdapterErrorSocketSetupFailed
|
||||
userInfo:userInfo];
|
||||
}
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
if (setsockopt(socketHandle, SOL_SOCKET, SO_SNDBUF, &buf_value, buf_len) == -1) {
|
||||
NSLog(@"Failed to setup buffer size for output: %@", [NSString stringWithUTF8String:strerror(errno)]);
|
||||
if (error) {
|
||||
NSDictionary *userInfo = @{
|
||||
NSLocalizedDescriptionKey: @"Failed to setup buffer size for output",
|
||||
NSLocalizedFailureReasonErrorKey: [NSString stringWithUTF8String:strerror(errno)],
|
||||
OpenVPNAdapterErrorFatalKey: @(YES)
|
||||
};
|
||||
|
||||
*error = [NSError errorWithDomain:OpenVPNAdapterErrorDomain
|
||||
code:OpenVPNAdapterErrorSocketSetupFailed
|
||||
userInfo:userInfo];
|
||||
}
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)readPacketFlowPackets {
|
||||
- (void)startReading {
|
||||
__weak typeof(self) weakSelf = self;
|
||||
[self.packetFlow readPacketObjectsWithCompletionHandler:^(NSArray<NEPacket *> * _Nonnull packets) {
|
||||
|
||||
[self.packetFlow readPacketsWithCompletionHandler:^(NSArray<NSData *> *packets, NSArray<NSNumber *> *protocols) {
|
||||
__strong typeof(self) self = weakSelf;
|
||||
|
||||
[self writeVPNPacketObjects:packets];
|
||||
[self readPacketFlowPackets];
|
||||
|
||||
[self writePackets:packets protocols:protocols toSocket:self.packetFlowSocket];
|
||||
[self startReading];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)writeVPNPacketObjects:(NSArray<NEPacket *> *)packets {
|
||||
for (NEPacket *packet in packets) {
|
||||
CFSocketSendData(_packetFlowSocket, NULL, (CFDataRef)[self dataFromPacket:packet], 0.05);
|
||||
}
|
||||
#pragma mark - TUN -> VPN
|
||||
|
||||
- (void)writePackets:(NSArray<NSData *> *)packets protocols:(NSArray<NSNumber *> *)protocols toSocket:(CFSocketRef)socket {
|
||||
[packets enumerateObjectsUsingBlock:^(NSData *data, NSUInteger idx, BOOL *stop) {
|
||||
NSNumber *protocolFamily = protocols[idx];
|
||||
OpenVPNPacket *packet = [[OpenVPNPacket alloc] initWithPacketFlowData:data protocolFamily:protocolFamily];
|
||||
|
||||
CFSocketSendData(socket, NULL, (CFDataRef)packet.vpnData, 0.05);
|
||||
}];
|
||||
}
|
||||
|
||||
- (NSData *)dataFromPacket:(NEPacket *)packet {
|
||||
#if TARGET_OS_IPHONE
|
||||
// Prepend data with network protocol. It should be done because OpenVPN on iOS uses uint32_t prefixes containing network protocol.
|
||||
uint32_t prefix = CFSwapInt32HostToBig((uint32_t)packet.protocolFamily);
|
||||
NSMutableData *data = [[NSMutableData alloc] initWithCapacity:sizeof(prefix) + packet.data.length];
|
||||
[data appendBytes:&prefix length:sizeof(prefix)];
|
||||
[data appendData:packet.data];
|
||||
return data;
|
||||
#else
|
||||
return packet.data;
|
||||
#endif
|
||||
#pragma mark - VPN -> TUN
|
||||
|
||||
- (void)writePackets:(NSArray<OpenVPNPacket *> *)packets toPacketFlow:(id<OpenVPNAdapterPacketFlow>)packetFlow {
|
||||
NSMutableArray<NSData *> *flowPackets = [[NSMutableArray alloc] init];
|
||||
NSMutableArray<NSNumber *> *protocols = [[NSMutableArray alloc] init];
|
||||
|
||||
[packets enumerateObjectsUsingBlock:^(OpenVPNPacket * _Nonnull packet, NSUInteger idx, BOOL * _Nonnull stop) {
|
||||
[flowPackets addObject:packet.packetFlowData];
|
||||
[protocols addObject:packet.protocolFamily];
|
||||
}];
|
||||
|
||||
[packetFlow writePackets:flowPackets withProtocols:protocols];
|
||||
}
|
||||
|
||||
- (NEPacket *)packetFromData:(NSData *)data {
|
||||
#if TARGET_OS_IPHONE
|
||||
// Get network protocol from prefix
|
||||
NSUInteger prefixSize = sizeof(uint32_t);
|
||||
|
||||
if (data.length < prefixSize) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
uint32_t protocol = PF_UNSPEC;
|
||||
[data getBytes:&protocol length:prefixSize];
|
||||
protocol = CFSwapInt32BigToHost(protocol);
|
||||
|
||||
NSRange range = NSMakeRange(prefixSize, data.length - prefixSize);
|
||||
NSData *packetData = [data subdataWithRange:range];
|
||||
#else
|
||||
// Get network protocol from header
|
||||
uint8_t header = 0;
|
||||
[data getBytes:&header length:1];
|
||||
|
||||
uint32_t version = openvpn::IPHeader::version(header);
|
||||
sa_family_t protocol = [self protocolFamilyForVersion:version];
|
||||
|
||||
NSData *packetData = data;
|
||||
#endif
|
||||
|
||||
return [[NEPacket alloc] initWithData:packetData protocolFamily:protocol];
|
||||
}
|
||||
|
||||
- (void)writeDataToPacketFlow:(NSData *)data {
|
||||
NEPacket *packet = [self packetFromData:data];
|
||||
|
||||
if (!packet) {
|
||||
return;
|
||||
}
|
||||
|
||||
[self.packetFlow writePacketObjects:@[packet]];
|
||||
}
|
||||
|
||||
- (sa_family_t)protocolFamilyForVersion:(uint32_t)version {
|
||||
switch (version) {
|
||||
case 4: return PF_INET;
|
||||
case 6: return PF_INET6;
|
||||
default: return PF_UNSPEC;
|
||||
}
|
||||
}
|
||||
#pragma mark -
|
||||
|
||||
- (void)dealloc {
|
||||
CFSocketInvalidate(_openVPNClientSocket);
|
||||
CFRelease(_openVPNClientSocket);
|
||||
CFSocketInvalidate(_openVPNSocket);
|
||||
CFRelease(_openVPNSocket);
|
||||
|
||||
CFSocketInvalidate(_packetFlowSocket);
|
||||
CFRelease(_packetFlowSocket);
|
||||
|
||||
@@ -8,24 +8,24 @@
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "OpenVPNKeyType.h"
|
||||
typedef NS_ENUM(NSInteger, OpenVPNKeyType);
|
||||
|
||||
@interface OpenVPNPrivateKey : NSObject
|
||||
|
||||
+ (nullable OpenVPNPrivateKey *)keyWithPEM:(nonnull NSData *)pemData
|
||||
password:(nullable NSString *)password
|
||||
error:(out NSError * __nullable * __nullable)error;
|
||||
error:(out NSError * _Nullable * _Nullable)error;
|
||||
|
||||
+ (nullable OpenVPNPrivateKey *)keyWithDER:(nonnull NSData *)derData
|
||||
password:(nullable NSString *)password
|
||||
error:(out NSError * __nullable * __nullable)error;
|
||||
error:(out NSError * _Nullable * _Nullable)error;
|
||||
|
||||
- (nonnull instancetype) __unavailable init;
|
||||
- (nonnull instancetype) init NS_UNAVAILABLE;
|
||||
|
||||
@property (nonatomic, readonly) NSInteger size;
|
||||
@property (nonatomic, readonly) OpenVPNKeyType type;
|
||||
|
||||
- (nullable NSData *)pemData:(out NSError * __nullable * __nullable)error;
|
||||
- (nullable NSData *)derData:(out NSError * __nullable * __nullable)error;
|
||||
- (nullable NSData *)pemData:(out NSError * _Nullable * _Nullable)error;
|
||||
- (nullable NSData *)derData:(out NSError * _Nullable * _Nullable)error;
|
||||
|
||||
@end
|
||||
|
||||
@@ -6,12 +6,13 @@
|
||||
//
|
||||
//
|
||||
|
||||
#import <mbedtls/pk.h>
|
||||
|
||||
#import "NSError+Message.h"
|
||||
#import "OpenVPNError.h"
|
||||
#import "OpenVPNPrivateKey.h"
|
||||
|
||||
#include <mbedtls/pk.h>
|
||||
|
||||
#import "OpenVPNKeyType.h"
|
||||
#import "NSError+OpenVPNError.h"
|
||||
|
||||
@interface OpenVPNPrivateKey ()
|
||||
|
||||
@property (nonatomic, assign) mbedtls_pk_context *ctx;
|
||||
@@ -20,23 +21,6 @@
|
||||
|
||||
@implementation OpenVPNPrivateKey
|
||||
|
||||
- (instancetype)init {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
self.ctx = malloc(sizeof(mbedtls_pk_context));
|
||||
mbedtls_pk_init(self.ctx);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSInteger)size {
|
||||
return mbedtls_pk_get_bitlen(self.ctx);
|
||||
}
|
||||
|
||||
- (OpenVPNKeyType)type {
|
||||
return (OpenVPNKeyType)mbedtls_pk_get_type(self.ctx);
|
||||
}
|
||||
|
||||
+ (nullable OpenVPNPrivateKey *)keyWithPEM:(NSData *)pemData password:(NSString *)password error:(out NSError **)error {
|
||||
OpenVPNPrivateKey *key = [OpenVPNPrivateKey new];
|
||||
|
||||
@@ -45,14 +29,12 @@
|
||||
size_t pem_length = strlen(pemString.UTF8String) + 1;
|
||||
size_t password_length = password != nil ? strlen(password.UTF8String) : 0;
|
||||
|
||||
int result = mbedtls_pk_parse_key(key.ctx, (const unsigned char *)pemString.UTF8String, pem_length, (const unsigned char *)password.UTF8String, password_length);
|
||||
int result = mbedtls_pk_parse_key(key.ctx, (const unsigned char *)pemString.UTF8String,
|
||||
pem_length, (const unsigned char *)password.UTF8String, password_length);
|
||||
|
||||
if (result < 0) {
|
||||
if (error) {
|
||||
NSString *reason = [NSError reasonFromResult:result];
|
||||
*error = [NSError errorWithDomain:OpenVPNIdentityErrorDomain code:result userInfo:@{
|
||||
NSLocalizedDescriptionKey: @"Failed to read PEM data.",
|
||||
NSLocalizedFailureReasonErrorKey: reason
|
||||
}];
|
||||
*error = [NSError ovpn_errorObjectForMbedTLSError:result description:@"Failed to read PEM data"];
|
||||
}
|
||||
|
||||
return nil;
|
||||
@@ -66,14 +48,12 @@
|
||||
|
||||
size_t password_length = password != nil ? strlen(password.UTF8String) : 0;
|
||||
|
||||
int result = mbedtls_pk_parse_key(key.ctx, derData.bytes, derData.length, (const unsigned char *)password.UTF8String, password_length);
|
||||
int result = mbedtls_pk_parse_key(key.ctx, derData.bytes,
|
||||
derData.length, (const unsigned char *)password.UTF8String, password_length);
|
||||
|
||||
if (result < 0) {
|
||||
if (error) {
|
||||
NSString *reason = [NSError reasonFromResult:result];
|
||||
*error = [NSError errorWithDomain:OpenVPNIdentityErrorDomain code:result userInfo:@{
|
||||
NSLocalizedDescriptionKey: @"Failed to read DER data.",
|
||||
NSLocalizedFailureReasonErrorKey: reason
|
||||
}];
|
||||
*error = [NSError ovpn_errorObjectForMbedTLSError:result description:@"Failed to read DER data"];
|
||||
}
|
||||
|
||||
return nil;
|
||||
@@ -82,6 +62,22 @@
|
||||
return key;
|
||||
}
|
||||
|
||||
- (instancetype)init {
|
||||
if (self = [super init]) {
|
||||
_ctx = malloc(sizeof(mbedtls_pk_context));
|
||||
mbedtls_pk_init(_ctx);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSInteger)size {
|
||||
return mbedtls_pk_get_bitlen(self.ctx);
|
||||
}
|
||||
|
||||
- (OpenVPNKeyType)type {
|
||||
return (OpenVPNKeyType)mbedtls_pk_get_type(self.ctx);
|
||||
}
|
||||
|
||||
- (NSData *)pemData:(out NSError **)error {
|
||||
size_t buffer_length = mbedtls_pk_get_len(self.ctx) * 10;
|
||||
unsigned char *pem_buffer = malloc(buffer_length);
|
||||
@@ -89,18 +85,15 @@
|
||||
int result = mbedtls_pk_write_key_pem(self.ctx, pem_buffer, buffer_length);
|
||||
if (result < 0) {
|
||||
if (error) {
|
||||
NSString *reason = [NSError reasonFromResult:result];
|
||||
*error = [NSError errorWithDomain:OpenVPNIdentityErrorDomain code:result userInfo:@{
|
||||
NSLocalizedDescriptionKey: @"Failed to write PEM data.",
|
||||
NSLocalizedFailureReasonErrorKey: reason
|
||||
}];
|
||||
*error = [NSError ovpn_errorObjectForMbedTLSError:result description:@"Failed to write PEM data"];
|
||||
}
|
||||
|
||||
free(pem_buffer);
|
||||
return nil;
|
||||
}
|
||||
|
||||
NSData *pemData = [[NSString stringWithCString:(const char *)pem_buffer encoding:NSUTF8StringEncoding] dataUsingEncoding:NSUTF8StringEncoding];
|
||||
NSData *pemData = [[NSString stringWithCString:(const char *)pem_buffer
|
||||
encoding:NSUTF8StringEncoding] dataUsingEncoding:NSUTF8StringEncoding];
|
||||
|
||||
free(pem_buffer);
|
||||
return pemData;
|
||||
@@ -113,11 +106,7 @@
|
||||
int result = mbedtls_pk_write_key_der(self.ctx, der_buffer, buffer_length);
|
||||
if (result < 0) {
|
||||
if (error) {
|
||||
NSString *reason = [NSError reasonFromResult:result];
|
||||
*error = [NSError errorWithDomain:OpenVPNIdentityErrorDomain code:result userInfo:@{
|
||||
NSLocalizedDescriptionKey: @"Failed to write DER data.",
|
||||
NSLocalizedFailureReasonErrorKey: reason
|
||||
}];
|
||||
*error = [NSError ovpn_errorObjectForMbedTLSError:result description:@"Failed to write DER data"];
|
||||
}
|
||||
|
||||
free(der_buffer);
|
||||
@@ -134,8 +123,8 @@
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
mbedtls_pk_free(self.ctx);
|
||||
free(self.ctx);
|
||||
mbedtls_pk_free(_ctx);
|
||||
free(_ctx);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -6,10 +6,10 @@
|
||||
//
|
||||
//
|
||||
|
||||
#import <client/ovpncli.hpp>
|
||||
|
||||
#import "OpenVPNProperties.h"
|
||||
|
||||
#include <client/ovpncli.hpp>
|
||||
|
||||
using namespace openvpn;
|
||||
|
||||
@interface OpenVPNProperties (Internal)
|
||||
|
||||
@@ -8,8 +8,7 @@
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "OpenVPNTransportProtocol.h"
|
||||
|
||||
typedef NS_ENUM(NSInteger, OpenVPNTransportProtocol);
|
||||
@class OpenVPNServerEntry;
|
||||
|
||||
@interface OpenVPNProperties : NSObject
|
||||
@@ -47,7 +46,7 @@
|
||||
/**
|
||||
YES if this profile requires a private key password
|
||||
*/
|
||||
@property (readonly, nonatomic) BOOL privateKeyPasswordRequired;
|
||||
@property (readonly, nonatomic, getter=isPrivateKeyPasswordRequired) BOOL privateKeyPasswordRequired;
|
||||
|
||||
/**
|
||||
YES if user is allowed to save authentication password in UI
|
||||
@@ -74,6 +73,6 @@
|
||||
*/
|
||||
@property (nullable, readonly, nonatomic) NSArray<OpenVPNServerEntry *> *servers;
|
||||
|
||||
- (nonnull instancetype) __unavailable init;
|
||||
- (nonnull instancetype) init NS_UNAVAILABLE;
|
||||
|
||||
@end
|
||||
|
||||
@@ -6,20 +6,20 @@
|
||||
//
|
||||
//
|
||||
|
||||
#import <openvpn/common/number.hpp>
|
||||
#import "OpenVPNProperties.h"
|
||||
#import "OpenVPNProperties+Internal.h"
|
||||
|
||||
#include <openvpn/common/number.hpp>
|
||||
|
||||
#import "OpenVPNConfiguration+Internal.h"
|
||||
#import "OpenVPNServerEntry+Internal.h"
|
||||
#import "OpenVPNProperties.h"
|
||||
#import "OpenVPNProperties+Internal.h"
|
||||
|
||||
using namespace openvpn;
|
||||
|
||||
@implementation OpenVPNProperties
|
||||
|
||||
- (instancetype)initWithEvalConfig:(ClientAPI::EvalConfig)eval {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
if (self = [super init]) {
|
||||
_username = !eval.userlockedUsername.empty() ? [NSString stringWithUTF8String:eval.userlockedUsername.c_str()] : nil;
|
||||
|
||||
_profileName = !eval.profileName.empty() ? [NSString stringWithUTF8String:eval.profileName.c_str()] : nil;
|
||||
@@ -44,6 +44,7 @@ using namespace openvpn;
|
||||
_remoteProto = [OpenVPNConfiguration getTransportProtocolFromValue:currentProto];
|
||||
|
||||
_servers = nil;
|
||||
|
||||
if (!eval.serverList.empty()) {
|
||||
NSMutableArray *servers = [NSMutableArray new];
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
//
|
||||
//
|
||||
|
||||
#import "OpenVPNReachabilityTracker.h"
|
||||
#import "OpenVPNReachability.h"
|
||||
|
||||
@interface OpenVPNReachability (Internal)
|
||||
|
||||
@@ -7,11 +7,12 @@
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "OpenVPNReachabilityStatus.h"
|
||||
|
||||
typedef NS_ENUM(NSInteger, OpenVPNReachabilityStatus);
|
||||
|
||||
@interface OpenVPNReachability : NSObject
|
||||
|
||||
@property (readonly, nonatomic) BOOL isTracking;
|
||||
@property (readonly, nonatomic, getter=isTracking) BOOL tracking;
|
||||
@property (readonly, nonatomic) OpenVPNReachabilityStatus reachabilityStatus;
|
||||
|
||||
- (nonnull instancetype)init;
|
||||
|
||||
@@ -6,11 +6,14 @@
|
||||
//
|
||||
//
|
||||
|
||||
#import <openvpn/apple/reachable.hpp>
|
||||
|
||||
#import "OpenVPNReachability.h"
|
||||
#import "OpenVPNReachability+Internal.h"
|
||||
|
||||
#include <openvpn/apple/reachable.hpp>
|
||||
|
||||
#import "OpenVPNReachabilityTracker.h"
|
||||
#import "OpenVPNReachabilityStatus.h"
|
||||
|
||||
@interface OpenVPNReachability () {
|
||||
BOOL _isTracking;
|
||||
}
|
||||
@@ -45,13 +48,12 @@
|
||||
}
|
||||
}
|
||||
|
||||
- (nonnull instancetype)init {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
- (instancetype)init {
|
||||
if (self = [super init]) {
|
||||
_isTracking = NO;
|
||||
|
||||
self.tracker = new OpenVPNReachabilityTracker(true, false, (__bridge void *)self);
|
||||
self.reachability = new Reachability(true, true);
|
||||
_tracker = new OpenVPNReachabilityTracker(true, false, (__bridge void *)self);
|
||||
_reachability = new Reachability(true, true);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
@@ -77,8 +79,8 @@
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
delete self.tracker;
|
||||
delete self.reachability;
|
||||
delete _tracker;
|
||||
delete _reachability;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
//
|
||||
//
|
||||
|
||||
#import <openvpn/apple/reachable.hpp>
|
||||
#include <openvpn/apple/reachable.hpp>
|
||||
|
||||
using namespace openvpn;
|
||||
|
||||
|
||||
@@ -6,10 +6,14 @@
|
||||
//
|
||||
//
|
||||
|
||||
#import "OpenVPNReachability+Internal.h"
|
||||
#import "OpenVPNReachabilityTracker.h"
|
||||
|
||||
OpenVPNReachabilityTracker::OpenVPNReachabilityTracker(const bool enable_internet, const bool enable_wifi, void* handler) : ReachabilityTracker(enable_internet, enable_wifi) {
|
||||
#import "OpenVPNReachability+Internal.h"
|
||||
#import "OpenVPNReachabilityStatus.h"
|
||||
|
||||
OpenVPNReachabilityTracker::OpenVPNReachabilityTracker(const bool enable_internet, const bool enable_wifi, void* handler) :
|
||||
ReachabilityTracker(enable_internet, enable_wifi)
|
||||
{
|
||||
this->handler = handler;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,10 +6,10 @@
|
||||
//
|
||||
//
|
||||
|
||||
#import <client/ovpncli.hpp>
|
||||
|
||||
#import "OpenVPNServerEntry.h"
|
||||
|
||||
#include <client/ovpncli.hpp>
|
||||
|
||||
using namespace openvpn;
|
||||
|
||||
@interface OpenVPNServerEntry (Internal)
|
||||
|
||||
@@ -13,6 +13,6 @@
|
||||
@property (nullable, readonly, nonatomic) NSString *server;
|
||||
@property (nullable, readonly, nonatomic) NSString *friendlyName;
|
||||
|
||||
- (nonnull instancetype) __unavailable init;
|
||||
- (nonnull instancetype) init NS_UNAVAILABLE;
|
||||
|
||||
@end
|
||||
|
||||
@@ -12,8 +12,7 @@
|
||||
@implementation OpenVPNServerEntry
|
||||
|
||||
- (instancetype)initWithServerEntry:(ClientAPI::ServerEntry)entry {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
if (self = [super init]) {
|
||||
_server = !entry.server.empty() ? [NSString stringWithUTF8String:entry.server.c_str()] : nil;
|
||||
_friendlyName = !entry.friendlyName.empty() ? [NSString stringWithUTF8String:entry.friendlyName.c_str()] : nil;
|
||||
}
|
||||
|
||||
@@ -6,10 +6,10 @@
|
||||
//
|
||||
//
|
||||
|
||||
#import <client/ovpncli.hpp>
|
||||
|
||||
#import "OpenVPNSessionToken.h"
|
||||
|
||||
#include <client/ovpncli.hpp>
|
||||
|
||||
using namespace openvpn;
|
||||
|
||||
@interface OpenVPNSessionToken (Internal)
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
//
|
||||
//
|
||||
|
||||
#import "OpenVPNSessionToken.h"
|
||||
#import "OpenVPNSessionToken+Internal.h"
|
||||
|
||||
using namespace openvpn;
|
||||
@@ -18,7 +19,7 @@ using namespace openvpn;
|
||||
@implementation OpenVPNSessionToken
|
||||
|
||||
- (instancetype)initWithSessionToken:(ClientAPI::SessionToken)token {
|
||||
if ((self = [super init])) {
|
||||
if (self = [super init]) {
|
||||
self.username = !token.username.empty() ? [NSString stringWithUTF8String:token.username.c_str()] : nil;
|
||||
self.session = !token.session_id.empty() ? [NSString stringWithUTF8String:token.session_id.c_str()] : nil;
|
||||
}
|
||||
@@ -38,7 +39,7 @@ using namespace openvpn;
|
||||
}
|
||||
|
||||
- (nullable instancetype)initWithCoder:(nonnull NSCoder *)aDecoder {
|
||||
if ((self = [self init])) {
|
||||
if (self = [self init]) {
|
||||
self.username = [aDecoder decodeObjectOfClass:[NSString class] forKey:NSStringFromSelector(@selector(username))];
|
||||
self.session = [aDecoder decodeObjectOfClass:[NSString class] forKey:NSStringFromSelector(@selector(session))];
|
||||
}
|
||||
|
||||
@@ -6,10 +6,10 @@
|
||||
//
|
||||
//
|
||||
|
||||
#import <client/ovpncli.hpp>
|
||||
|
||||
#import "OpenVPNTransportStats.h"
|
||||
|
||||
#include <client/ovpncli.hpp>
|
||||
|
||||
using namespace openvpn;
|
||||
|
||||
@interface OpenVPNTransportStats (Internal)
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
//
|
||||
//
|
||||
|
||||
#import "OpenVPNTransportStats.h"
|
||||
#import "OpenVPNTransportStats+Internal.h"
|
||||
|
||||
using namespace openvpn;
|
||||
@@ -21,12 +22,13 @@ using namespace openvpn;
|
||||
@implementation OpenVPNTransportStats
|
||||
|
||||
- (instancetype)initWithTransportStats:(ClientAPI::TransportStats)stats {
|
||||
if ((self = [self init])) {
|
||||
if (self = [self init]) {
|
||||
self.bytesIn = stats.bytesIn;
|
||||
self.bytesOut = stats.bytesOut;
|
||||
self.packetsIn = stats.packetsIn;
|
||||
self.packetsOut = stats.packetsOut;
|
||||
self.lastPacketReceived = stats.lastPacketReceived >= 0 ? [NSDate dateWithTimeIntervalSinceNow:stats.lastPacketReceived / -1024.0] : nil;
|
||||
self.lastPacketReceived = stats.lastPacketReceived >= 0 ?
|
||||
[NSDate dateWithTimeIntervalSinceNow:stats.lastPacketReceived / -1024.0] : nil;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
@@ -50,12 +52,13 @@ using namespace openvpn;
|
||||
}
|
||||
|
||||
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
|
||||
if ((self = [super init])) {
|
||||
if (self = [super init]) {
|
||||
self.bytesIn = [aDecoder decodeIntegerForKey:NSStringFromSelector(@selector(bytesIn))];
|
||||
self.bytesOut = [aDecoder decodeIntegerForKey:NSStringFromSelector(@selector(bytesOut))];
|
||||
self.packetsIn = [aDecoder decodeIntegerForKey:NSStringFromSelector(@selector(packetsIn))];
|
||||
self.packetsOut = [aDecoder decodeIntegerForKey:NSStringFromSelector(@selector(packetsOut))];
|
||||
self.lastPacketReceived = [aDecoder decodeObjectOfClass:[NSDate class] forKey:NSStringFromSelector(@selector(lastPacketReceived))];
|
||||
self.lastPacketReceived = [aDecoder decodeObjectOfClass:[NSDate class]
|
||||
forKey:NSStringFromSelector(@selector(lastPacketReceived))];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ FOUNDATION_EXPORT const unsigned char OpenVPNAdapterVersionString[];
|
||||
#import <OpenVPNAdapter/OpenVPNTransportStats.h>
|
||||
#import <OpenVPNAdapter/OpenVPNInterfaceStats.h>
|
||||
#import <OpenVPNAdapter/OpenVPNAdapter.h>
|
||||
#import <OpenVPNAdapter/OpenVPNAdapterPacketFlow.h>
|
||||
#import <OpenVPNAdapter/OpenVPNKeyType.h>
|
||||
#import <OpenVPNAdapter/OpenVPNCertificate.h>
|
||||
#import <OpenVPNAdapter/OpenVPNPrivateKey.h>
|
||||
|
||||
@@ -24,6 +24,9 @@
|
||||
// The crux of the API is defined in OpenVPNClient (below)
|
||||
// and TunBuilderBase.
|
||||
|
||||
#ifndef OVPNCLI_HPP
|
||||
#define OVPNCLI_HPP
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
@@ -600,3 +603,5 @@ namespace openvpn {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user