raw - 約束事その他の説明 - Linux コマンド集 一覧表
名前
raw, SOCK_RAW - Linux の IPv4 raw ソケット
書式
#include <sys/socket.h>
#include <netinet/in.h>
raw_socket = socket(PF_INET, SOCK_RAW, int
protocol
);
説明
raw ソケットを使うと、新しい IPv4 プロトコルをユーザ空間で
実装できるようになる。 raw ソケットは、リンクレベルヘッダを
含まない raw データグラムの送受信ができる。
IPv4 レイヤは、扱っているソケットで
IP_HDRINCL
ソケットオプションが有効になっていなければ、
パケットを送信するときに IP ヘッダを生成する。
IP_HDRINCL
オプションが有効になっているときは、パケットには
IP ヘッダが含まれていなければならない。
受信時には、 IP ヘッダは常にパケットに含まれている。
実効ユーザー ID が 0 のプロセスか、
CAP_NET_RAW
権限を持つプロセスだけが raw ソケットをオープンすることができる。
この raw ソケットに指定された
protocol
番号にマッチする全てのパケットとエラーとが、このソケットに渡される。
許可されているプロトコルのリストは RFC1700 の割り当て番号と
getprotobyname
(3)を見よ。
IPPROTO_RAW
のプロトコルは暗黙のうちに
IP_HDRINCL
を有効にするので、
渡されたヘッダで指定された、あらゆる IP プロトコルを送信できる。
IPPROTO_RAW
経由でのあらゆる IP プロトコルの受信は、
raw ソケットを用いては行えない。
.TS
tab(:) allbox;
c s
l l.
IP ヘッダフィールド。 IP_HDRINCL によって送信時に変更される。
IP チェックサム:常に変更される。
ソースアドレス:元の値が 0 の時に変更される。
パケット ID:元の値が 0 の時に変更される。
全体の長さ:常に埋められる。
IP_HERINCL
が指定されていて、 IP ヘッダに
0 でない送信先アドレスが記入されていた場合は、
その送信先アドレスがパケットの経路を決めるのに用いられる。
MSG_DONTROUTE
が指定されている時には、
送信先アドレスはローカルなインターフェースを参照するものでなければならない。
さもないと、ルーティングテーブルの参照はいずれにせよ行われるが、
ゲートウェイが必要な経路は無視される。
IP_HDRINCL
がセットされていなければ、
raw ソケットの IP ヘッダオプションを
setsockopt
(2)を用いて設定することができる。詳細な情報は
ip
(7) を見よ。
Linux 2.2 では、 IP ヘッダの全てのフィールドとオプションとを
IP ソケットオプションによって設定できる。したがって
raw ソケットが必要になるのは、新しいプロトコルを設計する場合か、
ユーザーインターフェースを持たないプロトコル (ICMP など) を扱う場合に
限られる。
パケットは、受信されるとまずプロトコルにバインドしている
raw ソケットに渡され、
その後で他のプロトコルハンドラ (カーネルのプロトコルモジュールなど)
に渡される。
アドレスのフォーマット
raw ソケットは標準の
sockaddr_in
アドレス構造体を用いる。定義は
ip
(7) でなされている。
sin_port
フィールドを IP プロトコル番号の指定に用いることができるが、
Linux 2.2 ではこれは送信時には無視され、常に 0 にされる
(バグ の項を参照)。
受信パケットに対しては、
sin_port
はそのパケットのプロトコルにセットされる。
用いることのできる IP プロトコルは、インクルードファイル
<netinet/in.h>
を見よ。
ソケットオプション
raw ソケットのオプションは、
IPPROTO_RAW
ファミリーフラグを与えて
setsockopt
(2)を呼べば設定でき、
getsockopt
(2) を呼べば取得できる。
- ICMP_FILTER
-
IPPROTO_ICMP
プロトコルにバインドされた raw ソケットのための特殊なフィルタを有効にする。
この値は ICMP メッセージのタイプそれぞれに対して、どれをフィルターアウト
するかを表したビットセットである。デフォルトでは
ICMP メッセージは全くフィルターしない。
さらに、データグラムソケットに使える全ての ip (7) SOL_IP ソケットオプションがサポートされている。
注意
raw ソケットは、パケット全体の大きさがインターフェースの MTU を越えていると、
そのパケットをフラグメント化する
(しかし問題もある - バグ のセクションを見ること)。
よりネットワークとの相性が良く、かつより高速な手法は、
ip
(7) の
IP_MTU_DISCOVER
セクションで記述されている
Path MTU Discovery
を実装することである。
bind
(2) システムコールを用いると、
raw ソケットを
特定のローカルアドレスにバインドさせることができる。
このバインドがされていない場合は、指定した IP プロトコルの
すべてのパケットが受信される。
さらに、
SO_BINDTODEVICE
を用いれば raw ソケットを特定のネットワークデバイスに
バインドさせることもできる。
socket
(7) を見よ。
IPPROTO_RAW
ソケットは送信専用である。もしどうしてもすべての IP パケットを
受信したい場合は、
packet
(7) ソケットを
ETH_P_IP
プロトコルで用いること。
packet ソケットは raw ソケットのように
IP フラグメントを再構成しないことに注意。
datagram ソケットに対するすべての ICMP パケットを受信したい場合は、
特定のソケットに対して
IP_RECVERR
を用いるほうが良い場合が多い。
ip
(7) を見よ。
raw ソケットは、 Linux のすべての IP プロトコルを受信することができる。
ICMP や TCP のように、カーネル内部にプロトコルモジュールを持つような
ものも可能である。この場合には、パケットはカーネルモジュールと
raw ソケットの両方に渡される (raw ソケットが複数あればそれぞれに渡される)。
移植性の必要なプログラムではこの機能に依存するべきではない。
他の多くの BSD におけるソケットの実装ではこの点において制限がある。
Linux はユーザーから渡されたヘッダを決して変更しない (ただし
IP_HDRINCL
の説明にあるように、 0 をいくつか埋める場合を除く)。
これは他の多くの raw ソケットの実装では異なる。
一般に raw ソケットは移植性がないことが多いので、
移植性が必要なプログラムでは避けるべきである。
raw ソケットへの送信では、 IP プロトコルを
sin_port
から取得できなければならない。この機能は Linux 2.2 では使えなくなった。
IP_HDRINCL
を用いれば同様のことが実現できる。
エラー処理
ネットワークで生じたエラーがユーザに渡されるのは、 ソケットが接続済みの場合か IP_RECVERR フラグが有効になっている場合に限られる。 接続済みのソケットに対しては、 EMSGSIZE および EPROTO だけが渡される (互換性のため)。 IP_RECVERR を設定すると、全てのネットワークエラーがエラーキューに保存される。
エラー
- EMSGSIZE
- パケットが大きすぎる。 Path MTU Discoverry が有効になっている ( IP_MTU_DISCOVER ソケットフラグ) か、パケットのサイズが IPv4 で許されている パケットサイズの最大値 64KB を越えている。
- EACCES
- ユーザーが broadcast フラグを設定していないソケットを用いて ブロードキャストアドレスに送信を行おうとした。
- EPROTO
- パラメータの問題を報告する ICMP エラーを受け取った。
- EFAULT
- 不正なメモリアドレスが与えられた。
- EOPNOTSUPP
- ソケット呼び出しに不正なフラグ ( MSG_OOB など) が渡された。
- EINVAL
- 引数が正しくない。
- EPERM
-
ユーザーは raw ソケットをオープンする権限を持っていない。
実行ユーザー ID が 0 のプロセスか、
CAP_NET_RAW
属性を持つプロセスだけがこれを行うことができる。
バージョン
IP_RECVERR
と
ICMP_FILTER
は Linux 2.2 で登場した。これらは Linux での拡張であり、
移植性の必要なプログラムでは用いるべきでない。
Linux 2.0 では SO_BSDCOMPAT ソケットオプションをセットすると、
BSD の raw ソケットにあるバグに互換性を取ることができた \(em
Linux 2.2 以降では、このオプションはもはや効力を持たない。
バグ
透過プロクシ (transparent proxy) 拡張については記述していない。
IP_HDRINCL
オプションがセットされているとデータグラムはフラグメント化されず、
インターフェースの MTU の大きさに制限される。
送信用の IP プロトコルの設定を
sin_port
にしておく機能は Linux 2.2 から使えなくなった。
ソケットにバインドされているプロトコルか、最初の
socket
(2) コールによって指定されたプロトコルが常に用いられる。
著者
この man ページは Andi Kleen が書いた。
関連項目
recvmsg
(2),
sendmsg
(2),
capabilities
(7),
ip
(7),
socket
(7)
パス MTU 発見に関する情報は
RFC1191
にある
IP プロトコルに関しては
RFC791
とインクルードファイル
<linux/ip.h>
を参照。