要約

  • RFC 792 の IPv4 Parameter Problem は、破棄という処理結果と説明を分離した。8ビットの Pointer は、元のヘッダー内で異常を検出したオクテットを示す。
  • ICMPv6 は Pointer を32ビットに広げ、異常なフィールド、未知の Next Header、未知のオプションを別のコードにした。位置は長い拡張ヘッダー列の先まで届く。
  • Pointer が返送された引用の外側を示す場合も正しい。精密な数値は、完全な証拠、認証、根本原因、あるいは安全なメモリー参照を意味しない。

捨てられた理由に位置を与える

1981年の RFC 792 が想定したのは、単に宛先へ届かないパケットではない。IPv4 のゲートウェイまたはホストがヘッダーのパラメーターを処理し、続行できないほどの問題を見つけた場合である。データグラムは破棄される。そのうえで送信元へ返せる報告が ICMP Type 12、Parameter Problem だった。

報告の中心は8ビットの Pointer である。Code 0 のとき、値は元の IPv4 ヘッダーで異常を検出したオクテット位置を表す。1なら当時の Type of Service、オプションがあれば20は最初のオプション型を示し得る。オプションの途中を指すことさえある。

この座標によって、送信側は「失敗した」という結果を、自分が生成したバイト列と照合できる。受信側は破棄の判断を保持し、送信側はシリアライザーや設定を直すための手掛かりを受け取る。Pointer は相手の実装を修理する命令ではなく、報告者の解析が止まった場所の主張である。

RFC 792 のエラーには、元の Internet Header とデータ先頭64ビットも入る。初期の TCP/UDP では、この8オクテットにポートが含まれ、該当プロセスとの対応を取りやすかった。引用は誰の通信かを結び付け、Pointer はどこで失敗したかを示す。役割は異なる。

そして ICMP は信頼性保証ではない。RFC 792 自身が、制御メッセージは通信環境のフィードバックであり、すべての破棄に返事が来るわけではないと明記した。応答がないことは受理の証明にならない。

診断にも資源の上限がある

RFC 1122 は1989年、Parameter Problem をホストの実装責任に組み込んだ。元のプロセスを特定できるなら、エラーを上位へ渡す。TCP では報告すべき事象であり、到着しただけで接続全体を必ず中断する命令ではない。上位層は自分の状態と照合して反応を決める。

同じ文書はログの節で、異常パケットのヘッダー情報を十分残す価値と、異常が資源を食い尽くす危険を並べた。診断を豊かにすることと、攻撃者や故障機器へ無制限の仕事を許すことは別である。

1995年の RFC 1812 は IPv4 ルーターの検査を具体化した。無効なパケットは破棄する。条件がそろえば、Internet Header Length や Total Length の位置を Pointer で示せる。ただし同じ失敗位置でも、リンク層での切断、転送中の破損、別の IP バージョン、送信側の不正な生成という複数の原因があり得る。位置は観測事実であって、因果関係の判決ではない。

引用できる元パケットは増えたが、ICMP 全体が IPv4 の最小再構成バッファ576バイトを超えない範囲に限られた。説明は詳しくなっても、エラー応答を無制限に大きくしない原則は残った。

IPv6では固定ヘッダーの先へ

IPv4 のヘッダーはオプション込みでも60バイトまでなので、8ビット Pointer で足りる。IPv6 では40バイトの基本ヘッダーの後ろに拡張ヘッダーが連なり、Next Header を順番にたどる。固定部分だけを指せる座標では、解析の現実を表せない。

RFC 2463 は1998年、ICMPv6 Parameter Problem を Type 4 とし、Pointer を32ビットのオクテットオフセットにした。Code 0 は異常なヘッダーフィールド、Code 1 は未知の Next Header、Code 2 は未知の IPv6 オプションである。RFC 4443 は2006年にこの構造を引き継いだ。

Code 1、Pointer 40 という例は象徴的だ。40バイトの基本ヘッダー直後にある Next Header 値を理解できなかった、という意味になる。値は経由ルーター数でもプロトコル番号でもない。元パケットの先頭から数えた位置である。

RFC 8200 は拡張ヘッダーを出現順に処理する。未知の遷移を飛ばして、後ろにある既知のヘッダーを先に探すことはできない。続行が必要なのに現在の Next Header を解釈できなければ、その値を指して破棄する。オプション型の上位ビットが Code 2 を要求する場合もあるが、その動作ビットの設計は別の論点である。

Pointer が証明するのは、あるノードがその位置まで進んだことだ。後続のヘッダーを検証したとは言わない。最初の停止点より後ろに、別の問題が存在しないとも言わない。

引用が終わっても位置は終わらない

ICMPv6 エラーは、応答全体が IPv6 の最小 MTU を超えない範囲で、原因となったパケットをできるだけ多く含める。長い拡張ヘッダー列では、異常フィールドが引用できる範囲より後ろに来る。

RFC 4443 は Pointer を引用末尾へ丸めない。32ビットの値は、ICMPv6 メッセージに含まれた元パケット部分の外側を指してよい。受信側は停止位置の座標を得るが、その座標の実バイトは今回の応答にはない。

ここに証拠設計の要点がある。誤った末尾位置を返せば別のフィールドを非難する。引用を際限なく延ばせば増幅と資源浪費を招く。規格は「位置は分かる」「該当バイトはここにはない」を同時に保存した。

実装は Pointer を配列添字として無条件に使えない。プロトコル上の座標空間と、手元のバッファ長は別である。RFC 8883 は後に、Pointer を使って引用を読む前に、値が実際のデータ長より小さいことを必ず検証するよう明文化した。

引用が上位プロトコルまで届かなければ、どのプロセスへ通知するか決められないこともある。RFC 4443 は、その場合に IPv6 層の処理後で捨てられる可能性を認める。正確な位置情報があっても、利用者への到達まで保証されない。

構文ではなく処理能力を指す

2020年の RFC 8883 は、Parameter Problem に Code 5〜10 を加えた。中間ノードで未知の Next Header に遭遇した場合、拡張ヘッダーが大きすぎる場合、チェーンが長すぎる場合、ヘッダーやオプションの数が多すぎる場合、個々のオプションが大きすぎる場合を区別する。

このときパケットの構文が壊れているとは限らない。正しく並んでいても、あるノードの解析上限を超えることがある。コードは上限の種類を表し、Pointer は最初に上限を越えたオクテットや項目を示す。

ローカルな容量をパケットの普遍的な不正と混同しないための区別である。別の装置なら処理できるかもしれない。一方、形式が正しいことは、すべての転送装置に無限の解析資源を要求しない。拒否を観測可能にしつつ、誰の限界なのかを残すことが重要になる。

報告は自動的な権限ではない

通常の ICMP エラーは既定で認証されない。RFC 4443 は、送信元の偽装、フィールドの改変、サービス妨害、上位層の反応を悪用する攻撃を挙げる。上位層は、引用されたアドレス、プロトコル、ポート、最近送ったパケットとの一致を確認してから行動すべきである。

エラー生成にはレート制限も必要だ。誤ったパケットの連打に一件ずつ応答すれば、診断機能そのものが負荷になる。マルチキャスト規則、フィルタリング、通常の損失も応答を消す。届いたメッセージは報告者の主張を示すが、届かなかったことは全ノードの成功を示さない。

Parameter Problem の歴史は、失敗を万能な一語にまとめなかった歴史である。破棄という動作、原因コード、停止位置、上限付きの引用。それぞれが別の事実であり、別の限界を持つ。精密さは、限界を隠さないときにだけ診断の力になる。

出典