-
-
Save wolever/4418079 to your computer and use it in GitHub Desktop.
#import <CoreWLAN/CoreWLAN.h> | |
#import <objc/message.h> | |
int main(int argc, char* argv[]) { | |
@autoreleasepool { | |
int ch; | |
NSString *ssid = nil, *password = nil; | |
while((ch = getopt(argc, argv, "s:p:h")) != -1) { | |
switch(ch) { | |
case 's': | |
ssid = [NSString stringWithUTF8String:optarg]; | |
break; | |
case 'p': | |
password = [NSString stringWithUTF8String:optarg]; | |
break; | |
case '?': | |
case 'h': | |
default: | |
printf("USAGE: %s [-s ssid] [-p password] [-h] command\n", argv[0]); | |
printf("\nOPTIONS:\n"); | |
printf(" -s ssid SSID\n"); | |
printf(" -p password WEP password\n"); | |
printf(" -h Print help\n"); | |
printf("\nCOMMAND:\n"); | |
printf(" status Print interface mode\n"); | |
printf(" start Start Host AP mode\n"); | |
printf(" stop Stop Host AP mode\n"); | |
return 0; | |
} | |
} | |
NSString *command = nil; | |
if(argv[optind]) { | |
command = [NSString stringWithUTF8String:argv[optind]]; | |
} | |
CWInterface *iface = [CWInterface interface]; | |
if(!command || [command isEqualToString:@"status"]) { | |
NSString *mode = nil; | |
switch(iface.interfaceMode) { | |
case kCWInterfaceModeStation: | |
mode = @"Station"; | |
break; | |
case kCWInterfaceModeIBSS: | |
mode = @"IBSS"; | |
break; | |
case kCWInterfaceModeHostAP: | |
mode = @"HostAP"; | |
break; | |
case kCWInterfaceModeNone: | |
default: | |
mode = @"None"; | |
} | |
printf("%s\n", [mode UTF8String]); | |
} else if([command isEqualToString:@"stop"]) { | |
// Stop Host AP mode | |
if(getuid() != 0) { | |
printf("this may need root (trying anyway)...\n"); | |
} | |
objc_msgSend(iface, @selector(stopHostAPMode)); | |
} else if([command isEqualToString:@"start"]) { | |
if(!ssid) { | |
printf("error: an ssid must be specified\n"); | |
return 1; | |
} | |
// known security types: | |
// 2: no securiry | |
// 16: wep | |
// Note: values [-127..127] have been tried, and all but these return errors. | |
int securityType = 2; | |
if(password) { | |
if([password length] < 10) { | |
printf("error: password too short (must be >= 10 characters)\n"); | |
return 1; | |
} | |
securityType = 16; | |
} | |
NSSet *chans = [iface supportedWLANChannels]; | |
//printf("chan count: %lu\n", [chans count]); | |
NSEnumerator *enumerator = [chans objectEnumerator]; | |
CWChannel *channel; | |
while ((channel = [enumerator nextObject])) { | |
//printf("channel: %lu\n", [channel channelNumber]); | |
if ([channel channelNumber] == 9) | |
break; | |
} | |
// Start Host AP mode | |
NSError *error = nil; | |
objc_msgSend(iface, | |
//@selector(startIBSSModeWithSSID:security:channel:password:error:), | |
@selector(startHostAPModeWithSSID:securityType:channel:password:error:), | |
//[@"hunter2" dataUsingEncoding:NSUTF8StringEncoding], | |
[ssid dataUsingEncoding:NSUTF8StringEncoding], | |
securityType, | |
channel, | |
//@"abc123ffff", | |
password, | |
&error); | |
if(error) { | |
printf("startHostAPModeWithSSID error: %s\n", [error.localizedDescription UTF8String]); | |
return 1; | |
} | |
} | |
return 0; | |
} | |
} |
all: hostap | |
hostap: hostap.m | |
clang -framework Foundation -framework CoreWLAN -o $@ $< | |
clean: | |
rm -rf hostap |
Copyright (C) 2012 Yoshimasa Niwa | |
Permission is hereby granted, free of charge, to any person obtaining | |
a copy of this software and associated documentation files (the | |
"Software"), to deal in the Software without restriction, including | |
without limitation the rights to use, copy, modify, merge, publish, | |
distribute, sublicense, and/or sell copies of the Software, and to | |
permit persons to whom the Software is furnished to do so, subject to | |
the following conditions: | |
The above copyright notice and this permission notice shall be | |
included in all copies or substantial portions of the Software. | |
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE | |
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | |
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | |
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
Here is a solution that works for 10.10: http://stackoverflow.com/questions/31342348/programmatically-create-ad-hoc-network-os-x
That's not a "solution" for 10.10, that creates an ad-hoc (IBSS) network with its huge limitations. This script, in contrast, used to create a full access point.
This seems to work partially on 10.14. Running sudo ./hostap -s MyNetworkName start
successfully enters HostAP mode and creates the access point (you can see the Wi-Fi icon in the menu bar turn to the one with the up arrow). I can see the access point exists in the Wi-Fi menus of my iOS and Android devices, but when I attempt to join the on any device, the device stalls and does not join the network (on Android the Wi-Fi listing says "obtaining IP address" continuously and on iOS the Wi-Fi listing keeps showing the loading symbol). Is there any way around this issue?
Another error I run into: if I try to start HostAP mode with a password sudo ./hostap -s MyNetworkName -p 12345abcde start
, I get the error:
startHostAPModeWithSSID error: The operation couldn’t be completed. (com.apple.wifi.apple80211API.error error -3900.)
Has anyone come across any solution to enter HostAP mode programmatically?
It works in 10.10 for a couple of seconds. Drops connection then. It would be really appreciated if someone experienced can troubleshoot this because there is no option to create a secured WiFi network in Yosemite.