Networking

為什麼乙太網幀中 IP 協議的協議類型值為 8?

  • April 27, 2021

我正在編寫一個簡單的數據包處理程序。這是程式碼摘錄:

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

這個簡單的函式應該將協議類型的十六進制值列印到日誌文件中。實際上它確實列印了值'8’。但是,在源 /usr/include/net/ethernet.h 和線上 ( https://en.wikipedia.org/wiki/EtherType ) 中,我看到 IP 協議類型定義為 0x0800。所以我實際上希望看到值 800(十六進制)或 2048(十進制)被列印到文件中,而不是 8。我認為這可能與字節序有關,並且需要從淨字節順序轉換為主機,但在 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);

我使用的機器是 little-endian (Ubuntu 16.04)。為什麼協議類型顯示 8 ?

結構定義顯示這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。

如果您嘗試列印 EtherType 廣告,您沒有得到正確的值,那麼您的機器沒有以正確的方式解釋字節序。解決方案將是:

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

這將為您提供文件中指定的 EtherType。

引用自:https://unix.stackexchange.com/questions/435233