packet 中文man页面

系统
分组套接口(也译为插口或套接字)被用于在设备层(OSI 的链路层) 收发原始(raw )分组。它允许用户在用户空间实现在物理层之上的协议模块。

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包含物理层协议。

#p#

NAME

packet, PF_PACKET - packet interface on device level.  

SYNOPSIS

#include <sys/socket.h>

#include <netpacket/packet.h>
#include <net/ethernet.h> /* the L2 protocols */ packet_socket = socket(PF_PACKET, int socket_type, int protocol);

DESCRIPTION

Packet sockets are used to receive or send raw packets at the device driver
(OSI Layer 2) level. They allow the user to implement protocol modules in user space on top of the physical layer.

The socket_type is either SOCK_RAW for raw packets including the link level header or SOCK_DGRAM for cooked packets with the link level header removed. The link level header information is available in a common format in a sockaddr_ll. protocol is the IEEE 802.3 protocol number in network order. See the <linux/if_ether.h> include file for a list of allowed protocols. When protocol is set to htons(ETH_P_ALL) then all protocols are received. All incoming packets of that protocol type will be passed to the packet socket before they are passed to the protocols implemented in the kernel.
  Only processes with effective uid 0 or the CAP_NET_RAW capability may open packet sockets.

SOCK_RAW packets are passed to and from the device driver without any changes in the packet data. When receiving a packet, the address is still parsed and passed in a standard sockaddr_ll address structure. When transmitting a packet, the user supplied buffer should contain the physical layer header. That packet is then queued unmodified to the network driver of the interface defined by the destination address. Some device drivers always add other headers. SOCK_RAW is similar to but not compatible with the obsolete SOCK_PACKET of Linux 2.0.

SOCK_DGRAM operates on a slightly higher level. The physical header is removed before the packet is passed to the user. Packets sent through a SOCK_DGRAM packet socket get a suitable physical layer header based on the information in the sockaddr_ll destination address before they are queued.

By default all packets of the specified protocol type are passed to a packet socket. To only get packets from a specific interface use bind(2) specifying an address in a struct sockaddr_ll to bind the packet socket to an interface. Only the sll_protocol and the sll_ifindex address fields are used for purposes of binding.

The connect(2) operation is not supported on packet sockets.

When the MSG_TRUNC flag is passed to recvmsg(2), recv(2), recvfrom(2) the real length of the packet on the wire is always returned, even when it is longer than the buffer.

ADDRESS TYPES

The sockaddr_ll is a device independent physical layer address.

struct sockaddr_ll {
    unsigned short  sll_family;    /* Always AF_PACKET */
    unsigned short  sll_protocol;  /* Physical layer protocol */
    int             sll_ifindex;   /* Interface number */
    unsigned short  sll_hatype;    /* Header type */
    unsigned char   sll_pkttype;   /* Packet type */
    unsigned char   sll_halen;     /* Length of address */ 
    unsigned char   sll_addr[8];   /* Physical layer address */
};

sll_protocol is the standard ethernet protocol type in network order as defined in the linux/if_ether.h include file. It defaults to the socket's protocol. sll_ifindex is the interface index of the interface (see netdevice(7)); 0 matches any interface (only legal for binding). sll_hatype is a ARP type as defined in the linux/if_arp.h include file. sll_pkttype contains the packet type. Valid types are PACKET_HOST for a packet addressed to the local host, PACKET_BROADCAST for a physical layer broadcast packet, PACKET_MULTICAST for a packet sent to a physical layer multicast address, PACKET_OTHERHOST for a packet to some other host that has been caught by a device driver in promiscuous mode, and PACKET_OUTGOING for a packet originated from the local host that is looped back to a packet socket. These types make only sense for receiving. sll_addr and sll_halen contain the physical layer (e.g. IEEE 802.3) address and its length. The exact interpretation depends on the device.

When you send packets it is enough to specify sll_family, sll_addr, sll_halen, sll_ifindex. The other fields should be 0. sll_hatype and sll_pkttype are set on received packets for your information. For bind only sll_protocol and sll_ifindex are used.

SOCKET OPTIONS

Packet sockets can be used to configure physical layer multicasting and promiscuous mode. It works by calling setsockopt(2) on a packet socket for SOL_PACKET and one of the options PACKET_ADD_MEMBERSHIP to add a binding or PACKET_DROP_MEMBERSHIP to drop it. They both expect a packet_mreq structure as argument:

struct packet_mreq
{
    int             mr_ifindex;    /* interface index */
    unsigned short  mr_type;       /* action */
    unsigned short  mr_alen;       /* address length */
    unsigned char   mr_address[8]; /* physical layer address */ 
};

mr_ifindex contains the interface index for the interface whose status should be changed. The mr_type parameter specifies which action to perform. PACKET_MR_PROMISC enables receiving all packets on a shared medium - often known as ``promiscuous mode'', PACKET_MR_MULTICAST binds the socket to the physical layer multicast group specified in mr_address and mr_alen, and PACKET_MR_ALLMULTI sets the socket up to receive all multicast packets arriving at the interface.

