Sre*_*esh 6 c sockets linux network-programming
我正在尝试使用原始套接字发送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));
}
Run Code Online (Sandbox Code Playgroud)
我无法使用wireshark捕获数据包.在尝试了太多的东西之后,我发现用于发送的缓冲区应该具有所有以太网帧字段(从目标地址开始).当我将目标和源地址以及其他以太网字段添加到缓冲区时,我能够使用wireshark捕获数据包.因此send函数不使用存储的MAC地址dest_addr.sll_addr.
我的问题是,那么sll_addr现场的需求是struct sockaddr_ll什么?手册说它是目标MAC地址.
对我来说,它听起来就像手册页描述的那样工作(man 7 packet):
SOCK_RAW 数据包在设备驱动程序之间传递,且数据包数据不发生任何更改。当接收到数据包时,地址仍然被解析并以标准的 sockaddr_ll 地址结构传递。 传输数据包时,用户提供的缓冲区应包含物理层标头。然后,该数据包未经修改地排队到由目标地址定义的接口的网络驱动程序。某些设备驱动程序总是添加其他标头。SOCK_RAW 与 Linux 2.0 已过时的 PF_INET/SOCK_PACKET 类似但不兼容。
这里的缓冲区指的是 的第二个参数sendto()。因此,sockaddr_ll结构仅用于向调用者返回数据,而不用于格式化RAW数据包。也许您想改用SOCK_DGRAM或libpcap?