0

私は Linux の tun/tap デバイスを学んでいます。ここで私がやったことを理解できない小さな問題があります:

1: タップ デバイスを作成します。名前は「tap1」です。ファイル記述子を取得します: tapfd

2: buf[2048] のように、十分に大きな配列を準備します。

3: イーサネット フレームを buf に書き込みます。その中には、合計 74 バイトの ip(udp) パケットがあります。次のような不器用な方法でそれを行いました:

    // mac dst
    buf[0] = 0xbb;
    buf[1] = 0xaa;
    buf[2] = 0xbb;
    ...
    // mac src
    buf[6] = 0xaa;
    buf[7] = 0xbb;
    ...
    // eth type
    ...
    // ip ver & ip hdr_len
    ...
    ...
    ...
    // data offset=42 length=32
    buf[42] = 0x61;
    ...
    buf[73] = 0x61

4: write() を呼び出し、上記の [74 バイト] を [tapfd] に送信します。

    write(fd, buf, 74);

5: 「tcpdump -i tap1 -vv」を使用して確認しますが、結果は以下のとおりです。

    18:06:40.466971 aa:bb:08:00:45:00 (oui Unknown) Unknown SSAP 0x18 > bb:aa:aa:bb:aa:bb (oui Unknown) Unknown DSAP 0x78 Information, send seq 0, rcv seq 0, Flags [Response], length 56
        0x0000:  7919 0000 4011 ed95 0a00 0001 0a00 0001  y...@...........
        0x0010:  5b25 5f7c 0028 1ae4 6161 6161 6161 6161  [%_|.(..aaaaaaaa
        0x0020:  6161 6161 6161 6161 6161 6161 6161 6161  aaaaaaaaaaaaaaaa
        0x0030:  6161 6161 6161 6161                      aaaaaaaa

合計 = 56 バイト + 12 バイト mac src&dst + 2 バイト eth タイプ = 70 バイト では、先頭の 4 バイトはどこですか?

最初に、先頭の 4 バイトは「プリアンブル & フレーム区切り文字の開始」である必要があると考えましたが、wiki によると、プリアンブルは 7 オクテットで、フレーム区切り文字の開始は 1 オクテットでした。

6: 次に、[buf] に 4 バイトを挿入すると、buf は次のようになります。

   buf[0] = 0xab;
   buf[1] = 0xab;
   buf[2] = 0xab;
   buf[3] = 0xcc;
   buf = buf + 4;
   { buf[0] ~ buf[73] just as before }


then retry to send 78 bytes to fd

    write(fd, buf, 78)

次に、もう一度確認してください。今度は、tcp ダンプから、これが正当なイーサネット フレームであることがわかりました。

    18:13:57.676562 IP (tos 0x0, ttl 64, id 31001, offset 0, flags [none], proto UDP (17), length 60, bad cksum ed95 (->ed96)!)
        localhost.23333 > localhost.24444: [bad udp cksum 0x1ae4 -> 0x1ae5!] UDP, length 32

できます!しかし、なぜ?先頭の 4 バイトが欠落しているのはなぜですか?(不正な udp チェックサムは無視してください)

4

1 に答える 1