Getting Device ID or Mac Address in iOS [duplicate] - ios

This question already has answers here:
How can I programmatically get the MAC address of an iphone
(12 answers)
Closed 9 years ago.
I have an application that uses rest to communicate to a server, i would like to obtain the iphones either mac address or device ID for uniqueness validation, how can this be done?

[[UIDevice currentDevice] uniqueIdentifier] is guaranteed to be unique to each device.

uniqueIdentifier (Deprecated in iOS 5.0. Instead, create a unique identifier specific to your app.)
The docs recommend use of CFUUIDCreate instead of [[UIDevice currentDevice] uniqueIdentifier]
So here is how you generate an unique id in your app
CFUUIDRef uuidRef = CFUUIDCreate(kCFAllocatorDefault);
NSString *uuidString = (NSString *)CFUUIDCreateString(NULL,uuidRef);
CFRelease(uuidRef);
Note that you have to save the uuidString in user defaults or in other place because you can not generate the same uuidString again.
You can use UIPasteboard to store your generated uuid. And if the app will be deleted and reinstalled you can read from UIPasteboard the old uuid. The paste board will be wiped out when the device will be erased.
In iOS 6 they have introduced the NSUUID Class that is designed to create UUIDs strings
Also they added in iOS 6 #property(nonatomic, readonly, retain) NSUUID *identifierForVendor to the UIDevice class
The value of this property is the same for apps that come from the
same vendor running on the same device. A different value is returned
for apps on the same device that come from different vendors, and for
apps on different devices regardless of vendor.
The value of this property may be nil if the app is running in the
background, before the user has unlocked the device the first time
after the device has been restarted. If the value is nil, wait and get
the value again later.
Also in iOS 6 you can use ASIdentifierManager class from AdSupport.framework. There you have
#property(nonatomic, readonly) NSUUID *advertisingIdentifier
Discussion Unlike the identifierForVendor property of the UIDevice,
the same value is returned to all vendors. This identifier may
change—for example, if the user erases the device—so you should not
cache it.
The value of this property may be nil if the app is running in the
background, before the user has unlocked the device the first time
after the device has been restarted. If the value is nil, wait and get
the value again later.
Edit:
Pay attention that the advertisingIdentifier may return
00000000-0000-0000-0000-000000000000
because there seems to be a bug in iOS. Related question: The advertisingIdentifier and identifierForVendor return "00000000-0000-0000-0000-000000000000"

