6

我正在编写一个内核模块来从存储在 sk_buff 中的数据包中获取 MAC 地址。我使用以下代码打印源和目标的 MAC 地址:

struct ethhdr *mh = eth_hdr(skb);  
printk(KERN_EMERG "Source MAC=%x:%x:%x:%x:%x:%x\n",mh->h_source[0],mh->h_source[1],mh->h_source[2],mh->h_source[3],mh->h_source[4],mh->h_source[5]);  

可以使用h_destinplace of访问目标地址h_source
我的问题是源 MAC 地址总是a8:c0:0:0:a8:c0,而目标 MAC 地址总是一些垃圾值,而不是我自己的 MAC 地址。
谁能帮我解决这个问题?我想获得正确的 MAC 地址。

4

4 回答 4

5

您到底在内核的哪个位置执行此操作?

a8:c0 看起来很可疑。它转换为十进制的 168.192,这让我怀疑您实际上是在查看 IPv4 标头而不是以太网标头。

于 2012-04-12T20:45:17.883 回答
3

仅当skb确实具有MAC 标头eth_hdr时才有意义。如果没有,skb 的 MAC 头指针只会指向数据包中的其他数据。

于 2012-04-12T19:47:05.453 回答
1

使用mac_len可以帮助您解决此问题。通常你会得到 14(6 用于目标 mac + 6 用于源 mac + 2 用于协议)字节或 0(数据包来自环回)。请注意,如果返回 0,eth_hdr将直接指向数据(在 ip 协议的情况下指向 ip 标头)而不是以太网帧标头,正如 jørgensen 所说。

要获取非零 mac_len 的 mac,可以直接使用返回的指针eth_hdr

struct ethhdr* pHdr = eth_hdr(skb);  
printk(KERN_EMERG "Source MAC=%x:%x:%x:%x:%x:%x\n", pHdr[6], pHdr[7], pHdr[8], pHdr[9], pHdr[10], pHdr[11]);  

如果您对计算环回数据包的 MAC 地址感兴趣,请参阅protocol字段。例如,如果它等于 08 00 (8),则可以从目标 ip 地址获取 mac。如果地址是ff:ff:ff:ff,你就知道mac是ff:ff:ff:ff:ff:ff(广播)。如果没有,请使用设备的 mac 地址,或任何您喜欢的地址。

于 2021-12-01T16:24:55.293 回答
0

您需要在第 2 层处理数据包才能访问以太网标头。如果您的 linux 内核模块在第 3 层(Netfilter 挂钩)获取数据包,则 MAC 地址不存在于数据包中。

于 2017-08-30T16:08:30.063 回答