Provided by: manpages-zh_1.6.3.2-1_all
NAME
分組(也譯爲數據包),PF_PACKET - 在設備層的分組接口 譯註:PF_PACKET 中的 PF 是 protocol family(協議族)的縮寫。
SYNOPSIS 總覽
#include <sys/socket.h> #include <features.h> /* 需要裏面的 glibc 版本號 */ #if __GLIBC__ >= 2 && __GLIBC_MINOR >= 1 #include <netpacket/packet.h> #include <net/ethernet.h> /* 鏈路層(L2)協議 */ #else #include <asm/types.h> #include <linux/if_packet.h> #include <linux/if_ether.h> /* 鏈路層協議 */ #endif packet_socket=socket(PF_PACKET,intsocket_type,intprotocol);
DESCRIPTION 描述
分組套接口(也譯爲插口或套接字)被用於在設備層(OSI 的鏈路層) 收發原始(raw )分組。它允許用戶 在用戶空間實現在物理層之上的 協議模塊。 對於包含鏈路層報頭的原始分組,socket_type 參數是 SOCK_RAW; 對於去除了鏈路層報頭的加工過的 分組,socket_type 參數是 SOCK_DGRAM。鏈路層報頭信息可在作爲一般格式的 sockaddr_ll 中 的中 得到。socket 的 protocol 參數指的是 IEEE 802.3 的按網絡 層排序的協議號,在頭文件中有所有被 允許的 協議的列表。當 protocol 被設置爲 htons(ETH_P_ALL)時,可以接 收所有的協議。到來的此 種類型的分組在傳送到在內核實現的協議 之前要先傳送給分組套接口。 譯註:DGRAM 是數據報的意思,htons 函數名是 hosts to networks of a short (16位整數的從主機 到網絡的字節序變換)的縮寫。 只有有效 uid 是 0 或有 CAP_NET_RAW 能力的進程可以打開分組 套接口。 傳送到設備和從設備傳送來的 SOCK_RAW 分組不改變任何分組數據。 當收到一個 SOCK_RAW 分組時, 地址仍被分析並傳送到一個標準的 sockaddr_ll 地址結構中。當發送一個 SOCK_RAW 分組時, 用戶供 給的緩衝區應該包含物理層報頭。接着此分組不加修改的放入目的 地址定義的接口的網絡驅動程序的 隊列中。一些設備驅動程序總是 增加其他報頭。SOCK_RAW 分組與已被廢棄的 Linux 2.0 的 SOCK_PACKET 分組類似但不兼容。 對 SOCK_DGRAM 分組的操作要稍微高一層次。在分組被傳送到用戶 之前物理報頭已被去除。從 SOCK_DGRAM分組套接口送出的分組在被 放入網絡驅動程序的隊列之前,基於在 sockaddr_ll 中的目的 地址 得到一個適合的物理層報頭。 缺省的所有特定協議類型的分組被髮送到分組套接口。爲了只從特 定的接口得到分組,使用bind(2)來 指定一個在 sockaddr_ll 結構 中的地址,以此把一個分組套接口綁定到一個接口上。只有地址字 段 sll_protocol 和 sll_ifindex 被綁定用途所使用。 不支持在分組套接口上的 connect(2) 操作。(不能作爲客戶端使用)
ADDRESS TYPES 地址類型
sockaddr_ll 是設備無關的物理層地址。 struct sockaddr_ll { unsigned short sll_family; /* 總是 AF_PACKET */ unsigned short sll_protocol; /* 物理層的協議 */ int sll_ifindex; /* 接口號 */ unsigned short sll_hatype; /* 報頭類型 */ unsigned char sll_pkttype; /* 分組類型 */ unsigned char sll_halen; /* 地址長度 */ unsigned char sll_addr[8]; /* 物理層地址 */ }; 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)地址和地址長度。精確 的解釋依賴於設備。 譯註: (1) 對於以太網(ethernet) OSI 模型不完全適用,以太楨定義包 括物理層和鏈路層的基本內 容, 所謂的以太楨協議類型標識的是網絡 層的協議。IEEE 802 委員會爲與 OSI 相一致,把以太楨定 義稱爲 MAC(medium access control)層,在 MAC 層與網絡層之間加入 LLC (logical link control)層,補充上了 OSI 標準的鏈路層。但在BSD TCP/IP 中是爲了兼容官方標準才被實現的。對於 TCP/IP 協議族 OSI 模型也不完全適用,TCP/IP 沒定義鏈路層,只能用 UNIX 的設 備驅動程序去對應 鏈路層。無論如何這是既成事實,在本手冊頁中物 理層、鏈路層、設備層指的都是以太網的 MAC 層。餘以爲不必嚴格 按層次劃分去理解問題,現在這個協議棧是優勝劣汰的結果,不是委 員會討論出 來的。 (2) 以太網地址分爲三類,物理地址(最高位爲0),多路廣播地址 (最高位爲1),廣播地址(全 是1)。以 DP8390 爲例,它的接收配置 寄存器的 D2 位用來指定 NIC 是否接受廣播楨,D3 位用來指 定 NIC 是否對多路廣播楨進行過濾,D4 位用來指定 NIC是否接受所有的物 理地址楨。混 雜(Promiscuous)模式就是接收所有物理地址楨。
SOCKET OPTIONS 套接口選項
分組套接口可被用來配置物理層的多路廣播和混雜模式。配置通過調用 setsockopt(2)實現,套接口參 數是一個分組套接口、層次參數爲 SOL_PACKET 、選項參數中的 PACKET_ADD_MEMBERSHIP 用於增加一 個綁定,選項參數中的 PACKET_DROP_MEMBERSHIP 用於刪除一個綁 定。兩個選項都需要作爲參數的 packet_mreq 結構: struct packet_mreq { int mr_ifindex; /* 接口索引號 */ unsigned short mr_type; /* 動作 */ unsigned short mr_alen; /* 地址長度 */ unsigned char mr_address[8]; /* 物理層地址 */ }; mr_ifindex 包括接口的接口索引號,mr_ifindex 的狀態是可以改 變的。mr_type 參數指定完成那個 動作。PACKET_MR_PROMISC 允許 接收在共享介質上的所有分組,這種接受狀態常被稱爲混雜模式; PACKET_MR_MULTICAST 把套接口綁定到由mr_address 和 mr_alen 指定的物理層多路廣播組 上;PACKET_MR_ALLMULTI 設置套接口接 收所有的來到接口的多路廣播分組。 除此之外傳統的 ioctls 如 SIOCSIFFLAGS, SIOCADDMULTI, SIOCDELMULTI 也能用於實現同樣的目的。
IOCTLS 輸入輸出控制
SIOCGSTAMP 用來接收最新收到的分組的時間戳。它的參數是 timeval 結構。 除此之外,所有的在 netdevice(7) 和 socket(7) 中定義的標準 的 ioctl 在分組套接口上均有效。
ERROR HANDLING 錯誤處理
分組套接只對傳送分組到設備驅動程序時發生的錯誤做錯誤處理, 其他不做錯誤處理。這裏沒有等待 解決的錯誤的概念。
COMPATIBILITY 兼容性
在 Linux 2.0 中,得到分組套接口的唯一方法是調用 socket(PF_INET, SOCK_PACKET, protocol)。它 仍被支持但變得 沒有價值。兩種方法的主要不同在於 SOCK_PACKET 使用老的 sockaddr_pkt 結構來指 定一個接口,沒有提供物理層接口無關性。 (依賴於物理設備) struct sockaddr_pkt { unsigned short spkt_family; unsigned char spkt_device[14]; unsigned short spkt_protocol; }; spkt_family 包括設備類型,spkt_protocol 是在 中定義的 IEEE 802.3 協議類型,spkt_device 是 表示設備名的 null 終結的字符串,例如 eth0。 譯註: "who is nntp" 就是一個以 null (' ')終結的字符串。 這個結構已經被廢棄,不應在新的代碼中使用。
NOTES 注意
不建議對要求可移植的程序通過 pcap(3) 使用 PF_PACKET 協議族; 它只覆蓋了 PF_PACKET 特徵的一 個子集。 譯註:該函數庫可在 ftp://ftp.ee.lbl.gov/libpcap.tar.Z 得到。 SOCK_DGRAM 分組套接口對 IEEE 802.3 楨不做生成或分析 IEEE 802.2 LLC 報頭的嘗試。當在套接口 中指定了 ETH_P_802_3 協議, 告知內核生成 802.3 楨,並填寫了長度字段;用戶必須提供提供 LLC 報頭來產生符合標準的分組。到來的 802.3 分組不在協議 字段 DSAP/SSAP 上實現多路複用;而是故 意的把 ETH_P_802_2 協議的 LLC 報頭提供給用戶。所以不可能綁定到 ETH_P_802_3; 而可以綁定到 ETH_P_802_2 並自己做多路複用。缺省的發送的是 標準的以太網 DIX 封裝並填寫協議字段。 譯註: 長度字段和協議字段其實都是以太楨的第四字段,這個字段 的值在小於 1518 時表示此以太楨 是 IEEE 802.3 楨,在大於1536 時表示此以太楨是 DIX 楨。DIX 中的 D 代表 DEC,I 代表 Intel, X 代表 Xerox。 分組套接口不是輸入或輸出防火牆的系列主題。
ERRORS 錯誤信息
ENETDOWN 接口未啓動。 ENOTCONN 未傳遞接口地址。 ENODEV 在接口地址中指定了未知的設備名或接口索引。 EMSGSIZE 分組比接口的 MTU(最大傳輸單元)大。 ENOBUFS 沒有足夠的內存分配給分組。 EFAULT 用戶傳遞了無效的地址。 EINVAL 無效參數。 ENXIO 接口地址包含非法接口索引號。 EPERM 用戶沒有足夠的權限來執行這個操作。 EADDRNOTAVAIL 傳遞了未知的多路廣播組地址。 ENOENT 未收到分組。 除此之外,底層的驅動程序可能產生其他的錯誤信息。
VERSIONS 版本
PF_PACKET 是 Linux 2.2 的新特徵。Linux 的早期版本只支持 SOCK_PACKET。
BUGS 缺陷
glibc 2.1 沒有定義 SOL_PACKET。建議的補救是使用 #ifndef SOL_PACKET #define SOL_PACKET 263 #endif 在此以後的 glibc 版本中更正了錯誤並且在 libc5 系統上不會發生。 沒有對 IEEE 802.2/803.3 LLC 的處理被認爲是缺陷。 套接口過濾器未歸入文檔。
CREDITS 貢獻者
本手冊頁是 Andi Kleen 寫的,他得到了 Matthew Wilcox 的幫助。 在 Linux 2.2 中的 PF_PACKET 是 Alexey Kuznetsov 實現的,他 的實現是以 Alan Cox 和其他人的代碼爲基礎的。
SEE ALSO 參見
ip(7),socket(7),socket(2),raw(7),pcap(3). RFC894-IP數據報的Ethernet楨封裝標準。 RFC1700-IP數據報的IEEE802.3楨封裝標準。 頭文件linux/if_ether.h包含物理層協議。
[中文版維護人]
mhss <jijingzhisheng@up369.com>
[中文版最新更新]
2000/10/15
《中國linux論壇man手冊頁翻譯計劃》:
http://cmpp.linuxforum.net
跋
本頁面中文版由中文 man 手冊頁計劃提供。 中文 man 手冊頁計劃:https://github.com/man-pages-zh/manpages-zh