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

[インデックス 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ソケットオプションと関連するデータ構造を追加しています。

  1. IPv6MTUInfo 構造体と関連する GetsockoptIPv6MTUInfo 関数:

    • IPv6MTUInfo は、IPv6のPath MTU Discovery (PMTUD) によって得られたMTU情報を含む構造体です。これには、宛先アドレスと、そのパスのMTU値が含まれます。
    • GetsockoptIPv6MTUInfo 関数は、ソケットから IPv6MTUInfo 構造体を取得するためのGo言語のラッパーです。これにより、Goアプリケーションは特定のIPv6パスのMTU情報を動的に取得できるようになります。これは、ネットワークのパフォーマンス最適化や、パケットフラグメンテーションを避けるために重要です。
  2. 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 ファイルに IPv6MTUInfoICMPv6Filter のGo言語での型定義が追加され、zerrors_*.goztypes_*.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> が追加されました。
    • IPv6MTUInfoICMPv6Filter という新しいGoの型が定義されました。これらは、C言語の対応する構造体 (C.struct_ip6_mtuinfo, C.struct_icmp6_filter) にマッピングされます。
    • これらの新しい型のサイズ (SizeofIPv6MTUInfo, SizeofICMPv6Filter) が定数として追加されました。
  • src/pkg/syscall/zerrors_*.go (各OSおよびアーキテクチャごと):

    • ICMP6_FILTER または ICMPV6_FILTER という定数が追加され、その値が定義されました。これは、ICMPv6フィルタリングソケットオプションの識別子です。
  • src/pkg/syscall/ztypes_*.go (各OSおよびアーキテクチャごと):

    • IPv6MTUInfoICMPv6Filter の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フィルタリングの設定と取得を行います。

  • GetsockoptICMPv6FilterGetsockoptIPv6MTUInfo と同様に、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_mtuinfostruct 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 には、IPv6MTUInfoICMPv6Filter のGo言語での具体的な構造体レイアウトとサイズが定義されます。これらの自動生成されたファイルは、Goの syscall パッケージが異なるOSやアーキテクチャ間で移植性を保ちつつ、低レベルなシステムコールインターフェースを提供するために不可欠です。

関連リンク

参考にした情報源リンク