Objective c 如何获取Mac OS网络配置 背景

Objective c 如何获取Mac OS网络配置 背景,objective-c,macos,Objective C,Macos,我正在开发一个应用程序来监控公司网络中的机器。 每台机器都将运行我的应用程序,它会跟踪许多有关机器状态的信息 我想跟踪的事情之一是网络配置 网络接口列表 ipv4 ipv6 名字 问题: 我可以获取网络设备列表(),或者获取其MAC地址或BSD名称 我在获取两个协议(IPv4和IPv6)的机器IP地址信息时遇到问题 我尝试了使用和,但只有空值和返回值 在SCNetworkInterfaceGetTextEndedConfiguration的情况下,我使用了以下值:kSCEntNetIPSec

我正在开发一个应用程序来监控公司网络中的机器。 每台机器都将运行我的应用程序,它会跟踪许多有关机器状态的信息

我想跟踪的事情之一是网络配置

  • 网络接口列表
  • ipv4
  • ipv6
  • 名字
问题: 我可以获取网络设备列表(),或者获取其MAC地址或BSD名称

我在获取两个协议(IPv4和IPv6)的机器IP地址信息时遇到问题

我尝试了使用和,但只有空值和返回值

SCNetworkInterfaceGetTextEndedConfiguration
的情况下,我使用了以下值:
kSCEntNetIPSec
kSCEntNetIPv4
kSCEntNetIPv6

文档不够精确和清晰,所以我知道这个API在哪里使用,这给了我一些提示,但仍然没有帮助

我做错了什么

这里我用一些测试代码来探索API(它是C++代码,因为我移植到MAC):

#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
内联作废myRelease(CFTypeRef p)
{
如果(p)CFP释放(p);
}
内联标准::字符串toStd(CFStringRef s)
{
如果(!s){
返回{};
}
if(auto fastCString=CFStringGetCStringPtr(s,kcfstringcodingutf8)){
返回快速字符串;
}
自动长度=CFStringGetLength(s);
自动大小=CFStringGetMaximumSizeForncoding(CFStringGetLength,kCFStringEncodingUTF8)+1;
std::字符串结果(大小,'\0');
CFStringGetBytes(s,{0,len},kCFStringEncodingUTF8',?',0,
重新解释_cast(&result[0]),result.size(),&size);
结果:调整大小(大小);
返回结果;
}

std::奥斯特拉姆和操作员感谢@Hofi和@johnelemans的帮助。这些暗示足以找到答案。 对于可能存在类似问题的其他人:

要获取Mac地址,必须使用。我可以从中获取连接详细信息,稍后需要这些信息

现在API的使用有点奇怪。 要探索可以做什么,可以使用命令行工具:。 最好在没有参数的情况下运行它,并键入以下命令:

list
list State:/Network/Interfaces/.*
get State:/Network/Interface/en0/IPv6
d.show
我找到了

根据从这个工具获得的信息,我想出了如何获取所需的数据。 C++中的测试代码:

#include <iostream>
#include <string>

#include <SystemConfiguration/SystemConfiguration.h>
#include <CoreFoundation/CoreFoundation.h>

inline void myRelease(CFTypeRef p)
{
    if (p) CFRelease(p);
}

inline std::string toStd(CFStringRef s)
{
    if (!s) {
        return {};
    }
    if (auto fastCString = CFStringGetCStringPtr(s, kCFStringEncodingUTF8)) {
        return fastCString;
    }
    auto len = CFStringGetLength(s);
    auto size = CFStringGetMaximumSizeForEncoding(CFStringGetLength(s), kCFStringEncodingUTF8) + 1;
    std::string result(size, '\0');

    CFStringGetBytes(s, { 0, len }, kCFStringEncodingUTF8, '?', 0,
                     reinterpret_cast<UInt8 *>(&result[0]), result.size(), &size);
    result.resize(size);

    return result;
}

std::ostream &operator<<(std::ostream &out, CFStringRef s) {
    return out << toStd(s);
}

struct DebugCf {
    DebugCf(CFTypeRef p) : mP(p) {}
    std::string toString() const {
        if (!mP) {
            return "<null>";
        }
        auto idOfType = CFGetTypeID(mP);
        if (CFStringGetTypeID() == idOfType) {
           return toStd((CFStringRef)mP);
        }
        auto s = CFCopyDescription(mP);
        auto result = toStd(s);
        CFRelease(s);

        return result;
    }

private:
    CFTypeRef mP;
};

std::ostream &operator<<(std::ostream &out, const DebugCf d) {
    return out << d.toString();
}

