# 機能設計書 77-dmesgシステムメッセージ

## 概要

本ドキュメントは、FreeBSDのカーネルメッセージバッファ表示コマンド（dmesg）の機能設計について記述する。dmesg(8)はカーネルの環状メッセージバッファの内容を読み出して標準出力に表示するシンプルなユーティリティである。

### 本機能の処理概要

**業務上の目的・背景**：カーネルは起動時および動作中にデバイス検出、ドライバ初期化、エラー状態等の重要なメッセージを環状バッファ（msgbuf）に記録する。管理者がこれらのメッセージを参照して、ハードウェア構成の確認、起動エラーの診断、デバイスドライバの状態確認を行うために、dmesgコマンドが必要である。

**機能の利用シーン**：システム起動後のカーネルメッセージ確認、ハードウェア障害の診断、デバイスドライバの認識状況確認、クラッシュダンプからのカーネルメッセージ抽出。

**主要な処理内容**：
1. sysctl(kern.msgbuf)経由でのカーネルメッセージバッファ読み出し（実行中カーネル）
2. kvm(3)ライブラリ経由でのコアファイルからのメッセージバッファ読み出し
3. syslogファシリティ/プライオリティタグの処理（非カーネルメッセージのフィルタリング）
4. メッセージバッファのクリア機能
5. strvisx(3)による非表示文字の安全な可視化

**関連システム・外部連携**：sysctl(3)インタフェース、kvm(3)ライブラリ（コアダンプ解析用）、msgbufカーネル構造体。

**権限による制御**：通常のメッセージバッファ読み出しは一般ユーザでも可能。メッセージバッファクリア（-c）およびコアファイル読み出し（-M）はroot権限が必要な場合がある。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | （画面なし） | - | コマンドラインツールであり直接的な画面UIを持たない |

## 機能種別

データ参照 / 障害診断

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| -a | フラグ | No | 全ファシリティのメッセージを表示（カーネル以外も含む） | なし |
| -c | フラグ | No | メッセージバッファをクリア | root権限必要 |
| -M | 文字列 | No | コアファイルのパス指定 | 有効なファイルパス |
| -N | 文字列 | No | 名前リストファイル（カーネルシンボル）のパス指定 | 有効なファイルパス |

### 入力データソース

- sysctl kern.msgbuf（実行中カーネルのメッセージバッファ）
- コアファイル（-Mオプション指定時、kvm(3)経由）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| カーネルメッセージ | テキスト | タイムスタンプ付きカーネルログメッセージ |

### 出力先

- 標準出力

## 処理フロー

### 処理シーケンス

```
1. オプション解析
   └─ -a, -c, -M, -N オプションの処理
2. メッセージバッファ取得
   └─ -M未指定: sysctl(kern.msgbuf)で取得
   └─ -M指定: kvm_open/kvm_readでコアファイルから取得
3. バッファクリア（-c指定時）
   └─ sysctl(kern.msgbuf_clear)でバッファクリア
4. メッセージ整形
   └─ 環状バッファのアンラップ（先頭NUL文字のスキップ）
5. ファシリティフィルタリング
   └─ <priority>タグを解析し、-a未指定時はLOG_KERN以外をスキップ
6. 出力
   └─ strvisx(3)で非表示文字を可視化して出力
```

### フローチャート

