2013-04-26 125 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取而代之?