イーサネットフレーム8では、IPプロトコルのプロトコルタイプ値がなぜですか?

イーサネットフレーム8では、IPプロトコルのプロトコルタイプ値がなぜですか?

私は単純なパケットハンドラを書いています。以下は抜粋したコードです。

void print_ethernet_header(unsigned char* buffer)
{
        struct ethhdr *eth = (struct ethhdr *)buffer;
        fprintf(logfile , "   |-Protocol  : %x \n",eth->h_proto);
}

この単純な関数は、プロトコルタイプの16進値をログファイルに印刷する必要があります。実際に「8」の値を印刷します。ただし、ソース/usr/include/net/ethernet.hと行(https://en.wikipedia.org/wiki/EtherType)IPプロトコルタイプが0x0800として定義されていることを確認しました。したがって、実際にはファイルに8以外の800(16進数)または2048(10進数)の値が印刷されると予想されます。私はこれがバイトオーダーに関連している可能性があり、ネットワークバイトオーダーからホストに変換する必要があると思いましたが、recvfrom()のマニュアルページでこれに関する情報を見つけることができませんでした。以下は、バッファ変数を埋める呼び出しです。

sock_raw = socket(AF_PACKET,SOCK_RAW,htons(ETH_P_ALL));
//some code here...
data_size = recvfrom(sock_raw , buffer , bufsize , 0 , (struct sockaddr*)&saddr , (socklen_t*)&saddr_size);

私が作業しているコンピュータはリトルエンディアン(Ubuntu 16.04)です。プロトコルタイプが8で表示されるのはなぜですか?

答え1

構造の定義これがh_protoビッグエンディアンの16ビット整数であることを示しています。

struct ethhdr {
        unsigned char   h_dest[ETH_ALEN];       /* destination eth addr */
        unsigned char   h_source[ETH_ALEN];     /* source ether addr    */
        __be16          h_proto;                /* packet type ID field */
} __attribute__((packed));

ntohsしたがって、読み取り前に実際に処理する必要があります。これにより、正しい値0x0800が表示されます。

答え2

EtherType広告を印刷しようとしましたが、正しい値を取得できない場合、コンピュータはエンディアンを正しい方法で解釈しません。解決策は次のとおりです。

 int etherType = ntohs(eth->h_proto);
 printf("EtherType: 02%x", etherType);

これにより、ドキュメントで指定されたEtherTypeが提供されます。

関連情報