# 機能設計書 8-dns

## 概要

本ドキュメントは、Node.jsのdnsモジュール（DNS名前解決機能）の機能設計を記載する。dnsモジュールは、ドメイン名からIPアドレスへの名前解決およびその逆引きを提供するコアモジュールである。

### 本機能の処理概要

dnsモジュールは、DNS（Domain Name System）を使用した名前解決機能を提供する。OSのネイティブ機能を使用するlookup()と、ネットワーク経由でDNSサーバーに直接問い合わせるResolverの2種類の方法を提供する。

**業務上の目的・背景**：ネットワークアプリケーションでは、人間が読みやすいドメイン名をIPアドレスに変換する必要がある。dnsモジュールは、http/https/net等のモジュールの基盤として、ホスト名の解決を行う。また、メール送信時のMXレコード検索やサービスディスカバリーのためのSRVレコード検索など、様々なDNSレコードタイプの問い合わせをサポートする。

**機能の利用シーン**：
- ホスト名からIPアドレスへの変換
- IPアドレスからホスト名への逆引き
- MXレコード検索（メールサーバー発見）
- TXTレコード検索（ドメイン検証、SPF等）
- SRVレコード検索（サービスディスカバリー）
- NSレコード検索（ネームサーバー発見）
- カスタムDNSサーバーの指定

**主要な処理内容**：
1. ホスト名解決（lookup）- OSのgetaddrinfo使用
2. 逆引き解決（lookupService）- OSのgetnameinfo使用
3. DNSレコード解決（resolve, resolve4, resolve6, resolveMx等）
4. 逆引き解決（reverse）
5. DNSサーバー設定（setServers, getServers）
6. 結果順序設定（setDefaultResultOrder）

**関連システム・外部連携**：
- cares_wrapバインディング（c-ares DNSライブラリ）
- OSのDNSリゾルバ（/etc/resolv.conf等）
- 外部DNSサーバー

**権限による制御**：特別な権限制御なし。ネットワークアクセスが必要。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 直接関連する画面なし |

## 機能種別

ネットワーク / 名前解決 / ユーティリティ

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| hostname | string | Yes | 解決するホスト名 | validateString |
| options | object/number | No | 解決オプションまたはfamily | - |
| options.family | number/string | No | 4, 6, 0, 'IPv4', 'IPv6' | validateOneOf |
| options.hints | number | No | getaddrinfoヒント | validateHints |
| options.all | boolean | No | すべての結果を返す | validateBoolean |
| options.verbatim | boolean | No | OSの順序を維持 | validateBoolean |
| options.order | string | No | 'verbatim', 'ipv4first', 'ipv6first' | validateOneOf |
| address | string | No | 逆引きするIPアドレス | isIP |
| port | number | No | サービス検索用ポート | validatePort |
| callback | Function | Yes | コールバック関数 | validateFunction |

### 入力データソース

- アプリケーションコード：ホスト名、IPアドレス
- OS設定：/etc/resolv.conf、システムDNS設定
- 外部DNSサーバー：DNS応答

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| address | string | 解決されたIPアドレス |
| family | number | アドレスファミリー（4または6） |
| addresses | Array | 複数アドレスの配列（all:true時） |
| hostname | string | 逆引きで得られたホスト名 |
| service | string | ポートに対応するサービス名 |

### 出力先

- コールバック関数
- Promiseオブジェクト（dns.promises使用時）

## 処理フロー

### 処理シーケンス（lookup）

```
1. lookup(hostname, options, callback)呼び出し
2. パラメータ検証
   └─ hostname, options, callback
3. IPアドレスチェック
   └─ 既にIPの場合は即座にコールバック
4. GetAddrInfoReqWrap生成
5. cares.getaddrinfo()呼び出し
   └─ OSのネイティブDNS機能使用
6. onlookup/onlookupall コールバック
   └─ DNSExceptionまたは結果を返却
```

### 処理シーケンス（resolve）

```
1. resolve(hostname, rrtype, callback)呼び出し
2. Resolverインスタンス使用
   └─ デフォルトまたはカスタムResolver
3. c-aresライブラリで直接DNS問い合わせ
4. 結果をコールバックで返却
```

### フローチャート

