Created
April 27, 2016 08:58
-
-
Save Haraguroicha/0b225876d58949002fdd8e8553b6e348 to your computer and use it in GitHub Desktop.
Get WiFi Info from private api
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@import SystemConfiguration; | |
#import <dlfcn.h> | |
#import <mach/port.h> | |
#import <mach/kern_return.h> | |
#include <sys/socket.h> | |
#include <sys/sysctl.h> | |
#include <net/if.h> | |
#include <net/if_dl.h> | |
#include <ifaddrs.h> | |
#include <arpa/inet.h> | |
@implementation UIDevice (detailInformation) | |
- (NSDictionary *)getWiFiInfo { | |
NSMutableDictionary *wifiInfo = [NSMutableDictionary new]; | |
// base path: Root>J86AP>AppleARMPE>arm-io>AppleS5L8960XIO>usb-complex>AppleS5L8960XUSBArbitrator>usb-ehci1>AppleS5L8960XUSBEHCI>wlan>AppleBCMWLANBusInterfaceHSIC>AppleBCMWLANCore | |
// to get wifi lqm | |
// . :LinkQualityMetrics | |
// to get wifi ssid and bssid | |
// . > en0:IO80211(B)?SSID | |
void *IOKit = dlopen("/System/Library/Frameworks/IOKit.framework/IOKit", RTLD_NOW); | |
NSMutableDictionary *io80211 = nil; | |
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 (*IORegistryEntryCreateCFProperties)(mach_port_t entry, CFMutableDictionaryRef *properties, CFAllocatorRef allocator, uint32_t options) = dlsym(IOKit, "IORegistryEntryCreateCFProperties"); | |
kern_return_t (*IORegistryEntryGetChildIterator)(mach_port_t entry, const char plane[128], mach_port_t *iterator) = dlsym(IOKit, "IORegistryEntryGetChildIterator"); | |
kern_return_t (*IOIteratorNext)(kern_return_t iterator) = dlsym(IOKit, "IOIteratorNext"); | |
kern_return_t (*IORegistryEntryGetNameInPlane)(mach_port_t entry, const char plane[128], char name[128]) = dlsym(IOKit, "IORegistryEntryGetNameInPlane"); | |
kern_return_t (*IOObjectRelease)(mach_port_t object) = dlsym(IOKit, "IOObjectRelease"); | |
if (kIOMasterPortDefault && IOServiceGetMatchingService && IORegistryEntryCreateCFProperty && IOObjectRelease) { | |
mach_port_t BCMWLANDevice = IOServiceGetMatchingService(*kIOMasterPortDefault, IOServiceMatching("AppleBCMWLANCore")); | |
if (BCMWLANDevice) { | |
CFMutableDictionaryRef properties = 0; | |
kern_return_t IO80211 = KERN_SUCCESS; | |
IO80211 = IORegistryEntryCreateCFProperties(BCMWLANDevice, &properties, kCFAllocatorDefault, 0); | |
if (CFGetTypeID(properties) == CFDictionaryGetTypeID()) { | |
io80211 = [NSMutableDictionary dictionaryWithDictionary:(__bridge NSDictionary *)properties]; | |
CFRelease(properties); | |
} | |
IOObjectRelease(IO80211); | |
kern_return_t status = KERN_SUCCESS; | |
mach_port_t children = 0; | |
status = IORegistryEntryGetChildIterator(BCMWLANDevice, "IOService", &children); | |
mach_port_t child = 0; | |
mach_port_t childUpNext = 0; | |
if (status == KERN_SUCCESS) { | |
childUpNext = IOIteratorNext(children); | |
while (childUpNext) { | |
child = childUpNext; | |
childUpNext = IOIteratorNext(children); | |
CFMutableDictionaryRef _properties = 0; | |
kern_return_t _IO80211 = KERN_SUCCESS; | |
_IO80211 = IORegistryEntryCreateCFProperties(child, &_properties, kCFAllocatorDefault, 0); | |
char title[128]; | |
IORegistryEntryGetNameInPlane(child, "IOService", title); | |
if (CFGetTypeID(_properties) == CFDictionaryGetTypeID()) { | |
NSDictionary *value = [NSDictionary dictionaryWithDictionary:(__bridge NSDictionary *)_properties]; | |
CFRelease(_properties); | |
[io80211 setValue:value | |
forKey:[NSString stringWithCString:title | |
encoding:NSUTF8StringEncoding]]; | |
} | |
IOObjectRelease(_IO80211); | |
IOObjectRelease(child); | |
} | |
IOObjectRelease(children); | |
} | |
IOObjectRelease(BCMWLANDevice); | |
} | |
} | |
dlclose(IOKit); | |
} | |
IOKit = nil; | |
if (io80211 != nil) { | |
NSArray *linkQualityMetrics = [[io80211 objectForKey:@"LinkQualityMetrics"] componentsSeparatedByString:@" "]; | |
for (NSString *linkQualityMetric in linkQualityMetrics) { | |
if ([linkQualityMetric containsString:@"="]) { | |
NSArray *lqm = [linkQualityMetric componentsSeparatedByString:@"="]; | |
[wifiInfo setValue:[lqm objectAtIndex:1] | |
forKey:[lqm objectAtIndex:0]]; | |
} | |
} | |
NSDictionary *en0 = [io80211 objectForKey:@"en0"]; | |
NSData *BSSIDData = [en0 objectForKey:@"IO80211BSSID"]; | |
const unsigned char *buffer = [BSSIDData bytes]; | |
NSMutableString *BSSID = [NSMutableString stringWithCapacity:[BSSIDData length] * 2]; | |
for (NSInteger i = 0; i < [BSSIDData length]; i++) { | |
[BSSID appendFormat:@"%02lX", (unsigned long)buffer[i]]; | |
} | |
BSSID = (NSMutableString *)[BSSID regexReplace:@"(\\w{2})(\\w{2})(\\w{2})(\\w{2})(\\w{2})(\\w{2})" WithTemplate:@"$1:$2:$3:$4:$5:$6"]; | |
[wifiInfo setValue:[en0 objectForKey:@"IO80211SSID"] forKey:@"SSID"]; | |
[wifiInfo setValue:[NSString stringWithString:BSSID] forKey:@"BSSID"]; | |
[wifiInfo setValue:[en0 objectForKey:@"IO80211Band"] forKey:@"Band"]; | |
[wifiInfo setValue:[en0 objectForKey:@"IO80211Channel"] forKey:@"Channel"]; | |
// following only support on iOS 9 and above | |
[wifiInfo setValue:[en0 objectForKey:@"IO80211ChannelBandwidth"] forKey:@"ChannelBandwidth"]; | |
[wifiInfo setValue:[en0 objectForKey:@"IO80211ChannelFrequency"] forKey:@"ChannelFrequency"]; | |
} | |
return [[NSDictionary alloc] initWithDictionary:wifiInfo]; | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment