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
協議的檔案.
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
裡已經修補了.
沒有描述透明代理擴充套件.
當設定 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 <[email protected]>
2000/10/15
http://cmpp.linuxforum.net
本頁面中文版由中文 man
手冊頁計劃提供。
中文 man 手冊頁計劃:
https://github.com/man-pages-zh/manpages-zh