EN JA
RAW(7)
RAW(7) Linux Programmer's Manual RAW(7)

名前

raw - Linux の IPv4 raw ソケット

書式

#include <sys/socket.h>
 
#include <netinet/in.h>
 
raw_socket = socket(AF_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 番号にマッチする全てのパケットとエラーとが、このソケットに渡される。許可されているプロトコルのリストは RFC 1700 の割り当て番号と getprotobyname(3) を見よ。
 
IPPROTO_RAW のプロトコルは暗黙のうちに IP_HDRINCL を有効にするので、渡されたヘッダで指定された、あらゆる IP プロトコルを送信できる。 IPPROTO_RAW 経由でのあらゆる IP プロトコルの受信は、 raw ソケットを用いては行えない。
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 ソケットオプションがサポートされている。

エラー処理

ネットワークで生じたエラーがユーザに渡されるのは、ソケットが接続済みの場合か IP_RECVERR フラグが有効になっている場合に限られる。接続済みのソケットに対しては、 EMSGSIZE および EPROTO だけが渡される (互換性のため)。 IP_RECVERR を設定すると、全てのネットワークエラーがエラーキューに保存される。

エラー

EACCES
ユーザーが broadcast フラグを設定していないソケットを用いてブロードキャストアドレスに送信を行おうとした。
EFAULT
不正なメモリアドレスが与えられた。
EINVAL
引き数が不正。
EMSGSIZE
パケットが大きすぎる。 Path MTU Discoverry が有効になっている ( IP_MTU_DISCOVER ソケットフラグ) か、パケットのサイズが IPv4 で許されているパケットサイズの最大値 64KB を越えている。
EOPNOTSUPP
ソケット呼び出しに不正なフラグ ( MSG_OOB など) が渡された。
EPERM
ユーザーは raw ソケットをオープンする権限を持っていない。実行ユーザー ID が 0 のプロセスか、 CAP_NET_RAW 属性を持つプロセスだけがこれを行うことができる。
EPROTO
パラメータの問題を報告する ICMP エラーを受け取った。

バージョン

IP_RECVERRICMP_FILTER は Linux 2.2 で登場した。これらは Linux での拡張であり、移植性の必要なプログラムでは用いるべきでない。
 
Linux 2.0 では SO_BSDCOMPAT ソケットオプションをセットすると、 BSD の raw ソケットにあるバグに互換性を取ることができた— Linux 2.2 以降では、このオプションはもはや効力を持たない。

注意

デフォルトでは、raw ソケットは Path MTU Discovery を行う。つまり、カーネルは特定の宛先 IP アドレスの MTU (Maximum Transmission Unit;最大転送単位) を記録し、raw パケットの書き込みが MTU を超えた場合 EMSGSIZE を返す。 EMSGSIZE を返された場合、アプリケーションはパケットサイズを小さくすべきである。ソケットオプション IP_MTU_DISCOVER または /proc/sys/net/ipv4/ip_no_pmtu_disc ファイルを使って Path MTU Discovery を無効にすることもできる (詳細は ip(7) を参照)。 Path MTU Discovery を無効にした場合は、パケットサイズがインタフェースの MTU よりも大きいと raw ソケットはそのパケットをフラグメント化して送出する。しかしながら、性能と信頼性の理由から 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 を用いれば同様のことが実現できる。

バグ

透過プロクシ (transparent proxy) 拡張については記述していない。
 
IP_HDRINCL オプションがセットされているとデータグラムはフラグメント化されず、インターフェースの MTU の大きさに制限される。
 
送信用の IP プロトコルの設定を sin_port にしておく機能は Linux 2.2 から使えなくなった。ソケットにバインドされているプロトコルか、最初の socket(2) コールによって指定されたプロトコルが常に用いられる。

関連項目

recvmsg(2), sendmsg(2), capabilities(7), ip(7), socket(7)
 
Path MTU discovery に関しては RFC 1191 を参照。 IP プロトコルに関しては RFC 791 とインクルードファイル <linux/ip.h> を参照。

この文書について

この man ページは Linux man-pages プロジェクトのリリース 3.51 の一部である。プロジェクトの説明とバグ報告に関する情報は http://www.kernel.org/doc/man-pages/ に書かれている。
2012-05-10 Linux