ipv6 - Linux IPv6
プロトコルの実装
#include <sys/socket.h>
#include <netinet/in.h>
tcp6_socket = socket(AF_INET6, SOCK_STREAM, 0);
raw6_socket = socket(AF_INET6, SOCK_RAW, protocol);
udp6_socket = socket(AF_INET6, SOCK_DGRAM,
protocol);
Linux 2.2 では、Internet Protocol, version 6 を
オプションとして実装している。
この man ページでは、Linux
カーネルと glibc 2.1
での実装に基づいて、
IPv6 の基本的な API
を解説する。
インターフェースは BSD
ソケットインターフェースをもとにしている。
socket(7) を参照。
IPv6 API は、 IPv4 API (
ip(7) 参照)
とほぼ互換になることを目指している。
この man
ページでは相違点のみを解説する。
AF_INET6
ソケットを何らかのプロセスにバインドするには、
ローカルアドレスを
in6_addr 型の変数
in6addr_any
からコピーしてくる必要がある。
static な初期値
IN6ADDR_ANY_INIT
も用いることができ、これは定数式に展開される。
これらの両者はネットワークバイトオーダーである。
IPv6
のループバックアドレス
(::1) は global 変数
in6addr_loopback
から取得できる。初期化には
IN6ADDR_LOOPBACK_INIT
を用いるべきである。
v4-mapped-on-v6
アドレス型を用いることで、
IPv4 接続も v6 API
で扱うことができる。
こうすれば、プログラムは
v6 の API
をサポートするだけで、
両方のプロトコルをサポートできる。
v4-mapped-on-v6 アドレス型は C
ライブラリ内部のアドレスを
扱う関数によって透過的に処理される。
IPv4 と IPv6
はローカルポート空間を共有する。
IPv4 の接続
(またはパケット) を IPv6
ソケットが取得すると、
発信元アドレスが v6
にマップされ、その接続
(パケット) も v6
にマップされる。
アドレスのフォーマット¶
struct sockaddr_in6 {
sa_family_t sin6_family; /* AF_INET6 */
in_port_t sin6_port; /* port number */
uint32_t sin6_flowinfo; /* IPv6 flow information */
struct in6_addr sin6_addr; /* IPv6 address */
uint32_t sin6_scope_id; /* Scope ID (new in 2.4) */
};
struct in6_addr {
unsigned char s6_addr[16]; /* IPv6 address */
};
sin6_family は常に
AF_INET6
に設定される。
sin6_port
はプロトコルポートである
(
ip(7) の
sin_port を参照)。
sin6_flowinfo は IPv6
のフロー指定子 (flow identifier)
である。
sin6_addr は 128
ビットの IPv6
アドレスである。
sin6_scope_id は
アドレスのスコープに依存した
ID である (これは Linux 2.4
で導入された)。 Linux
の場合は、これはリンクローカルアドレスでのみサポートされている。
この場合
sin6_scope_id
にはインターフェースのインデックスが含まれる
ことになる (
netdevice(7)
を参照)。
IPv6
は何種類かのアドレスタイプをサポートしている。
単一のホストをアドレスするための
unicast、
ホストのグループをアドレスするための
multicast、
ホストのグループ中で最も近くにいるものをアドレスするための
anycast (これは Linux
では実装されていない)、
IPv4
ホストをアドレスするための
IPv4-on-IPv6。
他にも予約済みのアドレスタイプがある。
IPv6 でのアドレス表記は 4
桁の 16 進数 8
個からなり、 ':'
は区切り文字はで、"::"
は 0
ビットの文字列を表す。
特殊なアドレスとして、ループバックを表す
::1、 IPv4-mapped-on-IPv6 を表す ::FFFF::<IPv4
アドレス> がある。
IPv6 のポート空間は IPv4
と共有されている。
ソケットオプション¶
IPv6
はプロトコル固有のソケットオプションをいくつかサポートしている。
これらは
setsockopt(2)
で設定でき、
getsockopt(2)
で取得できる。 IPv6
のソケットオプションレベルは
IPPROTO_IPV6 である。
ブール整数のフラグは、0
が偽であり、それ以外は真である。
- IPV6_ADDRFORM
- AF_INET6
ソケットを別のアドレスファミリーのソケットに変える。
現在は AF_INET
のみが変更先のアドレスファミリーとしてサポートされている。
これが許可されるのは、IPv6
が接続され、 v4-mapped-on-v6
アドレスにバインドされた場合に限られる。
引き数は AF_INET
が入っている整数へのポインタである。
v4-mapped ソケットを、IPv6 API
を扱えないプログラムに対して
ファイルディスクリプターとして渡す場合に便利。
- IPV6_ADD_MEMBERSHIP, IPV6_DROP_MEMBERSHIP
- multicast
グループのメンバーを制御する。
引き数は struct ipv6_mreq
構造体へのポインタ。
- IPV6_MTU
- そのソケットに対して用いる
MTU の値を設定する。 MTU
の大きさは、
そのデバイスの MTU
または (Path MTU Discovery
が可能なら)
その経路の MTU
の大きさ以下でなければならない。
引き数は整数へのポインタ。
- IPV6_MTU_DISCOVER
- そのソケットでの
Path MTU Discovery を制御する。
詳細は ip(7) の IP_MTU_DISCOVER
を参照。
- IPV6_MULTICAST_HOPS
- そのソケットでの
multicast の hop
数の上限値を設定する。
引き数は整数へのポインタである。
-1
を指定すると経路のデフォルトを用いることを意味する。
それ以外の場合は 0
から 255
の範囲を指定する。
- IPV6_MULTICAST_IF
- そのソケットでの、送信
multicast
パケットに用いるデバイスを設定する。
これは SOCK_DGRAM および
SOCK_RAW
各ソケットでのみ許される。
引き数はインターフェースのインデックスの整数値
( netdevice(7) を参照)
へのポインタである。
- IPV6_MULTICAST_LOOP
- ソケットが、自分自身の送信した
multicast
パケットを監視するかどうかを制御する。
引き数はブール値へのポインタ。
- IPV6_PKTINFO
- データグラムの到着時における
IPV6_PKTINFO
制御メッセージを配送するかどうかを設定する。
SOCK_DGRAM ソケットまたは
SOCK_RAW
ソケットに対してのみ許可される。
引き数はブール値の入った整数。
- IPV6_RTHDR, IPV6_AUTHHDR, IPV6_DSTOPTS, IPV6_HOPOPTS,
IPV6_FLOWINFO,
- IPV6_HOPLIMIT
受信パケットのデータグラムに拡張ヘッダが含まれている場合の、
制御メッセージの配送を設定する。
IPV6_RTHDR: routing
ヘッダを配送するかどうか。
IPV6_AUTHHDR: authentication
ヘッダを配送するかどうか。
IPV6_DSTOPTS: destination
オプションを配送するかどうか。
IPV6_HOPOPTS: hop
オプションを配送するかどうか。
IPV6_FLOWINFO: flow ID
を含む整数を配送するかどうか。
IPV6_HOPLIMIT: パケットの
hop
カウントを含む整数を配送するかどうか。
制御メッセージはソケットオプションのものと同じタイプを持つ。
これらのすべてのヘッダオプションは、
適切な制御メッセージを
sendmsg(2)
の制御バッファーに書きこめば、
送信パケットにでも設定できる。
SOCK_DGRAM
ソケットまたは
SOCK_RAW
ソケットでのみ許される。引き数はブール値へのポインタ。
- IPV6_RECVERR
- 非同期エラー
(asynchronous error)
オプションの受信を制御する。
詳細は ip(7) の IP_RECVERR
を参照。
引き数はブール値へのポインタ。
- IPV6_ROUTER_ALERT
- このソケットで、router
alert hop-by-hop
オプションの付いた転送パケットを
通すかどうかを制御する。
SOCK_RAW
ソケットでのみ許可される。
tap
されたパケットはカーネルによっては転送されない。そうしたパケットを
再度送信するのはユーザーの責任である。
引き数は整数 (integer)
へのポインタ。
正の整数は傍受を行う
router alert
オプション値を示す。
オプション値がこの整数である
router alert
オプションの付いたパケットは
ソケットに配送される。負の整数を指定すると、このソケットへの
router alert
オプションの付いたパケットの配送が行われない。
- IPV6_UNICAST_HOPS
- そのソケットでの
unicast の hop
数の上限値を設定する。
引き数は整数へのポインタである。
-1
を指定すると経路のデフォルトを用いることを意味する。
それ以外の場合は 0
から 255
の範囲を指定する。
- IPV6_V6ONLY (Linux 2.4.21
以降および 2.6 以降)
- このフラグを真 (0
以外)
に設定すると、そのソケットは
IPv6 パケットだけを
送受信するように制限される。
この場合、IPv4
アプリケーションと
IPv6
アプリケーションが同時に
一つのポートをバインドできる。
このフラグを偽 (0)
に設定すると、そのソケットはパケットの送受信に
IPv6 アドレスと IPv4-mapped IPv6
アドレスの両方を使用できる。
引き数はブール値の入った整数へのポインタである。
このフラグのデフォルト値はファイル
/proc/sys/net/ipv6/bindv6only
の内容により定義される。
このファイルのデフォルト値は
0 (偽) である。
エラー¶
- ENODEV
- ユーザがリンクローカルの
IPv6 アドレスを bind(2)
しようとしたが、
指定された sockaddr_in6
構造体の sin6_scope_id が
有効なインターフェースのインデックスでなかった。
バージョン¶
IPv6 API を libc5 ベースで Linux
向けに実装した、以前の
libinet6
についてはここでは記述していない。
おそらく細かいところには相違点があるだろう。
Linux 2.4 では 64
ビットのホストに対して
sockaddr_in6
のバイナリ互換性が保たれていない。
in6_addr
のアラインメントが変更され、また
sin6_scope_id
フィールドが新たに追加されたからである。
カーネルインターフェースの互換性は保たれているが、
sockaddr_in6 や
in6_addr
を他の構造体に含んでいるようなプログラムでは
保たれないかもしれない。
これは i386 のような 32
ビットのホストでは問題にならない。
sin6_flowinfo フィールドは Linux 2.4
で登場した。
これが渡されたアドレス長に含まれていると、
カーネルに透過的に渡され、読まれる。
より長いアドレスバッファを渡し、
そして送信アドレスの長さをチェックするようなプログラムは
うまく動かないかもしれない。
sockaddr_in6
構造体はジェネリックな
sockaddr よりも大きい。
すべてのアドレスタイプが
struct sockaddr
の中に安全に納められると仮定しているプログラムは、代わりに
struct sockaddr_storage
を用いるように変更する必要がある。
IPv6 拡張 API は、現在まだ
RFC 2292
を完全には実装していない。
2.2
カーネルは受信オプションをほぼ完全にサポートサポートしているが、
glibc2.1 には IPv6
オプションを生成するマクロが存在していない。
EH および AH ヘッダ での IPSec
のサポートは存在しない。
フローラベル管理はまだ完全でなく、ここにも記述されていない。
この man
ページはまだ完成していない。
関連項目¶
cmsg(3),
ip(7)
RFC 2553: IPv6 BASIC API. Linux はこの RFC
に準拠するようにしている。
RFC 2460: IPv6 specification.
この文書について¶
この man ページは Linux
man-pages
プロジェクトのリリース
3.41 の一部
である。プロジェクトの説明とバグ報告に関する情報は
http://www.kernel.org/doc/man-pages/
に書かれている。