Sunday, April 5, 2009

How to get the IP address of an iPhone OS v2.2.1

Lately I have been struggling with an iPhone OS 2.2.1 app that needs to know the WiFi IP address of the iPhone. Unfortunately at the time the app runs it does not have internet access and thus I cannot use whatismyip.com.

With thanks to Erica Sadun (iPhone cookbook) and gandreas and valexa on the iPhone dev forums I was able to create the following function. The function iterates over the IPs of the phone using getifaddrs(&addrs). if getWiFiIPAddress finds "en0" in the list interface addresses (ifaddrs) it will return the ethernet adapter zero (en0) IP address as a NSSring*. If no address is found the function will return NULL.


//------- includes

#include <ifaddrs.h>
#include
<arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <net/if.h>
#include <net/if_dl.h>
#include <arpa/inet.h>
#include <ifaddrs.h>

#if ! defined(IFT_ETHER)
#define IFT_ETHER 0x6/* Ethernet CSMACD */
#endif


//------- Implementation

- (NSString*)getWiFiIPAddress
{

BOOL success;
struct ifaddrs * addrs;
const struct ifaddrs * cursor;

success = getifaddrs(&addrs) == 0;
if (success) {
cursor = addrs;
while (cursor != NULL) {
if (cursor->ifa_addr->sa_family == AF_INET && (cursor->ifa_flags & IFF_LOOPBACK) == 0) // this second test keeps from picking up the loopback address
{
NSString *name = [NSString stringWithUTF8String:cursor->ifa_name];
if ([name isEqualToString:@"en0"]) { // found the WiFi adapter
return [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)cursor->ifa_addr)->sin_addr)];
}
}

cursor = cursor->ifa_next;
}
freeifaddrs(addrs);
}
return NULL;
}

PS: I need a better blog, that support snippets - comments?

10 comments:

  1. I tossed your code into an app I have and got lots of errors. Could you include the headers that are required to get this to work?

    ReplyDelete
  2. Note that I did find these locations but I don't know enough about networking on linux or the mac to reduce this list:

    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <net/if.h>
    #include <ifaddrs.h>

    ReplyDelete
  3. included includes - ooops. sorry 'bout that.

    ReplyDelete
  4. I'm gald to see this method.
    It's a perfect solution about my problem.
    Thank you!

    ReplyDelete
  5. Thanks for the code! The code fixed my problem.

    ReplyDelete
  6. I think you may have a memory leak if you don't call freeifaddrs(addrs) before returning the string.

    ReplyDelete
  7. Has anyone managed to pass Apple app approval process for an application whci uses this code?

    ReplyDelete
  8. Anonymous on Apr 14th was right. It does have a memory leak.. also it's bad programming practice to have a return from in the middle of your code.
    Try this.

    + (NSString *) localWiFiIPAddress
    {
    BOOL success;
    struct ifaddrs * addrs;
    const struct ifaddrs * cursor;
    NSString *address = nil;
    success = getifaddrs(&addrs) == 0;
    if (success) {
    cursor = addrs;
    while (cursor != NULL) {
    // the second test keeps from picking up the loopback address
    if (cursor->ifa_addr->sa_family == AF_INET && (cursor->ifa_flags & IFF_LOOPBACK) == 0)
    {
    NSString *name = [NSString stringWithUTF8String:cursor->ifa_name];
    if ([name isEqualToString:@"en0"]) // Wi-Fi adapter
    {
    address = [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)cursor->ifa_addr)->sin_addr)];
    break;
    }
    }
    cursor = cursor->ifa_next;
    }
    freeifaddrs(addrs);
    }
    return address;
    }

    ReplyDelete
    Replies
    1. Thanks jon, that's a proper code , now memory leak is fixed !

      Delete
  9. Is there a IPV6 version of it?

    ReplyDelete