RFC 1134

Point-to-Point Protocol: A proposal for multi-protocol transmission of datagrams over Point-to-Point links

๐Ÿ“… published November 1989, from ietf

RFC 1134: The Point-to-Point Protocol: A Proposal for Multi-Protocol Transmission of Datagrams Over Point-to-Point Links ๐Ÿฆ‹

  • Working group: Network Working Group ๐Ÿ’–
  • Author: D. Perkins, CMU
  • Date: November 1989
  • Status: a proposed protocol for the Internet community (see Status of this Memo below) โœจ
  • Obsoletes / Updates: the title block doesn't list anything this RFC obsoletes or updates ๐Ÿ™ˆ

Table of Contents ๐Ÿงš

   Status of this Memo ...................................    2
   Abstract ..............................................    2
   1. Introduction .......................................    2
   1.1 Motivation ........................................    2
   1.2 Overview of PPP ...................................    3
   1.3 Organization of the document ......................    4
   2. Physical Layer Requirements ........................    4
   3. The Data Link Layer ................................    4
   3.1 Frame Format ......................................    5
   4. The PPP Link Control Protocol (LCP) ................    8
   4.1 The LCP Automaton .................................    9
   4.1.1 Overview ........................................    9
   4.1.2 State Diagram ...................................   10
   4.1.3 State Transition Table ..........................   12
   4.1.4 Events ..........................................   12
   4.1.5 Actions .........................................   14
   4.1.6 States ..........................................   16
   4.2 Loop Avoidance ....................................   19
   4.3 Packet Format .....................................   19
   4.3.1 Configure-Request ...............................   21
   4.3.2 Configure-Ack ...................................   21
   4.3.3 Configure-Nak ...................................   22
   4.3.4 Configure-Reject ................................   24
   4.3.5 Terminate-Request and Terminate-Ack .............   25
   4.3.6 Code-Reject .....................................   26
   4.3.7 Protocol-Reject .................................   27
   4.3.8 Echo-Request and Echo-Reply .....................   28
   4.3.9 Discard-Request .................................   29
   4.4 Configuration Options .............................   30
   4.4.1 Format ..........................................   31
   5. A PPP Network Control Protocol (NCP) for IP ........   32
   5.1 Sending IP Datagrams ..............................   33
   APPENDICES ............................................   33
   A. Asynchronous HDLC ..................................   33
   B. Fast Frame Check Sequence (FCS) Implementation .....   35
   B.1 FCS Computation Method ............................   35
   B.2 Fast FCS table generator ..........................   36
   REFERENCES ............................................   37
   AUTHOR'S ADDRESS ......................................   38

Status of this Memo ๐Ÿ“ฃ

Okay so this memo is basically putting forward a proposed protocol for the whole Internet community ๐ŸŒ

This proposal came out of the Point-to-Point Protocol Working Group of the Internet Engineering Task Force (IETF). If you have comments on this memo, they should be sent to the IETF Point-to-Point Protocol Working Group chair by January 15, 1990. The comments will get reviewed at the February 1990 IETF meeting, with the goal of moving PPP up to draft standard status ๐Ÿš€ Distribution of this memo is unlimited ๐Ÿ’œ

Abstract ๐ŸŒธ

The Point-to-Point Protocol (PPP) is the thing that gives you a way to send datagrams over serial point-to-point links. PPP is made up of 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 establishing and configuring the Internet Protocol (IP) (called the IP Control Protocol, IPCP) ๐ŸŽ€

The options and facilities used by the LCP and the IPCP are defined in separate documents. Control protocols for configuring and utilizing other network-layer protocols besides IP (e.g., DECNET, OSI) are expected to be developed as needed ๐Ÿซถ

1. Introduction ๐ŸŽ€

1.1. Motivation ๐Ÿ’…

Over the last few years, the Internet has seen explosive growth in the number of hosts supporting TCP/IP. Most of these hosts are hooked up to Local Area Networks (LANs) of various types, with Ethernet being the most common ๐Ÿ˜ญ Most of the other hosts connect through Wide Area Networks (WANs) such as X.25 style Public Data Networks (PDNs). Only a few of these hosts are connected with simple point-to-point (i.e., serial) links, which is kind of wild because point-to-point links are among the oldest methods of data communications and almost every host supports them. For example, asynchronous RS-232-C [1] interfaces are essentially ubiquitous ๐Ÿ“

One reason there are so few point-to-point IP links is the lack of a standard encapsulation protocol. There are plenty of non-standard (and at least one de facto standard) encapsulation protocols out there, but none of them has been agreed upon as an Internet Standard. By contrast, standard encapsulation schemes do exist for sending datagrams over most popular LANs ๐Ÿ‘‘

One purpose of this memo is to fix that problem. But even more importantly, the Point-to-Point Protocol proposes more than just an encapsulation scheme. Point-to-point links tend to make a bunch of problems with the current family of network protocols even worse ๐Ÿ’€ For instance, assigning and managing IP addresses is a problem even in LAN environments, but it's especially difficult over switched point-to-point circuits (e.g., dialups) ๐Ÿฅฒ

PPP also deals with some additional issues, including asynchronous (start/stop) and bit-oriented synchronous encapsulation, network protocol multiplexing, link configuration, link quality testing, error detection, and option negotiation for things like network-layer address negotiation and data compression negotiation โœจ

PPP handles all of this by providing an extensible Link Control Protocol (LCP) and a family of Network Control Protocols (NCP) to negotiate optional configuration parameters and facilities. It's giving organized ๐Ÿงš

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.
  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 allow the simultaneous use of multiple network-layer protocols ๐ŸŒˆ

So to set up communications over a point-to-point link, the originating PPP would first send LCP packets to configure and test the data link. Once the link is established and any optional facilities have been negotiated as needed by the LCP, the originating PPP sends NCP packets to choose and configure one or more network-layer protocols. After each of the chosen network-layer protocols has been configured, datagrams from each of them can be sent over the link ๐Ÿ’–

