Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 18234] ファイルの概要

このコミットは、Go言語の標準ライブラリnetパッケージ内のテストコードにおける、IPv6アドレスの内部表現の誤りを修正するものです。具体的には、dialgoogle_test.goファイル内のIPv4-mapped IPv6アドレスのフォーマット文字列が修正されています。

コミット

commit 47dc18313684383ea2432b57f34e353db0593a4d
Author: Mikio Hara <mikioh.mikioh@gmail.com>
Date:   Tue Jan 14 07:36:38 2014 +0900

    net: fix incorrect internal IPv6 address representation in test
    
    Also fixes a dialgoogle test glitch after issue 6628 fix.
    
    R=golang-codereviews, r
    CC=golang-codereviews
    https://golang.org/cl/50660044

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/47dc18313684383ea2432b57f34e353db0593a4d

元コミット内容

net: fix incorrect internal IPv6 address representation in test Also fixes a dialgoogle test glitch after issue 6628 fix.

このコミットは、netパッケージのテストコードにおけるIPv6アドレスの内部表現の誤りを修正します。また、issue 6628の修正後に発生したdialgoogleテストの不具合も修正します。

変更の背景

このコミットの背景には、主に二つの側面があります。

  1. IPv4-mapped IPv6アドレスの表現の正確性: IPv6アドレスには、IPv4アドレスをIPv6アドレス空間にマッピングするための特別な形式が存在します。これは「IPv4-mapped IPv6アドレス」と呼ばれ、::ffff:C.D.E.Fまたは0:0:0:0:0:ffff:C.D.E.Fの形式で表現されます。Goのnetパッケージのテストコード内で、このIPv4-mapped IPv6アドレスの文字列表現に誤りがあり、それがテストの正確性に影響を与えていました。特に、::ffff:の部分のコロンの数が不正確でした。

  2. issue 6628の修正による影響: コミットメッセージに「Also fixes a dialgoogle test glitch after issue 6628 fix」とあるように、この変更は以前のissue 6628の修正によって引き起こされたdialgoogleテストの不具合を解消する目的も持っています。issue 6628は、GoのnetパッケージにおけるDNSリゾルバの動作に関するもので、特にIPv6アドレスの解決と関連していました。この修正が導入されたことで、dialgoogleテストが期待通りに動作しなくなるという副作用が発生したと考えられます。これは、テストが特定のIPv6アドレス形式を期待していたにもかかわらず、issue 6628の修正によってその期待が満たされなくなったため、テストが失敗するようになった可能性があります。このコミットは、テストコード内のIPv6アドレス表現を修正することで、この不具合を解消しています。

前提知識の解説

IPv6アドレスの基礎

IPv6アドレスは128ビット長で、8つの16ビットのセグメントをコロンで区切って表記します(例: 2001:0db8:85a3:0000:0000:8a2e:0370:7334)。 省略記法として、連続する0のセグメントは::で一度だけ省略できます(例: 2001:db8::8a2e:370:7334)。

IPv4-mapped IPv6アドレス

IPv4-mapped IPv6アドレスは、IPv4アドレスをIPv6アドレスとして表現するための特殊な形式です。これは、IPv4とIPv6が混在する環境で、IPv4専用のアプリケーションがIPv6スタック上で動作できるようにするために使用されます。 形式は以下の通りです。

  • ::ffff:C.D.E.F
  • 0:0:0:0:0:ffff:C.D.E.F

ここで、C.D.E.Fは標準的なIPv4アドレスです。最初の96ビット(6つの16ビットセグメント)はゼロで、次の16ビット(1セグメント)はすべて1(ffff)であり、最後の32ビット(2つの16ビットセグメント)がIPv4アドレスを表します。

Go言語のnetパッケージ

Go言語のnetパッケージは、ネットワークI/Oのプリミティブを提供します。TCP/IP、UDP、IP、Unixドメインソケットなどのネットワークプロトコルをサポートし、IPアドレスの解析、名前解決(DNSルックアップ)、ネットワーク接続の確立など、様々なネットワーク関連機能を提供します。テストコードでは、これらの機能が正しく動作するかを確認するために、様々な形式のIPアドレスが使用されます。

dialgoogle_test.go

このファイルは、GoのnetパッケージがGoogleのサービス(例えば、GoogleのDNSサーバーやWebサーバー)に正しく接続できるかをテストするために使用されます。これは、Goのネットワークスタックが一般的なインターネットサービスに対して正しく機能することを確認するための統合テストの一種です。テストでは、様々なIPアドレス形式(IPv4、IPv6、IPv4-mapped IPv6など)を使用して接続を試みます。

