0

生のソケットを開いて送信する次のコードがあります。send 関数には、パケットの長さが 21 であることを示すトレース ステートメントがあります。

  1. 実際のパケット長は 60 です。
  2. 長さ (802.3 ヘッダーで指定) は 256 です。

これらの数字はどちらも 21 ではなく、この不一致を嫌う組み込みデバイスと通信しています。私はグーグルで検索しましたが、 sendto() が正しい長さを報告する方法がわかりません。

bool EthernetSocket::_open(const char *ifname) {
  _sd = socket(AF_PACKET, SOCK_DGRAM, htons(ETH_P_802_2));
  _ifname = ifname;
  _ifidx = Ethernet::GetInterface(ifname);
  if(_sd < 0) {
    perror("Failed to open socket");
    _bOpened = false;
  }
  else {
    _bOpened = true;
  }
  return _bOpened;
}


bool EthernetSocket::_send(const Buffer& txbuff, Address& addr) {
  if(txbuff.Length() == 0)
    return false;

  if(_ifidx != -1)
    addr.SetInterface(_ifidx);

printf("SEND: Length: %d\n", txbuff.Length());
  if(sendto(_sd, txbuff.Data(), txbuff.Length(), 0, (struct sockaddr *) addr.Component(), (socklen_t) addr.Size()) == -1) {
    perror("Failed broadcast");
    return false;
  }
  return true;
}

編集:そのフィールドが sockaddr_ll 構造の sll_protocol フィールドに設定されていることを発見しました。しかし、なぜ?htons(ETH_P_802_2) に設定しても、本来は役に立ちません。

4

1 に答える 1

0

部分的な答えがあります。

sll_protocolをhtons(ETH_P_802_3)に設定すると、問題が修正されます。ETH_P_802_2とETH_P_802_3はほぼ同じように動作するはずなので、これがなぜであるかはわかりません。そして、私が見つけたすべての関連するカーネルソースがこれを裏付けています。

プロトコルETH_P_802_2を使用してrecvfrom()経由でパケットを受信したため、返されたアドレスのsll_protocolフィールドがETH_P_802_2に設定されています。つまり、返信するには、データを受信した後、フィールドを手動でETH_P_802_3に設定する必要があります。これはひどい恨みです。

どうしたの??

于 2010-08-05T21:13:35.723 に答える