The link stays configured for communications until explicit LCP or NCP packets close it down, or until some external event happens (e.g., an inactivity timer expires or a user intervenes) โณ

1.3. Organization of the document ๐Ÿ—บ๏ธ

This memo is split up into several sections. Section 2 talks about the physical-layer requirements of PPP. Section 3 covers the Data Link Layer, including the PPP frame format and data link encapsulation scheme. Section 4 specifies the LCP, including the 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 within PPP packets ๐Ÿ’œ Appendix A summarizes 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 you is a duplex circuit, either dedicated or switched, that can operate in either asynchronous (start/stop) or synchronous bit-serial mode, transparent to PPP Data Link Layer frames. PPP doesn't put any restrictions on transmission rate, other than whatever the particular DTE/DCE interface in use already imposes ๐ŸŒธ

PPP does not require modem control signals such as 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 greater functionality and performance ๐Ÿš€

PPP uses 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]), as modified by ISO 3309:1984/PDAD1 "Addendum 1: Start/stop transmission" [5]. ISO 3309-1979 specifies the HDLC frame structure for use in synchronous environments. ISO 3309:1984/PDAD1 specifies proposed modifications to ISO 3309-1979 so it can be used in asynchronous environments ๐Ÿ“

The PPP 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 is also consistent with CCITT Recommendation X.25 LAPB [6], since that one is based on HDLC too ๐ŸŽ€

Note: ISO 3309:1984/PDAD1 is a Proposed Draft standard. At present, it seems that ISO 3309:1984/PDAD1 is stable and likely to become an International Standard. Therefore, we feel comfortable about using it before it becomes an International Standard. The progress of this proposal should be tracked and encouraged by the Internet community. ๐Ÿ‘€

The purpose of this memo is not to document what's already standardized in ISO 3309. We assume the reader is already familiar with HDLC, or has access to a copy of [2] or [6]. Instead, this paper gives a concise summary and points out the specific options and features used by PPP ๐Ÿ’… Since "Addendum 1: Start/stop transmission" is not yet standardized and widely available, it gets summarized in Appendix A โœจ

3.1. Frame Format ๐ŸŽ€

okay so here's the standard PPP frame layout, bestie ๐Ÿซถ the fields go left to right, no cap:

      +----------+---------+---------+----------+------------
      |   Flag   | Address | Control | Protocol | Information
      | 01111110 | 1111111 | 0000011 | 16 bits  |      *
      +----------+---------+---------+----------+------------
              ---+---------+----------+
                 |   FCS   |   Flag   |
                 | 16 bits | 01111110 |
              ---+---------+----------+

This figure doesn't show start/stop bits (for asynchronous links) or any bits or octets added for transparency. When asynchronous links are used, every octet goes out with one start bit, eight bits of data, and one stop bit. There's no provision in PPP or ISO 3309:1984/PDAD1 for seven-bit asynchronous links ๐Ÿ’€

To stay consistent with standard Internet practice and avoid confusing anyone who's used to reading RFCs, all binary numbers in these descriptions are in Most Significant Bit to Least Significant Bit order, reading left to right, unless it says otherwise. This is contrary to standard ISO and CCITT practice, which orders bits as transmitted (aka network bit order). So if you're comparing this doc with the international standards, keep that in mind ๐Ÿ‘€โœจ

Flag Sequence

The Flag Sequence is a single octet that marks the beginning or end of a frame. It's the binary sequence 01111110 (hexadecimal 0x7e) ๐Ÿฆ‹

Address Field

The Address field is a single octet holding the binary sequence 11111111 (hexadecimal 0xff), the All-Stations address. PPP doesn't assign individual station addresses ๐Ÿ™ˆ The All-Stations address should always be recognized and received. Frames with other Addresses should be silently discarded.

Control Field

The Control field is a single octet holding the binary sequence 00000011 (hexadecimal 0x03), which is the Unnumbered Information (UI) command with the P/F bit set to zero. Frames with other Control field values should be silently discarded ๐Ÿ“

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 [11]. Initial values are also listed below.

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

This Protocol field is defined by PPP and isn't a field defined by HDLC. Still, 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 received which don't comply with 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 two rules above are the big ones here, so don't skip past them bestie ๐Ÿ’œ

The Protocol field is initially assigned as follows:

   Value (in hex)          Protocol

   0001 to 001f            reserved (transparency inefficient)
   0021                    Internet Protocol
   0023                  * ISO CLNP
   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                  * ISO CLNP 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 the protocol named in the Protocol field. You find the end of the Information field by locating the closing Flag Sequence and allowing two octets for the Frame Check Sequence field. The default maximum length of the Information field is 1500 octets. By prior agreement, consenting PPP implementations may use other values for the maximum Information field length.

On transmission, the Information field may be padded with an arbitrary number of octets up to the maximum length. It's the responsibility of each protocol to disambiguate padding characters from real information ๐Ÿ™ƒ

Frame Check Sequence (FCS) Field

The Frame Check Sequence field is normally 16 bits (two octets). By prior agreement, consenting PPP implementations may use a 32-bit (four-octet) FCS for improved error detection ๐Ÿ”ฅ

The FCS field is calculated over all bits of the Address, Control, Protocol and Information fields, not including any start and stop bits (asynchronous) and any bits (synchronous) or octets (asynchronous) inserted for transparency. This doesn't include the Flag Sequences or FCS field. The FCS is transmitted with the coefficient of the highest term first.

For more information on the specification of the FCS, see ISO 3309 or CCITT X.25.

๐Ÿ“ Note: a fast, table-driven implementation of the 16-bit FCS algorithm is shown in Appendix B. This implementation is based on [7] and [8].

Modifications to the Basic Frame Format

The Link Control Protocol can negotiate modifications to the standard PPP frame structure. However, modified frames will always be clearly distinguishable from standard frames ๐Ÿฆ‹โœจ


okay, the Link Control Protocol (LCP) is the one that handles establishing, configuring, maintaining and terminating the point-to-point connection ๐Ÿ‘‘ LCP goes through four distinct phases:

