ホーム > Mac, Objective-C, 開発 > SystemConfiguration.framework でネットワークの情報を得る

SystemConfiguration.framework でネットワークの情報を得る

2010 年 01 月 19 日 コメントをどうぞ コメント

Mac アプリのプログラミングで、SystemConfiguration.framework の DynamicStore を利用すると、ネットワーク関連の現在状態や設定値を取得できます。ネットワーク以外にもいくつか取得できたりします。

SystemConfiguration.framework は C 言語の API が用意されており、Objective-C の API はありません。関数等の接頭詞は “SC” です。

キー。

DynamicStore は名前からも分かるとおり現在のダイナミック(動的)な設定情報・状態値を保持していて、URI 形式のキーで値を取得することができます。
State:/Network/Global/DNS
といった表記でキーが表されます。キーは多岐にわたりますし、特定の文法で記載されるので、簡単にキーを取得するためのユーティリティ関数が用意されています。

SCDynamicStoreKey.h

  • SCDynamicStoreKeyCreateConsoleUser()
  • SCDynamicStoreKeyCreateHostNames()
  • SCDynamicStoreKeyCreateLocation()
  • SCDynamicStoreKeyCreateNetworkGlobalEntity()
  • SCDynamicStoreKeyCreateNetworkInterface()
  • SCDynamicStoreKeyCreateNetworkInterfaceEntity()
  • SCDynamicStoreKeyCreateNetworkServiceEntity()
  • SCDynamicStoreKeyCreateProxies()


また、各関数にキーの可変部をパラメタとして渡す場合の定数が、SCSchemaDefinitions.h に多数記載されています。
ただ、上記の関数リファレンスやヘッダを見ても、実際にどのようなキーがあり、上記のユーティリティ関数に与えるパラメタも、結果として得られるキーも、いまひとつ具体的に分かりません。
そこで役に立つのが scutil というコマンド。

$ scutil
>
> list
  subKey [0] = Plugin:IPConfiguration
  subKey [1] = Plugin:InterfaceNamer
  subKey [2] = Setup:
  subKey [3] = Setup:/
  subKey [4] = Setup:/Network/BackToMyMac
  subKey [5] = Setup:/Network/Global/IPv4
  subKey [6] = Setup:/Network/HostNames
  subKey [7] = Setup:/Network/Interface/en1/AirPort
  subKey [8] = Setup:/Network/Service/17252794-5272-4263-8436-93458EA29A41
  subKey [9] = Setup:/Network/Service/17252794-5272-4263-8436-93458EA29A41/IPv4
  subKey [10] = Setup:/Network/Service/17252794-5272-4263-8436-93458EA29A41/IPv6
  subKey [11] = Setup:/Network/Service/17252794-5272-4263-8436-93458EA29A41/Interface
  subKey [12] = Setup:/Network/Service/17252794-5272-4263-8436-93458EA29A41/Modem
  subKey [13] = Setup:/Network/Service/17252794-5272-4263-8436-93458EA29A41/PPP
  subKey [14] = Setup:/Network/Service/17252794-5272-4263-8436-93458EA29A41/Proxies
  subKey [15] = Setup:/Network/Service/6C67FE3C-C7EC-4885-9250-307B8EBA5DEA
  subKey [16] = Setup:/Network/Service/6C67FE3C-C7EC-4885-9250-307B8EBA5DEA/IPv4
  subKey [17] = Setup:/Network/Service/6C67FE3C-C7EC-4885-9250-307B8EBA5DEA/IPv6
  subKey [18] = Setup:/Network/Service/6C67FE3C-C7EC-4885-9250-307B8EBA5DEA/Interface
  subKey [19] = Setup:/Network/Service/6C67FE3C-C7EC-4885-9250-307B8EBA5DEA/Proxies
  subKey [20] = Setup:/Network/Service/9EAEE8A7-60C3-44EF-98F6-FA7E0D2E3396
  subKey [21] = Setup:/Network/Service/9EAEE8A7-60C3-44EF-98F6-FA7E0D2E3396/IPv4
  subKey [22] = Setup:/Network/Service/9EAEE8A7-60C3-44EF-98F6-FA7E0D2E3396/IPv6
  subKey [23] = Setup:/Network/Service/9EAEE8A7-60C3-44EF-98F6-FA7E0D2E3396/Interface
  subKey [24] = Setup:/Network/Service/9EAEE8A7-60C3-44EF-98F6-FA7E0D2E3396/Proxies
  subKey [25] = Setup:/System
  subKey [26] = State:/IOKit/LowBatteryWarning
  subKey [27] = State:/IOKit/Power/CPUPower
  subKey [28] = State:/IOKit/PowerAdapter
  subKey [29] = State:/IOKit/PowerManagement/Assertions
  subKey [30] = State:/IOKit/PowerManagement/CurrentSettings
  subKey [31] = State:/IOKit/PowerManagement/SystemLoad
  subKey [32] = State:/IOKit/PowerManagement/SystemLoad/Detailed
  subKey [33] = State:/IOKit/PowerSources/InternalBattery-0
  subKey [34] = State:/IOKit/SystemPowerCapabilities
  subKey [35] = State:/Network/BackToMyMac
  subKey [36] = State:/Network/Global/DNS
  subKey [37] = State:/Network/Global/IPv4
  subKey [38] = State:/Network/Global/Proxies
  subKey [39] = State:/Network/Interface
  subKey [40] = State:/Network/Interface/en0/Link
  subKey [41] = State:/Network/Interface/en1/AirPort
  subKey [42] = State:/Network/Interface/en1/IPv4
  subKey [43] = State:/Network/Interface/en1/IPv6
  subKey [44] = State:/Network/Interface/en1/Link
  subKey [45] = State:/Network/Interface/lo0/IPv4
  subKey [46] = State:/Network/Interface/lo0/IPv6
  subKey [47] = State:/Network/Interface/vmnet1/IPv4
  subKey [48] = State:/Network/Interface/vmnet8/IPv4
  subKey [49] = State:/Network/MulticastDNS
  subKey [50] = State:/Network/PrivateDNS
  subKey [51] = State:/Network/Service/6C67FE3C-C7EC-4885-9250-307B8EBA5DEA/DHCP
  subKey [52] = State:/Network/Service/6C67FE3C-C7EC-4885-9250-307B8EBA5DEA/DNS
  subKey [53] = State:/Network/Service/6C67FE3C-C7EC-4885-9250-307B8EBA5DEA/IPv4
  subKey [54] = State:/Users/ConsoleUser
  subKey [55] = com.apple.DirectoryService.NotifyTypeStandard:DirectoryNodeAdded
  subKey [56] = com.apple.network.identification
