RFC 1171

Point-to-Point Protocol for the transmission of multi-protocol datagrams over Point-to-Point links

๐Ÿ“… published July 1990, from ietf

okay bestie, this is the RFC that gave us PPP, the thing that lets your computer talk over a plain serial line ๐Ÿฆ‹ Here's the title-block tea:

  • Who wrote it: D. Perkins, from CMU ๐ŸŽ€
  • Stream: Network Working Group
  • Category: an IAB standards track protocol for the Internet community ๐Ÿ‘‘
  • Date: July 1990 ๐Ÿ“…
  • Obsoletes: RFC 1134 ๐Ÿ’…
  • Updates: nothing listed in the header

Status of this Memo โœจ

So this doc is an IAB standards track protocol, which means it's meant to be the real deal for the Internet community ๐Ÿ’œ

If you want the current standardization state and status, go check the current edition of the "IAB Official Protocol Standards" ๐ŸŒˆ

This proposal came out of the Point-to-Point Protocol Working Group of the Internet Engineering Task Force (IETF) ๐Ÿงš If you have comments, send them to the IETF Point-to-Point Protocol Working Group chair ๐Ÿ’Œ

And the best part: distribution of this memo is unlimited ๐Ÿซถ

Abstract ๐ŸŒธ

Okay, so the Point-to-Point Protocol (PPP) is how you send datagrams over serial point-to-point links ๐Ÿ”ฅ It has three parts:

  1. A method for encapsulating datagrams over serial links.
  2. An extensible Link Control Protocol (LCP).
  3. A family of Network Control Protocols (NCP) for establishing and configuring different network-layer protocols.

This document defines the encapsulation scheme, the basic LCP, and an NCP for setting up and configuring the Internet Protocol (IP), which is called the IP Control Protocol (IPCP) ๐Ÿฆ‹

The options and facilities used by the LCP and the IPCP get their own separate docs ๐Ÿ“„ And other network-layer protocols (like DECNET or OSI) get their own control protocols too, developed as needed โœจ

Table of Contents ๐ŸŽ€

     1.     Introduction ..........................................    1
        1.1       Motivation ......................................    1
        1.2       Overview of PPP .................................    1
        1.3       Organization of the document ....................    2

     2.     Physical Layer Requirements ...........................    3

     3.     The Data Link Layer ...................................    4
        3.1       Frame Format ....................................    5

     4.     The PPP Link Control Protocol (LCP) ...................    9
        4.1       The LCP Automaton ...............................   11
           4.1.1  Overview ........................................   11
           4.1.2  State Diagram ...................................   11
           4.1.3  State Transition Table ..........................   13
           4.1.4  Events ..........................................   13
           4.1.5  Actions .........................................   16
           4.1.6  States ..........................................   17
        4.2       Loop Avoidance ..................................   20
        4.3       Timers and Counters .............................   20
        4.4       Packet Format ...................................   21
           4.4.1  Configure-Request ...............................   23
           4.4.2  Configure-Ack ...................................   24
           4.4.3  Configure-Nak ...................................   25
           4.4.4  Configure-Reject ................................   27
           4.4.5  Terminate-Request and Terminate-Ack .............   29
           4.4.6  Code-Reject .....................................   31
           4.4.7  Protocol-Reject .................................   32
           4.4.8  Echo-Request and Echo-Reply .....................   34
           4.4.9  Discard-Request .................................   36
        4.5       Configuration Options ...........................   38
           4.5.1  Format ..........................................   39

     5.     A PPP Network Control Protocol (NCP) for IP ...........   40
        5.1       Sending IP Datagrams ............................   40

     APPENDICES ...................................................   42

     A.     Asynchronous HDLC .....................................   42

     B.     Fast Frame Check Sequence (FCS) Implementation ........   44
        B.1       FCS Computation Method ..........................   44
        B.2       Fast FCS table generator ........................   46

     REFERENCES ...................................................   47
     SECURITY CONSIDERATIONS ......................................   48

     CHAIRMAN'S ADDRESS ...........................................   48

1. Introduction ๐ŸŒˆ

1.1. Motivation ๐Ÿ’…

Over the last few years, the Internet blew up in the number of hosts running TCP/IP ๐Ÿ“ˆ Most of those hosts sit on Local Area Networks (LANs) of various types, with Ethernet being the most common one ๐Ÿงš Most of the rest hang off Wide Area Networks (WANs) like X.25 style Public Data Networks (PDNs) ๐ŸŒ Only a few hosts connect with simple point-to-point (i.e., serial) links, which is kind of wild because point-to-point links are some of the oldest ways to do data communications and almost every host supports them ๐Ÿ™ˆ Asynchronous RS-232-C [1] interfaces are basically everywhere, for example ๐Ÿ“

One reason there are so few point-to-point IP links is that there's no standard encapsulation protocol. There are loads of non-standard ones (and at least one de facto standard), but none has been agreed on as an Internet Standard ๐Ÿ˜ญ LANs already have standard encapsulation schemes for sending datagrams, so this gap really stands out โœจ

This memo is here to fix that. But even more importantly, PPP does more than just encapsulation ๐Ÿ’– Point-to-point links make a lot of existing network protocol problems worse ๐Ÿ’€ For example, assigning and managing IP addresses is a headache on LANs too, but it's especially painful over circuit switched point-to-point circuits (like dialups) ๐Ÿ˜ค

PPP also covers asynchronous (start/stop) and bit-oriented synchronous encapsulation, network protocol multiplexing, link configuration, link quality testing, error detection, and option negotiation. That negotiation includes stuff like network-layer address negotiation and data compression negotiation ๐Ÿ”ฅ

So how does PPP handle all of this? It gives you an extensible Link Control Protocol (LCP) and a family of Network Control Protocols (NCP) to negotiate optional configuration parameters and facilities. Iconic behavior, honestly ๐Ÿ‘‘

1.2. Overview of PPP ๐Ÿฆ‹

PPP has three main components:

  1. A method for encapsulating datagrams over serial links. PPP uses HDLC as a basis for encapsulating datagrams over point-to-point links. Right now, PPP specifies the use of asynchronous or synchronous duplex circuits, either dedicated or circuit switched.
  2. An extensible Link Control Protocol (LCP) to establish, configure, and test the data-link connection.
  3. A family of Network Control Protocols (NCP) for establishing and configuring different network-layer protocols. PPP is designed to let you use multiple network-layer protocols at the same time ๐ŸŒธ

Here's the flow. To set up communications over a point-to-point link, the originating PPP first sends LCP packets to configure and test the data link ๐Ÿงš Once the link is up and any optional facilities are negotiated (as LCP needs), the originating PPP sends NCP packets to choose and configure one or more network-layer protocols ๐Ÿ’œ After each chosen protocol is configured, its datagrams can start flowing over the link ๐ŸŽ€

The link stays configured until explicit LCP or NCP packets close it down, or until some external event happens, like an inactivity timer expiring or a user intervening ๐Ÿ™ˆ

1.3. Organization of the document ๐Ÿ“š

This memo is split into several sections. Section 2 covers the physical-layer requirements of PPP ๐Ÿ“ Section 3 describes the Data Link Layer, including the PPP frame format and the data link encapsulation scheme ๐Ÿ’… Section 4 specifies the LCP, including connection establishment and option negotiation procedures โœจ Section 5 specifies the IP Control Protocol (IPCP), which is the NCP for the Internet Protocol, and describes how IP datagrams get encapsulated inside PPP packets ๐Ÿฆ‹ Appendix A summarizes the important features of asynchronous HDLC, and Appendix B describes an efficient table-lookup algorithm for fast Frame Check Sequence (FCS) computation ๐ŸŒˆ

2. Physical Layer Requirements ๐Ÿ”Œ

PPP can run across any DTE/DCE interface, like EIA RS-232-C, EIA RS-422, EIA RS-423, and CCITT V.35 ๐Ÿ’– The only absolute requirement PPP puts on the hardware is a duplex circuit, either dedicated or circuit switched ๐Ÿ”ฅ That circuit can run in either asynchronous (start/stop) or synchronous bit-serial mode, as long as it's transparent to PPP Data Link Layer frames ๐Ÿ‘‘ PPP doesn't put any limits on transmission rate, other than whatever the particular DTE/DCE interface in use already imposes ๐Ÿงš

PPP doesn't require modem control signals like Request To Send (RTS), Clear To Send (CTS), Data Carrier Detect (DCD), and Data Terminal Ready (DTR) ๐ŸŒธ That said, using those signals when they're available can unlock more functionality and performance โœจ

