# 機能設計書 71-syslogd

## 概要

本ドキュメントは、FreeBSDのシステムログ収集・管理デーモン（syslogd）の機能設計について記述する。syslogdはカーネルおよびユーザ空間のプロセスから送信されるログメッセージを受信し、設定ファイルに基づいてファイル・コンソール・リモートホスト・パイプ等の各種出力先に振り分ける中核的なシステムサービスである。

### 本機能の処理概要

**業務上の目的・背景**：システム運用において、カーネルメッセージ、デーモンの動作状況、セキュリティイベント等のログを一元的に収集・管理することは、障害解析、セキュリティ監査、パフォーマンス監視の基盤として不可欠である。syslogdはBSD系UNIXの伝統的なシステムログデーモンとして、RFC 3164およびRFC 5424に準拠したログ管理機能を提供する。

**機能の利用シーン**：システム起動時にinitプロセスから自動起動され、システム稼働中は常駐してログメッセージを処理する。管理者はsyslog.confでファシリティ・プライオリティに基づくフィルタリングルールを定義し、ログの出力先（ファイル、リモートホスト、コンソール、パイプ、ユーザ端末）を制御する。

**主要な処理内容**：
1. UNIXドメインソケット（/var/run/log）およびUDP/TCPソケット経由でのログメッセージ受信
2. syslog.confに基づくファシリティ・プライオリティによるメッセージフィルタリング
3. プロパティベースフィルタリング（ホスト名、プログラム名、メッセージ内容による条件フィルタ）
4. ファイル、TTY、コンソール、リモートホスト（UDP転送）、パイプ、ユーザ端末への出力
5. RFC 3164（BSDレガシー形式）およびRFC 5424形式でのログフォーマッティング
6. SIGHUP受信時の設定ファイル再読み込み
7. メッセージ重複圧縮（"last message repeated N times"）
8. Capsicumケイパビリティモードによるサンドボックス化

**関連システム・外部連携**：リモートsyslogサーバへのUDP/TCP転送（IPv4/IPv6対応）、libcasperによるCapsicumサンドボックス化、kqueue(2)によるイベント駆動型I/O。

**権限による制御**：syslogdはroot権限で起動後、Capsicumケイパビリティモードに移行してサンドボックス化される。SecureModeにより、リモートからのメッセージ受信を制限可能（-sオプション）。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | （画面なし） | - | syslogdはデーモンプロセスであり、直接的な画面UIを持たない |

## 機能種別

イベント処理 / ログ管理 / データ転送

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| -4 | フラグ | No | IPv4アドレスのみにバインド | -6と排他 |
| -6 | フラグ | No | IPv6アドレスのみにバインド | -4と排他 |
| -8 | フラグ | No | C1文字（0x80-0x9F）を透過する | なし |
| -A | フラグ | No | 転送先メッセージにも日付を付加 | なし |
| -b/p | 文字列 | No | バインドアドレス/パスの指定 | host:service形式 |
| -C | フラグ | No | 設定ファイルの構文チェックのみ | なし |
| -c | フラグ | No | メッセージ重複圧縮の無効化 | なし |
| -d | フラグ | No | デバッグモード | なし |
| -f | 文字列 | No | 設定ファイルパス（デフォルト: /etc/syslog.conf） | ファイルが存在すること |
| -F | フラグ | No | フォアグラウンド実行 | なし |
| -H | フラグ | No | リモートメッセージのホスト名をログに含める | なし |
| -k | フラグ | No | カーネルファシリティを維持 | なし |
| -l | 文字列 | No | 指定パスにUNIXドメインソケットを追加 | なし |
| -m | 整数 | No | マーク間隔（分、デフォルト: 20） | 0以上 |
| -N | フラグ | No | RFC 3164推奨のソースポート非バインド | なし |
| -n | フラグ | No | DNS逆引き無効化 | なし |
| -O | 文字列 | No | 出力フォーマット（bsd, rfc3164, rfc5424） | 有効なフォーマット名 |
| -P | 文字列 | No | PIDファイルパス | なし |
| -S | フラグ | No | 転送先に全アドレスに送信 | なし |
| -s | フラグ | No | セキュアモード（リモート受信無効） | 複数指定でレベル増加 |
| -T | フラグ | No | RFC 3164厳密モード | なし |
| -v | フラグ | No | 詳細出力 | なし |

### 入力データソース

