要約
- 中核のソケット関数はアドレスへの不透明なポインターと長さを受け取るため、呼び出し形を保てた。一方、IPv6 には
PF_INET6、sockaddr_in6、名前解決と表記変換の新たな約束が必要だった。 - 旧
PF_INETプログラムがIPv4相手に動き続けることと、新しいPF_INET6プログラムがIPv4相手を写像アドレスで表すことは、別の互換性である。どちらも通信の成功までは証明しない。
問題が表面化するのは、動作中のソケットを別のプログラムに引き渡す場面だ。受け取った側は accept() や getpeername() を知っていても、返ってきたアドレスを旧来の sockaddr_in として読むべきか、sockaddr_in6 として読むべきかを取り違えうる。RFC 2133 は1997年にこの継ぎ目を記した Informational 文書で、のちに RFC 2553 によって廃止された。現在の実装手順としてではなく、設計史として扱う必要がある。
出発点は32ビットと128ビットの差だった。従来のソケット関数はアドレス本体を不透明なポインターで受け取り、長さを別に渡す。だから bind() や sendto() の文法を変える必要はなかった。ところがIPv4用の sockaddr_in は、空き領域を利用してもIPv6アドレスとポートとアドレス族を収められない。RFCは AF_INET6 と PF_INET6、新構造体を示し、名前からアドレスを得る処理や文字列表記の変換も広げた。4.3BSD系と4.4BSD系では構造体先頭の長さ・族の配置さえ異なる。関数名の安定は、固定長バッファや型変換の安全性を保証しない。
第一の約束は、旧来のプログラムを壊さないことだった。PF_INET と sockaddr_in を使うソースとバイナリーは、IPv6を扱えるシステム上でもIPv4ノードと通信できるようにする。旧バイナリーがIPv6を理解するという意味ではない。第二の約束は新しいプログラムに向けられた。PF_INET6 のソケットではIPv4ノードのアドレスを ::FFFF:<IPv4-address> というIPv4写像IPv6アドレスとして渡せる。これはアプリケーション側の表現であり、相手の通信路がIPv6だったという観測ではない。
IPv6のワイルドカードとループバックも、別々の範囲を持つ。ローカルアドレスをシステムに選ばせる指定と、自分自身への接続先は、遠隔からの到達性を示さない。仕様に書かれたインターフェースを、実際のサービス検証に置き換えることはできない。
引き継ぎ問題への当時の提案が IPV6_ADDRFORM だった。開いたソケットについて、後続の呼び出しが受け取るアドレス構造体の見え方を PF_INET と PF_INET6 の間で変える。ただしIPv4側へ下げるには、既に結び付いた非ワイルドカードのアドレスがすべてIPv4写像でなければならない。単なる表示切替ではなく、カーネルにある状態が許す変換に限られる。廃止済みRFCの提案を、現在のOSに共通する機能とみなしてはいけない。
ローカルな状態はインターフェース番号にも現れる。RFCは if_nametoindex による名前とカーネル割当番号の対応を記し、マルチキャストでは送出インターフェースや参加先を指定できるようにした。番号が得られたこと、参加を設定したことから、別のホストでパケットが届いたとは言えない。名前解決の結果も同じく、通信を試す材料であって成功の証拠ではない。
この歴史を読む際の補助線として、Heng Lu の稼働するコードを重視する議論を参照できる。ただし技術的な事実の根拠はRFC自体であり、論説は仕様と運用結果を分けるための視点にとどめる。
会員向け解説
プロフィールの詳細
適切な会員レベルでログインすると、解説全文と出典メモをご覧いただけます。
Strategic Circle 限定
Strategic Circle
すべての読者に公開されています。参加してログインすると プロフィール解説 を閲覧できます。
Strategic Circle に参加Leadership Alliance 会員限定
Leadership Alliance
対象となる IP 資産の所有者・管理者向けです。ログインすると Leadership Alliance の解説を閲覧できます。
Leadership Alliance に参加