>

scutil は起動するとプロンプトになりコマンドが入力できます。helpで利用出来るコマンドが表示されますので見てみてください。そこそこいろいろ出来ます。
今回は、listと言うコマンドで、利用出来るキーの一覧を表示しています。なお、キーは常に一定ではなく、ネットワークの状況によって増減します。

値。

DynamicStore から取得できる値は NSDictionary ( CFDictionary ) で、実際の個別の設定値はさらにその中に規定のプロパティ名で格納されています。これは scutilshow コマンドで確認することができます。

> show State:/Network/Global/IPv4
<dictionary> {
  PrimaryInterface : en1
  PrimaryService : 6C67FE3C-C7EC-4885-9250-307B8EBA5DEA
  Router : 192.168.1.1
}
> show State:/Network/Interface/en1/Link
<dictionary> {
  Active : TRUE
}
> show State:/Network/Interface/en1/IPv4
<dictionary> {
  Addresses : <array> {
    0 : 192.168.1.102
  }
  BroadcastAddresses : <array> {
    0 : 192.168.1.255
  }
  SubnetMasks : <array> {
    0 : 255.255.255.0
  }
}
>
このように、PrimaryInterface(優先されるネットワーク)が “en1” (無線 LAN)で、無線 LAN の リンク状態、IP アドレス、ブロードキャストアドレス、サブネットマスクなどが分かります。

コード例。

さて、これをプログラム上ではどう取得するかですが、結構簡単です。

  1. #import <Cocoa/Cocoa.h>
  2. #import <SystemConfiguration/SCDynamicStoreKey.h>
  3. #import <SystemConfiguration/SCSchemaDefinitions.h>
  4.  
  5. - (void)test
  6. {
  7.     SCDynamicStoreRef   store;
  8.     SCDynamicStoreContext   context;
  9.     CFStringRef     key;
  10.     CFDictionaryRef     val;
  11.     CFStringRef     host;
  12.     CFStringRef     primIF;
  13.     CFArrayRef      addrs;
  14.     CFStringRef     addr;
  15.  
  16.     // DynaimcStore生成
  17.     memset(&context, 0, sizeof(context));
  18.     context.info    = self;
  19.     store       = SCDynamicStoreCreate(NULL, (CFStringRef)[[NSBundle mainBundle] bundleIdentifier], NULL, &context);
  20.  
  21.     // コンピュータ名取得
  22.     key = SCDynamicStoreKeyCreateHostNames(NULL);
  23.     val = (CFDictionaryRef)SCDynamicStoreCopyValue(store, key);
  24.     host    = (CFStringRef)CFDictionaryGetValue(val, kSCPropNetLocalHostName);
  25.     NSLog(@"HostName is %@.", host);
  26.     CFRelease(val);
  27.     CFRelease(key);
  28.  
  29.     // PrimaryInteaface取得
  30.     key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, kSCDynamicStoreDomainState, kSCEntNetIPv4);
  31.     val = (CFDictionaryRef)SCDynamicStoreCopyValue(store, key);
  32.     primIF  = (CFStringRef)CFDictionaryGetValue(val, kSCDynamicStorePropNetPrimaryInterface);
  33.     NSLog(@"PrimaryInterface is %@.", primaryIF);
  34.     CFRetain(primIF);
  35.     CFRelease(val);
  36.     CFRelease(key);
  37.  
  38.     // IPアドレス取得
  39.     key = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL, kSCDynamicStoreDomainState, primIF, kSCEntNetIPv4);
  40.     val = (CFDictionaryRef)SCDynamicStoreCopyValue(store, key);
  41.     addrs   = (CFArrayRef)CFDictionaryGetValue(val, kSCPropNetIPv4Addresses);
  42.     addr    = (CFStringRef)CFArrayGetValueAtIndex(addrs, 0);
  43.     NSLog(@"IP Address is %@", addr);
  44.     CFRelease(val);
  45.     CFRelease(key);
  46.     CFRelease(primIF);
  47. }

上記サンプルはエラー処理をしていませんが、値を階層的に取得しているので、エラーチェックは処理の都度行う必要があります。

scutil で欲しいキーを確認すれば、別のキーでも取得の方法は同じ要領です。ネットワークの設定や諸情報、ネットワーク以外にも電源(電池)の状態などもわかったり、結構面白いです。

実は、DynamicStore を使うと今回取得したような値の変化(ネットワーク状態の変化、システム環境設定での変更)を検出することもできますが、それは次回に。


  1. コメントはまだありません。
  1. トラックバックはまだありません。