List device's names in the local network - ios

I'm able to fetch connected devices IP and their MAC address and also would like to fetch the device's names and services(open ports).
Can somebody please help me with this?

Here is sample project that can be helpful An iOS Local Area Network / wifi Scanner
Also u can try to use Bonjour
And here - even more regarding name of device in lan
I Found few variants:
1.
struct hostent *he;
struct in_addr ipv4addr;
inet_pton(AF_INET, [address UTF8String], &ipv4addr);
he = gethostbyaddr(&ipv4addr, sizeof ipv4addr, AF_INET);
if (he) {
printf("Host name: %s\n", he->h_name);
}
where [address UTF8String] - like 127.0.0.1 (ip)
2.
- (NSArray *)hostnamesForAddress:(NSString *)address {
// Get the host reference for the given address.
struct addrinfo hints;
struct addrinfo *result = NULL;
memset(&hints, 0, sizeof(hints));
hints.ai_flags = AI_NUMERICHOST;
hints.ai_family = PF_UNSPEC; /* Allow IPv4 or IPv6 */
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = 0;
hints.ai_canonname = NULL;
hints.ai_addr = NULL;
hints.ai_next = NULL;
int errorStatus = getaddrinfo([address cStringUsingEncoding:NSASCIIStringEncoding], NULL, &hints, &result);
if (errorStatus != 0) return #[[self getErrorDescription:errorStatus]];
CFDataRef addressRef = CFDataCreate(NULL, (UInt8 *)result->ai_addr, result->ai_addrlen);
if (addressRef == nil) return nil;
freeaddrinfo(result);
CFHostRef hostRef = CFHostCreateWithAddress(kCFAllocatorDefault, addressRef);
if (hostRef == nil) return nil;
CFRelease(addressRef);
BOOL isSuccess = CFHostStartInfoResolution(hostRef, kCFHostNames, NULL);
if (!isSuccess) return nil;
// Get the hostnames for the host reference.
CFArrayRef hostnamesRef = CFHostGetNames(hostRef, NULL);
NSMutableArray *hostnames = [NSMutableArray array];
for (int currentIndex = 0; currentIndex < [(__bridge NSArray *)hostnamesRef count]; currentIndex++) {
[hostnames addObject:[(__bridge NSArray *)hostnamesRef objectAtIndex:currentIndex]];
}
return hostnames;
}
- (NSString *)getErrorDescription:(NSInteger)errorCode
{
NSString *errorDescription = #"";;
switch (errorCode) {
case EAI_ADDRFAMILY: {
errorDescription = #" address family for hostname not supported";
break;
}
case EAI_AGAIN: {
errorDescription = #" temporary failure in name resolution";
break;
}
case EAI_BADFLAGS: {
errorDescription = #" invalid value for ai_flags";
break;
}
case EAI_FAIL: {
errorDescription = #" non-recoverable failure in name resolution";
break;
}
case EAI_FAMILY: {
errorDescription = #" ai_family not supported";
break;
}
case EAI_MEMORY: {
errorDescription = #" memory allocation failure";
break;
}
case EAI_NODATA: {
errorDescription = #" no address associated with hostname";
break;
}
case EAI_NONAME: {
errorDescription = #" hostname nor servname provided, or not known";
break;
}
case EAI_SERVICE: {
errorDescription = #" servname not supported for ai_socktype";
break;
}
case EAI_SOCKTYPE: {
errorDescription = #" ai_socktype not supported";
break;
}
case EAI_SYSTEM: {
errorDescription = #" system error returned in errno";
break;
}
case EAI_BADHINTS: {
errorDescription = #" invalid value for hints";
break;
}
case EAI_PROTOCOL: {
errorDescription = #" resolved protocol is unknown";
break;
}
case EAI_OVERFLOW: {
errorDescription = #" argument buffer overflow";
break;
}
}
return errorDescription;
}
3.
Additional info u can get from getifaddrs(&interfaces) where struct ifaddrs* interfaces like
unsigned char *ptr;
ptr = (unsigned char *)LLADDR((struct sockaddr_dl *)(temp_addr)->ifa_addr);
NSString *ip = [NSString stringWithUTF8String: inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr)];
NSArray *hostsNames = [self hostnamesForAddress:ip];
NSMutableDictionary *info = [NSMutableDictionary dictionaryWithDictionary:
#{
#"name": #(temp_addr->ifa_name),
#"flags": #(temp_addr->ifa_flags),
#"ip" : ip,
#"family": #(temp_addr->ifa_addr->sa_family),
#"mac" : [NSString stringWithFormat:#"MAC[%02x:%02x:%02x:%02x:%02x:%02x]", *ptr, *(ptr+1), *(ptr+2), *(ptr+3), *(ptr+4), *(ptr+5)],
#"hostName" : hostsNames.count ? hostsNames : #""
}
];
As result u will get something like:
{
family = 2;
flags = 32841;
hostName = (
localhost
);
ip = "127.0.0.1";
mac = "MAC[00:00:00:00:00:00]";
name = lo0;
}
{
family = 18;
flags = 34915;
hostName = ""; //here empty due to one of the following problem or due to CFHostStartInfoResolution return NO - o this point required a little bit more works to be done
ip = "6.3.6.0";
mac = "MAC[02:00:00:00:00:00]";
name = en1;
}
Also this post very interesting and may be useful (I will investigate it later)
Some info that can be helpful regarding ifa_name (interfaces)
// pdp_ip - interfaces are those that are used for 3G and cellular data
// lo = localhost
// en = ether
// eth - ethernet
// wlan, ww, wl - Wifi - Wireless LAN
// awdl - ???
// utun - ???
// ap - is used to represent currently active data connection, Wi-Fi, cellular data or bluetooth or for access point
// bridge - Active hotSpot connection
// sl -- serial line IP (slip)

Related

Apps are reviewed on an IPv6 network. Please ensure that your app supports IPv6 networks, as IPv6 compatibility is required

