[英]How to send data over a raw ethernet socket using sendto without using sockaddr_ll?
[英]sendto function does not use MAC address provided in struct sockaddr_ll when sending raw packets
我正在尝试使用原始套接字发送OAM以太网帧。 我成功了。
我写的发送功能是:
int send_frame(sock_info *info,char *buf,int length)
{
struct sockaddr_ll dest_addr;
memset(&dest_addr,0,sizeof(struct sockaddr_ll));
dest_addr.sll_family = PF_PACKET;
dest_addr.sll_protocol = htons(8902);
dest_addr.sll_ifindex = info->if_index;
dest_addr.sll_halen = ETH_MAC_ADDR_LEN;
dest_addr.sll_pkttype = PACKET_OTHERHOST;
dest_addr.sll_hatype = ARPHRD_ETHER;
memset(dest_addr.sll_addr,0,8);
dest_addr.sll_addr[0] = 0x00;
dest_addr.sll_addr[1] = 0xE0;
dest_addr.sll_addr[2] = 0x0C;
dest_addr.sll_addr[3] = 0x00;
dest_addr.sll_addr[4] = 0x95;
dest_addr.sll_addr[5] = 0x02;
return sendto(info->sock_fd, buf, length, 0, (struct sockaddr*) &dest_addr, sizeof(struct sockaddr_ll));
}
我无法使用wireshark捕获数据包。 在尝试了太多的东西之后,我发现用于发送的缓冲区应该具有所有以太网帧字段(从目标地址开始)。 当我将目标和源地址以及其他以太网字段添加到缓冲区时,我能够使用wireshark捕获数据包。 因此send函数不使用存储在dest_addr.sll_addr
的MAC地址。
我的问题是,那么struct sockaddr_ll
中sll_addr
字段的需求是什么? 手册说它是目标MAC地址。
对我来说,它听起来像手册页描述它( man 7数据包 ):
SOCK_RAW数据包传递到设备驱动程序和从设备驱动程序传递,而不会对数据包数据进行任何更改。 接收数据包时,仍会解析地址并将其传递到标准的sockaddr_ll地址结构中。 发送数据包时,用户提供的缓冲区应包含物理层标头 。 然后,该数据包未经修改地排队到由目标地址定义的接口的网络驱动程序 。 某些设备驱动程序始终添加其他标头 SOCK_RAW与Linux 2.0的过时PF_INET / SOCK_PACKET类似但不兼容。
这里的缓冲区是指sendto()
的第二个参数。 因此,stuct sockaddr_ll仅用于将数据返回给调用者,而不是用于格式化RAW数据包。 也许您想要使用SOCK_DGRAM或libpcap ?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.