Before any network-layer datagrams (e.g., IP) may be exchanged, LCP must first open the connection through an exchange of Configure packets. This exchange is complete, and the Open state entered, once a Configure-Ack packet (described below) has been both sent and received. Any non-LCP packets received before this exchange is complete are silently discarded ๐Ÿ™…โ€โ™€๏ธ

It's important to note that LCP handles configuration only of the link. LCP does not handle configuration of individual network-layer protocols. In particular, all Configuration Parameters which are independent of particular network-layer protocols are configured by LCP. All Configuration Options are assumed to be at default values unless altered by the configuration exchange ๐Ÿ’–

LCP allows an optional Link Quality Determination phase following transition to the LCP Open state. In this phase, the link is tested to determine if the link quality is sufficient to bring up network-layer protocols. This phase is completely optional. LCP may delay transmission of network-layer protocol information until this phase is completed ๐Ÿงช

The procedure for Link Quality Determination is unspecified and may vary from implementation to implementation, or because of user-configured parameters, but only so long as the procedure doesn't violate other aspects of LCP. One suggested method is to use LCP Echo-Request and Echo-Reply packets ๐Ÿซง

What's important is that this phase may persist for any length of time. Therefore, implementations should avoid fixed timeouts when waiting for their peers to advance to phase 3. Patience is a whole vibe ๐Ÿข๐Ÿ’œ

Phase 3: Network-Layer Protocol Configuration Negotiation

Once LCP has finished the Link Quality Determination phase, network-layer protocols may be separately configured by the appropriate Network Control Protocols (NCP), and may be brought up and taken down at any time. If LCP closes the link, it informs the network-layer protocols so that they may take appropriate action ๐ŸŒท

LCP may terminate the link at any time. This will usually be done at the request of a human user, but may happen because of a physical event such as the loss of carrier, or the expiration of an idle-period timer. Byeee for now ๐Ÿ‘‹๐ŸŒธ

4.1. The LCP Automation

4.1.1. Overview

okay so LCP is specified by a bunch of packet formats and a finite-state automation ๐Ÿค“ This section gives you an overview of the LCP automation, followed by a representation of it as both a state diagram and a state transition table ๐Ÿ“Š

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 automation is defined by events, state transitions and actions. Events include receipt of external commands such as Open and Close, expiration of the Restart timer, and receipt of packets from a LCP peer. Actions include the starting of the Restart timer and transmission of packets. โฑ๏ธ๐Ÿ’ซ

4.1.2. State Diagram โœจ

okay so this state diagram is basically the plot ๐ŸŽฌ of how both ends agree on Configuration Options (aka opening the PPP connection) and later close it again ๐Ÿ’…. The state machine starts out in the Closed state (1) ๐Ÿ’ค. Once it reaches the Open state (6), both ends have literally sent AND received a Configure-Ack packet, so they're officially on the same page ๐Ÿซถ

In the diagram, events sit above the horizontal lines and actions sit below them ๐Ÿงš. Configure-Naks and Configure-Rejects get lumped together here ๐Ÿ™ˆ. They're not the same thing, and they do different (kinda similar) jobs, but at this zoom level they always cause the same transition, so the diagram doesn't bother splitting them.

bestie, if you're actually implementing this, the implementation should be done by consulting the state transition table in the next section, NOT this diagram. the diagram is the big picture, the table is the real rulebook ๐Ÿ“–
    +------------------------------+
    |                              |
    V                              |
+---2---+           PO +---1---+        RTA +---7---+      |
|       |<-------------|       |<-----------|       |      |
|Listen |              |Closed |            |Closing|      |
RCR |       | C            |       | PLD        |       |      |
+----|       |----->+------>|       |<---Any     |       |<--+  |
|scr +-------+      ^       +-------+    State   +-------+   |  |
|                   |     AO  |                    ^   | TO  |  |
|       +-----------+     --- |                    |   +---->+  |
|       |                 SCR |     C              |     str ^  |
|    C  |   RCN/TO            |   +----------------+         |  |
|    -- | +-------->+<--------+   | str                      |  |
|       | | scr     |             |                          |  |
|    +---3---+      V   TO  +---4---+            +-------+   |  |
|    |       |<-----+<------|       |<-----------|       |   |  |
|    | Req-  |          scr | Ack-  |        scn | Good  |   |  |
|    | Sent  | RCA          | Rcvd  | RCR        | Req?  |   |  |
|    |       |------------->|       |----------->|       |   |  |
|    +-------+              +-------+            +-------+   |  |
|       | ^                                         |        |  |
|   RCR | +<--------+                               |        |  |
|   --- | |         |     TO        RCN         --- |        |  |
|       | | ---     +---------+   +-----+       sca |        |  |
|       | | scn           scr |   | scr |           V        |  |
|       V | scn           scr |   | scr |           V        |  |
+--->|       |------------->|       |<--+        |       |---+  |
| 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 or
RTR - Receive-Terminate-Req                   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

here's the full table ๐Ÿ’…. States go across the top, events get read going down, and each cell is written as action/new-state ๐ŸŽ€. When two actions get triggered by the same event, they're joined with an & like a power couple ๐Ÿ‘‘, written as 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/1    scj/1    scj/1    scj/1    scj/1  1 scj/1
 RER  | sta/1   sta/2      3        4        5      ser/1      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 triggered by events ๐Ÿ’ซ some come from commands run at the local end (Active-Open, Passive-Open, and Close ๐ŸŽฎ), some come from packets arriving from the remote end (Receive-Configure-Request, Receive-Configure-Ack, Receive-Configure-Nak, Receive-Terminate-Request, and Receive-Terminate-Ack ๐Ÿ“ฌ), and some come from the Restart timer going off after being started by other events (Timeout โฐ).

here's the lineup of LCP events ๐Ÿง

Active-Open (AO)

the Active-Open event is when the network administrator (human or program ๐Ÿค–) runs an Active-Open command locally ๐Ÿš€. 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 Active-Open's chill twin ๐Ÿ˜Œ. Instead of jumping straight into swapping configuration packets, LCP should wait for the peer to send the first packet. That only happens after an Active-Open event in the LCP peer.

