[インデックス 10033] net: allow LookupSRV on non-standard DNS names
コミット
コミットハッシュ: 48bb3e8f2883609ca56ea8afc0c11f141f4ec227
作成者: Russ Cox rsc@golang.org
日付: 2011年10月18日(火)13:57:04 -0400
メッセージ: net: allow LookupSRV on non-standard DNS names
変更ファイル:
- src/pkg/net/lookup_plan9.go (19行追加、5行削除)
- src/pkg/net/lookup_test.go (9行追加)
- src/pkg/net/lookup_unix.go (19行追加、5行削除)
- src/pkg/net/lookup_windows.go (16行追加、1行削除)
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/48bb3e8f2883609ca56ea8afc0c11f141f4ec227
元コミット内容
commit 48bb3e8f2883609ca56ea8afc0c11f141f4ec227
Author: Russ Cox <rsc@golang.org>
Date: Tue Oct 18 13:57:04 2011 -0400
net: allow LookupSRV on non-standard DNS names
R=golang-dev, bradfitz
CC=golang-dev
https://golang.org/cl/5313043
src/pkg/net/lookup_plan9.go | 19 ++++++++++++++-----
src/pkg/net/lookup_test.go | 9 +++++++++
src/pkg/net/lookup_unix.go | 19 ++++++++++++++-----
src/pkg/net/lookup_windows.go | 16 +++++++++++++++-
4 files changed, 52 insertions(+), 11 deletions(-)
変更の背景
このコミットは、Go言語のnetパッケージにおけるLookupSRV関数の機能拡張を行ったものです。従来のLookupSRV関数は、RFC 2782に準拠したDNS SRVレコードの標準形式のみをサポートしていました。しかし、実際のシステムでは、標準的でない名前でSRVレコードを発行するサービスも存在するため、そのような非標準のDNS名にも対応する必要がありました。
この変更により、サービスとプロトコルのパラメータが両方とも空文字列の場合、LookupSRVは名前を直接ルックアップできるようになりました。これは、標準のRFC 2782の_service._proto.nameフォーマットを使用しないサービスに対応するためのバイパス機能です。
前提知識の解説
DNS SRVレコードとは
DNS SRVレコード(Service Record)は、RFC 2782で定義されたDNSリソースレコードの一種で、特定のプロトコルとドメインに対してサーバーの場所を指定します。SRVレコードは、クライアントがサービスを自動的に発見できるようにするメカニズムを提供します。
RFC 2782の標準フォーマット
RFC 2782によると、SRVレコードの標準形式は以下の通りです:
_Service._Proto.Name TTL Class SRV Priority Weight Port Target
構成要素の説明:
- Service: 希望するサービスの記号名(例:_sip、_ldap)
- Proto: 希望するプロトコルの記号名(例:_tcp、_udp)
- Name: このRRが参照するドメイン名
- Priority: ターゲットホストの優先度
- Weight: 同じ優先度を持つエントリの相対的な重み
- Port: サービスが提供されるTCPまたはUDPポート
- Target: サービスを提供するマシンの正規ホスト名
非標準DNS名の問題
実際のシステムでは、RFC 2782の標準フォーマットに従わないSRVレコードを発行するサービスが存在します。例えば:
- 内部的なサービスディスカバリーシステム
- レガシーシステムとの互換性維持
- 特定のアプリケーション固有の命名規則
このような場合、標準のLookupSRV関数では正しく処理できないという問題がありました。
技術的詳細
LookupSRV関数の動作
通常のLookupSRV関数は、以下の引数を取ります:
service
: サービス名proto
: プロトコル名name
: ドメイン名
関数は内部的に_service._proto.name
の形式でDNSクエリを構築し、SRVレコードを検索します。
非標準名対応の実装
この変更により、以下のような動作が追加されました:
- 標準動作:
service
とproto
が空でない場合、従来通り_service._proto.name
形式でクエリを実行 - 非標準名対応:
service
とproto
が両方とも空文字列の場合、name
を直接クエリとして使用
これにより、標準的でない名前でSRVレコードを発行するサービスにも対応できるようになりました。
実装の詳細
変更は以下の4つのファイルに対して行われました:
- lookup_plan9.go: Plan 9オペレーティングシステム向けの実装
- lookup_unix.go: Unix系オペレーティングシステム向けの実装
- lookup_windows.go: Windows向けの実装
- lookup_test.go: テストケースの追加
各プラットフォーム固有の実装ファイルで、空文字列チェックロジックが追加され、条件に応じて異なるクエリ形式を使用するようになりました。
コアとなるコードの変更箇所
このコミットでは、複数のプラットフォーム向けのlookup実装ファイルに対して変更が行われました。主要な変更点は以下の通りです:
変更されたファイル
- src/pkg/net/lookup_plan9.go: Plan 9向け実装(+19行、-5行)
- src/pkg/net/lookup_unix.go: Unix系向け実装(+19行、-5行)
- src/pkg/net/lookup_windows.go: Windows向け実装(+16行、-1行)
- src/pkg/net/lookup_test.go: テストケース(+9行)
主な変更パターン
各プラットフォーム実装において、以下のような変更が行われました:
- 条件分岐の追加: serviceとprotoパラメータが空文字列かどうかをチェック
- クエリ形式の分岐: 標準形式と非標準形式のクエリを使い分け
- エラーハンドリング: 新しいケースに対応したエラー処理
コアとなるコードの解説
基本的な変更パターン
各プラットフォーム実装で共通して行われた変更は、以下のような条件分岐の追加です:
// 疑似コード(実際のコードではない)
func lookupSRV(service, proto, name string) ([]*SRV, error) {
var target string
if service == "" && proto == "" {
// 非標準名対応: 名前を直接使用
target = name
} else {
// 標準形式: _service._proto.name
target = "_" + service + "._" + proto + "." + name
}
// DNSクエリの実行
return querySRV(target)
}
新機能の利点
- 互換性の向上: 既存のコードは変更なしで動作
- 柔軟性の提供: 非標準的な名前でのSRVレコード検索が可能
- 明確な条件: 両方のパラメータが空の場合のみ新機能が有効
テストケースの追加
lookup_test.go
にテストケースが追加され、新機能の動作確認が可能になりました。これにより、回帰テストと機能検証が行われています。
プラットフォーム間の一貫性
Plan 9、Unix系、Windows向けの実装すべてで同様の変更が行われており、プラットフォーム間でのLookupSRVの動作の一貫性が保たれています。
関連リンク
- RFC 2782 - A DNS RR for specifying the location of services (DNS SRV)
- Go言語 net パッケージ ドキュメント
- DNS Service Discovery (DNS-SD)
- SRV Record - Wikipedia
- Go Issue #758: Add support for DNS SRV requests