- UNIXドメインソケット: /var/run/log（ローカルプロセスからのログメッセージ）
- UDPソケット: ポート514（リモートホストからのログメッセージ、SecureMode無効時）
- カーネルログ: /dev/klog（カーネルメッセージ）
- 設定ファイル: /etc/syslog.conf（ルーティングルール定義）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| タイムスタンプ | 文字列 | RFC 3164またはRFC 5424形式の日時 |
| ホスト名 | 文字列 | メッセージ送信元ホスト名 |
| ファシリティ | 整数/文字列 | syslogファシリティ（kern, user, mail等） |
| プライオリティ | 整数/文字列 | syslogプライオリティ（emerg, alert, crit等） |
| プログラム名 | 文字列 | メッセージ送信元プログラム名 |
| メッセージ本文 | 文字列 | ログメッセージ内容 |

### 出力先

- ログファイル（/var/log/messages等の設定されたファイルパス）
- コンソール（/dev/console）
- TTYデバイス（ログイン中のユーザ端末）
- リモートホスト（UDP転送）
- パイプ（外部プログラムへの転送）
- ログイン中の全ユーザ（wall機能）

## 処理フロー

### 処理シーケンス

```
1. 初期化処理
   └─ コマンドライン引数解析、設定ファイル読み込み、ソケット作成
2. デーモン化
   └─ fork()によるバックグラウンド化（-Fオプション指定時はフォアグラウンド）
3. Capsicumサンドボックス化
   └─ ケイパビリティモードへの移行、libcasperサービス初期化
4. kqueueイベントループ
   └─ ソケット・シグナルのイベント監視
5. メッセージ受信
   └─ UNIXドメインソケットまたはUDP/TCPソケットからのメッセージ読み取り
6. メッセージ解析
   └─ ファシリティ/プライオリティの抽出、タイムスタンプ解析
7. フィルタリング
   └─ syslog.confルールに基づくマッチング（ファシリティ/プライオリティ/プロパティ）
8. メッセージ出力
   └─ マッチしたルールの出力先へメッセージを書き込み
9. 重複メッセージ圧縮
   └─ 同一メッセージの繰り返しカウントと定期フラッシュ
10. シグナル処理
    └─ SIGHUP: 設定再読み込み、SIGTERM: 終了処理
```

### フローチャート

