【问题标题】:Programmatically creating an ad-hoc network in Big Sur以编程方式在 Big Sur 中创建自组织网络
【发布时间】:2022-01-11 13:06:12
【问题描述】:

在 Mac OS Big Sur 之前,可以通过调用从 CWWifiClient 获得的 CWInterfacestartIBSSModeWithSSID:security:channel:password:error: 函数来创建自组织网络。好像在更新到 Big Sur 之后,上面的函数就被弃用了,每次都会抛出一个kCWOperationNotPermittedErr (-3930) 错误。

我尝试从 root 启动应用程序,但它仍然拒绝创建 ad-hoc 网络。同时,使用 WiFi 下拉菜单中的“创建网络”选项需要管理员密码。

我在此站点上遇到的先前答案已过时,代码不再起作用。 5 个月前在 Apple 开发者论坛上创建了一个帖子,但仍未得到答复,“解决方案”是提交技术支持事件。

这是我正在使用的代码:

#import <Foundation/Foundation.h>
#import <CoreWLAN/CoreWLAN.h>
#import <SecurityFoundation/SFAuthorization.h>
#import <objc/message.h>

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        bool success = 0;
        
        CWWiFiClient* wifiClient = [CWWiFiClient sharedWiFiClient];
        CWInterface* interface = [wifiClient interface];
        
        NSString* namestr = @"very_creative_ssid";
        NSData* name = [namestr dataUsingEncoding:NSUTF8StringEncoding];
        NSString* pass = @"very_cruel_framework"; // not used
        NSError* err = nil;
        
        success = [interface startIBSSModeWithSSID:name
                                               security:kCWIBSSModeSecurityNone
                                                channel:11
                                               password:nil
                                                  error:&err];
        
        if (!success) {
            NSLog(@"%@", err);
            return 1;
        }
        
        [NSRunLoop.currentRunLoop run];
    }
    return 0;
}

有没有办法以编程方式在 Big Sur 中创建自组织网络而不会引发错误?

编辑:这是控制台输出(1 行):

2022-01-12 05:25:03.723 cwlantest[15305:448617] Error Domain=com.apple.coreWLAN.error Code=-3930 "(null)"

【问题讨论】:

  • startIBSSModeWithSSID 在开发人员文档中被标记为已弃用,因为它在较新的硬件上不受支持(我在 m1 上,所以他们可能完全放弃了对 IBSS 模式的支持?)。我能够使用网络共享创建一个 ad-hoc 网络,所以我不认为完全是这样。

标签: objective-c macos macos-big-sur corewlan


【解决方案1】:

我将把它作为一个答案,如果有人发现任何新东西或苹果将来添加此功能,我会很高兴错了。

TLDR:不再!

由于 Apple 从 wifi 菜单栏中删除了“创建网络...”选项,创建 ad-hoc 网络的唯一方法是通过网络共享。我跟着https://www.makeuseof.com/how-to-create-a-secure-ad-hoc-network-in-macos/How to Create a Secure Ad Hoc Network部分下做了一个网络:

sudo networksetup -createnetworkservice AdHoc lo0
sudo networksetup -setmanual AdHoc 192.168.1.88 255.255.255.255

在“系统偏好设置”中,通过 WiFi 从 AdHoc 共享您的网络连接。

打开之后,我检查了 CWInterface.interfaceMode(),它处于 HostAP 模式。纯属猜测,但我认为 IBSS 已被完全删除,它在开发人员文档中被标记为已弃用。 -3930 是 kCWOperationNotPermittedErr,所以我不能 100% 确定这是准确的,但这是可能的。

CoreWLAN中有设置HostAP模式的私有接口:

https://github.com/onmyway133/Runtime-Headers/blob/master/macOS/10.13/CoreWLAN.framework/CWInterface.hhttps://medium.com/swlh/calling-ios-and-macos-hidden-api-in-style-1a924f244ad1https://gist.github.com/wolever/4418079

在最后一个链接中将objc_msgsend 替换为NSInvocation 后,objc_msgsend 似乎已被删除:

#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 = [[CWWiFiClient sharedWiFiClient] 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");
      }
        SEL selector = @selector(stopHostAPMode);
        NSMethodSignature *signature = [iface methodSignatureForSelector: selector];
        NSInvocation *invocation =
        [NSInvocation invocationWithMethodSignature:signature];
        invocation.target = iface;
        invocation.selector = selector;
        
        [invocation invoke];
        printf("Done?");
        
      //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.
      unsigned long long 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] == 11)
          break;
      }
        
        printf("Found Channel: %d\n", channel.channelNumber);

        // Start Host AP mode
        NSError *error = nil;
        NSError **errorptr = &error;
        
        SEL selector = @selector(startHostAPModeWithSSID:securityType:channel:password:error:);
        NSMethodSignature *signature = [iface methodSignatureForSelector: selector];
        NSInvocation *invocation =
        [NSInvocation invocationWithMethodSignature:signature];
        invocation.target = iface;
        invocation.selector = selector;
            NSString * ssidstr = @"Test";
            NSString * pass = @"barbarbarr";
        NSData * ssidArg = [ssidstr dataUsingEncoding:NSUTF8StringEncoding];
        [invocation setArgument: &ssidArg atIndex:2];
        [invocation setArgument: &securityType atIndex:3];
        [invocation setArgument: &channel atIndex:4];
        [invocation setArgument: &pass atIndex:5];
        [invocation setArgument: &errorptr atIndex:6];
        
        [invocation invoke];
        BOOL success;
        [invocation getReturnValue:&success];
        
        if (!success) {
            printf("startHostAPModeWithSSID error: %s\n", [(*errorptr).localizedDescription UTF8String]);
            return 1;
        } else {
            printf("Success?\n");
            return 0;
        }
    }

    return 0;
  }
}

./hostap stop 确实成功地将我从网络共享启动的 hostap 模式中踢了出来,但 ./hostap start 失败并显示 -3903 kCWNotSupportedErr。 此外,在没有其他设置的情况下使用startHostAPMode: 确实成功,但是 wifi 菜单显示WiFi: Internet Sharing,所以我认为这是一个专用于网络共享的私有 api,可能需要其他配置才能正常工作。你可能会继续沿着这条路走下去,但它看起来并不是很有希望。最好的办法是仅使用网络共享,或者如果您真的想要脚本化方法,则可能会使用 AppleScript 研究脚本系统偏好设置。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-07-11
    • 2013-01-01
    • 1970-01-01
    • 2010-11-21
    • 1970-01-01
    • 2013-01-15
    • 2010-10-30
    • 1970-01-01
    相关资源
    最近更新 更多