#1: 1998/05/28 「最近のIPv6」 $Id: index.html,v 1.1.1.1 2003/08/28 05:58:03 itojun Exp $
IPv6に関する最近の動向ですが、あいかわらず各種の標準化活動は続いています。 最近で一番大きな変更は、struct sockaddr_in6の変更と それに関係する IPv6 basic socket API(RFC2133)と advanced socket API(RFC2292)の変更でしょう。
IPv6では、IPv4と違いアドレスに「スコープ」の概念が導入されています。 IPv4では、 (RFC1918 で定義されているプライベートアドレスを除けば) 任意のIPv4アドレスは、かならず「世界で唯一」でした。 例えば、ftp.iij.ad.jpは(これを書いてる時点では) 202.232.2.51というIPv4アドレスを持っていますが、 これは世界じゅうでただひとつのもので、他のひとが使ったりしません。 IPv6でもほとんどのIPv6アドレスは「世界でただひとつ」なのですが、 「世界でただひとつ」ではないIPv6アドレスも存在します。 たとえば、IPv6では単一のネットワーク内でしか一意性のないアドレスとして link-local addressというのを定義しています。 link-local addressはfe80::nantara(nantaraは64bit)と いうような形式をしているのですが、アドレスのなかにはどこにも 「どのネットワークのアドレスか」というのを示す識別子が入っていません。 このため、複数のネットワークに接続されたホスト上で 「このパケットはfe80::X行きね」と言われた場合、 どっちにパケットを投げればいいのか判断できません。
host A |fe80::A ==+===== | router 「fe80::X行きのパケットを | どっちに投げればいいのだろう?」 ==+===== |fe80::B host Bつまり、link-local addressを指定する場合、 「このネットワーク上のアドレス」と指定しないといけません。 ユーザから見える影響としては、例えばping6(IPv6のping)コマンドを 呼び出すときの引数があります。 多くのIPv6実装では、link-local addressへのping6を行うときは ping6 -I de0 fe80::X などとしてインタフェースを指定しないといけません。
今まではRFC2292に 述べられていたように、 sendmsgシステムコールを使って追加の構造体 struct in6_pktinfoを渡し、出力インタフェースを指定していました。 しかし、Tim Hartrickというひとが「これはめんどくさすぎる、やってられん、 sockaddr_in6にインタフェースを指定するフィールドをつけよう」と主張し、 これが受け入れられました。 これまではsockaddr_in6は以下のような定義になっていましたが、
struct sockaddr_in6 {
u_char sin6_len; /* length of this struct(sa_family_t)*/
u_char sin6_family; /* AF_INET6 (sa_family_t) */
u_int16_t sin6_port; /* Transport layer port # (in_port_t)*/
u_int32_t sin6_flowinfo; /* IP6 flow information */
struct in6_addr sin6_addr; /* IP6 address */
};
今度からはこのようになります。赤字部分が増えたところ。
struct sockaddr_in6 {
u_char sin6_len; /* length of this struct(sa_family_t)*/
u_char sin6_family; /* AF_INET6 (sa_family_t) */
u_int16_t sin6_port; /* Transport layer port # (in_port_t)*/
u_int32_t sin6_scope_id;
u_int32_t sin6_ifindex;
u_int32_t sin6_flowinfo; /* IP6 flow information */
struct in6_addr sin6_addr; /* IP6 address */
};
sin6_ifindexには、ネットワークインタフェースの番号を指定します。
例えば「3番のインタフェースにつながったネットワーク上ののfe80::Aに
パケットを投げたい場合、
struct sockaddr_in6 sin6; memset(&sin6, 0, sizeof(sin6)); sin6.sin6_family = AF_INET6; sin6.sin6_len = sizeof(struct sockaddr_in6); sin6.sin6_ifindex = 3; inet_pton(AF_INET6, "fe80::A", &sin6.sin6_addr); /* do what you want */というようなかんじになります。
まだこの変更を済ませた状態の internet-draftは 発行されていませんが、 この変更はかなり広範囲に影響がありますのではやめの対処が必要です。 ライブラリを直さないといけませんし、 カーネルやツール類も全部makeしなおさないといけません。 僕らが作業をしているKAME projectという BSD unixカーネル改造プロジェクトでは、 以前から似たような機構を違う方法で入れていました。 いい機会なので、sin6_ifindexの処理を 早めに実装して問題点を洗い出し、議論に反映させようと考えています。
いまさらこんな変更が加わったりしているのを見てもわかるように IPv6にはまだまだ決めないといけないこと、作らないといけないことが山もりです。 さらに、IPv4からIPv6にのりかえるためには、 上位層のプロトコルについてもいろいろ考えなければなりません。 また次回以降、こんなはなしについて書いていきたいとおもいます。
NOTE: この件についてはさらに方針変更がありました。 ここ参照。
FreeBSDを入れられるPCが一台あったら、いくつかpublicな実装がありますので インストールして使ってみるのをおすすめします。 ただ、どの実装も開発途上なので、ほとんど毎日毎晩更新されてます。