#define LOGCF(x) " " #x "["<< DebugCf(x) << "], "

std::string SCErrorString()
{
    switch (SCError()) {
        case kSCStatusOK: return "OK";
        case kSCStatusFailed: return "Failed";
        case kSCStatusInvalidArgument: return "InvalidArgument";
        case kSCStatusAccessError: return "AccessError";
        case kSCStatusNoKey: return "NoKey";
        case kSCStatusKeyExists: return "KeyExists";
        case kSCStatusLocked: return "Locked";
        case kSCStatusNeedLock: return "NeedLock";
        case kSCStatusNoStoreSession: return "NoStoreSession";
        case kSCStatusNoStoreServer: return "NoStoreServer";
        case kSCStatusNotifierActive: return "NotifierActive";
        case kSCStatusNoPrefsSession: return "NoPrefsSession";
        case kSCStatusPrefsBusy: return "PrefsBusy";
        case kSCStatusNoConfigFile: return "NoConfigFile";
        case kSCStatusNoLink: return "NoLink";
        case kSCStatusStale: return "Stale";
        case kSCStatusMaxLink: return "MaxLink";
        case kSCStatusReachabilityUnknown: return "ReachabilityUnknown";

        default:
            return std::to_string(SCError());
    }
}

void exploreServiceQuery(CFStringRef query, CFStringRef serviceId, SCDynamicStoreRef scSession) {
    auto resolvedQuery =
    CFStringCreateWithFormat(kCFAllocatorDefault,
                             NULL,
                             query, serviceId);

    auto dic = (CFDictionaryRef)SCDynamicStoreCopyValue(scSession,
                                                        resolvedQuery);

    std::cout << resolvedQuery << " - " << LOGCF(dic) << '\n';

    myRelease(dic);
    CFRelease(resolvedQuery);
}

void printIpv4Data(SCDynamicStoreRef scSession,
                   CFStringRef bsdName) {
    exploreServiceQuery(CFSTR("State:/Network/Interface/%@/IPv4"),
                        bsdName,
                        scSession);
}

void printIpv6Data(SCDynamicStoreRef scSession,
                   CFStringRef bsdName) {
    exploreServiceQuery(CFSTR("State:/Network/Interface/%@/IPv6"),
                        bsdName,
                        scSession);
}

void desiriedData() {
    auto allInterfaces = SCNetworkInterfaceCopyAll();

    auto scSession = SCDynamicStoreCreate(kCFAllocatorDefault,
                                          CFSTR("Custom"),
                                          NULL,
                                          NULL);

    auto count = CFArrayGetCount(allInterfaces);
    for (CFIndex i = 0; i < count; ++i) {
        auto netInterface = (SCNetworkInterfaceRef)CFArrayGetValueAtIndex(allInterfaces, i);

        auto macString = SCNetworkInterfaceGetHardwareAddressString(netInterface);
        auto bsdName = SCNetworkInterfaceGetBSDName(netInterface);

        std::cout << bsdName << " " << macString << '\n';
        printIpv4Data(scSession, bsdName);
        printIpv6Data(scSession, bsdName);
    }

    CFRelease(scSession);
    CFRelease(allInterfaces);
}

int main(int argc, const char * argv[]) {
    desiriedData();

    return 0;
}
#包括
#包括
#包括
#包括
内联作废myRelease(CFTypeRef p)
{
如果(p)CFP释放(p);
}
内联标准::字符串toStd(CFStringRef s)
{
如果(!s){
返回{};
}
if(auto fastCString=CFStringGetCStringPtr(s,kcfstringcodingutf8)){
返回快速字符串;
}
自动长度=CFStringGetLength(s);
自动大小=CFStringGetMaximumSizeForncoding(CFStringGetLength,kCFStringEncodingUTF8)+1;
std::字符串结果(大小,'\0');
CFStringGetBytes(s,{0,len},kCFStringEncodingUTF8',?',0,
重新解释_cast(&result[0]),result.size(),&size);
结果:调整大小(大小);
返回结果;
}

标准:奥斯特雷姆和运营商FWIW;我在swift中写下了这一点,对于SCNetworkInterfaceGetConfiguration和扩展调用,它也返回nil。这种方法是否可行;你查过菜单的来源了吗@谢谢,这很有帮助
#include <iostream>
#include <string>

#include <SystemConfiguration/SystemConfiguration.h>
#include <CoreFoundation/CoreFoundation.h>

inline void myRelease(CFTypeRef p)
{
    if (p) CFRelease(p);
}

