Some iPhones are unable to obtain IP addresses.

When I use the following code to try to obtain an IP address, some phones fail to get the IP address.

+ (NSDictionary *)getWLANAddressInfo {
    NSMutableDictionary *dict = [NSMutableDictionary dictionary];
    
    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->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:@"en0"]) {
                    // Get NSString from C String
                    NSString *address = [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr)];
                    NSString *dstaddr = [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_dstaddr)->sin_addr)];
                    [dict setObject:address forKey:@"ip"];
                    [dict setObject:dstaddr forKey:@"dst"];
                }
            }
            
            temp_addr = temp_addr->ifa_next;
        }
    }
    // Free memory
    freeifaddrs(interfaces);
    return dict;
}

The affected phones have iOS versions 16.3.1 and 16.4, Has anyone else encountered the same issue?

What's causing this issue and how can I work around it?

Accepted Reply

our accessory does not support Bonjour.

You should fix that. Right now you’re working around this limitation in your iOS, and you probably have similar workarounds in your apps on other platforms. If you’re accessory supported Bonjour, you could eliminate all the extra code, and you’d get a more reliable product in general.

The prerequisite for sending a subnet broadcast is that I already know the IP address of the accessory

No, the prerequisite is that you know the subnet broadcast address.

can I retrieve the IP addresses of all IPv4 network interfaces and then send a subnet broadcast?

Yes. That’s exactly what I’m suggesting. Don’t look for one specific interface but rather send this broadcast on all Ethernet-like interfaces.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Replies

This code assumes that the primary Wi-Fi interface is called en0, which isn’t a valid assumption. However, and somewhat annoyingly, iOS does not have an easy way to get the primary Wi-Fi interface.

What do you need this information for? That is, once you get this IP address, what do you intend to do with it?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Our main task is to configure smart devices for networking. When the phone connects to the AP hotspot emitted by the smart device, it needs to obtain the IP address of the smart device, and then send a subnet broadcast like xx.xx.xx.255 based on the IP segment in order to complete the networking configuration.

Additionally, can valid Wi-Fi interface be obtained through function CNCopySupportedInterfaces()?

Our main task is to configure smart devices for networking.

OK, that’s a concrete case for which there is probably a good solution.

When the phone connects to the AP hotspot emitted by the smart device, it needs to obtain the IP address of the smart device

Can you be more specific about what that means? getifaddrs returns the IP address that the iOS device is using. How does that relate to your accessory’s IP address?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

When a phone connects to a device's AP hotspot, the IP address it obtains is in the same network segment as the device. For example, if the current IP address of the phone is 192.168.1.100 and the device's IP address is 192.168.1.x, the phone sends a subnet broadcast to 192.168.1.255. The device will capture this UDP packet and use the information in the packet to connect to the router.

OK, let’s start with terminology. In Apple parlance, device always refers to the Apple device, so the iPhone in this example. We use accessory to refer to your device. If you use these ‘standard’ terms, that’ll help avoid confusion.

Also, this would all be a lot easier if your accessory supported Bonjour [1]. That’d obviate the need for all this messing around with broadcasts, DHCP servers, and so on.

Finally, the easiest way to avoid problems in this space is to send that broadcast on all Ethernet-like interfaces. If you do this using a socket per interface, bound to that interface using IP_BOUND_IF, you’ll receive the accessory’s response on a specific socket which lets you know what interface it’s using.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

[1] Apple’s marketing name for the following standards:

  • RFC 3927 Dynamic Configuration of IPv4 Link-Local Addresses

  • RFC 6762 Multicast DNS

  • RFC 6763 DNS-Based Service Discovery

Also, this would all be a lot easier if your accessory supported Bonjour [1].

I'm sorry, but our accessory does not support Bonjour.

the easiest way to avoid problems in this space is to send that broadcast on all Ethernet-like interfaces

The prerequisite for sending a subnet broadcast is that I already know the IP address of the accessory, If I fail to retrieve the IP address of the en0 network interface, can I retrieve the IP addresses of all IPv4 network interfaces and then send a subnet broadcast?

our accessory does not support Bonjour.

You should fix that. Right now you’re working around this limitation in your iOS, and you probably have similar workarounds in your apps on other platforms. If you’re accessory supported Bonjour, you could eliminate all the extra code, and you’d get a more reliable product in general.

The prerequisite for sending a subnet broadcast is that I already know the IP address of the accessory

No, the prerequisite is that you know the subnet broadcast address.

can I retrieve the IP addresses of all IPv4 network interfaces and then send a subnet broadcast?

Yes. That’s exactly what I’m suggesting. Don’t look for one specific interface but rather send this broadcast on all Ethernet-like interfaces.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

We recently also have the same issue and it only happens to some iPhone devices not all.

it only happens to some iPhone devices not all.

That gels with the anecdotal evidence I’ve heard from others.

Regardless, I don’t consider this a bug because BSD interface names are not considered API. If you write code that assumes that en0 is the Wi-Fi interface, it will break in various situations. So… don’t.

If you’re currently hard coding en0 in this way, feel free to start a new thread here on DevForums with the details as to why you’re doing that, and I’ll help you explore alternatives. Tag your thread with Network so that I see it.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"