Summary

  • PPP calculated its Frame Check Sequence over defined frame fields, not flags, start/stop bits or material inserted for link transparency. The sender stuffed after calculation; the receiver unstuffed before checking.
  • A receiving Async-Control-Character-Map allowed only selected octets below 0x20 to be removed before the check because intervening equipment might insert them. It was a directional, negotiated filter—not permission to ignore arbitrary mutation.
  • Octet stuffing and bit stuffing solved the same framing problem in different representations. A valid FCS remained evidence of error detection over the reconstructed frame, not identity, authentication or proof that the physical path was untouched.

The extra character could be correct

Imagine a serial trace containing a control character that was never part of the packet an endpoint intended to send. A modem, terminal driver or another piece of data communications equipment may have introduced it. If a receiver includes that character in the checksum calculation, a sound packet fails. If it discards every unfamiliar character, corrupted payload can pass unnoticed.

PPP chose neither extreme. It defined a small class of path material that could be reversed before integrity checking. That order made the contract precise. The checksum protected the reconstructed PPP frame. It did not certify every physical signal or every byte visible at every point between the peers.

This is why RFC 1662’s sentence about received ACCM characters matters more than it first appears. Octets selected by the receiving Async-Control-Character-Map are discarded before the FCS is calculated. The exception is not an afterthought. It defines the object being checked.

The checksum came before the disguise

The basic frame begins and ends with a Flag value of 0x7e. Between those flags sit Address, Control, Protocol, Information, optional Padding and the FCS. The FCS defaults to 16 bits; a 32-bit form also exists. Its input includes Address through Padding. It excludes the flags, the FCS field itself, asynchronous start and stop bits, and bits or octets inserted for transparency.

On an octet-stuffed link, the value 0x7d is Control Escape. A sender must at least protect both 0x7e and 0x7d so neither can masquerade as structure while appearing in data. The sequence is decisive: calculate the FCS first, then inspect the frame between the flags. For each required byte, transmit 0x7d followed by the original byte with 0x20 XORed into it. Thus 0x7e travels as 0x7d 0x5e, while 0x7d travels as 0x7d 0x5d.

The receiver reverses the operation before checking. It removes Control Escape and XORs the next octet with 0x20. A Control Escape immediately followed by a Flag does not produce an ordinary byte; it aborts the frame. Reversibility, not resemblance, distinguishes a temporary wire representation from the content whose integrity is being tested.

The word “canonical” is useful here only as editorial shorthand. RFC 1662 does not put a canonicalization field on the wire. It specifies an order of transformations from which one follows: both endpoints calculate over the same reconstructed set of frame fields even when the serial representation contains extra transparency octets.

A map described a direction, not a universal blacklist

ASCII control characters made asynchronous paths awkward. Software flow control could intercept XON at 0x11 or XOFF at 0x13, sometimes without respecting the parity bit. PPP could carry such values by escaping them. It also had to tolerate configured control values inserted on the way.

Each asynchronous endpoint therefore maintained two maps: one for reception and one for transmission. The receiving map is 32 bits, covering values below 0x20. The sending map may be as large as 256 bits. Across two endpoints, that produces four maps, not one global policy.

The LCP ACCM option is type 2, length 6, with a four-octet bitmap. A set bit tells the peer that the corresponding control character must remain mapped when it sends toward the requester. A clear bit says only that mapping is no longer required. The peer may still escape more values because it knows something about its local path that the requester does not.

Authority is deliberately split. A receiver can state the minimum protection its inbound path needs. A sender can be more conservative. A Configure-Nak should propose the union of required sets so that spuriously introduced control characters can be ignored on arrival. Neither side turns the bitmap into a universal rule for unrelated links.

The defaults make the design’s posture visible. An asynchronous receiving map begins with every low control character selected; after negotiation, implementations can narrow the obligation, and mapping every control character is often unnecessary. Other link types default to no mapping. Interoperability begins safely, then local knowledge removes needless overhead.

Bits solved the same problem without an escape byte

Bit-synchronous framing cannot be understood by copying the octet algorithm. It has its own transparency rule. After calculating the FCS, the sender inserts a zero after each run of five consecutive one bits, including runs inside the FCS. Before calculating on reception, the receiver removes that zero. A flag pattern is therefore prevented from appearing accidentally inside the frame.

The two methods share an invariant—transparency is added after the check value is produced and removed before it is verified—but their wire representations differ. An asynchronous-to-synchronous converter owns the translation between them. RFC 1662 even requires a synchronous implementation to acknowledge the ACCM option for converter compatibility while warning that this acknowledgment does not mean the synchronous endpoint itself performs octet mapping.

That is a useful evidence boundary. A negotiated option can be necessary for an intermediate component without describing the code path at the final endpoint. Configuration acceptance is not implementation-location proof.

Not every discarded frame was a checksum failure

PPP also separated malformed framing from a failed FCS. A frame that is too short, ends with a dangling Control Escape before a closing Flag, or violates octet framing is silently discarded and is not counted as an FCS error. On a bit-stuffed link, an invalid run of more than six ones receives the same treatment.

An operator looking only at an FCS counter can therefore miss a framing fault. A capture taken after a driver has removed escape material can look different from a capture taken on the raw serial side. An analyzer applying the wrong ACCM or the wrong stuffing mode can manufacture a checksum failure that the endpoint never saw—or hide the representation in which it occurred.

The minimum useful incident record includes direction, negotiated receiving and sending maps, link mode, FCS form, capture point, decoder stage, invalid-frame counters and the exact raw and reconstructed bytes. “Bad checksum” is a result only after those boundaries are fixed.

Error detection stopped where security had to begin

RFC 1570 allowed Null, 16-bit and 32-bit FCS alternatives by direction, with phase-specific rules. RFC 1662 also noted that NRZI encoding weakened the error properties of the 16-bit FCS and recommended negotiating 32 bits in that case. These provisions adjusted error detection; they did not create authentication.

RFC 1662’s security discussion makes the separation explicit in another way. A link layer may not learn that the underlying switched connection has changed. Insertion or spoofed calling identity can then bypass assumptions made elsewhere. A valid FCS can accompany traffic from the wrong physical continuation because the check answers whether bits agree with a polynomial, not who is entitled to send them.

The historical achievement was narrower and more durable. PPP let endpoints agree on the frame they meant to test while allowing the serial path to require reversible accommodation. It worked because the exclusions were enumerated, directional and small. The moment an implementation treats that exception as a general license to erase inconvenient bytes, it abandons the very integrity boundary the mechanism was designed to preserve.

Sources