summaryrefslogtreecommitdiffhomepage
path: root/ios
diff options
context:
space:
mode:
authorAndrej Mihajlov <and@mullvad.net>2021-10-05 11:59:33 +0200
committerAndrej Mihajlov <and@mullvad.net>2021-11-03 13:30:51 +0100
commitcbf7d656ab49144ebd0bfddc7667ecf144316f54 (patch)
tree589eff1aec97c64a902300f209de2cf5e7db13b3 /ios
parent7f54468f674e991038bf676113dba61e46a60353 (diff)
downloadmullvadvpn-cbf7d656ab49144ebd0bfddc7667ecf144316f54.tar.xz
mullvadvpn-cbf7d656ab49144ebd0bfddc7667ecf144316f54.zip
DNSSettings: add custom DNS configuration
Diffstat (limited to 'ios')
-rw-r--r--ios/MullvadVPN.xcodeproj/project.pbxproj6
-rw-r--r--ios/MullvadVPN/AnyIPAddress.swift101
-rw-r--r--ios/MullvadVPN/TunnelSettings.swift39
3 files changed, 146 insertions, 0 deletions
diff --git a/ios/MullvadVPN.xcodeproj/project.pbxproj b/ios/MullvadVPN.xcodeproj/project.pbxproj
index 4417fd14e9..5d9c205ec8 100644
--- a/ios/MullvadVPN.xcodeproj/project.pbxproj
+++ b/ios/MullvadVPN.xcodeproj/project.pbxproj
@@ -98,6 +98,8 @@
584789BE264D4A2A000E45FB /* le_root_cert.cer in Resources */ = {isa = PBXBuildFile; fileRef = 584789B7264D4A2A000E45FB /* le_root_cert.cer */; };
584789E026529D72000E45FB /* SSLPinningURLSessionDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 584789DF26529D72000E45FB /* SSLPinningURLSessionDelegate.swift */; };
584789EC2652A1A2000E45FB /* Logging in Frameworks */ = {isa = PBXBuildFile; productRef = 584789EB2652A1A2000E45FB /* Logging */; };
+ 584D26BF270C550B004EA533 /* AnyIPAddress.swift in Sources */ = {isa = PBXBuildFile; fileRef = 584D26BE270C550B004EA533 /* AnyIPAddress.swift */; };
+ 584D26C0270C550E004EA533 /* AnyIPAddress.swift in Sources */ = {isa = PBXBuildFile; fileRef = 584D26BE270C550B004EA533 /* AnyIPAddress.swift */; };
584E96BC240FD4DA00D3334F /* Location.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58A1AA8623F43901009F7EA6 /* Location.swift */; };
584E96BD240FD4DA00D3334F /* Location.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58A1AA8623F43901009F7EA6 /* Location.swift */; };
584E96BE240FD4DB00D3334F /* Location.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58A1AA8623F43901009F7EA6 /* Location.swift */; };
@@ -394,6 +396,7 @@
584789B7264D4A2A000E45FB /* le_root_cert.cer */ = {isa = PBXFileReference; lastKnownFileType = file; path = le_root_cert.cer; sourceTree = "<group>"; };
584789DF26529D72000E45FB /* SSLPinningURLSessionDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SSLPinningURLSessionDelegate.swift; sourceTree = "<group>"; };
584B26F3237434D00073B10E /* RelaySelectorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RelaySelectorTests.swift; sourceTree = "<group>"; };
+ 584D26BE270C550B004EA533 /* AnyIPAddress.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnyIPAddress.swift; sourceTree = "<group>"; };
5850366725A47AC700A43E93 /* IPAddressRange+Codable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "IPAddressRange+Codable.swift"; sourceTree = "<group>"; };
58561C98239A5D1500BD6B5E /* IPEndpoint.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IPEndpoint.swift; sourceTree = "<group>"; };
5857F24224C8662600CF6F47 /* SelectLocationHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SelectLocationHeaderView.swift; sourceTree = "<group>"; };
@@ -786,6 +789,7 @@
582AE30F2440A6CA00E6733A /* AccountTokenInput.swift */,
58CCA01722426713004F3011 /* AccountViewController.swift */,
58B9EB122488ED2100095626 /* AlertPresenter.swift */,
+ 584D26BE270C550B004EA533 /* AnyIPAddress.swift */,
5868585424054096000B8131 /* AppButton.swift */,
58CE5E63224146200008646E /* AppDelegate.swift */,
58BFA5CB22A7CE1F00A6173D /* ApplicationConfiguration.swift */,
@@ -1337,6 +1341,7 @@
5820674926E63EC900655B05 /* Promise+BackgroundTask.swift in Sources */,
58B9EB132488ED2100095626 /* AlertPresenter.swift in Sources */,
587A01FC23F1F0BE00B68763 /* SimulatorTunnelProviderHost.swift in Sources */,
+ 584D26BF270C550B004EA533 /* AnyIPAddress.swift in Sources */,
5862805422428EF100F5A6E1 /* TranslucentButtonBlurView.swift in Sources */,
580EE20624B3222200F9D8A1 /* ExclusivityController.swift in Sources */,
5888AD83227B11080051EB06 /* SelectLocationCell.swift in Sources */,
@@ -1421,6 +1426,7 @@
58BFA5CD22A7CE1F00A6173D /* ApplicationConfiguration.swift in Sources */,
5850368D25A49E2200A43E93 /* PrivateKeyWithMetadata.swift in Sources */,
5820675826E652AF00655B05 /* RelayCacheIO.swift in Sources */,
+ 584D26C0270C550E004EA533 /* AnyIPAddress.swift in Sources */,
5820675726E652A600655B05 /* REST.swift in Sources */,
585DA88F26B031E200B8C587 /* TunnelIPCCoding.swift in Sources */,
5806767C27048E9B00C858CB /* PacketTunnelProvider.swift in Sources */,
diff --git a/ios/MullvadVPN/AnyIPAddress.swift b/ios/MullvadVPN/AnyIPAddress.swift
new file mode 100644
index 0000000000..1898754a69
--- /dev/null
+++ b/ios/MullvadVPN/AnyIPAddress.swift
@@ -0,0 +1,101 @@
+//
+// AnyIPAddress.swift
+// MullvadVPN
+//
+// Created by pronebird on 05/10/2021.
+// Copyright © 2021 Mullvad VPN AB. All rights reserved.
+//
+
+import Foundation
+import Network
+
+/// Container type that holds either `IPv4Address` or `IPv6Address`.
+enum AnyIPAddress: IPAddress, Codable, Equatable, CustomDebugStringConvertible {
+ case ipv4(IPv4Address)
+ case ipv6(IPv6Address)
+
+ private enum CodingKeys: String, CodingKey {
+ case ipv4, ipv6
+ }
+
+ private var innerAddress: IPAddress {
+ switch self {
+ case .ipv4(let ipv4Address):
+ return ipv4Address
+ case .ipv6(let ipv6Address):
+ return ipv6Address
+ }
+ }
+
+ var rawValue: Data {
+ return innerAddress.rawValue
+ }
+
+ init(from decoder: Decoder) throws {
+ let container = try decoder.container(keyedBy: CodingKeys.self)
+
+ if container.contains(.ipv4) {
+ self = .ipv4(try container.decode(IPv4Address.self, forKey: .ipv4))
+ } else if container.contains(.ipv6) {
+ self = .ipv6(try container.decode(IPv6Address.self, forKey: .ipv6))
+ } else {
+ throw DecodingError.dataCorruptedError(forKey: .ipv4, in: container, debugDescription: "Invalid AnyIPAddress representation")
+ }
+ }
+
+ func encode(to encoder: Encoder) throws {
+ var container = encoder.container(keyedBy: CodingKeys.self)
+
+ switch self {
+ case .ipv4(let ipv4Address):
+ try container.encode(ipv4Address, forKey: .ipv4)
+ case .ipv6(let ipv6Address):
+ try container.encode(ipv6Address, forKey: .ipv6)
+ }
+ }
+
+ init?(_ rawValue: Data, _ interface: NWInterface?) {
+ if let ipv4Address = IPv4Address(rawValue, interface) {
+ self = .ipv4(ipv4Address)
+ } else if let ipv6Address = IPv6Address(rawValue, interface) {
+ self = .ipv6(ipv6Address)
+ } else {
+ return nil
+ }
+ }
+
+ init?(_ string: String) {
+ if let ipv4Address = IPv4Address(string) {
+ self = .ipv4(ipv4Address)
+ } else if let ipv6Address = IPv6Address(string) {
+ self = .ipv6(ipv6Address)
+ } else {
+ return nil
+ }
+ }
+
+ var interface: NWInterface? {
+ return innerAddress.interface
+ }
+
+ var isLoopback: Bool {
+ return innerAddress.isLoopback
+ }
+
+ var isLinkLocal: Bool {
+ return innerAddress.isLinkLocal
+ }
+
+ var isMulticast: Bool {
+ return innerAddress.isMulticast
+ }
+
+ var debugDescription: String {
+ switch self {
+ case .ipv4(let ipv4Address):
+ return "\(ipv4Address)"
+ case .ipv6(let ipv6Address):
+ return "\(ipv6Address)"
+ }
+ }
+}
diff --git a/ios/MullvadVPN/TunnelSettings.swift b/ios/MullvadVPN/TunnelSettings.swift
index c8503c894d..9f3b47162d 100644
--- a/ios/MullvadVPN/TunnelSettings.swift
+++ b/ios/MullvadVPN/TunnelSettings.swift
@@ -58,9 +58,48 @@ struct TunnelSettings: Codable, Equatable {
/// A struct that holds DNS settings.
struct DNSSettings: Codable, Equatable {
+ /// Maximum number of allowed DNS domains.
+ static let maxAllowedCustomDNSDomains = 3
+
/// Block advertising.
var blockAdvertising: Bool = false
/// Block tracking.
var blockTracking: Bool = false
+
+ /// Enable custom DNS.
+ var enableCustomDNS: Bool = false
+
+ /// Custom DNS domains.
+ var customDNSDomains: [AnyIPAddress] = []
+
+ private enum CodingKeys: String, CodingKey {
+ case blockAdvertising, blockTracking, enableCustomDNS, customDNSDomains
+ }
+
+ init() {}
+
+ init(from decoder: Decoder) throws {
+ let container = try decoder.container(keyedBy: CodingKeys.self)
+
+ blockAdvertising = try container.decode(Bool.self, forKey: .blockAdvertising)
+ blockTracking = try container.decode(Bool.self, forKey: .blockTracking)
+
+ if let storedEnableCustomDNS = try container.decodeIfPresent(Bool.self, forKey: .enableCustomDNS) {
+ enableCustomDNS = storedEnableCustomDNS
+ }
+
+ if let storedCustomDNSDomains = try container.decodeIfPresent([AnyIPAddress].self, forKey: .customDNSDomains) {
+ customDNSDomains = storedCustomDNSDomains
+ }
+ }
+
+ func encode(to encoder: Encoder) throws {
+ var container = encoder.container(keyedBy: CodingKeys.self)
+
+ try container.encode(blockAdvertising, forKey: .blockAdvertising)
+ try container.encode(blockTracking, forKey: .blockTracking)
+ try container.encode(enableCustomDNS, forKey: .enableCustomDNS)
+ try container.encode(customDNSDomains, forKey: .customDNSDomains)
+ }
}