鏈路層套接字PF PACKET簡介 轉)

2021-06-12 05:48:48 字數 2113 閱讀 8057

在linux環境中要從鏈路層(mac)直接收發資料幀,可以通過libpcap與libnet兩個動態庫來分別完成收與發的工作。雖然它已被廣泛使用,但在要求進行跨平台移植的軟體中使用仍然有很多弊端。

這裡介紹一種更為直接地、無須安裝其它庫的從mac層收發資料幀的方式,即通過定義鏈路層的套接字來完成。

packet套接字用於在mac層上收發原始資料幀,這樣就允許使用者在使用者空間完成mac之上各個層次的實現。給無論是進行開發還是測試的人們帶來了極大的便利性。

packet套接字的定義方式與傳送層的套接字定義類似,如下:

packet_socket=socket(pf_packet,int socket_type,int protocol);
(這個套接字的開啟需要使用者有root許可權)

其中socket_type有兩種型別,一種為sock_raw,它是包含了mac層頭部資訊的原始分組,當然這種型別的套接字在傳送的時候需要自己加上乙個mac頭部(其型別定義在linux/if_ether.h中,ethhdr),另一種是sock_dgram型別,它是已經進行了mac層頭部處理的,即收上的幀已經去掉了頭部,而傳送時也無須使用者新增頭部字段。

protocol是指其送交的上層的協議號,如ip為0x0800,當其為htons(eth_p_all) (其巨集定義為0)時表示收發所有的協議。

建立好套接字後,就可以通過與udp一樣的recvfrom與sendto函式進行資料的收發,其目的位址結構為sockaddr_ll,這與傳送層的位址結構定義是不一樣的,其長度為20位元組(在tcp/ip的鏈路層位址中使用了18位元組),而傳送層的位址結構長度為16位元組。

sockaddr_ll結構如下:

struct sockaddr_ll
;
sll_protocol

是在 linux/if_ether.h 標頭檔案中定義的按網路層排序的標準的以太楨協議型別。sll_ifindex 是介面的索引號(參見netdevice(2));0 匹配所有的介面(當然只有合法的才用於繫結)。 sll_hatype 是在 linux/if_arp.h 中定義的 arp 硬體位址型別。 sll_pkttype 包含分組型別。有效的分組型別是:目標位址是本地主機的分組用的 packet_host,物理層廣播分組用的 packet_broadcast ,傳送到乙個物理層多路廣播位址的分組用的 packet_multicast,在混雜(promiscuous)模式下的裝置驅動器發向其他主機的分組用的 packet_otherhost,本源於本地主機的分組被環回到分組套介面用的 packet_outgoing。這些型別只對接收到的分組有意義。sll_addr 和 sll_halen 包括物理層(例如 ieee 802.3)位址和位址長度。精確的解釋依賴於裝置。(本段引於packet的使用者手冊)

當在多個網路介面的主機上使用這個套接字時,若要指定接收或傳送的介面時可以使用bind進行繫結,這與tcp套接字的操作一樣,但其內涵並不相同。繫結時將根據位址結構中的sll_protocal和sll_ifindex分別繫結收發的協議號和介面索引號,介面索引號sll_ifindex為0時表示使用有效的所有介面。介面的sll_ifindex值可以通過ioctl獲得,如下面是獲得名字為「eth0」的介面的索引號

strcpy(ifr.ifr_name,"eth0");

ioctl(fd_packet,siocgifindex,&ifr);

取得的值儲存在ifr結構體的ifr_ifindex中,ifr結構型別為「struct ifreq」

btw,要獲得介面的實體地址同樣使用ioctl可以得到

ioctl(fd_packet,siocgifhwaddr,&ifr);

以資料形式儲存在ifr的ifr_hwaddr.sa_data中。

另外需要注意的是,在呼叫recvfrom函式時返回的位址長度資訊為18位元組,原因是在sockaddr_ll結構中的sll_addr[8]為8位元組,mac位址只使用了其中的前6位元組。在用sendto傳送時需要將目的位址結構體強制轉換為struct sockaddr 型別,而且指定的長度必須為20位元組,而不能是18或其它值。

我在使用中當指定了協議型別後可以準備接收該型別的資料幀,但有個問題一直困擾著我,就是無法過濾掉廣播幀,必須要收到幀後判斷目的位址是否為自己,然後如果用sock_dgram的時候又如何判斷呢?本人正在探索中,一旦有新進展將第一時間與大家分享。

鏈路層套接字PF PACKET簡介

在linux環境中要從鏈路層 mac 直接收發資料幀,可以通過libpcap與libnet兩個動態庫來分別完成收與發的工作。雖然它已被廣泛使用,但在要求進行跨平台移植的軟體中使用仍然有很多弊端。這裡介紹一種更為直接地 無須安裝其它庫的從mac層收發資料幀的方式,即通過定義鏈路層的套接字來完成。pac...

監聽套接字 連線套接字

摘要 對於伺服器程式設計中最重要的一步等待並接受客戶的連線,那麼這一步在程式設計中如何完成,accept函式就是完成這一步的。它從核心中取出已經建立的客戶連線,然後把這個已經建立的連線返回給使用者程式,此時使用者程式就可以與自己的客戶進行點到點的通訊了。accept函式等待並接受客戶請求 inclu...

python套接字 python套接字基本使用

socket socket通常也稱作 套接字 用於描述ip位址和埠,應用程式通常通過 套接字 向網路發出請求或者應答網路請求,可以認為是一種計算機網路的資料結構,介面。它是網路程式設計的基礎 套接字還分為面向連線的和無連線的 第一種是指tcp型別套接字,在通訊前需要建立連線,這種連線是較為可靠的,使...