```mermaid
flowchart TD
    A[lookup] --> B{hostnameはIP?}
    B -->|Yes| C[即座にコールバック]
    B -->|No| D[GetAddrInfoReqWrap生成]
    D --> E[cares.getaddrinfo]
    E --> F{all: true?}
    F -->|Yes| G[onlookupall]
    F -->|No| H[onlookup]
    G --> I[結果配列を返却]
    H --> J[最初の結果を返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | デフォルト結果順序 | getDefaultResultOrder()で取得 | order未指定時 |
| BR-002 | verbatimオプション | OSの返す順序を維持 | verbatim:true時 |
| BR-003 | ipv4firstオプション | IPv4を優先 | order:'ipv4first'時 |
| BR-004 | ipv6firstオプション | IPv6を優先 | order:'ipv6first'時 |
| BR-005 | 既存IPの場合 | DNS問い合わせをスキップ | isIP()がtrue時 |
| BR-006 | エラーコード | DNSExceptionで詳細なエラー | 解決失敗時 |

### 計算ロジック

- DNS_ORDER_VERBATIM: OSの返す順序
- DNS_ORDER_IPV4_FIRST: IPv4アドレスを先に返す
- DNS_ORDER_IPV6_FIRST: IPv6アドレスを先に返す

## データベース操作仕様

本モジュールはデータベースを直接操作しない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| NODATA | DNS | データなし | 別のレコードタイプを試行 |
| FORMERR | DNS | クエリ形式エラー | クエリ内容を確認 |
| SERVFAIL | DNS | サーバー障害 | 別のDNSサーバーを試行 |
| NOTFOUND | DNS | ドメインが見つからない | ドメイン名を確認 |
| NOTIMP | DNS | 未実装 | 別のDNSサーバーを試行 |
| REFUSED | DNS | 拒否された | DNSサーバー設定を確認 |
| TIMEOUT | DNS | タイムアウト | ネットワーク接続を確認 |
| CONNREFUSED | DNS | 接続拒否 | DNSサーバーを確認 |
| CANCELLED | DNS | キャンセルされた | 再試行 |
| ERR_INVALID_ARG_VALUE | バリデーション | 無効な引数値 | 引数を確認 |

### リトライ仕様

c-aresライブラリが内部でリトライを行う。アプリケーション層での追加リトライも検討。

## トランザクション仕様

DNSはステートレスプロトコル。各クエリは独立。

## パフォーマンス要件

- lookup()はOSのキャッシュを利用
- Resolverは直接DNS問い合わせ（キャッシュなし）
- 非同期処理による高スループット
- perf_hooksでのパフォーマンス計測サポート

## セキュリティ考慮事項

- DNSスプーフィング対策（DNSSEC推奨）
- 信頼できるDNSサーバーの使用
- DNS over HTTPS/TLS検討

## 備考

- lookup()はOSのネイティブ機能を使用（/etc/hosts対応）
- resolve*()はc-aresライブラリを使用（直接DNS問い合わせ）
- dns.promises.lookup()でPromise版を提供
- diagnostics_channelでdnsチャネルを提供

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | dns.js | `lib/dns.js` | エラーコード定義とエクスポート |

**読解のコツ**: エラーコード（55-79行目）がDNS操作の結果を表す。GetAddrInfoReqWrap, GetNameInfoReqWrap（90-91行目）がリクエストラッパー。

#### Step 2: エントリーポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | dns.js | `lib/dns.js` | 公開API定義（314-369行目） |

**主要処理フロー**:
1. **142-249行目**: lookup()関数 - OSネイティブ名前解決
2. **266-298行目**: lookupService()関数 - 逆引き解決
3. **303-312行目**: defaultResolverSetServers() - DNSサーバー設定
4. **355行目**: bindDefaultResolver() - Resolverメソッドのバインド

#### Step 3: lookup処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | dns.js | `lib/dns.js` | lookup処理の実装 |

**主要処理フロー**:
- **108-116行目**: onlookup() - 単一結果コールバック
- **119-137行目**: onlookupall() - 複数結果コールバック
- **205-214行目**: IPアドレスチェックとショートカット
- **216-248行目**: GetAddrInfoReqWrap生成とcares.getaddrinfo呼び出し

#### Step 4: エラーコードを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | dns.js | `lib/dns.js` | エラーコード定義 |

**主要処理フロー**:
- **55-79行目**: dnsErrorCodesからのエラーコードインポート
- **328-352行目**: エラーコードのエクスポート

### プログラム呼び出し階層図

```
dns.lookup(hostname, options, callback)
    │
    ├─ validateString(hostname)
    │
    ├─ オプション解析
    │      └─ family, hints, all, verbatim, order
    │
    ├─ isIP(hostname)チェック
    │      │
    │      └─ IPの場合 → process.nextTick(callback, ...)
    │
    └─ new GetAddrInfoReqWrap()
           │
           ├─ req.callback = callback
           ├─ req.hostname = hostname
           ├─ req.oncomplete = onlookup/onlookupall
           │
           └─ cares.getaddrinfo(req, hostname, family, hints, order)
                  │
                  └─ OSのgetaddrinfo() [非同期]
                         │
                         └─ onlookup()/onlookupall()
                                │
                                └─ callback(err, address, family)

dns.lookupService(address, port, callback)
    │
    ├─ isIP(address)チェック
    ├─ validatePort(port)
    ├─ validateFunction(callback)
    │
    └─ new GetNameInfoReqWrap()
           │
           ├─ req.callback = callback
           ├─ req.oncomplete = onlookupservice
           │
           └─ cares.getnameinfo(req, address, port)
                  │
                  └─ OSのgetnameinfo() [非同期]
                         │
                         └─ onlookupservice()
                                │
                                └─ callback(err, hostname, service)

dns.resolve/resolve4/resolve6/... (Resolverを使用)
    │
    └─ Resolver.prototype.resolve*()
           │
           └─ c-aresライブラリで直接DNS問い合わせ
```

### データフロー図

```
[入力]                    [処理]                         [出力]

hostname        ───▶  lookup                 ───▶  address, family
                           │
                      isIP(hostname)?
                           │
                      ┌────┴────┐
                      │         │
                   Yes│         │No
                      │         │
           即座にコールバック  GetAddrInfoReqWrap
                               │
                          cares.getaddrinfo
                               │
                          OS getaddrinfo
                               │
                          onlookup/onlookupall
                               │
                          callback(err, address, family)

[Resolver]

hostname        ───▶  resolve*              ───▶  records
                           │
                      c-ares DNS問い合わせ
                           │
                      DNSサーバー応答
                           │
                      callback(err, records)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| dns.js | `lib/dns.js` | ソース | 公開API定義（メイン） |
| internal/dns/utils.js | `lib/internal/dns/utils.js` | ソース | 内部ユーティリティ |
| internal/dns/callback_resolver.js | `lib/internal/dns/callback_resolver.js` | ソース | Resolverコールバック版 |
| internal/dns/promises.js | `lib/internal/dns/promises.js` | ソース | Promise版API |
