# 機能設計書 103-ARPテーブル管理

## 概要

本ドキュメントは、FreeBSDのARPキャッシュテーブルの参照・操作を行うarpコマンドの機能設計を記述する。ARPテーブルはIPv4アドレスとMACアドレスの対応関係を管理するネットワーク基盤機能である。

### 本機能の処理概要

arpコマンドは、カーネルのARPキャッシュテーブルに対して表示・追加・削除・一括操作を行うユーザ空間コマンドである。ルーティングソケットおよびNetLinkソケットの2つのバックエンドを使用してカーネルと通信する。

**業務上の目的・背景**：ARP（Address Resolution Protocol）はIPv4ネットワークにおいてIPアドレスからMACアドレス（リンク層アドレス）を解決するための基本プロトコルである。arpコマンドは、ネットワーク障害の診断、静的ARPエントリの設定、ARPキャッシュのクリア等のネットワーク管理作業に不可欠なツールである。

**機能の利用シーン**：ネットワーク障害診断時にARPキャッシュの状態を確認する場合、特定のホストに対する静的ARPエントリを設定する場合、ARPキャッシュを一括クリアする場合、ファイルからARPエントリを一括設定する場合に使用される。

**主要な処理内容**：
1. ARPキャッシュの全エントリ表示（-aオプション）
2. 特定ホストのARPエントリ取得（引数にホスト名/IPアドレス指定）
3. 静的ARPエントリの追加（-sオプション）
4. ARPエントリの削除（-dオプション）
5. ARPエントリの置換（-Sオプション、既存エントリを削除してから追加）
6. ファイルからのARP一括設定（-fオプション）
7. 特定インタフェースへのフィルタリング（-iオプション）
8. libxoによる構造化出力（JSON/XML対応）

**関連システム・外部連携**：カーネルARPテーブル（routing socket経由またはNetLink経由）、/etc/ethers（イーサネットアドレスデータベース）、libxo（構造化出力ライブラリ）。

**権限による制御**：ARPエントリの追加・削除にはroot権限が必要。参照操作は一般ユーザでも可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | CLIコマンド | 主機能 | コマンドライン操作、画面なし |

## 機能種別

CRUD操作（ARPキャッシュエントリの表示・追加・更新・削除）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| -a | フラグ | No | 全ARPエントリを表示 | なし |
| -d hostname | 文字列 | No | 指定ホストのARPエントリを削除 | 有効なホスト名/IPアドレス |
| -d -a | フラグ | No | 全ARPエントリを削除 | なし |
| -s hostname ether_addr | 文字列 | No | 静的ARPエントリの追加 | 有効なホスト名とMACアドレス |
| -S hostname ether_addr | 文字列 | No | ARPエントリの置換（削除+追加） | 有効なホスト名とMACアドレス |
| -f filename | 文字列 | No | ファイルからARP一括設定 | 読み取り可能なファイル |
| -n | フラグ | No | 名前解決を行わない | なし |
| -i interface | 文字列 | No | 特定インタフェースに限定 | 有効なインタフェース名 |
| temp | キーワード | No | 一時的エントリ（タイムアウトあり） | -sまたは-Sと併用 |
| pub | キーワード | No | プロキシARPエントリ | -sまたは-Sと併用 |
| reject | キーワード | No | 拒否エントリ | -sまたは-Sと併用 |
| blackhole | キーワード | No | ブラックホールエントリ | -sまたは-Sと併用 |

### 入力データソース

- コマンドライン引数
- ARPエントリ設定ファイル（-fオプション時）
- カーネルARPキャッシュ（routing socket / NetLink経由）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| hostname | 文字列 | ホスト名またはIPアドレス |
| ether_addr | 文字列 | MACアドレス (xx:xx:xx:xx:xx:xx) |
| expires | 整数 | 有効期限（秒） |
| interface | 文字列 | ネットワークインタフェース名 |
| flags | 文字列 | エントリフラグ（permanent, published等） |

### 出力先

- 標準出力（libxoによるテキスト/JSON/XML形式）
- 標準エラー出力（エラーメッセージ）

## 処理フロー

### 処理シーケンス

```
1. 引数解析
   └─ getopt()による-a, -d, -n, -S, -s, -f, -iオプション解析
2. インタフェース名解決
   └─ -iオプション指定時、if_nametoindex()でインデックスに変換
3. 操作種別による分岐
   ├─ F_GET: get()またはprint_entries()でARPエントリ取得・表示
   ├─ F_SET/F_REPLACE: set()で静的ARPエントリ追加
   ├─ F_DELETE: delete()でARPエントリ削除
   └─ F_FILESET: file()でファイルから一括設定
4. カーネルとの通信
   ├─ ルーティングソケット: rtmsg()経由でRTM_GET/RTM_ADD/RTM_DELETE
   └─ NetLink: print_entries_nl()/delete_nl()/set_nl()経由
5. 結果出力
   └─ libxo APIで構造化出力
```