I have received the following rejection from Apple for my app the last couple of days. My app communicates with UDP and the remote server is always IPv4. I have used BSD sockets. Please guide me how can I solve this problem.
I have tried to create a NAT64 hotspot using an IPv4 network but I was unable to send any packets to the server. Moreover, we don't have IPv6 available at my place now.
From Apple:
2.2 Details
We discovered one or more bugs in your app when reviewed on an iPad running iOS 9.3.2 and iPhone running iOS 9.3.2 on both Wi-Fi and cellular networks.
Specifically, during review we were unable to bypass the Initializing page. We encountered an error while waiting for the app to load. We've attached a screenshot for your reference.
Next Steps
Please run your app on a device to identify the issue(s), then revise and resubmit your app for review.
Apps are reviewed on an IPv6 network. Please ensure that your app supports IPv6 networks, as IPv6 compatibility is required.
For additional information about supporting IPv6 Networks, please refer to Supporting iPv6 DNS64/NAT64 Networks.
Source Code Bellow:
UdpSocketManager.h >>
#ifndef UDP_SOCKET_MANAGER_H__
#define UDP_SOCKET_MANAGER_H__
#import "TInetAddr.h"
class UdpSocketManager
{
public:
UdpSocketManager();
~UdpSocketManager();
void getLocalAddress();
void initializeSocket();
void start();
void stop();
void sendSignal(int p_type, TInetAddr *p_destAddress, unsigned char *p_data, int p_length);
void receiveSignal();
int localPort;
int signalingSocket;
int signalSocketRecvLength;
int socketFamily;
int isIPV4Available;
int isIPV6Available;
char wifiIP[INET_ADDRSTRLEN];
char cellularIP[INET_ADDRSTRLEN];
char wifiIP_v6[INET6_ADDRSTRLEN];
char cellularIP_v6[INET6_ADDRSTRLEN];
long returnLength;
struct sockaddr_in remoteAddrForRecv;
struct sockaddr_in srcAddrV4;
struct sockaddr_in6 srcAddrV6;
struct sockaddr_in sendAddr4;
struct sockaddr_in6 sendAddr6;
bool running;
pthread_t thread;
};
#endif
UdpSocketManager.m >>
#include <string.h>
#include <pthread.h>
#include <ifaddrs.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include "UdpSocketManager.h"
#import <Foundation/Foundation.h>
unsigned int ipAddressToUnsignedInt(char *ipAddress)
{
unsigned int ipAddressLongValue = 0L;
int byteSegment = 0;
for(int i = 0; i < strlen(ipAddress); i++)
{
char ch = ipAddress[i];
if(ch == '.')
{
ipAddressLongValue <<= 8;
ipAddressLongValue |= byteSegment;
byteSegment = 0;
}
else
{
byteSegment = byteSegment * 10 + (ch - 48);
}
}
ipAddressLongValue <<= 8;
ipAddressLongValue |= byteSegment;
return ipAddressLongValue;
}
int custom_random(int max=65535)
{
int randomValue;
randomValue = arc4random_uniform(65535)%max;
return randomValue;
}
int custom_random(int min, int max)
{
int randomValue;
randomValue = arc4random_uniform(max);
if(randomValue<min)
randomValue=(min+custom_random(max-min));
return randomValue;
}
void* runUdpSocketManager(void *objRef)
{
UdpSocketManager *THIS = (UdpSocketManager *) objRef;
THIS->running=true;
while (THIS->running)
{
THIS->receiveSignal();
}
pthread_exit(NULL);
return 0;
}
UdpSocketManager::UdpSocketManager()
{
socketFamily=AF_INET;
signalingSocket=-1;
running=false;
initializeSocket();
}
UdpSocketManager::~UdpSocketManager()
{
}
void UdpSocketManager::getLocalAddress()
{
//Read local address
getLocalAddress();
struct ifaddrs *interfaces = NULL;
struct ifaddrs *temp_addr = NULL;
int success=0;
isIPV4Available=FALSE;
isIPV6Available=FALSE;
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)
{
if([[NSString stringWithUTF8String:temp_addr->ifa_name] hasPrefix:#"en"])
{
isIPV4Available=TRUE;
strcpy(wifiIP, inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr));
printf("IP Address: %s\n",inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr));
}
else if([[NSString stringWithUTF8String:temp_addr->ifa_name] hasPrefix:#"pdp_ip0"])
{
isIPV4Available=TRUE;
strcpy(cellularIP, inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr));
printf("IP Address: %s\n",inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr));
}
}
else if(temp_addr->ifa_addr->sa_family==AF_INET6)
{
if([[NSString stringWithUTF8String:temp_addr->ifa_name] hasPrefix:#"en"])
{
isIPV6Available=TRUE;
inet_ntop(AF_INET6, &(((struct sockaddr_in6 *)temp_addr->ifa_addr)->sin6_addr), (char*)wifiIP_v6, INET6_ADDRSTRLEN);
printf("Interface: %s IPV6: %s\n",temp_addr->ifa_name,wifiIP_v6);
}
else if([[NSString stringWithUTF8String:temp_addr->ifa_name] hasPrefix:#"pdp_ip0"])
{
isIPV6Available=TRUE;
inet_ntop(AF_INET6, &(((struct sockaddr_in6 *)temp_addr->ifa_addr)->sin6_addr), (char*)cellularIP_v6, INET6_ADDRSTRLEN);
printf("Interface: %s IPV6: %s\n",temp_addr->ifa_name,cellularIP_v6);
}
}
temp_addr = temp_addr->ifa_next;
}
}
freeifaddrs(interfaces);
}
void UdpSocketManager::initializeSocket()
{
if(signalingSocket!=-1)
close(signalingSocket);
if (isIPV4Available)
{
if((signalingSocket=socket(AF_INET, SOCK_DGRAM, 0))==-1)
{
NSLog(#"Unable to create signaling socket of AF_INET");
}
else
{
socketFamily=AF_INET;
NSLog(#"Socket created successfully. [AF_INET]");
}
}
else if(!isIPV4Available && isIPV6Available)
{
if((signalingSocket=socket(AF_INET6, SOCK_DGRAM, 0))==-1)
{
NSLog(#"Unable to create signaling socket of AF_INET6");
}
else
{
socketFamily=AF_INET6;
NSLog(#"Socket created successfully. [AF_INET6]");
}
}
else
{
if((signalingSocket=socket(AF_INET, SOCK_DGRAM, 0))==-1)
{
NSLog(#"Unable to create signaling socket of AF_INET");
}
else
{
socketFamily=AF_INET;
NSLog(#"Socket created successfully. [AF_INET]");
}
}
int count=0;
while(true)
{
count++;
if(socketFamily==AF_INET)
{
srcAddrV4.sin_len = sizeof(srcAddrV4);
srcAddrV4.sin_family = socketFamily;
srcAddrV4.sin_addr.s_addr = INADDR_ANY;
srcAddrV4.sin_port = htons(localPort);
if (bind(signalingSocket, (struct sockaddr *) &srcAddrV4, sizeof(srcAddrV4)) < 0)
{
NSLog(#"[AF_INET] ERROR occured creating signaling port at attempt (%d) Port: %d", count, localPort);
localPort=(int)custom_random(1024, 65535);
}
else
{
int on=1;
setsockopt(signalingSocket, SOL_SOCKET, SO_NOSIGPIPE, (void *)&on, sizeof(on));
setsockopt(signalingSocket, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on));
NSLog(#"[AF_INET] SignalingSocket Created Successfully at attempt (%d) Port: %d\n", count, localPort);
break;
}
}
else
{
srcAddrV6.sin6_len = sizeof(srcAddrV6);
srcAddrV6.sin6_family = socketFamily;
srcAddrV6.sin6_addr = in6addr_any;
srcAddrV6.sin6_port = htons(localPort);
if (bind(signalingSocket, (struct sockaddr *) &srcAddrV6, sizeof(srcAddrV6)) < 0)
{
NSLog(#"[AF_INET] ERROR occured creating signaling port at attempt (%d) Port: %d", count, localPort);
localPort=(int)custom_random(1024, 65535);
}
else
{
int on=1;
setsockopt(signalingSocket, SOL_SOCKET, SO_NOSIGPIPE, (void *)&on, sizeof(on));
setsockopt(signalingSocket, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on));
NSLog(#"[AF_INET6] SignalingSocket Created Successfully at attempt (%d) Port: %d\n", count, localPort);
break;
}
}
}
}
void UdpSocketManager::start()
{
pthread_create(&thread, NULL, runUdpSocketManager, (void *) this);
}
void UdpSocketManager::stop()
{
running=false;
}
void UdpSocketManager::receiveSignal()
{
int port;
char ipAddress[16];
socklen_t fromlen;
unsigned char udpSignalRecvBuffer[1600];
fromlen = sizeof(remoteAddrForRecv);
signalSocketRecvLength = (int)recvfrom(signalingSocket, (char *)udpSignalRecvBuffer,1600,0,(struct sockaddr *)&remoteAddrForRecv,&fromlen);
if(signalSocketRecvLength>0)
{
strcpy(ipAddress, inet_ntoa(remoteAddrForRecv.sin_addr));
port = ntohs(remoteAddrForRecv.sin_port);
NSLog(#"RECEIVED %d bytes from %s:%d", signalSocketRecvLength, ipAddress, port);
}
else
{
usleep(10000);// 10 ms
}
}
void UdpSocketManager::sendSignal(int p_type, TInetAddr *p_destAddress, unsigned char *p_data, int p_length)
{
if(socketFamily==AF_INET6)
{
// Convert IPv4 address to IPv4-mapped-into-IPv6 address.
sendAddr6.sin6_family = AF_INET6;
sendAddr6.sin6_port = p_destAddress->m_port;
sendAddr6.sin6_addr.__u6_addr.__u6_addr32[0] = 0;
sendAddr6.sin6_addr.__u6_addr.__u6_addr32[1] = 0;
sendAddr6.sin6_addr.__u6_addr.__u6_addr32[2] = htonl(0xffff);
sendAddr6.sin6_addr.__u6_addr.__u6_addr32[3] = ntohl(ipAddressToUnsignedInt(p_destAddress->m_address));
sendAddr6.sin6_addr.__u6_addr.__u6_addr16[4] = 0;
sendAddr6.sin6_addr.__u6_addr.__u6_addr16[5] = 0xffff;
char ipV6Address[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, &sendAddr6.sin6_addr, ipV6Address, INET6_ADDRSTRLEN);
NSLog(#"ipV6Address: %s\n", ipV6Address);
sendAddr6.sin6_flowinfo = 0;
sendAddr6.sin6_scope_id = 0;
}
else
{
sendAddr4.sin_family = AF_INET;
sendAddr4.sin_port = htons(p_destAddress->m_port);
if(inet_aton((char *) p_destAddress->m_address, &sendAddr4.sin_addr)==0)
{
NSLog(#"signal message - inet_aton() failed, %s", p_destAddress->m_address);
}
}
if(socketFamily==AF_INET)
returnLength=sendto(signalingSocket, p_data, p_length, 0, (struct sockaddr *)&sendAddr4, sizeof(sendAddr4));
else
returnLength=sendto(signalingSocket, p_data, p_length, 0, (struct sockaddr *)&sendAddr6, sizeof(sendAddr6));
NSLog(#"SENT %ld bytes to %s:%d\n", returnLength,p_destAddress->m_address,p_destAddress->m_port);
}
I don't think your "Convert IPv4 address to IPv4-mapped-into-IPv6 address" is correct. Rather than trying to construct an address yourself, you should call getaddrinfo() with a string of the thing you want to connect to (which could be either a hostname or an IPv4 address literal), and it will return to you a list of sockaddrs; you should use the first one from there to pass to sendto. It will give you the appropriate IP address family to use, and if you give an IPv4 address and it is an IPv6-only network (without you having to test anything), it will automatically give you the correct IPv6 address to use for that NAT64 router (without you needing to figure this out yourself). (If you wanted to manually construct an IPv6 address from IPv4 using NAT64/DNS64 without using getaddrinfo(), you would have to follow the complicated procedure in RFC 7050.)
Also, all the things you are doing in getLocalAddress() is unnecessary and potentially leads to more problems. You don't need isIPV4Available or isIPV6Available -- you shouldn't care at that point. Just create and bind both an IPv4 and an IPv6 socket in the beginning (not needing to care which one works), and each time you need to send, you get the right sockaddr to use using getaddrinfo() as above, and then send to the socket whose address family corresponds to the sockaddr you are using. And when you want to receive, you call recvfrom on both sockets.
I see several problems with the code you have shown:
UdpSocketManager does not call getLocalAddress() before calling initializeSocket(), so the binding socket is always IPv4, never IPv6. You are also not initializing localPort before calling initializeSocket(), either.
getLocalAddress() (if ever called) calls itself, so you have an endless recursion loop.
The use of custom_random() in a loop to pick a random binding port is just plain wrong, unnecessary, and potentially unending. To pick a random port when your configured port fails, just call bind() one time with the port set to 0. The OS knows which ports are available and will pick an available random port for you. Your entire initializeSocket() is overly complicated for what it attempts to do. It can be greatly simplified.
When enabling SO_REUSEADDR, it must be enabled before calling bind(), not after. Also look at SO_REUSEPORT.
Your remoteAddrForRecv variable is declared as sockaddr_in, which is only large enough to hold an IPv4 address and will cause recvfrom() to fail if called on an IPv6 socket. Use sockaddr_storage instead. In fact. All of your sockaddr_in and sockaddr_in6 variables should be replaced with sockaddr_storage.
inet_ntoa() is likewise also IPv4-only. Use inet_ntop() instead to handle both IPv4 and IPv6 addresses.
Try something more like this instead:
UdpSocketManager.h
#ifndef UDP_SOCKET_MANAGER_H__
#define UDP_SOCKET_MANAGER_H__
#import "TInetAddr.h"
class UdpSocketManager
{
public:
UdpSocketManager();
~UdpSocketManager();
void getLocalAddresses();
void initializeSocket();
void start();
void stop();
void sendSignal(int p_type, TInetAddr *p_destAddress, unsigned char *p_data, int p_length);
void receiveSignal();
int localPort;
int signalingSocket;
int socketFamily;
int isIPV4Available;
int isIPV6Available;
char wifiIP_v4[INET_ADDRSTRLEN];
char cellularIP_v4[INET_ADDRSTRLEN];
char wifiIP_v6[INET6_ADDRSTRLEN];
char cellularIP_v6[INET6_ADDRSTRLEN];
bool running;
pthread_t thread;
};
#endif
UdpSocketManager.m
#include <string.h>
#include <pthread.h>
#include <ifaddrs.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include "UdpSocketManager.h"
#import <Foundation/Foundation.h>
void* runUdpSocketManager(void *objRef)
{
UdpSocketManager *THIS = (UdpSocketManager *) objRef;
while (THIS->running)
{
THIS->receiveSignal();
}
pthread_exit(NULL);
return 0;
}
UdpSocketManager::UdpSocketManager()
{
socketFamily = AF_INET;
signalingSocket = -1;
localPort = 0; // or whatever port you actual want
srcAddrLen = 0;
sendAddrLen = 0;
running = false;
initializeSocket();
}
UdpSocketManager::~UdpSocketManager()
{
if(signalingSocket != -1)
{
close(signalingSocket);
signalingSocket = -1;
}
}
void UdpSocketManager::getLocalAddresses()
{
//Read local addresses
struct ifaddrs *interfaces = NULL;
struct ifaddrs *temp_addr = NULL;
isIPV4Available = FALSE;
isIPV6Available = FALSE;
memset(&wifiIP_v4, 0, sizeof(wifiIP_v4));
memset(&cellularIP_v4, 0, sizeof(cellularIP_v4));
memset(&wifiIP_v6, 0, sizeof(wifiIP_v6));
memset(&cellularIP_v6, 0, sizeof(cellularIP_v6));
if(getifaddrs(&interfaces) == 0)
{
// Loop through linked list of interfaces
temp_addr = interfaces;
while(temp_addr != NULL)
{
if ([[NSString stringWithUTF8String:temp_addr->ifa_name] hasPrefix:#"en"])
{
if(temp_addr->ifa_addr->sa_family == AF_INET)
{
isIPV4Available = TRUE;
inet_ntop(AF_INET, &(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr), wifiIP_v4, sizeof(wifiIP_v4));
printf("Interface: %s IPv4: %s\n", temp_addr->ifa_name, wifiIP_v4);
}
else if(temp_addr->ifa_addr->sa_family == AF_INET6)
{
isIPV6Available = TRUE;
inet_ntop(AF_INET6, &(((struct sockaddr_in6 *)temp_addr->ifa_addr)->sin6_addr), wifiIP_v6, sizeof(wifiIP_v6));
printf("Interface: %s IPv6: %s\n", temp_addr->ifa_name, wifiIP_v6);
}
}
else if([[NSString stringWithUTF8String:temp_addr->ifa_name] hasPrefix:#"pdp_ip0"])
{
if(temp_addr->ifa_addr->sa_family == AF_INET)
{
isIPV4Available = TRUE;
inet_ntop(AF_INET, &(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr), cellularIP_v4, sizeof(cellularIP_v4));
printf("Interface: %s IPv6: %s\n", temp_addr->ifa_name, cellularIP_v4);
}
else if(temp_addr->ifa_addr->sa_family == AF_INET6)
{
isIPV6Available = TRUE;
inet_ntop(AF_INET6, &(((struct sockaddr_in6 *)temp_addr->ifa_addr)->sin6_addr), cellularIP_v6, sizeof(cellularIP_v6));
printf("Interface: %s IPv6: %s\n", temp_addr->ifa_name, cellularIP_v6);
}
}
temp_addr = temp_addr->ifa_next;
}
freeifaddrs(interfaces);
}
}
void UdpSocketManager::initializeSocket()
{
struct sockaddr_storage srcAddr;
struct sockaddr_in6 *srcAddr6;
struct sockaddr_in *srcAddr4;
socklen_t srcAddrLen;
if(signalingSocket != -1)
{
close(signalingSocket);
signalingSocket = -1;
}
getLocalAddresses();
if(isIPV6Available)
{
signalingSocket = socket(AF_INET6, SOCK_DGRAM, 0);
if(signalingSocket == -1)
{
NSLog(#"Unable to create IPv6 signaling socket");
return;
}
socketFamily = AF_INET6;
NSLog(#"IPv6 Socket created successfully");
}
else
{
signalingSocket = socket(AF_INET, SOCK_DGRAM, 0);
if(signalingSocket == -1)
{
NSLog(#"Unable to create IPv4 signaling socket");
return;
}
socketFamily = AF_INET;
NSLog(#"IPv4 Socket created successfully");
}
int on = 1;
setsockopt(signalingSocket, SOL_SOCKET, SO_NOSIGPIPE, &on, sizeof(on));
setsockopt(signalingSocket, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
if(socketFamily == AF_INET6)
{
on = 0;
setsockopt(signalingSocket, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on));
srcAddr6 = (struct sockaddr_in6 *) &srcAddr;
srcAddrLen = sizeof(sockaddr_in6);
srcAddr6->sin6_len = srcAddrLen;
srcAddr6->sin6_family = socketFamily;
srcAddr6->sin6_addr = in6addr_any;
srcAddr6->sin6_port = htons(localPort);
}
else
{
srcAddr4 = (struct sockaddr_in *) &srcAddr;
srcAddrLen = sizeof(sockaddr_in);
srcAddr4->sin_len = srcAddrLen;
srcAddr4->sin_family = socketFamily;
srcAddr4->sin_addr.s_addr = INADDR_ANY;
srcAddr4->sin_port = htons(localPort);
}
if (bind(signalingSocket, (struct sockaddr *) &srcAddr, srcAddrLen) < 0)
{
if (localPort == 0)
{
NSLog(#"ERROR occured binding random signaling port");
close(signalingSocket);
signalingSocket = -1;
return;
}
NSLog(#"ERROR occured binding signaling port: %d", localPort);
if(socketFamily == AF_INET6)
srcAddr6->sin6_port = 0;
else
srcAddr4->sin_port = 0;
if (bind(signalingSocket, (struct sockaddr *) &srcAddr, srcAddrLen) < 0)
{
NSLog(#"ERROR occured binding random signaling port");
close(signalingSocket);
signalingSocket = -1;
return;
}
getsockname(signalingSocket, (struct sockaddr *) &srcAddr, &srcAddrLen);
if(socketFamily == AF_INET6)
localPort = ntohs(srcAddr6->sin6_port);
else
localPort = ntohs(srcAddr4->sin_port);
}
NSLog(#"SignalingSocket bound successfully on Port: %d\n", localPort);
}
void UdpSocketManager::start()
{
if(signalingSocket != -1)
{
running = true;
pthread_create(&thread, NULL, runUdpSocketManager, this);
}
}
void UdpSocketManager::stop()
{
running = false;
}
void UdpSocketManager::receiveSignal()
{
int port;
char ipAddress[INET6_ADDRSTRLEN];
unsigned char udpSignalRecvBuffer[1600];
ssize_t signalRecvLength;
struct sockaddr_storage remoteAddr;
socklen_t fromlen;
fromlen = sizeof(remoteAddr);
signalRecvLength = recvfrom(signalingSocket, udpSignalRecvBuffer, sizeof(udpSignalRecvBuffer), 0, (struct sockaddr *) &remoteAddr, &fromlen);
if(signalRecvLength >= 0)
{
if(remoteAddrForRecv.ss_family == AF_INET6)
{
struct sockaddr_in6 *remoteAddr6 = (struct sockaddr_in6 *) &remoteAddr;
inet_ntop(AF_INET6, &(remoteAddr6->sin6_addr), ipAddress, sizeof(ipAddress));
port = ntohs(remoteAddr6->sin6_port);
}
else
{
struct sockaddr_in *remoteAddr4 = (struct sockaddr_in4 *) &remoteAddr;
inet_ntop(AF_INET, &(remoteAddr4->sin_addr), ipAddress, sizeof(ipAddress));
port = ntohs(remoteAddr4->sin_port);
}
NSLog(#"RECEIVED %d bytes from %s:%d", signalRecvLength, ipAddress, port);
}
else
{
usleep(10000);// 10 ms
}
}
void UdpSocketManager::sendSignal(int p_type, TInetAddr *p_destAddress, unsigned char *p_data, int p_length)
{
struct sockaddr_storage sendAddr;
socklen_t sendAddrLen;
ssize_t returnLength;
char ipAddress[INET6_ADDRSTRLEN];
if(socketFamily == AF_INET6)
{
struct sockaddr_in6 *sendAddr6 = (struct sockaddr_in6 *) &sendAddr;
sendAddrLen = sizeof(sockaddr_in6);
sendAddr6->sin6_family = AF_INET6;
sendAddr6->sin6_port = htons(p_destAddress->m_port);
// Convert IPv4 address to IPv4-mapped IPv6 address.
sendAddr6->sin6_addr.__u6_addr.__u6_addr32[0] = 0;
sendAddr6->sin6_addr.__u6_addr.__u6_addr32[1] = 0;
sendAddr6->sin6_addr.__u6_addr.__u6_addr16[4] = 0;
sendAddr6->sin6_addr.__u6_addr.__u6_addr16[5] = 0xffff;
sendAddr6->sin6_addr.__u6_addr.__u6_addr32[3] = inet_addr(p_destAddress->m_address);
sendAddr6->sin6_flowinfo = 0;
sendAddr6->sin6_scope_id = 0;
inet_ntop(AF_INET6, &(sendAddr6->sin6_addr), ipAddress, sizeof(ipAddress));
}
else
{
struct sockaddr_in *sendAddr4 = (struct sockaddr_in *) &sendAddr;
sendAddrLen = sizeof(sockaddr_in);
sendAddr4->sin_family = AF_INET;
sendAddr4->sin_port = htons(p_destAddress->m_port);
if(inet_aton((char *) p_destAddress->m_address, &(sendAddr4->sin_addr)) == 0)
{
NSLog(#"signal message - inet_aton() failed, %s", p_destAddress->m_address);
return;
}
inet_ntop(AF_INET, &(sendAddr4->sin_addr), ipAddress, sizeof(ipAddress));
}
returnLength = sendto(signalingSocket, p_data, p_length, 0, (struct sockaddr *) &sendAddr, sendAddrLen);
if(returnLength >= 0)
NSLog(#"SENT %ld bytes to %s:%d\n", returnLength, ipAddress, p_destAddress->m_port);
}
Solution for AFNetworking for reachability in IPv6 and IPv4
change the following code in class AFNetworkReachabilityManager
+ (instancetype)sharedManager {
static AFNetworkReachabilityManager *_sharedManager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
struct sockaddr_in6 address;
bzero(&address, sizeof(address));
address.sin6_len = sizeof(address);
address.sin6_family = AF_INET6;
_sharedManager = [self managerForAddress:&address];
});
return _sharedManager;
}

iOS - How to get the IPv6 DNS IP address?

I can use the code below to get the IPv4 DNS address. With the IPv6 DNS address, res_ninit() can not analyse IPv6 address. Like this, iOS - Get device's DNS server address on IPv6 only network, sin_family is always AF_UNSPEC.
Is there any other solutions to get the IPv6 DNS address? Thanks for help.
+ (void)outPutDNSServers {
res_state res = malloc(sizeof(struct __res_state));
int result = res_ninit(res);
if ( result == 0 ) {
for ( int i = 0; i < res->nscount; i++ ) {
NSString *s = [NSString stringWithUTF8String : inet_ntoa(res->nsaddr_list[i].sin_addr)];
NSLog(#"%#",s);
}
}
else {
NSLog(#"%#",#" res_init result != 0");
}
res_nclose(res);
}
Edit:
I have already solved the problem like below.
+ (void)outPutDNSServers {
res_state res = malloc(sizeof(struct __res_state));
int result = res_ninit(res);
if (result == 0) {
union res_9_sockaddr_union *addr_union = malloc(res->nscount * sizeof(union res_9_sockaddr_union));
res_getservers(res, addr_union, res->nscount);
for (int i = 0; i < res->nscount; i++) {
if (addr_union[i].sin.sin_family == AF_INET) {
char ip[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &(addr_union[i].sin.sin_addr), ip, INET_ADDRSTRLEN);
NSString *dnsIP = [NSString stringWithUTF8String:ip];
NSLog(#"IPv4 DNS IP: %#", dnsIP);
} else if (addr_union[i].sin6.sin6_family == AF_INET6) {
char ip[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, &(addr_union[i].sin6.sin6_addr), ip, INET6_ADDRSTRLEN);
NSString *dnsIP = [NSString stringWithUTF8String:ip];
NSLog(#"IPv6 DNS IP: %#", dnsIP);
} else {
NSLog(#"Undefined family.");
}
}
}
res_nclose(res);
}

iOS Network Stack "What kind of network am I"? [duplicate]

How to get Wi-Fi encryption mode in iOS without private libraries?
The code from the answer above has been posted originally on this website: http://www.codeproject.com/Articles/621213/Non-Standard-Way-to-Get-Inaccessible-Data-from-iOS
By the way, for this code to work you need to include the appropriate header files with #include <mach/mach.h> so that your compiler recognizes NDR_record_t ndr.
However, this whole setup did not actually return me the encryption mode of the current WiFi, but rather the configuration of AirPort (the variable key in the code from above needs to be set to NSString *key = #"Setup:/Network/Interface/en0/AirPort"; before). I tried different values instead of AirPort which I got from running $scutil in the Terminal of my Mac (such as Setup:/Network/Interface/en0/IPv4 or Setup:/Network/Interface/en0/Modem or from this website)
Hope that helps someone having similar issues...
For iOS 5:
aslmsg asl, message;
aslresponse searchResult;
int i;
const char *key, *val;
NSMutableArray *result_dicts = [NSMutableArray array];
asl = asl_new(ASL_TYPE_QUERY);
if (!asl)
{
DDLogCError(#"Failed creating ASL query");
}
asl_set_query(asl, "Sender", "kernel", ASL_QUERY_OP_EQUAL);
asl_set_query(asl, "Message", "AppleBCMWLAN Joined BSS:", ASL_QUERY_OP_PREFIX|ASL_QUERY_OP_EQUAL);
searchResult = asl_search(NULL, asl);
while (NULL != (message = aslresponse_next(searchResult)))
{
NSMutableDictionary *tmpDict = [NSMutableDictionary dictionary];
for (i = 0; (NULL != (key = asl_key(message, i))); i++)
{
NSString *keyString = [NSString stringWithUTF8String:(char *)key];
val = asl_get(message, key);
NSString *string = [NSString stringWithUTF8String:val];
[tmpDict setObject:string forKey:keyString];
}
[result_dicts addObject:tmpDict];
}
aslresponse_free(searchResult);
asl_free(asl);
For iOS 6:
#define kMachPortConfigd "com.apple.SystemConfiguration.configd"
-(NSDictionary *)getSCdata:(NSString *)key
{
if(SYSTEM_VERSION_LESS_THAN(#"6.0"))
{
// It does not work on iOS 5.*
return nil;
}
struct send_body {mach_msg_header_t header; int count; UInt8 *addr; CFIndex size0; int flags; NDR_record_t ndr; CFIndex size; int retB; int rcB; int f24; int f28;};
mach_port_t bootstrapport = MACH_PORT_NULL;
mach_port_t configport = MACH_PORT_NULL;
mach_msg_header_t *msg;
mach_msg_return_t msg_return;
struct send_body send_msg;
// Make request
CFDataRef extRepr;
extRepr = CFStringCreateExternalRepresentation(NULL, (__bridge CFStringRef)(key), kCFStringEncodingUTF8, 0);
// Connect to Mach MIG port of configd
task_get_bootstrap_port(mach_task_self(), &bootstrapport);
bootstrap_look_up2(bootstrapport, kMachPortConfigd, &configport, 0, 8LL);
// Make request
send_msg.count = 1;
send_msg.addr = (UInt8*)CFDataGetBytePtr(extRepr);
send_msg.size0 = CFDataGetLength(extRepr);
send_msg.size = CFDataGetLength(extRepr);
send_msg.flags = 0x1000100u;
send_msg.ndr = NDR_record;
// Make message header
msg = &(send_msg.header);
msg->msgh_bits = 0x80001513u;
msg->msgh_remote_port = configport;
msg->msgh_local_port = mig_get_reply_port();
msg->msgh_id = 20010;
// Request server
msg_return = mach_msg(msg, 3, 0x34u, 0x44u, msg->msgh_local_port, 0, 0);
if(msg_return)
{
if (msg_return - 0x10000002u >= 2 && msg_return != 0x10000010 )
{
mig_dealloc_reply_port(msg->msgh_local_port);
}
else
{
mig_put_reply_port(msg->msgh_local_port);
}
}
else if ( msg->msgh_id != 71 && msg->msgh_id == 20110 && msg->msgh_bits <= -1 )
{
if ((send_msg.flags & 0xFF000000) == 0x1000000)
{
CFDataRef deserializedData = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, send_msg.addr,send_msg.size0, kCFAllocatorNull);
CFPropertyListRef proplist = CFPropertyListCreateWithData(kCFAllocatorDefault, deserializedData, kCFPropertyListImmutable, NULL, NULL);
mig_dealloc_reply_port(msg->msgh_local_port);
mach_port_deallocate(mach_task_self(), bootstrapport);
mach_port_deallocate(mach_task_self(), configport);
mach_msg_destroy(msg);
NSDictionary *property_list = (__bridge NSDictionary*)proplist;
if(proplist)
CFRelease(proplist);
CFRelease(deserializedData);
CFRelease(extRepr);
return property_list;
}
}
mig_dealloc_reply_port(msg->msgh_local_port);
mach_port_deallocate(mach_task_self(), bootstrapport);
mach_port_deallocate(mach_task_self(), configport);
mach_msg_destroy(msg);
CFRelease(extRepr);
return nil;
}

How to get WiFi encryption mode on iOS/iPhone/iPad?

How to get Wi-Fi encryption mode in iOS without private libraries?
The code from the answer above has been posted originally on this website: http://www.codeproject.com/Articles/621213/Non-Standard-Way-to-Get-Inaccessible-Data-from-iOS
By the way, for this code to work you need to include the appropriate header files with #include <mach/mach.h> so that your compiler recognizes NDR_record_t ndr.
However, this whole setup did not actually return me the encryption mode of the current WiFi, but rather the configuration of AirPort (the variable key in the code from above needs to be set to NSString *key = #"Setup:/Network/Interface/en0/AirPort"; before). I tried different values instead of AirPort which I got from running $scutil in the Terminal of my Mac (such as Setup:/Network/Interface/en0/IPv4 or Setup:/Network/Interface/en0/Modem or from this website)
Hope that helps someone having similar issues...
For iOS 5:
aslmsg asl, message;
aslresponse searchResult;
int i;
const char *key, *val;
NSMutableArray *result_dicts = [NSMutableArray array];
asl = asl_new(ASL_TYPE_QUERY);
if (!asl)
{
DDLogCError(#"Failed creating ASL query");
}
asl_set_query(asl, "Sender", "kernel", ASL_QUERY_OP_EQUAL);
asl_set_query(asl, "Message", "AppleBCMWLAN Joined BSS:", ASL_QUERY_OP_PREFIX|ASL_QUERY_OP_EQUAL);
searchResult = asl_search(NULL, asl);
while (NULL != (message = aslresponse_next(searchResult)))
{
NSMutableDictionary *tmpDict = [NSMutableDictionary dictionary];
for (i = 0; (NULL != (key = asl_key(message, i))); i++)
{
NSString *keyString = [NSString stringWithUTF8String:(char *)key];
val = asl_get(message, key);
NSString *string = [NSString stringWithUTF8String:val];
[tmpDict setObject:string forKey:keyString];
}
[result_dicts addObject:tmpDict];
}
aslresponse_free(searchResult);
asl_free(asl);
For iOS 6:
#define kMachPortConfigd "com.apple.SystemConfiguration.configd"
-(NSDictionary *)getSCdata:(NSString *)key
{
if(SYSTEM_VERSION_LESS_THAN(#"6.0"))
{
// It does not work on iOS 5.*
return nil;
}
struct send_body {mach_msg_header_t header; int count; UInt8 *addr; CFIndex size0; int flags; NDR_record_t ndr; CFIndex size; int retB; int rcB; int f24; int f28;};
mach_port_t bootstrapport = MACH_PORT_NULL;
mach_port_t configport = MACH_PORT_NULL;
mach_msg_header_t *msg;
mach_msg_return_t msg_return;
struct send_body send_msg;
// Make request
CFDataRef extRepr;
extRepr = CFStringCreateExternalRepresentation(NULL, (__bridge CFStringRef)(key), kCFStringEncodingUTF8, 0);
// Connect to Mach MIG port of configd
task_get_bootstrap_port(mach_task_self(), &bootstrapport);
bootstrap_look_up2(bootstrapport, kMachPortConfigd, &configport, 0, 8LL);
// Make request
send_msg.count = 1;
send_msg.addr = (UInt8*)CFDataGetBytePtr(extRepr);
send_msg.size0 = CFDataGetLength(extRepr);
send_msg.size = CFDataGetLength(extRepr);
send_msg.flags = 0x1000100u;
send_msg.ndr = NDR_record;
// Make message header
msg = &(send_msg.header);
msg->msgh_bits = 0x80001513u;
msg->msgh_remote_port = configport;
msg->msgh_local_port = mig_get_reply_port();
msg->msgh_id = 20010;
// Request server
msg_return = mach_msg(msg, 3, 0x34u, 0x44u, msg->msgh_local_port, 0, 0);
if(msg_return)
{
if (msg_return - 0x10000002u >= 2 && msg_return != 0x10000010 )
{
mig_dealloc_reply_port(msg->msgh_local_port);
}
else
{
mig_put_reply_port(msg->msgh_local_port);
}
}
else if ( msg->msgh_id != 71 && msg->msgh_id == 20110 && msg->msgh_bits <= -1 )
{
if ((send_msg.flags & 0xFF000000) == 0x1000000)
{
CFDataRef deserializedData = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, send_msg.addr,send_msg.size0, kCFAllocatorNull);
CFPropertyListRef proplist = CFPropertyListCreateWithData(kCFAllocatorDefault, deserializedData, kCFPropertyListImmutable, NULL, NULL);
mig_dealloc_reply_port(msg->msgh_local_port);
mach_port_deallocate(mach_task_self(), bootstrapport);
mach_port_deallocate(mach_task_self(), configport);
mach_msg_destroy(msg);
NSDictionary *property_list = (__bridge NSDictionary*)proplist;
if(proplist)
CFRelease(proplist);
CFRelease(deserializedData);
CFRelease(extRepr);
return property_list;
}
}
mig_dealloc_reply_port(msg->msgh_local_port);
mach_port_deallocate(mach_task_self(), bootstrapport);
mach_port_deallocate(mach_task_self(), configport);
mach_msg_destroy(msg);
CFRelease(extRepr);
return nil;
}

How can I programmatically get the MAC address of an iphone

How to programmatically get an iPhone's MAC address and IP address?
NOTE As of iOS7, you can no longer retrieve device MAC addresses. A fixed value will be returned rather than the actual MAC
Somthing I stumbled across a while ago. Originally from here I modified it a bit and cleaned things up.
IPAddress.h
IPAddress.c
And to use it
InitAddresses();
GetIPAddresses();
GetHWAddresses();
int i;
NSString *deviceIP = nil;
for (i=0; i<MAXADDRS; ++i)
{
static unsigned long localHost = 0x7F000001; // 127.0.0.1
unsigned long theAddr;
theAddr = ip_addrs[i];
if (theAddr == 0) break;
if (theAddr == localHost) continue;
NSLog(#"Name: %s MAC: %s IP: %s\n", if_names[i], hw_addrs[i], ip_names[i]);
//decided what adapter you want details for
if (strncmp(if_names[i], "en", 2) == 0)
{
NSLog(#"Adapter en has a IP of %s", ip_names[i]);
}
}
Adapter names vary depending on the simulator/device as well as wifi or cell on the device.
Update: this will not work on iOS 7. You should use ASIdentifierManager.
More clean solution on MobileDeveloperTips website:
#include <sys/socket.h>
#include <sys/sysctl.h>
#include <net/if.h>
#include <net/if_dl.h>
...
- (NSString *)getMacAddress
{
int mgmtInfoBase[6];
char *msgBuffer = NULL;
size_t length;
unsigned char macAddress[6];
struct if_msghdr *interfaceMsgStruct;
struct sockaddr_dl *socketStruct;
NSString *errorFlag = NULL;
// Setup the management Information Base (mib)
mgmtInfoBase[0] = CTL_NET; // Request network subsystem
mgmtInfoBase[1] = AF_ROUTE; // Routing table info
mgmtInfoBase[2] = 0;
mgmtInfoBase[3] = AF_LINK; // Request link layer information
mgmtInfoBase[4] = NET_RT_IFLIST; // Request all configured interfaces
// With all configured interfaces requested, get handle index
if ((mgmtInfoBase[5] = if_nametoindex("en0")) == 0)
errorFlag = #"if_nametoindex failure";
else
{
// Get the size of the data available (store in len)
if (sysctl(mgmtInfoBase, 6, NULL, &length, NULL, 0) < 0)
errorFlag = #"sysctl mgmtInfoBase failure";
else
{
// Alloc memory based on above call
if ((msgBuffer = malloc(length)) == NULL)
errorFlag = #"buffer allocation failure";
else
{
// Get system information, store in buffer
if (sysctl(mgmtInfoBase, 6, msgBuffer, &length, NULL, 0) < 0)
errorFlag = #"sysctl msgBuffer failure";
}
}
}
// Befor going any further...
if (errorFlag != NULL)
{
NSLog(#"Error: %#", errorFlag);
return errorFlag;
}
// Map msgbuffer to interface message structure
interfaceMsgStruct = (struct if_msghdr *) msgBuffer;
// Map to link-level socket structure
socketStruct = (struct sockaddr_dl *) (interfaceMsgStruct + 1);
// Copy link layer address data in socket structure to an array
memcpy(&macAddress, socketStruct->sdl_data + socketStruct->sdl_nlen, 6);
// Read from char array into a string object, into traditional Mac address format
NSString *macAddressString = [NSString stringWithFormat:#"%02X:%02X:%02X:%02X:%02X:%02X",
macAddress[0], macAddress[1], macAddress[2],
macAddress[3], macAddress[4], macAddress[5]];
NSLog(#"Mac Address: %#", macAddressString);
// Release the buffer memory
free(msgBuffer);
return macAddressString;
}
I wanted something to return the address regardless of whether or not wifi was enabled, so the chosen solution didn't work for me. I used another call I found on some forum after some tweaking. I ended up with the following (excuse my rusty C ) :
#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <net/if_dl.h>
#include <ifaddrs.h>
char* getMacAddress(char* macAddress, char* ifName) {
int success;
struct ifaddrs * addrs;
struct ifaddrs * cursor;
const struct sockaddr_dl * dlAddr;
const unsigned char* base;
int i;
success = getifaddrs(&addrs) == 0;
if (success) {
cursor = addrs;
while (cursor != 0) {
if ( (cursor->ifa_addr->sa_family == AF_LINK)
&& (((const struct sockaddr_dl *) cursor->ifa_addr)->sdl_type == IFT_ETHER) && strcmp(ifName, cursor->ifa_name)==0 ) {
dlAddr = (const struct sockaddr_dl *) cursor->ifa_addr;
base = (const unsigned char*) &dlAddr->sdl_data[dlAddr->sdl_nlen];
strcpy(macAddress, "");
for (i = 0; i < dlAddr->sdl_alen; i++) {
if (i != 0) {
strcat(macAddress, ":");
}
char partialAddr[3];
sprintf(partialAddr, "%02X", base[i]);
strcat(macAddress, partialAddr);
}
}
cursor = cursor->ifa_next;
}
freeifaddrs(addrs);
}
return macAddress;
}
And then I would call it asking for en0, as follows:
char* macAddressString= (char*)malloc(18);
NSString* macAddress= [[NSString alloc] initWithCString:getMacAddress(macAddressString, "en0")
encoding:NSMacOSRomanStringEncoding];
free(macAddressString);
Starting from iOS 7, the system always returns the value 02:00:00:00:00:00 when you ask for the MAC address on any device.
In iOS 7 and later, if you ask for the MAC address of an iOS device, the system returns the value 02:00:00:00:00:00. If you need to identify the device, use the identifierForVendor property of UIDevice instead. (Apps that need an identifier for their own advertising purposes should consider using the advertisingIdentifier property of ASIdentifierManager instead.)"
Reference: releasenotes
There are vary solutions about this, but I couldn't find a whole thing.
So I made my own solution for :
nicinfo
How to use :
NICInfoSummary* summary = [[[NICInfoSummary alloc] init] autorelease];
// en0 is for WiFi
NICInfo* wifi_info = [summary findNICInfo:#"en0"];
// you can get mac address in 'XX-XX-XX-XX-XX-XX' form
NSString* mac_address = [wifi_info getMacAddressWithSeparator:#"-"];
// ip can be multiple
if(wifi_info.nicIPInfos.count > 0)
{
NICIPInfo* ip_info = [wifi_info.nicIPInfos objectAtIndex:0];
NSString* ip = ip_info.ip;
NSString* netmask = ip_info.netmask;
NSString* broadcast_ip = ip_info.broadcastIP;
}
else
{
NSLog(#"WiFi not connected!");
}
This looks like a pretty clean solution: UIDevice BIdentifier
// Return the local MAC addy
// Courtesy of FreeBSD hackers email list
// Accidentally munged during previous update. Fixed thanks to erica sadun & mlamb.
- (NSString *) macaddress{
int mib[6];
size_t len;
char *buf;
unsigned char *ptr;
struct if_msghdr *ifm;
struct sockaddr_dl *sdl;
mib[0] = CTL_NET;
mib[1] = AF_ROUTE;
mib[2] = 0;
mib[3] = AF_LINK;
mib[4] = NET_RT_IFLIST;
if ((mib[5] = if_nametoindex("en0")) == 0) {
printf("Error: if_nametoindex error\n");
return NULL;
}
if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) {
printf("Error: sysctl, take 1\n");
return NULL;
}
if ((buf = malloc(len)) == NULL) {
printf("Could not allocate memory. error!\n");
return NULL;
}
if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) {
printf("Error: sysctl, take 2");
free(buf);
return NULL;
}
ifm = (struct if_msghdr *)buf;
sdl = (struct sockaddr_dl *)(ifm + 1);
ptr = (unsigned char *)LLADDR(sdl);
NSString *outstring = [NSString stringWithFormat:#"%02X:%02X:%02X:%02X:%02X:%02X",
*ptr, *(ptr+1), *(ptr+2), *(ptr+3), *(ptr+4), *(ptr+5)];
free(buf);
return outstring;
}
Now iOS 7 devices – are always returning a MAC address of 02:00:00:00:00:00.
So better use [UIDevice identifierForVendor].
so better to call this method to get app specific unique key
Category will more suitable
import "UIDevice+Identifier.h"
- (NSString *) identifierForVendor1
{
if ([[UIDevice currentDevice] respondsToSelector:#selector(identifierForVendor)]) {
return [[[UIDevice currentDevice] identifierForVendor] UUIDString];
}
return #"";
}
Now call above method to get unique address
NSString *like_UDID=[NSString stringWithFormat:#"%#",
[[UIDevice currentDevice] identifierForVendor1]];
NSLog(#"%#",like_UDID);
#Grantland
This "pretty clean solution" looks similar to my own improvement over iPhoneDeveloperTips solution.
You can see my step here:
https://gist.github.com/1409855/
/* Original source code courtesy John from iOSDeveloperTips.com */
#include <sys/socket.h>
#include <sys/sysctl.h>
#include <net/if.h>
#include <net/if_dl.h>
+ (NSString *)getMacAddress
{
int mgmtInfoBase[6];
char *msgBuffer = NULL;
NSString *errorFlag = NULL;
size_t length;
// Setup the management Information Base (mib)
mgmtInfoBase[0] = CTL_NET; // Request network subsystem
mgmtInfoBase[1] = AF_ROUTE; // Routing table info
mgmtInfoBase[2] = 0;
mgmtInfoBase[3] = AF_LINK; // Request link layer information
mgmtInfoBase[4] = NET_RT_IFLIST; // Request all configured interfaces
// With all configured interfaces requested, get handle index
if ((mgmtInfoBase[5] = if_nametoindex("en0")) == 0)
errorFlag = #"if_nametoindex failure";
// Get the size of the data available (store in len)
else if (sysctl(mgmtInfoBase, 6, NULL, &length, NULL, 0) < 0)
errorFlag = #"sysctl mgmtInfoBase failure";
// Alloc memory based on above call
else if ((msgBuffer = malloc(length)) == NULL)
errorFlag = #"buffer allocation failure";
// Get system information, store in buffer
else if (sysctl(mgmtInfoBase, 6, msgBuffer, &length, NULL, 0) < 0)
{
free(msgBuffer);
errorFlag = #"sysctl msgBuffer failure";
}
else
{
// Map msgbuffer to interface message structure
struct if_msghdr *interfaceMsgStruct = (struct if_msghdr *) msgBuffer;
// Map to link-level socket structure
struct sockaddr_dl *socketStruct = (struct sockaddr_dl *) (interfaceMsgStruct + 1);
// Copy link layer address data in socket structure to an array
unsigned char macAddress[6];
memcpy(&macAddress, socketStruct->sdl_data + socketStruct->sdl_nlen, 6);
// Read from char array into a string object, into traditional Mac address format
NSString *macAddressString = [NSString stringWithFormat:#"%02X:%02X:%02X:%02X:%02X:%02X",
macAddress[0], macAddress[1], macAddress[2], macAddress[3], macAddress[4], macAddress[5]];
NSLog(#"Mac Address: %#", macAddressString);
// Release the buffer memory
free(msgBuffer);
return macAddressString;
}
// Error...
NSLog(#"Error: %#", errorFlag);
return nil;
}
It's not possible anymore on devices running iOS 7.0 or later, thus unavailable to get MAC address in Swift.
As Apple stated:
In iOS 7 and later, if you ask for the MAC address of an iOS device, the system returns the value 02:00:00:00:00:00. If you need to identify the device, use the identifierForVendor property of UIDevice instead. (Apps that need an identifier for their own advertising purposes should consider using the advertisingIdentifier property of ASIdentifierManager instead.)
#import <sys/socket.h>
#import <net/if_dl.h>
#import <ifaddrs.h>
#import <sys/xattr.h>
#define IFT_ETHER 0x6
...
- (NSString*)macAddress
{
NSString* result = nil;
char* macAddressString = (char*)malloc(18);
if (macAddressString != NULL)
{
strcpy(macAddressString, "");
struct ifaddrs* addrs = NULL;
struct ifaddrs* cursor;
if (getifaddrs(&addrs) == 0)
{
cursor = addrs;
while (cursor != NULL)
{
if ((cursor->ifa_addr->sa_family == AF_LINK) && (((const struct sockaddr_dl*)cursor->ifa_addr)->sdl_type == IFT_ETHER) && strcmp("en0", cursor->ifa_name) == 0)
{
const struct sockaddr_dl* dlAddr = (const struct sockaddr_dl*) cursor->ifa_addr;
const unsigned char* base = (const unsigned char*)&dlAddr->sdl_data[dlAddr->sdl_nlen];
for (NSInteger index = 0; index < dlAddr->sdl_alen; index++)
{
char partialAddr[3];
sprintf(partialAddr, "%02X", base[index]);
strcat(macAddressString, partialAddr);
}
}
cursor = cursor->ifa_next;
}
}
result = [[[NSString alloc] initWithUTF8String:macAddressString] autorelease];
free(macAddressString);
}
return result;
}
To create a uniqueString based on unique identifier of device in iOS 6:
#import <AdSupport/ASIdentifierManager.h>
NSString *uniqueString = [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];
NSLog(#"uniqueString: %#", uniqueString);
A lot of these questions only address the Mac address. If you also require the IP address I just wrote this, may need some work but seems to work well on my machine...
- (NSString *)getLocalIPAddress
{
NSArray *ipAddresses = [[NSHost currentHost] addresses];
NSArray *sortedIPAddresses = [ipAddresses sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
numberFormatter.allowsFloats = NO;
for (NSString *potentialIPAddress in sortedIPAddresses)
{
if ([potentialIPAddress isEqualToString:#"127.0.0.1"]) {
continue;
}
NSArray *ipParts = [potentialIPAddress componentsSeparatedByString:#"."];
BOOL isMatch = YES;
for (NSString *ipPart in ipParts) {
if (![numberFormatter numberFromString:ipPart]) {
isMatch = NO;
break;
}
}
if (isMatch) {
return potentialIPAddress;
}
}
// No IP found
return #"?.?.?.?";
}

Resources