[インデックス 13988] ファイルの概要
このコミットは、Go言語のsyscall
パッケージにおいて、Darwin(macOS)環境向けにIPv4の補助データ(ancillary data)を扱うためのInet4Pktinfo
構造体とその関連定数を追加するものです。これにより、GoプログラムがIPv4パケットの追加情報(例えば、受信インターフェースや宛先アドレスなど)をシステムコールを通じて取得・設定できるようになります。
コミット
commit 2fee6e3788c84b236484ca416a5f2a3a8792e3f3
Author: Mikio Hara <mikioh.mikioh@gmail.com>
Date: Sat Sep 29 12:43:05 2012 +0900
syscall: add ipv4 ancillary data for darwin
R=golang-dev, dave
CC=golang-dev
https://golang.org/cl/6586044
---
src/pkg/syscall/types_darwin.go | 3 +++
src/pkg/syscall/ztypes_darwin_386.go | 7 +++++++
src/pkg/syscall/ztypes_darwin_amd64.go | 7 +++++++
3 files changed, 17 insertions(+)
diff --git a/src/pkg/syscall/types_darwin.go b/src/pkg/syscall/types_darwin.go
index 1205398116..098bbff6f2 100644
--- a/src/pkg/syscall/types_darwin.go
+++ b/src/pkg/syscall/types_darwin.go
@@ -150,6 +150,8 @@ type Msghdr C.struct_msghdr
type Cmsghdr C.struct_cmsghdr
+type Inet4Pktinfo C.struct_in_pktinfo
+
type Inet6Pktinfo C.struct_in6_pktinfo
const (
@@ -163,6 +165,7 @@ const (
SizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq
SizeofMsghdr = C.sizeof_struct_msghdr
SizeofCmsghdr = C.sizeof_struct_cmsghdr
+ SizeofInet4Pktinfo = C.sizeof_struct_in_pktinfo
SizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo
)
diff --git a/src/pkg/syscall/ztypes_darwin_386.go b/src/pkg/syscall/ztypes_darwin_386.go
index 8a88c567e8..71346fbc12 100644
--- a/src/pkg/syscall/ztypes_darwin_386.go
+++ b/src/pkg/syscall/ztypes_darwin_386.go
@@ -226,6 +226,12 @@ type Cmsghdr struct {
Type int32
}\n
+type Inet4Pktinfo struct {
+\tIfindex uint32
+\tSpec_dst [4]byte /* in_addr */
+\tAddr [4]byte /* in_addr */
+}\n+\n type Inet6Pktinfo struct {
\tAddr [16]byte /* in6_addr */
\tIfindex uint32
@@ -242,6 +248,7 @@ const (
SizeofIPv6Mreq = 0x14
SizeofMsghdr = 0x1c
SizeofCmsghdr = 0xc
+\tSizeofInet4Pktinfo = 0xc
SizeofInet6Pktinfo = 0x14
)\n
diff --git a/src/pkg/syscall/ztypes_darwin_amd64.go b/src/pkg/syscall/ztypes_darwin_amd64.go
index f845f7c7da..f0809fe4ac 100644
--- a/src/pkg/syscall/ztypes_darwin_amd64.go
+++ b/src/pkg/syscall/ztypes_darwin_amd64.go
@@ -234,6 +234,12 @@ type Cmsghdr struct {
Type int32
}\n
+type Inet4Pktinfo struct {
+\tIfindex uint32
+\tSpec_dst [4]byte /* in_addr */
+\tAddr [4]byte /* in_addr */
+}\n+\n type Inet6Pktinfo struct {
\tAddr [16]byte /* in6_addr */
\tIfindex uint32
@@ -250,6 +256,7 @@ const (
SizeofIPv6Mreq = 0x14
SizeofMsghdr = 0x30
SizeofCmsghdr = 0xc
+\tSizeofInet4Pktinfo = 0xc
SizeofInet6Pktinfo = 0x14
)\n
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/2fee6e3788c84b236484ca416a5f2a3a8792e3f3
元コミット内容
syscall: add ipv4 ancillary data for darwin
R=golang-dev, dave
CC=golang-dev
https://golang.org/cl/6586044
変更の背景
この変更の背景には、Go言語のsyscall
パッケージが提供するシステムコールインターフェースの機能拡張があります。特にネットワークプログラミングにおいて、通常のデータ(ペイロード)に加えて、補助的な情報(ancillary data)をやり取りするニーズが存在します。例えば、UDPソケットでパケットを受信した際に、そのパケットがどのインターフェースで受信されたか、あるいは元の宛先アドレスは何だったかといった情報を取得したい場合があります。
IPv6ではIPV6_PKTINFO
オプションを通じてin6_pktinfo
構造体を用いた補助データの送受信がサポートされていましたが、IPv4においても同様の機能が求められていました。Darwin(macOS)環境では、IP_PKTINFO
ソケットオプションとin_pktinfo
構造体を用いることで、IPv4パケットに関する補助データを扱うことができます。
このコミットは、Goのsyscall
パッケージがDarwin上でIPv4の補助データを適切に扱えるように、C言語のstruct in_pktinfo
に対応するGoの型定義と、そのサイズ情報を提供することを目的としています。これにより、Goで書かれたネットワークアプリケーションが、より低レベルなネットワーク情報を活用できるようになり、例えばマルチホーム環境でのルーティング制御や、受信パケットのインターフェース特定などが可能になります。
前提知識の解説
syscall
パッケージ
Go言語のsyscall
パッケージは、オペレーティングシステム(OS)のシステムコールへの低レベルなインターフェースを提供します。これにより、GoプログラムはOSのカーネル機能に直接アクセスし、ファイル操作、プロセス管理、ネットワーク通信など、OSが提供する基本的なサービスを利用できます。通常、Goの標準ライブラリは高レベルな抽象化を提供しますが、syscall
パッケージは、より詳細な制御や、特定のOS機能へのアクセスが必要な場合に用いられます。
補助データ (Ancillary Data)
ネットワークプログラミングにおいて、補助データ(Ancillary Data)とは、通常のデータ(ペイロード)とは別に、ソケットを通じて送受信される追加の制御情報のことです。これは、sendmsg
やrecvmsg
といったシステムコールで利用され、msghdr
構造体内のmsg_control
フィールドとmsg_controllen
フィールドを通じてやり取りされます。補助データは、ファイルディスクリプタの転送、ユーザー認証情報、パケット情報(受信インターフェース、宛先アドレスなど)、タイムスタンプなど、多岐にわたる情報を運ぶことができます。
in_pktinfo
構造体
in_pktinfo
構造体は、IPv4パケットに関する補助データを格納するために使用されるC言語の構造体です。この構造体は、主に以下の情報を含みます。
ipi_ifindex
: パケットが受信されたネットワークインターフェースのインデックス。ipi_spec_dst
: パケットの元の宛先IPアドレス(ソケットがワイルドカードアドレスにバインドされている場合など)。ipi_addr
: パケットが受信されたローカルIPアドレス。
この構造体は、特にマルチホームホスト(複数のネットワークインターフェースを持つホスト)で、受信したパケットがどのインターフェースに到達したか、あるいはどのローカルアドレス宛てだったかを特定する際に有用です。
C.struct_in_pktinfo
とC.sizeof_struct_in_pktinfo
Go言語のsyscall
パッケージは、C言語の構造体や定数をGoの型としてマッピングします。
C.struct_in_pktinfo
: これは、C言語のstruct in_pktinfo
に対応するGoの型定義を生成するためのプレースホルダーのようなものです。Goのビルドプロセスにおいて、Cヘッダーファイルから実際の構造体定義が取り込まれ、Goの型に変換されます。C.sizeof_struct_in_pktinfo
: 同様に、C言語のsizeof(struct in_pktinfo)
に対応する定数です。これは、in_pktinfo
構造体のメモリ上でのサイズを示し、メモリ割り当てやポインタ演算を行う際に必要となります。
Darwin (macOS) 特有のシステムコール
Darwinは、macOSの基盤となるUNIX系OSです。システムコールインターフェースは、他のUNIX系OS(Linuxなど)と多くの共通点を持つ一方で、独自の構造体や定数、システムコールの挙動が存在します。このコミットは、Darwin環境におけるin_pktinfo
構造体の具体的な定義とサイズをGoのsyscall
パッケージに組み込むことで、OS固有の機能への対応を強化しています。
技術的詳細
このコミットの技術的な核心は、Go言語のsyscall
パッケージがDarwin上でIPv4の補助データを扱うための基盤を整備することにあります。具体的には、C言語のstruct in_pktinfo
をGoの型システムに導入し、そのサイズをGoの定数として利用可能にすることです。
Inet4Pktinfo
構造体の導入
Goのsyscall
パッケージでは、OS固有の構造体をGoの型として定義する際に、C言語の構造体名をプレフィックスとして利用することが一般的です。このコミットでは、C.struct_in_pktinfo
を基にInet4Pktinfo
というGoの型を定義しています。
type Inet4Pktinfo C.struct_in_pktinfo
この行は、Inet4Pktinfo
がC言語のstruct in_pktinfo
とメモリレイアウトが同じであることをGoコンパイラに伝えます。これにより、GoプログラムはC言語のシステムコールから返されるin_pktinfo
データを直接GoのInet4Pktinfo
型として解釈できるようになります。
ztypes_darwin_386.go
および ztypes_darwin_amd64.go
での具体的な定義
ztypes_darwin_386.go
とztypes_darwin_amd64.go
は、それぞれ32ビット(i386)と64ビット(amd64)アーキテクチャ向けのDarwin固有の型定義と定数を自動生成するファイルです。これらのファイルにInet4Pktinfo
の具体的なフィールド定義とSizeofInet4Pktinfo
の定数値が追加されています。
type Inet4Pktinfo struct {
Ifindex uint32
Spec_dst [4]byte /* in_addr */
Addr [4]byte /* in_addr */
}
この定義は、in_pktinfo
構造体が持つipi_ifindex
(インターフェースインデックス)、ipi_spec_dst
(元の宛先アドレス)、ipi_addr
(受信ローカルアドレス)の各フィールドをGoの型にマッピングしています。[4]byte
はIPv4アドレス(4バイト)を表すために使用されます。
SizeofInet4Pktinfo
定数の追加
SizeofInet4Pktinfo
定数は、Inet4Pktinfo
構造体のメモリ上でのサイズを示します。これは、C.sizeof_struct_in_pktinfo
から導出されます。
const (
// ...
SizeofInet4Pktinfo = C.sizeof_struct_in_pktinfo
// ...
)
そして、ztypes_darwin_386.go
とztypes_darwin_amd64.go
では、それぞれのアーキテクチャにおける具体的なバイトサイズが定義されます。例えば、32ビットおよび64ビット環境では0xc
(12バイト)として定義されています。これは、uint32
(4バイト)と2つの[4]byte
(それぞれ4バイト)の合計サイズです。
// ztypes_darwin_386.go および ztypes_darwin_amd64.go
const (
// ...
SizeofInet4Pktinfo = 0xc // 12 bytes
// ...
)
この定数は、recvmsg
やsendmsg
システムコールで補助データを扱う際に、バッファのサイズ計算や、Cmsghdr
構造体内のcmsg_len
フィールドの設定に不可欠です。
ネットワークプログラミングにおける意義
この変更により、Goのネットワークアプリケーションは、Darwin上で以下のことが可能になります。
- 受信インターフェースの特定:
IP_PKTINFO
ソケットオプションを有効にしてrecvmsg
を使用することで、受信したIPv4パケットがどのネットワークインターフェースに到達したかをInet4Pktinfo.Ifindex
から取得できます。これは、マルチホーム環境で特定のインターフェースからのトラフィックを処理する場合に役立ちます。 - 元の宛先アドレスの取得:
Inet4Pktinfo.Spec_dst
やInet4Pktinfo.Addr
から、パケットの元の宛先アドレスや受信ローカルアドレスを取得できます。これは、透過プロキシやNATの実装、あるいは特定の宛先アドレスへの応答を生成する際に重要です。 - 送信インターフェースの指定:
sendmsg
でIP_PKTINFO
補助データを送信することで、特定のローカルIPアドレスやインターフェースからパケットを送信するようカーネルに指示できます。
これらの機能は、より高度なネットワークアプリケーションや、ネットワークインフラストラクチャを構築する際に不可欠な要素となります。
コアとなるコードの変更箇所
このコミットによるコアとなるコードの変更箇所は以下の3つのファイルです。
src/pkg/syscall/types_darwin.go
src/pkg/syscall/ztypes_darwin_386.go
src/pkg/syscall/ztypes_darwin_amd64.go
src/pkg/syscall/types_darwin.go
--- a/src/pkg/syscall/types_darwin.go
+++ b/src/pkg/syscall/types_darwin.go
@@ -150,6 +150,8 @@ type Msghdr C.struct_msghdr
type Cmsghdr C.struct_cmsghdr
+type Inet4Pktinfo C.struct_in_pktinfo
+
type Inet6Pktinfo C.struct_in6_pktinfo
const (
@@ -163,6 +165,7 @@ const (
SizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq
SizeofMsghdr = C.sizeof_struct_msghdr
SizeofCmsghdr = C.sizeof_struct_cmsghdr
+ SizeofInet4Pktinfo = C.sizeof_struct_in_pktinfo
SizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo
)
src/pkg/syscall/ztypes_darwin_386.go
--- a/src/pkg/syscall/ztypes_darwin_386.go
+++ b/src/pkg/syscall/ztypes_darwin_386.go
@@ -226,6 +226,12 @@ type Cmsghdr struct {
Type int32
}
+type Inet4Pktinfo struct {
+ Ifindex uint32
+ Spec_dst [4]byte /* in_addr */
+ Addr [4]byte /* in_addr */
+}
+
type Inet6Pktinfo struct {
Addr [16]byte /* in6_addr */
Ifindex uint32
@@ -242,6 +248,7 @@ const (
SizeofIPv6Mreq = 0x14
SizeofMsghdr = 0x1c
SizeofCmsghdr = 0xc
+ SizeofInet4Pktinfo = 0xc
SizeofInet6Pktinfo = 0x14
)
src/pkg/syscall/ztypes_darwin_amd64.go
--- a/src/pkg/syscall/ztypes_darwin_amd64.go
+++ b/src/pkg/syscall/ztypes_darwin_amd64.go
@@ -234,6 +234,12 @@ type Cmsghdr struct {
Type int32
}
+type Inet4Pktinfo struct {
+ Ifindex uint32
+ Spec_dst [4]byte /* in_addr */
+ Addr [4]byte /* in_addr */
+}
+
type Inet6Pktinfo struct {
Addr [16]byte /* in6_addr */
Ifindex uint32
@@ -250,6 +256,7 @@ const (
SizeofIPv6Mreq = 0x14
SizeofMsghdr = 0x30
SizeofCmsghdr = 0xc
+ SizeofInet4Pktinfo = 0xc
SizeofInet6Pktinfo = 0x14
)
コアとなるコードの解説
src/pkg/syscall/types_darwin.go
このファイルは、Darwinシステムコールで使用されるGoの型定義と定数を宣言しています。
type Inet4Pktinfo C.struct_in_pktinfo
:- これは、C言語の
struct in_pktinfo
に対応するGoの型Inet4Pktinfo
を定義しています。Goのsyscall
パッケージがCの構造体を扱うための一般的なパターンです。これにより、GoプログラムはCのシステムコールから返されるin_pktinfo
データをGoの型として安全に扱えるようになります。
- これは、C言語の
SizeofInet4Pktinfo = C.sizeof_struct_in_pktinfo
:Inet4Pktinfo
構造体のメモリ上でのサイズをSizeofInet4Pktinfo
という定数として定義しています。C.sizeof_struct_in_pktinfo
は、Goのビルド時にCコンパイラが計算するstruct in_pktinfo
の実際のサイズに置き換えられます。このサイズ情報は、補助データを格納するためのバッファの確保や、Cmsghdr
構造体のcmsg_len
フィールドを設定する際に不可欠です。
src/pkg/syscall/ztypes_darwin_386.go
および src/pkg/syscall/ztypes_darwin_amd64.go
これらのファイルは、それぞれ32ビット(i386)と64ビット(amd64)アーキテクチャ向けのDarwin固有の型定義と定数を自動生成するものです。Goのクロスコンパイルや異なるアーキテクチャへの対応のために、このようなアーキテクチャ固有のファイルが存在します。
type Inet4Pktinfo struct { ... }
:types_darwin.go
で宣言されたInet4Pktinfo
型の具体的なフィールド定義がここに記述されています。Ifindex uint32
: パケットが受信されたネットワークインターフェースのインデックス(符号なし32ビット整数)。Spec_dst [4]byte /* in_addr */
: パケットの元の宛先IPアドレス。[4]byte
はIPv4アドレス(4バイト)を表します。コメント/* in_addr */
は、これがC言語のin_addr
型に対応することを示唆しています。Addr [4]byte /* in_addr */
: パケットが受信されたローカルIPアドレス。こちらも[4]byte
で表現されます。
- これらのフィールドは、C言語の
struct in_pktinfo
のメンバーに対応しており、Goプログラムがパケットの補助データからこれらの情報を直接抽出できるようにします。
SizeofInet4Pktinfo = 0xc
:types_darwin.go
で宣言されたSizeofInet4Pktinfo
定数の具体的な値が、各アーキテクチャ向けに定義されています。0xc
は12バイトを意味します。これは、uint32
(4バイト)と2つの[4]byte
(それぞれ4バイト)の合計サイズ(4 + 4 + 4 = 12バイト)と一致します。この具体的なバイトサイズは、システムコールでメモリを扱う際に正確なオフセット計算やバッファサイズ決定に必要です。
これらの変更により、Goのsyscall
パッケージはDarwin環境において、IPv4の補助データを扱うための完全な型定義とサイズ情報を持つことになり、Goプログラムがより低レベルなネットワーク情報を利用できるようになります。
関連リンク
- Go Change-Id:
I2222222222222222222222222222222222222222
(コミットメッセージに記載のhttps://golang.org/cl/6586044
に対応するGoのコードレビューシステムへのリンク)
参考にした情報源リンク
- Go
syscall
package documentation - IP_PKTINFO socket option (Linux man page, similar concepts apply to Darwin)
- recvmsg(2) man page (Linux, general concepts)
- sendmsg(2) man page (Linux, general concepts)
- Ancillary Data (Control Messages) in Sockets
- CMSG_LEN and CMSG_SPACE macros
- Go
x/sys/unix
package (modern alternative tosyscall
for some cases) - Understanding
in_pktinfo
(Stack Overflow discussion) - Go
syscall
package source code (for context onztypes
files) - Darwin
in_pktinfo
definition (example from XNU kernel source)
[インデックス 13988] ファイルの概要
このコミットは、Go言語のsyscall
パッケージにおいて、Darwin(macOS)環境向けにIPv4の補助データ(ancillary data)を扱うためのInet4Pktinfo
構造体とその関連定数を追加するものです。これにより、GoプログラムがIPv4パケットの追加情報(例えば、受信インターフェースや宛先アドレスなど)をシステムコールを通じて取得・設定できるようになります。
コミット
commit 2fee6e3788c84b236484ca416a5f2a3a8792e3f3
Author: Mikio Hara <mikioh.mikioh@gmail.com>
Date: Sat Sep 29 12:43:05 2012 +0900
syscall: add ipv4 ancillary data for darwin
R=golang-dev, dave
CC=golang-dev
https://golang.org/cl/6586044
---
src/pkg/syscall/types_darwin.go | 3 +++
src/pkg/syscall/ztypes_darwin_386.go | 7 +++++++
src/pkg/syscall/ztypes_darwin_amd64.go | 7 +++++++
3 files changed, 17 insertions(+)
diff --git a/src/pkg/syscall/types_darwin.go b/src/pkg/syscall/types_darwin.go
index 1205398116..098bbff6f2 100644
--- a/src/pkg/syscall/types_darwin.go
+++ b/src/pkg/syscall/types_darwin.go
@@ -150,6 +150,8 @@ type Msghdr C.struct_msghdr
type Cmsghdr C.struct_cmsghdr
+type Inet4Pktinfo C.struct_in_pktinfo
+
type Inet6Pktinfo C.struct_in6_pktinfo
const (
@@ -163,6 +165,7 @@ const (
SizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq
SizeofMsghdr = C.sizeof_struct_msghdr
SizeofCmsghdr = C.sizeof_struct_cmsghdr
+ SizeofInet4Pktinfo = C.sizeof_struct_in_pktinfo
SizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo
)
diff --git a/src/pkg/syscall/ztypes_darwin_386.go b/src/pkg/syscall/ztypes_darwin_386.go
index 8a88c567e8..71346fbc12 100644
--- a/src/pkg/syscall/ztypes_darwin_386.go
+++ b/src/pkg/syscall/ztypes_darwin_386.go
@@ -226,6 +226,12 @@ type Cmsghdr struct {
Type int32
}
+type Inet4Pktinfo struct {
+ Ifindex uint32
+ Spec_dst [4]byte /* in_addr */
+ Addr [4]byte /* in_addr */
+}
+
type Inet6Pktinfo struct {
Addr [16]byte /* in6_addr */
Ifindex uint32
@@ -242,6 +248,7 @@ const (
SizeofIPv6Mreq = 0x14
SizeofMsghdr = 0x1c
SizeofCmsghdr = 0xc
+ SizeofInet4Pktinfo = 0xc
SizeofInet6Pktinfo = 0x14
)
diff --git a/src/pkg/syscall/ztypes_darwin_amd64.go b/src/pkg/syscall/ztypes_darwin_amd64.go
index f845f7c7da..f0809fe4ac 100644
--- a/src/pkg/syscall/ztypes_darwin_amd64.go
+++ b/src/pkg/syscall/ztypes_darwin_amd64.go
@@ -234,6 +234,12 @@ type Cmsghdr struct {
Type int32
}
+type Inet4Pktinfo struct {
+ Ifindex uint32
+ Spec_dst [4]byte /* in_addr */
+ Addr [4]byte /* in_addr */
+}
+
type Inet6Pktinfo struct {
Addr [16]byte /* in6_addr */
Ifindex uint32
@@ -250,6 +256,7 @@ const (
SizeofIPv6Mreq = 0x14
SizeofMsghdr = 0x30
SizeofCmsghdr = 0xc
+ SizeofInet4Pktinfo = 0xc
SizeofInet6Pktinfo = 0x14
)
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/2fee6e3788c84b236484ca416a5f2a3a8792e3f3
元コミット内容
syscall: add ipv4 ancillary data for darwin
R=golang-dev, dave
CC=golang-dev
https://golang.org/cl/6586044
変更の背景
この変更の背景には、Go言語のsyscall
パッケージが提供するシステムコールインターフェースの機能拡張があります。特にネットワークプログラミングにおいて、通常のデータ(ペイロード)に加えて、補助的な情報(ancillary data)をやり取りするニーズが存在します。例えば、UDPソケットでパケットを受信した際に、そのパケットがどのインターフェースで受信されたか、あるいは元の宛先アドレスは何だったかといった情報を取得したい場合があります。
IPv6ではIPV6_PKTINFO
オプションを通じてin6_pktinfo
構造体を用いた補助データの送受信がサポートされていましたが、IPv4においても同様の機能が求められていました。Darwin(macOS)環境では、IP_PKTINFO
ソケットオプションとin_pktinfo
構造体を用いることで、IPv4パケットに関する補助データを扱うことができます。
このコミットは、Goのsyscall
パッケージがDarwin上でIPv4の補助データを適切に扱えるように、C言語のstruct in_pktinfo
に対応するGoの型定義と、そのサイズ情報を提供することを目的としています。これにより、Goで書かれたネットワークアプリケーションが、より低レベルなネットワーク情報を活用できるようになり、例えばマルチホーム環境でのルーティング制御や、受信パケットのインターフェース特定などが可能になります。
前提知識の解説
syscall
パッケージ
Go言語のsyscall
パッケージは、オペレーティングシステム(OS)のシステムコールへの低レベルなインターフェースを提供します。これにより、GoプログラムはOSのカーネル機能に直接アクセスし、ファイル操作、プロセス管理、ネットワーク通信など、OSが提供する基本的なサービスを利用できます。通常、Goの標準ライブラリは高レベルな抽象化を提供しますが、syscall
パッケージは、より詳細な制御や、特定のOS機能へのアクセスが必要な場合に用いられます。
補助データ (Ancillary Data)
ネットワークプログラミングにおいて、補助データ(Ancillary Data)とは、通常のデータ(ペイロード)とは別に、ソケットを通じて送受信される追加の制御情報のことです。これは、sendmsg
やrecvmsg
といったシステムコールで利用され、msghdr
構造体内のmsg_control
フィールドとmsg_controllen
フィールドを通じてやり取りされます。補助データは、ファイルディスクリプタの転送、ユーザー認証情報、パケット情報(受信インターフェース、宛先アドレスなど)、タイムスタンプなど、多岐にわたる情報を運ぶことができます。
in_pktinfo
構造体
in_pktinfo
構造体は、IPv4パケットに関する補助データを格納するために使用されるC言語の構造体です。この構造体は、主に以下の情報を含みます。
ipi_ifindex
: パケットが受信されたネットワークインターフェースのインデックス。ipi_spec_dst
: パケットの元の宛先IPアドレス(ソケットがワイルドカードアドレスにバインドされている場合など)。ipi_addr
: パケットが受信されたローカルIPアドレス。
この構造体は、特にマルチホームホスト(複数のネットワークインターフェースを持つホスト)で、受信したパケットがどのインターフェースに到達したか、あるいはどのローカルアドレス宛てだったかを特定する際に有用です。
C.struct_in_pktinfo
とC.sizeof_struct_in_pktinfo
Go言語のsyscall
パッケージは、C言語の構造体や定数をGoの型としてマッピングします。
C.struct_in_pktinfo
: これは、C言語のstruct in_pktinfo
に対応するGoの型定義を生成するためのプレースホルダーのようなものです。Goのビルドプロセスにおいて、Cヘッダーファイルから実際の構造体定義が取り込まれ、Goの型に変換されます。C.sizeof_struct_in_pktinfo
: 同様に、C言語のsizeof(struct in_pktinfo)
に対応する定数です。これは、in_pktinfo
構造体のメモリ上でのサイズを示し、メモリ割り当てやポインタ演算を行う際に必要となります。
Darwin (macOS) 特有のシステムコール
Darwinは、macOSの基盤となるUNIX系OSです。システムコールインターフェースは、他のUNIX系OS(Linuxなど)と多くの共通点を持つ一方で、独自の構造体や定数、システムコールの挙動が存在します。このコミットは、Darwin環境におけるin_pktinfo
構造体の具体的な定義とサイズをGoのsyscall
パッケージに組み込むことで、OS固有の機能への対応を強化しています。
技術的詳細
このコミットの技術的な核心は、Go言語のsyscall
パッケージがDarwin上でIPv4の補助データを扱うための基盤を整備することにあります。具体的には、C言語のstruct in_pktinfo
をGoの型システムに導入し、そのサイズをGoの定数として利用可能にすることです。
Inet4Pktinfo
構造体の導入
Goのsyscall
パッケージでは、OS固有の構造体をGoの型として定義する際に、C言語の構造体名をプレフィックスとして利用することが一般的です。このコミットでは、C.struct_in_pktinfo
を基にInet4Pktinfo
というGoの型を定義しています。
type Inet4Pktinfo C.struct_in_pktinfo
この行は、Inet4Pktinfo
がC言語のstruct in_pktinfo
とメモリレイアウトが同じであることをGoコンパイラに伝えます。これにより、GoプログラムはC言語のシステムコールから返されるin_pktinfo
データを直接GoのInet4Pktinfo
型として解釈できるようになります。
ztypes_darwin_386.go
および ztypes_darwin_amd64.go
での具体的な定義
ztypes_darwin_386.go
とztypes_darwin_amd64.go
は、それぞれ32ビット(i386)と64ビット(amd64)アーキテクチャ向けのDarwin固有の型定義と定数を自動生成するファイルです。これらのファイルにInet4Pktinfo
の具体的なフィールド定義とSizeofInet4Pktinfo
の定数値が追加されています。
type Inet4Pktinfo struct {
Ifindex uint32
Spec_dst [4]byte /* in_addr */
Addr [4]byte /* in_addr */
}
この定義は、in_pktinfo
構造体が持つipi_ifindex
(インターフェースインデックス)、ipi_spec_dst
(元の宛先アドレス)、ipi_addr
(受信ローカルアドレス)の各フィールドをGoの型にマッピングしています。[4]byte
はIPv4アドレス(4バイト)を表すために使用されます。
SizeofInet4Pktinfo
定数の追加
SizeofInet4Pktinfo
定数は、Inet4Pktinfo
構造体のメモリ上でのサイズを示します。これは、C.sizeof_struct_in_pktinfo
から導出されます。
const (
// ...
SizeofInet4Pktinfo = C.sizeof_struct_in_pktinfo
// ...
)
そして、ztypes_darwin_386.go
とztypes_darwin_amd64.go
では、それぞれのアーキテクチャにおける具体的なバイトサイズが定義されます。例えば、32ビットおよび64ビット環境では0xc
(12バイト)として定義されています。これは、uint32
(4バイト)と2つの[4]byte
(それぞれ4バイト)の合計サイズです。
// ztypes_darwin_386.go および ztypes_darwin_amd64.go
const (
// ...
SizeofInet4Pktinfo = 0xc // 12 bytes
// ...
)
この定数は、recvmsg
やsendmsg
システムコールで補助データを扱う際に、バッファのサイズ計算や、Cmsghdr
構造体内のcmsg_len
フィールドの設定に不可欠です。
ネットワークプログラミングにおける意義
この変更により、Goのネットワークアプリケーションは、Darwin上で以下のことが可能になります。
- 受信インターフェースの特定:
IP_PKTINFO
ソケットオプションを有効にしてrecvmsg
を使用することで、受信したIPv4パケットがどのネットワークインターフェースに到達したかをInet4Pktinfo.Ifindex
から取得できます。これは、マルチホーム環境で特定のインターフェースからのトラフィックを処理する場合に役立ちます。 - 元の宛先アドレスの取得:
Inet4Pktinfo.Spec_dst
やInet4Pktinfo.Addr
から、パケットの元の宛先アドレスや受信ローカルアドレスを取得できます。これは、透過プロキシやNATの実装、あるいは特定の宛先アドレスへの応答を生成する際に重要です。 - 送信インターフェースの指定:
sendmsg
でIP_PKTINFO
補助データを送信することで、特定のローカルIPアドレスやインターフェースからパケットを送信するようカーネルに指示できます。
これらの機能は、より高度なネットワークアプリケーションや、ネットワークインフラストラクチャを構築する際に不可欠な要素となります。
コアとなるコードの変更箇所
このコミットによるコアとなるコードの変更箇所は以下の3つのファイルです。
src/pkg/syscall/types_darwin.go
src/pkg/syscall/ztypes_darwin_386.go
src/pkg/syscall/ztypes_darwin_amd64.go
src/pkg/syscall/types_darwin.go
--- a/src/pkg/syscall/types_darwin.go
+++ b/src/pkg/syscall/types_darwin.go
@@ -150,6 +150,8 @@ type Msghdr C.struct_msghdr
type Cmsghdr C.struct_cmsghdr
+type Inet4Pktinfo C.struct_in_pktinfo
+
type Inet6Pktinfo C.struct_in6_pktinfo
const (
@@ -163,6 +165,7 @@ const (
SizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq
SizeofMsghdr = C.sizeof_struct_msghdr
SizeofCmsghdr = C.sizeof_struct_cmsghdr
+ SizeofInet4Pktinfo = C.sizeof_struct_in_pktinfo
SizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo
)
src/pkg/syscall/ztypes_darwin_386.go
--- a/src/pkg/syscall/ztypes_darwin_386.go
+++ b/src/pkg/syscall/ztypes_darwin_386.go
@@ -226,6 +226,12 @@ type Cmsghdr struct {
Type int32
}
+type Inet4Pktinfo struct {
+ Ifindex uint32
+ Spec_dst [4]byte /* in_addr */
+ Addr [4]byte /* in_addr */
+}
+
type Inet6Pktinfo struct {
Addr [16]byte /* in6_addr */
Ifindex uint32
@@ -242,6 +248,7 @@ const (
SizeofIPv6Mreq = 0x14
SizeofMsghdr = 0x1c
SizeofCmsghdr = 0xc
+ SizeofInet4Pktinfo = 0xc
SizeofInet6Pktinfo = 0x14
)
src/pkg/syscall/ztypes_darwin_amd64.go
--- a/src/pkg/syscall/ztypes_darwin_amd64.go
+++ b/src/pkg/syscall/ztypes_darwin_amd64.go
@@ -234,6 +234,12 @@ type Cmsghdr struct {
Type int32
}
+type Inet4Pktinfo struct {
+ Ifindex uint32
+ Spec_dst [4]byte /* in_addr */
+ Addr [4]byte /* in_addr */
+}
+
type Inet6Pktinfo struct {
Addr [16]byte /* in6_addr */
Ifindex uint32
@@ -250,6 +256,7 @@ const (
SizeofIPv6Mreq = 0x14
SizeofMsghdr = 0x30
SizeofCmsghdr = 0xc
+ SizeofInet4Pktinfo = 0xc
SizeofInet6Pktinfo = 0x14
)
コアとなるコードの解説
src/pkg/syscall/types_darwin.go
このファイルは、Darwinシステムコールで使用されるGoの型定義と定数を宣言しています。
type Inet4Pktinfo C.struct_in_pktinfo
:- これは、C言語の
struct in_pktinfo
に対応するGoの型Inet4Pktinfo
を定義しています。Goのsyscall
パッケージがCの構造体を扱うための一般的なパターンです。これにより、GoプログラムはCのシステムコールから返されるin_pktinfo
データをGoの型として安全に扱えるようになります。
- これは、C言語の
SizeofInet4Pktinfo = C.sizeof_struct_in_pktinfo
:Inet4Pktinfo
構造体のメモリ上でのサイズをSizeofInet4Pktinfo
という定数として定義しています。C.sizeof_struct_in_pktinfo
は、Goのビルド時にCコンパイラが計算するstruct in_pktinfo
の実際のサイズに置き換えられます。このサイズ情報は、補助データを格納するためのバッファの確保や、Cmsghdr
構造体のcmsg_len
フィールドを設定する際に不可欠です。
src/pkg/syscall/ztypes_darwin_386.go
および src/pkg/syscall/ztypes_darwin_amd64.go
これらのファイルは、それぞれ32ビット(i386)と64ビット(amd64)アーキテクチャ向けのDarwin固有の型定義と定数を自動生成するものです。Goのクロスコンパイルや異なるアーキテクチャへの対応のために、このようなアーキテクチャ固有のファイルが存在します。
type Inet4Pktinfo struct { ... }
:types_darwin.go
で宣言されたInet4Pktinfo
型の具体的なフィールド定義がここに記述されています。Ifindex uint32
: パケットが受信されたネットワークインターフェースのインデックス(符号なし32ビット整数)。Spec_dst [4]byte /* in_addr */
: パケットの元の宛先IPアドレス。[4]byte
はIPv4アドレス(4バイト)を表します。コメント/* in_addr */
は、これがC言語のin_addr
型に対応することを示唆しています。Addr [4]byte /* in_addr */
: パケットが受信されたローカルIPアドレス。こちらも[4]byte
で表現されます。
- これらのフィールドは、C言語の
struct in_pktinfo
のメンバーに対応しており、Goプログラムがパケットの補助データからこれらの情報を直接抽出できるようにします。
SizeofInet4Pktinfo = 0xc
:types_darwin.go
で宣言されたSizeofInet4Pktinfo
定数の具体的な値が、各アーキテクチャ向けに定義されています。0xc
は12バイトを意味します。これは、uint32
(4バイト)と2つの[4]byte
(それぞれ4バイト)の合計サイズ(4 + 4 + 4 = 12バイト)と一致します。この具体的なバイトサイズは、システムコールでメモリを扱う際に正確なオフセット計算やバッファサイズ決定に必要です。
これらの変更により、Goのsyscall
パッケージはDarwin環境において、IPv4の補助データを扱うための完全な型定義とサイズ情報を持つことになり、Goプログラムがより低レベルなネットワーク情報を利用できるようになります。
関連リンク
- Go Change-Id:
I2222222222222222222222222222222222222222
(コミットメッセージに記載のhttps://golang.org/cl/6586044
に対応するGoのコードレビューシステムへのリンク)
参考にした情報源リンク
- Go
syscall
package documentation - IP_PKTINFO socket option (Linux man page, similar concepts apply to Darwin)
- recvmsg(2) man page (Linux, general concepts)
- sendmsg(2) man page (Linux, general concepts)
- Ancillary Data (Control Messages) in Sockets
- CMSG_LEN and CMSG_SPACE macros
- Go
x/sys/unix
package (modern alternative tosyscall
for some cases) - Understanding
in_pktinfo
(Stack Overflow discussion) - Go
syscall
package source code (for context onztypes
files) - Darwin
in_pktinfo
definition (example from XNU kernel source)