使用原始套接字时,为什么需要两次发出MAC地址?

时间:2013-12-16 12:50:50

标签: c linux macos raw-sockets

我想在Linux中使用raw_socket发送以太网帧,我使用下面的代码。它有效,但我无法理解,因为我已经在帧(缓冲区)中发出了MAC地址,为什么我必须在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));

3 个答案:

答案 0 :(得分:3)

如果您输入man 2 sendto,则会收到以下信息:

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


也许你应该使用sendsendmsg

答案 1 :(得分:0)

sendto function does not use MAC address provided in struct sockaddr_ll when sending raw packets处的类似帖子。

似乎在其他情况下,目标地址结构将提供额外的数据,例如接口索引。

答案 2 :(得分:0)

使用AF_PACKET原始套接字时,不应使用sendto。您甚至可以使用写入或发送。数据包套接字正好位于您绑定的网络设备上方。因此,输出数据包将完全按照您在缓冲区中指定的方式通过线路发送(仅自动添加FCS / CRC32以控制数据包完整性)。