2

.NETのネットワークプログラミングという本があります。この本には、ネットワークスタック上のIPパケットをスニッフィングするための次のコードサンプルがあります。本からコードサンプルWORD-FOR-WORDをコピーしたので、文体の慣習などがないことをお許しください。

List<string> packets = new List<string>();

public void Run()
{
    int len_receive_buf = 4096;
    int len_send_buf = 4096;
    byte[] receive_buf = new byte[len_receive_buf];
    byte[] send_buf = new byte[len_send_buf];
    int cout_receive_bytes;
    Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.IP);
    socket.Blocking = false;
    IPHostEntry IPHost = Dns.GetHostByName(Dns.GetHostName());
    socket.Bind(new IPEndPoint(IPAddress.Parse(IPHost.AddressList[0].ToString()), 0));
    socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.HeaderIncluded, 1);
    byte[] IN = new byte[4] { 1, 0, 0, 0 };
    byte[] OUT = new byte[4];
    int SIO_RCVALL = unchecked((int)0x98000001);
    int ret_code = socket.IOControl(SIO_RCVALL, IN, OUT);
    while(true)
    {
        IAsyncResult ar = socket.BeginReceive(receive_buf, 0, len_receive_buf, SocketFlags.None, null, this);
        cout_receive_bytes = socket.EndReceive(ar);
        Receive(receive_buf, cout_receive_bytes);
    }
}

public void Receive(byte[] buf, int len)
{
    if(buf[9] == 6)
    {
        packets.Add(Encoding.ASCII.GetString(buf).Replace("\0", " "));
    }
}

これを最初にテストしたのは数年前(Vistaが存在する前)で、使用したマシンはIPv4で実行されているNICを備えた32ビットのWindowsXPProfersionalプラットフォームでした。

現在、IPv6を実行しているNICを備えた64ビットWindows 7プラットフォームでテストしようとしていますが、機能していません。これはIPv6と関係があると思います。誰かがこれを効率的に修正する方法を提案できますか?

編集:これは私が実行しようとしたときに私が得る例外です...

ここに画像の説明を入力してください

4

1 に答える 1

6

ヘッダーは、 IPv4IPv6で大幅に異なります。

したがって、次のチェックを行います。

if(buf[9] == 6)

パケットがTCPforIPv4であるかどうかをチェックするのは、IPv6パケットの送信元アドレスフィールドの一部をクエリしていることです。IPv6の場合、オフセット6*にある「次のヘッダー」をチェックする必要があります。もちろん、オフセット6とオフセット9のどちらをチェックするかを知るために、最初にIPバージョンもチェックする必要があります。


例外メッセージの場合、Administratorとして実行していない可能性があります。これは、 rawソケットでリッスンする必要があります(ネイティブドキュメントですが、引き続き適用可能です)。

タイプSOCK_RAWのソケットを使用するには、管理者権限が必要です。rawソケットを使用するWinsockアプリケーションを実行しているユーザーは、ローカルコンピューターのAd​​ministratorsグループのメンバーである必要があります。そうでない場合、rawソケット呼び出しはエラーコード.で失敗しますWSAEACCES。Windows Vista以降では、rawソケットへのアクセスはソケットの作成時に適用されます。以前のバージョンのWindowsでは、rawソケットへのアクセスは他のソケット操作中に強制されます。


(*)もちろん、TCPパケットであることがわかる前に、複数のIPv6ヘッダーを処理する必要がある場合があります。

于 2012-09-10T09:17:11.730 に答える