Close (C)

the Close event is when someone runs a Close command locally ๐Ÿ™…โ€โ™€๏ธ. When that happens, LCP should immediately try to close the connection.

Timeout (TO)

the Timeout event is the Restart timer expiring โณ, and the LCP Restart timer gets started because of other LCP events. The Restart timer is what times out Configure-Request and Terminate-Request transmissions. When it expires, a Timeout event fires, and that retransmits the matching Configure-Request or Terminate-Request packet ๐Ÿ”. The Restart timer MUST be configurable, but should default to three (3) seconds โฑ๏ธ.

Receive-Configure-Request (RCR)

this one happens when a Configure-Request packet shows up from the LCP peer ๐Ÿ“ฉ. It's basically the peer saying "I want to open an LCP connection," and it might also specify Configuration Options ๐ŸŽ€. The Configure-Request packet gets the full breakdown in a later section.

Receive-Configure-Ack (RCA)

this happens when a valid Configure-Ack packet arrives from the LCP peer โœ…. The Configure-Ack is a positive response to a Configure-Request packet, so it's a big ol' yes ๐Ÿ’–.

Receive-Configure-Nak (RCN)

this one happens when a valid Configure-Nak or Configure-Reject packet arrives from the LCP peer ๐Ÿ™…. Both of those are negative responses to a Configure-Request packet, so it's more of a "not quite" energy ๐Ÿซ .

Receive-Terminate-Request (RTR)

this happens when a Terminate-Request packet arrives from the LCP peer ๐Ÿ‘‹. The Terminate-Request packet means the peer wants to close the LCP connection.

Receive-Terminate-Ack (RTA)

this happens when a Terminate-Ack packet arrives from the LCP peer ๐Ÿฆ‹. The Terminate-Ack is the response to a Terminate-Request packet.

Receive-Code-Reject (RCJ)

this one fires when a Code-Reject packet arrives from the LCP peer ๐Ÿšจ. The Code-Reject packet communicates an error that immediately closes the connection. yikes ๐Ÿ’€

Receive-Unknown-Code (RUC)

this happens when an un-interpretable packet arrives from the LCP peer ๐Ÿคทโ€โ™€๏ธ. The Code-Reject packet is the response to an unknown packet.

Receive-Echo-Request (RER)

this one happens when an Echo-Request, Echo-Reply, or Discard-Request packet arrives from the LCP peer ๐Ÿ“ฃ. The Echo-Reply packet is the response to an Echo-Request packet. There is no reply to a Discard-Request, so it just goes into the void ๐ŸŒŒ.

Physical-Layer-Down (PLD)

this event happens when the Physical Layer says it's down ๐Ÿ”Œ. that's the hardware-level plot twist nobody wants ๐Ÿ˜ญ

4.1.5. Actions ๐ŸŽฌ

okay so actions are what the LCP state machine actually does once an event hits ๐Ÿ’…. they're usually sending packets and/or starting or stopping the Restart timer. here's the whole lineup โœจ

Send-Configure-Request (scr)

The Send-Configure-Request action transmits a Configure-Request packet. this is basically the "I wanna open an LCP connection with this specific set of Configuration Options" move ๐Ÿ™Œ. the Restart timer gets started right after the Configure-Request goes out, to guard against packet loss ๐Ÿ›ก๏ธ.

Send-Configure-Ack (sca)

The Send-Configure-Ack action transmits a Configure-Ack packet. it acknowledges the receipt of a Configure-Request packet with an acceptable set of Configuration Options โœ….

Send-Configure-Nak (scn)

The Send-Configure-Nak action transmits a Configure-Nak or Configure-Reject packet, as appropriate. this is the negative response ๐Ÿ™…, reporting the receipt of a Configure-Request with an unacceptable set of Configuration Options. Configure-Nak packets are used to refuse a Configuration Option value and suggest a new, acceptable one ๐Ÿ”„. Configure-Reject packets are used to refuse all negotiation about a Configuration Option, typically because it's not recognized or implemented ๐Ÿšซ. the difference between Configure-Nak vs. Configure-Reject is more fully described in the section on LCP Packet Formats, so go check that out ๐Ÿ“–.

Send-Terminate-Req (str)

The Send-Terminate-Request action transmits a Terminate-Request packet. this indicates the desire to close an LCP connection ๐Ÿ‘‹. the Restart timer is started after the Terminate-Request is transmitted, to guard against packet loss.

Send-Terminate-Ack (sta)

The Send-Terminate-Request action transmits a Terminate-Ack packet. this acknowledges the receipt of a Terminate-Request packet 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 the receipt of an unknown type of packet. it's an unrecoverable error ๐Ÿ’€ which causes immediate transitions to the Closed state on both ends of the link. no recovering from that one, bestie ๐Ÿ˜ญ.

Send-Echo-Reply (ser)

The Send-Echo-Reply action transmits an Echo-Reply packet. this acknowledges the receipt of an Echo-Request packet ๐Ÿ“.


4.1.6. States ๐ŸŒˆ

okay now for the detailed tea on each LCP state โ˜•. let's gooo ๐Ÿš€.

Closed (1)

The initial and final state is the Closed state. in Closed the connection is down and there's no attempt 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 can kick you out of Closed: Active-Open and Passive-Open ๐Ÿ”‘. on an Active-Open, a Configure-Request is transmitted, the Restart timer is started, and the Request-Sent state is entered. on a Passive-Open, the Listen state is entered immediately ๐Ÿ‘‚. upon receipt of any packet, with the exception of a Terminate-Ack, a Terminate-Ack is sent back. Terminate-Acks are silently discarded to avoid creating a loop ๐Ÿ”.

the Restart timer is not running in Closed. and the Physical Layer connection may be disconnected at any time when in the LCP Closed state ๐Ÿ”Œ.

Listen (2)

