Retrieve local IPv4/IPv6 on Wifi/Cellular

From Wikichris
Jump to: navigation, search

Purpose

On iOS, you want to know your local IP (for example for a sharing app on the wifi) but the iOS SDK provides no simple way to get the IP Address for the wifi connection.

I found an interesting Method in Objective-C which retrieve the IPv4 address of the wifi connection as a NSString

Sadly it doesn't work with IPv6. So I modified it and here is the code

Method for IPv4 and IPv6 on iOS

Remember to import

#import <ifaddrs.h>
#import <arpa/inet.h>

Then after, here is the Method <source lang="objc">

/**
Retrive the Local IP

Need to include <ifaddrs.h> and <arpa/inet.h>

@author Christian Gonzalvez, http://wiki.gonzofamily.com

@param networkInterface Can be "ios_wifi" "ios_cellular"
@param ipVersion Can be 4 or 6 only

@return the IPv6 or v4 address if found, nil otherwise
*/
+(NSString *)getIpLocally:(NSString *)networkInterface ipVersion:(int)ipVersion
{
	if(ipVersion != 4 && ipVersion != 6)
	  {
		NSLog(@"getIpLocally unknown version of IP: %i",ipVersion);
		return nil;
	  }
	
	NSString *networkInterfaceRef;
	
	if (networkInterface == @"ios_cellular")
	  {
		networkInterfaceRef = @"pdp_ip0";
	  }
	else if(networkInterface == @"ios_wifi")
	  {
		networkInterfaceRef = @"en0"; //en1 on simulator if mac on wifi
	  }
	else
	  {
		NSLog(@"getIpLocally unknown interface: %@",networkInterface);
		return nil;
	  }
	
	NSString *address = nil;
	struct ifaddrs *interfaces = NULL;
	struct ifaddrs *temp_addr = NULL;
	struct sockaddr_in *s4;
	struct sockaddr_in6 *s6;
	char buf[64];
	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( (ipVersion == 4 && temp_addr->ifa_addr->sa_family == AF_INET) ||
			   (ipVersion == 6 &&  temp_addr->ifa_addr->sa_family == AF_INET6))
			  {
				NSLog(@"Network Interface: %@",[NSString stringWithUTF8String:temp_addr->ifa_name]);
				
					// Check if interface is en0 which is the wifi connection on the iPhone
				if([[NSString stringWithUTF8String:temp_addr->ifa_name] isEqualToString:networkInterfaceRef])
				  {
					if(ipVersion == 4)
					  {
						s4 = (struct sockaddr_in *)temp_addr->ifa_addr;

						if (inet_ntop(temp_addr->ifa_addr->sa_family, (void *)&(s4->sin_addr), buf, sizeof(buf)) == NULL)
						  {
							NSLog(@"%s: inet_ntop failed for v4!\n",temp_addr->ifa_name);
						  }
						else{
							address = [NSString stringWithUTF8String:buf];
						}
					  }
					if (ipVersion == 6)
					  {
						s6 = (struct sockaddr_in6 *)(temp_addr->ifa_addr);

						if (inet_ntop(temp_addr->ifa_addr->sa_family, (void *)&(s6->sin6_addr), buf, sizeof(buf)) == NULL)
						  {
							NSLog(@"%s: inet_ntop failed for v6!\n",temp_addr->ifa_name);
						  }
						else{
							address = [NSString stringWithUTF8String:buf];
						}
					  }
				  }
			  }
			
			temp_addr = temp_addr->ifa_next;
		  }
	  }
	
		// Free memory
	freeifaddrs(interfaces);
	return address;
}

</source>


NB: this code will work with the Simulator if my Macbook is connected via Ethernet, but if I use Wifi I must change "en0" into "en1"

Method for IPv4 and IPv6 on Mac OS X

The previous code should work on Mac OS X as well, but NSHost is a lot more convenient.

References