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

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

このコミットは、Go言語の標準ライブラリであるnetパッケージ内のIPv6テストにおけるプロトコル番号の誤りを修正するものです。具体的には、ICMPv6(IPv6のためのインターネット制御メッセージプロトコル)のテストケースで、誤ってIPv4 ICMPのプロトコル番号(1)が使われていたのを、正しいICMPv6のプロトコル番号(58)に対応する名称に修正しています。これにより、IPv6環境下でのICMPテストが正確に行われるようになります。

コミット

  • コミットハッシュ: 63f29d17d15651b810dd15cf6f61587a6fc5a2a6
  • 作者: Mikio Hara mikioh.mikioh@gmail.com
  • コミット日時: 2012年11月7日(水) 21:55:29 +0900
  • 変更ファイル: src/pkg/net/ipraw_test.go
  • 変更概要: IPv6テストにおけるプロトコル番号の修正。ICMPv6のプロトコル番号は58であり、1ではないことを明確にする。

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

https://github.com/golang/go/commit/63f29d17d15651b810dd15cf6f61587a6fc5a2a6

元コミット内容

net: fix protocol number for IPv6 test

The protocol number of ICMP for IPv6 is 58, not 1.

R=golang-dev, bradfitz
CC=golang-dev
https://golang.org/cl/6810093

変更の背景

この変更の背景には、ネットワークプログラミングにおけるプロトコル番号の正確な理解と適用があります。インターネットプロトコル(IP)は、そのヘッダ内に「プロトコル番号」というフィールドを持ち、これによってIPパケットのペイロード(データ部分)がどのトランスポート層プロトコル(TCP、UDPなど)またはインターネット層プロトコル(ICMPなど)に属するかを識別します。

Go言語のnetパッケージは、低レベルのネットワーク操作、特にRaw IPソケット(IPraw)を扱う機能を提供しています。Raw IPソケットを使用すると、アプリケーションはIPヘッダやその後のプロトコルデータに直接アクセスし、操作することができます。これは、カスタムプロトコルの実装や、ICMPのような制御プロトコルを扱う際に特に有用です。

このコミット以前のnetパッケージのテストコードでは、IPv6環境下でのICMPテストにおいて、プロトコル名として"ip6:icmp"が指定されていました。しかし、ICMPにはIPv4用のICMPとIPv6用のICMPv6があり、それぞれ異なるプロトコル番号が割り当てられています。

  • IPv4 ICMP: プロトコル番号 1
  • IPv6 ICMP (ICMPv6): プロトコル番号 58

テストコードが"ip6:icmp"を使用していた場合、Goのnetパッケージや基盤となるOSが、この文字列をIPv4 ICMPのプロトコル番号1として解釈してしまう可能性がありました。これは、IPv6アドレス(::1、ループバックアドレス)を使用しているにもかかわらず、誤ったプロトコル番号でパケットを構築しようとすることを意味します。結果として、テストが意図した通りにICMPv6パケットを生成・処理できず、IPv6ネットワークスタックの正確な動作検証が妨げられる可能性がありました。

このコミットは、この誤りを修正し、IPv6 ICMPのテストには明示的に"ip6:ipv6-icmp"というプロトコル名を使用することで、正しいプロトコル番号58が適用されるようにしました。これにより、IPv6環境下でのICMP関連機能のテストが正確かつ堅牢に行われるようになります。

前提知識の解説

1. IPraw (Raw IP Sockets)

Raw IPソケットは、通常のTCPやUDPソケットとは異なり、トランスポート層(TCP/UDP)をバイパスして、IP層のパケットに直接アクセスできるソケットです。これにより、アプリケーションはIPヘッダを自分で構築したり、受信したIPパケットのヘッダを直接検査したりすることが可能になります。

  • 用途:
    • ICMP(pingなど)のような制御プロトコルの実装。
    • 新しいネットワークプロトコルの実験的実装。
    • ネットワーク監視ツール(パケットスニッファなど)。
    • 特定のIPヘッダオプションを持つパケットの送信。
  • 注意点: Rawソケットは特権を必要とすることが多く(通常はroot権限)、誤用するとネットワークに悪影響を与える可能性があるため、慎重な扱いが求められます。

