NAME
raw, SOCK_RAW - Linux IPv4 raw socket.
总 览
#include
<sys/socket.h>
#include <netinet/in.h>
raw_socket = socket(PF_INET, SOCK_RAW, int protocol );
描 述
Raw sockets 使 得 用 户 端 可 以 实 现 新 的 IPv4 协 议 。 raw socket 设 备 接 收 或 发 送 不 含 链 接 层 报 头 的 原 始 数 据 包 。 只 有 激 活 接 口 选 项 IP_HDRINCL 时 IPv4 层 才 会 在 传 输 包 中 添 加 IP 报 头 。 而 且 当 激 活 时 , 包 中 必 须 含 有 IP 报 头 。 包 中 含 有 IP 报 头 才 能 被 接 收 。 只 有 user id 为 0 或 具 有 CAP_NET_RAW 能 力 才 能 打 开 raw sockets. 所 有 匹 配 为 此 raw socket 声 明 的 协 议 号 的 包 或 错 误 都 将 被 传 送 到 该 socket.要 察 看 许 可 的 协 议 列 表 , 请 参 考 RFC1700 给 出 的 代 号 和 getprotobyname (3).
IPPROTO_RAW 意 味 着 IP_HDRINCL 处 于 激 活 状 态 , 也 意 味 着 接 收 所 有 IP 协 议 . 但 是 不 允 许 传 送 。
如 果 指 定 了 IP_HDRINCL 且 IP 报 头 含 有 的 目 的 地 址 不 是 0, 那 么 该 socket 的 目 的 地 址 用 于 路 由 该 包 。 如 果 指 定 了 MSG_DONTROUTE 则 目 的 地 址 应 指 向 某 个 本 地 接 口 。 否 则 会 进 行 路 有 表 查 找 , 但 是 网 关 路 由 会 被 忽 略 。 如 果 未 设 定 IP_HDRINCL 则 可 通 过 setsockopt (2) 在 raw socket 中 设 定 IP header 选 项 。 参 考 ip (7) 了 解 更 多 信 息 。 在 Linux 2.2 下 可 以 用 IP socket 选 项 设 置 所 有 的 IP 报 头 域 和 选 项 . 这 意 味 着 通 常 只 有 新 的 协 议 或 没 有 用 户 界 面 的 协 议 需 要 raw socket (就 象 ICMP). 当 收 到 一 个 包 时 , 它 首 先 被 传 给 绑 定 到 包 协 议 的 任 何 raw socket 然 后 才 传 给 其 他 协 议 句 柄 (handler)。 (比 如 . 内 核 协 议 模 块 ).
地 址 格 式
raw socket 使 用 在 ip (7) 中 定 义 的 标 准 sockaddr_in 地 址 结 构 。 sin_port 域 用 于 指 定 IP 协 议 号 , 但 是 在 Linux 2.2 下 传 送 时 应 将 其 忽 略 , 而 且 应 该 一 直 设 为 0 (参 见 BUGS). 对 于 接 收 的 包 , sin_port 被 设 置 为 该 包 的 协 议 号 。 参 考 其 中 包 括 介 绍 有 效 的 IP 协 议 的 文 件 .
SOCKET选 项
raw socket
选 项 可 使 用 setsockopt (2)
进 行 设 置 , 用
getsockopt (2)进 行 读 取 (
通 过 传 递 SOL_RAW 族
标 志 ) .
ICMP_FILTER 激 活 绑 定 到
IPPROTO_ICMP 协 议 的 一 个
用 于 raw socket 特 殊 的
过 滤 器 。 该 值
对 每 种 ICMP 消 息 都
有 一 个 位 ( 掩
码 ) , 可 以 把
那 种 ICMP 消 息 过 滤
掉 . 缺 省 时 是
不 过 滤 ICMP 消 息 .
另 外 , 还 支 持
所 有 对 数 据 报 socket
有 效 的 ip(7) SOL_IP socket 选
项 .
注 意
raw socket 包 长 超 过 接 口 MTU 时 会 把 包 分 成 碎 片 。 (另 见 BUGS). 另 一 个 更 友 好 和 快 速 的 选 择 是 使 用 路 径 MTU 查 找 。 在 ip (7) IP_PMTU_DISCOVER 一 段 有 详 细 描 述 。 使 用 bind (2) 可 将 raw socket 绑 定 到 指 定 的 本 地 地 址 。 如 果 没 有 绑 定 , 则 接 收 所 有 符 合 指 定 的 IP 协 议 的 包 。 另 外 用 SO_BINDTODEVICE 可 以 将 RAW socket 绑 定 到 指 定 的 网 络 设 备 。 详 见 : socket (7).
IPPROTO_RAW 只 能 传 送 。 如 果 你 确 实 想 接 收 所 有 的 IP 包 用 packet (7) socket 和 ETH_P_IP 协 议 . 请 注 意 packet socket不 象 raw socket 那 样 对 IP 碎 片 进 行 重 组 。 如 果 想 要 为 一 个 datagram socket 接 收 的 所 有 ICMP 包 , 那 么 最 好 在 那 个 socket 上 使 用 IP_RECVERR。 详 见 : ip (7).
raw socket 能 窃 听 所 有 的 IP 协 议 , 即 使 象 ICMP 或 TCP 这 样 在 内 核 中 有 协 议 模 块 的 也 不 例 外 。 这 时 候 包 会 同 时 传 送 到 核 心 模 块 和 raw socket. 一 个 可 移 植 的 程 序 不 能 依 赖 这 个 特 性 , 许 多 其 他 BSD socket 实 现 在 这 方 面 有 局 限 .
Linux 从 不 改 变 用 户 传 输 的 包 (除 了 前 面 提 到 的 IP_HDRINCL , 填 入 一 些 0字 段 ).这 与 其 他 raw socket 实 现 方 式 是 不 同 的 .
RAW socket 通 常 很 难 移 植 . socket 传 输 时 使 用 sin_port 中 设 置 的 协 议 , 但 Linux2.2 下 不 行 了 , 解 决 办 法 是 使 用 IP_HDRINCL.
错 误 处 理
只 有 连 接 了 socket 或 IP_RECVERR 设 置 为 有 效 时 , 网 络 错 误 才 会 传 送 给 用 户 。 因 为 兼 容 性 的 原 因 只 有 EMSGSIZE 和 EPROTO 被 传 送 给 socket.
错 误
IP_RECVERR
使 得 所 有 的 错
误 存 储 到 error queue(
错 误 队 列 ) .
EMSGSIZE 包 太 大 。 或
者 因 为 路 径 MTU 查
找 ( IP_PMTU_DISCOVER) 设 置
为 有 效 , 或 者
因 为 包 的 尺 寸
超 过 IPv4 规 定 的 包
最 大 尺 寸 64KB.
EACCES 用 户 试 图 传 送 到 某 广 播 地 址 但 是 并 未 事 先 在 |
socket中 设 置 广 播 标 志 。 | ||
EPROTO |
ICMP 错 误 报 告 有 参 数 问 题 。
EFAULT 无 效 内 存 地 址 。 |
EOPNOTSUPP 传 送 给 socket 的 标 志 无 效 (比 如 : MSG_OOB ).
EINVAL 无 效 参 数 |
. 打 开 raw socket. 只 有 用 户 id 为 0 或 具 有 CAP_NET_RAW 属 性 方 可 。 版 本IP_RECVERR 和 ICMP_FILTER 是 Linux 2.2 的 新 实 现 . 不 能 用 于 可 移 植 程 序 。 如 果 设 置 了 SO_BSDCOMPAT 标 志 , Linux 2.0 里 面 有 和 BSD 里 兼 容 的 raw socket 代 码 错 误 , 在 2.2 里 已 经 修 补 了 . BUGS没 有 描 述 透 明 代 理 扩 展 . 当 设 置 IP_HDRINCL 选 项 后 datagrams( 自 寻 址 数 据 包 ) 不 会 被 分 段 并 受 MTU 限 制 . 这 是 Linux 2.2 的 限 制 . 在 Linux 2.2 sin_port 中 设 置 的 IP 协 议 会 丢 失 。 使 用 的 是 绑 定 了 socket 的 协 议 , 或 在 socket (2)初 始 化 调 用 中 指 定 的 协 议 。 作 者Andi Kleen. 另 见ip(7), socket(7), recvmsg(2), sendmsg(2). RFC1191 for
path MTU discovery. [中 文 版 维 护 人 ]RedCandle <redcandle51 [AT] chinaren.com> [中 文 版 最 新 更 新 ]2000/10/15 《 中 国 linux论 坛 man手 册 页 翻 译 计 划 》 :跋本 页 面 中 文 版 由 中 文 man 手 册 页 计 划 提 供 。 中 文 man 手 册 页 计 划 : https://github.com/man-pages-zh/manpages-zh |