Question

I am buliding a server/client software using PF_PACKET and SOCK_RAW and a custom protocol when calling socket()

When in the client software I create the socket the same way and just do a rcvfrom that socket and I get the data

My question is do I have to fill out the sockaddr_ll struct the same way I do for the server since when I reply from the client the source MAC address I got is a wierd one something like 11:11:00:00:00:00 and of course this is not my client's MAC

Does anyone know what this happens? Open the socket

if ( (sckfd=socket(PF_PACKET, SOCK_RAW, htons(proto)))<0)
{
    myError("socket");

}

this is how I receive the data

n = recvfrom(sckfd, buffer, 2048, 0, NULL, NULL);
printf("%d bytes read\n",n);

So this is how I basically receive the data in the client without filling the struct sockaddr_ll

For the server Program I do have to fill the struct

struct sockaddr_ll saddrll;
memset((void*)&saddrll, 0, sizeof(saddrll));
saddrll.sll_family = PF_PACKET;   
saddrll.sll_ifindex = ifindex;
saddrll.sll_halen = ETH_ALEN;
memcpy((void*)(saddrll.sll_addr), (void*)dest, ETH_ALEN);

My question is I receive as shown and send as shown and when I reply to the server call the same function used in the server for Sending then what do I get 11:11:00:00:00:00 when receiving client replies

Was it helpful?

Solution

You should probably use

socket(AF_PACKET, SOCK_DGRAM, htons(proto)))

instead of a SOCK_RAW socket. With a SOCK_RAW, you are sending/receiving the entire ethernet frame, including source and destination MAC address. with SOCK_DGRAM, the kernel will fill in the ethernet header.

You probably want to send the reply to the same address as the request comes from, recvfrom() can fill in the source address;

struct sockaddr_ll src_addr;
socklen_t addr_len = sizeof src_addr;
n = recvfrom(sckfd, buffer, 2048, 0, 
            (struct sockaddr*)&src_addr, &addr_len);

Now you've learned the source address, so send the packet back to it:

...
sendto(sckfd, data, data_len, src_addr, addr_len);

And if you rather need to use SOCK_RAW, your will receive the ethernet header too, so just copy out the MAC addresses from the received data and swap them around when you are constructing the reply frame.

For an a SOCK_RAW socket, you craft the entire ethernet frame, you don't need to fill in the ethernet address, so the following is not needed;

 memcpy((void*)(saddrll.sll_addr), (void*)dest, ETH_ALEN);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top