### フローチャート

```mermaid
flowchart TD
    A[起動] --> B[xo_parse_args + getopt]
    B --> C{操作種別判定}
    C -->|F_GET + -a| D[print_entries - 全エントリ表示]
    C -->|F_GET| E[get - 特定ホスト取得]
    C -->|F_SET| F[set - エントリ追加]
    C -->|F_REPLACE| G[delete + set - エントリ置換]
    C -->|F_DELETE + -a| H[nuke_entries - 全削除]
    C -->|F_DELETE| I[delete - 特定エントリ削除]
    C -->|F_FILESET| J[file - ファイル一括設定]
    D --> K[libxo出力]
    E --> K
    F --> K
    G --> K
    H --> K
    I --> K
    J --> K
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-103-1 | 有効インタフェースタイプ | ARP対象はIFT_ETHER, IFT_FDDI, IFT_IEEE1394, IFT_INFINIBAND, IFT_ISO88023, IFT_ISO88024, IFT_L2VLAN, IFT_BRIDGEのみ | 常時 |
| BR-103-2 | 置換操作 | -Sオプションは既存エントリの削除後に新規追加を行う | F_REPLACE時 |
| BR-103-3 | インタフェースフィルタ | -iオプション指定時、指定インタフェースのエントリのみ対象 | -i指定時 |
| BR-103-4 | ファイル形式 | -fオプションのファイルは「hostname ether_addr [temp] [pub]」形式、#でコメント | F_FILESET時 |

### 計算ロジック

特になし。

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

### 操作別データベース影響一覧

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| get/print_entries | カーネルARPキャッシュ | SELECT | ARPエントリの取得・表示 |
| set | カーネルARPキャッシュ | INSERT | 静的ARPエントリの追加 |
| delete | カーネルARPキャッシュ | DELETE | ARPエントリの削除 |
| nuke_entries | カーネルARPキャッシュ | DELETE | 全ARPエントリの一括削除 |

### テーブル別操作詳細

#### カーネルARPキャッシュ（ルーティングソケット経由）

| 操作 | 項目 | 値 | 備考 |
|-----|------|-----|------|
| RTM_GET | dst (sockaddr_in) | 対象IPアドレス | ルーティングソケットメッセージ |
| RTM_ADD | dst + gateway (sockaddr_dl) | IP+MACアドレス | フラグにRTF_STATIC等設定 |
| RTM_DELETE | dst | 対象IPアドレス | エントリ削除 |

#### カーネルARPキャッシュ（NetLink経由）

| 操作 | 項目 | 値 | 備考 |
|-----|------|-----|------|
| RTM_GETNEIGH | ifindex, dst | インタフェース+IPアドレス | NetLinkメッセージ |
| RTM_NEWNEIGH | ifindex, dst, lladdr | インタフェース+IP+MACアドレス | NLM_F_CREATE |
| RTM_DELNEIGH | ifindex, dst | インタフェース+IPアドレス | エントリ削除 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 1 | 引数エラー | 不正なオプション組み合わせ | usage()表示、終了 |
| 1 | インタフェース不在 | -iで指定したインタフェースが存在しない | xo_errx出力、終了 |
| 1 | ホスト解決失敗 | getaddr()でホスト名解決に失敗 | xo_warnx出力 |
| 1 | NetLink初期化失敗 | netlinkモジュールのロード失敗 | xo_err出力、終了 |
| 1 | ルーティングソケット操作失敗 | rtmsg()でのカーネル通信失敗 | xo_warn出力 |

### リトライ仕様

リトライ機構なし。操作失敗時はエラーを報告して終了する。

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

個別のARP操作はカーネル内でアトミックに処理される。-fオプションによるファイル一括設定は行単位の逐次処理であり、一部の失敗が他の行の処理を妨げない。

## パフォーマンス要件

- 単一ARPエントリの操作は即座に完了する
- 全エントリ表示（-a）はカーネルARPテーブルのサイズに比例

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

- ARPエントリの追加・削除にはroot権限（またはネットワーク管理ケイパビリティ）が必要
- プロキシARP（pub）の設定はネットワークセキュリティに影響するため注意が必要
- ARPスプーフィング対策として静的ARPエントリの設定が可能

## 備考

- FreeBSDのarpコマンドはNetLink対応が追加されており、arp_netlink.cにNetLinkバックエンドの実装がある
- libxo対応により、JSON/XML形式での出力が可能（スクリプト連携に有用）
- ARP_XO_VERSION "1"として構造化出力のバージョン管理を行っている

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | arp.h | `usr.sbin/arp/arp.h` | arp_opts構造体、関数プロトタイプ（NetLink系関数含む） |

**読解のコツ**: `arp_opts`構造体(8-15行目)がコマンドラインオプションの状態を保持するグローバル構造体。`aflag`（全エントリ表示）、`nflag`（名前解決抑止）、`rifname/rifindex`（インタフェースフィルタ）が主要フィールド。NetLink対応関数（print_entries_nl, delete_nl, set_nl）は18-20行目で宣言。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | arp.c | `usr.sbin/arp/arp.c` | main関数（102-209行目） |

**主要処理フロー**:
1. **108行目**: xo_parse_args()でlibxoオプション解析
2. **112-138行目**: getopt()ループで-a, -d, -n, -S, -s, -f, -iオプション解析
3. **144-155行目**: -iオプションのインタフェース名からインデックスへの変換
4. **156-204行目**: switch文で操作種別に応じた関数呼び出し
5. **92-98行目**: F_GET/F_SET/F_FILESET/F_REPLACE/F_DELETE定数定義

#### Step 3: 各操作関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | arp.c | `usr.sbin/arp/arp.c` | get(), set(), delete(), file(), getaddr(), valid_type()関数 |

**主要処理フロー**:
- **215-248行目**: file()関数 - ファイルからの一括ARP設定
- **255-274行目**: getaddr()関数 - ホスト名解決
- **279-296行目**: valid_type()関数 - 有効インタフェースタイプ判定

#### Step 4: NetLinkバックエンドを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | arp_netlink.c | `usr.sbin/arp/arp_netlink.c` | nl_init_socket(), get_link_info(), has_l2(), print_entries_nl(), delete_nl(), set_nl() |

**主要処理フロー**:
- **37-51行目**: nl_init_socket() - NetLinkソケット初期化（モジュール自動ロード対応）
- **53-77行目**: get_link_info() - RTM_GETLINKでリンク情報取得
- **81-92行目**: has_l2() - L2層の有無とインタフェースタイプ検証
- **94-100行目**: get_myfib() - FIB番号取得

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

```
main() [arp.c:102]
    |
    ├─ xo_parse_args() [libxo]
    |
    ├─ [F_GET]
    |   ├─ print_entries() ─── [routing socket経由]
    |   ├─ print_entries_nl() ─── nl_init_socket() [NetLink経由]
    |   └─ get() ─── getaddr() + rtmsg(RTM_GET)
    |
    ├─ [F_SET/F_REPLACE]
    |   ├─ delete() (F_REPLACE時のみ)
    |   ├─ set() ─── getaddr() + set_rtsock() [routing socket]
    |   └─ set_nl() ─── nl_init_socket() [NetLink]
    |
    ├─ [F_DELETE]
    |   ├─ delete() ─── getaddr() + rtmsg(RTM_DELETE)
    |   ├─ delete_nl() ─── nl_init_socket() [NetLink]
    |   └─ nuke_entries() (aflag時)
    |
    └─ [F_FILESET]
        └─ file() ─── set() (行ごと)
```

### データフロー図

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

コマンドライン引数 ──▶ main() 引数解析 ──▶ 操作種別判定
                              |
                    ┌─────────┼──────────┐
                    |         |          |
               get()/set()/delete()  file()
                    |         |          |
          getaddr() ──▶ sockaddr_in 構築
                    |
    ┌───────────────┼───────────────┐
    |               |               |
routing socket   NetLink socket   libxo
 rtmsg()       print_entries_nl() xo_emit()
    |               |               |
カーネルARP      カーネルARP      標準出力
キャッシュ       キャッシュ       (text/JSON/XML)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| arp.c | `usr.sbin/arp/arp.c` | ソース | メインプログラム（引数解析、ルーティングソケット操作） |
| arp.h | `usr.sbin/arp/arp.h` | ヘッダ | arp_opts構造体定義、関数プロトタイプ |
| arp_netlink.c | `usr.sbin/arp/arp_netlink.c` | ソース | NetLinkバックエンド実装 |
| arp.8 | `usr.sbin/arp/arp.8` | マニュアル | manページ |
| arp.4 | `usr.sbin/arp/arp.4` | マニュアル | ARPプロトコルのmanページ |
| Makefile | `usr.sbin/arp/Makefile` | ビルド | ビルド設定 |
