Преглед изворни кода

Use active interface IP address for network ID on mobile

CTCarrier methods deprecated in iOS 16.0 and now return static value 65535.
mirokuratczyk пре 2 година
родитељ
комит
28ff88b459

+ 34 - 25
MobileLibrary/iOS/PsiphonTunnel/PsiphonTunnel/Network/NetworkID.m

@@ -58,42 +58,51 @@
         }
     } else if (currentNetworkStatus == NetworkReachabilityReachableViaCellular) {
         [networkID setString:@"MOBILE"];
-        CTTelephonyNetworkInfo *telephonyNetworkinfo = [[CTTelephonyNetworkInfo alloc] init];
-        CTCarrier *cellularProvider = [telephonyNetworkinfo subscriberCellularProvider];
-        if (cellularProvider != nil) {
-            NSString *mcc = [cellularProvider mobileCountryCode];
-            NSString *mnc = [cellularProvider mobileNetworkCode];
-            [networkID appendFormat:@"-%@-%@", mcc, mnc];
+
+        if (@available(iOS 16.0, *)) {
+            // Testing showed that the IP address of the active interface uniquely identified the
+            // corresponding network and did not change over long periods of time, which makes it a
+            // useful addition to the network ID value.
+            NSError *err;
+            NSString *activeInterfaceAddress =
+                [NetworkInterface getActiveInterfaceAddressWithReachability:reachability
+                                                    andCurrentNetworkStatus:currentNetworkStatus
+                                                                      error:&err];
+            if (err != nil) {
+                NSString *localizedDescription = [NSString stringWithFormat:@"error getting active interface address %@", err.localizedDescription];
+                *outWarn = [[NSError alloc] initWithDomain:@"iOSLibrary"
+                                                      code:1
+                                                  userInfo:@{NSLocalizedDescriptionKey:localizedDescription}];
+                return networkID;
+            }
+            [networkID appendFormat:@"-%@", activeInterfaceAddress];
+        } else {
+            // CTCarrier.mobileCountryCode and CTCarrier.mobileCountryCode deprecated
+            // without replacement in iOS 16.0 https://developer.apple.com/forums/thread/714876.
+            CTTelephonyNetworkInfo *telephonyNetworkinfo = [[CTTelephonyNetworkInfo alloc] init];
+            CTCarrier *cellularProvider = [telephonyNetworkinfo subscriberCellularProvider];
+            if (cellularProvider != nil) {
+                NSString *mcc = [cellularProvider mobileCountryCode];
+                NSString *mnc = [cellularProvider mobileNetworkCode];
+                [networkID appendFormat:@"-%@-%@", mcc, mnc];
+            }
         }
     } else if (currentNetworkStatus == NetworkReachabilityReachableViaWired) {
         [networkID setString:@"WIRED"];
 
         NSError *err;
-        NSString *activeInterface =
-            [NetworkInterface getActiveInterfaceWithReachability:reachability
-                                         andCurrentNetworkStatus:currentNetworkStatus
-                                                           error:&err];
+        NSString *activeInterfaceAddress =
+            [NetworkInterface getActiveInterfaceAddressWithReachability:reachability
+                                                andCurrentNetworkStatus:currentNetworkStatus
+                                                                  error:&err];
         if (err != nil) {
-            NSString *localizedDescription = [NSString stringWithFormat:@"error getting active interface %@", err.localizedDescription];
+            NSString *localizedDescription = [NSString stringWithFormat:@"error getting active interface address %@", err.localizedDescription];
             *outWarn = [[NSError alloc] initWithDomain:@"iOSLibrary"
                                                   code:1
                                               userInfo:@{NSLocalizedDescriptionKey:localizedDescription}];
             return networkID;
         }
-
-        if (activeInterface != nil) {
-            NSError *err;
-            NSString *interfaceAddress = [NetworkInterface getInterfaceAddress:activeInterface
-                                                                         error:&err];
-            if (err != nil) {
-                NSString *localizedDescription =
-                    [NSString stringWithFormat:@"getNetworkID: error getting interface address %@", err.localizedDescription];
-                *outWarn = [[NSError alloc] initWithDomain:@"iOSLibrary" code:1 userInfo:@{NSLocalizedDescriptionKey: localizedDescription}];
-                return networkID;
-            } else if (interfaceAddress != nil) {
-                [networkID appendFormat:@"-%@", interfaceAddress];
-            }
-        }
+        [networkID appendFormat:@"-%@", activeInterfaceAddress];
     } else if (currentNetworkStatus == NetworkReachabilityReachableViaLoopback) {
         [networkID setString:@"LOOPBACK"];
     }

+ 7 - 0
MobileLibrary/iOS/PsiphonTunnel/PsiphonTunnel/Network/NetworkInterface.h

@@ -43,6 +43,13 @@ NS_ASSUME_NONNULL_BEGIN
 + (NSString*)getActiveInterfaceWithReachability:(id<ReachabilityProtocol>)reachability
                         andCurrentNetworkStatus:(NetworkReachability)currentNetworkStatus
                                           error:(NSError *_Nullable *_Nonnull)outError;
+/// Returns the active interface address.
+/// @param reachability ReachabilityProtocol implementer used to determine active interface on iOS >=12.
+/// @param currentNetworkStatus Used to determine active interface on iOS <12.
+/// @param outError If non-nil, then an error occurred while determining the active interface.
++ (NSString*)getActiveInterfaceAddressWithReachability:(id<ReachabilityProtocol>)reachability
+                               andCurrentNetworkStatus:(NetworkReachability)currentNetworkStatus
+                                                 error:(NSError *_Nullable *_Nonnull)outError;
 
 @end
 

+ 45 - 0
MobileLibrary/iOS/PsiphonTunnel/PsiphonTunnel/Network/NetworkInterface.m

@@ -226,4 +226,49 @@
     return activeInterface;
 }
 
