2013-04-26 127 views
6

我正尝试使用原始套接字发送OAM以太网帧。我成功地这样做了。发送原始数据包时,sendto函数不使用struct sockaddr_ll中提供的MAC地址

我写的发送功能是:

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捕获数据包。所以发送功能不使用存储在dest_addr.sll_addr中的MAC地址。

我的问题是,那么sll_addr字段中的struct sockaddr_ll有什么需要?手册说它是目标MAC地址。

回答

3

对我来说,这听起来像它会像手册页描述它(人7包):

SOCK_RAW包传递到并从设备驱动程序,而不在分组数据的任何 变化。当收到一个数据包时,地址是 仍然解析并通过一个标准的sockaddr_ll地址结构。 发送数据包时,用户提供的缓冲区应该包含物理层标头的 。那个数据包然后是未修改排队的 网络驱动程序由目标地址定义的接口。 某些设备驱动程序始终添加其他标头。 SOCK_RAW类似于 ,但与Linux 2.0的废弃PF_INET/SOCK_PACKET不兼容。

这里的缓冲区是指第二个参数sendto()。因此,stuck sockaddr_ll仅用于将数据返回给调用者,而不用于格式化数据包。也许你想用户SOCK_DGRAMlibpcap取而代之?