Как обнаружить изменение адреса IPv4 в macOS с помощью инфраструктуры SystemConfiguration - PullRequest
0 голосов
/ 29 января 2019

Я пытаюсь использовать SystemConfiguration в Mac OS, чтобы получить уведомление, когда на Mac появляется новый сетевой интерфейс и ему назначен новый IP-адрес.

Я настроил его для наблюдения засистемный конфигурационный ключ State:/Network/Interface, и он работает так, что я получаю уведомление всякий раз, когда новый сетевой интерфейс появляется или исчезает.

Однако я хотел бы получать уведомление всякий раз, когда IPv4-адрес назначается на новом сетевом интерфейсе (например,по DHCP).Я знаю, что ключ State:/Network/Interface/en0/IPv4 содержит адрес IPv4 для интерфейса en0.Но использование регулярных выражений, как показано на странице руководства для всех адресов IPv4 State:/Network/Interface/.*/IPv4, не работает для нового интерфейса.

Я собрал небольшой пример минимального кода на github, однако можно также использовать scutil инструмент командной строки.

Ссылка на демонстрационный репозиторий

main.c

#import <Foundation/Foundation.h>
#import <SystemConfiguration/SystemConfiguration.h>

/* Callback used if a configuration change on monitored keys was detected.
 */
void dynamicStoreCallback(SCDynamicStoreRef store, CFArrayRef changedKeys, void* __nullable info) {
    CFIndex count = CFArrayGetCount(changedKeys);
    for (CFIndex i=0; i<count; i++) {
        NSLog(@"Key \"%@\" was changed", CFArrayGetValueAtIndex(changedKeys, i));
    }
}

int main(int argc, const char * argv[]) {
    NSArray *SCMonitoringInterfaceKeys = @[@"State:/Network/Interface.*"];
    @autoreleasepool {
        SCDynamicStoreRef dsr = SCDynamicStoreCreate(NULL, CFSTR("network_interface_detector"), &dynamicStoreCallback, NULL);
        SCDynamicStoreSetNotificationKeys(dsr, CFBridgingRetain(SCMonitoringInterfaceKeys), NULL);
        CFRunLoopAddSource(CFRunLoopGetCurrent(), SCDynamicStoreCreateRunLoopSource(NULL, dsr, 0), kCFRunLoopDefaultMode);
        NSLog(@"Starting RunLoop...");
        while([[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]);
    }
    return 0;
}

1 Ответ

0 голосов
/ 17 февраля 2019

С помощью коллег-разработчиков я выяснил, что пошло не так.Подпись для функции SCDynamicStoreSetNotificationKeys выглядит следующим образом:

Boolean SCDynamicStoreSetNotificationKeys (SCDynamicStoreRef store,
                CFArrayRef          __nullable  keys,
                CFArrayRef          __nullable  patterns
                )

Это означает, что я должен установить шаблон отдельно от ключей, которые действуют как корень дерева, под которым будет происходить сопоставление с шаблоном.Вот модифицированная версия моего main.m :

int main(int argc, const char * argv[]) {
    NSArray *SCMonitoringInterfaceKeys = @[@"State:/Network/Interface"];
    NSArray *patterns = @[@"en\\d*/IPv4"];
    @autoreleasepool {
        SCDynamicStoreRef dsr = SCDynamicStoreCreate(NULL, CFSTR("network_interface_detector"), &dynamicStoreCallback, NULL);
        SCDynamicStoreSetNotificationKeys(dsr, CFBridgingRetain(SCMonitoringInterfaceKeys), CFBridgingRetain(patterns));
        CFRunLoopAddSource(CFRunLoopGetCurrent(), SCDynamicStoreCreateRunLoopSource(NULL, dsr, 0), kCFRunLoopDefaultMode);
        NSLog(@"Starting RunLoop...");
        while([[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]);
    }
    return 0;
}

Я включил решение в решенную ветку репо .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...