Search code examples
iosobjective-cipadnetwork-programming

iPad: How to get Ethernet IP address programmatically


I know how to get the IP address, via en0 interface, seen here: iPhone/iPad/OSX: How to get my IP address programmatically?

But now I'm implementing an ethernet connection to the LAN using the Lightning to USB 3 Camera Adapter in order to connect to the internet without Wifi in 9.3, so the above solution can't resolve the IP address without the wireless connection. The iPad is on the internet fine, now it's just important the app can resolve the device's own IP address.

How can I get the iPad's IP address through a Lightning->USB->Ethernet connection? As opposed to wirelessly.
Thanks in advance!


Solution

  • en2 interface.

    Add:

    [[NSString stringWithUTF8String:temp_addr->ifa_name] isEqualToString:@"en2"]
    

    to the first solution in iPhone/iPad/OSX: How to get my IP address programmatically? to also get the device's IP address through wired connection.

    UPDATE: Just expanding on @Raptor's solution linked above; this will return both wired and wireless IP Address, if both or either is present. Then just check the return dictionary's values' lengths to see what you're working with.

    #import <ifaddrs.h>
    #import <arpa/inet.h>
    
    + (NSDictionary *)getBothIPAddresses {
        const NSString *WIFI_IF = @"en0";
        NSArray *KNOWN_WIRED_IFS = @[@"en1",@"en2",@"en3",@"en4"];
        NSArray *KNOWN_CELL_IFS = @[@"pdp_ip0",@"pdp_ip1",@"pdp_ip2",@"pdp_ip3"];
    
        const NSString *UNKNOWN_IP_ADDRESS = @"";
    
        NSMutableDictionary *addresses = [NSMutableDictionary dictionaryWithDictionary:@{@"wireless":UNKNOWN_IP_ADDRESS,
                                                                                            @"wired":UNKNOWN_IP_ADDRESS,
                                                                                             @"cell":UNKNOWN_IP_ADDRESS}];
    
        struct ifaddrs *interfaces = NULL;
        struct ifaddrs *temp_addr = NULL;
        int success = 0;
        // retrieve the current interfaces - returns 0 on success
        success = getifaddrs(&interfaces);
        if (success == 0) {
            // Loop through linked list of interfaces
            temp_addr = interfaces;
            while(temp_addr != NULL) {
                if (temp_addr->ifa_addr == NULL) {
                     temp_addr = temp_addr->ifa_next;
                     continue;
                }
                if(temp_addr->ifa_addr->sa_family == AF_INET) {
                    // Check if interface is en0 which is the wifi connection on the iPhone
                    if([[NSString stringWithUTF8String:temp_addr->ifa_name] isEqualToString:WIFI_IF]) {
                        // Get NSString from C String
                        [addresses setObject:[NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr)] forKey:@"wireless"];
                    
                    }
                    // Check if interface is a wired connection
                    if([KNOWN_WIRED_IFS containsObject:[NSString stringWithUTF8String:temp_addr->ifa_name]]) {
                        [addresses setObject:[NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr)] forKey:@"wired"];
                    }
                    // Check if interface is a cellular connection
                    if([KNOWN_CELL_IFS containsObject:[NSString stringWithUTF8String:temp_addr->ifa_name]]) {
                        [addresses setObject:[NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr)] forKey:@"cell"];
                    }
                }
    
                temp_addr = temp_addr->ifa_next;
            }
        }
        // Free memory
        freeifaddrs(interfaces);
    
        return addresses;
    }
    

    UPDATE: en3 interface, another possibility; seems to depend on the type of adapter. Makes me think there could be more interfaces that I'm still missing based on hardware being used, so please comment if anyone discovers more.

    UPDATE: en4 as well; doesn't necessarily depend on adapter like I originally thought, because a Mini with all the same hardware at one point decided to switch from one interface to this new one. Also, I'm starting to think it may be easier to just compare the ifa_name to any string with a format of en[2..n], so long as it's in the AF_INET family (for example, en1 is NOT and doesn't return an address we're looking for); it's likely premature to implement something like that for Prod without more proof, so for now I manage with a list of 'known' wired interfaces.

    UPDATE: Considers cellular AF_INET interfaces too, mentioned in What exactly means iOS networking interface name? what's pdp_ip ? what's ap?

    UPDATE: Ethernet IP addresses have begun showing up on the en1 interface lately on certain new iPads, so it should also be considered when it's a member of the AF_INET family. No distinguishable rhyme or reason, it happens with varying iPad models and iOS versions.