the Listen state is giving similar to Closed ๐Ÿ‘€: the connection is down and there's no attempt to open it. the difference is that peer connection requests are no longer rejected ๐Ÿ™‹โ€โ™€๏ธ.

upon receipt of a Configure-Request, a Configure-Request is immediately transmitted and the Restart timer is started. 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 exits its passive state and begins to actively open the connection ๐ŸŽ‰. Terminate-Ack packets are sent in response to either Configure-Ack or Configure-Nak packets,

the Restart timer is not running in Listen ๐Ÿ’ค.

Request-Sent (3)

in Request-Sent an active attempt is made to open the connection ๐Ÿ’ช. a Configure-Request has been sent and the Restart timer is running, but a Configure-Ack hasn't been received yet, nor has one been sent.

upon receipt of a Configure-Ack, the Ack-Received state is immediately entered โœ…. upon receipt of a Configure-Nak or Configure-Reject, the Configure-Request Configuration Options are adjusted appropriately, a new Configure-Request is transmitted, and the Restart timer is restarted ๐Ÿ”. similarly, upon the expiration of the Restart timer, a new Configure-Request goes out and the Restart timer is restarted again. upon receipt of a Configure-Request, the Configuration Options are examined and if they're 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 implementing the Passive-Open and Close events. otherwise the LCP peer might think the connection is open ๐Ÿ˜ฑ. processing of 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 hasn't been transmitted yet.

upon receipt of a Configure-Request with acceptable Configuration Options, 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. upon the expiration of the Restart timer, 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 hasn't been received yet ๐Ÿ“ค. the Restart timer is always running in Ack-Sent โฑ๏ธ.

upon receipt of a Configure-Ack, the Restart timer is stopped and the Open state is entered ๐ŸŽ‰. upon receipt of a Configure-Nak or Configure-Reject, the Configure-Request Configuration Options are adjusted appropriately, a new Configure-Request is transmitted, and the Restart timer is restarted. upon the expiration of the Restart timer, a new Configure-Request is transmitted, the Restart timer is restarted, and the state machine returns to Request-Sent ๐Ÿ”.

Open (6)

Open is the main character moment ๐Ÿ‘‘. a connection exists here and data may be communicated over the link ๐Ÿ“ก. the Restart timer is not running in Open.

in normal operation, only two events can move you out of Open. upon receipt of a Close command, a Terminate-Request is transmitted, the Restart timer is started, and the Closing state is entered ๐Ÿšช. upon receipt of a Terminate-Request, a Terminate-Ack is transmitted and the Closed state is entered. upon receipt of an Echo-Request, 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 ๐Ÿซถ.

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 a Terminate-Ack hasn't been received yet โณ.

upon receipt of a Terminate-Ack, the Closed state is immediately entered โœจ. upon the expiration of the Restart timer, 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 must be taken to implement the Passive-Open event. otherwise, it's possible for the LCP peer to think the connection is open ๐Ÿ˜ฌ. processing of 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 ๐Ÿ”

okay real talk, the protocol makes a reasonable attempt at avoiding Configuration Option negotiation loops ๐Ÿ™. however, the protocol does not guarantee that loops won't happen. like with any negotiation, you can configure two PPP implementations with conflicting policies that will never converge ๐Ÿ’”. it's also possible to configure policies that do converge, but take significant time to get there ๐ŸŒ. 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 โš™๏ธ.

for example, implementations could take care to avoid Configure-Request or Terminate-Request livelocks by using a Max-Retries counter ๐Ÿ”ข. a Configure-Request livelock could happen when an originating PPP sends and re-sends a C-R without getting a reply (e.g., the receiving PPP entity may have died ๐Ÿ’€). a Terminate-Request livelock could happen when the originating PPP sends and re-sends a T-R without receiving a Terminate-Ack (e.g., the T-A may have been lost, but the remote PPP may have already terminated ๐Ÿซ ).

Max-Retries indicates the number of packet retransmissions that are allowed before there's reasonable assurance that a livelock situation exists ๐Ÿ“Š. Max-Retries MUST also be configurable, but should default to ten (10) retransmissions ๐Ÿ”Ÿ๐Ÿ’–.

4.3. Packet Format โœจ

okay so, 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 LCP packet format at a glance. everything gets sent 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 ๐Ÿงš

the Code field is one octet and tells you what kind of LCP packet you're looking at. the codes go like this:

   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 ๐Ÿ’˜

the Identifier field is one octet, and its whole job is helping match requests with their replies ๐Ÿฆ‹

Length ๐Ÿ“

the Length field is two octets and says how long the LCP packet is, counting the Code, Identifier, Length and Data fields. any octets outside the range of the Length field are Data Link Layer padding, so they should be ignored when received ๐Ÿ™ˆ

Data ๐Ÿซถ

the Data field is zero or more octets, as the Length field says. what the Data field looks like depends on the Code field ๐Ÿ’…

here's the vibe check: no matter which Configuration Options are enabled, every LCP packet always goes out in the full, standard form, like none of the options were turned on. why? so a Configure-Request is always recognizable, even when one end of the link wrongly thinks the link is already Open ๐Ÿ‘€๐Ÿ”ฅ

this doc describes Version 1 of the Link Control Protocol. for simplicity's sake (we love simple ๐Ÿ’…), there's no version field in the LCP packet. if a new version of LCP is ever needed, the plan is for a new Data Link Layer Protocol field value to tell Version 1 LCP apart from all the other versions. a Version 1 LCP implementation that's working properly will always answer unknown Protocols (including other versions) with an easy-to-spot Version 1 packet, which gives other versions a predictable fallback ๐Ÿงšโœจ


4.3.1. Configure-Request ๐ŸŽ€

Description ๐Ÿ’Œ

an LCP implementation that wants to open a connection MUST transmit an LCP packet with the Code field set to 1 (Configure-Request), and the Options field filled with any changes it wants to make to the default link Configuration Options ๐ŸŒธ

when a Configure-Request comes in, an appropriate reply MUST be transmitted ๐Ÿ“จ

