Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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!

like image 765
lundhjem Avatar asked Mar 25 '16 04:03

lundhjem


2 Answers

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.

like image 116
lundhjem Avatar answered Sep 25 '22 18:09

lundhjem


Updated For Swift 3

 import arpa
    import ifaddrs
    
    class func getBothIPAddresses() -> [AnyHashable: Any] {
        let WIFI_IF: String = "en0"
        let KNOWN_WIRED_IFS: [Any] = ["en2", "en3", "en4"]
        let KNOWN_CELL_IFS: [Any] = ["pdp_ip0", "pdp_ip1", "pdp_ip2", "pdp_ip3"]
        let UNKNOWN_IP_ADDRESS: String = ""
        var addresses: [AnyHashable: Any] = ["wireless": UNKNOWN_IP_ADDRESS, "wired": UNKNOWN_IP_ADDRESS, "cell": UNKNOWN_IP_ADDRESS]
    
        var interfaces: ifaddrs? = nil
    
        var temp_addr: ifaddrs? = nil
        var success: Int = 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 != nil {
                if temp_addr?.ifa_addr == nil {
                    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 (String(utf8String: temp_addr?.ifa_name) == WIFI_IF) {
                        // Get NSString from C String
                        addresses["wireless"] = String(utf8String: inet_ntoa((temp_addr?.ifa_addr as? sockaddr_in)?.sin_addr))
                    }
                    // Check if interface is a wired connection
                    if KNOWN_WIRED_IFS.contains(String(utf8String: temp_addr?.ifa_name)) {
                        addresses["wired"] = String(utf8String: inet_ntoa((temp_addr?.ifa_addr as? sockaddr_in)?.sin_addr))
                    }
                    // Check if interface is a cellular connection
                    if KNOWN_CELL_IFS.contains(String(utf8String: temp_addr?.ifa_name)) {
                        addresses["cell"] = String(utf8String: inet_ntoa((temp_addr?.ifa_addr as? sockaddr_in)?.sin_addr))
                    }
                }
                temp_addr = temp_addr?.ifa_next
            }
        }
            // Free memory
        freeifaddrs(interfaces)
        return addresses
    }
like image 25
BHAVIK Avatar answered Sep 24 '22 18:09

BHAVIK