[インデックス 16389] ファイルの概要
このコミットは、Go言語の syscall
パッケージに、Unix系OS向けのIPv6ソケットオプションを追加するものです。具体的には、IPv6のPath MTU Discovery (PMTUD) 情報とICMPv6フィルタリングを制御するためのソケットオプションが追加されています。これにより、GoアプリケーションがIPv6ネットワークスタックのより低レベルな機能にアクセスできるようになり、ネットワーク通信の最適化や特定のネットワーク制御が可能になります。
コミット
commit adbe59e332baada83d939325a03b5746ff25138e
Author: Mikio Hara <mikioh.mikioh@gmail.com>
Date: Thu May 23 16:22:05 2013 +0900
syscall: add IPv6 socket options for Unix variants
This CL adds missing IPv6 socket options which are required
to control IPv6 as described in RFC 3493, RFC 3542.
Update #5538
R=golang-dev, dave, iant
CC=golang-dev
https://golang.org/cl/9373046
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/adbe59e332baada83d939325a03b5746ff25138e
元コミット内容
元のコミットメッセージは以下の通りです。
「syscall: Unix系OS向けにIPv6ソケットオプションを追加。この変更は、RFC 3493およびRFC 3542で記述されているIPv6を制御するために必要な、不足しているIPv6ソケットオプションを追加するものです。Issue #5538を更新します。」
変更の背景
この変更の背景には、Go言語の syscall
パッケージが、IPv6ネットワークプログラミングにおいて、特定の重要なソケットオプションをサポートしていなかったという問題があります。特に、RFC 3493 (IPv6 Advanced Sockets API for IPv6) とRFC 3542 (Advanced Sockets Application Program Interface (API) for IPv6) で定義されている機能へのアクセスが不足していました。これらのRFCは、IPv6における高度なソケットプログラミングインターフェースを規定しており、例えばPath MTU Discovery (PMTUD) の情報取得や、ICMPv6メッセージのフィルタリングといった機能が含まれます。
Go言語でこれらの機能を利用しようとする場合、直接的なAPIが提供されていなかったため、開発者は低レベルなC言語のシステムコールを呼び出すか、あるいはこれらの機能を利用できないという制約がありました。このコミットは、Go言語の標準ライブラリを通じてこれらのIPv6ソケットオプションへのアクセスを提供することで、Goで記述されたネットワークアプリケーションの機能性と柔軟性を向上させることを目的としています。
コミットメッセージに記載されている Update #5538
は、この変更がGoのIssueトラッカーにおける特定の課題(おそらくIPv6ソケットオプションの不足に関するもの)を解決するものであることを示唆しています。
前提知識の解説
syscall
パッケージ
Go言語の syscall
パッケージは、オペレーティングシステムが提供する低レベルなシステムコールへのインターフェースを提供します。これにより、Goプログラムはファイルシステム操作、プロセス管理、ネットワーク通信など、OSカーネルが提供する基本的な機能に直接アクセスできます。このパッケージは、OSに依存する部分が多く、各OSのシステムコール規約に合わせて実装されています。
ソケットオプション
ソケットオプションは、ネットワークソケットの動作を制御するためのパラメータです。setsockopt
(ソケットオプションの設定) および getsockopt
(ソケットオプションの取得) システムコールを通じて設定・取得されます。これらのオプションは、バッファサイズ、タイムアウト、再利用アドレス、ブロードキャストの許可など、多岐にわたるネットワーク通信の挙動を調整するために使用されます。
IPv6
IPv6 (Internet Protocol Version 6) は、インターネットプロトコルの最新バージョンであり、IPv4の後継です。IPv4のアドレス枯渇問題に対処するために、より広大なアドレス空間(128ビット)を提供します。また、IPv6は、自動設定、セキュリティ機能の組み込み(IPsec)、QoS (Quality of Service) の改善など、多くの新機能と改善を含んでいます。
ICMPv6 (Internet Control Message Protocol for IPv6)
ICMPv6は、IPv6ネットワークにおけるエラー報告や診断メッセージの交換に使用されるプロトコルです。IPv4におけるICMPの役割をIPv6で果たします。例えば、到達不能なホストの通知、パケットが大きすぎる場合の通知(Path MTU Discoveryに関連)、エコー要求/応答(ping)などに使用されます。
Path MTU Discovery (PMTUD)
Path MTU Discoveryは、送信元から宛先までのネットワークパスにおける最大転送単位 (MTU: Maximum Transmission Unit) を動的に決定するメカニズムです。MTUは、ネットワーク上で一度に送信できる最大パケットサイズを指します。PMTUDは、パケットが途中のルーターでフラグメント化されるのを防ぎ、ネットワークの効率を向上させるために重要です。IPv6では、ルーターによるパケットのフラグメント化がサポートされていないため、PMTUDは特に重要です。PMTUDは、パケットがMTUを超える場合にルーターが送信元に「Packet Too Big」ICMPv6メッセージを送信することで機能します。
RFC 3493: IPv6 Advanced Sockets API for IPv6
このRFCは、IPv6ソケットプログラミングのための高度なAPIを定義しています。これには、IPv6アドレスのバインディング、マルチキャスト、ユニキャスト、およびその他のIPv6固有の機能に関するソケットオプションが含まれます。
RFC 3542: Advanced Sockets Application Program Interface (API) for IPv6
このRFCは、RFC 3493を補完し、IPv6ソケットAPIのさらなる詳細と拡張を提供します。特に、IPv6のヘッダーオプションや宛先オプションの処理、そしてICMPv6メッセージのフィルタリングに関する機能が記述されています。
技術的詳細
このコミットは、Go言語の syscall
パッケージにおいて、以下の主要なIPv6ソケットオプションと関連するデータ構造を追加しています。
-
IPv6MTUInfo
構造体と関連するGetsockoptIPv6MTUInfo
関数:IPv6MTUInfo
は、IPv6のPath MTU Discovery (PMTUD) によって得られたMTU情報を含む構造体です。これには、宛先アドレスと、そのパスのMTU値が含まれます。GetsockoptIPv6MTUInfo
関数は、ソケットからIPv6MTUInfo
構造体を取得するためのGo言語のラッパーです。これにより、Goアプリケーションは特定のIPv6パスのMTU情報を動的に取得できるようになります。これは、ネットワークのパフォーマンス最適化や、パケットフラグメンテーションを避けるために重要です。
-
ICMPv6Filter
構造体と関連するGetsockoptICMPv6Filter
,SetsockoptICMPv6Filter
関数:ICMPv6Filter
は、ICMPv6メッセージをフィルタリングするための構造体です。これにより、アプリケーションは特定の種類のICMPv6メッセージのみを受信したり、特定のメッセージをブロックしたりすることができます。これは、セキュリティ目的や、特定のネットワーク診断ツールを実装する際に有用です。GetsockoptICMPv6Filter
はソケットから現在のICMPv6フィルタ設定を取得し、SetsockoptICMPv6Filter
はICMPv6フィルタを設定します。
これらの機能は、Unix系OS(BSD、Linux、Darwin、FreeBSD、NetBSD、OpenBSD)のシステムコールに依存しており、各OSの syscall
パッケージの実装にこれらのオプションが追加されています。具体的には、mkerrors.sh
スクリプトが更新され、新しいソケットオプション定数(ICMPV6_FILTER
など)が生成されるように変更されています。また、各OS固有の types_*.go
ファイルに IPv6MTUInfo
と ICMPv6Filter
のGo言語での型定義が追加され、zerrors_*.go
と ztypes_*.go
ファイルには、これらの定数と型のOSごとの具体的な値やサイズが自動生成されるようになっています。
これにより、Goアプリケーションは、OSの低レベルなIPv6ソケット機能に、よりGoらしい方法でアクセスできるようになります。
コアとなるコードの変更箇所
このコミットで変更された主要なファイルと、その変更の概要は以下の通りです。
-
src/pkg/syscall/mkerrors.sh
:#include <sys/socket.h>
と#include <linux/icmpv6.h>
が追加され、ソケット関連およびICMPv6関連のヘッダーファイルがインクルードされるようになりました。- 定数生成の正規表現に
ICMP6
が追加され、ICMPV6_FILTER
という新しい定数が認識されるようになりました。
-
src/pkg/syscall/syscall_bsd.go
およびsrc/pkg/syscall/syscall_linux.go
:GetsockoptIPv6MTUInfo
関数が追加されました。これは、IPv6MTUInfo
構造体を取得するためのgetsockopt
システムコールのラッパーです。GetsockoptICMPv6Filter
関数が追加されました。これは、ICMPv6Filter
構造体を取得するためのgetsockopt
システムコールのラッパーです。SetsockoptICMPv6Filter
関数が追加されました。これは、ICMPv6Filter
構造体を設定するためのsetsockopt
システムコールのラッパーです。
-
src/pkg/syscall/types_darwin.go
,src/pkg/syscall/types_freebsd.go
,src/pkg/syscall/types_linux.go
,src/pkg/syscall/types_netbsd.go
,src/pkg/syscall/types_openbsd.go
:- 各OSの
types_*.go
ファイルに、#include <netinet/icmp6.h>
または#include <linux/icmpv6.h>
が追加されました。 IPv6MTUInfo
とICMPv6Filter
という新しいGoの型が定義されました。これらは、C言語の対応する構造体 (C.struct_ip6_mtuinfo
,C.struct_icmp6_filter
) にマッピングされます。- これらの新しい型のサイズ (
SizeofIPv6MTUInfo
,SizeofICMPv6Filter
) が定数として追加されました。
- 各OSの
-
src/pkg/syscall/zerrors_*.go
(各OSおよびアーキテクチャごと):ICMP6_FILTER
またはICMPV6_FILTER
という定数が追加され、その値が定義されました。これは、ICMPv6フィルタリングソケットオプションの識別子です。
-
src/pkg/syscall/ztypes_*.go
(各OSおよびアーキテクチャごと):IPv6MTUInfo
とICMPv6Filter
のGo言語での構造体定義が追加されました。これには、C言語の構造体に対応するフィールドと、そのサイズが記述されています。
コアとなるコードの解説
syscall_bsd.go
および syscall_linux.go
における GetsockoptIPv6MTUInfo
の追加
func GetsockoptIPv6MTUInfo(fd, level, opt int) (*IPv6MTUInfo, error) {
var value IPv6MTUInfo
vallen := _Socklen(SizeofIPv6MTUInfo)
err := getsockopt(fd, level, opt, uintptr(unsafe.Pointer(&value)), &vallen)
return &value, err
}
この関数は、指定されたファイルディスクリプタ fd
、ソケットレベル level
、およびソケットオプション opt
を使用して、IPv6のMTU情報を取得します。
var value IPv6MTUInfo
:IPv6MTUInfo
型の変数を宣言し、取得したMTU情報を格納します。vallen := _Socklen(SizeofIPv6MTUInfo)
:IPv6MTUInfo
構造体のサイズを_Socklen
型にキャストしてvallen
に設定します。これはgetsockopt
システムコールに渡すバッファのサイズを示します。err := getsockopt(fd, level, opt, uintptr(unsafe.Pointer(&value)), &vallen)
: 実際のgetsockopt
システムコールを呼び出します。unsafe.Pointer(&value)
は、Goの構造体のアドレスをC言語のポインタに変換するために使用されます。return &value, err
: 取得したIPv6MTUInfo
構造体へのポインタと、発生したエラーを返します。
syscall_bsd.go
および syscall_linux.go
における GetsockoptICMPv6Filter
および SetsockoptICMPv6Filter
の追加
func GetsockoptICMPv6Filter(fd, level, opt int) (*ICMPv6Filter, error) {
var value ICMPv6Filter
vallen := _Socklen(SizeofICMPv6Filter)
err := getsockopt(fd, level, opt, uintptr(unsafe.Pointer(&value)), &vallen)
return &value, err
}
func SetsockoptICMPv6Filter(fd, level, opt int, filter *ICMPv6Filter) error {
return setsockopt(fd, level, opt, uintptr(unsafe.Pointer(filter)), SizeofICMPv6Filter)
}
これらの関数は、ICMPv6フィルタリングの設定と取得を行います。
GetsockoptICMPv6Filter
はGetsockoptIPv6MTUInfo
と同様に、ICMPv6Filter
構造体を取得します。SetsockoptICMPv6Filter
は、filter
引数で渡されたICMPv6Filter
構造体を使用して、ソケットのICMPv6フィルタを設定します。setsockopt
システムコールを呼び出し、filter
の内容をカーネルに渡します。
types_*.go
における型定義の追加
type IPv6MTUInfo C.struct_ip6_mtuinfo
type ICMPv6Filter C.struct_icmp6_filter
これらの行は、Go言語の syscall
パッケージ内で、C言語の構造体 struct ip6_mtuinfo
と struct icmp6_filter
に対応するGoの型を定義しています。これにより、GoプログラムはこれらのC言語の構造体を直接扱うかのように、型安全な方法でアクセスできるようになります。
zerrors_*.go
および ztypes_*.go
における自動生成された定数と型の追加
これらのファイルは、mkerrors.sh
スクリプトによって自動生成されます。例えば、zerrors_darwin_386.go
には以下のような行が追加されます。
const (
// ...
ICMP6_FILTER = 0x12
// ...
)
これは、Darwin (macOS) の32ビットシステムにおける ICMP6_FILTER
ソケットオプションの定数値が 0x12
であることを示しています。同様に、ztypes_darwin_386.go
には、IPv6MTUInfo
や ICMPv6Filter
のGo言語での具体的な構造体レイアウトとサイズが定義されます。これらの自動生成されたファイルは、Goの syscall
パッケージが異なるOSやアーキテクチャ間で移植性を保ちつつ、低レベルなシステムコールインターフェースを提供するために不可欠です。
関連リンク
- Go Issue #5538: https://github.com/golang/go/issues/5538 (このコミットが解決した可能性のあるGoのIssue)
- Go Change List 9373046: https://golang.org/cl/9373046 (このコミットに対応するGoのコードレビューシステム上の変更リスト)
参考にした情報源リンク
- RFC 3493: IPv6 Advanced Sockets API for IPv6: https://datatracker.ietf.org/doc/html/rfc3493
- RFC 3542: Advanced Sockets Application Program Interface (API) for IPv6: https://datatracker.ietf.org/doc/html/rfc3542
- Linux man pages - ip(7): https://man7.org/linux/man-pages/man7/ip.7.html (LinuxにおけるIPv6ソケットオプションに関する情報)
- FreeBSD man pages - ip6(4): https://www.freebsd.org/cgi/man.cgi?query=ip6&sektion=4 (FreeBSDにおけるIPv6ソケットオプションに関する情報)
- Go
syscall
package documentation: https://pkg.go.dev/syscall (Go言語のsyscall
パッケージの公式ドキュメント)