For a Mac Adress you could use
#import <Foundation/Foundation.h>
#interface MacAddressHelper : NSObject
+ (NSString *)getMacAddress;
#end
implentation
#import "MacAddressHelper.h"
#import <sys/socket.h>
#import <sys/sysctl.h>
#import <net/if.h>
#import <net/if_dl.h>
#implementation MacAddressHelper
+ (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;
}
#end
Use:
NSLog(#"MAC address: %#",[MacAddressHelper getMacAddress]);

Use this:
NSUUID *id = [[UIDevice currentDevice] identifierForVendor];
NSLog(#"ID: %#", id);

In IOS 5 [[UIDevice currentDevice] uniqueIdentifier] is deprecated.
It's better to use -identifierForVendor or -identifierForAdvertising.
A lot of useful information can be found here:
iOS6 UDID - What advantages does identifierForVendor have over identifierForAdvertising?

Here, We can find mac address for IOS device using Asp.net C# Code...
.aspx.cs
-
var UserDeviceInfo = HttpContext.Current.Request.UserAgent.ToLower(); // User's Iphone/Ipad Info.
var UserMacAdd = HttpContext.Current.Request.UserHostAddress; // User's Iphone/Ipad Mac Address
GetMacAddressfromIP macadd = new GetMacAddressfromIP();
if (UserDeviceInfo.Contains("iphone;"))
{
// iPhone
Label1.Text = UserDeviceInfo;
Label2.Text = UserMacAdd;
string Getmac = macadd.GetMacAddress(UserMacAdd);
Label3.Text = Getmac;
}
else if (UserDeviceInfo.Contains("ipad;"))
{
// iPad
Label1.Text = UserDeviceInfo;
Label2.Text = UserMacAdd;
string Getmac = macadd.GetMacAddress(UserMacAdd);
Label3.Text = Getmac;
}
else
{
Label1.Text = UserDeviceInfo;
Label2.Text = UserMacAdd;
string Getmac = macadd.GetMacAddress(UserMacAdd);
Label3.Text = Getmac;
}
.class File
public string GetMacAddress(string ipAddress)
{
string macAddress = string.Empty;
if (!IsHostAccessible(ipAddress)) return null;
try
{
ProcessStartInfo processStartInfo = new ProcessStartInfo();
Process process = new Process();
processStartInfo.FileName = "arp";
processStartInfo.RedirectStandardInput = false;
processStartInfo.RedirectStandardOutput = true;
processStartInfo.Arguments = "-a " + ipAddress;
processStartInfo.UseShellExecute = false;
process = Process.Start(processStartInfo);
int Counter = -1;
while (Counter <= -1)
{
Counter = macAddress.Trim().ToLower().IndexOf("mac address", 0);
if (Counter > -1)
{
break;
}
macAddress = process.StandardOutput.ReadLine();
if (macAddress != "")
{
string[] mac = macAddress.Split(' ');
if (Array.IndexOf(mac, ipAddress) > -1)
{
if (mac[11] != "")
{
macAddress = mac[11].ToString();
break;
}
}
}
}
process.WaitForExit();
macAddress = macAddress.Trim();
}
catch (Exception e)
{
Console.WriteLine("Failed because:" + e.ToString());
}
return macAddress;
}

Related

Objective C / C. I get wrong Value when i try to get Mac Adress on IOS device

I'm trying to use a C code to obtain mac adress on any IOS device.
I'm trying it on a iPhone 6 plus but it seems not work.
My output will look as follows:
2015-02-15 15:37:37.947 MyDemo[438:223963] Mac Address: 02:00:00:00:00:00
Anyone can help me for this please ?
Thanks.
This is the GetMacAdress.m
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;
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;
}
That is some pretty nasty low-level code.
I personally think that anyone who writes code of the form:
if ((a=b)==c)
...should be shot. We're not writing assembler here - Don't write code that looks like a typo to save 1 statement. (That rant is directed at the original author, not you.)
I'm not familiar enough with the low-level system functions to be able to tell what's wrong without a lot of digging.
However, stepping back from why your code isn't working, WHY do you need the MAC address? Does it have to be the actual network MAC address?
Apple no longer allows you to get that information because it allows you to uniquely track the user's device. If you do find a way to do it, your app will be rejected. (Not really Apple's fault; there was a big stink in the industry and all the device vendors had to block providing this info.)
#mad_mask's suggestion of using identifierForVendor is probably the best solution. That gives you an ID that's unique for that device for your company.
It is not possible to get the MAC address for an apple device any longer. This was added to prevent applications from using the MAC address as a unique identifier for tracking. It always comes out as 02:00:00:00:00:00 regardless of the route you take to finding it.
The vendor and marketing Ids you have to use instead are not the MAC address but something else.
I have written a network scanner and as far as I have been able to tell, there is no way round this unless you can talk to an external device on the same LAN segment which has visibility of the device on the network and can send it to you.

Is there any way to register a notification when ip address changed on device?

I want to use NSStream to send send and receive information to server.
I thought if I can obtain the ip address the server can send information back in order to replace the silent push notification.
Is is possible to register a notification when ip address changed?
P.S.
I'm currently using reachability class to register a notification when network changed but if there is a better way it'll be great!
I think there is not straight way to achieve this but Use
`[[NSHost currentHost] address];`
save value into userDefault and every time when you connect check with stored value and get notify
i found this on SO hope this work for you
#include <ifaddrs.h>
#include <arpa/inet.h>
- (NSString *)getIPAddress {
NSString *address = #"error";
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
address = [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr)];
}
}
temp_addr = temp_addr->ifa_next;
}
}
// Free memory
freeifaddrs(interfaces);
return address;
}

