7

2 つの Linux ボックス間で生のイーサネット フレームを送信するコードを書いています。これをテストするには、単純なクライアント送信とサーバー受信を取得したいだけです。

クライアントが正しくパケットを作成しています (パケット スニファを使用してパケットを確認できます)。

サーバー側では、次のようにソケットを初期化します。

fd = socket(PF_PACKET, SOCK_RAW, htons(MY_ETH_PROTOCOL));

whereMY_ETH_PROTOCOLは、ethertype として使用する 2 バイトの定数で、不要なネットワーク トラフィックが聞こえないようにします。

このソケットをインターフェースにバインドするときは、socket_addr 構造体でプロトコルを再度渡す必要があり socket_address.sll_protocol = htons(MY_ETH_PROTOCOL);
ます。このようなコードをコンパイルして実行すると、失敗します。サーバーがパケットを認識しません。ただし、次のようにコードを変更すると、
socket_address.sll_protocol = htons(ETH_P_ALL);
サーバーはクライアントから送信されたパケット (および他の多くのパケット) を確認できるため、パケットが一致することを確認するためにパケットをチェックする必要がありますMY_ETH_PROTOCOL

しかし、指定されたプロトコルで送信されていないトラフィックをサーバーに聞かせたくないので、これは解決策ではありません。どうすればいいですか?

4

2 に答える 2

5

問題を解決しました。

http://linuxreviews.org/dictionary/Ethernet/によると、MACアドレスに続く2バイトのフィールドを参照しています。

「64〜1522のフィールドの値は、長さフィールドを備えた新しい802.3イーサネットフォーマットの使用を示し、1536 10進数(0600 16進数)以上の値は、EtherTypeサブを備えた元のDIXまたはイーサネットIIフレームフォーマットの使用を示しました。 -プロトコル識別子。」

したがって、イーサタイプが>=0x0600であることを確認する必要があります。

http://standards.ieee.org/regauth/ethertype/eth.txtによると、0x88b5および0x88b6の使用は、「プロトタイプおよびベンダー固有のプロトコル開発で一般に使用できます」。これが私がイーサタイプとして使用するものです。カーネルは正しい宛先MACアドレスを持ち、そのプロトコルを使用するイーサネットフレームのみを取得するようにする必要があるため、これ以上のフィルタリングは必要ありません。

于 2010-07-30T13:12:17.013 に答える
0

過去に、パケット フィルターを使用してこの問題を回避しました。

Hand Waving (テストされていない疑似コード)

struct bpf_insn my_filter[] = {
    ...
}

s = socket(PF_PACKET, SOCK_DGRAM, htons(protocol));
struct sock_fprog pf;
pf.filter = my_filter;
pf.len = my_filter_len;
setsockopt(s, SOL_SOCKET, SO_ATTACH_FILTER, &pf, sizeof(pf));

sll.sll_family = PF_PACKET;
sll.sll_protocol = htons(protocol);
sll.sll_ifindex = if_nametoindex("eth0");

bind(s, &sll, sizeof(sll));

エラーチェックとパケットフィルターの正しい取得は、読者の演習として残されています...

アプリケーションによっては、より簡単に動作する代替手段としてlibpcapがあります。

于 2010-07-29T22:16:51.897 に答える