来自带有 AF_PACKET / PF_PACKET 的 recvfrom() 的套接字地址类型
在两台 PC 上,我打开一个 AF_PACKET / PF_PACKET 套接字,原始协议。
sock = 套接字(AF_PACKET, SOCK_RAW, htons(PROTO_BULK))
创建的。我不希望它推断出这个问题,但我可能是错的。)
(编辑:PROTO_BULK 是一个虚拟类型,是我自己为这个测试 PC 以标准 send() 方式向对方发送数据包,对方通过以下方式接收该数据包:
recvfrom(sock, buffer, 1600, 0, (struct sockaddr*) &from, &fromlen);
我现在的问题是:“from”中的数据类型是什么?这是我收到的示例:
00 00 00 00 00 00 00 00 f8 cd a1 00 58 1d a1 00 94 60
从长度和内容来看,它不像“struct sockaddr”,也不像“sockaddr_ll”。有什么想法吗?
我实际上正在寻找接收数据包的接口。我可以使用数据包中的目标 MAC 并从中识别接口,但它不适用于广播数据包。
我正在运行最新的 Linux 内核(并且我不想研究内核源代码!)。
编辑:我的代码是错误的。我没有用“from”缓冲区大小初始化“fromlen”,所以我认为存在一些虚假值,并且“recvfrom()”无法正确完成其工作。感谢 Ben Voigt 在下面的评论中指出了这个错误!当然,我没有在我的问题中包含这部分错误代码,因为很明显,如此简单的代码不会有错误......
使用正确的参数,我得到正确填充的“struct sockaddr_ll”,包括我正在寻找的接口号。
On two PC, I am opening an AF_PACKET / PF_PACKET socket, raw protocol.
sock = socket(AF_PACKET, SOCK_RAW, htons(PROTO_BULK))
(edit: PROTO_BULK is a dummy type, created by myself for this test. I do not expect it to be inferring with this problem, but I may be wrong.)
The first PC send a packet to the other the standard send() way, which is received on the other side with:
recvfrom(sock, buffer, 1600, 0, (struct sockaddr*) &from, &fromlen);
My problem is now: what is the type of the data in "from"? Here is an exemple of what I am receiving:
00 00 00 00 00 00 00 00 f8 cd a1 00 58 1d a1 00 94 60
From the length and the content, it does not look like a "struct sockaddr" nor a "sockaddr_ll". Any idea?
I am actually looking for the interface the packet was received on. I could use the destination MAC from the packet and identify the interface from it, but it would not work with a broadcast packet.
I am running a recent Linux kernel (and I do not want to investigate in the kernel sources!).
Edit: My code was wrong. I did not initialized "fromlen" with "from" buffer size, so I supposed some spurious value was there and "recvfrom()" could not do its job correctly. Thanks to Ben Voigt for pointing me this bug with his comment below! Of course, I did not include this part of the faulty code in my question, as it was obvious there could be no mistake with such simple code...
With the correct paramter, I get a "struct sockaddr_ll" correctly filled, including the interface number I was looking for.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您应该使用
recvmsg
,它可以访问元数据,例如作为数据包的目标地址(对于多宿主系统有用),我认为也是接口。您现在查看的发件人地址不会告诉您接口。不过,使用
sendto
发送回复数据包还是很有用的。You should be using
recvmsg
, which gives access to metadata such as the packet's destination address (useful for multihomed systems) and I think also the interface.The sender address you're looking at now isn't going to tell you the interface. It's good for sending a reply packet with
sendto
though.我浏览了内核源代码。我并不声称完全理解它们,但是......
PROTO_BULK 37984 (0x9460) 是吗?
如果是这样,这可能是一个“struct sockaddr_pkt”。 (无论如何,它的大小是正确的。)虽然我不确定其他字节的含义。如果我正确地读取代码,它们应该是接收数据包的接口的“名称”。所以我可能错误地阅读了代码。
I took a glance at the kernel sources. I do not claim to fully understand them, but...
Is PROTO_BULK 37984 (0x9460)?
If so, this is probably a "struct sockaddr_pkt". (It has the right size, anyway.) Although I am not sure what the other bytes mean. If I am reading the code correctly, they should be the "name" of the interface on which the packet was received. So I am probably reading the code incorrectly.