```mermaid
flowchart TD
    A[syslogd起動] --> B[コマンドライン引数解析]
    B --> C[設定ファイル読み込み]
    C --> D[ソケット作成・バインド]
    D --> E{フォアグラウンド?}
    E -->|No| F[fork してデーモン化]
    E -->|Yes| G[Capsicumサンドボックス化]
    F --> G
    G --> H[kqueueイベントループ]
    H --> I{イベント種別}
    I -->|ソケット受信| J[メッセージ受信・解析]
    I -->|SIGHUP| K[設定ファイル再読み込み]
    I -->|SIGTERM| L[終了処理]
    I -->|タイマー| M[マーク出力・fsync]
    J --> N[ファシリティ/プライオリティフィルタリング]
    N --> O[プロパティベースフィルタリング]
    O --> P[出力先への書き込み]
    P --> Q{重複メッセージ?}
    Q -->|Yes| R[カウント増加]
    Q -->|No| S[メッセージ出力]
    R --> H
    S --> H
    K --> H
    M --> H
    L --> T[ソケットクローズ・終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-71-01 | ファシリティ・プライオリティマッチング | syslog.confで定義されたファシリティとプライオリティの組み合わせに基づきメッセージをフィルタリングする | 全メッセージ受信時 |
| BR-71-02 | セキュアモード | -sオプションのレベルに応じてリモートからのメッセージ受信を制限する。レベル1: リモートUDP無効、レベル2: リモートソケット全無効 | sオプション指定時 |
| BR-71-03 | 重複メッセージ圧縮 | 連続する同一メッセージは最初のメッセージのみ出力し、繰り返し回数を後から出力する | -ccオプション未指定時 |
| BR-71-04 | マーク出力 | 一定間隔（デフォルト20分）でマークメッセージを出力する | MarkInterval > 0 |
| BR-71-05 | includeディレクティブ | syslog.confにincludeディレクティブがある場合、指定ディレクトリの.confファイルを追加読み込みする | include行検出時 |

### 計算ロジック

- プライオリティマスク計算: ファシリティごとにビットマスクとして管理。比較演算子（<, <=, =, >=, >）によるフィルタリングをサポート。
- 重複メッセージ間隔: 30秒、120秒、600秒の段階的バックオフ（repeatinterval配列で定義）。

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| - | - | - | syslogdはデータベースを使用しない。ログはファイルシステムに直接書き込まれる |

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

該当なし。syslogdはデータベースを使用せず、ログメッセージはファイルシステム上のログファイル（/var/log/配下等）に直接書き込まれる。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | ソケットバインド失敗 | 指定ポートが既に使用中、権限不足 | エラーメッセージ出力後、そのソケットをスキップ |
| - | ログファイルオープン失敗 | パーミッション不足、ディスク容量不足 | コンソールにエラーメッセージを出力 |
| - | リモート転送失敗 | ネットワーク到達不能、DNS解決失敗 | エラーログ出力、次回再試行 |
| - | パイプ書き込み失敗 | パイプ先プロセスの異常終了 | プロセスをdeadqueueに登録し、タイムアウト後に再起動 |
| - | 設定ファイル解析エラー | syslog.confの構文エラー | エラーメッセージ出力、該当行をスキップ |

### リトライ仕様

- パイプ先プロセスが異常終了した場合、deadqueueに登録され、DQ_TIMO_INIT（2マーク間隔=40分）後にクリーンアップされる。
- リモート転送先への接続失敗時は、次のメッセージ送信時に再試行される。

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

syslogdはデータベーストランザクションを使用しない。ログファイルへの書き込みは、O_WRONLY|O_APPENDフラグで行われ、FFLAGの設定に応じてfsync()が呼ばれる。定期的なfsync（dofsync関数）によりディスクへの書き込みが保証される。

## パフォーマンス要件

- 受信バッファサイズ: 最小80KB（RCVBUF_MINSIZE）で、ソケットごとに設定
- 最大行長: 8192バイト（MAXLINE）
- kqueue(2)によるイベント駆動型処理で、ポーリングによるCPU消費を回避
- TTYメッセージ送信タイムアウト: 1秒（TTYMSGTIME）
- マーク・フラッシュチェック間隔: 30秒（TIMERINTVL）

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

- Capsicumケイパビリティモードによるプロセスサンドボックス化（WITH_CASPER有効時）
- SecureModeによるリモートメッセージ受信制限（-sオプション）
- UNIXドメインソケットのパーミッション制御（-pオプションのmode指定）
- allowedpeer機構によるリモートログ送信元のアクセス制御
- C1制御文字（0x80-0x9F）のマスキング（デフォルト有効）

## 備考

- syslogdは/etc/syslog.confのincludeディレクティブにより、/etc/syslog.d/*.confの分割設定をサポートする。
- FreeBSD固有の機能として、Capsicum（libcasper）によるサンドボックス化がデフォルトで有効。
- syslog.confの設定構文はRFC 3164に準拠しつつ、プロパティベースフィルタ（:msg,contains,"pattern"形式）等の拡張をサポート。

---

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

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

### 推奨読解順序

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

まず、syslogdの中核データ構造であるfiled構造体とその関連型を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | syslogd.h | `usr.sbin/syslogd/syslogd.h` | filed構造体（ログ出力先の定義）、f_type列挙型（F_FILE, F_FORW, F_PIPE等）、prop_filter構造体（プロパティベースフィルタ）、logtime構造体を理解する |
| 1-2 | pathnames.h | `usr.sbin/syslogd/pathnames.h` | 設定ファイル・PIDファイル・ソケットのパス定義を確認する |

**読解のコツ**: filed構造体はunionを使って出力先タイプごとに異なるフィールドを持つ。f_typeの値に応じてunionのどのメンバが有効かが変わる点に注意。f_pmask配列はファシリティごとのプライオリティマスクを保持し、フィルタリングの核心となる。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | syslogd.c | `usr.sbin/syslogd/syslogd.c` | main関数の引数解析、デーモン化、kqueueイベントループの構造を理解する |

**主要処理フロー**:
1. **79-81行目**: DEFUPRI（デフォルトプライオリティ LOG_USER|LOG_NOTICE）、DEFSPRI（デフォルトセキュアプライオリティ LOG_KERN|LOG_CRIT）の定義
2. **133-136行目**: 設定ファイルパス（ConfFile = _PATH_LOGCONF）、PIDファイルパス、include関連定数の定義
3. **291-331行目**: グローバル変数群（Debug, SecureMode, MarkInterval, family, output_format等）の定義
4. **334-349行目**: 主要関数のプロトタイプ宣言（init, cfline, fprintlog_first等）

#### Step 3: 設定ファイル処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | syslogd.c | `usr.sbin/syslogd/syslogd.c` | readconfigfile関数: syslog.confの解析、cfline関数: 各設定行の解析とfiled構造体への変換、init関数: 設定の初期化と再読み込みを理解する |

#### Step 4: Capsicumサンドボックスを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | syslogd_cap.c | `usr.sbin/syslogd/syslogd_cap.c` | libcasperサービス定義（p_open, readconfigfile, ttymsg, wallmsg）を理解する |
| 4-2 | syslogd_cap.h | `usr.sbin/syslogd/syslogd_cap.h` | Capsicumサービスのインタフェース定義を確認する |
| 4-3 | syslogd_cap_config.c | `usr.sbin/syslogd/syslogd_cap_config.c` | 設定ファイル読み込みのCapsicum対応処理を確認する |
| 4-4 | syslogd_cap_log.c | `usr.sbin/syslogd/syslogd_cap_log.c` | ログ出力のCapsicum対応処理を確認する |

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

```
main()
    |
    +-- コマンドライン引数解析（getopt）
    +-- init(true)                    # 初期設定
    |     +-- readconfigfile()        # syslog.conf読み込み
    |     |     +-- cfline()          # 各行の解析
    |     +-- addsock()               # ソケット作成
    |
    +-- Capsicumサンドボックス化
    |     +-- cap_init() / casper系関数
    |
    +-- kqueueイベントループ
          +-- kevent()                # イベント待機
          |
          +-- socklist->sl_recv()     # メッセージ受信コールバック
          |     +-- logmsg()          # メッセージ処理
          |           +-- fprintlog_first()    # 初回メッセージ出力
          |           +-- fprintlog_successive() # 繰り返しメッセージ出力
          |           +-- fprintlog_write()    # 実際の書き込み
          |
          +-- init(false)             # SIGHUP時の設定再読み込み
          +-- die()                   # SIGTERM時の終了処理
          +-- dofsync()               # 定期的なファイル同期
