WinPcapでEther Frame受信・Dump

id:higepon:20051206:1133877107の続きです。

WinPcapでは2つの方法でパケットを受信できます。
1つ目の方法はパケット受信ハンドラを登録する方法。
2つ目の方法はパケットを能動的にループで受信する方法です。


今回は今後のMonaでの実装を考えて後者の方法を試してみました。
基本的な流れとしては

  1. ネットワークアダプタの列挙
  2. ネットワークアダプタの選択
  3. バイスオープン
  4. 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で決まりの予感。