├── .gitignore ├── Makefile ├── src ├── entitlements.xml ├── Constants.h ├── UtilNetworksManager.h ├── UtilNetwork.h ├── UtilNetwork.m ├── main.m └── UtilNetworksManager.m ├── README.md └── headers └── MobileWiFi ├── MobileWiFi.h ├── WiFiManager.h ├── WiFiNetwork.h └── WiFiDeviceClient.h /.gitignore: -------------------------------------------------------------------------------- 1 | .theos/ 2 | debs/ 3 | control 4 | *.o 5 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | include $(THEOS)/makefiles/common.mk 2 | 3 | TOOL_NAME = wifiutil 4 | wifiutil_FILES = $(wildcard src/*.m*) 5 | wifiutil_PRIVATE_FRAMEWORKS = MobileWiFi 6 | wifiutil_CODESIGN_FLAGS = -Ssrc/entitlements.xml 7 | 8 | ADDITIONAL_CFLAGS = -I$(THEOS_PROJECT_DIR)/headers/ 9 | 10 | include $(THEOS_MAKE_PATH)/tool.mk 11 | -------------------------------------------------------------------------------- /src/entitlements.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.wifi.manager-access 6 | 7 | keychain-access-groups 8 | 9 | apple 10 | com.apple.preferences 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/Constants.h: -------------------------------------------------------------------------------- 1 | // Colors 2 | // Normal "\x1B[0m" 3 | // Red "\x1B[31m" 4 | // Green "\x1B[32m" 5 | // Yellow "\x1B[33m" 6 | // Blue "\x1B[34m" 7 | // CYAN "\x1B[36m" 8 | // White "\x1B[37m" 9 | 10 | #define LOG_DBG(x) \ 11 | NSLog(@"\x1B[32m[Debug] \x1B[0m%@", x); 12 | #define LOG_ERR(x) \ 13 | NSLog(@"\x1B[31m[Error] \x1B[0m%@", x); 14 | #define LOG_OUTPUT(x) \ 15 | NSLog(@"\x1B[36m[Output] \x1B[0m%@", x); 16 | -------------------------------------------------------------------------------- /src/UtilNetworksManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // UtilNetworksManager.h 3 | // 4 | // 5 | // Created by qpiu on 2016/2/12. 6 | // 7 | // 8 | 9 | #import 10 | #import "MobileWiFi/MobileWiFi.h" 11 | 12 | @class UtilNetwork; 13 | 14 | @interface UtilNetworksManager : NSObject { 15 | WiFiManagerRef _manager; 16 | WiFiDeviceClientRef _client; 17 | WiFiNetworkRef _currentNetwork; 18 | BOOL _scanning; 19 | BOOL _associating; 20 | NSMutableArray *_networks; 21 | int _statusCode; 22 | } 23 | 24 | @property(nonatomic, retain, readonly) NSArray *networks; 25 | @property(nonatomic, assign, readonly, getter = isScanning) BOOL scanning; 26 | @property(nonatomic, assign, readonly) int statusCode; 27 | @property(nonatomic, assign, getter = isWiFiEnabled) BOOL wiFiEnabled; 28 | 29 | + (id)sharedInstance; 30 | - (void)scan; 31 | //- (void)removeNetwork:(UtilNetwork *)network; 32 | - (void)associateWithNetwork:(UtilNetwork *)network; 33 | - (void)associateWithEncNetwork:(UtilNetwork *)network Password:(NSString *)passwd; 34 | - (void)disassociate; 35 | - (UtilNetwork *)getNetworkWithSSID:(NSString *)ssid; 36 | //- (NSArray *)knownNetworks; 37 | //- (NSString *)interfaceName; 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # wifiutil 2 | 3 | 4 | 5 | 6 | 7 | iOS command-line tool for WiFi-related operation. 8 | 9 | # Installation 10 | 14 | 15 | # Usage 16 | 25 | 26 | # License 27 | Licensed under: 28 | 29 | -------------------------------------------------------------------------------- /src/UtilNetwork.h: -------------------------------------------------------------------------------- 1 | // 2 | // UtilNetwork.h 3 | // 4 | // 5 | // Created by qpiu on 2016/2/12. 6 | // 7 | // 8 | 9 | #ifndef UtilNetwork_h 10 | #define UtilNetwork_h 11 | 12 | #import "MobileWiFi/MobileWiFi.h" 13 | 14 | @interface UtilNetwork : NSObject { 15 | WiFiNetworkRef _network; 16 | NSString *_SSID; 17 | NSString *_encryptionModel; 18 | NSString *_BSSID; 19 | NSString *_username; 20 | NSString *_password; 21 | int _channel; 22 | BOOL _isCurrentNetwork; 23 | BOOL _isHidden; 24 | BOOL _isAssociating; 25 | BOOL _requiresUsername; 26 | BOOL _requiresPassword; 27 | } 28 | 29 | @property(nonatomic, copy) NSString *SSID; 30 | @property(nonatomic, copy) NSString *encryptionModel; 31 | @property(nonatomic, copy) NSString *BSSID; 32 | @property(nonatomic, copy) NSString *username; 33 | @property(nonatomic, copy) NSString *password; 34 | @property(nonatomic, assign) int channel; 35 | @property(nonatomic, assign) BOOL isCurrentNetwork; 36 | @property(nonatomic, assign) BOOL isHidden; 37 | @property(nonatomic, assign) BOOL isAssociating; 38 | @property(nonatomic, assign) BOOL requiresPassword; 39 | @property(nonatomic, assign) BOOL requiresUsername; 40 | @property(nonatomic, assign, readonly) WiFiNetworkRef _networkRef; 41 | 42 | - (id)initWithNetwork:(WiFiNetworkRef)network; 43 | - (void)populateData; 44 | 45 | 46 | @end 47 | #endif /* UtilNetwork_h */ 48 | -------------------------------------------------------------------------------- /headers/MobileWiFi/MobileWiFi.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MobileWiFi framework base header. 3 | * 4 | * Copyright (c) 2013-2014 Cykey (David Murray) 5 | * All rights reserved. 6 | */ 7 | 8 | #ifndef MOBILEWIFI_H_ 9 | #define MOBILEWIFI_H_ 10 | 11 | #include "WiFiDeviceClient.h" 12 | #include "WiFiNetwork.h" 13 | #include "WiFiManager.h" 14 | 15 | #if __cplusplus 16 | extern "C" { 17 | #endif 18 | 19 | #pragma mark - Constants 20 | 21 | extern CFStringRef kWiFiATJTestModeEnabledKey; 22 | extern CFStringRef kWiFiDeviceCapabilitiesKey; 23 | extern CFStringRef kWiFiDeviceSupportsWAPIKey; 24 | extern CFStringRef kWiFiDeviceSupportsWoWKey; 25 | extern CFStringRef kWiFiDeviceVendorIDKey; 26 | extern CFStringRef kWiFiLocaleTestParamsKey; 27 | extern CFStringRef kWiFiLoggingDriverFileKey; 28 | extern CFStringRef kWiFiLoggingDriverLoggingEnabledKey; 29 | extern CFStringRef kWiFiLoggingEnabledKey; 30 | extern CFStringRef kWiFiLoggingFileEnabledKey; 31 | extern CFStringRef kWiFiLoggingFileKey; 32 | extern CFStringRef kWiFiManagerDisableBlackListKey; 33 | extern CFStringRef kWiFiNetworkEnterpriseProfileKey; 34 | extern CFStringRef kWiFiPreferenceCustomNetworksSettingsKey; 35 | extern CFStringRef kWiFiPreferenceEnhancedWoWEnabledKey; 36 | extern CFStringRef kWiFiPreferenceMStageAutoJoinKey; 37 | extern CFStringRef kWiFiRSSIThresholdKey; // '-80' 38 | extern CFStringRef kWiFiScaledRSSIKey; 39 | extern CFStringRef kWiFiScaledRateKey; 40 | extern CFStringRef kWiFiStrengthKey; 41 | extern CFStringRef kWiFiTetheringCredentialsKey; 42 | 43 | #if __cplusplus 44 | } 45 | #endif 46 | 47 | #endif /* MOBILEWIFI_H_ */ 48 | -------------------------------------------------------------------------------- /headers/MobileWiFi/WiFiManager.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MobileWiFi manager header. 3 | * 4 | * Copyright (c) 2013-2014 Cykey (David Murray) 5 | * All rights reserved. 6 | */ 7 | 8 | #ifndef WIFIMANAGER_H_ 9 | #define WIFIMANAGER_H_ 10 | 11 | #include 12 | #include "WiFiNetwork.h" 13 | #include "WiFiDeviceClient.h" 14 | 15 | #if __cplusplus 16 | extern "C" { 17 | #endif 18 | 19 | #pragma mark - Definitions 20 | 21 | typedef struct __WiFiManager *WiFiManagerRef; 22 | 23 | #pragma mark - API 24 | 25 | WiFiManagerRef WiFiManagerClientCreate(CFAllocatorRef allocator, int flags); 26 | 27 | CFArrayRef WiFiManagerClientCopyDevices(WiFiManagerRef manager); 28 | CFArrayRef WiFiManagerClientCopyNetworks(WiFiManagerRef manager); 29 | 30 | void WiFiManagerClientRemoveNetwork(WiFiManagerRef manager, WiFiNetworkRef network); 31 | 32 | WiFiDeviceClientRef WiFiManagerClientGetDevice(WiFiManagerRef manager); 33 | 34 | void WiFiManagerClientScheduleWithRunLoop(WiFiManagerRef manager, CFRunLoopRef runLoop, CFStringRef mode); 35 | void WiFiManagerClientUnscheduleFromRunLoop(WiFiManagerRef manager); 36 | void WiFiManagerClientSetProperty(WiFiManagerRef manager, CFStringRef property, CFPropertyListRef value); 37 | 38 | CFPropertyListRef WiFiManagerClientCopyProperty(WiFiManagerRef manager, CFStringRef property); 39 | 40 | void WiFiManagerClientQuiesceWiFi(WiFiManagerRef manager, int state); 41 | 42 | void WiFiManagerClientSetMISState(WiFiManagerRef manager, int state); 43 | void WiFiManagerClientSetMisPassword(WiFiManagerRef manager, CFStringRef password); 44 | void WiFiManagerClientSetMISDiscoveryState(WiFiManagerRef manager, int state); 45 | 46 | int WiFiManagerClientGetMISState(WiFiManagerRef manager); 47 | int WiFiManagerClientGetMISDiscoveryState(WiFiManagerRef manager); 48 | 49 | #if __cplusplus 50 | } 51 | #endif 52 | 53 | #endif /* WIFIMANAGER_H_ */ 54 | -------------------------------------------------------------------------------- /headers/MobileWiFi/WiFiNetwork.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MobileWiFi network header. 3 | * 4 | * Copyright (c) 2013-2014 Cykey (David Murray) 5 | * All rights reserved. 6 | */ 7 | 8 | #ifndef WIFINETWORK_H_ 9 | #define WIFINETWORK_H_ 10 | 11 | #include 12 | 13 | #if __cplusplus 14 | extern "C" { 15 | #endif 16 | 17 | #pragma mark - Definitions 18 | 19 | /* 20 | * Opaque structure definitions. 21 | */ 22 | 23 | typedef struct __WiFiNetwork *WiFiNetworkRef; 24 | 25 | #pragma mark - API 26 | 27 | CFPropertyListRef WiFiNetworkGetProperty(WiFiNetworkRef network, CFStringRef property); 28 | 29 | int WiFiNetworkGetIntProperty(WiFiNetworkRef network, CFStringRef property); 30 | 31 | float WiFiNetworkGetFloatProperty(WiFiNetworkRef network, CFStringRef property); 32 | 33 | CFStringRef WiFiNetworkCopyPassword(WiFiNetworkRef); 34 | CFStringRef WiFiNetworkGetSSID(WiFiNetworkRef network); 35 | 36 | void WiFiNetworkSetPassword(WiFiNetworkRef network, CFStringRef password); 37 | 38 | float WiFiNetworkGetNetworkUsage(WiFiNetworkRef network); 39 | 40 | Boolean WiFiNetworkIsWEP(WiFiNetworkRef network); 41 | Boolean WiFiNetworkIsWPA(WiFiNetworkRef network); 42 | Boolean WiFiNetworkIsEAP(WiFiNetworkRef network); 43 | Boolean WiFiNetworkIsApplePersonalHotspot(WiFiNetworkRef network); 44 | Boolean WiFiNetworkIsAdHoc(WiFiNetworkRef network); 45 | Boolean WiFiNetworkIsHidden(WiFiNetworkRef network); 46 | Boolean WiFiNetworkRequiresPassword(WiFiNetworkRef network); 47 | Boolean WiFiNetworkRequiresUsername(WiFiNetworkRef network); 48 | 49 | /* This returns NULL a lot, not sure why. */ 50 | CFDateRef WiFiNetworkGetLastAssociationDate(WiFiNetworkRef network); 51 | 52 | CFDictionaryRef WiFiNetworkCopyRecord(WiFiNetworkRef network); 53 | 54 | #if __cplusplus 55 | } 56 | #endif 57 | 58 | #endif /* WIFINETWORK_H_ */ 59 | -------------------------------------------------------------------------------- /src/UtilNetwork.m: -------------------------------------------------------------------------------- 1 | // 2 | // UtilNetwork.m 3 | // 4 | // 5 | // Created by qpiu on 2016/2/12. 6 | // 7 | // 8 | 9 | //#import 10 | #import "UtilNetwork.h" 11 | #import 12 | #import "Constants.h" 13 | 14 | @implementation UtilNetwork 15 | @synthesize _networkRef = _network; 16 | @synthesize SSID = _SSID; 17 | @synthesize encryptionModel = _encryptionModel; 18 | @synthesize BSSID = _BSSID; 19 | @synthesize username = _username; 20 | @synthesize password = _password; 21 | @synthesize channel = _channel; 22 | @synthesize isCurrentNetwork = _isCurrentNetwork; 23 | @synthesize isHidden = _isHidden; 24 | @synthesize isAssociating = _isAssociating; 25 | @synthesize requiresUsername = _requiresUsername; 26 | @synthesize requiresPassword = _requiresPassword; 27 | 28 | - (id)initWithNetwork:(WiFiNetworkRef)network 29 | { 30 | self = [super init]; 31 | 32 | if (self) { 33 | _network = (WiFiNetworkRef)CFRetain(network); 34 | } 35 | 36 | return self; 37 | } 38 | 39 | - (void)dealloc 40 | { 41 | [_SSID release]; 42 | [_encryptionModel release]; 43 | [_username release]; 44 | [_password release]; 45 | CFRelease(_network); 46 | 47 | [super dealloc]; 48 | } 49 | 50 | - (NSString *)description 51 | { 52 | return [NSString stringWithFormat:@"%@ SSID: %@ Encryption Model: %@ Channel: %i CurrentNetwork: %i Hidden: %i Associating: %i", [super description], [self SSID], [self encryptionModel], [self channel], [self isCurrentNetwork], [self isHidden], [self isAssociating]]; 53 | } 54 | 55 | - (void)populateData 56 | { 57 | // SSID 58 | NSString *SSID = (NSString *)WiFiNetworkGetSSID(_network); 59 | [self setSSID:SSID]; 60 | //NSString *dbg_str = [NSString stringWithFormat:@"setSSID: %@", SSID]; 61 | //LOG_DBG(dbg_str); 62 | 63 | // Encryption model 64 | if (WiFiNetworkIsWEP(_network)) { 65 | [self setEncryptionModel:@"WEP"]; 66 | //dbg_str = [NSString stringWithFormat:@"setEncryptionModel: %s", "WEP"]; 67 | //LOG_DBG(dbg_str); 68 | } 69 | else if (WiFiNetworkIsWPA(_network)) { 70 | [self setEncryptionModel:@"WPA"]; 71 | //dbg_str = [NSString stringWithFormat:@"setEncryptionModel: %s", "WPA"]; 72 | //LOG_DBG(dbg_str); 73 | } 74 | else { 75 | [self setEncryptionModel:@"None"]; 76 | //dbg_str = [NSString stringWithFormat:@"setEncryptionModel: %s", "None"]; 77 | //LOG_DBG(dbg_str); 78 | } 79 | 80 | // BSSID 81 | NSString *BSSID = (NSString *)WiFiNetworkGetProperty(_network, CFSTR("BSSID")); 82 | [self setBSSID:BSSID]; 83 | //dbg_str = [NSString stringWithFormat:@"setBSSID: %@", BSSID]; 84 | //LOG_DBG(dbg_str); 85 | 86 | // Channel 87 | CFNumberRef networkChannel = (CFNumberRef)WiFiNetworkGetProperty(_network, CFSTR("CHANNEL")); 88 | int channel; 89 | CFNumberGetValue(networkChannel, 9, &channel); // 9: kCFNumberIntType 90 | [self setChannel:channel]; 91 | 92 | // Hidden 93 | BOOL isHidden = WiFiNetworkIsHidden(_network); 94 | [self setIsHidden:isHidden]; 95 | 96 | // Requires username 97 | BOOL requiresUsername = WiFiNetworkRequiresUsername(_network); 98 | [self setRequiresUsername:requiresUsername]; 99 | 100 | // Requires password 101 | BOOL requiresPassword = WiFiNetworkRequiresPassword(_network); 102 | [self setRequiresPassword:requiresPassword]; 103 | } 104 | 105 | @end 106 | -------------------------------------------------------------------------------- /headers/MobileWiFi/WiFiDeviceClient.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MobileWiFi device client header. 3 | * 4 | * Copyright (c) 2013-2014 Cykey (David Murray) 5 | * All rights reserved. 6 | */ 7 | 8 | #ifndef WIFIDEVICECLIENT_H_ 9 | #define WIFIDEVICECLIENT_H_ 10 | 11 | #include 12 | #include "WiFiNetwork.h" 13 | 14 | #if __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | #pragma mark - Definitions 19 | 20 | /* 21 | * Opaque structure definition. 22 | */ 23 | 24 | typedef struct __WiFiDeviceClient *WiFiDeviceClientRef; 25 | 26 | /* Callback typedefs. */ 27 | typedef void (*WiFiDeviceClientGenericCallback)(WiFiDeviceClientRef device, CFDictionaryRef data, const void *object); 28 | typedef void (*WiFiDeviceClientLinkOrPowerCallback)(WiFiDeviceClientRef device, const void *object); 29 | typedef void (*WiFiDeviceScanCallback)(WiFiDeviceClientRef device, CFArrayRef results, int error, const void *object); 30 | typedef void (*WiFiDeviceAssociateCallback)(WiFiDeviceClientRef device, WiFiNetworkRef network, CFDictionaryRef dict, int error, const void *object); 31 | 32 | #pragma mark - API 33 | 34 | CFPropertyListRef WiFiDeviceClientCopyProperty(WiFiDeviceClientRef client, CFStringRef property); 35 | 36 | WiFiNetworkRef WiFiDeviceClientCopyCurrentNetwork(WiFiDeviceClientRef client); 37 | 38 | int WiFiDeviceClientGetPower(WiFiDeviceClientRef client); 39 | void WiFiDeviceClientSetPower(WiFiDeviceClientRef client, int power); 40 | 41 | /* 42 | * The following keys in the dict parameter are understood by wifid: 43 | * "SCAN_CHANNELS": An array of dictionaries containing the 'CHANNEL' and 'CHANNEL_FLAGS' keys. 44 | * "SCAN_MAXAGE": Unknown. Use 2. 45 | * "SCAN_MERGE": Unknown. Use 1. 46 | * "SCAN_NUM_SCANS": Number of scans to perform. 47 | * "SCAN_PHY_MODE": Has something to do with PHY. 48 | * "SCAN_RSSI_THRESHOLD": The RSSI theshold level. Apple uses -80, meaning that networks that have a signal strength lower than -80 will be ignored. 49 | * "SCAN_TYPE": Unknown. Use 1. 50 | */ 51 | int WiFiDeviceClientScanAsync(WiFiDeviceClientRef device, CFDictionaryRef dict, WiFiDeviceScanCallback callback, const void *object); 52 | 53 | /* 54 | * Used to connect to a network. Example usage: 55 | * (Get a WiFiNetworkRef instance from the scan results or something.) 56 | * WiFiNetworkSetPassword(network, CFSTR("Password1")); 57 | * WiFiDeviceClientAssociateAsync(client, network, MyCallbackFunction, NULL); 58 | */ 59 | int WiFiDeviceClientAssociateAsync(WiFiDeviceClientRef client, WiFiNetworkRef network, WiFiDeviceAssociateCallback callback, CFDictionaryRef dict); 60 | void WiFiDeviceClientAssociateCancel(WiFiDeviceClientRef client); 61 | int WiFiDeviceClientDisassociate(WiFiDeviceClientRef client); 62 | 63 | CFStringRef WiFiDeviceClientGetInterfaceName(WiFiDeviceClientRef client); 64 | 65 | /* 66 | * LQM stands for 'Link Quality Metrics': 67 | * Jan 23 15:25:01 kernel[0] : 187357.621783 wlan.A[13651] AppleBCMWLANNetManager::updateLinkQualityMetrics(): Report LQM to User Land 50, fAverageRSSI -71 68 | */ 69 | 70 | void WiFiDeviceClientRegisterLQMCallback(WiFiDeviceClientRef device, WiFiDeviceClientGenericCallback callback, const void *object); 71 | void WiFiDeviceClientRegisterExtendedLinkCallback(WiFiDeviceClientRef device, WiFiDeviceClientGenericCallback callback, const void *object); 72 | void WiFiDeviceClientRegisterLinkCallback(WiFiDeviceClientRef device, WiFiDeviceClientLinkOrPowerCallback callback, const void *object); 73 | void WiFiDeviceClientRegisterPowerCallback(WiFiDeviceClientRef device, WiFiDeviceClientLinkOrPowerCallback callback, const void *object); 74 | 75 | #if __cplusplus 76 | } 77 | #endif 78 | 79 | #endif /* WIFIDEVICECLIENT_H_ */ 80 | -------------------------------------------------------------------------------- /src/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.c 3 | // wifiutil 4 | // 5 | // Created by qpiu on 2016/2/9. 6 | // Copyright (c) 2016年 orangegogo. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import 12 | #import 13 | #import "UtilNetwork.h" 14 | #import "UtilNetworksManager.h" 15 | #import "Constants.h" 16 | #include 17 | 18 | //static WiFiManagerRef _manager; 19 | //static void scan_callback(WiFiDeviceClientRef device, CFArrayRef results, CFErrorRef error, void *token); 20 | //static void scan_networks(); 21 | 22 | int getUsageType(NSString *usage); 23 | void printUsage(); 24 | 25 | int main(int argc, char **argv, char **envp) { 26 | // insert code here... 27 | NSString *hello = @"Hello, wifiutil! Type \x1B[32mwifiutil help \x1B[0mto see usage."; 28 | LOG_OUTPUT(hello); 29 | NSString *str = [NSString stringWithFormat:@"argc = %d", argc]; 30 | //LOG_DBG(str); 31 | /*for (int i = 1; i < argc; i++) { 32 | NSString *str = [NSString stringWithFormat:@"argv[%d] = %s", i, argv[i]]; 33 | LOG_DBG(str); 34 | }*/ 35 | 36 | if (argc < 2) { 37 | LOG_ERR(@"Specify arguments to use wifiutil."); 38 | return -1; 39 | } 40 | 41 | NSString *usage = [NSString stringWithUTF8String:argv[1]]; 42 | str = [NSString stringWithFormat:@"wifiutil: %@", usage]; 43 | LOG_DBG(str); 44 | int usageType = getUsageType(usage); 45 | switch (usageType) 46 | { 47 | case 0: // scan 48 | [[UtilNetworksManager sharedInstance] scan]; 49 | break; 50 | case 1: // associate: wifiutil associate || wifiutil associate -p 51 | // Argument parsing 52 | if (argc < 3) { 53 | LOG_ERR(@"Specify SSID to use wifiutil to associate."); 54 | return -1; 55 | } 56 | NSString *conn_SSID = [NSString stringWithUTF8String:argv[2]]; 57 | NSString *passwd = nil; 58 | if (argc > 3) { // associate with encrypted network 59 | if (argc == 4) { 60 | LOG_ERR(@"Invalid argument format."); 61 | return -1; 62 | } 63 | if ( [[NSString stringWithUTF8String:argv[3]] isEqualToString:@"-p"] ) { 64 | passwd = [NSString stringWithUTF8String:argv[4]]; 65 | str = [NSString stringWithFormat:@"Prepare to associate with network %@, passwd: %@", conn_SSID, passwd]; 66 | LOG_DBG(str); 67 | } 68 | else { 69 | LOG_ERR(@"Invalid argument format."); 70 | return -1; 71 | } 72 | } 73 | else { // associate with open network 74 | str = [NSString stringWithFormat:@"Prepare to associate with network %@", conn_SSID]; 75 | LOG_DBG(str); 76 | } 77 | 78 | // Scan networks first, and get the network instance with the specified SSID. 79 | UtilNetworksManager *manager = [UtilNetworksManager sharedInstance]; 80 | [manager scan]; 81 | 82 | UtilNetwork *conn_Network = [manager getNetworkWithSSID: conn_SSID]; 83 | if (conn_Network) 84 | { 85 | str = [NSString stringWithFormat:@"Found network %@ :)", [conn_Network SSID]]; 86 | LOG_OUTPUT(str); 87 | if ( [[conn_Network encryptionModel] isEqualToString:@"None"]) { // Open network 88 | [manager associateWithNetwork: conn_Network]; 89 | } 90 | else if ( ![[conn_Network encryptionModel] isEqualToString:@"None"]) { // Encrypted network 91 | if (!passwd) 92 | { 93 | LOG_ERR(@"Specify PASSWORD to use associate with encrypted network."); 94 | [manager dealloc]; 95 | return -1; 96 | } 97 | [manager associateWithEncNetwork: conn_Network Password: passwd]; 98 | } 99 | } 100 | else 101 | { 102 | str = [NSString stringWithFormat:@"Can not find network %@ :(", conn_SSID]; 103 | LOG_ERR(str); 104 | [manager dealloc]; 105 | return -1; 106 | } 107 | break; 108 | 109 | case 2: // disassociate 110 | [[UtilNetworksManager sharedInstance] disassociate]; 111 | break; 112 | 113 | case 3: // enable-wifi 114 | //UtilNetworksManager *manager = [UtilNetworksManager sharedInstance]; 115 | str = [NSString stringWithFormat:@"Enable WiFi on iPhone."]; 116 | LOG_DBG(str); 117 | [[UtilNetworksManager sharedInstance] setWiFiEnabled: YES]; 118 | break; 119 | 120 | case 4: // disable-wifi 121 | //UtilNetworksManager *manager = [UtilNetworksManager sharedInstance]; 122 | str = [NSString stringWithFormat:@"Disable WiFi on iPhone."]; 123 | LOG_DBG(str); 124 | [[UtilNetworksManager sharedInstance] setWiFiEnabled: NO]; 125 | break; 126 | 127 | case 5: // ping 128 | if (argc < 3) { 129 | LOG_ERR(@"Specify IP to use wifiutil to ping.\n"); 130 | return -1; 131 | } 132 | NSString *ping_ip = [NSString stringWithUTF8String:argv[2]]; 133 | 134 | // execute ping 135 | NSPipe *pipe = [NSPipe pipe]; 136 | NSFileHandle *file = pipe.fileHandleForReading; 137 | 138 | NSTask *task = [[NSTask alloc] init]; 139 | task.launchPath = @"/usr/bin/ping"; 140 | task.arguments = @[@"-i", @"0.2", @"-c", @"50", ping_ip]; 141 | task.standardOutput = pipe; 142 | [task launch]; 143 | 144 | NSData *data = [file readDataToEndOfFile]; 145 | [file closeFile]; 146 | NSString *output = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding]; 147 | LOG_OUTPUT(output); 148 | LOG_OUTPUT(@"Ping Finished !"); 149 | break; 150 | 151 | case 6: // help 152 | printUsage(); 153 | break; 154 | 155 | default: 156 | LOG_ERR(@"Invalid usage >__< "); 157 | break; 158 | } 159 | 160 | return 0; 161 | } 162 | 163 | int getUsageType(NSString *usage) 164 | { 165 | if ([usage isEqualToString:@"scan"]) { 166 | return 0; 167 | } 168 | else if ([usage isEqualToString:@"associate"]) { 169 | return 1; 170 | } 171 | else if ([usage isEqualToString:@"disassociate"]) { 172 | return 2; 173 | } 174 | else if ([usage isEqualToString:@"enable-wifi"]) { 175 | return 3; 176 | } 177 | else if ([usage isEqualToString:@"disable-wifi"]) { 178 | return 4; 179 | } 180 | else if ([usage isEqualToString:@"ping"]) { 181 | return 5; 182 | } 183 | else if ([usage isEqualToString:@"help"]) { 184 | return 6; 185 | } 186 | else { 187 | return -1; 188 | } 189 | } 190 | 191 | void printUsage() 192 | { 193 | NSString *usage = @"\n########## WifiUtil Usage ##########"; 194 | usage = [NSString stringWithFormat:@"%@\nScan available wifi hotspots:", usage]; 195 | usage = [NSString stringWithFormat:@"%@\n\t\t\x1B[36mwifiutil scan\x1B[0m", usage]; 196 | usage = [NSString stringWithFormat:@"%@\nEnable wifi on iPhone:", usage]; 197 | usage = [NSString stringWithFormat:@"%@\n\t\t\x1B[36mwifiutil enable-wifi\x1B[0m", usage]; 198 | usage = [NSString stringWithFormat:@"%@\nDisable wifi on iPhone:", usage]; 199 | usage = [NSString stringWithFormat:@"%@\n\t\t\x1B[36mwifiutil disable-wifi\x1B[0m", usage]; 200 | usage = [NSString stringWithFormat:@"%@\nAssociate to wifi:", usage]; 201 | usage = [NSString stringWithFormat:@"%@\n\t\t\x1B[36mwifiutil associate \x1B[0m--> For wifi networks without password\x1B[0m", usage]; 202 | usage = [NSString stringWithFormat:@"%@\n\t\t\x1B[36mwifiutil associate -p \x1B[0m--> For wifi networks with password\x1B[0m", usage]; 203 | usage = [NSString stringWithFormat:@"%@\nDisassociate with current wifi network:", usage]; 204 | usage = [NSString stringWithFormat:@"%@\n\t\t\x1B[36mwifiutil disassociate\x1B[0m", usage]; 205 | NSLog(@"%@", usage); 206 | 207 | return; 208 | } 209 | 210 | /*static void scan_networks() 211 | { 212 | _manager = WiFiManagerClientCreate(kCFAllocatorDefault, 0); 213 | 214 | CFArrayRef devices = WiFiManagerClientCopyDevices(_manager); 215 | if (!devices) { 216 | fprintf(stderr, "Couldn't get WiFi devices. Bailing.\n"); 217 | exit(EXIT_FAILURE); 218 | } 219 | 220 | WiFiDeviceClientRef client = (WiFiDeviceClientRef)CFArrayGetValueAtIndex(devices, 0); 221 | 222 | WiFiManagerClientScheduleWithRunLoop(_manager, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); 223 | WiFiDeviceClientScanAsync(client, (CFDictionaryRef)[NSDictionary dictionary], (WiFiDeviceScanCallback)scan_callback, 0); 224 | 225 | CFRelease(devices); 226 | 227 | CFRunLoopRun(); 228 | } 229 | 230 | static void scan_callback(WiFiDeviceClientRef device, CFArrayRef results, CFErrorRef error, void *token) 231 | { 232 | NSLog(@"Finished scanning! networks: %@", results); 233 | 234 | WiFiManagerClientUnscheduleFromRunLoop(_manager); 235 | CFRelease(_manager); 236 | 237 | CFRunLoopStop(CFRunLoopGetCurrent()); 238 | }*/ 239 | 240 | // vim:ft=objc 241 | -------------------------------------------------------------------------------- /src/UtilNetworksManager.m: -------------------------------------------------------------------------------- 1 | // 2 | // UtilNetworksManager.m 3 | // 4 | // 5 | // Created by qpiu on 2016/2/12. 6 | // 7 | // 8 | 9 | #import "UtilNetworksManager.h" 10 | #import "UtilNetwork.h" 11 | #import "Constants.h" 12 | 13 | @interface UtilNetworksManager () 14 | 15 | - (void)_scan; 16 | - (void)_clearNetworks; 17 | - (void)_addNetwork:(UtilNetwork *)network; 18 | - (void)_reloadCurrentNetwork; 19 | - (void)_scanDidFinishWithError:(int)error; 20 | - (void)_associationDidFinishWithError:(int)error; 21 | - (WiFiNetworkRef)_currentNetwork; 22 | 23 | static void UtilScanCallback(WiFiDeviceClientRef device, CFArrayRef results, CFErrorRef error, void *token); 24 | static void UtilAssociationCallback(WiFiDeviceClientRef device, WiFiNetworkRef networkRef, CFDictionaryRef dict, CFErrorRef error, void *token); 25 | 26 | @end 27 | 28 | static UtilNetworksManager *_sharedInstance = nil; 29 | 30 | @implementation UtilNetworksManager 31 | @synthesize networks = _networks; 32 | @synthesize scanning = _scanning; 33 | @synthesize statusCode = _statusCode; 34 | 35 | + (id)sharedInstance 36 | { 37 | @synchronized(self) { 38 | if (!_sharedInstance) 39 | _sharedInstance = [[self alloc] init]; 40 | 41 | return _sharedInstance; 42 | } 43 | } 44 | 45 | - (id)init 46 | { 47 | self = [super init]; 48 | 49 | if (self) { 50 | _manager = WiFiManagerClientCreate(kCFAllocatorDefault, 0); 51 | CFArrayRef devices = WiFiManagerClientCopyDevices(_manager); 52 | if (!devices) { 53 | fprintf(stderr, "Couldn't get WiFi devices. Bailing.\n"); 54 | exit(EXIT_FAILURE); 55 | } 56 | 57 | _client = (WiFiDeviceClientRef)CFArrayGetValueAtIndex(devices, 0); 58 | CFRetain(_client); 59 | CFRelease(devices); 60 | 61 | _networks = [[NSMutableArray alloc] init]; 62 | } 63 | 64 | return self; 65 | } 66 | 67 | - (void)dealloc 68 | { 69 | //CFNotificationCenterRemoveObserver(CFNotificationCenterGetDarwinNotifyCenter(), self, NULL, NULL); 70 | 71 | CFRelease(_currentNetwork); 72 | CFRelease(_client); 73 | CFRelease(_manager); 74 | 75 | [self _clearNetworks]; 76 | 77 | [super dealloc]; 78 | } 79 | 80 | - (void)scan 81 | { 82 | _statusCode = -1; 83 | // If WiFi is off 84 | if(![self isWiFiEnabled]) { 85 | [self setWiFiEnabled: YES]; 86 | [NSThread sleepForTimeInterval:5]; 87 | } 88 | 89 | // Prevent initiating a scan when we're already scanning. 90 | if (_scanning) 91 | return; 92 | _scanning = YES; 93 | 94 | // Reload the current network. 95 | [self _reloadCurrentNetwork]; 96 | 97 | // Actually initiate a scan. 98 | [self _scan]; 99 | } 100 | 101 | - (void)associateWithNetwork:(UtilNetwork *)network 102 | { 103 | _statusCode = -1; 104 | // Prevent initiating an association if we're already associating. 105 | if (_associating) { 106 | LOG_DBG(@"already associating...stop"); 107 | return; 108 | } 109 | 110 | if (_currentNetwork) { 111 | LOG_DBG(@"Disassociate with the current network"); 112 | [self disassociate]; 113 | } 114 | 115 | WiFiManagerClientScheduleWithRunLoop(_manager, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); 116 | 117 | WiFiNetworkRef net = [network _networkRef]; 118 | if(!net) 119 | LOG_ERR(@"Cannot get networkRef"); 120 | 121 | [network setIsAssociating:YES]; 122 | _associating = YES; 123 | LOG_DBG(@"Start associating"); 124 | WiFiDeviceClientAssociateAsync(_client, net, (WiFiDeviceAssociateCallback)UtilAssociationCallback, 0); 125 | CFRunLoopRun(); 126 | } 127 | 128 | - (void)associateWithEncNetwork:(UtilNetwork *)network Password:(NSString *)passwd 129 | { 130 | _statusCode = -1; 131 | // Prevent initiating an association if we're already associating. 132 | if (_associating) { 133 | LOG_DBG(@"already associating...stop"); 134 | return; 135 | } 136 | 137 | if (_currentNetwork) { 138 | // Disassociate with the current network before association. 139 | LOG_DBG(@"Disassociate with the current network"); 140 | [self disassociate]; 141 | } 142 | 143 | WiFiManagerClientScheduleWithRunLoop(_manager, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); 144 | 145 | WiFiNetworkRef net = [network _networkRef]; 146 | if(!net) 147 | LOG_ERR(@"Cannot get networkRef"); 148 | 149 | WiFiNetworkSetPassword(net, (__bridge CFStringRef)passwd); 150 | 151 | [network setIsAssociating:YES]; 152 | _associating = YES; 153 | LOG_DBG(@"Start associating"); 154 | WiFiDeviceClientAssociateAsync(_client, net, (WiFiDeviceAssociateCallback)UtilAssociationCallback, 0); 155 | CFRunLoopRun(); 156 | 157 | } 158 | 159 | - (BOOL)isWiFiEnabled 160 | { 161 | CFBooleanRef enabled = WiFiManagerClientCopyProperty(_manager, CFSTR("AllowEnable")); 162 | BOOL value = CFBooleanGetValue(enabled); 163 | CFRelease(enabled); 164 | return value; 165 | } 166 | 167 | - (void)setWiFiEnabled:(BOOL)enabled 168 | { 169 | CFBooleanRef value = (enabled ? kCFBooleanTrue : kCFBooleanFalse); 170 | WiFiManagerClientSetProperty(_manager, CFSTR("AllowEnable"), value); 171 | return; 172 | } 173 | 174 | - (void)disassociate 175 | { 176 | WiFiDeviceClientDisassociate(_client); 177 | } 178 | 179 | - (UtilNetwork *)getNetworkWithSSID:(NSString *)ssid 180 | { 181 | for(UtilNetwork *network in _networks) 182 | { 183 | if( [[network SSID] isEqualToString:ssid] ) 184 | return network; // network exists 185 | } 186 | return nil; // cannot find the network 187 | } 188 | 189 | - (NSString *)prettyPrintNetworks 190 | { 191 | NSString *output = [[NSString alloc] init]; 192 | NSString *str = [[NSString alloc] init]; 193 | 194 | for(UtilNetwork *network in _networks) 195 | { 196 | str = [NSString stringWithFormat:@" %30s\t| %20s\t| %s %d\t", [[network SSID] UTF8String], [[network BSSID] UTF8String], "channel", [network channel]]; 197 | output = [NSString stringWithFormat:@"%@\n%@", output, str]; 198 | } 199 | return output; 200 | } 201 | 202 | #pragma mark - Private APIs 203 | 204 | - (void)_scan 205 | { 206 | //LOG_DBG(@"Scanning...\n"); 207 | WiFiManagerClientScheduleWithRunLoop(_manager, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); 208 | WiFiDeviceClientScanAsync(_client, (CFDictionaryRef)[NSDictionary dictionary], (WiFiDeviceScanCallback)UtilScanCallback, 0); 209 | CFRunLoopRun(); 210 | } 211 | 212 | - (void)_clearNetworks 213 | { 214 | [_networks removeAllObjects]; 215 | } 216 | 217 | - (void)_addNetwork:(UtilNetwork *)network 218 | { 219 | [_networks addObject:network]; 220 | } 221 | 222 | - (WiFiNetworkRef)_currentNetwork 223 | { 224 | return _currentNetwork; 225 | } 226 | 227 | - (void)_reloadCurrentNetwork 228 | { 229 | if (_currentNetwork) { 230 | CFRelease(_currentNetwork); 231 | _currentNetwork = nil; 232 | } 233 | 234 | _currentNetwork = WiFiDeviceClientCopyCurrentNetwork(_client); 235 | } 236 | 237 | - (void)_scanDidFinishWithError:(int)error 238 | { 239 | WiFiManagerClientUnscheduleFromRunLoop(_manager); 240 | //NSString *str = [NSString stringWithFormat:@"Scanning finished code: %d", error]; 241 | //LOG_DBG(str); 242 | _statusCode = error; 243 | if (_statusCode == 0) { 244 | LOG_OUTPUT(@"Scanning is successful :) "); 245 | } 246 | else if (_statusCode < 0) { 247 | LOG_DBG(@"Scanning failed :( "); 248 | } 249 | _scanning = NO; 250 | } 251 | 252 | - (void)_associationDidFinishWithError:(int)error 253 | { 254 | WiFiManagerClientUnscheduleFromRunLoop(_manager); 255 | 256 | for (UtilNetwork *network in [[UtilNetworksManager sharedInstance] networks]) { 257 | if ([network isAssociating]) 258 | [network setIsAssociating:NO]; 259 | } 260 | //NSString *str = [NSString stringWithFormat:@"Association finished code: %d", error]; 261 | //LOG_DBG(str); 262 | _statusCode = error; 263 | if (_statusCode == 0) { 264 | LOG_OUTPUT(@"Association is successful :) "); 265 | } 266 | else if (_statusCode < 0) { 267 | LOG_DBG(@"Association failed :( "); 268 | } 269 | 270 | _associating = NO; 271 | // Reload the current network. 272 | [self _reloadCurrentNetwork]; 273 | } 274 | 275 | #pragma mark - Functions 276 | 277 | static void UtilScanCallback(WiFiDeviceClientRef device, CFArrayRef results, CFErrorRef error, void *token) 278 | { 279 | //NSString *str = [NSString stringWithFormat:@"Finished scanning! %lu networks: %@", (unsigned long)[(__bridge NSArray *)results count], results]; 280 | //LOG_OUTPUT(str); 281 | CFRunLoopStop(CFRunLoopGetCurrent()); 282 | 283 | [[UtilNetworksManager sharedInstance] _clearNetworks]; 284 | for (unsigned x = 0; x < CFArrayGetCount(results); x++) { 285 | WiFiNetworkRef networkRef = (WiFiNetworkRef)CFArrayGetValueAtIndex(results, x); 286 | 287 | UtilNetwork *network = [[UtilNetwork alloc] initWithNetwork:networkRef]; 288 | [network populateData]; 289 | 290 | WiFiNetworkRef currentNetwork = [[UtilNetworksManager sharedInstance] _currentNetwork]; 291 | 292 | // WiFiNetworkGetProperty() crashes if the network parameter is NULL therefore we need to check if it exists first. 293 | if (currentNetwork) { 294 | if ([[network BSSID] isEqualToString:(NSString *)WiFiNetworkGetProperty(currentNetwork, CFSTR("BSSID"))]) 295 | [network setIsCurrentNetwork:YES]; 296 | } 297 | 298 | BOOL netExists = 0; 299 | for (UtilNetwork *n in [[UtilNetworksManager sharedInstance] networks]) 300 | { 301 | if ( [[n BSSID] isEqualToString: [network BSSID]] ) { 302 | netExists = 1; 303 | NSString *str = [NSString stringWithFormat:@"(%@, %@) is already exists.", [network SSID], [network BSSID]]; 304 | LOG_DBG(str); 305 | break; // network is already in _networks 306 | } 307 | } 308 | if (!netExists) 309 | [[UtilNetworksManager sharedInstance] _addNetwork: network]; 310 | 311 | [network release]; 312 | } 313 | NSString *str = [NSString stringWithFormat:@"Finished scanning! %lu networks: %@", 314 | (unsigned long)[[[UtilNetworksManager sharedInstance] networks] count], [[UtilNetworksManager sharedInstance] prettyPrintNetworks]]; 315 | LOG_OUTPUT(str); 316 | [[UtilNetworksManager sharedInstance] _scanDidFinishWithError:(int)error]; 317 | } 318 | 319 | static void UtilAssociationCallback(WiFiDeviceClientRef device, WiFiNetworkRef networkRef, CFDictionaryRef dict, CFErrorRef error, void *token) 320 | { 321 | CFRunLoopStop(CFRunLoopGetCurrent()); 322 | // Reload every network's data. 323 | for (UtilNetwork *network in [[UtilNetworksManager sharedInstance] networks]) { 324 | [network populateData]; 325 | 326 | if (networkRef) { 327 | [network setIsCurrentNetwork:[[network BSSID] isEqualToString:(NSString *)WiFiNetworkGetProperty(networkRef, CFSTR("BSSID"))]]; 328 | } 329 | } 330 | 331 | [[UtilNetworksManager sharedInstance] _associationDidFinishWithError:(int)error]; 332 | 333 | } 334 | 335 | /*static void UtilReceivedNotification(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo) 336 | { 337 | [(UtilNetworksManager *)observer _receivedNotificationNamed:(NSString *)name]; 338 | }*/ 339 | 340 | @end 341 | --------------------------------------------------------------------------------