Question

I want to send Ethernet frames using raw_socket in Linux, and I use the code below. It works, but I cannot understand that since I have given out the MAC address in the frame (buffer), why do I have to give it again in the struct sockaddr_ll?

s = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
/*socket_address*/
struct sockaddr_ll socket_address;      
socket_address.sll_addr[0]  = 0x00;     
socket_address.sll_addr[1]  = 0x04;     
socket_address.sll_addr[2]  = 0x75;
socket_address.sll_addr[3]  = 0xC8;
socket_address.sll_addr[4]  = 0x28;
socket_address.sll_addr[5]  = 0xE5;
/*frame*/
unsigned char src_mac[6] = {0x00, 0x01, 0x02, 0xFA, 0x70, 0xAA};
unsigned char dest_mac[6] = {0x00, 0x04, 0x75, 0xC8, 0x28, 0xE5};
memcpy((void*)buffer, (void*)dest_mac, ETH_ALEN);
memcpy((void*)(buffer+ETH_ALEN), (void*)src_mac, ETH_ALEN);

send_result = sendto(s, buffer, ETH_FRAME_LEN, 0, 
          (struct sockaddr*)&socket_address, sizeof(socket_address));
Was it helpful?

Solution 2

Similar thread at sendto function does not use MAC address provided in struct sockaddr_ll when sending raw packets.

It seems that in other case the destination address struct will provide additional data like the interface index for example.

OTHER TIPS

if you type man 2 sendto you get the following:

 ssize_t
 send(int socket, const void *buffer, size_t length, int flags);

 ssize_t
 sendmsg(int socket, const struct msghdr *buffer, int flags);

 ssize_t
 sendto(int socket, const void *buffer, size_t length, int flags,
     const struct sockaddr *dest_addr, socklen_t dest_len);


maybe you should use send or sendmsg

When you use AF_PACKET raw socket you shouldn't use sendto. You can use even write or send. Packet socket is placed exactly above network device you have bound. So outgoing packet will be send over the wire exactly as you specify in the buffer (only FCS/CRC32 will be automatically added to control packet integrity).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top