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
报头。 |
|
IP Checksum |
总是写入。 |
Source Address |
为 0 时写入。 |
Packet Id |
为 0 时写入。 |
Total Length |
总是写入。 |
如果指定了 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
- 无效参数.
- EPERM
- 用户无权打开 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.
RFC791 and the include file for the IP protocol.
[中文版维护人]¶
RedCandle <redcandle51@chinaren.com>
[中文版最新更新]¶
2000/10/15
《中国linux论坛man手册页翻译计划》:¶
http://cmpp.linuxforum.net