PF_PACKET 设备层编程接口
定义:
#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中会用到链路层头部信息.协议为IEEE 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类型用于本机地址的包;
PACKET_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
阅读(2256) | 评论(0) | 转发(0) |