要約

  • PPPのFCSはAddressからPaddingまでの定義済みフィールドを対象とし、Flag、FCS自身、非同期の開始・停止ビット、透過化のために挿入された材料は対象外とした。送信は計算後にstuffingし、受信は検査前に元へ戻す。
  • 受信ACCMによって除去できるのは、経路上の機器が挿入し得る0x20未満の選択済み制御文字だけである。これは方向別の狭い契約であり、任意の変更を無視する権限ではない。
  • octet stuffingとbit stuffingは表現が異なる。良好なFCSが示すのは復元されたフレームの誤り検出であって、相手の身元、認証、物理経路の無変更ではない。

回線にあったものと、フレームに属するもの

受信したシリアル列に、送信端末が載せていない制御文字が一つ混じっていたとする。モデムや端末ドライバーなどの通信装置が途中で挿入した可能性がある。その文字までFCSに含めれば、正しいフレームが不正になる。逆に、都合の悪い文字を何でも捨てれば、payloadの破損を隠せてしまう。

RFC 1662は除外範囲を小さく固定した。受信ACCMで指定され、かつ0x20未満であるoctetはFCS計算前に取り除く。Control Escapeによる表現も同じく元へ戻す。検査対象は経路上の全ての現象ではなく、合意された手順から再構成されたPPPフレームである。

ここで「正規化」という言葉を使うなら、それは編集上の説明にすぎない。RFCにその名のフィールドはない。重要なのは、どの変換をいつ実行するかが列挙されていることだ。

検査値を作ってから、経路用の姿に変える

HDLC-likeフレームは0x7eのFlagで区切られる。その内側にAddress、Control、Protocol、Information、必要ならPadding、そしてFCSがある。標準は16 bitで、32 bitの形式も定義された。FCSはAddressからPaddingまでを計算するが、Flag、FCS欄、開始・停止bit、透過化の挿入物は含めない。

octet-stuffedリンクでは0x7dがControl Escapeになる。送信側は少なくとも0x7eと0x7dをescapeしなければならない。先にFCSを計算し、その後でFlag間を走査する。対象octetは0x7dと、元の値に0x20をXORしたoctetの二つに置き換わる。0x7eは0x7d 0x5eに、0x7dは0x7d 0x5dになる。

受信側は逆順に処理する。FCSを調べる前にControl Escapeを外し、次のoctetに0x20をXORする。ただしEscapeの直後がFlagならフレームは中止であり、通常のデータとして復元してはならない。透過化が安全に消せるのは、変換が明示的かつ可逆だからである。

ACCMは一方向の最低条件を伝える

非同期回線ではASCII制御文字が経路の都合と衝突した。software flow controlがXONの0x11やXOFFの0x13を捕まえ、最上位のparity bitを無視する機器も想定された。PPPはそれらをescapeして通す一方、途中で挿入されたと判断できる設定済みの低位制御文字を受信時に外せるようにした。

各非同期端点は受信用と送信用の二つのACCMを持つ。受信用は0x20未満を表す32 bit、送信用は最大256 bitである。両端を合わせれば四つのmapが存在する。一つの世界共通blacklistではない。

LCP option type 2は長さ6で、四octetのbitmapを持つ。bitが1なら、peerはその方向へ送る際に該当制御文字を必ずmapped formのままにする。0なら「mapしなくてもよい」という意味であり、escapeを禁止するわけではない。peerは自身が知る経路制約のため、さらに多くの値をmapしてよい。

受信側は自分へ向かう経路の最低条件を述べ、送信側はより保守的に振る舞える。Configure-Nakは必要集合の論理和を提案し、途中で余計な制御文字が入った場合に受信側が無視できるようにする。権限を方向と経路に閉じ込める設計だった。

同期リンクではbyteではなくbitを足した

bit-synchronousリンクは0x7dを使わない。送信側はFCS計算後、連続する五つの1の後に0を挿入する。FCS内部の並びも対象である。受信側はFCS計算前にその0を外すため、フレーム内部が偶然Flag列に見えることを防げる。

二つの方式の共通点は処理順であって、wire imageではない。非同期・同期変換器がstuffing形式の変換を担当する。RFC 1662はconverterとの互換性のため同期実装にもACCM optionのAckを要求するが、そのAckは同期端点自身がoctet mappingを実行する証明ではないと明記する。

設定の受理と、処理を行った場所は別の証拠である。中間装置が契約を必要とする場合、端点のoption stateだけから実装位置を推定できない。

捨てられたフレームが全てFCS errorとは限らない

必要な長さに満たないフレーム、closing Flag直前でControl Escapeが宙に残ったフレーム、octet framingに違反したフレームはsilent discardされ、FCS errorには数えられない。bit-stuffedリンクで六つを超える1が続く場合も同様である。

したがってFCS counterだけを監視すると、framing faultを見落とす。driverがescapeを除いた後のcaptureと、raw serial側のcaptureは同じ証拠ではない。誤ったACCMやstuffing modeで外部解析を行えば、端点には存在しなかった「bad checksum」を作り出せる。

調査記録には、方向、送受信ACCM、link mode、FCS形式、capture位置、decode段階、invalid-frame counter、raw bytesと復元後bytesを含める必要がある。それらを固定して初めて、FCS失敗は原因分析に使える。

誤り検出はsecurityの代用品ではない

RFC 1570はNull、16 bit、32 bitのFCS alternativeを方向別に定義し、適用phaseも制限した。RFC 1662はNRZIで16 bit FCSの検出特性が弱くなるため32 bitを推奨する。いずれもerror detectionの調整であり、認証を追加するものではない。

RFC 1662のSecurity Considerationsは、link layerが下位の交換接続変更を知らない場合があり、挿入やcalling identityのspoofingが別の信頼仮定を破り得ると警告する。正しいFCSを持つフレームでも、期待した相手から来たとは限らない。多項式はbit列を検査するが、発信権限を検査しない。

PPPの成果は、例外を広げたことではなく狭くしたことにある。経路への適応を列挙可能で方向別の操作に留め、検査対象を共有できるようにした。実装がこの仕組みを「不都合なbyteを削除する一般権限」と読んだ瞬間、守るべきフレームそのものが曖昧になる。

Sources