PPP borrows the principles, terminology, and frame structure of the International Organization For Standardization's (ISO) High-level Data Link Control (HDLC) procedures (ISO 3309-1979 [2]) ๐Ÿ’… It also adopts the changes from ISO 3309:1984/PDAD1 "Addendum 1: Start/stop transmission" [5] ๐Ÿฆ‹ ISO 3309-1979 defines the HDLC frame structure for synchronous environments, and ISO 3309:1984/PDAD1 proposes changes so it can work in asynchronous environments too ๐ŸŒˆ

PPP's control procedures use the definitions and Control field encodings standardized in ISO 4335-1979 [3] and ISO 4335-1979/Addendum 1-1979 [4] ๐Ÿ’œ The PPP frame structure also matches CCITT Recommendation X.25 LAPB [6], since that's based on HDLC too ๐Ÿงš

Note: ISO 3309:1984/PDAD1 is still a Proposed Draft standard. Right now it seems stable and likely to become an International Standard, so the authors feel comfy using it before it's officially one ๐Ÿ’– The Internet community should track and encourage this proposal as it moves along ๐Ÿ‘‘

This memo isn't trying to re-document what's already standardized in ISO 3309 ๐Ÿ™ˆ We assume you already know HDLC or can get a copy of [2] or [6] ๐Ÿ“„ Instead, this paper gives a concise summary and points out the specific options and features PPP uses ๐ŸŒธ Since "Addendum 1: Start/stop transmission" isn't standardized or widely available yet, it gets summarized in Appendix A ๐Ÿ“

3.1. Frame Format

okay bestie, here's the PPP frame layout ๐ŸŽ€ the fields go left to right, no cap:

           +----------+----------+----------+----------+------------
           |   Flag   | Address  | Control  | Protocol | Information
           | 01111110 | 11111111 | 00000011 | 16 bits  |      *
           +----------+----------+----------+----------+------------
                   ---+---------+----------+
                      |   FCS   |   Flag   |
                      | 16 bits | 01111110 |
                   ---+---------+----------+

so the diagram doesn't show the start/stop bits (for async links) or any bits or octets that get stuffed in for transparency ๐Ÿซถ when async links are used, every octet goes out with one start bit, eight data bits, and one stop bit. and ngl, neither PPP nor ISO 3309:1984/PDAD1 has any provision for seven-bit async links. not on my watch ๐Ÿ’…

Bit order time! ๐ŸŒธ to match normal Internet practice and not confuse anyone who's used to reading RFCs, all binary numbers here are written Most Significant Bit to Least Significant Bit, left to right, unless it says otherwise. this is literally the opposite of ISO and CCITT, which order bits as they're transmitted (aka network bit order). so keep that in mind when you compare this doc with the international standards docs ๐Ÿ‘€

Flag Sequence

The Flag Sequence is one octet and marks the beginning or end of a frame โœจ it's the binary sequence 01111110 (hex 0x7e). iconic.

Address Field

The Address field is one octet and holds 11111111 (hex 0xff), the All-Stations address ๐Ÿงš PPP doesn't assign individual station addresses, so there's no "my own personal address" situation here. the All-Stations address should always be recognized and received. other address lengths and values may be defined later, or by prior agreement. and frames with unrecognized Addresses should be reported through the normal network management facility ๐Ÿ“‹

Control Field

The Control field is one octet and holds 00000011 (hex 0x03), which is the Unnumbered Information (UI) command with the P/F bit set to zero ๐ŸŒˆ frames with any other Control field value should be silently discarded. ghosted, no notes ๐Ÿ’€

Protocol Field

The Protocol field is two octets, and its value tells you which protocol is encapsulated in the Information field ๐Ÿฆ‹ the most up-to-date values live in the most recent "Assigned Numbers" RFC [12]. the initial values are listed below too, so you're not left hanging.

Protocol field values in the "cxxx" range identify datagrams belonging to the Link Control Protocol (LCP) or its associated protocols. values in the "8xxx" range are the family of Network Control Protocols (NCP) ๐Ÿ‘‘ and values in the "0xxx" range are the network protocol of specific datagrams.

okay the drama: this Protocol field is defined by PPP and is NOT a field defined by HDLC. however, it's consistent with the ISO 3309 extension mechanism for Address fields ๐ŸŽ€ All Protocols MUST be odd; the least significant bit of the least significant octet MUST equal "1". also, all Protocols MUST be assigned such that the least significant bit of the most significant octet equals "0". frames that don't follow these rules should be considered as having an unrecognized Protocol, and should be handled as specified by the LCP. the Protocol field is transmitted and received most significant octet first ๐Ÿ’–

the initial assignments:

   Value (in hex)          Protocol

   0001 to 001f            reserved (transparency inefficient)
   0021                    Internet Protocol
   0023                  * OSI Network Layer
   0025                  * Xerox NS IDP
   0027                  * DECnet Phase IV
   0029                  * Appletalk
   002b                  * Novell IPX
   002d                  * Van Jacobson Compressed TCP/IP 1
   002f                  * Van Jacobson Compressed TCP/IP 2

   8021                    Internet Protocol Control Protocol
   8023                  * OSI Network Layer Control Protocol
   8025                  * Xerox NS IDP Control Protocol
   8027                  * DECnet Phase IV Control Protocol
   8029                  * Appletalk Control Protocol
   802b                  * Novell IPX Control Protocol
   802d                  * Reserved
   802f                  * Reserved

   c021                    Link Control Protocol
   c023                  * User/Password Authentication Protocol

      * Reserved for future use; not described in this document.

Information Field

The Information field is zero or more octets ๐Ÿ“ it holds the datagram for whichever protocol is named in the Protocol field. you find the end of the Information field by locating the closing Flag Sequence and then allowing two octets for the Frame Check Sequence field. the default maximum length is 1500 octets, but consenting PPP implementations can agree on other values by prior agreement ๐Ÿค

on transmission, the Information field may be padded with any number of octets, up to the max length. and it's each protocol's job to tell padding octets apart from real information ๐Ÿ™ˆ

Frame Check Sequence (FCS) Field

The Frame Check Sequence field is normally 16 bits (two octets) โœจ consenting PPP implementations may agree to use a 32-bit (four-octet) FCS for better error detection, by prior agreement.

the FCS is calculated over all bits of the Address, Control, Protocol and Information fields. it doesn't include start and stop bits (async), or any bits (sync) or octets (async) inserted for transparency. it also doesn't include the Flag Sequences or the FCS field itself. and the FCS is transmitted with the coefficient of the highest term first ๐Ÿงฎ

for more on the FCS spec, check ISO 3309 or CCITT X.25 ๐Ÿ“š

Note: a fast, table-driven implementation of the 16-bit FCS algorithm is shown in Appendix B. it's based on [7], [8], and [9]. the people who built it are actually geniuses ๐Ÿซถ

Modifications to the Basic Frame Format

The Link Control Protocol can negotiate changes to the standard PPP frame structure ๐ŸŒธ however, modified frames will always be clearly distinguishable from standard frames. no one gets confused about which frame is which. โœจ


okay this is the main character of PPP ๐Ÿ‘‘ the Link Control Protocol (LCP) is how you establish, configure, maintain, and terminate the point-to-point connection. LCP goes through four distinct phases, so let's go ๐Ÿฆ‹

before any network-layer datagrams (like IP) can get exchanged, LCP has to open the connection first through an exchange of Configure packets ๐ŸŽ€ this exchange is complete, and the Open state is entered, once a Configure-Ack packet (described below) has been both sent and received. and any non-LCP packets that show up before this is done get silently discarded. bye ๐Ÿ’€

it's really important to know that LCP handles configuration of the link only. it does NOT handle configuration of individual network-layer protocols ๐Ÿงš all Configuration Parameters that don't depend on a particular network-layer protocol get configured by LCP. all Configuration Options are assumed to be at default values unless the configuration exchange changes them.

LCP allows an optional Link Quality Determination phase after it moves into the LCP Open state ๐ŸŒˆ in this phase, the link gets tested to see if its quality is good enough to bring up network-layer protocols. this phase is completely optional. LCP may delay sending network-layer protocol info until this phase is done.

the procedure for Link Quality Determination is unspecified. it can vary between implementations or because of user-configured parameters, but only as long as it doesn't violate other parts of LCP. one suggested method is to use LCP Echo-Request and Echo-Reply packets ๐Ÿ”ฅ