What is the simplest way to retrieve the device serial number of an iOS device using MonoTouch?

Does MonoTouch have a simple mechanism for retrieving the device serial number (not UDID) of an iOS device? Is there a third-party library which I can use to obtain this?
In case it matters, I'm looking to use this functionality in an in-house application and am not concerned with the App Store approval process.
UPDATE: from iOS 8, we cannot retrieve the serial number of our iDevice.
To retrieve iphone serial number from Monotouch, you can use this technic:
Create a static library .a from XCode that have a function to get serial number
In MonoDevelop, create a binding project to bind you .a library into C# classes/functions (http://docs.xamarin.com/guides/ios/advanced_topics/binding_objective-c_libraries)
In your application, you call this binding library (in step 2).
For detail:
STEP 1. In my library.a, I have a class DeviceInfo, here is the implementation to get Serial number
#import "DeviceInfo.h"
#import <dlfcn.h>
#import <mach/port.h>
#import <mach/kern_return.h>
#implementation DeviceInfo
- (NSString *) serialNumber
{
NSString *serialNumber = nil;
void *IOKit = dlopen("/System/Library/Frameworks/IOKit.framework/IOKit", RTLD_NOW);
if (IOKit)
{
mach_port_t *kIOMasterPortDefault = dlsym(IOKit, "kIOMasterPortDefault");
CFMutableDictionaryRef (*IOServiceMatching)(const char *name) = dlsym(IOKit, "IOServiceMatching");
mach_port_t (*IOServiceGetMatchingService)(mach_port_t masterPort, CFDictionaryRef matching) = dlsym(IOKit, "IOServiceGetMatchingService");
CFTypeRef (*IORegistryEntryCreateCFProperty)(mach_port_t entry, CFStringRef key, CFAllocatorRef allocator, uint32_t options) = dlsym(IOKit, "IORegistryEntryCreateCFProperty");
kern_return_t (*IOObjectRelease)(mach_port_t object) = dlsym(IOKit, "IOObjectRelease");
if (kIOMasterPortDefault && IOServiceGetMatchingService && IORegistryEntryCreateCFProperty && IOObjectRelease)
{
mach_port_t platformExpertDevice = IOServiceGetMatchingService(*kIOMasterPortDefault, IOServiceMatching("IOPlatformExpertDevice"));
if (platformExpertDevice)
{
CFTypeRef platformSerialNumber = IORegistryEntryCreateCFProperty(platformExpertDevice, CFSTR("IOPlatformSerialNumber"), kCFAllocatorDefault, 0);
if (CFGetTypeID(platformSerialNumber) == CFStringGetTypeID())
{
serialNumber = [NSString stringWithString:(__bridge NSString*)platformSerialNumber];
CFRelease(platformSerialNumber);
}
IOObjectRelease(platformExpertDevice);
}
}
dlclose(IOKit);
}
return serialNumber;
}
#end
STEP 2. In ApiDefinition.cs of my Binding Library project in Monotouch, I add this binding:
[BaseType (typeof (NSObject))]
public interface DeviceInfo {
[Export ("serialNumber")]
NSString GetSerialNumber ();
}
STEP 3. In my application, I import Reference to Binding library project in step 2, then add
using MyBindingProject;
...
string serialNumber = "";
try {
DeviceInfo nativeDeviceInfo = new DeviceInfo ();
NSString temp = nativeDeviceInfo.GetSerialNumber();
serialNumber = temp.ToString();
} catch (Exception ex) {
Console.WriteLine("Cannot get serial number {0} - {1}",ex.Message, ex.StackTrace);
}
Hope that helps. Don't hesitate if you have any question.