2. ICMP (Internet Control Message Protocol)

ICMPは、IPネットワーク上でエラーメッセージや運用情報(診断機能)を交換するために使用されるプロトコルです。IP層で動作し、IPパケットの配信に関する問題(例: ホスト到達不能、ポート到達不能、TTL超過)を報告したり、ネットワークの健全性を診断したりするのに使われます。

  • 主な機能:
    • エラー報告: 宛先到達不能、時間超過、パラメータ問題など。
    • 診断: エコー要求/応答(pingコマンドの基盤)、タイムスタンプ要求/応答など。
    • ルーティング情報: ルータ広告/要請(IPv6のNDPの一部)。

3. ICMPv6 (ICMP for IPv6)

ICMPv6は、IPv6ネットワークにおけるICMPのバージョンです。IPv4のICMPと同様にエラー報告や診断機能を提供しますが、IPv6の特性に合わせて拡張されており、特に重要な役割を担っています。

  • ICMPv6のプロトコル番号: 58
  • IPv4 ICMPのプロトコル番号: 1
  • ICMPv6の重要な役割:
    • Neighbor Discovery Protocol (NDP): IPv6アドレス解決(ARPの代替)、ルータ発見、プレフィックス発見、重複アドレス検出(DAD)など、IPv6の基本的な動作に不可欠な機能を提供します。
    • Multicast Listener Discovery (MLD): マルチキャストグループへの参加/離脱を管理します。
    • Path MTU Discovery: 経路上の最小MTU(最大転送単位)を決定します。

ICMPv6は、IPv6ネットワークの機能性においてIPv4 ICMPよりもはるかに中心的な役割を果たしており、その正確な実装とテストはIPv6スタックの安定性に直結します。

4. プロトコル番号

プロトコル番号は、IPヘッダの「プロトコル」フィールドに格納される8ビットの数値で、IPパケットのペイロードがどのプロトコルに属するかを示します。IANA (Internet Assigned Numbers Authority) によって管理されており、一般的なプロトコルには以下のような番号が割り当てられています。

  • 1: ICMP (IPv4)
  • 6: TCP
  • 17: UDP
  • 58: ICMPv6
  • 132: SCTP

Goのnetパッケージのような高レベルのAPIでは、これらのプロトコル番号を直接指定する代わりに、"tcp""udp""icmp""ipv6-icmp"といったプロトコル名を使用することが一般的です。これらの名前は、内部的に対応するプロトコル番号にマッピングされます。

技術的詳細

Go言語のnetパッケージは、ネットワークプログラミングのための強力なプリミティブを提供します。net.ListenPacketnet.Dialのような関数は、プロトコル名(例: "ip4:icmp", "ip6:icmp", "ip6:ipv6-icmp")を受け取り、それに基づいて適切なソケットを作成します。

このコミットで修正されたsrc/pkg/net/ipraw_test.goファイルは、netパッケージのRaw IPソケット機能、特にICMPパケットの送受信に関するテストケースを定義しています。

icmpTestsという構造体のスライスは、異なるICMPテストシナリオを定義しています。各要素は以下のフィールドを持ちます。

  • network: ネットワークタイプとプロトコル名を組み合わせた文字列(例: "ip4:icmp", "ip6:icmp")。
  • laddr: ローカルアドレス。
  • raddr: リモートアドレス。
  • ipv6: 基盤となるソケットがAF_INET6(IPv6)であるべきかを示すブール値。

問題となっていたのは、IPv6テストケースのnetworkフィールドでした。

  • 修正前: {"ip6:icmp", "", "::1", true}
    • "ip6:icmp"という文字列は、Goのnetパッケージが内部的にプロトコル番号を解決する際に、IPv4のICMP(プロトコル番号1)と誤って関連付けてしまう可能性がありました。これは、icmpという名前が歴史的にIPv4 ICMPを指すことが多かったためです。
  • 修正後: {"ip6:ipv6-icmp", "", "::1", true}
    • "ip6:ipv6-icmp"という文字列は、より明示的にIPv6のICMP(ICMPv6)を指します。これにより、netパッケージは正しくプロトコル番号58を識別し、IPv6 ICMPパケットが適切に構築・処理されるようになります。

