RFC 2341
Cisco Layer Two Forwarding (Protocol) "L2F"
RFC 2341: Cisco Layer Two Forwarding (Protocol) "L2F" ๐
Authors: A. Valencia, M. Littlewood, and T. Kolar, all at Cisco Systems. The header lists them under the Network Working Group. Category: Historic Date: May 1998 Obsoletes / Updates: the header doesn't list anything this RFC obsoletes or updates ๐คทโโ๏ธ
Status of Memo ๐
Okay so this memo describes a historic protocol for the Internet community ๐ฐ๏ธ It does NOT specify an Internet standard of any kind, so don't go treating it like one. Distribution of this memo is unlimited โจ
Copyright Notice ยฉ๏ธ
Copyright (C) The Internet Society (1998). All Rights Reserved.
Abstract ๐
Virtual dial-up lets lots of separate, autonomous protocol domains share the same access gear, like modems, Access Servers, and ISDN routers ๐ Earlier RFCs covered IP dial-up over SLIP [1] and multiprotocol dial-up over PPP [2]. This doc describes the Layer Two Forwarding protocol (L2F), which tunnels the link layer (HDLC, async HDLC, or SLIP frames) of higher-level protocols ๐ฆ With those tunnels, you can split the spot where the initial dial-up server lives from the spot where the dial-up connection actually ends and network access gets provided. Main character energy, honestly ๐
Table of Contents ๐๏ธ
1.0 Introduction 3
1.1 Conventions 3
2.0 Problem Space Overview 3
2.1 Initial Assumptions 3
2.2 Topology 4
2.3 Virtual dial-up Service - a walk-though 5
3.0 Service Model Issues 7
3.1 Security 7
3.2 Address allocation 8
3.3 Authentication 8
3.4 Accounting 8
4.0 Protocol Definition 9
4.1 Encapsulation within L2F 10
4.1.1 Encapsulation of PPP within L2F 10
4.1.2 Encapsulation of SLIP within L2F 10
4.2 L2F Packet Format 10
4.2.1 Overall Packet Format 10
4.2.2 Packet Header 11
4.2.3 Version field 11
4.2.4 Protocol field 11
4.2.5 Sequence Number 12
4.2.6 Packet Multiplex ID 12
4.2.7 Client ID 13
4.2.8 Length 13
4.2.9 Packet Checksum 13
4.2.10 Payload Offset 14
4.2.11 Packet Key 14
4.2.12 Packet priority 14
4.3 L2F Tunnel Establishment 14
4.3.1 Normal Tunnel Negotiation Sequence 15
4.3.2 Normal Client Negotiation Sequence 17
4.4 L2F management message types 18
4.4.1 L2F message type: Invalid 18
4.4.2 L2F_CONF 19
4.4.3 L2F_OPEN, tunnel establishment 20
4.4.4 L2F_OPEN, client establishment 20
4.4.5 L2F_CLOSE 22
4.4.6 L2F_ECHO 22
4.4.7 L2F_ECHO_RESP 23
4.5 L2F Message Delivery 23
4.5.1 Sequenced Delivery 23
4.5.2 Flow Control 23
4.5.3 Tunnel State Table 24
4.5.4 Client State Table 25
5.0 Protocol Considerations 26
5.1 PPP Features 26
5.2 Termination 26
5.3 Extended Authentication 26
5.4 MNP4 and Apple Remote Access Protocol 27
5.5 Operation over IP/UDP 27
6.0 Acknowledgments 27
7.0 References 27
8.0 Security Considerations 28
9.0 Authors' Addresses 28
10.0 Full Copyright Statement 29
1.0 Introduction ๐
The traditional dial-up network service on the Internet is only for registered IP addresses ๐ But there's a new class of virtual dial-up app that lets multiple protocols and unregistered IP addresses hop on too, and people want it ๐ Examples of this class are support for privately addressed IP, IPX, and AppleTalk dial-up via SLIP/PPP across the existing Internet infrastructure ๐ง
Supporting these multiprotocol virtual dial-up apps is a huge win for end users and Internet Service Providers โจ It lets everyone share the very large investments in access and core infrastructure, and it lets local calls get used. It also means existing investments in non-IP protocol apps can keep working in a secure manner while still leveraging the Internet's access infrastructure ๐ซถ
So the point of this RFC is to pin down the issues you run into when you try to fit multiprotocol dial-up services into an existing Internet Service Provider's Point of Presence (called ISP and POP for short, respectively) ๐ข It also describes the L2F protocol, which lets you keep leveraging existing access protocols ๐
1.1. Conventions ๐
The following language conventions are used in the items of specification in this document:
- MUST, SHALL, or MANDATORY: this one is an absolute requirement of the spec. No cap, no skipping it ๐ญ
- SHOULD or RECOMMEND: you should generally follow this for all but exceptional circumstances ๐ซฃ
- MAY or OPTIONAL: this one is truly optional. You can follow it or ignore it, depending on what the implementor needs ๐ธ
2.0 Problem Space Overview ๐ธ
In this section we describe, in high-level terms, the scope of the problem that gets explored in more detail in later sections ๐
2.1 Initial Assumptions ๐
We begin by assuming that Internet access is provided by an ISP, and that the ISP wants to offer services other than the traditional registered IP address-based ones to dial-up users of the network ๐
We also assume that the user of such a service wants all of the security facilities that are available to them in a dedicated dial-up configuration. In particular, the end user requires:
- End System transparency: neither the remote end system nor their home site hosts should require any special software to use this service in a secure manner. Zero extra downloads, bestie ๐
- Authentication as provided via dial-up PPP CHAP or PAP, or through other dialogs as needed for protocols without authentication (e.g., SLIP). This will include TACACS+ and RADIUS solutions as well as support for smart cards and one-time passwords ๐ The authentication should be manageable by the user independently of the ISP.
- Addressing should be as manageable as dedicated dial-up solutions. The address should be assigned by the home site and not the ISP ๐ก
- Authorization should be managed by the home site, the same way it would be in a direct dial-up solution ๐
- Accounting should be performed both by the ISP (for billing purposes) and by the user (for charge-back and auditing) ๐งพ
2.2 Topology ๐ฆ
Okay so here's a generic Internet with Public switched Telephone Network (PSTN) access, which is async PPP via modems, and Integrated Services Digital Network (ISDN) access, which is synchronous PPP access ๐ Remote users (async PPP, SLIP, or ISDN) can reach the Home LAN as if they'd dialed straight into the Home Gateway, even though their physical dial-up actually goes through the ISP Network Access Server ๐ช
...----[L]----+---[L]-----...
|
|
[H]
|
________|________________________
| |
________|__ ______|________
| | | |
| PSTN [R] [R] ISDN |
| Cloud | | Cloud [N]__[U]
| | Internet | |
| | [R] |
[N]______[R] |_____________|
| | |
| | |
[U] |________________________________|
[H] = Home Gateway
[L] = Home LAN(s)
[R] = Router
[U] = Remote User
[N] = ISP Network Access Server ("NAS")
To be continued, bestie ๐ง๐
2.3. Providing Virtual dial-up Services - a walk-through โจ
okay bestie, to make this click, let's walk through what happens when a Virtual dial-up client shows up ๐ง
The Remote User starts a PPP connection to an ISP over either the PSTN or ISDN ๐. The Network Access Server (NAS) picks up and the PPP link gets established ๐.
The ISP does a partial authentication of the end system/user using CHAP or PAP. Only the username field gets read to figure out whether the user needs a Virtual dial-up service ๐ต๏ธโโ๏ธ. It is expected -- but not required -- that usernames will be structured (for example, littlewo@cisco.com). Alternatively, the ISP may keep a database mapping users to services. For Virtual dial-up, that mapping names a specific endpoint, the Home Gateway ๐ .
If a virtual dial-up service is not required, standard access to the Internet may be provided ๐.
If there's no tunnel to the desired Home Gateway yet, one gets initiated ๐. L2F is designed to be largely insulated from the details of the media the tunnel runs over. L2F only requires that the tunnel media provide packet oriented point-to-point connectivity. Obvious examples of such media are UDP, Frame Relay PVC's, or X.25 VC's. Details for L2F operation over UDP are in section 5.5. The L2F packet format spec is in section 4.2, and the message types and semantics start in section 4.4 ๐.
Once the tunnel exists, an unused Multiplex ID (hereafter, "MID") gets allocated, and a connect indication is sent to tell the Home Gateway about this new dial-up session โจ. The Home Gateway either accepts or rejects. A rejection may include a reason indication that can be displayed to the dial-up user, and after that the call should be disconnected ๐ .
The initial setup notification may include the authentication information required to let the Home Gateway authenticate the user and decide to accept or decline the connection ๐. For CHAP, the set-up packet includes the challenge, username and raw response. For PAP or text dialog (i.e., for SLIP users), it includes username and clear text password. The Home Gateway may use this info to finish its authentication, skipping an extra cycle of authentication ๐.
For PPP, the initial setup notification may also include a copy of the LCP CONFACKs sent in each direction that completed LCP negotiation ๐งฉ. The Home Gateway may use this to initialize its own PPP state (so it skips another LCP negotiation), or it may choose to start a new LCP CONFREQ exchange.
If the Home Gateway accepts the connection, it creates a "virtual interface" for SLIP or PPP, the same way it would for a direct-dialed connection ๐. With this "virtual interface" in place, link layer frames can now pass over the tunnel in both directions ๐ฆ. Frames from the remote user are received at the POP, stripped of any link framing or transparency bytes, encapsulated in L2F, and forwarded over the appropriate tunnel.
The Home Gateway accepts these frames, strips L2F, and processes them as normal incoming frames for the appropriate interface and protocol ๐. The "virtual interface" acts very much like a hardware interface, except the hardware is physically located at the ISP POP. The other direction works the same way: the Home Gateway encapsulates the packet in L2F, and the POP strips L2F before transmitting it out the physical interface to the remote user ๐ .
At this point, the connectivity is a point-to-point PPP or SLIP connection. Its endpoints are the remote user's networking application on one end, and the termination of this connectivity into the Home Gateway's SLIP or PPP support on the other ๐. Because the remote user is now just another dial-up client of the Home Gateway access server, client connectivity can be managed with traditional mechanisms for further authorization, protocol access, and filtering ๐ซถ.
Accounting can be performed at both the NAS and the Home Gateway ๐งพ. This document illustrates some Accounting techniques that are possible using L2F, but the policies surrounding such Accounting are outside the scope of this specification.
Because L2F connect notifications for PPP clients contain enough information for a Home Gateway to authenticate and initialize its LCP state machine, the remote user doesn't have to be queried a second time for CHAP authentication, and the client doesn't have to go through multiple rounds of LCP negotiation and convergence ๐. These techniques are meant to optimize connection setup. They are not meant to deprecate any functions required by the PPP specification.
3.0 Service Model Issues ๐
There are several big differences between standard Internet access service and Virtual dial-up service when it comes to authentication, address allocation, authorization and accounting ๐ค. The details of those differences, and the problems they cause, are described below. The mechanisms for Virtual dial-up service are meant to coexist with more traditional mechanisms, so an ISP's POP can serve ISP clients and Virtual dial-up clients at the same time ๐ค.
3.1. Security ๐
For the Virtual dial-up service, the ISP only pursues authentication as far as needed to discover the user's apparent identity (and, by implication, their desired Home Gateway). As soon as that's determined, a connection to the Home Gateway is initiated with the authentication information the ISP gathered. The Home Gateway finishes the authentication by either accepting the connection or rejecting it.
The Home Gateway must also protect against attempts by third parties to establish tunnels to it. Tunnel establishment involves an ISP-to-Home Gateway authentication phase to guard against those attacks ๐ก๏ธ.
3.2. Address Allocation ๐ก
For an Internet service, the user accepts that the IP address may be allocated dynamically from a pool of Service provider addresses. This often means the remote user has little or no access to their home network's resources, because of firewalls and other security policies the home network applies to access from external IP addresses ๐งฑ.
For the Virtual dial-up service, the Home Gateway can sit behind the home firewall and allocate addresses that are internal. Those can be RFC1597 addresses, or non-IP addresses ๐ง . Because L2F tunnels exclusively at the frame layer, the actual policies of such address management don't matter for correct Virtual dial-up service. For all purposes of PPP or SLIP protocol handling, the dial-in user appears to have connected at the Home Gateway ๐.
3.3. Authentication ๐ชช
Authentication of the user happens in three phases: the first at the ISP, and the second and optional third at the Home Gateway.
The ISP uses the username to determine that a Virtual dial-up service is required, then initiates the tunnel connection to the appropriate Home Gateway. Once a tunnel is established, a new MID is allocated and a session is initiated by forwarding the gathered authentication information ๐จ.
The Home Gateway runs the second phase by deciding whether or not to accept the connection. The connection indication may include CHAP, PAP, or textual authentication information. Based on that, the Home Gateway may accept the connection or reject it. For example, it might reject a PAP request if the username/password turn out to be incorrect ๐ โโ๏ธ.
Once the connection is accepted, the Home Gateway is free to run a third phase of authentication at the PPP or SLIP layer. These activities are outside the scope of this specification, but might include an additional cycle of LCP authentication, proprietary PPP extensions, or textual challenges carried via a TCP/IP telnet session ๐ง.
3.4. Accounting ๐
It is a requirement that both the Access gateway and the Home Gateway can provide accounting data, and so both may count packets, octets, and connection start and stop times โฑ๏ธ.
Since Virtual dial-up is an access service, accounting of connection attempts (especially failed ones) is of significant interest ๐. The Home Gateway can reject new connections based on the authentication information the ISP gathered, with corresponding logging. When the Home Gateway accepts a connection and then continues with further authentication, it might disconnect the client later on. For those scenarios, the disconnection indication sent back to the ISP may also include a reason ๐.
Because the Home Gateway can decline a connection based on the authentication information collected by the ISP, accounting can easily tell apart a series of failed connection attempts from a series of brief successful connections ๐งฎ. Without this facility, the Home Gateway must always accept connection requests, and would need to exchange a number of PPP packets with the remote system ๐ฉ.
4.0 Protocol Definition ๐
The protocol definition for Virtual dial-up services requires two areas of standardization ๐ :
- Encapsulation of PPP packets within L2F. The ISP NAS and the Home gateway require a common understanding of the encapsulation protocol, so SLIP/PPP packets can be successfully transmitted and received across the Internet ๐.
- Connection management of L2F and MIDs. The tunnel must be initiated and terminated, as must MIDs within the tunnel. Termination includes diagnostic codes to help diagnose problems and to support accounting ๐ฉบ.
While providing these services, the protocol must address the following required attributes ๐:
- Low overhead. The protocol must impose a minimal additional overhead. This requires a compact encapsulation, and a structure for omitting some portions of the encapsulation where their function isn't required ๐ชถ.
- Efficiency. The protocol must be efficient to encapsulate and deencapsulate โก.
- Protocol independence. The protocol must make very few assumptions about the substrate over which L2F packets are carried ๐ง.
- Simple deployment. The protocol must not rely on additional telecommunication support (for instance, unique called numbers, or caller ID) to operate ๐ฑ.
4.1. Encapsulation within L2F ๐
4.1.1. Encapsulation of PPP within L2F
The PPP packets may be encapsulated within L2F. The packet encapsulated is the packet as it would be transmitted over a physical link ๐. The following are NOT present in the packet:
- Flags
- Transparency data (ACCM for async, bit stuffing for sync)
- CRC
The following ARE still present:
- Address and control flags (unless negotiated away by LCP)
- Protocol value
4.1.2. Encapsulation of SLIP within L2F
SLIP is encapsulated within L2F in much the same way as PPP ๐ซง. The transparency characters are removed before encapsulating within L2F, and so is the framing.
4.2. L2F Packet Format ๐ฆ
4.2.1. Overall Packet Format โจ
Okay so the whole encapsulated packet looks like a little sandwich ๐ฅช๐. You've got the L2F Header on top, then the payload packet (SLIP/PPP) in the middle, then an optional L2F Checksum on the bottom.
---------------------------------
| |
| L2F Header |
| |
---------------------------------
| |
| Payload packet (SLIP/PPP) |
| |
---------------------------------
| |
| L2F Checksum (optional) |
| |
---------------------------------
4.2.2. Packet Format ๐ฆ
An L2F packet is laid out like this, and honestly it's giving bit-level art ๐ญ๐:
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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|F|K|P|S|0|0|0|0|0|0|0|0|C| Ver | Protocol |Sequence (opt)|\
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\
| Multiplex ID | Client ID | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | L2F
| Length | Offset (opt) | |Header
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| Key (opt) | /
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+/
+ (payload) |
+ ..... |
+ ..... |
+ ..... |
+ (payload) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| L2F Checksum (optional) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4.2.3. Version field ๐ฅ
The Ver ("Version") field tells you the major version of the L2F software that made the packet. It MUST contain the value 001. Period ๐ .
If Ver holds a value other than 1, or any bits are non-zero after bit S but before bit C, that means the packet has extensions the receiving end doesn't understand. The packet is handled as an invalid packet, as defined in 4.4.1. Not me being dramatic, but this is a big deal ๐.
4.2.4. Protocol field ๐ธ
The Protocol field says which protocol is riding inside the L2F packet. The legal values (in hex) are:
Value Type Description
0x00 L2F_ILLEGAL Illegal
0x01 L2F_PROTO L2F management packets
0x02 L2F_PPP PPP tunneled inside L2F
0x03 L2F_SLIP SLIP tunneled inside L2F
If a packet comes in with a Protocol of L2F_ILLEGAL, or any other value that isn't recognised, it MUST be treated as an illegal packet as defined in 4.4.1. Nobody gets to be an unknown guest ๐ โโ๏ธ.
4.2.5. Sequence Number ๐
The Sequence number only shows up if the S bit in the L2F header is set to 1. That bit MUST be 1 for all L2F management packets. It MAY be set to 1 for non-L2F management packets. If a non-L2F management packet comes in with the S bit set, then every future L2F packet sent for that MID MUST have the S bit set too (and, by implication, be sent using sequence numbers). For instance, the Home Gateway might choose to force sequenced packet delivery if it spots an NCP opening for a protocol which can not operate with out-of-sequence packets. Bestie, that's a whole plot twist ๐ญ๐ง.
The Sequence number starts at 0 for the first sequenced L2F packet. Each packet after that gets the next increment. So the sequence number is basically a free-running counter, represented modulo 256. Every distinct MID value has its own separate Sequence number state (aka its own counter) ๐ฆโจ.
For packets with the S bit and a sequence number, the sequence number is used to protect against duplicated packets, and it works like this:
The receiving side of the tunnel records the sequence number of each valid L2F packet it receives. If a received packet appears to have a value less than or equal to the last received value, the packet MUST be silently discarded. Otherwise, the packet is accepted, and its sequence number gets recorded as the latest value last received.
For the purposes of detecting duplication, a received sequence value counts as less than or equal to the last received value if it lands in the range from that last value through its 127 successor values. For example, if the last received sequence number was 15, then packets with sequence numbers 0 through 15, as well as 144 through 255, would be considered less than or equal to it, and would be silently discarded. Anything else would be accepted. The wraparound math is lowkey iconic ๐.
4.2.6. Packet Multiplex ID ๐
The Multiplex ID ("MID") identifies a particular connection within the tunnel. Each new connection gets a MID that's currently unused within the tunnel. It is recommended that the MID cycle through the entire 16-bit namespace, to reduce aliasing between previous and current sessions. A MID value that has been used before within a tunnel, has been closed, and is now going to be used again must be considered as an entirely new MID, and initialised as such. Fresh start, no baggage ๐งผโจ.
The MID with value 0 is special. It's used to communicate the state of the tunnel itself, as opposed to any connection inside the tunnel. Only L2F_PROTO packets may be sent using a MID of 0. If any other type is sent on MID 0, the packet is illegal and MUST be processed as defined in 4.4.1. MID 0 is for tunnel business only, babe ๐ โโ๏ธ.
4.2.7. Client ID ๐
The Client ID ("CLID") helps the endpoints demultiplex tunnels when the underlying point-to-point substrate doesn't have an efficient or dependable way to do it directly. With the CLID, you can tell apart multiple tunnels whose packets arrive over the point-to-point media all interleaved, and you don't need any media-specific semantics to do it. Iykyk ๐ซถ.
When transmitting the L2F_CONF message (described below), the peer's CLID MUST be communicated via the Assigned_CLID field. This MUST be a unique non-zero value on the sender's side, which is expected in the Home Gateway's L2F_CONF response, as well as in all future non-L2F_CONF packets received.
The CLID value from the last valid L2F_CONF message received MUST be recorded, and it MUST be used as the CLID field value for all subsequent packets sent to the peer.
Packets with an unknown Client ID MUST be silently discarded.
For the initial packet sent during tunnel establishment, where no L2F_CONF has been received yet, the CLID field MUST be set to 0.
So basically, during L2F_CONF each side gets told its CLID value. Every later packet tagged with that CLID acts like a little name tag that uniquely identifies this peer. Main character energy ๐๐.
4.2.8. Length ๐
Length is the size in octets of the entire packet, including the header, all fields that are present, and the payload. Length does not include the checksum, if there is one. The packet should be silently discarded if the received packet is shorter than the indicated length. Any extra bytes beyond the indicated length MUST be silently ignored. Short packets get dropped, extra bytes get ignored, we move ๐.
4.2.9. Packet Checksum ๐งฎ
The Checksum is present if the C bit is present in the header flags. It's a 16-bit CRC, the same one used by PPP/HDLC (specifically, FCS-16 [3]). It is applied over the entire packet, starting with the first byte of the L2F flags and running through the last byte of payload data. The checksum then gets added as two bytes right after the last byte of payload data. Math girlies, this one's for you ๐ค๐.
4.2.10. Payload Offset ๐ท
The Offset is present if the F bit is set in the header flags. This field says how many bytes past the L2F header the payload data is expected to start. If it's 0, or the F bit isn't set, then the first byte after the last byte of the L2F header is the first byte of payload data.
It's recommended that data skipped because of the payload offset be initialised to 0's.
For architectures where it's more efficient to have the payload start at an aligned 32-bit boundary with respect to the L2F header, it's recommended that the F bit be set, and an offset of 0 be used. Hardware is lowkey picky and this is how we keep it happy ๐งโโ๏ธโจ.
4.2.11. Packet Key ๐
The Key field is present if the K bit is set in the L2F header. The Key is based on the authentication response last given to the peer during tunnel creation (the details of tunnel creation are in the next section). It acts as a key for the life of a session, to resist attacks based on spoofing. If a packet arrives where the Key doesn't match the expected value, the packet MUST be silently discarded. That handling takes precedence over 4.4.1. Anti-spoofing security is a whole vibe ๐ก๏ธ๐ .
The Key value is generated by taking the 128-bit authentication response from the peer, interpreting it as four adjacent 32-bit words in network byte order, XOR'ing these words together, and using the resulting 32-bit value as the Key.
4.2.12. Packet priority ๐จ
If the P bit in the L2F header is set, the packet is a "priority" packet. When it's possible for an implementation, a packet received with the P bit should be processed ahead of previously received unprocessed packets that don't have the P bit. Priority packets cut the line, obviously ๐โโ๏ธ๐จ.
The P bit may be set by an implementation based on criteria that are beyond the scope of this specification. However, it is recommended that PPP keepalive traffic, if there is any, be sent with this bit set. Keepalives get VIP treatment ๐.
4.3. L2F Tunnel Establishment ๐
When the point-to-point link is first initiated between the NAS and the Home Gateway, the endpoints talk to each other on MID 0 before they provide any general L2F services to clients. This chat is used to check that L2F is actually there on the remote end, and to allow any authentication that's needed. Verifying the vibe before the party starts ๐๐ซถ.
The protocol for this negotiation is always 1, which means L2F management. The message itself is structured as a sequence of single octets, where each octet indicates an option, followed by zero or more further octets formatted however that option needs them to be ๐ง.
4.3.1 Normal Tunnel Negotiation Sequence
okay so this is the main event ๐ โจ it walks through a "typical" connection from start to finish, and then we'll get into what happens when things go sideways. ๐
each packet gets shown as a source->destination line, then the L2F packet fields, then the body underneath. we'll get into the exact octet encoding later, so don't stress about bytes yet ๐ซถ
this example uses the Key option but not the Offset and Checksum options. the Length field would still be there, since it reflects the actual length of the packet once it's encoded as an octet stream ๐
1. NAS->GW:
Proto=L2F, Seq=0, MID=0, CLID=0, Key=0
L2F_CONF
Name: NAS_name
Challenge: Rnd
Assigned_CLID: 22
the NAS decides a tunnel needs to be set up from the NAS to the GW ๐ธ so it sends an L2F packet with Proto set to say it's carrying an L2F management message.
since the tunnel is being started, Key is 0. the sequence number starts at 0, and MID is 0 because this is all about the tunnel itself. the NAS hasn't gotten an L2F_CONF back yet, so CLID is 0 too. the vibe is "new here, don't know anyone yet" ๐ฅน
the body carries the NAS's claimed name and a random challenge number. the GW uses that challenge to prove it's a legit tunnel endpoint. and Assigned_CLID is a value that isn't already handed out to any other tunnel going to any other Home Gateway. no duplicates, bestie ๐
2. GW->NAS:
Proto=L2F, Seq=0, MID=0, CLID=22, Key=0
L2F_CONF
Name: GW_name
Challenge: Rnd2
Assigned_CLID: 73
the Home Gateway processed that first packet and is replying ๐ it's still L2F, and the sequence number is 0 again because each side keeps its own counter for what it sends. MID stays 0 since we're still setting up the tunnel. CLID now matches the Assigned_CLID from the L2F_CONF it got. Key stays 0 for this whole phase.
the body has the Home Gateway's name, its own random challenge, and its own Assigned_CLID, which the NAS will put in the CLID field from now on. the GW makes its CLID the same way the NAS did. from this point on, every packet coming from the NAS has to be tagged with CLID 73, and every packet going to the NAS has to be tagged with CLID 22. main character CLIDs only ๐ฆ
3. NAS->GW
Proto=L2F, Seq=1, MID=0, CLID=73, Key=C(Rnd2)
L2F_OPEN
Response: C(Rnd2)
the NAS answers with Key now set to the shared secret, so it's finally in on the secret ๐ the Key is a CHAP-style hash of the random number it received. every packet from here on carries that value, and it works as a key for the whole life of the tunnel. both the Home Gateway and the NAS use these Keys until the tunnel is gone. the Key itself is a 32-bit chunk of the MD5 digest that comes out of encrypting the shared secret, but the full MD5 digest shows up in the response field of the L2F_OPEN.
4. GW->NAS
Proto=L2F, Seq=1, MID=0, CLID=22, Key=C(Rnd)
L2F_OPEN
Response: C(Rnd)
last step, and the Home Gateway wraps up the key exchange from the NAS's side ๐ it shows that in both the Key field and the response field. the tunnel is open and ready for clients to join. party starts now โจ
4.3.2 Normal Client Negotiation Sequence
this section is about getting a Virtual dial-up client on a NAS set up into a Home Gateway ๐ it assumes the tunnel was already made the way we just did in 4.3.1. the client in this example is a PPP client configured for CHAP ๐
the rules for Checksum, Length, and Offset are the same as in 4.3.1, so nothing new there ๐
1. NAS->GW
Proto=L2F, Seq=2, MID=1, CLID=73, Key=C(Rnd2)
L2F_OPEN
Type: CHAP
Name: CHAP-name
Challenge: Rnd3
Response: <Value received, presumably C(Rnd3)>
ID: <ID used in challenge>
the NAS got a call, tried CHAP using a challenge value of Rnd3, and the client answered ๐ฒ the name the client gave made the NAS think it was a Virtual dial-up client hosted by the Home Gateway. so the NAS grabs the next free MID, and all the info from the CHAP challenge and response goes into the connect notification.
2. GW->NAS
Proto=L2F, Seq=2, MID=1, CLID=22, Key=C(Rnd)
L2F_OPEN
the Home Gateway sends back the L2F_OPEN, which is basically a big "yes, you're in" ๐ฅณ
3. NAS->GW
Proto=PPP, Seq=0, MID=1, CLID=73, Key=C(Rnd2)
<Frame follows>
4. GW->NAS
Proto=PPP, Seq=0, MID=1, CLID=22, Key=C(Rnd)
<Frame follows>
traffic can now flow both ways, whether it's coming from the remote client or the home site ๐ the contents are just uninterpreted data, which in this case is HDLC. data traffic isn't the L2F protocol, so it usually doesn't use the Seq field, and that means Seq is set to 0 in non-L2F messages. (there's an exception to that, and it's in the S bit in section 4.2.5 if you want the details ๐ง)
4.4. L2F management message types
when an L2F packet's Proto field says L2F management, the body is made up of zero or more options ๐ each option starts with a single octet "message type", and then it can have zero or more sub-options. every sub-option is a single byte sub-option value, plus however many extra bytes that particular sub-option needs.
here's the list of options in L2F ๐
Hex Value Abbreviation Description
-------- ------------ -----------
0x00 Invalid Invalid message
0x01 L2F_CONF Request configuration
0x02 L2F_CONF_NAME Name of peer sending L2F_CONF
0x03 L2F_CONF_CHAL Random number peer challenges with
0x04 L2F_CONF_CLID Assigned_CLID for peer to use
0x02 L2F_OPEN Accept configuration
0x01 L2F_OPEN_NAME Name received from client
0x02 L2F_OPEN_CHAL Challenge client received
0x03 L2F_OPEN_RESP Challenge response from client
0x04 L2F_ACK_LCP1 LCP CONFACK accepted from client
0x05 L2F_ACK_LCP2 LCP CONFACK sent to client
0x06 L2F_OPEN_TYPE Type of authentication used
0x07 L2F_OPEN_ID ID associated with authentication
0x08 L2F_REQ_LCP0 First LCP CONFREQ from client
0x03 L2F_CLOSE Request disconnect
0x01 L2F_CLOSE_WHY Reason code for close
0x02 L2F_CLOSE_STR ASCII string description
0x04 L2F_ECHO Verify presence of peer
0x05 L2F_ECHO_RESP Respond to L2F_ECHO
4.4.1 L2F message type: Invalid
if a message comes in with this value, or with any value higher than the last recognized option value, or if it's an illegal packet under the rules of the other parts of this spec, the packet counts as invalid ๐ซ the packet MUST be discarded, and an L2F_CLOSE for the whole tunnel MUST be requested. once an L2F_CLOSE comes in, the tunnel itself may be closed. every other received message MUST be discarded. an implementation MAY close the tunnel after a wait that fits the tunnel's characteristics โณ
โ ๏ธ packets with an invalid Key get discarded, but disconnect is NOT initiated. that's on purpose, because it stops denial-of-service attacks ๐ก๏ธ invalid option types inside a message MUST be treated as if the whole message type was invalid.
4.4.2 L2F_CONF
this is the message type that sets up the tunnel between the NAS and the Home Gateway ๐ค MID is always 0. the body starts with the octet 0x01 (L2F_CONF), followed by all three of the sub-options below.
the L2F_CONF_NAME sub-option MUST be present. it's encoded as the octet value 0x02, then an octet giving a non-zero length, then that many bytes, which get read as the sender's ASCII name ๐
the L2F_CONF_CHAL sub-option MUST be present. it's encoded as the octet value 0x03, then a non-zero octet, then however many bytes that octet says ๐ฒ
the challenge value should be generated using whatever gives the highest quality of random numbers the implementation has access to ๐ง
the L2F_CONF_CLID sub-option MUST be present. it's encoded as the octet 0x04, followed by four bytes of Assigned_CLID value. Assigned_CLID is a non-zero 16-bit integer that's unique across all the tunnels on the sending system. the two least significant octets get set to that value, and the two most significant octets MUST be set to 0 ๐ข
the CLID field is sent as 0 in the first L2F_CONF packet from the NAS to the Home Gateway. after that it otherwise MUST be sent containing the value from the Assigned_CLID field of the last L2F_CONF message received โจ
Key MUST be set to 0 in all L2F_CONF packets, and no key field is included in the packet.
when a NAS sends an L2F_CONF to a Home Gateway, it's the very first packet in the conversation ๐ฌ
when the Home Gateway sends an L2F_CONF back to the NAS, it's saying "got it, I recognize this tunnel request" ๐ the Home Gateway MUST provide its name and its own challenge in the message body.
in every packet after the L2F_CONF, Key MUST be set to the CHAP-style hash of the received challenge bytes ๐ that hash gets done over the concatenation of the low 8 bits of the assigned CLID, the secret, and the challenge value. how the 32-bit key value gets generated is covered in section 4.2.11.
4.4.3 L2F_OPEN, tunnel establishment
the L2F_OPEN message does two jobs ๐ it wraps up tunnel setup (when MID is 0), or it sets up a client connection inside a tunnel that's already been built with L2F_CONF and L2F_OPEN messages (when MID is not equal to 0). this section covers tunnel establishment, and section 4.4.4 coming up next covers clients inside the tunnel.
an L2F_OPEN for tunnel establishment MUST contain only the sub-option 0x03, L2F_OPEN_RESP. that option MUST be followed by the octet 0x10, which says how big the 128-bit MD5 digest is. that digest comes from encrypting the challenge value in the L2F_CONF, and the low byte of the Assigned_CLID goes along with it. after that byte, the sixteen bytes of the generated MD5 digest MUST be there ๐
๐จ if an L2F_OPEN shows up during tunnel establishment with an incorrect L2F_OPEN_RESP, the packet MUST be silently discarded. it is recommended that such an event generate a log event as well ๐
4.4.4 L2F_OPEN, client establishment โจ
okay so an L2F_OPEN with a non-zero MID is how the NAS tells the Home Gateway "hey, a new dial-in client just showed up!" ๐ When the Home Gateway sends one back, that's its "yes, come in" moment. The message starts with the octet 0x02. The NAS is allowed to attach further sub-options, but the Home Gateway may not include any. Everything I'm about to say about sub-options only applies to the NAS-to-Home-Gateway direction, so keep that in mind ๐
The L2F_OPEN_TYPE sub-option MUST be present. It's encoded as the octet 0x06, followed by one byte that describes the authentication the NAS did with the client to figure out who they claim to be. The authentication type also quietly decides the encapsulation for the whole life of the session, which is so iconic. The types are:
0x01 Textual username/password exchange for SLIP
0x02 PPP CHAP
0x03 PPP PAP
0x04 PPP no authentication
0x05 SLIP no authentication
The L2F_OPEN_NAME sub-option is encoded as the octet 0x01, then an octet giving the length of the name, then that many bytes of name. This field MUST be present for any authentication type except 0x04 (None). It MUST contain the name from the client's authentication response. Non-negotiable, bestie ๐ซถ
The L2F_OPEN_CHAL sub-option is encoded as the octet 0x02, then an octet with the length of the challenge that was sent, then the challenge itself. This field is only present for CHAP, and it MUST contain the challenge value the NAS sent to the client.
The L2F_OPEN_RESP sub-option is encoded as the octet 0x03, then an octet with the length of the response that was received, then the client's response to the challenge. For CHAP, this is the response value the NAS received. For PAP or textual authentication, it's the clear text password the NAS got from the client. And for authentication 0x04 "None," this field is absent, so it just vanishes ๐ป
The L2F_ACK_LCP1 and L2F_ACK_LCP2 sub-options are encoded as the octets 0x04 and 0x05 respectively. Either way, two octets come next in network byte order giving the length of the LCP CONFACK that was last received from or sent to the client. After those is an exact copy of the CONFACK packet. L2F_ACK_LCP1 is a copy of the closing CONFACK received from the client, and L2F_ACK_LCP2 is a copy of the closing CONFACK sent to the client by the NAS. The receipts, but make it LCP ๐งพ๐
The L2F_REQ_LCP0 sub-option is encoded as the octet 0x08, followed by two octets in network byte order giving the length of the LCP CONFREQ that was first received from the client. The Home Gateway can use this to spot capabilities the client had that got negotiated away while LCP was starting with the NAS. If it finds any of those, it can decide to renegotiate LCP. Detective work, ngl ๐ต๏ธโโ๏ธ
The L2F_OPEN_ID sub-option is encoded as the octet 0x06, followed by a single octet. This sub-option is only present for CHAP, and that single octet holds the CHAP Identifier value that was sent to the client during the CHAP challenge.
The Home Gateway may choose to ignore any sub-option of the L2F_OPEN and accept the connection anyway. If it does that, it has to run its own LCP negotiations and authentication. To maximize the transparency of the L2F tunnel, it is recommended that extra negotiations and authentication be avoided if possible. Less drama, more vibes โจ
4.4.5 L2F_CLOSE ๐
This message is encoded as the byte 0x03. Either side of the tunnel can send an L2F_CLOSE at any time, no permission slip needed ๐
If it's sent with a MID of 0, it means "bye, tunnel and every client inside it, we're done." If the Home Gateway sends it in response to an L2F_OPEN, it means the Home Gateway has declined the connection. And if it's sent with a non-zero MID, it means only that one client is being terminated inside the tunnel.
The L2F_CLOSE_WHY sub-option is encoded as the byte 0x01, followed by four bytes in network byte order giving a bit mask of the reasons for the disconnection. The bits are:
0x00000001 Authentication failed
0x00000002 Out of resources
0x00000004 Administrative intervention
0x00000008 User quota exceeded
0x00000010 Protocol error
0x00000020 Unknown user
0x00000040 Incorrect password
0x00000080 PPP configuration incompatible
0x00000100 Wrong multilink PPP destination
Bits in the mask 0xFF000000 are reserved for per-vendor interpretation, so each vendor gets its own little corner ๐
An implementation can choose not to provide status bits even when it detects a condition that one of these bits describes. For example, an implementation may choose not to use 0x00000020 for security considerations, because it can be used to probe the user name space. Privacy matters, babe ๐
The L2F_CLOSE_STR sub-option is encoded as the byte 0x02, followed by a two-byte length in network byte order, followed by that many bytes, which are read as descriptive ASCII text about the disconnection. This string can be ignored, but it could be logged to give detailed or auxiliary info about the L2F_CLOSE ๐
4.4.6 L2F_ECHO ๐ฆ
Sending L2F_ECHO messages is optional ๐ธ If an implementation does send them, it MUST not send more than one such request each second. The payload size MUST be 64 bytes or less. It is recommended that at least 5 L2F_ECHO messages go out without a response before an implementation decides its peer has terminated. Patience is a virtue, even with the internet ๐งโโ๏ธ
The L2F_ECHO message is encoded as the single byte 0x04. Either side can send it once the tunnel is established. The MID MUST be 0. An L2F_ECHO_RESP (documented below) MUST be sent back in response.
4.4.7 L2F_ECHO_RESP ๐ซถ
All implementations MUST respond to L2F_ECHO using L2F_ECHO_RESP. The packet you received MUST be sent back verbatim, except that the CLID, sequence number, and checksum (if there is one) MUST be updated, and the message type gets changed from L2F_ECHO to L2F_ECHO_RESP. Any payload data after the 0x04 octet MUST be preserved in the response. Main character, but make it a faithful echo ๐
When an L2F_ECHO_RESP comes in, the payload data may be used to match it up with a previously sent L2F_ECHO, or the packet may just be silently discarded. Your call ๐
4.5 L2F Message Delivery ๐
L2F is designed to run over point-to-point unreliable links. It is not designed to provide flow control for the data traffic, and it doesn't provide reliable delivery of that traffic either. Each protocol tunnel carried via L2F is expected to handle its own flow control and retries. So only L2F control messages must be retransmitted, and that process is what this section is about ๐ฆ
4.5.1 Sequenced delivery
All L2F control messages (the ones that are L2F packets with a protocol type of 0x01) are sent with a sequence number. The sequence number is a per-L2F-tunnel free running counter that goes up by one (modulo 256) after each packet is transmitted. It lets the receiving end spot duplicated or out-of-order packets, and then throw those away. Section 4.2.5 walks through the process in detail ๐ข
4.5.2 Flow control
L2F control messages are expected to be exchanged lock-step. That means per-client activities can't happen until tunnel setup is complete, and one client can't be serviced until the L2F message exchange for the previous client is finished. So a flow control action should rarely, if ever, be needed. If the input queue of L2F control messages gets to a level that's objectionable for an implementation, the implementation may silently discard all messages in the queue to get things stable again ๐งน
4.5.3 Tunnel State table ๐
The following lists how L2F messages are handled for tunnel creation, in state table format. Events name an L2F_ message type, and the L2F_ part of the name is left off so the table stays compact. A start ("*") matches any event not otherwise matched for the named state.
A NAS starts in the initial state Start0, sending a packet before it waits for its first event. A Home Gateway starts at Start1, waiting for an initial packet to kick off service.
If an event isn't matched for a given state, the packet associated with that event is silently discarded.
Tunnel establishment (MID == 0), NAS side.
State Event Action New State
----- ----- ------ ---------
Start0 Send CONF Start1
Start1 CONF Send OPEN Start2
Start1 timeout 1-3 Send CONF Start1
Start1 timeout 4 Clean up tunnel (done)
Start2 OPEN (initiate 1st client) Open1
Start2 timeout 1-3 Send OPEN Start2
Start2 timeout 4 Clean up tunnel (done)
Open1 OPEN Send OPEN Open1
Open1 CLOSE Send CLOSE Close1
Open1 no MIDs open Send CLOSE Close2
Close1 CLOSE Send CLOSE Close1
Close1 timeout 4 Clean up tunnel (done)
Close2 CLOSE Clean up tunnel (done)
Close2 timeout 1-3 Send CLOSE Close2
Close2 timeout 4 Clean up tunnel (done)
Tunnel establishment (MID == 0), Home Gateway side.
State Event Action New State
----- ----- ------ ---------
Start0 CONF Send CONF Start1
Start1 CONF Send CONF Start1
Start1 OPEN Send OPEN Open1
Start1 timeout 4 Clean up tunnel (done)
Open1 OPEN Send OPEN Open1
Open1 OPEN (MID > 0) (1st client, below) Open2
Open1 CLOSE Send CLOSE Close1
Open1 timeout 4 Clean up tunnel (done)
Open2 OPEN (MID > 0) (below) Open2
Open2 CLOSE Send CLOSE Close1
Close1 CLOSE Send CLOSE Close1
Close1 timeout 4 Clean up tunnel (done)
4.5.4 Client State table ๐
okay so this table is basically the sibling of the last one ๐ซถ but instead of tracking the whole tunnel, it tracks ONE client connection living inside a tunnel that's already in the opened state (from 4.5.3). since this one is all about clients, MID will be non-zero here โจ
Client establishment (MID != 0), NAS side.
State Event Action New State
----- ----- ------ ---------
Start0 Send OPEN Start1
Start1 OPEN (enable forwarding) Open1
Start1 CLOSE Clean up MID (MID done)
Start1 timeout 1-3 Send OPEN Start1
Start1 timeout 4 Clean up MID (MID done)
Start1 client done Send CLOSE Close2
Open1 OPEN (no change) Open1
Open1 CLOSE Send CLOSE Close1
Open1 client done Send CLOSE Close2
Close1 CLOSE Send CLOSE Close1
Close1 timeout 4 Clean up MID (MID done)
Close2 CLOSE Clean up MID (MID done)
Close2 timeout 1-3 Send CLOSE Close2
Close2 timeout 4 Clean up MID (MID done)
Client establishment (MID != 0), Home Gateway side.
State Event Action New State
----- ----- ------ ---------
Start0 OPEN Send OPEN Open1
Start0 OPEN (fail) Send CLOSE Close3
Open1 OPEN Send OPEN Open1
Open1 CLOSE Send CLOSE Close1
Open1 client done Send CLOSE Close2
Close1 CLOSE Send CLOSE Close1
Close1 timeout 4 Clean up MID (MID done)
Close2 CLOSE Clean up MID (MID done)
Close2 timeout 1-3 Send CLOSE Close2
Close2 timeout 4 Clean up MID (MID done)
Close3 OPEN Send CLOSE Close3
Close3 timeout 4 Clean up MID (MID done)
5. Protocol Considerations ๐ง
okay so these bits aren't technically part of the protocol itself, but they totally help explain how L2F actually behaves out in the wild ๐ธ
5.1 PPP Features ๐ฆ
L2F just carries uninterpreted frames, which is giving total freedom ๐ซง It can run features without ever needing to understand them. like, if a PPP session is being carried, L2F is literally just shipping HDLC frames back and forth. the two PPP endpoints (the dial-in client on one end, the Home Gateway on the other) can negotiate higher-level stuff like reliable link, compression, multi-link, or encryption. those features operate between the two endpoints, and L2F keeps on shipping HDLC frames like nothing happened ๐
same energy for PPP echo requests, NCP configuration negotiation, and even termination requests. they're all just tunneled HDLC frames โจ
5.2 Termination ๐
L2F simply tunnels link-layer frames, so it does not detect frames like PPP TERMREQ ๐ instead, termination gets driven from a protocol endpoint. for example, if a Home Gateway receives a TERMREQ, its action is to "hang up" the PPP session. it's the responsibility of the L2F implementation at the Home Gateway to convert that "hang up" into an L2F_CLOSE action, which shuts the client's session down cleanly in the tunnel ๐ซถ L2F_CLOSE_WHY and L2F_CLOSE_STR may be included to describe the reason for the shutdown.
5.3 Extended Authentication ๐
L2F is compatible with both PAP and CHAP โจ SLIP doesn't do authentication inside the protocol, so it needs an ASCII exchange of username and password before SLIP even starts. L2F works with that mode too, bestie ๐
one-time password cards are everywhere now ๐ to the extent the NAS can capture and forward the one-time password, L2F operation is compatible with password cards. for the most general solution, an arbitrary request/response exchange must be supported. so in an L2F environment, the protocol must be structured so the NAS can detect the apparent identity of the user and set up a tunnel connection to the Home Gateway, where that arbitrary exchange can happen ๐
5.4 MNP4 and Apple Remote Access Protocol ๐
L2F appears compatible with Apple's ARAP protocol ๐ its operation under L2F hasn't been described because this experimental RFC doesn't have a corresponding implementation of that operation. not me being like "we'll figure it out later" ๐
5.5 Operation of IP and UDP ๐
L2F tries to be self-describing, operating at a level above the particular media it's carried over. however, some details of its connection to media are required to permit interoperable implementations, so this section covers the issues that have been found when operating L2F over IP and UDP โจ
L2F uses the well-known UDP port 1701 [4]. the entire L2F packet, including payload and L2F header, is sent within a UDP datagram. the source and destination ports are both 1701, and demultiplexing is achieved using CLID values ๐ฆ it's legal for the source IP address of a given CLID to change over the life of a connection, since this may correspond to a peer with multiple IP interfaces responding to a network topology change. responses should reflect the last source IP address for that CLID ๐
IP fragmentation may occur as the L2F packet travels over the IP substrate. L2F makes no special efforts to optimize this ๐ a NAS implementation MAY cause its LCP to negotiate for a specific MRU, which could optimize for NAS environments where the MTUs of the path the L2F packets are likely to travel have a consistent value. main character optimization energy ๐
6.0 Acknowledgments ๐ซถ
L2F uses a packet format inspired by GRE [5] ๐ธ huge thanks to Fred Baker for consultation, Dave Carrel for consulting on security aspects, and Paul Traina for philosophical guidance. the real MVPs ๐
7.0 References ๐
[1] Romkey, J., "A Nonstandard for Transmission of IP Datagrams over
Serial Lines: SLIP", RFC 1055, June 1988.
[2] Simpson, W., "The Point-to-Point Protocol (PPP)", STD 51,
RFC 1661, July 1994.
[3] Simpson, W., "PPP in HDLC-like Framing", STD 51,, RFC 1662,
July 1994.
[4] Reynolds, J., and J. Postel, "Assigned Numbers", STD 2, RFC 1700,
October 1994.
[5] Hanks, S., Li, T., Farinacci, D., and P. Traina, "Generic Routing
Encapsulation (GRE)", RFC 1701, October 1994.
8.0 Security Considerations ๐จ
Security issues are discussed in Section 3.1. bestie, go read that section. this is the part where things get very serious ๐
9.0 Authors' Addresses ๐
Tim Kolar
Cisco Systems
170 West Tasman Drive
San Jose CA 95134-1706
EMail: tkolar@cisco.com
Morgan Littlewood
Cisco Systems
170 West Tasman Drive
San Jose CA 95134-1706
EMail: littlewo@cisco.com
Andy Valencia
Cisco Systems
170 West Tasman Drive
San Jose CA 95134-1706
EMail: valencia@cisco.com
9.0 Full Copyright Statement ๐
Copyright (C) The Internet Society (1998). All Rights Reserved.
This document and translations of it may be copied and furnished to others, and derivative works that comment on or otherwise explain it or assist in its implementation may be prepared, copied, published and distributed, in whole or in part, without restriction of any kind, provided that the above copyright notice and this paragraph are included on all such copies and derivative works. However, this document itself may not be modified in any way, such as by removing the copyright notice or references to the Internet Society or other Internet organizations, except as needed for the purpose of developing Internet standards in which case the procedures for copyrights defined in the Internet Standards process must be followed, or as required to translate it into languages other than English.
The limited permissions granted above are perpetual and will not be revoked by the Internet Society or its successors or assigns.
This document and the information contained herein is provided on an "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
๐ฆ where this page comes from
- ietf: rfc2341 1998-05
- ๐ girlified by claude-haiku-5-5 on : a language model's rewrite of the original, under its terms