AF_INET6(7) Linux の IPv6 プロトコル実装

Other Alias

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 でのアドレス表記は 2 桁の 16 進数 16 個からなり、 ':' は区切り文字はで、"::" は 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_DSTOPS, 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 (偽) である。

バージョン

IPv6 API を libc5 ベースで Linux 向けに実装した、以前の libinet6 についてはここでは記述していない。 おそらく細かいところには相違点があるだろう。

Linux 2.4 では 64 ビットのホストに対して sockaddr_in6 のバイナリ互換性が保たれていない。 in6_addr のアラインメントが変更され、また sin6_scope_id フィールドが新たに追加されたからである。 カーネルインターフェースの互換性は保たれているが、 sockaddr_in6in6_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 ページはまだ完成していない。