```

### データフロー図

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

/var/run/log         +--> メッセージ受信              /var/log/messages
(UNIXソケット) ------+    (socklist->sl_recv)          (ファイル)
                     |         |
/dev/klog            |    メッセージ解析              /dev/console
(カーネルログ) ------+    (ファシリティ/プライオリティ)  (コンソール)
                     |         |
UDP:514              |    syslog.confルール            リモートホスト
(リモートホスト) ----+    マッチング                   (UDP転送)
                     |    (filed->f_pmask)
                     |         |                      パイプ先プログラム
syslog.conf --------+    出力先振り分け              (F_PIPE)
(設定ファイル)             (f_type判定)
                                                      ユーザ端末
                                                      (F_USERS/F_WALL)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| syslogd.c | `usr.sbin/syslogd/syslogd.c` | ソース | syslogdのメイン処理（main, init, logmsg, cfline等） |
| syslogd.h | `usr.sbin/syslogd/syslogd.h` | ヘッダ | 中核データ構造定義（filed, logtime, prop_filter等） |
| syslogd_cap.c | `usr.sbin/syslogd/syslogd_cap.c` | ソース | Capsicumサンドボックスのlibcasperサービス定義 |
| syslogd_cap.h | `usr.sbin/syslogd/syslogd_cap.h` | ヘッダ | Capsicumサービスのインタフェース定義 |
| syslogd_cap_config.c | `usr.sbin/syslogd/syslogd_cap_config.c` | ソース | 設定ファイル読み込みのCapsicum対応処理 |
| syslogd_cap_log.c | `usr.sbin/syslogd/syslogd_cap_log.c` | ソース | ログ出力のCapsicum対応処理 |
| pathnames.h | `usr.sbin/syslogd/pathnames.h` | ヘッダ | パス定義（設定ファイル、PIDファイル、ソケット） |
| syslog.conf | `usr.sbin/syslogd/syslog.conf` | 設定 | デフォルトsyslog設定ファイルのサンプル |
| syslog.conf.5 | `usr.sbin/syslogd/syslog.conf.5` | マニュアル | syslog.conf設定ファイルのmanページ |
| syslogd.8 | `usr.sbin/syslogd/syslogd.8` | マニュアル | syslogdコマンドのmanページ |