here's the vibe check: this phase may last for any length of time ๐Ÿ˜ญ so implementations should avoid fixed timeouts when they're waiting for their peers to move on to phase 3. patience is a virtue, bestie ๐ŸŒธ

Phase 3: Network-Layer Protocol Configuration Negotiation

once LCP finishes the Link Quality Determination phase, the network-layer protocols can get configured separately by the appropriate Network Control Protocols (NCP) โญ they may be brought up and taken down at any time. and if LCP closes the link, it lets the network-layer protocols know so they can take appropriate action ๐Ÿซถ

LCP may terminate the link at any time ๐Ÿ’… this usually happens at the request of a human user, but it can also happen because of a physical event, like loss of carrier, or the expiry of an idle-period timer.


4.1. The LCP Automaton

4.1.1. Overview

okay so LCP is specified by a bunch of packet formats plus a finite-state automaton ๐Ÿง  this section gives you an overview of the LCP automaton, then shows it as both a state diagram and a state transition table. it's giving organized ๐ŸŽ€

there are three classes of LCP packets:

  1. Link Establishment packets, used to establish and configure a link (e.g., Configure-Request, Configure-Ack, Configure-Nak and Configure-Reject)
  2. Link Termination packets, used to terminate a link (e.g., Terminate-Request and Terminate-Ack)
  3. Link Maintenance packets, used to manage and debug a link (e.g., Code-Reject, Protocol-Reject, Echo-Request, Echo-Reply and Discard-Request)

the finite-state automaton is defined by events, state transitions, and actions โœจ events include things like receiving external commands such as Open and Close, the Restart timer expiring, and receiving packets from an LCP peer. actions include starting the Restart timer and sending packets. literally the whole plot in one sentence ๐Ÿ’–

4.1.2. State Diagram โœจ

okay so this section is the big picture ๐Ÿฆ‹ The state diagram shows the whole sequence of events for agreeing on Configuration Options (aka opening the PPP connection) and then closing it later ๐Ÿ’… The machine starts out in the Closed state (1). Once it hits the Open state (6), both ends have sent AND received a Configure-Ack packet, and that's the moment the link is officially ready ๐ŸŽ€

Events go above the horizontal lines and actions go below them ๐ŸŒธ Configure-Naks and Configure-Rejects look the same in this diagram, even though they really do serve different (but similar!) jobs ๐Ÿ™ˆ At this level of detail they always cause the same transition, so the diagram doesn't bother splitting them up ๐Ÿ’œ

Real talk though: if you're actually implementing this, go to the state transition table in the next section instead of this diagram ๐Ÿซถ It's the more detailed spec, and it's the one you should follow ๐Ÿ”ฅ

                                    +------------------------------+
                                    |                              |
                                    V                              |
        +---2---+           PO +---1---+        RTA +---7---+      |
        |       |<-------------|       |<-----------|       |      |
        |Listen |              |Closed |            |Closing|      |
    RCR |       | C            |       | PLD        |       |      |
   +----|       |----->+------>|       |<---Any     |       |<--+  |
   |scr +-------+      ^       +-------+    State   +-------+   |  |
   |                   |     AO  |   ^                    | TO  |  |
   |       +-----------+     --- |   |                    +---->+  |
   |       |                 SCR |   |                      str ^  |
   |   C   |   RCN/TO            |   | C                        |  |
   |   --- | +-------->+<--------+   | ---                      |  |
   |       | | scr     |             |                          |  |
   |    +---3---+      V   TO  +---4---+            +-------+   |  |
   |    |       |<-----+<------|       |<-----------|       |   |  |
   |    | Req-  |          scr | Ack-  |        scn | Good  |   |  |
   |    | Sent  | RCA          | Rcvd  | RCR        | Req?  |   |  |
   |    |       |------------->|       |----------->|       |   |  |
   |    +-------+              +-------+            +-------+   |  |
   |       | ^                                         |        |  |
   |   RCR | +<--------+                               |        |  |
   |   --- | |         |     TO        RCN         --- |        |  |
   |       | | ---     +---------+   +-----+       sca |        |  |
   |       V | scn           scr |   | scr |           V        |  |
   |    +-------+              +---5---+   |        +---6---+ C |  |
   +--->|       |------------->|       |<--+        |       |---+  |
        | Good  | sca          | Ack-  |            | Open  | str  |
        | Req?  |          RCR | Sent  | RCA        |       |      |
        |       |<-------------|       |----------->|       |      |
        +-------+              +-------+            +-------+      |
              ^                                       |   |        |
              |                                   RCR |   | RTR    |
              +---------------------------------------+   +--------+
                                                  scr       sta

   Events                                  Actions

   RCR - Receive-Configure-Request         scr - Send Configure-Request
   RCA - Receive-Configure-Ack             sca - Send Configure-Ack
   RCN - Receive-Configure-Nak or Reject   scn - Send Configure-Nak
   RTR - Receive-Terminate-Req                    or Reject
   RTA - Receive-Terminate-Ack             str - Send Terminate-Req
   AO  - Active-Open                       sta - Sent Terminate-Ack
   PO  - Passive-Open
   C   - Close
   TO  - Timeout
   PLD - Physical-Layer-Down

4.1.3. State Transition Table ๐Ÿ’–

the complete state transition table is here, and it's the real deal ๐Ÿ“ States go across the top (horizontally) and events go down the side (vertically) โœจ Each entry is written as action/new-state, and if one event triggers two actions, they're joined with an & like action1&action2 ๐Ÿงš

         | State
         |   1       2        3        4        5        6        7
   Events| Closed  Listen  Req-Sent Ack-Rcvd Ack-Sent  Open    Closing
   ------+-------------------------------------------------------------
     AO  | scr/3   scr/3      3        4        5        6      scr/3
     PO  |   2       2        2*       4        5        6      sta/3*
     C   |   1       1        1*       1      str/7    str/7      7
     TO  |   1       2      scr/3    scr/3    scr/3      6      str/7*
    PLD  |   1       1        1        1        1        1        1
    RCR+ | sta/1 scr&sca/5  sca/5    sca/6    sca/5  scr&sca/5    7
    RCR- | sta/1 scr&scn/3  scn/3    scn/4    scn/3  scr&scn/3    7
    RCA  | sta/1   sta/2      4      scr/3      6      scr/3      7
    RCN  | sta/1   sta/2    scr/3    scr/3    scr/5    scr/3      7
    RTR  | sta/1   sta/2    sta/3    sta/3    sta/3    sta/1    sta/7
    RTA  |   1       2        3        3        3        1        1
    RCJ  |   1       2        1        1        1        1        1
    RUC  | scj/1   scj/2    scj/1    scj/1    scj/1    scj/1  1 scj/7
    RER  | sta/1   sta/2      3        4        5      ser/6      7

   Notes:
       RCR+ - Receive-Configure-Request (Good)
       RCR- - Receive-Configure-Request (Bad)
       RCJ  - Receive-Code-Reject
       RUC  - Receive-Unknown-Code
       RER  - Receive-Echo-Request
       scj  - Send-Code-Reject
       ser  - Send-Echo-Reply
        *   - Special attention necessary, see detailed text

4.1.4. Events ๐ŸŒˆ