この変更は、Goのnetパッケージが提供する抽象化レイヤーの下で、基盤となるOSのネットワークスタックが期待通りに動作するようにするためのものです。OSによっては、"icmp"という文字列がIPv4とIPv6の両方でICMPを指すように設定されている場合もありますが、より堅牢で移植性の高いコードのためには、明示的に"ipv6-icmp"を使用することが推奨されます。

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

--- a/src/pkg/net/ipraw_test.go
+++ b/src/pkg/net/ipraw_test.go
@@ -21,7 +21,7 @@ var icmpTests = []struct {
 	ipv6  bool // test with underlying AF_INET6 socket
 }{
 	{"ip4:icmp", "", "127.0.0.1", false},
-	{"ip6:icmp", "", "::1", true},
+	{"ip6:ipv6-icmp", "", "::1", true},
 }
 
 func TestICMP(t *testing.T) {

コアとなるコードの解説

このコミットによる変更は、src/pkg/net/ipraw_test.goファイル内のicmpTestsというグローバル変数に限定されています。

icmpTestsは、netパッケージのRaw IPソケット機能を使ってICMPパケットを送受信するテストケースを定義したスライスです。各要素は匿名構造体であり、networkladdr(ローカルアドレス)、raddr(リモートアドレス)、ipv6(IPv6ソケットを使用するかどうか)の各フィールドを持ちます。

変更された行は、IPv6ループバックアドレス::1を使用するテストケースです。

  • - {"ip6:icmp", "", "::1", true},:

    • この行は削除されました。以前は、IPv6ソケット(true)を使用し、リモートアドレスとしてIPv6ループバックアドレス::1を指定しながらも、ネットワークタイプとして"ip6:icmp"を使用していました。この"icmp"という指定が、内部的にIPv4 ICMPのプロトコル番号1にマッピングされる可能性があり、IPv6環境でのICMPv6テストとしては不適切でした。
  • + {"ip6:ipv6-icmp", "", "::1", true},:

    • この行が追加されました。変更後のコードでは、ネットワークタイプが"ip6:ipv6-icmp"と明示的に指定されています。これにより、Goのnetパッケージは、この文字列をICMPv6の正しいプロトコル番号58にマッピングし、IPv6環境下でICMPv6パケットが正しく生成・処理されることを保証します。
    • "ipv6-icmp"というより具体的なプロトコル名を使用することで、コードの意図が明確になり、将来的な互換性や移植性も向上します。

この修正により、TestICMP関数が実行される際に、IPv6ループバックアドレスに対するICMPテストが、正しいICMPv6プロトコル番号(58)を用いて行われるようになり、テストの正確性が向上しました。

関連リンク

  • Go CL (Code Review): https://golang.org/cl/6810093
    • Goプロジェクトでは、GitHubのコミットに加えて、内部のコードレビューシステム(Gerritベース)のリンクが提供されることがよくあります。このリンクは、コミットに至るまでの議論やレビューの履歴を確認できます。

参考にした情報源リンク

  • RFC 792 - Internet Control Message Protocol (ICMPv4): https://datatracker.ietf.org/doc/html/rfc792
    • IPv4 ICMPのプロトコル番号1について記述されています。
  • RFC 4443 - Internet Control Message Protocol (ICMPv6) for the Internet Protocol Version 6 (IPv6): https://datatracker.ietf.org/doc/html/rfc4443
    • ICMPv6のプロトコル番号58について記述されています。
  • IANA Protocol Numbers: https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml
    • 公式のプロトコル番号割り当てリスト。ICMP (1) と IPv6-ICMP (58) を確認できます。
  • Go net package documentation: https://pkg.go.dev/net
    • Go言語のnetパッケージに関する公式ドキュメント。ListenPacketなどの関数が受け取るネットワークタイプ文字列に関する情報が含まれています。
  • Go source code for net package (e.g., lookup_unix.go or similar files handling protocol names):
    • Goのソースコードを直接参照することで、"icmp""ipv6-icmp"といった文字列がどのようにプロトコル番号に解決されるかの詳細な実装を確認できます。