Manpages

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 [AT] up369.com>

[中 文 版 最 新 更 新 ]

2000/10/15

《 中 国 linux论 坛 man手 册 页 翻 译 计 划 》 :

http://cmpp.linuxforum.net

本 页 面 中 文 版 由 中 文 man 手 册 页 计 划 提 供 。 中 文 man 手 册 页 计 划 : https://github.com/man-pages-zh/manpages-zh