どうもみむらです。
Windows は内部に DNS キャッシュを持っていまして、
その中身というのはやはり見てみたいものです。
ただ見るだけであれば、
ipconfig /displaydns
と打てば一覧で出てきてしまいますが、
今回は API を呼び出して取得してみます。
情報を取得するためには、dnsapi.dll にある “DnsGetCacheDataTable” という API を呼び出します。
#include <Windows.h> #include <WinDNS.h> #pragma comment(lib,"Dnsapi.lib") typedef LSTATUS(WINAPI *PDnsGetCacheDataTable)(PDNS_RECORD*); void main() { PDNS_RECORD entry; PDnsGetCacheDataTable dgcdt = (PDnsGetCacheDataTable)GetProcAddress(LoadLibrary(L"dnsapi.dll"), "DnsGetCacheDataTable"); dgcdt(&entry); DnsRecordListFree(entry, DnsFreeRecordList); }
ヘッダファイルに書かれていない API ですので、GetProcAddress で関数アドレスを取得して
動的に呼び出してやる必要があります。
実行しますとこのように、 “pNext” に次の情報が入った
「片方向のリンクリスト」の形で情報が入ったデータが返されます。
さらにここから、IP アドレスも求めるということであれば、
DnsQuery 関数を “DNS_QUERY_NO_WIRE_QUERY” ( キャッシュのみに問い合わせるオプション )を付けて呼び出すことで求まります。
#include <Windows.h> #include <WinDNS.h> #include <stdio.h> #pragma comment(lib,"Dnsapi.lib") #pragma comment(lib,"ws2_32.lib") typedef LSTATUS(WINAPI *PDnsGetCacheDataTable)(PDNS_RECORD*); void main() { PDNS_RECORD entry, orig_entry, data; PDnsGetCacheDataTable dgcdt = (PDnsGetCacheDataTable)GetProcAddress(LoadLibrary(L"dnsapi.dll"), "DnsGetCacheDataTable"); dgcdt(&orig_entry); entry = orig_entry; while (entry != NULL && entry->pNext != NULL) { DnsQuery(entry->pName, DNS_TYPE_A, DNS_QUERY_NO_WIRE_QUERY, 0, &data, 0); if (data != NULL) { IN_ADDR addr; addr.S_un.S_addr = data->Data.A.IpAddress; printf("%S : %s\n", entry->pName, inet_ntoa(addr)); } entry = entry->pNext; } DnsRecordListFree(orig_entry, DnsFreeRecordList); }
実行結果としてはこんな感じ:
・・・私がどこによくアクセスするかが丸わかりですね・・
というわけで・・
このような感じで、リゾルバキャッシュのデータを取り出すことが出来ました。
ですが、一点注意点として
“DnsGetCacheDataTable” 関数は MSDN にて明確にドキュメント化されていません。
ですので、今後呼び出し方法が変更される可能性は十分にあります。
使う場合は “現状は動く” 程度でとらえて頂ければと思います。