どうもみむらです。
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 にて明確にドキュメント化されていません。
ですので、今後呼び出し方法が変更される可能性は十分にあります。
使う場合は “現状は動く” 程度でとらえて頂ければと思います。