a summary of the Configure-Request packet format is shown below. the fields go 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             |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   | Options ...
   +-+-+-+-+

Code ๐Ÿ’œ

1 for Configure-Request.

Identifier ๐Ÿ”

the Identifier field should be changed on each transmission. when one comes in, its Identifier should be copied into the Identifier field of the appropriate reply packet ๐Ÿฆ‹

Options ๐ŸŽ

the Options field is variable in length and holds the list of zero or more Configuration Options the sender wants to negotiate. all Configuration Options get negotiated at the same time, no cap ๐Ÿซถ the format of Configuration Options gets explained further in a later section โœจ


4.3.2. Configure-Ack ๐Ÿ’–

Description ๐Ÿ’…

if every Configuration Option in a Configure-Request is both recognizable and acceptable, then an LCP implementation should transmit an 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 too. the acknowledged Configuration Options MUST NOT be reordered or modified in any way. zero touching, periodt ๐Ÿ’…

on reception of a Configure-Ack, the Identifier field must match that of the last transmitted Configure-Request, or the packet is invalid. additionally, 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 ๐Ÿ™ˆ

reception of a valid Configure-Ack indicates that all Configuration Options sent in the last Configure-Request are acceptable โœจ

a summary of the Configure-Ack packet format is shown below. the fields go 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             |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   | Options ...
   +-+-+-+-+

Code ๐Ÿ’œ

2 for Configure-Ack.

Identifier ๐Ÿ”

a copy of the Identifier field from the Configure-Request that caused this Configure-Ack ๐Ÿฆ‹

Options ๐ŸŽ

the Options field is variable in length and holds the list of zero or more Configuration Options the sender is acknowledging. all Configuration Options are always acknowledged simultaneously ๐Ÿซถ


4.3.3. Configure-Nak ๐ŸŒˆ

Description ๐Ÿ”ฅ

if every element of the received Configuration Options is recognizable but some aren't acceptable, then an LCP implementation should transmit an 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 that 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 isn't listed, then it may be appended to the list of nak'd Configuration Options, so the remote end lists it 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 ๐Ÿ’Œ

a summary of the Configure-Nak packet format is shown below. the fields go 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             |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   | Options ...
   +-+-+-+-+

Code ๐Ÿ’œ

3 for Configure-Nak.

Identifier ๐Ÿ”

a copy of the Identifier field from the Configure-Request that caused this Configure-Nak ๐Ÿฆ‹

Options ๐ŸŽ

the Options field is variable in length and holds the list of zero or more Configuration Options the sender is nak'ing. all Configuration Options are always nak'd simultaneously ๐Ÿซถ


4.3.4. Configure-Reject ๐Ÿฆ„

Description ๐Ÿฅ€

if some Configuration Options received in a Configure-Request are not recognizable, or aren't acceptable for negotiation (as configured by a network manager), then an LCP implementation should transmit an 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 that 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 ๐Ÿ’ซ

a summary of the Configure-Reject packet format is shown below. the fields go 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             |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   | Options ...
   +-+-+-+-+

Code ๐Ÿ’œ

4 for Configure-Reject.

Identifier ๐Ÿ”

a copy of the Identifier field from the Configure-Request that caused this Configure-Reject ๐Ÿฆ‹

Options ๐ŸŽ

the Options field is variable in length and holds the list of zero or more Configuration Options the sender is rejecting. all Configuration Options are always rejected simultaneously ๐Ÿซถ

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

Description ๐Ÿฆ‹

Okay bestie, LCP has Terminate-Request and Terminate-Ack Codes so it can close a connection politely. ๐Ÿ’… It's the goodbye party, and everyone gets a turn to say bye. ๐Ÿซถ

An LCP implementation that wants to close a connection should send an LCP packet with the Code field set to 5 (Terminate-Request) and the Data field filled with whatever data it likes. Terminate-Request packets should keep getting sent until a Terminate-Ack shows up, the Physical Layer says it has gone down, or enough of them have gone out that the remote end is down with reasonable certainty. ๐Ÿ˜ญ

When a Terminate-Request comes in, an LCP packet MUST be sent back with the Code field set to 6 (Terminate-Ack), the Identifier field copied from the Terminate-Request, and the Data field filled with any data you want. ๐Ÿ‘‘

If a Terminate-Ack shows up without anyone asking for one, that means the connection has been closed. ๐ŸŒธ

A quick look at the Terminate-Request and Terminate-Ack packet formats. Fields go 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 is how requests and replies get matched up. Main character matching energy. โœจ

Data ๐Ÿ’œ

The Data field is zero or more octets of uninterpreted data for the sender to use. It can be any binary value, and its length can be anywhere from zero up to the established value for the peer's MRU. Totally flexible. ๐ŸŒˆ


4.3.6. Code-Reject ๐Ÿ™ˆ

Description ๐Ÿฆ‹

If an LCP packet arrives with a Code nobody recognises, that tells us one of the communicating LCP implementations is faulty or incomplete. Not great, not terrible, just a little sad. ๐Ÿ˜ญ That error MUST be reported back to the sender of the unknown Code by sending an LCP packet with the Code field set to 7 (Code-Reject), and the inducing packet copied into the Rejected-Packet field.

When a Code-Reject comes in, an LCP implementation should make an immediate transition to the Closed state, and should report the error, since it's unlikely the situation can be fixed automatically. ๐Ÿ’€

Here's the Code-Reject 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             |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   | Rejected-Packet ...
   +-+-+-+-+-+-+-+-+

Code ๐Ÿ“

  • 7 for Code-Reject.

Identifier ๐Ÿงš

The Identifier field is one octet and is for use by the transmitter.

Rejected-Packet ๐Ÿฅ€

The Rejected-Packet field contains 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 comply with the established value of the peer's MRU. โœ‚๏ธ


4.3.7. Protocol-Reject ๐ŸŒˆ

Description ๐Ÿฆ‹

