development

프로그래밍 방식으로 아이폰의 MAC 주소를 얻는 방법

big-blog 2020. 6. 18. 07:25
반응형

프로그래밍 방식으로 아이폰의 MAC 주소를 얻는 방법


프로그래밍 방식으로 iPhone의 MAC 주소와 IP 주소를 얻는 방법은 무엇입니까?



참고 iOS7부터는 더 이상 장치 MAC 주소를 검색 할 수 없습니다. 실제 MAC이 아닌 고정 값이 반환됩니다


나는 얼마 전에 우연히 발견되었습니다. 원래부터 여기 에서 약간 수정하고 정리했습니다.

IPAddress.h
IPAddress.c

그리고 그것을 사용하려면

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]);
    }
}

어댑터 이름은 시뮬레이터 / 장치 및 장치의 Wi-Fi 또는 셀에 따라 다릅니다.


업데이트 : iOS 7에서는 작동하지 않습니다 . ASIdentifierManager를 사용해야합니다 .


MobileDeveloperTips 웹 사이트에서 더 깨끗한 솔루션 :

#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;
}

Wi-Fi 사용 여부에 관계없이 주소를 반환하기를 원했기 때문에 선택한 솔루션이 작동하지 않습니다. 조정 후 일부 포럼에서 찾은 다른 전화를 사용했습니다. 나는 다음과 같이 끝났다 (내 녹슨 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;
}

그런 다음 다음과 같이 en0을 요청하여 호출합니다 .

char* macAddressString= (char*)malloc(18);
NSString* macAddress= [[NSString alloc] initWithCString:getMacAddress(macAddressString, "en0")
                                              encoding:NSMacOSRomanStringEncoding];
free(macAddressString);

iOS 7부터 시스템 02:00:00:00:00:00은 모든 장치에서 MAC 주소를 요청할 때 항상 값을 반환합니다 .

iOS 7 이상에서 iOS 장치의 MAC 주소를 요청하면 시스템은 02 : 00 : 00 : 00 : 00 : 00 값을 반환합니다. 장치를 식별해야하는 경우 대신 UIDevice의 identifierForVendor 속성을 사용하십시오. (자신의 광고 목적으로 식별자가 필요한 앱은 대신 ASIdentifierManager의 AdvertisingIdentifier 속성을 사용해야합니다. ""

참조 : 릴리즈 노트


이것에 대한 다양한 해결책이 있지만 모든 것을 찾을 수는 없습니다. 그래서 나는 다음을 위해 나만의 해결책을 만들었다.

nicinfo

사용하는 방법 :

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!");
}

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;
}

이제 iOS 7 기기는 항상 02 : 00 : 00 : 00 : 00 : 00의 MAC 주소를 반환합니다.

[UIDevice identifierForVendor]를 사용하는 것이 좋습니다.

앱 고유의 고유 키를 얻으려면이 메소드를 호출하는 것이 좋습니다.

카테고리가 더 적합합니다

"UIDevice + Identifier.h"가져 오기

- (NSString *) identifierForVendor1
{
    if ([[UIDevice currentDevice] respondsToSelector:@selector(identifierForVendor)]) {
        return [[[UIDevice currentDevice] identifierForVendor] UUIDString];
    }
    return @"";
}

고유 주소를 얻기 위해 위의 메소드를 호출하십시오.

NSString *like_UDID=[NSString stringWithFormat:@"%@",
                [[UIDevice currentDevice] identifierForVendor1]];

NSLog(@"%@",like_UDID);

@Grantland이 "정말 깨끗한 솔루션"은 iPhoneDeveloperTips 솔루션에 대한 저의 개선과 비슷합니다.

여기 내 단계를 볼 수 있습니다 : 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 @"?.?.?.?";
}

참고URL : https://stackoverflow.com/questions/677530/how-can-i-programmatically-get-the-mac-address-of-an-iphone

반응형