++ (NSString*)getActiveInterfaceAddressWithReachability:(id<ReachabilityProtocol>)reachability
+                               andCurrentNetworkStatus:(NetworkReachability)currentNetworkStatus
+                                                 error:(NSError *_Nullable *_Nonnull)outError {
+
+    *outError = nil;
+
+    NSError *err;
+    NSString *activeInterface =
+        [NetworkInterface getActiveInterfaceWithReachability:reachability
+                                     andCurrentNetworkStatus:currentNetworkStatus
+                                                       error:&err];
+    if (err != nil) {
+        NSString *localizedDescription = [NSString stringWithFormat:@"error getting active interface %@", err.localizedDescription];
+        *outError = [[NSError alloc] initWithDomain:@"iOSLibrary"
+                                               code:1
+                                           userInfo:@{NSLocalizedDescriptionKey:localizedDescription}];
+        return @"";
+    } else if (activeInterface == nil) {
+        NSString *localizedDescription = @"active interface nil";
+        *outError = [[NSError alloc] initWithDomain:@"iOSLibrary"
+                                               code:1
+                                           userInfo:@{NSLocalizedDescriptionKey:localizedDescription}];
+        return @"";
+    }
+
+    NSString *interfaceAddress = [NetworkInterface getInterfaceAddress:activeInterface
+                                                                 error:&err];
+    if (err != nil) {
+        NSString *localizedDescription =
+            [NSString stringWithFormat:@"error getting interface address %@", err.localizedDescription];
+        *outError = [[NSError alloc] initWithDomain:@"iOSLibrary"
+                                               code:1
+                                           userInfo:@{NSLocalizedDescriptionKey:localizedDescription}];
+        return @"";
+    } else if (interfaceAddress == nil) {
+        NSString *localizedDescription = @"interface address nil";
+        *outError = [[NSError alloc] initWithDomain:@"iOSLibrary"
+                                               code:1
+                                           userInfo:@{NSLocalizedDescriptionKey:localizedDescription}];
+        return @"";
+    }
+
+    return interfaceAddress;
+}
+
 @end