WinPcapでEther Frame受信・Dump
id:higepon:20051206:1133877107の続きです。
WinPcapでは2つの方法でパケットを受信できます。
1つ目の方法はパケット受信ハンドラを登録する方法。
2つ目の方法はパケットを能動的にループで受信する方法です。
今回は今後のMonaでの実装を考えて後者の方法を試してみました。
基本的な流れとしては
- ネットワークアダプタの列挙
- ネットワークアダプタの選択
- デバイスオープン
- readループで受信
となります。
ソースを見たほうが良いと思うので全文載せておきます。
#include "Ether.h"
#include "Util.h"
#include "pcap.h"
int main(int argc, char** argv)
{
char errbuf[PCAP_ERRBUF_SIZE];
pcap_if_t* devices;
if (pcap_findalldevs(&devices, errbuf) == -1)
{
fprintf(stderr, "error pcap_findalldevs: %s\n", errbuf);
exit(1);
}
pcap_if_t* device;
for(device = devices; device; device = device->next)
{
if (device->description)
{
printf(" (%s)\n", device->description);
}
else
{
printf("no device\n");
exit(1);
}
}
// アダプタを選択 自分の環境に合わせてね
device = devices->next->next;
// オープン
pcap_t* handle;
if (NULL == (handle= pcap_open_live(device->name // デバイス名
, 65536 // パケット全体をゲット
, 1 // プロミスキャスモード
, 1000 // 読み込みタイムアウト
, errbuf // エラーバッファ
)))
{
fprintf(stderr, "\nUnable to open the adapter. %s is not supported by WinPcap\n");
pcap_freealldevs(devices);
return -1;
}
pcap_freealldevs(devices);
int res;
const u_char* packet;
struct pcap_pkthdr* header;
while ( (res = pcap_next_ex(handle, &header, &packet)) >= 0)
{
/* タイムアウト */
if(res == 0) continue;
/* Print the packet */
mones::Ether::Frame* frame;
frame = (mones::Ether::Frame*)packet;
printf("\nframe type=%x\n from ", mones::Util::swapShort(frame->type));
for (int i = 0; i < 6; i++)
{
printf("%02x ", frame->srcmac[i]);
}
}
if(res == -1)
{
printf("Error reading the packets: %s\n", pcap_geterr(handle) );
return -1;
}
return 0;
}
んで出力結果はこんな感じです。
frame type=800 from 00 0d 0b 87 56 xx frame type=800 from 00 0d 0b 87 56 xx
とても簡単です。
少なくとも受信に限れば WinPcapで決まりの予感。