Networking
為什麼乙太網幀中 IP 協議的協議類型值為 8?
我正在編寫一個簡單的數據包處理程序。這是程式碼摘錄:
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。