3
votes

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.

2
1. What is the value of fromlen. 2. Have you actually tried to cast to sockaddr_ll and found out it contains invalid data?cnicutar
To cnicutar: 1. fromlen is 18, as the dump shows. 2. Yes, it has no sense.calandoa
struct sockaddr isn't guaranteed to have portable layout, so please also include what the different fields are when the buffer is interpreted (via cast) as struct sockaddr, struct sockaddr_pkt, struct sockaddr_ll, etc.Ben Voigt
What is fromlen before you call recvfrom? The kernel can't make your address buffer bigger than it started out.Ben Voigt

2 Answers

3
votes

I am actually looking for the interface the packet was received on.

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.

1
votes

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.