私は単純なパケットハンドラを書いています。以下は抜粋したコードです。
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が提供されます。