transitions and actions in the LCP state machine are kicked off by events ๐Ÿ”ฅ Some come from commands run on the local end (like Active-Open, Passive-Open, and Close) ๐ŸŽ€ Others come from packets arriving from the remote end (like Receive-Configure-Request, Receive-Configure-Ack, Receive-Configure-Nak, Receive-Terminate-Request, and Receive-Terminate-Ack) ๐Ÿ’Œ And some are caused by the Restart timer running out, which was started by some other event (that's Timeout!) โฐ

here's the full list of LCP events, bestie ๐Ÿ’…

Active-Open (AO) ๐ŸŒธ

the Active-Open event means the local network administrator (human or program) ran an Active-Open command ๐Ÿฆ‹ When that happens, LCP should immediately try to open the connection by swapping configuration packets with its LCP peer โœจ

Passive-Open (PO) ๐Ÿงš

Passive-Open is kind of like Active-Open, but with a twist ๐Ÿ™ƒ Instead of jumping right into swapping configuration packets, LCP waits for the peer to send the first packet ๐Ÿ‘€ That only happens after the LCP peer has done an Active-Open event ๐Ÿ’œ

Close (C) ๐Ÿšช

the Close event means the local end ran a Close command ๐Ÿซถ When that happens, LCP should immediately try to close the connection ๐Ÿ’€

Timeout (TO) โฐ

the Timeout event means the LCP Restart timer ran out โŒ› That timer gets started by other LCP events ๐ŸŒท

The Restart timer is what times out transmissions of Configure-Request and Terminate-Request packets ๐Ÿ’– When it expires, it causes a Timeout event, and that event makes the matching Configure-Request or Terminate-Request get sent again ๐Ÿ” The Restart timer MUST be configurable, but should default to three (3) seconds ๐ŸŽ€

Receive-Configure-Request (RCR) ๐Ÿ“ฌ

the Receive-Configure-Request event happens when a Configure-Request packet shows up from the LCP peer ๐Ÿ’Œ That packet says "hey, I want to open an LCP connection!" and it may include Configuration Options too ๐ŸŒธ The Configure-Request packet gets a much fuller explanation in a later section, so stay tuned ๐Ÿง

Receive-Configure-Ack (RCA) โœ…

the Receive-Configure-Ack event happens when a valid Configure-Ack packet arrives from the LCP peer ๐Ÿ’ฏ A Configure-Ack is a positive response to a Configure-Request packet, aka a big ol' "yes, looks good" ๐Ÿฅฐ

Receive-Configure-Nak (RCN) ๐Ÿ™…

the Receive-Configure-Nak event happens when a valid Configure-Nak or Configure-Reject packet arrives from the LCP peer ๐Ÿ˜ฌ Both of them are negative responses to a Configure-Request packet, so they're basically the "nope, not like that" replies ๐Ÿ’…

Receive-Terminate-Request (RTR) ๐Ÿ‘‹

the Receive-Terminate-Request event happens when a Terminate-Request packet arrives from the LCP peer ๐Ÿฅบ That packet means the peer wants to close the LCP connection, so it's a little goodbye ๐Ÿ’œ

Receive-Terminate-Ack (RTA) ๐Ÿซก

the Receive-Terminate-Ack event happens when a Terminate-Ack packet arrives from the LCP peer ๐ŸŒˆ A Terminate-Ack is the response to a Terminate-Request packet, so it's like saying "bye, got it" back ๐Ÿฆ‹

Receive-Code-Reject (RCJ) ๐Ÿšซ

the Receive-Code-Reject event happens when a Code-Reject packet arrives from the LCP peer โš ๏ธ The Code-Reject packet communicates an error that immediately closes the connection ๐Ÿ’€ yikes, no cap

Receive-Unknown-Code (RUC) ๐Ÿค”

the Receive-Unknown-Code event happens when an un-interpretable packet arrives from the LCP peer ๐Ÿ˜ต The Code-Reject packet is the response to an unknown packet, so the other side knows what's up ๐Ÿซถ

Receive-Echo-Request (RER) ๐Ÿ“

the Receive-Echo-Request event happens when an Echo-Request, Echo-Reply, or Discard-Request packet arrives from the LCP peer โœจ An Echo-Reply is the response to an Echo-Request packet ๐Ÿ’– There is no reply to a Discard-Request, so it just gets quietly accepted ๐Ÿคซ

Physical-Layer-Down (PLD) ๐Ÿ”Œ

the Physical-Layer-Down event happens when the Physical Layer says it's down ๐Ÿ˜ญ that's the one that cuts the whole thing off at the source, periodt ๐Ÿ’…

4.1.5. Actions โœจ

Okay so actions are what the LCP state machine actually does when an event happens ๐ŸŽฌ They usually mean sending a packet and/or starting or stopping the Restart timer. Here's the full list, bestie ๐Ÿ’…

Send-Configure-Request (scr)

The Send-Configure-Request action transmits a Configure-Request packet. This is basically saying "hey, I'd love to open an LCP connection with this specific set of Configuration Options" ๐Ÿฆ‹ The Restart timer starts right after the Configure-Request goes out, to guard against packet loss. Protect your packets, periodt ๐Ÿ’–

Send-Configure-Ack (sca)

The Send-Configure-Ack action transmits a Configure-Ack packet. This acknowledges a Configure-Request that came in with an acceptable set of Configuration Options. Yes queen, approved โœ…๐Ÿซถ

Send-Configure-Nak (scn)

The Send-Configure-Nak action transmits a Configure-Nak or Configure-Reject packet, as appropriate. This is the negative response to a Configure-Request with an unacceptable set of Configuration Options. Configure-Nak packets refuse a Configuration Option value and suggest a new, acceptable one. Configure-Reject packets refuse all negotiation about a Configuration Option, usually because it's not recognized or implemented. The difference between Configure-Nak vs. Configure-Reject is explained more fully in the section on LCP Packet Formats. Nak is the "try this instead" energy, Reject is the "absolutely not, we don't do that here" energy ๐Ÿ’€

Send-Terminate-Req (str)

The Send-Terminate-Request action transmits a Terminate-Request packet. This is the "okay bye" request that says the desire to close an LCP connection. The Restart timer starts after the Terminate-Request is sent, to guard against packet loss. ๐ŸŒธ

Send-Terminate-Ack (sta)

The Send-Terminate-Request action transmits a Terminate-Ack packet. This acknowledges a Terminate-Request or otherwise confirms the belief that an LCP connection is Closed. ๐Ÿงš

Send-Code-Reject (scj)

The Send-Code-Reject action transmits a Code-Reject packet. This indicates an unknown type of packet was received. This is an unrecoverable error, so it causes immediate transitions to the Closed state on both ends of the link. Not the vibe. Full stop. ๐Ÿ˜ญ

Send-Echo-Reply (ser)

The Send-Echo-Reply action transmits an Echo-Reply packet. This acknowledges the receipt of an Echo-Request packet. Basically the "I see you, I'm still here" response ๐ŸŒˆ

4.1.6. States

Okay, now the states themselves! Here's a more detailed look at each LCP state, so grab a snack ๐Ÿ“

Closed (1)

The initial and final state is Closed. In Closed, the connection is down and nobody's trying to open it. All connection requests from peers get rejected. Physical-Layer-Down events always cause an immediate transition to Closed ๐Ÿซ 

There are two events that kick you out of Closed: Active-Open and Passive-Open. On an Active-Open event, a Configure-Request is transmitted, the Restart timer starts, and the Request-Sent state is entered. On a Passive-Open event, the Listen state is entered immediately. When any packet arrives, except a Terminate-Ack, a Terminate-Ack gets sent back. Terminate-Acks are silently discarded to avoid creating a loop ๐Ÿ”

The Restart timer is not running in the Closed state.

The Physical Layer connection may be disconnected at any time while in the LCP Closed state. โœจ

Listen (2)

The Listen state is similar to Closed in that the connection is down and nobody's trying to open it. The big difference is that peer connection requests are no longer rejected ๐Ÿ‘€

When a Configure-Request comes in, a Configure-Request is immediately transmitted and the Restart timer starts. The received Configuration Options get examined and the proper response is sent. If a Configure-Ack is sent, the Ack-Sent state is entered. Otherwise, if a Configure-Nak or Configure-Reject is sent, the Request-Sent state is entered. Either way, LCP leaves its passive state and begins actively opening the connection. Terminate-Ack packets are sent in response to either Configure-Ack or Configure-Nak packets, ๐ŸŽ€

The Restart timer is not running in the Listen state.

Request-Sent (3)

Request-Sent is when an active attempt to open the connection is happening ๐Ÿƒโ€โ™€๏ธ A Configure-Request has been sent and the Restart timer is running, but no Configure-Ack has been received or sent yet.

When a Configure-Ack arrives, the Ack-Received state is immediately entered. When a Configure-Nak or Configure-Reject arrives, the Configure-Request Configuration Options get adjusted appropriately, a new Configure-Request is transmitted, and the Restart timer is restarted. Same deal when the Restart timer expires: a new Configure-Request goes out and the timer restarts. When a Configure-Request arrives, the Configuration Options are examined and, if acceptable, a Configure-Ack is sent and the Ack-Sent state is entered. If the Configuration Options are unacceptable, a Configure-Nak or Configure-Reject is sent, as appropriate.

Since there's an outstanding Configure-Request in Request-Sent, you have to be extra careful with the Passive-Open and Close events. Otherwise the LCP peer might think the connection is open when it isn't ๐Ÿ™ˆ Processing either event should be postponed until there's reasonable assurance that the peer is not open. In particular, the Restart timer should be allowed to expire.

Ack-Received (4)

In Ack-Received, a Configure-Request has been sent and a Configure-Ack has been received. The Restart timer is still running, since a Configure-Ack has not yet been transmitted.

When a Configure-Request with acceptable Configuration Options arrives, a Configure-Ack is transmitted, the Restart timer is stopped, and the Open state is entered. If the Configuration Options are unacceptable, a Configure-Nak or Configure-Reject is sent, as appropriate. When the Restart timer expires, a new Configure-Request is transmitted, the Restart timer is restarted, and the state machine goes back to Request-Sent ๐Ÿ”„

Ack-Sent (5)

In Ack-Sent, a Configure-Ack and a Configure-Request have been sent, but a Configure-Ack has not yet been received. The Restart timer is always running in Ack-Sent. โฐ

When a Configure-Ack arrives, the Restart timer is stopped and the Open state is entered. When a Configure-Nak or Configure-Reject arrives, the Configure-Request Configuration Options get adjusted appropriately, a new Configure-Request is transmitted, and the Restart timer is restarted. When the Restart timer expires, a new Configure-Request is transmitted, the Restart timer is restarted, and the state machine returns to Request-Sent.

Open (6)

In Open, a connection exists and data can be communicated over the link. This is the main character moment ๐Ÿ‘‘ The Restart timer is not running in Open.

In normal operation, only two events move you out of Open. When a Close command comes in, a Terminate-Request is transmitted, the Restart timer starts, and the Closing state is entered. When a Terminate-Request comes in, a Terminate-Ack is transmitted and the Closed state is entered. When an Echo-Request arrives, an Echo-Reply is transmitted. Similarly, Echo-Reply and Discard-Request packets are silently discarded or processed as expected. All other events cause immediate transitions out of Open and should be handled as if the state machine were in the Listen state. Plot twist energy ๐Ÿ˜ญ

Closing (7)

In Closing, an active attempt is made to close the connection. A Terminate-Request has been sent and the Restart timer is running, but no Terminate-Ack has been received yet ๐Ÿšช

When a Terminate-Ack arrives, the Closed state is immediately entered. When the Restart timer expires, a new Terminate-Request is transmitted and the Restart timer is restarted. After the Restart timer has expired Max-Restart times, this action may be skipped, and the Closed state may be entered. Max-Restart MUST be a configurable parameter. โš™๏ธ

Since there's an outstanding Terminate-Request in Closing, special care is needed with the Passive-Open event, or the LCP peer might think the connection is still open. Processing the Passive-Open event should be postponed until there's reasonable assurance that the peer is not open. In particular, the implementation should wait until the state machine would normally transition to Closed because of a Receive-Terminate-Ack event or Max-Restart Timeout events. ๐Ÿซถ


4.2. Loop Avoidance

Note that the protocol makes a reasonable attempt at avoiding Configuration Option negotiation loops. However, the protocol does NOT guarantee that loops won't happen. Like any negotiation, it's possible to configure two PPP implementations with conflicting policies that will never converge. It's also possible to configure policies that do converge, but take a significant amount of time to do so ๐ŸŒ Implementors should keep this in mind and should implement loop detection mechanisms or higher level timeouts. If a timeout is implemented, it MUST be configurable. ๐Ÿ’œ

4.3. Timers and Counters

There's one special timer used by LCP: the Restart timer. It's used to time out transmissions of Configure-Request and Terminate-Request packets. When the Restart timer expires, it causes a Timeout event and the corresponding Configure-Request or Terminate-Request packet gets retransmitted. The Restart timer MUST be configurable, but should default to three (3) seconds. โฑ๏ธ

There's one more restart parameter, Max-Restarts. Max-Restarts is the number of packet retransmissions that are required before there's reasonable assurance that the link closed. Max-Restarts MUST also be configurable, but should default to ten (10) retransmissions. ๐ŸŒธ

4.4. Packet Format โœจ

okay bestie, this is where the actual packets live ๐ŸŽ€ Exactly one Link Control Protocol packet rides inside the Information field of a PPP Data Link Layer frame whenever the Protocol field says hex c021 (Link Control Protocol) ๐Ÿ’–

here's the vibe of an LCP packet. Fields go left to right, no cap ๐Ÿ’…

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |     Code      |  Identifier   |            Length             |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |    Data ...
   +-+-+-+-+

Code ๐Ÿงš This one is a single octet and it tells you what kind of LCP packet you're looking at. The codes are:

   1       Configure-Request
   2       Configure-Ack
   3       Configure-Nak
   4       Configure-Reject
   5       Terminate-Request
   6       Terminate-Ack
   7       Code-Reject
   8       Protocol-Reject
   9       Echo-Request
   10      Echo-Reply
   11      Discard-Request

Identifier ๐Ÿ“ Also one octet. It's the matchmaker that helps pair up requests with their replies ๐Ÿ’œ

Length ๐Ÿฆ‹ Two octets, and it counts the whole LCP packet, including the Code, Identifier, Length and Data fields. Any octets sitting outside the Length range should be treated as Data Link Layer padding and should be ignored on reception. bestie, that's the padding getting politely ignored ๐Ÿ™ˆ

Data ๐ŸŒธ Zero or more octets, as the Length field says. What the Data field looks like depends entirely on the Code field โœจ

Regardless of which Configuration Options are turned on, every LCP packet goes out in the full, standard form, as if no Configuration Options were enabled at all. The reason is iconic: LCP Configure-Request packets stay recognizable even when one end of the link wrongly thinks the link is Open ๐Ÿ‘‘

this document is describing Version 1 of LCP. To keep things simple there's no version field in the LCP packet. If a new version ever becomes necessary, the plan is to use a new Data Link Layer Protocol field value to tell Version 1 LCP apart from every other version. A Version 1 LCP implementation that's working properly will always answer unknown Protocols (including other versions) with an easily recognizable Version 1 packet, which gives other versions a deterministic fallback mechanism. main character energy ๐ŸŒˆ

4.4.1. Configure-Request ๐Ÿ’–

Description

A LCP implementation that wants to open a connection MUST transmit a LCP packet with the Code field set to 1 (Configure-Request) and the Options field filled with any desired changes to the default link Configuration Options.

Upon reception of a Configure-Request, an appropriate reply MUST be transmitted. ๐Ÿซถ

Here's the Configure-Request packet format. Left to right, as always โœจ

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |     Code      |  Identifier   |            Length             |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   | Options ...
   +-+-+-+-+

Code ๐ŸŽ€ It's 1 for Configure-Request.

Identifier ๐Ÿฆ‹ The Identifier field should be changed on each transmission. When a packet comes in, the Identifier should be copied into the Identifier field of the appropriate reply packet ๐Ÿ”ฅ

Options ๐Ÿ’… This field is variable in length and holds a list of zero or more Configuration Options the sender wants to negotiate. All Configuration Options are always negotiated simultaneously, so it's all or nothing in one go. The format of Configuration Options gets its own spotlight in a later section ๐Ÿงš

4.4.2. Configure-Ack ๐ŸŒธ

Description

If every Configuration Option received in a Configure-Request is both recognizable and acceptable, then a LCP implementation should transmit a LCP packet with the Code field set to 2 (Configure-Ack), the Identifier field copied from the received Configure-Request, and the Options field copied from the received Configure-Request. The acknowledged Configuration Options MUST NOT be reordered or modified in any way. ๐Ÿ”’

On reception of a Configure-Ack, the Identifier field must match that of the last transmitted Configure-Request, or the packet is invalid. On top of that, the Configuration Options in a Configure-Ack must match those of the last transmitted Configure-Request, or the packet is invalid. Invalid packets should be silently discarded. bestie, we don't do drama, we just ghost invalid packets ๐Ÿ‘ป

Reception of a valid Configure-Ack indicates that all Configuration Options sent in the last Configure-Request are acceptable. โœ… Iconic.

Here's the Configure-Ack packet format:

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |     Code      |  Identifier   |            Length             |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   | Options ...
   +-+-+-+-+

Code ๐Ÿ“ It's 2 for Configure-Ack.

Identifier ๐Ÿ’œ This is a copy of the Identifier field from the Configure-Request that caused this Configure-Ack.

Options ๐ŸŒˆ This field is variable in length and holds a list of zero or more Configuration Options the sender is acknowledging. All Configuration Options are always acknowledged simultaneously.

4.4.3. Configure-Nak ๐Ÿฆ‹

Description

If every element of the received Configuration Options is recognizable but some are not acceptable, then a LCP implementation should transmit a LCP packet with the Code field set to 3 (Configure-Nak), the Identifier field copied from the received Configure-Request, and the Options field filled with only the unacceptable Configuration Options from the Configure-Request. All acceptable Configuration Options should be filtered out of the Configure-Nak, but otherwise the Configuration Options from the Configure-Request MUST NOT be reordered. Each of the nak'd Configuration Options MUST be modified to a value acceptable to the Configure-Nak sender. Finally, an implementation may be configured to require the negotiation of a specific option. If that option is not listed, then that option may be appended to the list of nak'd Configuration Options in order to request the remote end to list that option in its next Configure-Request packet. The appended option must include a value acceptable to the Configure-Nak sender. ๐ŸŽฏ

On reception of a Configure-Nak, the Identifier field must match that of the last transmitted Configure-Request, or the packet is invalid and should be silently discarded.

Reception of a valid Configure-Nak indicates that a new Configure-Request should be sent with the Configuration Options modified as specified in the Configure-Nak. ๐Ÿ”

Here's the Configure-Nak packet format:

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |     Code      |  Identifier   |            Length             |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   | Options ...
   +-+-+-+-+

Code ๐Ÿซถ It's 3 for Configure-Nak.

Identifier โœจ This is a copy of the Identifier field from the Configure-Request that caused this Configure-Nak.

Options ๐ŸŽ€ This field is variable in length and holds a list of zero or more Configuration Options the sender is nak'ing. All Configuration Options are always nak'd simultaneously.

4.4.4. Configure-Reject ๐ŸŒธ

Description

If some Configuration Options received in a Configure-Request are not recognizable or are not acceptable for negotiation (as configured by a network manager), then a LCP implementation should transmit a LCP packet with the Code field set to 4 (Configure-Reject), the Identifier field copied from the received Configure-Request, and the Options field filled with only the unrecognized Configuration Options from the Configure-Request. All recognizable and negotiable Configuration Options must be filtered out of the Configure-Reject, but otherwise the Configuration Options MUST not be reordered. ๐Ÿ™…โ€โ™€๏ธ

On reception of a Configure-Reject, the Identifier field must match that of the last transmitted Configure-Request, or the packet is invalid. Additionally, the Configuration Options in a Configure-Reject must be a proper subset of those in the last transmitted Configure-Request, or the packet is invalid. Invalid packets should be silently discarded.

Reception of a Configure-Reject indicates that a new Configure-Request should be sent which does not include any of the Configuration Options listed in the Configure-Reject. ๐Ÿšซ

Here's the Configure-Reject packet format:

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |     Code      |  Identifier   |            Length             |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   | Options ...
   +-+-+-+-+

Code ๐Ÿ’… It's 4 for Configure-Reject.

Identifier ๐Ÿ’œ This is a copy of the Identifier field from the Configure-Request that caused this Configure-Reject.

Options ๐Ÿ“ This field is variable in length and holds a list of zero or more Configuration Options the sender is rejecting. All Configuration Options are always rejected simultaneously.

4.4.5. Terminate-Request and Terminate-Ack โœจ

Description

okay so LCP has Terminate-Request and Terminate-Ack Codes ๐Ÿ’… they're how you close a connection, bestie ๐Ÿฆ‹

an LCP implementation that wants to close a connection sends an LCP packet with the Code field set to 5 (Terminate-Request), and the Data field can hold whatever data it wants ๐ŸŽ€ it should keep sending Terminate-Requests until a Terminate-Ack comes back, the Physical Layer says it's gone down, or it has sent enough of them that the remote end is down with reasonable certainty ๐Ÿ˜ญ

when an implementation gets a Terminate-Request, it MUST send back an LCP packet with the Code field set to 6 (Terminate-Ack), copy the Identifier field from the Terminate-Request, and fill the Data field with whatever data it likes ๐Ÿซถ

and if a Terminate-Ack shows up with no Terminate-Request behind it, that means the connection has been closed ๐ŸŒธ

A summary of the Terminate-Request and Terminate-Ack packet formats is shown below. The fields are transmitted from left to right.

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |     Code      |  Identifier   |            Length             |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |    Data ...
   +-+-+-+-+

Code

  • 5 for Terminate-Request;
  • 6 for Terminate-Ack.

Identifier

The Identifier field is one octet, and it's how requests and replies get matched up ๐Ÿงš

Data

The Data field is zero or more octets of uninterpreted data for the sender to use ๐Ÿ’œ it can be any binary value and any length from zero up to the established maximum Information field length minus four ๐Ÿ“

4.4.6. Code-Reject โœจ

Description

so if an LCP packet shows up with a Code nobody recognizes, that means one of the LCP implementations is faulty or incomplete ๐Ÿ’€ the error MUST be reported back to whoever sent the unknown Code, by sending an LCP packet with the Code field set to 7 (Code-Reject) and copying the inducing packet into the Rejected-Packet field ๐Ÿ™ˆ

when a Code-Reject comes in, an LCP implementation should go straight to the Closed state and report the error, because it's unlikely the situation can fix itself automatically ๐Ÿ˜ญ๐Ÿ”ฅ

A summary of the Code-Reject packet format is shown below. The fields are transmitted from left to right.

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |     Code      |  Identifier   |            Length             |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   | Rejected-Packet ...
   +-+-+-+-+-+-+-+-+

Code

  • 7 for Code-Reject.

Identifier

The Identifier field is one octet and is for the transmitter to use ๐ŸŒˆ

Rejected-Packet

The Rejected-Packet field holds a copy of the LCP packet being rejected ๐Ÿฆ‹ it starts with the rejected Code field, and it does not include any PPP Data Link Layer headers. The Rejected-Packet should be truncated to fit within the established maximum Information field length โœจ

4.4.7. Protocol-Reject โœจ

Description

when a PPP frame arrives with a Data Link Layer Protocol nobody recognizes, that means the remote end is trying to use a protocol the local end doesn't support ๐Ÿ‘€ this usually happens when the remote end tries to set up a new protocol that isn't supported here ๐Ÿงš

if the LCP state machine is in the Open state, this error MUST be reported back to whoever sent the unknown protocol, by sending an LCP packet with the Code field set to 8 (Protocol-Reject), the Rejected-Protocol field set to the Protocol that was received, and the Data field filled with whatever data ๐Ÿ’…

when a Protocol-Reject comes in, an LCP implementation should stop sending frames of the protocol that got rejected ๐Ÿ›‘

Protocol-Reject packets may only be sent in the LCP Open state. Protocol-Reject packets received in any other state should be discarded, and no further action should be taken ๐Ÿ™…โ€โ™€๏ธ

A summary of the Protocol-Reject packet format is shown below. The fields are transmitted from left to right.

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |     Code      |  Identifier   |            Length             |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |       Rejected-Protocol       |      Rejected-Information ...
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Code

  • 8 for Protocol-Reject.

Identifier

The Identifier field is one octet and is for the transmitter to use ๐ŸŒธ

Rejected-Protocol

The Rejected-Protocol field is two octets, and it holds the Protocol of the Data Link Layer frame being rejected ๐ŸŽ€

Rejected-Information

The Rejected-Information field is a copy from the frame being rejected ๐Ÿ’– it starts with the Information field, and it leaves out any PPP Data Link Layer headers and the FCS. The Rejected-Information field should be truncated to fit within the established maximum Information field length ๐Ÿซถ

4.4.8. Echo-Request and Echo-Reply ๐Ÿ”ฅ

Description

LCP has Echo-Request and Echo-Reply Codes, which give you a Data Link Layer loopback mechanism for testing both directions of the link ๐Ÿ” this is super useful for debugging, checking link quality, performance testing, and a bunch of other stuff too ๐Ÿค“

an Echo-Request sender transmits an LCP packet with the Code field set to 9 (Echo-Request) and the Data field filled with whatever data, up to but not going over the receiver's established maximum Information field length minus eight ๐Ÿ’…

when an Echo-Request comes in, an LCP packet MUST be sent back with the Code field set to 10 (Echo-Reply), the Identifier field copied from the Echo-Request, and the Data field copied from the Echo-Request. Trim it as needed so it doesn't go over the peer's established maximum Information field length โœ‚๏ธ

Echo-Request and Echo-Reply packets may only be sent in the LCP Open state. Echo-Request and Echo-Reply packets received in any other state should be discarded, and no further action should be taken ๐Ÿ™…โ€โ™€๏ธ

A summary of the Echo-Request and Echo-Reply packet formats is shown below. The fields are transmitted from left to right.

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |     Code      |  Identifier   |            Length             |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                         Magic-Number                          |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |    Data ...
   +-+-+-+-+

Code

  • 9 for Echo-Request;
  • 10 for Echo-Reply.

Identifier

The Identifier field is one octet and helps match Echo-Requests with Echo-Replies ๐Ÿงš

Magic-Number

The Magic-Number field is four octets and helps detect loopbacked links ๐Ÿ” unless a Configuration Option changes it, the Magic-Number MUST always be transmitted as zero, and it MUST always be ignored on reception. Anything beyond that about the Magic-Number is out of scope here ๐Ÿ™ˆ

Data

The Data field is zero or more octets of uninterpreted data for the sender to use ๐Ÿ’œ it can be any binary value and any length from zero up to the established maximum Information field length minus eight ๐Ÿ“

4.4.9. Discard-Request

Description

LCP has a Discard-Request Code that gives you a Data Link Layer data sink, so you can test the local-to-remote direction of the link ๐Ÿ•ณ๏ธ it's handy for debugging, performance testing, and lots of other things too ๐ŸŒˆ

a discard sender transmits an LCP packet with the Code field set to 11 (Discard-Request) and the Data field filled with whatever data, up to but not going over the receiver's established maximum Information field length minus eight ๐Ÿ’…

a discard receiver MUST simply throw away any Discard-Request it receives ๐Ÿ—‘๏ธ

Discard-Request packets may only be sent in the LCP Open state.

A summary of the Discard-Request packet formats is shown below. The fields are transmitted from left to right.

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |     Code      |  Identifier   |            Length             |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                         Magic-Number                          |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |    Data ...
   +-+-+-+-+

Code

  • 11 for Discard-Request.

Identifier

The Identifier field is one octet and is for the Discard-Request transmitter to use ๐ŸŒธ

Magic-Number

The Magic-Number field is four octets and helps detect loopbacked links ๐Ÿ” unless a configuration option changes it, the Magic-Number MUST always be transmitted as zero, and it MUST always be ignored on reception. Anything beyond that about the Magic-Number is out of scope here ๐Ÿ™ˆ

Data

The Data field is zero or more octets of uninterpreted data for the sender to use ๐Ÿ’œ it can be any binary value and any length from zero up to the established maximum Information field length minus four ๐Ÿ“

4.5. Configuration Options ๐ŸŽ€

LCP Configuration Options let you negotiate changes to the standard characteristics of a point-to-point link โญ stuff like the maximum receive unit, async control character mapping, the link authentication method, and so on ๐Ÿงฉ the Configuration Options themselves are described in separate documents. If a Configuration Option isn't included in a Configure-Request packet, the default value for that option is assumed ๐Ÿ’–

the end of the Configuration Options list is marked by the end of the LCP packet ๐Ÿ

Unless otherwise specified, a specific Configuration Option should be listed no more than once in a Configuration Options list. Specific Configuration Options can override this general rule and be listed more than once, and what that does depends on each option and is specified by that option ๐Ÿฆ‹

also unless otherwise specified, all Configuration Options work in a half-duplex fashion. Once negotiated, they only apply to one direction of the link, typically the receive direction when you look at it from the point of view of the Configure-Request sender ๐Ÿซถ

4.5.1. Format โœจ

okay so here's how a Configuration Option is laid out, bestie ๐ŸŽ€ the fields go left to right, no cap:

    0                   1
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |     Type      |    Length     |    Data ...
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Type ๐Ÿ’– The Type field is one octet and tells you what kind of Configuration Option it is. The latest values are listed in the most recent "Assigned Numbers" RFC [12], so go check there. ๐Ÿ‘€

Length ๐Ÿ“ The Length field is one octet and counts the whole Configuration Option, Type, Length and Data fields included. Now this is the lowkey important part ๐Ÿซถ: if a negotiable Configuration Option shows up in a Configure-Request with an invalid Length, a Configure-Nak should be sent back. That Configure-Nak should include the desired Configuration Option with an appropriate Length and Data. Fixing it is the whole point, it's giving self-correction โœจ

Data ๐ŸŒธ The Data field is zero or more octets and carries the value or other info for this Configuration Option. Its format and length are figured out from the Type and Length fields, so the two fields before it are doing a lot of the work here ๐Ÿ’…


5. A PPP Network Control Protocol (NCP) for IP ๐Ÿฆ‹

okay the IP Control Protocol (IPCP) is the one in charge of configuring, enabling, and disabling the IP protocol modules on both ends of the point-to-point link ๐Ÿงš It works just like the Link Control Protocol does, through an exchange of packets. But there's a rule: IPCP packets may not be exchanged until LCP has reached the Network-Layer Protocol Configuration Negotiation phase. If an IPCP packet shows up before that phase is reached, it should be silently discarded, no drama ๐Ÿ™ˆ And IP datagrams can't be exchanged until IPCP has first opened the connection, meaning it has reached the Open state. Gatekeeping at its finest ๐Ÿ‘‘

The IP Control Protocol is exactly the same as the Link Control Protocol, with the following exceptions:

Data Link Layer Protocol Field ๐Ÿ“ Exactly one IP Control Protocol packet is encapsulated in the Information field of PPP Data Link Layer frames where the Protocol field indicates type hex 8021 (IP Control Protocol).

Code field ๐Ÿ”ฅ Only Codes 1 through 7 (Configure-Request, Configure-Ack, Configure-Nak, Configure-Reject, Terminate-Request, Terminate-Ack and Code-Reject) are used. Any other Codes should be treated as unrecognized, and they should result in Code-Rejects. Not me reading unknown codes and just vibing ๐Ÿ’€

Timeouts โณ IPCP packets may not be exchanged until the Link Control Protocol has reached the network-layer Protocol Configuration Negotiation phase. An implementation should be prepared to wait for Link Quality testing to finish before it times out waiting for a Configure-Ack or other response. Patience is a whole vibe ๐Ÿฆ‹ It's suggested that an implementation give up only after user intervention or a configurable amount of time.

Configuration Option Types ๐ŸŒˆ The IPCP has its own separate set of Configuration Options. The latest values of the type field are specified in the most recent "Assigned Numbers" RFC [12].


5.1. Sending IP Datagrams ๐Ÿ“จ

Before any IP packets may be communicated, both the Link Control Protocol and the IP Control Protocol must reach the Open state. Non-negotiable, bestie ๐Ÿ’–

Exactly one IP packet is encapsulated in the Information field of PPP Data Link Layer frames where the Protocol field indicates type hex 0021 (Internet Protocol). โœจ

The maximum length of an IP packet sent over a PPP link is the same as the maximum length of the Information field of a PPP data link layer frame. Larger IP datagrams must be fragmented as necessary, so no skipping that step ๐Ÿ˜ญ If a system wants to avoid fragmentation and reassembly, it should use the TCP Maximum Segment Size option [13], or a similar mechanism, to discourage others from sending large datagrams. Big datagrams are literally not the vibe here ๐Ÿ™…โ€โ™€๏ธ


A. Asynchronous HDLC ๐ŸŽ€

This appendix summarizes the modifications to ISO 3309-1979 proposed in ISO 3309:1984/PDAD1. These modifications are what allow HDLC to be used with 8-bit asynchronous links. Iconic glow-up energy ๐ŸŒŸ

Transmission Considerations

Each octet is delimited by a start and a stop element. Simple, clean, no notes ๐Ÿงผ

Flag Sequence ๐Ÿ

The Flag Sequence is a single octet and marks the beginning or end of a frame. It's the binary sequence 01111110 (hexadecimal 0x7e). Main character marker energy ๐Ÿ’…

Transparency ๐Ÿซง

On asynchronous links, a character stuffing procedure is used. The Control Escape octet is defined as binary 01111101 (hexadecimal 0x7d), where the bit positions are numbered 87654321 (not 76543210, BEWARE โš ๏ธ).

After FCS computation, the transmitter looks at the entire frame between the two Flag Sequences. Each Flag Sequence, each Control Escape octet, and each octet with a value less than hexadecimal 0x20 gets replaced by a two octet sequence. That sequence is the Control Escape octet followed by the original octet with bit 6 complemented (i.e., exclusive-or'd with hexadecimal 0x20). ๐Ÿ”

Before FCS computation, the receiver looks at the entire frame between the two Flag Sequences. Each octet with a value less than hexadecimal 0x20 is simply removed, because it may have been inserted by intervening data communications equipment. For each Control Escape octet, that octet is removed too, but bit 6 of the following octet is complemented. A Control Escape octet immediately before the closing Flag Sequence indicates an invalid frame. Red flag ๐Ÿšฉ

Note: The inclusion of all octets less than hexadecimal 0x20 allows all ASCII control characters [10] excluding DEL (Delete) to be transparently communicated through almost all known data communications equipment. ๐Ÿงš

A few examples might make this clearer ๐ŸŒธ Packet data is transmitted on the link as follows:

0x7e is encoded as 0x7d, 0x5e.

0x7d is encoded as 0x7d, 0x5d.
0x01 is encoded as 0x7d, 0x21.

Aborting a Transmission ๐Ÿ™…โ€โ™€๏ธ

On asynchronous links, frames may be aborted by transmitting a "0" stop bit where a "1" bit is expected (a framing error), or by transmitting a Control Escape octet followed immediately by a closing Flag Sequence. Abort abort abort ๐Ÿšจ

Inter-frame Time Fill โฑ๏ธ

On asynchronous links, inter-octet and inter-frame time fill should be accomplished by transmitting continuous "1" bits (mark-hold state).

Note: On asynchronous links, inter-frame time fill can be viewed as extended inter-octet time fill. Doing so can save one octet for every frame, decreasing delay and increasing bandwidth. This is possible since a Flag Sequence may serve as both a frame close and a frame begin. After having received any frame, an idle receiver will always be in a frame begin state. ๐Ÿฆ‹

Robust transmitters should avoid using this trick over-zealously, since the price for decreased delay is decreased reliability. ๐Ÿฅบ Noisy links may cause the receiver to receive garbage characters and interpret them as part of an incoming frame. If the transmitter does not transmit a new opening Flag Sequence before sending the next frame, then that frame will be appended to the noise characters, causing an invalid frame (with high reliability). Transmitters should avoid this by transmitting an open Flag Sequence whenever "appreciable time" has elapsed since the prior closing Flag Sequence. It's suggested that implementations will achieve the best results by always sending an opening Flag Sequence if the new frame is not back-to-back with the last one. The maximum value for "appreciable time" is likely to be no greater than the typing rate of a slow to average typist, say 1 second. โŒจ๏ธ๐Ÿ’œ


B. Fast Frame Check Sequence (FCS) Implementation ๐Ÿงฎ

B.1. FCS Computation Method ๐Ÿ”ข

The following code provides a table lookup computation for calculating the Frame Check Sequence as data arrives at the interface. The table is created by the code in section 2. Table lookups are giving efficiency ๐Ÿ†

/*
 * u16 represents an unsigned 16-bit number.  Adjust the typedef for
 * your hardware.
 */
typedef unsigned short u16;


/*
 * FCS lookup table as calculated by the table generator in section 2.
 */
static u16 fcstab[256] = {
   0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
   0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
   0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
   0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
   0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
   0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
   0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
   0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
   0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
   0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
   0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
   0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
   0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
   0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
   0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
   0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
   0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
   0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
   0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
   0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
   0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
   0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
   0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
   0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
   0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
   0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
   0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
   0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
   0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
   0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
   0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
   0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
};

#define PPPINITFCS      0xffff  /* Initial FCS value */
#define PPPGOODFCS      0xf0b8  /* Good final FCS value */

/*
 * Calculate a new fcs given the current fcs and the new data.
 */
u16 pppfcs(fcs, cp, len)
    register u16 fcs;
    register unsigned char *cp;
    register int len;
{
    ASSERT(sizeof (u16) == 2);
    ASSERT(((u16) -1) > 0);
    while (len--)
        fcs = (fcs >> 8) ^ fcstab[(fcs ^ *cp++) & 0xff];

    return (fcs);
}

B.2. Fast FCS table generator ๐Ÿงฎโœจ

okay so this part is the table generator, and it is giving main character energy ๐Ÿ’… It's the little C program that builds the lookup table the FCS math uses, so you never have to type all 256 numbers yourself. Drew D. Perkins wrote it at Carnegie Mellon, and it's borrowed from Mohsen Banan and D. Hugh Redelmeier, which is so sweet ๐Ÿซถ

/*
 * Generate a FCS table for the HDLC FCS.
 *
 * Drew D. Perkins at Carnegie Mellon University.
 *
 * Code liberally borrowed from Mohsen Banan and D. Hugh Redelmeier.
 */

/*
 * The HDLC polynomial: x**0 + x**5 + x**12 + x**16 (0x8408).
 */
#define P       0x8408


main()
{
    register unsigned int b, v;
    register int i;

    printf("typedef unsigned short u16;\n");
    printf("static u16 fcstab[256] = {");
    for (b = 0; ; ) {
        if (b % 8 == 0)
            printf("\n");

        v = b;
        for (i = 8; i--; )
            v = v & 1 ? (v >> 1) ^ P : v >> 1;

        printf("0x%04x", v & 0xFFFF);
        if (++b == 256)
            break;
        printf(",");
    }
    printf("\n};\n");
}

References ๐Ÿ“š

  • [1] Electronic Industries Association, EIA Standard RS-232-C, "Interface Between Data Terminal Equipment and Data Communications Equipment Employing Serial Binary Data Interchange", August 1969.
  • [2] International Organization For Standardization, ISO Standard 3309-1979, "Data communication - High-level data link control procedures - Frame structure", 1979.
  • [3] International Organization For Standardization, ISO Standard 4335-1979, "Data communication - High-level data link control procedures - Elements of procedures", 1979.
  • [4] International Organization For Standardization, ISO Standard 4335-1979/Addendum 1, "Data communication - High-level data link control procedures - Elements of procedures - Addendum 1", 1979.
  • [5] International Organization For Standardization, Proposed Draft International Standard ISO 3309:1983/PDAD1, "Information processing systems - Data communication - High-level data link control procedures - Frame structure - Addendum 1: Start/stop transmission", 1984.
  • [6] International Telecommunication Union, CCITT Recommendation X.25, "Interface Between Data Terminal Equipment (DTE) and Data Circuit Terminating Equipment (DCE) for Terminals Operating in the Packet Mode on Public Data Networks", CCITT Red Book, Volume VIII, Fascicle VIII.3, Rec. X.25., October 1984.
  • [7] Perez, "Byte-wise CRC Calculations", IEEE Micro, June, 1983.
  • [8] Morse, G., "Calculating CRC's by Bits and Bytes", Byte, September 1986.
  • [9] LeVan, J., "A Fast CRC", Byte, November 1987.
  • [10] American National Standards Institute, ANSI X3.4-1977, "American National Standard Code for Information Interchange", 1977.
  • [11] Postel, J., "Internet Protocol", RFC 791, USC/Information Sciences Institute, September 1981.
  • [12] Reynolds, J., and J. Postel, "Assigned Numbers", RFC 1060, USC/Information Sciences Institute, March 1990.
  • [13] Postel, J., "The TCP Maximum Segment Size Option and Related Topics", RFC 879, USC/Information Sciences Institute, November 1983.

Security Considerations ๐Ÿ”

Security issues are not discussed in this memo. ๐Ÿ™ˆ

Chairman's Address ๐ŸŽ€

This proposal is the product of the Point-to-Point Protocol Working Group of the Internet Engineering Task Force (IETF). The working group can be contacted via the chair:

Russ Hobby
UC Davis
Computing Services
Davis, CA 95616

Phone: (916) 752-0236

EMail: rdhobby@ucdavis.edu

Author's Address ๐Ÿฆ‹

Questions about this memo can also be directed to the author:

Drew D. Perkins
Carnegie Mellon University
Networking and Communications
Pittsburgh, PA 15213

Phone: (412) 268-8576

EMail: ddp@andrew.cmu.edu

Acknowledgments ๐ŸŒˆ

Many people spent significant time helping to develop the Point-to-Point Protocol. The complete list of people is too numerous to list, but the following people deserve special thanks: Ken Adelman (TGV), Craig Fox (NSC), Phill Gross (NRI), Russ Hobby (UC Davis), David Kaufman (Proteon), John LoVerso (Xylogics), Bill Melohn (Sun Microsystems), Mike Patton (MIT), Drew Perkins (CMU), Greg Satz (cisco systems) and Asher Waldfogel (Wellfleet). ๐Ÿซถ๐Ÿ’–

๐Ÿ“ฆ where this page comes from