How to get iOS device MAC address programmatically

How do I get an iOS device's MAC code programmatically in my app?
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);
You can get the MAC Adress using the following function:
+(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]];
if(IsDEBUG) NSLog(#"Mac Address: %#", macAddressString);
// Release the buffer memory
free(msgBuffer);
return macAddressString;
}
// Error...
if(IsDEBUG) NSLog(#"Error: %#", errorFlag);
return errorFlag;
}
But as he said #Randomclik, mac address is unavailable from ios 7 and up.
form apple:
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.)
link:
https://developer.apple.com/library/prerelease/ios/releasenotes/General/WhatsNewIniOS/Articles/iOS7.html#//apple_ref/doc/uid/TP40013162-SW1
Conversation about MAC Address:
How can I programmatically get the MAC address of an iphone
It seems that in iOS 7 and later get MAC addres will not work. Look at What's new on iOS document from Apple. (Deprecated APIs section.)
everybody is good advised to use the offical ios 7 way and use [UIDevice identifierForVendor]
http://developer.apple.com/library/ios/#documentation/uikit/reference/UIDevice_Class/Reference/UIDevice.html
And also think about the migration from some older assumptions.
You can get it by combining the following two answers i guess.
First, find ip of the device by using the following:
https://stackoverflow.com/a/30754194/1089206
Second, find the MAC of that address, by using the following:
https://stackoverflow.com/a/31246085/1089206
I'll be trying it out now and will let you know how it goes.
Actually it seems possible to get macaddr even on iOS >= 7 the information comes from this blog and the solution is based on ipV6.
I have tested on iPhone12 running under 15.5 and it works fine.
Here is the interesting code:
func GetMACAddress(){
let address = getAddress()
macAddressLabel = GetMACAddressFromIPv6(ip: address ?? "")
print(macAddressLabel)
}
func GetMACAddressFromIPv6(ip: String) -> String{
let IPStruct = IPv6Address(ip)
if(IPStruct == nil){
return ""
}
let extractedMAC = [
(IPStruct?.rawValue[8])! ^ 0b00000010,
IPStruct?.rawValue[9],
IPStruct?.rawValue[10],
IPStruct?.rawValue[13],
IPStruct?.rawValue[14],
IPStruct?.rawValue[15]
]
let str = String(format: "%02x:%02x:%02x:%02x:%02x:%02x", extractedMAC[0] ?? 00,
extractedMAC[1] ?? 00,
extractedMAC[2] ?? 00,
extractedMAC[3] ?? 00,
extractedMAC[4] ?? 00,
extractedMAC[5] ?? 00)
return str
}
// this function was taken from
// https://stackoverflow.com/a/30754194/3508517
//and is slightly modified:
func getAddress() -> String? {
var address: String?
// Get list of all interfaces on the local machine:
var ifaddr: UnsafeMutablePointer<ifaddrs>?
guard getifaddrs(&ifaddr) == 0 else { return nil }
guard let firstAddr = ifaddr else { return nil }
// For each interface ...
for ifptr in sequence(first: firstAddr, next: { $0.pointee.ifa_next }) {
let interface = ifptr.pointee
// Check IPv6 interface:
let addrFamily = interface.ifa_addr.pointee.sa_family
if addrFamily == UInt8(AF_INET6) {
// Check interface name:
let name = String(cString: interface.ifa_name)
if name.contains("ipsec") {
// Convert interface address to a human readable string:
var hostname = [CChar](repeating: 0, count: Int(NI_MAXHOST))
getnameinfo(interface.ifa_addr, socklen_t(interface.ifa_addr.pointee.sa_len),
&hostname, socklen_t(hostname.count),
nil, socklen_t(0), NI_NUMERICHOST)
address = String(cString: hostname)
let ipv6addr = IPv6Address(address ?? "::")
if(ipv6addr?.isLinkLocal ?? false){
return address
}
}
}
}
freeifaddrs(ifaddr)
return address
}

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