[インデックス 18005] ファイルの概要
このコミットは、Go言語のネットワークパッケージ(net
)におけるPlan 9オペレーティングシステム向けのプロトコルルックアップとホストルックアップの挙動を修正するものです。具体的には、プロトコル名の検索時に小文字を使用するように変更し、lookupHost
関数でより汎用的なネットワークプロトコルを使用するように更新しています。
コミット
commit 20dee338c322bb3beb805f837ab780f98cfe8d59
Author: David du Colombier <0intro@gmail.com>
Date: Mon Dec 16 12:00:23 2013 -0800
net: lookup protocol in lower-case on Plan 9
Protocol keywords are case-insensitive,
but the Ndb database is case-sensitive.
Also use the generic net protocol instead
of tcp in lookupHost.
R=golang-dev, bradfitz
CC=golang-dev
https://golang.org/cl/40600047
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/20dee338c322bb3beb805f837ab780f98cfe8d59
元コミット内容
このコミットは、src/pkg/net/lookup_plan9.go
ファイルに対して以下の変更を加えています。
strings
パッケージのインポートを追加。lookupProtocol
関数内で、プロトコル名をクエリする際にstrings.ToLower()
を使用して小文字に変換するように変更。- 変更前:
lines, err := query("/net/cs", "!protocol="+name, 128)
- 変更後:
lines, err := query("/net/cs", "!protocol="+strings.ToLower(name), 128)
- 変更前:
lookupHost
関数内で、queryCS
を呼び出す際のプロトコル指定を"tcp"
から"net"
に変更。- 変更前:
lines, err := queryCS("tcp", host, "1")
- 変更後:
lines, err := queryCS("net", host, "1")
- 変更前:
変更の背景
この変更の背景には、Plan 9オペレーティングシステムのネットワーク設定とデータベースの特性があります。
-
Ndbデータベースのケースセンシティブ性: Plan 9のネットワーク設定は、主にNdb (Name database) と呼ばれるデータベースによって管理されています。このNdbデータベースは、その内部でキーと値のペアを格納する際にケースセンシティブ(大文字と小文字を区別する)な挙動を示します。しかし、一般的なネットワークプロトコルのキーワード(例: "TCP", "tcp")は、通常ケースインセンシティブに扱われるべきです。この不一致が問題を引き起こしていました。Goの
net
パッケージがプロトコル名をNdbに問い合わせる際、ユーザーが指定したプロトコル名(例: "TCP")がNdbに登録されている小文字のプロトコル名(例: "tcp")と一致しない場合、正しい情報が取得できない可能性がありました。このコミットは、Ndbに問い合わせる前にプロトコル名を小文字に統一することで、この問題を解決しようとしています。 -
lookupHost
における汎用プロトコルの使用:lookupHost
関数は、ホスト名からIPアドレスを解決する役割を担っています。以前は、この関数が内部でqueryCS
を呼び出す際に、特定のプロトコルとして"tcp"を指定していました。しかし、ホスト名の解決はTCPプロトコルに限定されるものではなく、より汎用的なネットワークサービスに関連する情報であるべきです。"net"
という汎用的なプロトコル指定を使用することで、TCPに限定されず、より広範なネットワーク設定(例えば、ローカルネットワーク内のホスト名解決など)に対応できるようになります。これは、/net/cs
(connection server)がローカルのホスト名解決情報(/lib/ndb/local
などから)も知っているというコメントからも裏付けられます。
これらの変更は、Goのnet
パッケージがPlan 9環境でより堅牢かつ正確に動作するようにするためのものです。
前提知識の解説
このコミットを理解するためには、以下の概念について基本的な知識が必要です。
- Plan 9 from Bell Labs: ベル研究所で開発された分散オペレーティングシステム。Unixの後継として設計され、"Everything is a file"(すべてはファイルである)という哲学を徹底しています。ネットワークリソースもファイルシステムを通じてアクセスされます。
- Ndb (Name database): Plan 9におけるネットワーク設定情報(ホスト名、IPアドレス、プロトコルなど)を管理するためのデータベースシステム。
/lib/ndb
ディレクトリ以下のファイル群で構成され、ndb/cs
(connection server)などのサービスがこのデータベースを利用して名前解決やプロトコル情報のルックアップを行います。Ndbは、その設計上、キーの検索においてケースセンシティブな挙動を示すことがあります。 /net/cs
(Connection Server): Plan 9のネットワークサービスの一つで、接続に関する情報を提供します。これには、プロトコル番号のルックアップや、ホスト名からIPアドレスへの解決などが含まれます。ファイルシステム上の/net/cs
というパスを通じてアクセスされます。/net/dns
: Plan 9におけるDNS(Domain Name System)クライアントサービス。外部のDNSサーバーに問い合わせてホスト名を解決する際に使用されます。query
およびqueryCS
関数: Goのnet
パッケージ(特にPlan 9向けの実装)内で、Plan 9のファイルシステムを通じてネットワークサービスに問い合わせを行うための内部関数です。query(filename, query string, bufSize int)
: 指定されたfilename
(例:/net/cs
)に対してquery
文字列を送信し、結果を読み取ります。queryCS(proto, name, typ string)
:/net/cs
に対して特定のプロトコル、名前、タイプで問い合わせを行います。
- ケースセンシティブとケースインセンシティブ:
- ケースセンシティブ (Case-sensitive): 大文字と小文字を区別すること。例えば、"TCP"と"tcp"は異なるものとして扱われます。
- ケースインセンシティブ (Case-insensitive): 大文字と小文字を区別しないこと。例えば、"TCP"と"tcp"は同じものとして扱われます。
技術的詳細
このコミットの技術的詳細は、Plan 9のネットワークスタックとGoのnet
パッケージの連携に深く関わっています。
1. lookupProtocol
における小文字化の必要性
lookupProtocol
関数は、与えられたプロトコル名(例: "tcp", "udp")に対応するプロトコル番号(例: TCPなら6, UDPなら17)を取得するために使用されます。Plan 9では、この情報は/net/cs
を通じてNdbデータベースから取得されます。
Ndbデータベースは、プロトコル名をキーとしてプロトコル番号を格納していますが、その内部的なキーの比較はケースセンシティブです。しかし、Goのnet
パッケージを使用するアプリケーションや、一般的なネットワークプロトコルの慣習では、プロトコル名はケースインセンシティブに扱われることが期待されます。
例えば、ユーザーが"TCP"
という文字列をプロトコル名として指定した場合、Goのnet
パッケージはこれをlookupProtocol
に渡します。もしNdbに"tcp"
というエントリしか登録されていない場合、ケースセンシティブな検索では"TCP"
と"tcp"
は一致しないため、正しいプロトコル番号が取得できませんでした。
このコミットでは、query
関数を呼び出す前にstrings.ToLower(name)
を使用することで、入力されたプロトコル名を強制的に小文字に変換しています。これにより、Ndbデータベースが内部的に小文字のプロトコル名(例: "tcp")でエントリを保持している場合でも、ユーザーがどのような大文字・小文字の組み合わせでプロトコル名を指定しても、常に正しいエントリにヒットするようになります。これは、堅牢性と互換性を向上させるための重要な変更です。
2. lookupHost
におけるプロトコル指定の変更
lookupHost
関数は、ホスト名(例: "google.com")に対応するIPアドレスを解決するために使用されます。Plan 9では、この解決は/net/cs
を通じて行われます。
以前の実装では、queryCS
関数を呼び出す際に、プロトコルとして"tcp"
がハードコードされていました。これは、ホスト名の解決が主にTCP接続の確立に関連しているという一般的な認識に基づいていた可能性があります。しかし、ホスト名の解決はTCPに限定されるものではなく、より広範なネットワークサービスや設定(例えば、ローカルネットワーク内のホスト名解決や、他のプロトコルに関連する名前解決)にも適用されるべきです。
Plan 9の/net/cs
は、単にDNSクエリを転送するだけでなく、/lib/ndb/local
のようなローカルのNdbファイルに定義されたホスト名情報も利用して名前解決を行います。これらのローカルなエントリは、必ずしも特定のトランスポートプロトコル(TCPやUDP)に厳密に結びついているわけではありません。
"net"
というプロトコル指定は、TCPやUDPのような特定のトランスポートプロトコルではなく、より抽象的で汎用的な「ネットワーク」サービス全般を指します。この変更により、lookupHost
はTCPに限定されず、/net/cs
が提供するあらゆる種類のホスト名解決情報(ローカルなNdbエントリを含む)をより適切に利用できるようになります。これにより、Plan 9環境におけるホスト名解決の柔軟性と正確性が向上します。
コアとなるコードの変更箇所
変更は src/pkg/net/lookup_plan9.go
ファイルに集中しています。
--- a/src/pkg/net/lookup_plan9.go
+++ b/src/pkg/net/lookup_plan9.go
@@ -7,6 +7,7 @@ package net
import (
"errors"
"os"
+ "strings" // 追加
)
func query(filename, query string, bufSize int) (res []string, err error) {
@@ -72,7 +73,7 @@ func queryDNS(addr string, typ string) (res []string, err error) {
// lookupProtocol looks up IP protocol name and returns
// the corresponding protocol number.
func lookupProtocol(name string) (proto int, err error) {
- lines, err := query("/net/cs", "!protocol="+name, 128) // 変更前
+ lines, err := query("/net/cs", "!protocol="+strings.ToLower(name), 128) // 変更後
if err != nil {
return 0, err
}
@@ -94,7 +95,7 @@ func lookupProtocol(name string) (proto int, err error) {
func lookupHost(host string) (addrs []string, err error) {
// Use /net/cs instead of /net/dns because cs knows about
// host names in local network (e.g. from /lib/ndb/local)
- lines, err := queryCS("tcp", host, "1") // 変更前
+ lines, err := queryCS("net", host, "1") // 変更後
if err != nil {
return
}
コアとなるコードの解説
import "strings"
の追加
strings.ToLower()
関数を使用するために、Goの標準ライブラリであるstrings
パッケージがインポートされました。
lookupProtocol
関数の変更
func lookupProtocol(name string) (proto int, err error) {
lines, err := query("/net/cs", "!protocol="+strings.ToLower(name), 128)
if err != nil {
return 0, err
}
// ... (後続の処理は変更なし)
}
この変更の核心は、query
関数に渡すクエリ文字列の構築部分です。
- 変更前は、引数として受け取った
name
(プロトコル名)をそのままクエリ文字列に連結していました。 - 変更後は、
strings.ToLower(name)
を使用して、name
を小文字に変換してからクエリ文字列に連結しています。
これにより、例えばlookupProtocol("TCP")
が呼び出された場合でも、/net/cs
へのクエリは!protocol=tcp
となり、Ndbデータベースがtcp
という小文字のキーでプロトコル情報を保持している場合に正しくマッチするようになります。
lookupHost
関数の変更
func lookupHost(host string) (addrs []string, err error) {
// Use /net/cs instead of /net/dns because cs knows about
// host names in local network (e.g. from /lib/ndb/local)
lines, err := queryCS("net", host, "1")
if err != nil {
return
}
// ... (後続の処理は変更なし)
}
この変更は、queryCS
関数の最初の引数(プロトコル指定)を"tcp"
から"net"
に変更した点です。
- 変更前は、ホスト名解決のためにTCPプロトコルに特化した問い合わせを行っていました。
- 変更後は、より汎用的な
"net"
プロトコルを指定することで、/net/cs
が提供する広範な名前解決サービス(ローカルのNdbエントリを含む)を利用できるようになりました。これにより、ホスト名解決の範囲がTCPに限定されず、Plan 9のネットワーク環境により適した挙動となります。コメントにもあるように、/net/cs
は/lib/ndb/local
からのホスト名も認識しているため、この変更は理にかなっています。
関連リンク
- Go言語の公式リポジトリ: https://github.com/golang/go
- Go言語のコードレビューシステム (Gerrit): https://go-review.googlesource.com/
- このコミットのGerritレビューページ: https://golang.org/cl/40600047
参考にした情報源リンク
- Plan 9 from Bell Labs: https://9p.io/plan9/
- Plan 9のNdb (Name database) に関する情報:
- Go言語の
net
パッケージのドキュメント: https://pkg.go.dev/net - Go言語の
strings
パッケージのドキュメント: https://pkg.go.dev/strings - Plan 9のネットワークに関する一般的な情報源(検索結果に基づく)
- "Plan 9 /net/cs"
- "Plan 9 Ndb case sensitive"
- "Go net package Plan 9"
- "Plan 9 network protocols"
- "Plan 9 /lib/ndb/local"