(十三)Packet socket 和 sockaddr_ll
描述
本文簡單描述了數據鏈路層的socket使用的兩種方法
正文
Linux下有兩種方式接收數據鏈路層的數據包:
(1)原始的方法,即創建一個類型為SOCK_PACKET的socket,該方法很普遍,但是缺乏靈活性;
(2)最新的方法,引入了幀過濾功能和性能上的提升,即創建一個指定協議簇為 PF_PACKET的socket,這需要root權限(類似于創建一個raw socket),并且socket的第三個參數必須指定一個以太網幀類型(Ethernet frame type);
使用第二種方法時,socket的第二個參數可以被設置為SOCK_DGRAM,主要區別是當指定SOCK_DGRAM時,獲取的數據包是去掉了數據鏈路層的頭(link-layer header),當指定SOCK_RAW時,獲取的數據包是一個完整的數據鏈路層數據包; SOCK_PACKET只返返回完整的數據鏈路層數據包,示例,接收完整的數據鏈路層數據包,可以這樣寫:
fd=socket(AF_INET,SOCK_PACKET,htons(ETH_P_ALL));/*older systems*/
或者
fd=socket(PF_PACKET,SOCK_RAW,htons(ETH_P_ALL));/*newer systems*/
這樣將會接收到數據鏈路層所有協議幀;
如果我們只需要IPv4幀,可以這樣寫:
fd=socket(PF_PACKET,SOCK_RAW,htons(ETH_P_IP));/*new systems*/
或者
fd=socket(AF_INET,SOCK_PACKET,htons(ETH_P_IP));/*older systems*/
其它數據鏈路層類型定義的常量參數有 ETH_P_ARP 和 ETH_P_IPV6;
指定協議(protocol)為ETH_P_XXX即告訴數據鏈路層我只接收該類型的幀(frame),socket會自動過濾。如果數據鏈路支持混雜模式(promiscuous mode),可以設置socket可選參數PACKET_ADD_MEMBERSHIP選項,使用packet_mreq結構體指定一個以太網接口和混雜模式行為(PACKET_MR_PROMISC)。
接下來詳解 數據鏈路層的頭信息結構體sockaddr_ll:
點擊(此處)折疊或打開
#include<sys/socket.h>
#include<linux/if_packet.h>
#include<net/ethernet.h>/*the L2 protocols*/
packet_socket=socket(AF_PACKET,intsocket_type,intprotocol);
數據鏈路層的頭信息通常定義在sockaddr_ll 的結構體中,protocol是按照網絡字節順序(network byte order),大部分定義在頭文件中,設置協議時,例如 htons(ETH_P_ALL)來接收所有的數據包;
如果要獲取從指定以太網接口卡上的數據包時,在 struct sockaddr_ll中指定網絡接口卡,綁定(bind)數據包到該interface上。只有sll_protocol和sll_ifindex這兩個地址字段是用來bind的。
struct sockaddr_ll{
unsigned short sll_family;/*Always AF_PACKET*/
unsigned short sll_protocol;/*Physical-layer protocol*/
intsll_ifindex;/*Interface number*/
unsigned short sll_hatype;/*ARP hardware type*/
unsigned char sll_pkttype;/*Packet type*/
unsigned char sll_halen;/*Length of address*/
unsigned char sll_addr[8];/*Physical-layer address*/
};
sll_protocol: 標準以太網協議類型,按網絡字節順序。定義在中。
sll_ifindex: interface索引,0 匹配所有的網絡接口卡;
sll_hatype: ARP 硬件地址類型(hardware address type) 定義在中,常用 ARPHRD_ETHER
sll_pkttype: 包含了packet類型。
PACK_HOST 包地址為本地主機地址。
PACK_BROADCAST 物理層廣播包。
PACK_MULTICAST 發送到物理層多播地址的包。
PACK_OTHERHOST 發往其它在混雜模式下被設備捕獲的主機的包。
PACK_OUTGOING 本地回環包;
sll_addr和ssl_halen包含了物理層地址和其長度;
當發送數據包時,指定 sll_family, sll_addr, sll_halen, sll_ifindex, sll_protocol 就足夠了。其它字段設置為0; sll_hatype和 sll_pkttype是在接收數據包時使用的; 如果要bind, 只需要使用 sll_protocol和 sll_ifindex;
總結
以上是生活随笔為你收集整理的(十三)Packet socket 和 sockaddr_ll的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 波涛1202wm8833 lihomme
- 下一篇: 嵌入式单片机,ATmega328P,外部