技術的詳細

このコミットの技術的な核心は、IPv4-mapped IPv6アドレスの文字列表現におけるコロンの数の修正です。

元のコードでは、googleaddrsipv4という文字列スライスの中に、以下のようなIPv4-mapped IPv6アドレスのフォーマット文字列が含まれていました。

"[0:0:0:0:0:ffff::%d.%d.%d.%d]:80",

この文字列は、IPv4アドレスをIPv6アドレスにマッピングする際の標準的な形式である::ffff:C.D.E.Fを意図しています。しかし、::は連続する0のセグメントを一度だけ省略するために使用されるため、0:0:0:0:0:ffff::という表現は文法的に誤りです。

正しいIPv4-mapped IPv6アドレスの表現は、0:0:0:0:0:ffff:C.D.E.Fまたは::ffff:C.D.E.Fです。 元のコードの0:0:0:0:0:ffff::の部分は、0:0:0:0:0:ffff:の後に::が続くことで、ffffの後にさらに0のセグメントが省略されているかのように見えますが、実際にはffffはIPv4アドレスのプレフィックスであり、その後に続くのはIPv4アドレスの各オクテットです。

正しい形式は、0:0:0:0::ffff:%d.%d.%d.%dのように、0:0:0:0の後に::で残りの0セグメントを省略し、その後にffffとIPv4アドレスが続く形です。

修正後のコードは以下のようになります。

"[0:0:0:0::ffff:%d.%d.%d.%d]:80",

この変更により、0:0:0:0の後に::が来て、その後にffffとIPv4アドレスが続くという、IPv4-mapped IPv6アドレスの正しい省略形式がテストコードに反映されました。これにより、テストが生成するIPv6アドレス文字列がRFCに準拠し、Goのnetパッケージがこれらのアドレスを正しく解析・処理できることを保証します。

また、この修正は、issue 6628の修正によってdialgoogleテストが失敗するようになった問題も解決します。issue 6628の修正がネットワークスタックの動作に影響を与え、テストが期待するIPv6アドレスの形式と実際の動作が乖離した可能性があります。テストコード内のIPv6アドレス表現を正確にすることで、この乖離が解消され、テストが再びパスするようになりました。

コアとなるコードの変更箇所

変更はsrc/pkg/net/dialgoogle_test.goファイルの一箇所のみです。

--- a/src/pkg/net/dialgoogle_test.go
+++ b/src/pkg/net/dialgoogle_test.go
@@ -104,7 +104,7 @@ var googleaddrsipv4 = []string{
 	"[::ffff:%02x%02x:%02x%02x]:80",
 	"[0:0:0:0:0000:ffff:%d.%d.%d.%d]:80",
 	"[0:0:0:0:000000:ffff:%d.%d.%d.%d]:80",
-	"[0:0:0:0:0:ffff::%d.%d.%d.%d]:80",
+	"[0:0:0:0::ffff:%d.%d.%d.%d]:80",
 }
 
 func TestDialGoogleIPv4(t *testing.T) {

コアとなるコードの解説

変更された行は、googleaddrsipv4という文字列スライス内のIPv4-mapped IPv6アドレスのフォーマット文字列です。

元の行: "[0:0:0:0:0:ffff::%d.%d.%d.%d]:80",

修正後の行: "[0:0:0:0::ffff:%d.%d.%d.%d]:80",

この修正は、IPv6アドレスの省略記法である::の適用ルールに準拠するためのものです。 IPv6アドレスでは、連続する0のセグメントを::で一度だけ省略できます。 元の文字列0:0:0:0:0:ffff::では、0:0:0:0:0の後にffffが来て、その後に::が続いています。これは、ffffの後にさらに0のセグメントが省略されているかのように見えますが、IPv4-mapped IPv6アドレスの構造上、ffffの後に続くのはIPv4アドレスのオクテットであり、0のセグメントではありません。

正しいIPv4-mapped IPv6アドレスの省略形式は、0:0:0:0:0000:ffff:C.D.E.Fを省略して0:0:0:0::ffff:C.D.E.Fとするものです。 つまり、0:0:0:0の後に続く0000(または0)のセグメントを::で省略し、その後にffffとIPv4アドレスが続く形が正しいです。

この修正により、テストコードが生成するIPv4-mapped IPv6アドレスの文字列がRFCに準拠し、Goのnetパッケージがこれらのアドレスを正しく処理できることを保証します。これにより、dialgoogleテストの信頼性が向上し、以前のissue 6628の修正によって引き起こされたテストの不具合が解消されました。

関連リンク

参考にした情報源リンク