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で決まりの予感。