为什么以太网帧中IP协议的协议类型值为8?

为什么以太网帧中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);

我工作的机器是小端(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。

相关内容