In addition the traditional ioctls SIOCSIFFLAGS, SIOCADDMULTI, SIOCDELMULTI can be used for the same purpose.

IOCTLS

SIOCGSTAMP can be used to receive the time stamp of the last received packet. Argument is a struct timeval.

In addition all standard ioctls defined in netdevice(7) and socket(7) are valid on packet sockets.

ERROR HANDLING

Packet sockets do no error handling other than errors occurred while passing the packet to the device driver. They don't have the concept of a pending error.

COMPATIBILITY

In Linux 2.0, the only way to get a packet socket was by calling socket(PF_INET, SOCK_PACKET, protocol). This is still supported but strongly deprecated. The main difference between the two methods is that SOCK_PACKET uses the old struct sockaddr_pkt to specify an interface, which doesn't provide physical layer independence.

struct sockaddr_pkt
{
    unsigned short  spkt_family;
    unsigned char   spkt_device[14];
    unsigned short  spkt_protocol;
};

spkt_family contains the device type, spkt_protocol is the IEEE 802.3 protocol type as defined in <sys/if_ether.h> and spkt_device is the device name as a null terminated string, e.g. eth0.

This structure is obsolete and should not be used in new code.

NOTES

For portable programs it is suggested to use PF_PACKET via pcap(3); although this only covers a subset of the PF_PACKET features.

The SOCK_DGRAM packet sockets make no attempt to create or parse the IEEE 802.2 LLC header for a IEEE 802.3 frame. When ETH_P_802_3 is specified as protocol for sending the kernel creates the 802.3 frame and fills out the length field; the user has to supply the LLC header to get a fully conforming packet. Incoming 802.3 packets are not multiplexed on the DSAP/SSAP protocol fields; instead they are supplied to the user as protocol ETH_P_802_2 with the LLC header prepended. It is thus not possible to bind to ETH_P_802_3; bind to ETH_P_802_2 instead and do the protocol multiplex yourself. The default for sending is the standard Ethernet DIX encapsulation with the protocol filled in.

Packet sockets are not subject to the input or output firewall chains.

ERRORS

ENETDOWN
Interface is not up.
ENOTCONN
No interface address passed.
ENODEV
Unknown device name or interface index specified in interface address.
EMSGSIZE
Packet is bigger than interface MTU.
ENOBUFS
Not enough memory to allocate the packet.
EFAULT
User passed invalid memory address.
EINVAL
Invalid argument.
ENXIO
Interface address contained illegal interface index.
EPERM
User has insufficient privileges to carry out this operation.
EADDRNOTAVAIL
Unknown multicast group address passed.
ENOENT
No packet received.

In addition other errors may be generated by the low-level driver.

VERSIONS

PF_PACKET is a new feature in Linux 2.2. Earlier Linux versions supported only SOCK_PACKET.

BUGS

glibc 2.1 does not have a define for SOL_PACKET. The suggested workaround is to use

#ifndef SOL_PACKET
#define SOL_PACKET 263
#endif

This is fixed in later glibc versions and also does not occur on libc5 systems.

The IEEE 802.2/803.3 LLC handling could be considered as a bug.

Socket filters are not documented.

The MSG_TRUNC recvmsg extension is an ugly hack and should be replaced by a control message. There is currently no way to get the original destination address of packets via SOCK_DGRAM.

HISTORICAL NOTE

The include file <netpacket/packet.h> is present since glibc2.1. Older systems need

#include <asm/types.h>

#include <linux/if_packet.h>
#include <linux/if_ether.h> /* The L2 protocols */

SEE ALSO

ip(7), socket(7), socket(2), raw(7), pcap(3)

RFC 894 for the standard IP Ethernet encapsulation.

RFC 1700 for the IEEE 802.3 IP encapsulation.

The <linux/if_ether.h> include file for physical layer protocols.

责任编辑:韩亚珊 来源: CMPP.net
相关推荐

2011-08-24 16:48:36

man中文man

2011-08-15 10:21:09

man中文man

2011-08-11 16:11:49

at中文man

2011-08-25 10:21:56

man.conf中文man

2011-11-01 13:46:50

中文mantac

2011-08-25 16:55:26

gets中文man

2011-08-25 15:49:02

freopen中文man

2011-08-25 16:00:56

fflush中文man

2011-08-25 16:08:55

fsetpos中文man

2011-08-25 15:33:18

exit中文man

2011-08-25 10:55:37

services中文man

2011-08-25 09:35:26

units中文man

2011-08-24 13:57:35

DECLARE中文man

2011-08-11 15:28:43

ali中文man

2011-08-23 17:24:11

userdel中文man

2011-08-23 17:33:22

rdev中文man

2011-08-23 18:05:21

ABORT中文man

2011-08-18 19:15:25

group中文man

2011-08-23 10:17:54

bdflush中文man

2011-08-23 10:48:03

exportfs中文man
点赞
收藏

51CTO技术栈公众号