If a PPP frame arrives with an unknown Data Link Layer Protocol, the remote end is trying to use a protocol the local end doesn't support. This usually happens when the remote end tries to configure something new that isn't supported. ๐Ÿ™ƒ

If the LCP state machine is in the Open state, this error MUST be reported back to the sender of the unknown protocol by sending an LCP packet with the Code field set to 8 (Protocol-Reject), the Rejected-Protocol field set to the received Protocol, and the Data field filled with any data you like.

When a Protocol-Reject comes in, an LCP implementation should stop transmitting frames of the indicated protocol. Hint taken. ๐Ÿคซ

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. Ignore and move on, babe. ๐Ÿ’…

Here's the Protocol-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             |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |       Rejected-Protocol       |      Rejected-Information ...
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Code ๐Ÿ“

  • 8 for Protocol-Reject.

Identifier ๐Ÿงš

The Identifier field is one octet and is for use by the transmitter.

Rejected-Protocol ๐Ÿฅ€

The Rejected-Protocol field is two octets and contains the Protocol of the Data Link Layer frame being rejected.

Rejected-Information ๐Ÿฅ€

The Rejected-Information field contains a copy from the frame being rejected. It begins with the Information field, and it doesn't include any PPP Data Link Layer headers or the FCS. The Rejected-Information field should be truncated to comply with the established value of the peer's MRU. โœ‚๏ธ


4.3.8. Echo-Request and Echo-Reply ๐Ÿ“

Description ๐Ÿฆ‹

LCP includes Echo-Request and Echo-Reply Codes so it can provide a Data Link Layer loopback mechanism for exercising both directions of the link. ๐Ÿ’– This is super useful for debugging, link quality determination, performance testing, and a bunch of other stuff. ๐Ÿ”ฅ

An Echo-Request sender transmits an LCP packet with the Code field set to 9 (Echo-Request) and the Data field filled with any data it likes, up to but not exceeding the receiver's established MRU. ๐Ÿ“ฆ

Upon reception of an Echo-Request, an LCP packet MUST be transmitted with the Code field set to 10 (Echo-Reply), the Identifier field copied from the received Echo-Request, and the Data field copied from the Echo-Request. Truncate as necessary so it never goes over the peer's established MRU. โœ‚๏ธ

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. ๐Ÿ™…โ€โ™€๏ธ

Here's the Echo-Request and Echo-Reply 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             |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                         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 it's modified by a Configuration Option, the Magic-Number MUST always be transmitted as zero and MUST always be ignored on reception. Any further use of the Magic-Number is beyond the scope of this discussion, so we'll leave it there for now. ๐Ÿค

Data ๐Ÿ’œ

The Data field is zero or more octets of uninterpreted data for the sender to use. It can be any binary value, with a length from zero up to the established value for the peer's MRU. ๐ŸŒˆ


4.3.9. Discard-Request ๐Ÿซง

Description ๐Ÿฆ‹

LCP includes a Discard-Request Code to provide a Data Link Layer data sink. This is for exercising the local-to-remote direction of the link. It's handy for debugging, performance testing, and lots of other things. ๐Ÿงช

A discard sender transmits an LCP packet with the Code field set to 11 (Discard-Request) and the Data field filled with any data it likes, up to but not exceeding the receiver's established MRU. ๐Ÿ“ฆ

A discard receiver MUST simply throw away any Discard-Request it receives. Gone. Bye. ๐Ÿ—‘๏ธ

Discard-Request packets may only be sent in the LCP Open state. ๐Ÿ’…

Here's the Discard-Request 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             |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                         Magic-Number                          |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |    Data ...
   +-+-+-+-+

Code ๐Ÿ“

  • 11 for Discard-Request.

Identifier ๐Ÿงš

The Identifier field is one octet and is for use by the Discard-Request transmitter.

Magic-Number โœจ

The Magic-Number field is four octets and helps detect loopbacked links. Unless it's modified by a configuration option, the Magic-Number MUST always be transmitted as zero and MUST always be ignored on reception. Further use of the Magic-Number is beyond the scope of this discussion. ๐Ÿค

Data ๐Ÿ’œ

The Data field is zero or more octets of uninterpreted data for the sender to use. It can be any binary value, with a length from zero up to the established value for the peer's MRU. ๐ŸŒˆ


4.4. Configuration Options ๐ŸŽ€

LCP Configuration Options let you negotiate changes to the standard characteristics of a point-to-point link. ๐Ÿฆ‹ Things you can negotiate include the maximum receive unit, async control character mapping, the link authentication method, the link encryption method, and so on. The 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 list of Configuration Options 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. Some Configuration Options can override this general rule and be listed more than once. When that happens, the effect is specific to that option and is defined by each such option. ๐Ÿงฉ

Also unless otherwise specified, all Configuration Options apply in a half-duplex fashion. Once negotiated, they only apply to one direction of the link. Usually that's the receive direction, looked at from the point of view of the Configure-Request sender. โ†”๏ธโœจ

4.4.1. Format ๐ŸŽ€

okay so here's the Configuration Option format at a glance ๐Ÿ‘€ The fields are sent left to right, bestie ๐Ÿฆ‹

 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 ๐Ÿ’– This one is a single octet, and it tells you what kind of Configuration Option you're looking at. For the freshest values, check the most recent "Assigned Numbers" RFC [11] โœจ

Length ๐Ÿงš Also one octet! It covers the whole Configuration Option, so the Type, Length and Data fields are all counted. Now here's the tea: if a negotiable Configuration Option shows up in a Configure-Request with an invalid Length, a Configure-Nak should be transmitted. That Configure-Nak includes the desired Configuration Option with an appropriate Length and Data ๐Ÿ”ฅ

Data ๐ŸŒธ This is zero or more octets carrying the value or other info for the option. Its format and length are decided by the Type and Length fields, so the Data is basically whatever those two say it is ๐Ÿ’…


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

okay this section is about the IP Control Protocol (IPCP), and it is literally the one in charge of configuring, enabling, and disabling the IP protocol modules on both ends of the point-to-point link ๐Ÿ‘‘ Just like the Link Control Protocol, it gets all this done by swapping packets back and forth ๐Ÿซถ

