# 通知設計書 9-IFNET DETACH

## 概要

本ドキュメントは、FreeBSDカーネルのネットワークスタックにおいて、ネットワークインターフェースがデタッチされた際に発行されるdevctl通知「IFNET <インターフェース名> DETACH」の設計を記述する。

### 本通知の処理概要

ネットワークインターフェースがカーネルから切り離された（デタッチ）際に、devctlサブシステムを通じてユーザランドに通知を送信する処理である。

**業務上の目的・背景**：ネットワークインターフェースがシステムから取り外された際に、ユーザランドのネットワーク管理デーモンがインターフェースの消失を検知する必要がある。これにより、関連するIPアドレスの解放、ルーティングテーブルの更新、DHCPリースの解放、ファイアウォールルールの調整などの自動化が可能になる。

**通知の送信タイミング**：if_detach_internal()関数内で、if_purgeaddrs()とEVENTHANDLER_INVOKE(ifnet_departure_event)の後、if_purgemaddrs()の後にデフォルトVNET内でのみ送信される。

**通知の受信者**：devd(8)デーモンおよび/dev/devctlをモニタリングしているユーザランドプロセスが受信する。

**通知内容の概要**：デタッチされたインターフェースの名前がsubsystemとして通知される。dataはNULL。

**期待されるアクション**：受信したデーモンは、インターフェースに関連するネットワーク設定のクリーンアップ、DHCPクライアントの停止、監視アラートの発行などを実行する。

## 通知種別

カーネル内devctl通知（/dev/devctl経由のユーザランド通知）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 非同期（devctlキューへのエンキュー） |
| 優先度 | 通常 |
| リトライ | なし |

### 送信先決定ロジック

devctl_notify()により全リスナーにブロードキャストされる。

## 通知テンプレート

### devctl通知メッセージ

| 項目 | 内容 |
|-----|------|
| system | `IFNET` |
| subsystem | `<インターフェース名>` (例: "em0", "igb0") |
| type | `DETACH` |
| data | NULL |

### 本文テンプレート

```
!system=IFNET subsystem=<インターフェース名> type=DETACH
```

### 添付ファイル

該当なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| subsystem (インターフェース名) | デタッチされたインターフェースの名前 | ifp->if_xname | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| カーネル内部イベント | if_detach_internal()実行 | IS_DEFAULT_VNET(curvnet) == true | デフォルトVNET内でのみ通知 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| 非デフォルトVNET | jail(8)等で作成された非デフォルトVNETではDETACH通知は発行されない |
| vmoveフラグ | VNET間のインターフェース移動時はvmove==trueとなるが、DETACH通知自体は移動元で発行される |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[ネットワークインターフェース切り離し] --> B[if_detach_internal呼出]
    B --> C[if_purgeaddrs]
    C --> D[EVENTHANDLER_INVOKE ifnet_departure_event]
    D --> E[if_purgemaddrs]
    E --> F{IS_DEFAULT_VNET?}
    F -->|Yes| G[devctl_notify IFNET if_xname DETACH NULL]
    F -->|No| H[通知なし]
    G --> I[後続処理]
    H --> I
```

## データベース参照・更新仕様

### カーネル内データ構造

| データ構造 | 用途 | 備考 |
|-----------|------|------|
| struct ifnet | ネットワークインターフェース | if_xnameからインターフェース名を取得 |

### 更新テーブル一覧

該当なし

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| なし | devctl_notify()は戻り値なし | N/A |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | なし |
| リトライ間隔 | N/A |
| リトライ対象エラー | N/A |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | 制限なし |
| 1日あたり上限 | 制限なし |

### 配信時間帯

制限なし

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

- /dev/devctlへのアクセスにはroot権限が必要
- 通知に含まれるのはインターフェース名のみ
- data引数はNULL

## 備考

- DETACH通知はif_purgeaddrs()とif_purgemaddrs()の後に発行されるため、通知受信時点ではインターフェースのアドレスは既にパージ済み
- EVENTHANDLER_INVOKE(ifnet_departure_event)もDETACH通知の前に呼ばれるため、イベントハンドラからの処理も完了済み
- vmove（VNET間移動）の場合でもDETACH通知は発行されるが、移動先で再度ATTACH通知が発行されるかはVNETの設定に依存する

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | if_var.h | `sys/net/if_var.h` | struct ifnetの定義：if_xnameフィールド |

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | if.c | `sys/net/if.c` | if_detach_internal()関数（行1119-1124付近） |

**主要処理フロー**:
1. **行1120**: if_purgeaddrs(ifp)でアドレスをパージ
2. **行1121**: EVENTHANDLER_INVOKE(ifnet_departure_event, ifp)
3. **行1122**: if_purgemaddrs(ifp)でマルチキャストアドレスをパージ
4. **行1123-1124**: IS_DEFAULT_VNET判定後、devctl_notify("IFNET", ifp->if_xname, "DETACH", NULL)

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

```
[ネットワークドライバ / ifconfig destroy]
    |
    +-- if_detach() / ether_ifdetach() / ...
            |
            +-- if_detach_internal() [sys/net/if.c]
                    |
                    +-- if_purgeaddrs(ifp)
                    +-- EVENTHANDLER_INVOKE(ifnet_departure_event)
                    +-- if_purgemaddrs(ifp)
                    +-- devctl_notify("IFNET", ifp->if_xname, "DETACH", NULL) [行1124]
```

### データフロー図

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

NICドライバのdetach      --->  if_detach_internal()         --->  if_purgeaddrs()
(struct ifnet)                  |                                   if_purgemaddrs()
                                v                                   EVENTHANDLER通知
                          IS_DEFAULT_VNET判定                        |
                                                                    v
                                                              devctl_notify("IFNET",name,"DETACH",NULL)
                                                                    |
                                                                    v
                                                              /dev/devctl
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| if.c | `sys/net/if.c` | ソース | if_detach_internal()でDETACH通知を発行 |
| if_var.h | `sys/net/if_var.h` | ヘッダ | struct ifnetの定義 |
| devctl.h | `sys/sys/devctl.h` | ヘッダ | devctl_notify()のプロトタイプ |
| subr_bus.c | `sys/kern/subr_bus.c` | ソース | devctl_notify()の実装 |