```mermaid
flowchart TD
    A[dmesg起動] --> B[オプション解析]
    B --> C{-M指定?}
    C -->|No| D[sysctl kern.msgbuf読み出し]
    C -->|Yes| E[kvm_open コアファイルオープン]
    E --> F[kvm_nlist シンボル検索]
    F --> G[kvm_read msgbuf読み出し]
    G --> H[環状バッファアンラップ]
    D --> I{-c指定?}
    I -->|Yes| J[sysctl kern.msgbuf_clear]
    I -->|No| K[バッファ正規化]
    J --> K
    H --> K
    K --> L[先頭NUL文字スキップ]
    L --> M[行ごとのループ処理]
    M --> N{syslogタグあり?}
    N -->|Yes| O{LOG_KERN or -a?}
    O -->|No| P[スキップ]
    O -->|Yes| Q[タグ除去]
    N -->|No| R[strvisx で可視化・出力]
    Q --> R
    P --> M
    R --> M
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-77-01 | カーネルメッセージフィルタ | デフォルトではLOG_KERNファシリティのメッセージのみ表示する | -a未指定時 |
| BR-77-02 | 環状バッファ処理 | メッセージバッファは環状であり、古いデータが先頭に来るようアンラップする | コアファイル読み出し時 |
| BR-77-03 | マジック番号検証 | コアファイルからの読み出し時にMSG_MAGICでmsgbufの整合性を検証する | -M指定時 |
| BR-77-04 | バッファ成長対応 | sysctl呼び出し間にバッファが成長する可能性があるため、25%の余裕を持って確保 | 実行中カーネル読み出し時 |

### 計算ロジック

- バッファ余裕確保: `buflen += buflen/8`（sysctl呼び出し間の成長に対応、dmesg.c 110行目）
- 環状バッファ位置計算: `MSGBUF_SEQ_TO_POS(&cur, cur.msg_wseq)`（dmesg.c 140行目）

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| - | - | - | データベースは使用しない |

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

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 1 | sysctl失敗 | kern.msgbufへのアクセス失敗 | err(1, "sysctl kern.msgbuf") |
| 1 | メモリ割当失敗 | malloc失敗 | errx(1, "malloc failed") |
| 1 | kvm_openエラー | コアファイルのオープン失敗 | エラーメッセージ出力しexit(1) |
| 1 | kvm_nlist失敗 | シンボル検索失敗 | errx(1, "kvm_nlist: ...") |
| 1 | msgbufマジック不一致 | コアファイルのmsgbuf破損 | errx(1, "different magic number") |

### リトライ仕様

リトライは行わない。

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

該当なし。dmesgは読み取り専用の操作（-cによるクリアを除く）。

## パフォーマンス要件

- メッセージバッファ全体を一度にメモリに読み込むため、バッファサイズ分のメモリを消費する（通常数十KB〜数MB）
- strvisx(3)による可視化処理のため、出力バッファは入力の4倍のサイズを確保（dmesg.c 159行目）

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

- カーネルメッセージにはネットワーク設定等のシステム情報が含まれる可能性がある
- -cオプション（バッファクリア）は証拠隠滅に使用される可能性があるため、監査が必要
- strvisx(3)による非表示文字の安全な可視化でターミナルエスケープシーケンス攻撃を防止

## 備考

- dmesgの出力はシステム起動時に/var/run/dmesg.bootにも保存される（RCスクリプト経由）
- メッセージバッファサイズはカーネルのkern.msgbufsizeで設定可能

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | msgbuf.h | `sys/sys/msgbuf.h` | msgbuf構造体（環状メッセージバッファ）、MSG_MAGIC定義、MSGBUF_SEQ_TO_POSマクロを理解する |

**読解のコツ**: msgbufは環状バッファで、msg_wseqが書き込みシーケンス番号、msg_ptrがデータ領域、msg_sizeがバッファサイズを保持する。MSGBUF_SEQ_TO_POSマクロでシーケンス番号からバッファ位置を計算する。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | dmesg.c | `sbin/dmesg/dmesg.c` | main関数の全体フロー（202行の比較的短いプログラム）を通読する |

**主要処理フロー**:
1. **52-56行目**: nlist配列（_msgbufpシンボルのkvm検索用）
2. **60-61行目**: KREADマクロ（kvm_readのラッパー）
3. **64-95行目**: main関数のオプション解析（-a, -c, -M, -N）
4. **100-117行目**: 実行中カーネルからのバッファ取得（sysctlbyname）
5. **107-108行目**: sysctl kern.msgbufでバッファサイズ取得
6. **110行目**: buflen += buflen/8（25%余裕確保）
7. **114-115行目**: sysctl kern.msgbufでバッファ内容取得
8. **118-120行目**: -c指定時のsysctl kern.msgbuf_clearによるクリア
9. **122-148行目**: コアファイルからのバッファ取得（kvm_open/read）
10. **133-134行目**: MSG_MAGIC検証
11. **140-146行目**: 環状バッファのアンラップ処理
12. **155-157行目**: バッファ末尾に改行とNULを追加
13. **159-160行目**: visbp = malloc(4 * buflen + 1)（可視化バッファ確保）
14. **169-173行目**: 先頭NUL文字のスキップ
15. **174-192行目**: 行ごとのループ（syslogタグ解析、ファシリティフィルタ、strvisx出力）
16. **179-188行目**: <priority>タグのパースとLOG_KERNフィルタリング

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

```
dmesg (sbin/dmesg/dmesg.c)
    |
    +-- main()
          |
          +-- [実行中カーネル]
          |     +-- sysctlbyname("kern.msgbuf", NULL, &buflen, ...)  # サイズ取得
          |     +-- malloc(buflen + 2)                                # バッファ確保
          |     +-- sysctlbyname("kern.msgbuf", bp, &buflen, ...)    # データ取得
          |     +-- sysctlbyname("kern.msgbuf_clear", ...)           # クリア (-c)
          |
          +-- [コアファイル]
          |     +-- kvm_open()                     # コアファイルオープン
          |     +-- kvm_nlist()                     # _msgbufpシンボル検索
          |     +-- kvm_read() x3                   # msgbuf構造体、データ読み出し
          |     +-- MSGBUF_SEQ_TO_POS()             # 環状バッファアンラップ
          |
          +-- [出力処理]
                +-- strtol()                        # <priority>タグ解析
                +-- LOG_FAC()                       # ファシリティ抽出
                +-- strvisx()                       # 非表示文字の可視化
                +-- printf()                        # 標準出力
```

### データフロー図

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

kern.msgbuf             sysctlbyname()              標準出力
(カーネルバッファ) ---> バッファ読み出し          --> (カーネルメッセージ)
                         |
                    <priority>タグ解析
                         |
                    ファシリティフィルタ
                    (LOG_KERN以外除外)
                         |
                    strvisx()
                    (非表示文字可視化)

コアファイル (-M)    kvm_open/read              標準出力
                ---> msgbuf読み出し           --> (過去のメッセージ)
                     環状バッファアンラップ
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| dmesg.c | `sbin/dmesg/dmesg.c` | ソース | dmesgコマンドの全処理（202行） |
| msgbuf.h | `sys/sys/msgbuf.h` | ヘッダ | msgbuf構造体、MSG_MAGIC定義 |
| syslog.h | `sys/sys/syslog.h` | ヘッダ | LOG_KERN等のファシリティ定義 |
| dmesg.8 | `sbin/dmesg/dmesg.8` | マニュアル | dmesgコマンドのmanページ |