The timing is super specific, so pay attention ๐Ÿ‘€ IPCP packets may not be exchanged until LCP has reached the network-layer Protocol Configuration Negotiation phase. And then IP datagrams may not be exchanged until IPCP has first opened the connection. No skipping ahead, bestie ๐Ÿ™ˆ

IPCP is basically the same as the Link Control Protocol, with the following exceptions:

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 it ๐Ÿ’€

Timeouts

IPCP packets may not be exchanged until the Link Control Protocol has reached the network-layer Protocol Configuration Negotiation phase ๐Ÿ’… Also, an implementation should be prepared to wait for Link Quality testing to finish before it times out waiting for a Configure-Ack or some other response. Patience is a whole vibe ๐ŸŒˆ It is suggested that an implementation give up only after user intervention or a configurable amount of time.

Configuration Option Types

IPCP has its own separate set of Configuration Options ๐ŸŽ€ For the most up-to-date values of the type field, check the most recent "Assigned Numbers" RFC [11].

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. No shortcuts, periodt ๐Ÿ’–

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. Bigger IP datagrams must be fragmented as necessary ๐Ÿงš If a system wants to avoid fragmentation and reassembly, it should use the TCP Maximum Segment Size option [12], or a similar mechanism, to discourage others from sending large datagrams. That's a whole strategy, bestie ๐Ÿ”ฅ


A. Asynchronous HDLC ๐ŸŒธ

This appendix summarizes the modifications to ISO 3309-1979 proposed in ISO 3309:1984/PDAD1 โœจ These modifications allow HDLC to be used with 8-bit asynchronous links. It's giving "making old tech work on new links" ๐Ÿ’…

Transmission Considerations

Each octet is delimited by a start and a stop element ๐Ÿซถ

Flag Sequence

The Flag Sequence is a single octet and indicates the beginning or end of a frame. It consists of the binary sequence 01111110 (hexadecimal 0x7e) ๐Ÿ’œ

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 examines the entire frame between the two Flag Sequences. Each Flag Sequence, Control Escape octet and octet with value less than hexadecimal 0x20 is replaced by a two character 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) ๐ŸŒˆ

Prior to FCS computation, the receiver examines the entire frame between the two Flag Sequences. For each Control Escape octet, that octet is removed and bit 6 of the following octet is complemented. A Control Escape octet immediately preceding the closing Flag Sequence indicates an invalid frame ๐Ÿ™ˆ

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 may make this more clear. 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 (framing error). They can also be aborted by transmitting a Control Escape octet followed immediately by a closing Flag Sequence ๐Ÿ’€

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 is 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. 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.

/*
 * FCS lookup table as calculated by the table generator in section 2.
 */
static unsigned short 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.
 */
unsigned short pppfcs(fcs, cp, len)
    register unsigned short fcs;
    register unsigned char *cp;
    register int len;
{
    while (len--)
        fcs = (fcs >> 8) ^ fcstab[(fcs ^ *cp++) & 0xff];

    return (fcs);
}

B.2. Fast FCS table generator ๐ŸŒˆ

The following code creates the lookup table used to calculate the FCS. Bestie, this is the one that makes the magic table from B.1 โœจ

/*
 * 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("static unsigned short fcstab[256] = {");
    for (b = 0; ; ) {
        if (b % 8 == 0)

            printf("0);

        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("0;0);
}

References โœจ

[1] Electronic Industries Association, "Interface Between Data Terminal Equipment and Data Communications Equipment Employing Serial Binary Data Interchange", EIA Standard RS-232-C, August 1969. ๐Ÿ”Œ

[2] International Organization For Standardization, "Data Communication - High-level Data Link Control Procedures - Frame Structure", ISO Standard 3309-1979, 1979. ๐Ÿงฑ

[3] International Organization For Standardization, "Data Communication - High-Level Data Link Control Procedures - Elements of Procedures", ISO Standard 4335-1979, 1979. ๐Ÿ“‹

[4] International Organization For Standardization, "Data Communication - High-Level Data Link Control Procedures - Elements of Procedures - Addendum 1", ISO Standard 4335-1979/Addendum 1, 1979. ๐Ÿ“Ž

[5] International Organization For Standardization, "Information Processing Systems - Data Communication - High-level Data Link Control Procedures - Frame structure - Addendum 1: Start/stop Transmission", Proposed Draft International Standard ISO 3309:1983/PDAD1, 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. Morse, G., "Calculating CRC's by Bits and Bytes", Byte, September 1986. ๐Ÿ”ข

[8] LeVan, J., "A Fast CRC", Byte, November 1987. โšก

[9] American National Standards Institute, "American National Standard Code for Information Interchange", ANSI X3.4-1977, 1977. ๐Ÿ”ค

[10] Postel, J., "Internet Protocol", RFC 791, USC/Information Sciences Institute, September 1981. ๐ŸŒ

[11] Reynolds, J.K., and J. Postel, "Assigned Numbers", RFC 1010, USC/Information Sciences Institute, May 1987. ๐Ÿ—‚๏ธ

[12] Postel, J., "The TCP Maximum Segment Size Option and Related Topics", RFC 879, USC/Information Sciences Institute, November 1983. ๐Ÿ“


Security Considerations ๐Ÿ’€

Okay, this part is short but it's a Big Deal, so pay attention bestie ๐Ÿ™ˆ Security issues are not addressed in this memo. ๐Ÿ˜ฌ That's it. That's the whole section. We are not making promises about security in this one, so please don't read anything into it that isn't actually written here. ๐Ÿซฃ

Author'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

Acknowledgments ๐Ÿซถ

Okay so a LOT of people spent serious time helping to build the Point-to-Point Protocol ๐ŸŒธ The full list is way too long to write out, but there are some people who absolutely deserve special thanks, and they are: 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). ๐Ÿ‘‘ Iconic team, no notes. ๐Ÿ’…

๐Ÿ“ฆ where this page comes from