Просмотр исходного кода

Fixed bindToDevice to use active network interface

Amir Khan 8 лет назад
Родитель
Сommit
2ea634463b
1 измененных файлов с 56 добавлено и 5 удалено
  1. 56 5
      MobileLibrary/iOS/PsiphonTunnel/PsiphonTunnel/PsiphonTunnel.m

+ 56 - 5
MobileLibrary/iOS/PsiphonTunnel/PsiphonTunnel/PsiphonTunnel.m

@@ -693,19 +693,70 @@
     if (!tunnelWholeDevice) {
         return FALSE;
     }
-
-    // TODO: Select correct WiFi or mobile data interface.
-    unsigned int interfaceIndex = if_nametoindex("en0");
-
+    
+    NSString *activeInterface = [self getActiveInterface];
+    if (activeInterface == nil) {
+        return FALSE;
+    }
+    [self logMessage:[NSString stringWithFormat:@"bindToDevice: Active interface: %@", activeInterface]];
+    
+    unsigned int interfaceIndex = if_nametoindex([activeInterface UTF8String]);
+    
     int ret = setsockopt((int)fileDescriptor, IPPROTO_IP, IP_BOUND_IF, &interfaceIndex, sizeof(interfaceIndex));
     if (ret != 0) {
         [self logMessage:[NSString stringWithFormat: @"bindToDevice: setsockopt failed; errno: %d", errno]];
         return FALSE;
     }
-
+    
     return TRUE;
 }
 
+/*!
+ @brief Returns name of active network interface.
+ @return Active interface name, nil otherwise.
+ */
+- (NSString *)getActiveInterface {
+    
+    // Getting list of all active interfaces
+    NSMutableArray *upIffList = [NSMutableArray new];
+    struct ifaddrs *interfaces;
+    if (EXIT_FAILURE == getifaddrs(&interfaces)) {
+        return nil;
+    }
+    
+    struct ifaddrs *interface;
+    for (interface=interfaces; interface; interface=interface->ifa_next) {
+        
+        // Only IFF_UP interfaces. Loopback is ignored.
+        if (interface->ifa_flags & IFF_UP && !(interface->ifa_flags & IFF_LOOPBACK)) {
+            
+            if (interface->ifa_addr && (interface->ifa_addr->sa_family==AF_INET || interface->ifa_addr->sa_family==AF_INET6)) {
+                NSString *interfaceName = [NSString stringWithUTF8String:interface->ifa_name];
+                [upIffList addObject:interfaceName];
+            }
+        }
+    }
+    
+    [self logMessage:[NSString stringWithFormat:@"getActiveInterace: List of UP interfaces: %@", upIffList]];
+    
+    
+    // TODO: following is a heuristic for choosing active network interface
+    // Only Wi-Fi and Cellular interfaces are considered
+    // @see : https://forums.developer.apple.com/thread/76711
+    NSArray *iffPriorityList = @[ @"en0", @"pdp_ip0"];
+    for ( NSString * key in iffPriorityList) {
+        for (NSString * upIff in upIffList) {
+            if ([key isEqualToString:upIff]) {
+                return [NSString stringWithString:upIff];
+            }
+        }
+    }
+    
+    [self logMessage:@"getActiveInterface: No active interface found"];
+    
+    return nil;
+}
+
 - (NSString *)getPrimaryDnsServer {
     // This function is only called when BindToDevice is used/supported.
     // TODO: Implement correctly