PF_PACKET 設備層編程接口

http://bbs.openlab.net.cn/forums/threads/167.aspx

定義:
#include "/usr/include/sys/socket.h"
#include "/usr/includ/sys/if_packet.h"

packet_socket = socket(PF_PACKET, socket_type, protocol);

描述:
packet socket用於從設備驅動層接收或發送原始數據包,可用於用戶在
物理層以上構建自己的通信協議.

socket_type 可爲: SOCK_RAW/或SOCK_DGRAM.其中SOCK_RAW可用於發送
原始數據包,此時可自定義數據鏈路層頭部;SOCK_DGRAM可用於在數據鏈
路層以上構建包.結構sockaddr_ll中會用到鏈路層頭部信息.協議爲IE-
EE 802.3 協議號的網絡序列(可參考文件--它包含了
可接受的協議號定義).所有到達的屬於已定義物理層協議的包先通過p-
acket socket到達已在內核實現的鏈路層協議處理層.

僅有特權進程或有CAP_NET_RAW屬性的進程才能打開packet套接口.

如果用SOCK_RAW,則數據包將直接通過設備驅動程序不加任何改變地發送
出去.這就要求用戶程序必須瞭解物理層頭部結構,並適當地構建包,此時
地址解析將用到標準sockaddr_ll結構.SOCK_RAW很象用於2.0版核心老的
SOCK_PACKET,但他們並不完全一致.

SOCK_DGRAM建立在更高層.在接受包時,物理頭將在到達用戶前被去掉;而
在發包時,物理頭部將在發送前被自動添加.

默認地所有的包都從packet socket層接收.當僅接收從特定界面來的包時
將使用bind來綁定由sockaddr_ll地址結構指定的接口.

爲發送SOCK_RAW包,用戶必須提供空間並構建包括物理頭部在內的完整的數
據包.此包將不僅任何改變地加入網卡驅動程序發送隊列,而網卡將由目的
地址確認.對於SOCK_DGRAM包,其頭部將在包被加入發送隊列前由系統根據
地址結構(sockaddr_ll)信息自動填寫.

地址結構:
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爲在sys/if_ether.h中定義的標準以太協議好的網絡序列.
sll_pkttype爲包類型.可用的有PACKET_HOST類型用於本機地址的包;PAC-
KET_BROADCAST類型用於物理廣播;PACKET_MULTICAST類型用於物理
組播;PACKET_OTHERHOST用於在網卡混雜模式下從別的主機通信上接
收包;PACKET_OUTGOING類型用於從本機packet socket發出的包.
sll_halen和sll_addr爲物理地址及其長度.

組播和混雜模式的支持:
Linux2.2支持一種建立在packet socket上的新方法來配置組播和混雜模式.
他調用setsockopt來工作,其工作建立在SOL_PACKET packet socket之上,其
選項爲PACKET_ADD_MEMBERSHIP或PACKET_DROP_MEMBERSHIP.底層結構爲:

struct packet_mreq
{
intmr_ifindex; /* 接口編號 */
unsigned shortmr_type; /* mreq 類型 */
unsigned shortmr_alen; /* 地址長度 */
unsigned charmr_address[8]; /* 物理地址 */
};

mr_interfac包含接口索引,他指出了誰將要被改變.
mr_type有:PACKET_MR_MULTICAST用於綁定套接口和由mr_address指定的物理
組播地址;PACKET_MR_PROMISC 用於激活混雜模式以接受所有網絡包;
PACKET_DROP_MEMBERSHIP用於撤銷綁訂或重置.

輸入輸出控制:
輸入輸出控制可調用ioct:
ioctl(tcp_socket, ioctl_type, value_ptr);

SIOCGSTAMP 返回一個標準timeval結構,則在須精確時間記錄時很有用.
FIOCSETOWN 和 SIOCSPGRP 用於在進程在異步通信結束時發送SIGIO信號,其參
數爲pid_t類型.
FIOCGETOWN 和 SIOCGPGRP 用於得到當前接收到SIGIO信號的進程組,當沒有設
置時返回0,參數類型爲pid_t.
出錯處理:
無出錯處理機制.

兼容性:
Linux 2.0僅支持SOCK_RAW它使用老的結構:
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爲設備名,如"eth0";

出錯類型:
ENETDOWN 接口未工作.

ENOTCONN 沒有接口地址.

ENODEV 未知的設備或接口名.

EMSGSIZE 包太大.

ENOBUFS 沒有足夠的內存來存放接收的包.

EFAULT 錯誤的內存地址.

EINVAL 參數錯.

ENXIO 接口地址包含不合法接口索引.

EPERM 無打開packet socket接口權用戶.

EADDRNOTAVAIL 未知組播地址.oup address passed.

ENOENT 未接收到包.

翻譯太匆忙且小第水平太差望大家見諒. by cloud ---- 1999/12/18

發佈了24 篇原創文章 · 獲贊 1 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章