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));
有帮助吗?

解决方案 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.

其他提示

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).

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top