inline std::string toStd(CFStringRef s)
{
    if (!s) {
        return {};
    }
    if (auto fastCString = CFStringGetCStringPtr(s, kCFStringEncodingUTF8)) {
        return fastCString;
    }
    auto len = CFStringGetLength(s);
    auto size = CFStringGetMaximumSizeForEncoding(CFStringGetLength(s), kCFStringEncodingUTF8) + 1;
    std::string result(size, '\0');

    CFStringGetBytes(s, { 0, len }, kCFStringEncodingUTF8, '?', 0,
                     reinterpret_cast<UInt8 *>(&result[0]), result.size(), &size);
    result.resize(size);

    return result;
}

std::ostream &operator<<(std::ostream &out, CFStringRef s) {
    return out << toStd(s);
}

struct DebugCf {
    DebugCf(CFTypeRef p) : mP(p) {}
    std::string toString() const {
        if (!mP) {
            return "<null>";
        }
        auto idOfType = CFGetTypeID(mP);
        if (CFStringGetTypeID() == idOfType) {
           return toStd((CFStringRef)mP);
        }
        auto s = CFCopyDescription(mP);
        auto result = toStd(s);
        CFRelease(s);

        return result;
    }

private:
    CFTypeRef mP;
};

std::ostream &operator<<(std::ostream &out, const DebugCf d) {
    return out << d.toString();
}

#define LOGCF(x) " " #x "["<< DebugCf(x) << "], "

std::string SCErrorString()
{
    switch (SCError()) {
        case kSCStatusOK: return "OK";
        case kSCStatusFailed: return "Failed";
        case kSCStatusInvalidArgument: return "InvalidArgument";
        case kSCStatusAccessError: return "AccessError";
        case kSCStatusNoKey: return "NoKey";
        case kSCStatusKeyExists: return "KeyExists";
        case kSCStatusLocked: return "Locked";
        case kSCStatusNeedLock: return "NeedLock";
        case kSCStatusNoStoreSession: return "NoStoreSession";
        case kSCStatusNoStoreServer: return "NoStoreServer";
        case kSCStatusNotifierActive: return "NotifierActive";
        case kSCStatusNoPrefsSession: return "NoPrefsSession";
        case kSCStatusPrefsBusy: return "PrefsBusy";
        case kSCStatusNoConfigFile: return "NoConfigFile";
        case kSCStatusNoLink: return "NoLink";
        case kSCStatusStale: return "Stale";
        case kSCStatusMaxLink: return "MaxLink";
        case kSCStatusReachabilityUnknown: return "ReachabilityUnknown";

        default:
            return std::to_string(SCError());
    }
}

void exploreServiceQuery(CFStringRef query, CFStringRef serviceId, SCDynamicStoreRef scSession) {
    auto resolvedQuery =
    CFStringCreateWithFormat(kCFAllocatorDefault,
                             NULL,
                             query, serviceId);

    auto dic = (CFDictionaryRef)SCDynamicStoreCopyValue(scSession,
                                                        resolvedQuery);

    std::cout << resolvedQuery << " - " << LOGCF(dic) << '\n';

    myRelease(dic);
    CFRelease(resolvedQuery);
}

void printIpv4Data(SCDynamicStoreRef scSession,
                   CFStringRef bsdName) {
    exploreServiceQuery(CFSTR("State:/Network/Interface/%@/IPv4"),
                        bsdName,
                        scSession);
}

void printIpv6Data(SCDynamicStoreRef scSession,
                   CFStringRef bsdName) {
    exploreServiceQuery(CFSTR("State:/Network/Interface/%@/IPv6"),
                        bsdName,
                        scSession);
}

void desiriedData() {
    auto allInterfaces = SCNetworkInterfaceCopyAll();

    auto scSession = SCDynamicStoreCreate(kCFAllocatorDefault,
                                          CFSTR("Custom"),
                                          NULL,
                                          NULL);

    auto count = CFArrayGetCount(allInterfaces);
    for (CFIndex i = 0; i < count; ++i) {
        auto netInterface = (SCNetworkInterfaceRef)CFArrayGetValueAtIndex(allInterfaces, i);

        auto macString = SCNetworkInterfaceGetHardwareAddressString(netInterface);
        auto bsdName = SCNetworkInterfaceGetBSDName(netInterface);

        std::cout << bsdName << " " << macString << '\n';
        printIpv4Data(scSession, bsdName);
        printIpv6Data(scSession, bsdName);
    }

    CFRelease(scSession);
    CFRelease(allInterfaces);
}

int main(int argc, const char * argv[]) {
    desiriedData();

    return 0;
}