rfc8764v1.txt | rfc8764.txt | |||
---|---|---|---|---|
Independent Submission S. Cheshire | Independent Submission S. Cheshire | |||
Request for Comments: 8764 M. Krochmal | Request for Comments: 8764 M. Krochmal | |||
Category: Informational Apple Inc. | Category: Informational Apple Inc. | |||
ISSN: 2070-1721 March 2020 | ISSN: 2070-1721 April 2020 | |||
Apple's DNS Long-Lived Queries Protocol | Apple's DNS Long-Lived Queries Protocol | |||
Abstract | Abstract | |||
Apple's DNS Long-Lived Queries protocol (LLQ) is a protocol for | Apple's DNS Long-Lived Queries (LLQ) is a mechanism for extending the | |||
extending the DNS protocol to support change notification, thus | DNS protocol to support change notification, thus allowing clients to | |||
allowing clients to learn about changes to DNS data without polling | learn about changes to DNS data without polling the server. From | |||
the server. From 2005 onwards, LLQ was implemented in Apple products | 2005 onwards, LLQ was implemented in Apple products including Mac OS | |||
including Mac OS X, Bonjour for Windows, and AirPort wireless base | X, Bonjour for Windows, and AirPort wireless base stations. In 2020, | |||
stations. In 2019, the LLQ protocol was superseded by the IETF | the LLQ protocol was superseded by the IETF Standards Track RFC 8765, | |||
Standards Track RFC 8765, "DNS Push Notifications", which builds on | "DNS Push Notifications", which builds on experience gained with the | |||
experience gained with the LLQ protocol to create a superior | LLQ protocol to create a superior replacement. | |||
replacement. | ||||
The existing LLQ protocol deployed and used from 2005 to 2019 is | The existing LLQ protocol deployed and used from 2005 to 2020 is | |||
documented here to give background regarding the operational | documented here to give background regarding the operational | |||
experience that informed the development of DNS Push Notifications | experience that informed the development of DNS Push Notifications, | |||
and to help facilitate a smooth transition from LLQ to DNS Push | and to help facilitate a smooth transition from LLQ to DNS Push | |||
Notifications. | Notifications. | |||
Status of This Memo | Status of This Memo | |||
This document is not an Internet Standards Track specification; it is | This document is not an Internet Standards Track specification; it is | |||
published for informational purposes. | published for informational purposes. | |||
This is a contribution to the RFC Series, independently of any other | This is a contribution to the RFC Series, independently of any other | |||
RFC stream. The RFC Editor has chosen to publish this document at | RFC stream. The RFC Editor has chosen to publish this document at | |||
skipping to change at line 97 ¶ | skipping to change at line 96 ¶ | |||
Appendix A. Problems with the LLQ Protocol | Appendix A. Problems with the LLQ Protocol | |||
Acknowledgments | Acknowledgments | |||
Authors' Addresses | Authors' Addresses | |||
1. Introduction | 1. Introduction | |||
In dynamic environments, DNS Service Discovery [RFC6763] benefits | In dynamic environments, DNS Service Discovery [RFC6763] benefits | |||
significantly from clients being able to learn about changes to DNS | significantly from clients being able to learn about changes to DNS | |||
information via a mechanism that is both more timely and more | information via a mechanism that is both more timely and more | |||
efficient than simple polling. Such a mechanism enables "live | efficient than simple polling. Such a mechanism enables "live | |||
browses" that learn when a new instance of a service appears or when | browses" that (a) learn when a new instance of a service appears, (b) | |||
an existing service disappears from the network and allows clients to | learn when an existing service instance disappears from the network, | |||
monitor changes to a service. Multicast DNS [RFC6762] supports this | and (c) allows clients to monitor status changes to a service | |||
natively. When a host on the network publishes or deletes DNS | instance (e.g., printer ink levels). Multicast DNS [RFC6762] | |||
records, these changes are multicast to other hosts on the network. | supports this natively. When a device on the network publishes or | |||
These hosts deliver the change notifications to interested clients | deletes Multicast DNS records, these changes are multicast to other | |||
(applications running on the host). Hosts also send occasional | hosts on the network. Those hosts deliver the change notifications | |||
queries to the network in case gratuitous announcements are not | to interested clients (applications running on that host). Hosts | |||
received due to packet loss and to detect records lost due to their | also send occasional queries to the network, in case gratuitous | |||
publishers crashing or having become disconnected from the network. | announcements are not received due to packet loss, and to detect | |||
records lost due to their publishers crashing or having become | ||||
disconnected from the network. | ||||
This document defines an Apple extension to DNS that enables a client | This document defines an Apple extension to unicast DNS that enables | |||
to issue long-lived queries that allow a DNS server to notify clients | a client to issue long-lived queries that allow a unicast DNS server | |||
about changes to DNS data. This is a more scalable and practical | to notify clients about changes to DNS data. This is a more scalable | |||
solution than can be achieved by polling of the name server because a | and practical solution than can be achieved by polling of the name | |||
low polling rate could leave the client with stale information while | server, because a low polling rate could leave the client with stale | |||
a high polling rate would have an adverse impact on the network and | information, while a high polling rate would have an adverse impact | |||
server. | on the network and server. | |||
The mechanism defined in this document is now being replaced by DNS | The mechanism defined in this document is now being replaced by DNS | |||
Push Notifications [RFC8765] as explained in Section 1.1. | Push Notifications [RFC8765] as explained in Section 1.1. | |||
1.1. Transition to DNS Push Notifications | 1.1. Transition to DNS Push Notifications | |||
The LLQ protocol enjoyed over a decade of useful operation, enabling | The LLQ protocol enjoyed over a decade of useful operation, enabling | |||
timely live updates for the service discovery user interface in | timely live updates for the service discovery user interface in | |||
Apple's Back to My Mac [RFC6281] service. | Apple's Back to My Mac [RFC6281] service. | |||
skipping to change at line 139 ¶ | skipping to change at line 140 ¶ | |||
specification will not be updated to remedy these problems. | specification will not be updated to remedy these problems. | |||
All existing LLQ implementations are RECOMMENDED to migrate to using | All existing LLQ implementations are RECOMMENDED to migrate to using | |||
DNS Push Notifications instead. | DNS Push Notifications instead. | |||
Existing LLQ servers are RECOMMENDED to implement and support DNS | Existing LLQ servers are RECOMMENDED to implement and support DNS | |||
Push Notifications so that clients can begin migrating to the newer | Push Notifications so that clients can begin migrating to the newer | |||
protocol. | protocol. | |||
Existing LLQ clients are RECOMMENDED to query for the | Existing LLQ clients are RECOMMENDED to query for the | |||
"_dns-push-tls._tcp.<zone>" SRV record first and then, only if DNS | "_dns-push-tls._tcp.<zone>" SRV record first, and then only if DNS | |||
Push Notifications fail, fall back to query for | Push Notifications fail, fall back to query for | |||
"_dns-llq._udp.<zone>" instead. | "_dns-llq._udp.<zone>" instead. Use of the "_dns-llq._udp.<zone>" | |||
SRV record is described in Section 4. | ||||
This will cause clients to prefer the newer protocol when possible. | This will cause clients to prefer the newer protocol when possible. | |||
It is RECOMMENDED that clients always attempt DNS Push Notifications | It is RECOMMENDED that clients always attempt DNS Push Notifications | |||
first for every new request and, only if that fails, revert back to | first for every new request, and only if that fails, then fall back | |||
using LLQ. Clients SHOULD NOT record that a given server only speaks | to using LLQ. Clients SHOULD NOT record that a given server only | |||
LLQ and subsequently default to LLQ for that server, since server | speaks LLQ and subsequently default to LLQ for that server, since | |||
software gets updated and even a server that speaks only LLQ today | server software gets updated and even a server that speaks only LLQ | |||
may be updated to support DNS Push Notifications tomorrow. | today may be updated to support DNS Push Notifications tomorrow. | |||
New client and server implementations are RECOMMENDED to support only | New client and server implementations are RECOMMENDED to support only | |||
DNS Push Notifications. | DNS Push Notifications. | |||
2. Conventions and Terminology Used in This Document | 2. Conventions and Terminology Used in This Document | |||
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", | The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", | |||
"SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and | "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and | |||
"OPTIONAL" in this document are to be interpreted as described in | "OPTIONAL" in this document are to be interpreted as described in | |||
BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all | BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all | |||
capitals, as shown here. | capitals, as shown here. | |||
3. Mechanisms | 3. Mechanisms | |||
DNS Long-Lived Queries (DNS-LLQ) are implemented using the standard | DNS Long-Lived Queries (LLQ) are implemented using the standard DNS | |||
DNS message format [RFC1035] in conjunction with an Extension | message format [RFC1035] in conjunction with an EDNS(0) OPT pseudo-RR | |||
Mechanisms for DNS, denoted as EDNS(0), OPT pseudo-RR [RFC6891] with | [RFC6891] with a new OPTION-CODE and OPTION-DATA format specified | |||
a new OPT and RDATA format specified here. Encoding the LLQ request | here. Encoding the LLQ request in an OPT pseudo-RR allows for | |||
in an OPT RR allows for implementation of LLQ with minimal | implementation of LLQ with minimal modification to a name server's | |||
modification to a name server's front end. If a DNS query containing | front end. If a DNS query containing an LLQ option is sent to a | |||
an LLQ option is sent to a server that does not implement LLQ, a | server that does not implement LLQ, a server that complies with the | |||
server that complies with the EDNS(0) specification [RFC6891] will | EDNS(0) specification [RFC6891] will silently ignore the unrecognized | |||
silently ignore the unrecognized option and answer the request as a | option and answer the request as a normal DNS query without | |||
normal DNS query without establishing any long-lived state and | establishing any long-lived state and without returning an LLQ option | |||
without returning an LLQ option in its response. If a DNS query | in its response. If a DNS query containing an LLQ option is sent to | |||
containing an LLQ option is sent to a server that does not implement | a server that does not implement EDNS(0) at all, the server may | |||
EDNS(0) at all, the server may silently ignore the EDNS(0) OPT | silently ignore the EDNS(0) OPT pseudo-RR or it may return a nonzero | |||
pseudo-RR or it may return a nonzero RCODE. However, in practice, | RCODE. However, in practice, this issue is mostly theoretical, since | |||
this issue is mostly theoretical, since having a zone's | having a zone's _dns-llq._udp.<zone> SRV record target a host that | |||
_dns-llq._udp.<zone> SRV record target a host that does not implement | does not implement LLQ is a configuration error. | |||
LLQ is a configuration error. | ||||
Note that this protocol is designed for data set sizes of a few dozen | Note that this protocol is designed for data set sizes of a few dozen | |||
resource records at most and change rates no more than one every 10 | resource records at most and change rates no more than once every 10 | |||
seconds on average. Data sets in response to queries that frequently | seconds on average. Data sets that frequently exceed a single IP | |||
exceed a single packet, or that experience a rapid change rate, may | packet, or that experience a rapid change rate, may have undesirable | |||
have undesirable performance implications. | performance implications. | |||
3.1. Assigned Numbers | 3.1. Assigned Numbers | |||
This section describes constants used in this document. | This section describes constants used in this document. | |||
EDNS(0) Option Code (recorded with IANA): | EDNS(0) OPTION-CODE (recorded with IANA): | |||
LLQ 1 | LLQ 1 | |||
LLQ-PORT 5352 (recorded with IANA) | LLQ-PORT 5352 (recorded with IANA) | |||
LLQ Opcodes (specific to this LLQ EDNS(0) Option): | ||||
LLQ-SETUP 1 | ||||
LLQ-REFRESH 2 | ||||
LLQ-EVENT 3 | ||||
LLQ Error Codes (specific to this LLQ EDNS(0) Option): | LLQ Error Codes (specific to this LLQ EDNS(0) Option): | |||
NO-ERROR 0 | NO-ERROR 0 | |||
SERV-FULL 1 | SERV-FULL 1 | |||
STATIC 2 | STATIC 2 | |||
FORMAT-ERR 3 | FORMAT-ERR 3 | |||
NO-SUCH-LLQ 4 | NO-SUCH-LLQ 4 | |||
BAD-VERS 5 | BAD-VERS 5 | |||
UNKNOWN-ERR 6 | UNKNOWN-ERR 6 | |||
LLQ Opcodes (specific to this LLQ EDNS(0) Option): | ||||
LLQ-SETUP 1 | ||||
LLQ-REFRESH 2 | ||||
LLQ-EVENT 3 | ||||
3.2. Opt-RR Format | 3.2. Opt-RR Format | |||
As required by the EDNS(0) specification [RFC6891], all OPT-RRs used | As required by the EDNS(0) specification [RFC6891], all OPT | |||
in LLQs are formatted as follows: | pseudo-RRs used in LLQs are formatted as follows: | |||
+------------+--------------+---------------------+ | +------------+--------------+-------------------------+ | |||
| Field Name | Field Type | Description | | | Field Name | Field Type | Description | | |||
+============+==============+=====================+ | +============+==============+=========================+ | |||
| NAME | domain name | empty (root domain) | | | NAME | domain name | MUST be 0 (root domain) | | |||
+------------+--------------+---------------------+ | +------------+--------------+-------------------------+ | |||
| TYPE | u_int16_t | OPT | | | TYPE | u_int16_t | OPT (41) | | |||
+------------+--------------+---------------------+ | +------------+--------------+-------------------------+ | |||
| CLASS | u_int16_t | 0* | | | CLASS | u_int16_t | 0* | | |||
+------------+--------------+---------------------+ | +------------+--------------+-------------------------+ | |||
| TTL | u_int32_t | 0 | | | TTL | u_int32_t | 0 | | |||
+------------+--------------+---------------------+ | +------------+--------------+-------------------------+ | |||
| RDLEN | u_int16_t | describes RDATA | | | RDLEN | u_int16_t | length of all RDATA | | |||
+------------+--------------+---------------------+ | +------------+--------------+-------------------------+ | |||
| RDATA | octet stream | (see below) | | | RDATA | octet stream | (see below) | | |||
+------------+--------------+---------------------+ | +------------+--------------+-------------------------+ | |||
Table 1: OPT-RRs Used in LLQs | Table 1: OPT-RRs Used in LLQs | |||
* The CLASS field indicates, as per the EDNS(0) specification | * The CLASS field indicates, as per the EDNS(0) specification | |||
[RFC6891], the sender's UDP payload size. However, clients and | [RFC6891], the sender's UDP payload size. However, clients and | |||
servers need not be required to determine their reassembly buffer | servers are not required to determine their reassembly buffer size, | |||
size, path MTU, etc., to support LLQ. Thus, the sender of an LLQ | path MTU, etc., to support LLQ. Thus, the sender of an LLQ Request | |||
Request or Response MAY set the CLASS field to 0. The recipient MUST | or Response MAY set the CLASS field to 0. The recipient MUST ignore | |||
ignore the class field if it is set to 0. | the class field if it is set to 0. | |||
RDATA Format: | ||||
+---------------+------------+-------------------------+ | The RDATA of an EDNS(0) OPT pseudo-RR consists of zero or more | |||
| Field Name | Field Type | Description | | options of the form { OPTION-CODE, OPTION-LENGTH, OPTION-DATA } | |||
+===============+============+=========================+ | packed together, with the RDLEN field set accordingly to indicate the | |||
| OPTION-CODE | u_int16_t | LLQ | | total size. An LLQ OPTION is illustrated below. An EDNS(0) OPT | |||
+---------------+------------+-------------------------+ | pseudo-RR may contain zero or more LLQ OPTIONS in addition to zero or | |||
| OPTION-LENGTH | u_int16_t | Length of following | | more other EDNS(0) options. | |||
| | | fields, as appropriate | | ||||
+---------------+------------+-------------------------+ | ||||
| VERSION | u_int16_t | Version of LLQ protocol | | ||||
| | | implemented | | ||||
+---------------+------------+-------------------------+ | ||||
| LLQ-OPCODE | u_int16_t | Identifies LLQ | | ||||
| | | operation | | ||||
+---------------+------------+-------------------------+ | ||||
| ERROR-CODE | u_int16_t | Identifies LLQ errors | | ||||
+---------------+------------+-------------------------+ | ||||
| LLQ-ID | u_int64_t | Identifier for an LLQ | | ||||
+---------------+------------+-------------------------+ | ||||
| LEASE-LIFE | u_int32_t | Requested or granted | | ||||
| | | life of LLQ, in seconds | | ||||
+---------------+------------+-------------------------+ | ||||
Table 2: RDATA | +---------------+------------+-------------------------------------+ | |||
| Field Name | Field Type | Description | | ||||
+===============+============+=====================================+ | ||||
| OPTION-CODE | u_int16_t | LLQ (1) | | ||||
+---------------+------------+-------------------------------------+ | ||||
| OPTION-LENGTH | u_int16_t | Length of following fields (18) | | ||||
+---------------+------------+-------------------------------------+ | ||||
| LLQ-VERSION | u_int16_t | Version of LLQ protocol implemented | | ||||
+---------------+------------+-------------------------------------+ | ||||
| LLQ-OPCODE | u_int16_t | Identifies LLQ operation | | ||||
+---------------+------------+-------------------------------------+ | ||||
| LLQ-ERROR | u_int16_t | Identifies LLQ errors | | ||||
+---------------+------------+-------------------------------------+ | ||||
| LLQ-ID | u_int64_t | Identifier for an LLQ | | ||||
+---------------+------------+-------------------------------------+ | ||||
| LLQ-LEASE | u_int32_t | Requested or granted life of LLQ, | | ||||
| | | in seconds | | ||||
+---------------+------------+-------------------------------------+ | ||||
This data format, consisting of (OPTION-CODE, OPTION-LENGTH, | Table 2: LLQ OPTION | |||
LLQ-Metadata) tuples, may be repeated an arbitrary number of times in | ||||
the RDATA section, with the RDLEN field set accordingly. | ||||
The size and meaning of the OPTION-CODE and OPTION-LENGTH fields are | The size and meaning of the OPTION-CODE and OPTION-LENGTH fields are | |||
as described in the EDNS(0) specification [RFC6891]. The remainder | as described in the EDNS(0) specification [RFC6891]. The remainder | |||
of the fields comprise the OPTION-DATA of the EDNS(0) option. Since | of the fields comprise the OPTION-DATA of the EDNS(0) LLQ OPTION. | |||
for LLQ the OPTION-DATA is a fixed size, in LLQ EDNS(0) options, the | Since for LLQ the OPTION-DATA is a fixed size, in EDNS(0) LLQ OPTIONS | |||
OPTION-LENGTH field always has the value 18. | the OPTION-LENGTH field always has the value 18. | |||
In keeping with Internet convention, all multi-byte numeric | ||||
quantities (u_int16_t, u_int32_t, and u_int64_t) are represented in | ||||
big endian byte order (most significant byte first). | ||||
4. LLQ Address and Port Identification | 4. LLQ Address and Port Identification | |||
The client requires a mechanism to determine to which server it | The client requires a mechanism to determine to which server it | |||
should send LLQ operations. | should send LLQ operations. | |||
Additionally, some firewalls block direct communication with a name | Additionally, some firewalls block direct communication with a name | |||
server on port 53 to avoid spoof responses. However, this direct | server on port 53 to avoid spoof responses. However, this direct | |||
communication is necessary for LLQs. Thus, servers MAY listen for | communication is necessary for LLQs. Thus, servers MAY listen for | |||
LLQs on a different port (typically 5352). Clients, therefore, also | LLQs on a different port (typically 5352). Clients, therefore, also | |||
need a mechanism to determine to which port to send LLQ operations. | need a mechanism to determine to which port to send LLQ operations. | |||
The client determines the server responsible for a given LLQ much as | The client determines the server responsible for a given LLQ much as | |||
a client determines to which server to send a dynamic update. The | a client determines to which server to send a DNS dynamic update. | |||
client begins by sending a standard DNS query for the name of the | The client begins by sending a standard DNS query for the name of the | |||
LLQ, with type SOA. The server MUST answer with that SOA record in | LLQ, with type SOA. If the record exists, then the server MUST | |||
the Answer section if the record exists. The server SHOULD include | answer with that SOA record in the Answer section. If a record of | |||
an SOA record for that name's zone in the Authority section if the | type SOA with the LLQ name does not exist, then the server SHOULD | |||
LLQ name (type SOA) does not exist. For example, a query for | include an SOA record for that name's zone in the Authority section. | |||
"_ftp._tcp.example.com." may return an SOA record named | For example, a query for "_ftp._tcp.example.com." with type SOA, when | |||
"example.com." in the Authority section if there is no SOA record | there is no SOA record with that name, might return an SOA record | |||
named "_ftp._tcp.example.com.". If, in this case, the server does | named "example.com." in the Authority section. If the named SOA | |||
not include the SOA record in the Authority section, the client | record does not exist and the server fails to include the enclosing | |||
strips the leading label from the name and tries again, repeating | SOA record in the Authority section, the client strips the leading | |||
until an answer is received. | label from the name and tries again, repeating until an answer is | |||
received. | ||||
This iterative zone apex discovery algorithm is described in more | This iterative zone apex discovery algorithm is described in more | |||
detail in the DNS Push Notifications specification [RFC8765]. | detail in the DNS Push Notifications specification [RFC8765]. | |||
Upon learning the zone (SOA), the client then constructs and sends an | Upon learning the zone apex (SOA), the client then constructs and | |||
SRV query for the name _dns-llq._udp.<zone>, | sends an SRV query for the name, "_dns-llq._udp.<zone>", | |||
e.g., _dns-llq._udp.example.com. | e.g., "_dns-llq._udp.example.com.". | |||
A server implementing LLQ MUST answer with an SRV record [RFC2782] | An authoritative server for a zone implementing LLQ MUST answer with | |||
for this name. The SRV RDATA is as follows: | an SRV record [RFC2782] for this name. The SRV RDATA is as follows: | |||
+----------+------------------------------------------------------+ | +----------+------------------------------------------------------+ | |||
| PRIORITY | typically 0 | | | PRIORITY | typically 0 | | |||
+----------+------------------------------------------------------+ | +----------+------------------------------------------------------+ | |||
| WEIGHT | typically 0 | | | WEIGHT | typically 0 | | |||
+----------+------------------------------------------------------+ | +----------+------------------------------------------------------+ | |||
| PORT | typically 53 or 5352 | | | PORT | typically 53 or 5352 | | |||
+----------+------------------------------------------------------+ | +----------+------------------------------------------------------+ | |||
| TARGET | name of server providing LLQs for the requested zone | | | TARGET | name of server providing LLQs for the requested zone | | |||
+----------+------------------------------------------------------+ | +----------+------------------------------------------------------+ | |||
Table 3: SRV RDATA | Table 3: SRV RDATA | |||
The server SHOULD include its address record(s) in the Additional | The server SHOULD include the address record(s) for the target host | |||
section of the response. | in the Additional section of the response. | |||
If the server does not include its address record in the Additional | If the server does not include the target host's address record(s) in | |||
section, the client SHOULD query explicitly for the address record | the Additional section, the client SHOULD query explicitly for the | |||
with the name of the SRV target. | address record(s) with the name of the SRV target. | |||
The client MUST send all LLQ requests, refreshes, and acknowledgments | The client MUST send all LLQ requests, refreshes, and acknowledgments | |||
to the name server specified in the SRV target at the address | to the name server specified in the SRV target, at the address | |||
contained in the address record for that target. Note that the | contained in the address record for that target. Note that the | |||
queries described in this section (including those for SOA and SRV | queries described in this section (including those for SOA and SRV | |||
records) MAY be sent to an intermediate DNS recursive resolver -- | records) MAY be sent to an intermediate DNS recursive resolver -- | |||
they need not be sent directly to the name server. | they need not be sent directly to the name server. | |||
If, on issuing the SRV query, the client receives an NXDOMAIN | If, on issuing the SRV query, the client receives a negative response | |||
response indicating that the SRV record does not exist, the client | indicating that the SRV record does not exist, the client SHOULD | |||
SHOULD conclude that the server does not support an LLQ in the | conclude that the zone does not support LLQ. The client then SHOULD | |||
requested zone. The client then SHOULD NOT send an LLQ request for | NOT send an LLQ request for the desired name, instead utilizing the | |||
the desired name, instead utilizing the behavior for LLQ-unaware | behavior for LLQ-unaware servers described in Section 5, "LLQ Setup". | |||
servers described in Section 5, "LLQ Setup". | ||||
Servers should send all messages to the source address and port of | Servers should send all messages to the source address and port of | |||
the LLQ setup message received from the client. | the LLQ setup message received from the client. | |||
5. LLQ Setup | 5. LLQ Setup | |||
An LLQ is initiated by a client and is completed via a four-way | An LLQ is initiated by a client and is completed via a four-way | |||
handshake. This handshake provides resilience to packet loss, | handshake. This handshake provides resilience to packet loss, | |||
demonstrates client reachability, and reduces denial-of-service | demonstrates client reachability, and reduces denial-of-service | |||
attack opportunities (see Section 8, "Security Considerations"). | attack opportunities (see Section 8, "Security Considerations"). | |||
skipping to change at line 376 ¶ | skipping to change at line 379 ¶ | |||
response for at least 8 seconds after the 3rd attempt before | response for at least 8 seconds after the 3rd attempt before | |||
considering the server down or unreachable. Upon determining a | considering the server down or unreachable. Upon determining a | |||
server to be down, a client MAY periodically attempt to re-initiate | server to be down, a client MAY periodically attempt to re-initiate | |||
an LLQ setup at a rate of not more than once per hour. | an LLQ setup at a rate of not more than once per hour. | |||
Servers MUST NOT retransmit acknowledgments that do not generate | Servers MUST NOT retransmit acknowledgments that do not generate | |||
responses from the client. Retransmission in setup is client driven, | responses from the client. Retransmission in setup is client driven, | |||
freeing servers from maintaining timers for incomplete LLQ setups. | freeing servers from maintaining timers for incomplete LLQ setups. | |||
If servers receive duplicate messages from clients (perhaps due to | If servers receive duplicate messages from clients (perhaps due to | |||
the loss of the server's responses mid-flight), the server MUST | the loss of the server's responses mid-flight), the server MUST | |||
resend its reply (possibly modifying the LEASE-LIFE as described in | resend its reply (possibly modifying the LLQ-LEASE as described in | |||
Section 5.2.4, "ACK + Answers"). | Section 5.2.4, "ACK + Answers"). | |||
Servers MUST NOT garbage collect LLQs that fail to complete the four- | Servers MUST NOT garbage collect LLQs that fail to complete the four- | |||
way handshake until the initially granted LEASE-LIFE has elapsed. | way handshake until the initially granted LLQ-LEASE has elapsed. | |||
5.2. LLQ Setup Four-Way Handshake | 5.2. LLQ Setup Four-Way Handshake | |||
The four phases of the handshake include: | The four phases of the handshake include: | |||
1) Setup Request client to server, identifies LLQ(s) | 1) Setup Request client to server, identifies LLQ(s) | |||
requested | requested | |||
2) Setup Challenge server to client, provides error(s) for | 2) Setup Challenge server to client, provides unique | |||
requested LLQs and unique identifiers for | identifiers for successful requested LLQs, | |||
the successful requests | and error(s) for unsuccessful requested | |||
LLQs. | ||||
3) Challenge Response client to server, echoes identifier(s), | 3) Challenge Response client to server, echoes identifier(s), | |||
demonstrating client's reachability and | demonstrating client's reachability and | |||
willingness to participate | willingness to participate | |||
4) ACK + Answers server to client, confirms setup and | 4) ACK + Answers server to client, confirms setup and | |||
provides initial answers | provides initial answers | |||
5.2.1. Setup Request | 5.2.1. Setup Request | |||
A request for an LLQ is formatted like a standard DNS query but with | A request for an LLQ is formatted like a standard DNS query but with | |||
an OPT RR containing LLQ metadata in its Additional section. LLQ | an OPT pseudo-RR containing LLQ metadata in its Additional section. | |||
Setup Requests are identified by the LLQ-SETUP opcode and a | LLQ Setup Requests are identified by the LLQ-SETUP opcode and a | |||
zero-valued LLQ-ID. | zero-valued LLQ-ID. | |||
The request MAY contain multiple questions to set up multiple LLQs. | The request MAY contain multiple questions to set up multiple LLQs. | |||
A request consisting of multiple questions MUST contain multiple LLQ | A Setup Request consisting of multiple questions MUST contain | |||
metadata sections, one per question, with metadata sections in the | multiple LLQ OPTIONS, one per question, with the LLQ OPTIONS in the | |||
same order as the questions they correspond to (i.e., the first | same order as the questions they correspond to (i.e., the first LLQ | |||
metadata section corresponds to the first question, the second | OPTION corresponds to the first question, the second LLQ OPTION | |||
metadata section corresponds to the second question, etc.). If | corresponds to the second question, etc.). If requesting multiple | |||
requesting multiple LLQs, clients SHOULD request the same LEASE-LIFE | LLQs, clients SHOULD request the same LLQ-LEASE for each LLQ. | |||
for each LLQ. Requests over UDP MUST NOT contain multiple questions | Requests over UDP MUST NOT contain multiple questions if doing so | |||
if doing so would cause the message to not fit in a single packet. | would cause the message to exceed a single IP packet. | |||
A client MUST NOT request multiple identical LLQs (i.e., containing | A client MUST NOT request multiple identical LLQs (i.e., containing | |||
the same qname/type/class) from the same source IP address and port. | the same qname/type/class) from the same source IP address and port. | |||
This requirement is to avoid unnecessary load on servers. In the | This requirement is to avoid unnecessary load on servers. In the | |||
case of multiple independent client implementations that may run on | case of multiple independent client implementations that may run on | |||
the same device without knowledge of each other, it is allowable if | the same device without knowledge of each other, it is allowable if | |||
they by chance send LLQ requests for the same qname/type/class. | they by chance send LLQ requests for the same qname/type/class. | |||
These independent implementations on the same client will be using | These independent implementations on the same client will be using | |||
different source ports. Likewise, to the server, multiple | different source ports. Likewise, to the server, multiple | |||
independent clients behind the same NAT gateway will appear as if | independent clients behind the same NAT gateway will appear as if | |||
they were multiple independent clients using different ports on the | they were multiple independent clients using different ports on the | |||
same host. | same host, and this is also allowable. | |||
The query MUST NOT be for record type ANY (255), class ANY (255), or | The query MUST NOT be for record type ANY (255), class ANY (255), or | |||
class NONE (0). | class NONE (0). | |||
+---------------+------------+---------------------------------+ | +---------------+------------+---------------------------------+ | |||
| Field Name | Field Type | Description | | | Field Name | Field Type | Description | | |||
+===============+============+=================================+ | +===============+============+=================================+ | |||
| OPTION-CODE | u_int16_t | LLQ (1) | | | OPTION-CODE | u_int16_t | LLQ (1) | | |||
+---------------+------------+---------------------------------+ | +---------------+------------+---------------------------------+ | |||
| OPTION-LENGTH | u_int16_t | Length of following fields (18) | | | OPTION-LENGTH | u_int16_t | Length of following fields (18) | | |||
+---------------+------------+---------------------------------+ | +---------------+------------+---------------------------------+ | |||
| VERSION | u_int16_t | Version of LLQ protocol | | | LLQ-VERSION | u_int16_t | Version of LLQ protocol | | |||
| | | implemented by requester (1) | | | | | implemented by requester (1) | | |||
+---------------+------------+---------------------------------+ | +---------------+------------+---------------------------------+ | |||
| LLQ-OPCODE | u_int16_t | LLQ-SETUP (1) | | | LLQ-OPCODE | u_int16_t | LLQ-SETUP (1) | | |||
+---------------+------------+---------------------------------+ | +---------------+------------+---------------------------------+ | |||
| ERROR-CODE | u_int16_t | NOERROR (0) | | | LLQ-ERROR | u_int16_t | NO-ERROR (0) | | |||
+---------------+------------+---------------------------------+ | +---------------+------------+---------------------------------+ | |||
| LLQ-ID | u_int64_t | 0 | | | LLQ-ID | u_int64_t | 0 | | |||
+---------------+------------+---------------------------------+ | +---------------+------------+---------------------------------+ | |||
| LEASE-LIFE | u_int32_t | Desired life of LLQ request | | | LLQ-LEASE | u_int32_t | Desired life of LLQ request | | |||
+---------------+------------+---------------------------------+ | +---------------+------------+---------------------------------+ | |||
Table 4: Setup Request OPT-RR LLQ Metadata Format | Table 4: Setup Request LLQ OPTION Format | |||
These fields MUST be repeated once for each additional query in the | The Setup Request LLQ OPTION MUST be repeated once for each | |||
Question section. | additional query in the Question section. | |||
5.2.2. Setup Challenge | 5.2.2. Setup Challenge | |||
Upon receiving an LLQ Setup Request, a server implementing LLQs will | Upon receiving an LLQ Setup Request, a server implementing LLQs will | |||
send a Setup Challenge to the requester (client). An LLQ Setup | send a Setup Challenge to the requester (client). An LLQ Setup | |||
Challenge is a DNS response, with the DNS message ID matching that of | Challenge is a DNS response, with the DNS message ID matching that of | |||
the request, and with all questions contained in the request present | the Setup Request, and with all questions contained in the Setup | |||
in the Question section of the response. Additionally, the challenge | Request present in the Question section of the response. | |||
contains a single OPT-RR with an LLQ metadata section for each LLQ | Additionally, the challenge contains a single OPT pseudo-RR with an | |||
request, indicating the success or failure of each request. Metadata | LLQ OPTION for each LLQ request, indicating the success or failure of | |||
sections MUST be in the same order as the questions they correspond | each request. The LLQ OPTIONS MUST be in the same order as the | |||
to. Note that in a request containing multiple questions, some LLQs | questions they correspond to. Note that in a Setup Request | |||
may succeed, while others may fail. | containing multiple questions, some LLQs may succeed while others may | |||
fail. | ||||
+---------------+------------+---------------------------------+ | +---------------+------------+---------------------------------+ | |||
| Field Name | Field Type | Description | | | Field Name | Field Type | Description | | |||
+===============+============+=================================+ | +===============+============+=================================+ | |||
| OPTION-CODE | u_int16_t | LLQ (1) | | | OPTION-CODE | u_int16_t | LLQ (1) | | |||
+---------------+------------+---------------------------------+ | +---------------+------------+---------------------------------+ | |||
| OPTION-LENGTH | u_int16_t | Length of following fields (18) | | | OPTION-LENGTH | u_int16_t | Length of following fields (18) | | |||
+---------------+------------+---------------------------------+ | +---------------+------------+---------------------------------+ | |||
| VERSION | u_int16_t | Version of LLQ protocol | | | LLQ-VERSION | u_int16_t | Version of LLQ protocol | | |||
| | | implemented in server (1) | | | | | implemented in server (1) | | |||
+---------------+------------+---------------------------------+ | +---------------+------------+---------------------------------+ | |||
| LLQ-OPCODE | u_int16_t | LLQ-SETUP (1) | | | LLQ-OPCODE | u_int16_t | LLQ-SETUP (1) | | |||
+---------------+------------+---------------------------------+ | +---------------+------------+---------------------------------+ | |||
| ERROR-CODE | u_int16_t | [As Appropriate] | | | LLQ-ERROR | u_int16_t | [As Appropriate] | | |||
+---------------+------------+---------------------------------+ | +---------------+------------+---------------------------------+ | |||
| LLQ-ID | u_int64_t | [As Appropriate] | | | LLQ-ID | u_int64_t | [As Appropriate] | | |||
+---------------+------------+---------------------------------+ | +---------------+------------+---------------------------------+ | |||
| LEASE-LIFE | u_int32_t | [As Appropriate] | | | LLQ-LEASE | u_int32_t | [As Appropriate] | | |||
+---------------+------------+---------------------------------+ | +---------------+------------+---------------------------------+ | |||
Table 5: Setup Challenge OPT-RR RDATA Format | Table 5: Setup Challenge LLQ OPTION Format | |||
These fields MUST be repeated once for each query in the Questions | The Setup Challenge LLQ OPTION MUST be repeated once for each query | |||
section of the Setup Request. | in the Questions section of the Setup Challenge. Further details for | |||
LLQ-ERROR, LLQ-ID and LLQ-LEASE are given below. | ||||
For LLQ Metadata field descriptions, possible ERROR-CODE values | LLQ-ERROR: | |||
include: | ||||
NO-ERROR: The LLQ Setup Request was successful. | NO-ERROR: The LLQ Setup Request was successful. | |||
FORMAT-ERR: The LLQ was improperly formatted. Note that if | FORMAT-ERR: The LLQ was improperly formatted. Note that if | |||
the rest of the DNS message is properly | the rest of the DNS message is properly | |||
formatted, the DNS header error code MUST NOT | formatted, the DNS header error code MUST NOT | |||
include a format error code, as this would cause | include a format error code, since to do so | |||
confusion between a server that does not | would cause ambiguity between the case where a | |||
understand the LLQ format and a client that | client sends a valid LLQ Setup Request to a | |||
sends malformed LLQs. | server that does not understand LLQ and the case | |||
where a client sends a malformed LLQ Setup | ||||
Request to a server that does understand LLQ. | ||||
SERV-FULL: The server cannot grant the LLQ request because | SERV-FULL: The server cannot grant the LLQ request because | |||
it is overloaded or the request exceeds the | it is overloaded or the request exceeds the | |||
server's rate limit (see Section 8, Security | server's rate limit (see Section 8, Security | |||
Considerations). Upon returning this error, the | Considerations). Upon returning this error, the | |||
server MUST include in the LEASE-LIFE field a | server MUST include in the LLQ-LEASE field a | |||
time interval, in seconds, after which the | time interval, in seconds, after which the | |||
client may retry the LLQ Setup. | client may retry the LLQ Setup. | |||
STATIC: The data for this name and type is not expected | STATIC: The data for this name and type is not expected | |||
to change frequently, and the server, therefore, | to change frequently, and the server, therefore, | |||
does not support the requested LLQ. The client | does not support the requested LLQ. The client | |||
MUST NOT poll for this name and type, nor should | MUST honor the resource record TTLs returned and | |||
it retry the LLQ Setup, and should instead honor | MUST NOT poll sooner than indicated by those | |||
the normal resource record TTLs returned. | TTLs, nor should it retry the LLQ Setup for this | |||
name and type. | ||||
BAD-VERS: The protocol version specified in the client's | BAD-VERS: The protocol version specified in the client's | |||
request is not supported by the server. | Setup Request is not supported by the server. | |||
UNKNOWN-ERR: The LLQ was not granted for an unknown reason. | ||||
Other LLQ Metadata field descriptions include the following: | UNKNOWN-ERR: The LLQ was not granted for some other reason | |||
not covered by the preceding error code values. | ||||
LLQ-ID: On success, a random number generated by the server | LLQ-ID: On success, a random number generated by the server | |||
that is unique for the requested name/type/class. | that is unique on the server for the requested | |||
The LLQ-ID SHOULD be an unpredictable random | name/type/class. The LLQ-ID SHOULD be an | |||
number. A possible method of allocating LLQ-IDs | unpredictable random number. A possible method of | |||
with minimal bookkeeping would be to store the | allocating LLQ-IDs with minimal bookkeeping would | |||
time, in seconds since the Epoch, in the high 32 | be to store the time, in seconds since the Epoch, | |||
bits of the field and a cryptographically generated | in the high 32 bits of the field, and a | |||
32-bit random integer in the low 32 bits. | cryptographically generated 32-bit random integer | |||
in the low 32 bits. | ||||
On error, the LLQ-ID is set to 0. | On error, the LLQ-ID is set to 0. | |||
LEASE-LIFE: On success, the actual life of the LLQ, in seconds. | LLQ-LEASE: On success, the actual life of the LLQ, in seconds. | |||
Value may be greater than, less than, or equal to | Value may be greater than, less than, or equal to | |||
the value requested by the client as per the server | the value requested by the client, as per the | |||
administrator's policy. The server MAY discard the | server administrator's policy. The server MAY | |||
LLQ after this LEASE-LIFE expires unless the LLQ | discard the LLQ after this LLQ-LEASE expires unless | |||
has been renewed by the client (see Section 7, "LLQ | the LLQ has been renewed by the client (see | |||
Lease-Life Expiration"). The server MUST NOT | Section 7, "LLQ Lease-Life Expiration"). The | |||
generate events (see Section 6, "Event Responses) | server MUST NOT generate events (see Section 6, | |||
for expired LLQs. | "Event Responses") for expired LLQs. | |||
On SERV-FULL error, LEASE-LIFE MUST be set to a | On SERV-FULL error, LLQ-LEASE MUST be set to a time | |||
time interval, in seconds, after which the client | interval, in seconds, after which the client may | |||
may retry the LLQ Setup. | retry the LLQ Setup. | |||
On other errors, the LEASE-LIFE MUST be set to 0. | On other errors, the LLQ-LEASE MUST be set to 0. | |||
5.2.3. Challenge Response | 5.2.3. Challenge Response | |||
Upon issuing a Setup Request, a client listens for a Setup Challenge | Upon issuing a Setup Request, a client listens for a Setup Challenge | |||
(Section 5.2.2) retransmitting the request as necessary | (Section 5.2.2) retransmitting the Setup Request as necessary | |||
(Section 5.1). After receiving a successful challenge, the client | (Section 5.1). After receiving a successful Setup Challenge, the | |||
SHOULD send a Challenge Response to the server. This Challenge | client SHOULD send a Challenge Response to the server. This | |||
Response is a DNS request with questions from the request and | Challenge Response is a DNS request with questions as in the Setup | |||
challenge, and a single OPT-RR in the Additional section, with the | Request and Setup Challenge, and a single OPT pseudo-RR in the | |||
OPT-RR RDATA identical to the OPT-RR RDATA contained in the Setup | Additional section, with the LLQ OPTIONS corresponding to the LLQ | |||
Challenge (i.e., echoing, for each set of fields, the random LLQ-ID | OPTIONS contained in the Setup Challenge (i.e., echoing, for each LLQ | |||
and the granted lease life). If the Challenge Response contains | OPTION, the random LLQ-ID and the granted LLQ-LEASE). If the | |||
multiple questions, the first question MUST correspond to the first | Challenge Response contains multiple questions, the first question | |||
OPT-RR RDATA tuple, etc. | MUST correspond to the first LLQ OPTION, etc. | |||
If the Setup Request fails with a STATIC error, the client MUST NOT | If the Setup Request for a particular LLQ fails with a STATIC error, | |||
poll the server. The client SHOULD honor the resource record TTLs | the client MUST NOT poll the server for that LLQ. The client SHOULD | |||
contained in the response. | honor the resource record TTLs contained in the response. | |||
If the Setup Request fails with a SERV-FULL error, the client MAY | If a Setup Request fails with a SERV-FULL error, the client MAY retry | |||
retry the LLQ Setup Request (Section 5.2.1) after the time indicated | the LLQ Setup Request (Section 5.2.1) after the time indicated in the | |||
in the LEASE-LIFE field. | LLQ-LEASE field. | |||
If the Setup Request fails with an error other than STATIC or | If the Setup Request fails with an error other than STATIC or | |||
SERV-FULL, or the server is determined not to support LLQ (i.e., the | SERV-FULL, or the server is determined not to support LLQ (i.e., the | |||
client receives a DNS response with a nonzero RCODE, or a DNS | client receives a DNS response with a nonzero RCODE, or a DNS | |||
response containing no LLQ option), the client MAY poll the server | response containing no LLQ option), the client MAY poll the server | |||
periodically with standard DNS queries, inferring Add and Remove | periodically with standard DNS queries, inferring Add and Remove | |||
Events (see Section 6, "Event Responses") by comparing answers to | Events (see Section 6, "Event Responses") by comparing answers to | |||
these queries. The client SHOULD NOT poll more than once every 15 | these queries. The client SHOULD NOT poll more than once every 15 | |||
minutes for a given query. The client MUST NOT poll if it receives a | minutes for a given query. The client MUST NOT poll if it receives a | |||
STATIC error code in the acknowledgment. | STATIC error code in the acknowledgment. | |||
5.2.4. ACK + Answers | 5.2.4. ACK + Answers | |||
Upon receiving a correct Challenge Response, a server MUST return an | Upon receiving a correct Challenge Response, a server MUST return an | |||
acknowledgment, completing the LLQ setup, and provide all current | acknowledgment, completing the LLQ setup, and provide all current | |||
answers to the question(s). | answers to the question(s). | |||
To acknowledge a successful Challenge Response, i.e., a Challenge | To acknowledge a successful Challenge Response, i.e., a Challenge | |||
Response in which the LLQ-ID and LEASE-LIFE echoed by the client | Response in which the LLQ-ID and LLQ-LEASE echoed by the client match | |||
match the values issued by the server, the server MUST send a DNS | the values issued by the server, the server MUST send a DNS response | |||
response containing all available answers to the question(s) | containing all available answers to the question(s) contained in the | |||
contained in the original Setup Request, along with all additional | original Setup Request, along with all additional resource records | |||
resource records appropriate for those answers in the Additional | appropriate for those answers in the Additional section. The | |||
section. The Additional section also contains an OPT-RR formatted as | Additional section also contains LLQ OPTIONS formatted as follows: | |||
follows: | ||||
+---------------+------------+-----------------------------+ | +---------------+------------+---------------------------------+ | |||
| Field Name | Field Type | Description | | | Field Name | Field Type | Description | | |||
+===============+============+=============================+ | +===============+============+=================================+ | |||
| OPTION-CODE | u_int16_t | LLQ | | | OPTION-CODE | u_int16_t | LLQ (1) | | |||
+---------------+------------+-----------------------------+ | +---------------+------------+---------------------------------+ | |||
| OPTION-LENGTH | u_int16_t | Length of following fields, | | | OPTION-LENGTH | u_int16_t | Length of following fields (18) | | |||
| | | as appropriate | | +---------------+------------+---------------------------------+ | |||
+---------------+------------+-----------------------------+ | | LLQ-VERSION | u_int16_t | Version of LLQ protocol | | |||
| VERSION | u_int16_t | Version of LLQ protocol | | | | | implemented in server (1) | | |||
| | | implemented in server | | +---------------+------------+---------------------------------+ | |||
+---------------+------------+-----------------------------+ | | LLQ-OPCODE | u_int16_t | LLQ-SETUP (1) | | |||
| LLQ-OPCODE | u_int16_t | LLQ-SETUP (1) | | +---------------+------------+---------------------------------+ | |||
+---------------+------------+-----------------------------+ | | LLQ-ERROR | u_int16_t | NO-ERROR (0) | | |||
| ERROR-CODE | u_int16_t | NO-ERROR | | +---------------+------------+---------------------------------+ | |||
+---------------+------------+-----------------------------+ | | LLQ-ID | u_int64_t | Originally granted ID, echoed | | |||
| LLQ-ID | u_int64_t | Originally granted ID, | | | | | in client's Response | | |||
| | | echoed in client's Response | | +---------------+------------+---------------------------------+ | |||
+---------------+------------+-----------------------------+ | | LLQ-LEASE | u_int32_t | Remaining life of LLQ, in | | |||
| LEASE-LIFE | u_int32_t | Remaining life of LLQ, in | | | | | seconds | | |||
| | | seconds | | +---------------+------------+---------------------------------+ | |||
+---------------+------------+-----------------------------+ | ||||
Table 6: Successful ACK + Answers OPT-RR RDATA Format | Table 6: Successful ACK + Answers LLQ OPTION Format | |||
If there is a significant delay in receiving a Challenge Response, or | If there is a significant delay in receiving a Challenge Response, or | |||
multiple Challenge Responses are issued (possibly because they were | multiple Challenge Responses are issued (possibly because they were | |||
lost en route to the client, causing the client to resend the | lost en route to the client, causing the client to resend the | |||
Challenge Response), the server MAY decrement the LEASE-LIFE by the | Challenge Response), the server MAY decrement the LLQ-LEASE by the | |||
time elapsed since the Setup Challenge was initially issued. | time elapsed since the Setup Challenge was initially issued. | |||
If the setup is completed over UDP and all initially available | If the setup is completed over UDP and all initially available | |||
answers to the question(s), additional records, and the OPT-RR do not | answers to the question(s), additional records, and the OPT pseudo-RR | |||
fit in a single packet, some or all additional records (excluding the | do not fit in a single IP packet, some or all additional records | |||
OPT-RR) MUST be omitted. If, after omission of all additional | (excluding the OPT pseudo-RR) MUST be omitted. If, after omission of | |||
records, the answers still do not fit in a single message, answers | all additional records, the answers still do not fit in a single | |||
MUST be removed until the message fits in a single packet. These | message, answers MUST be removed until the message fits in a single | |||
answers not delivered in the ACK + Answers MUST be delivered without | IP packet. These answers not delivered in the ACK + Answers MUST be | |||
undue delay to the client via Add Events (Section 6, "Event | delivered without undue delay to the client via Add Events | |||
Responses"). | (Section 6, "Event Responses"). | |||
5.3. Resource Record TTLs | 5.3. Resource Record TTLs | |||
The TTLs of resource records contained in answers to successful LLQs | The TTLs of resource records contained in answers to successful LLQs | |||
SHOULD be ignored by the client. The client MAY cache LLQ answers | SHOULD be ignored by the client. The client MAY cache LLQ answers | |||
until the client receives a gratuitous announcement (see Section 6, | until the client receives a gratuitous announcement (see Section 6, | |||
"Event Responses") indicating that the answer to the LLQ has changed. | "Event Responses") indicating that the answer to the LLQ has changed. | |||
The client SHOULD NOT cache answers after the LLQs LEASE-LIFE expires | The client SHOULD NOT cache answers after the LLQs LLQ-LEASE expires | |||
without being refreshed (see Section 7, "LLQ Lease-Life Expiration"). | without being refreshed (see Section 7, "LLQ Lease-Life Expiration"). | |||
If an LLQ request fails, the client SHOULD NOT cache answers for a | If an LLQ request fails, the client SHOULD NOT cache answers for a | |||
period longer than the client's polling interval. | period longer than the client's polling interval. | |||
Note that resource records intended specifically to be transmitted | Note that resource records intended specifically to be transmitted | |||
via LLQs (e.g., DNS Service Discovery resource records) may have | via LLQs (e.g., DNS Service Discovery resource records) may have | |||
unusually short TTLs. This is because it is assumed that the records | unusually short TTLs. This is because it is assumed that the records | |||
may change frequently, and that a client's cache coherence will be | may change frequently, and that a client's cache coherence will be | |||
maintained via the LLQ and gratuitous responses. Short TTLs prevent | maintained via the LLQ and gratuitous responses. Short TTLs prevent | |||
stale information from residing in intermediate DNS recursive | stale information from residing in intermediate DNS recursive | |||
skipping to change at line 671 ¶ | skipping to change at line 677 ¶ | |||
TTLs of resource records included in the Additional section of an LLQ | TTLs of resource records included in the Additional section of an LLQ | |||
response (which do not directly answer the LLQ) SHOULD be honored by | response (which do not directly answer the LLQ) SHOULD be honored by | |||
the client. | the client. | |||
6. Event Responses | 6. Event Responses | |||
When a change ("event") occurs to a name server's zone, the server | When a change ("event") occurs to a name server's zone, the server | |||
MUST check if the new or deleted resource records answer any LLQs. | MUST check if the new or deleted resource records answer any LLQs. | |||
If so, the changes MUST be communicated to the LLQ requesters in the | If so, the changes MUST be communicated to the LLQ requesters in the | |||
form of a gratuitous DNS response sent to the client, with the | form of a gratuitous DNS response sent to the client, with the | |||
question(s) being answered in the Question section, and answers to | relevant question(s) in the Question section, and the corresponding | |||
these questions in the Answer section. The response also includes an | answers in the Answer section. The response also includes an OPT | |||
OPT RR in the Additional section. This OPT RR contains, in its | pseudo-RR in the Additional section. This OPT pseudo-RR contains, in | |||
RDATA, an entry for each LLQ being answered in the message. Entries | its RDATA, an LLQ OPTION for each LLQ being answered in the message. | |||
must include the LLQ-ID. This reduces the potential for spoof events | Each LLQ OPTION must include the LLQ-ID. This reduces the potential | |||
being sent to a client. | for spoof events being sent to a client. | |||
Event Response OPT-RR RDATA Format: | ||||
+---------------+------------+---------------------------------+ | +---------------+------------+---------------------------------+ | |||
| Field Name | Field Type | Description | | | Field Name | Field Type | Description | | |||
+===============+============+=================================+ | +===============+============+=================================+ | |||
| OPTION-CODE | u_int16_t | LLQ (1) | | | OPTION-CODE | u_int16_t | LLQ (1) | | |||
+---------------+------------+---------------------------------+ | +---------------+------------+---------------------------------+ | |||
| OPTION-LENGTH | u_int16_t | Length of following fields (18) | | | OPTION-LENGTH | u_int16_t | Length of following fields (18) | | |||
+---------------+------------+---------------------------------+ | +---------------+------------+---------------------------------+ | |||
| VERSION | u_int16_t | Version of LLQ protocol | | | LLQ-VERSION | u_int16_t | Version of LLQ protocol | | |||
| | | implemented in server (1) | | | | | implemented in server (1) | | |||
+---------------+------------+---------------------------------+ | +---------------+------------+---------------------------------+ | |||
| LLQ-OPCODE | u_int16_t | LLQ-EVENT (3) | | | LLQ-OPCODE | u_int16_t | LLQ-EVENT (3) | | |||
+---------------+------------+---------------------------------+ | +---------------+------------+---------------------------------+ | |||
| ERROR-CODE | u_int16_t | 0 | | | LLQ-ERROR | u_int16_t | NO-ERROR (0) | | |||
+---------------+------------+---------------------------------+ | +---------------+------------+---------------------------------+ | |||
| LLQ-ID | u_int64_t | [As Appropriate] | | | LLQ-ID | u_int64_t | [As Appropriate] | | |||
+---------------+------------+---------------------------------+ | +---------------+------------+---------------------------------+ | |||
| LEASE-LIFE | u_int32_t | 0 | | | LLQ-LEASE | u_int32_t | 0 | | |||
+---------------+------------+---------------------------------+ | +---------------+------------+---------------------------------+ | |||
Table 7: Event Response OPT-RR RDATA | Table 7: Event Response LLQ OPTION Format | |||
Gratuitous responses for a single LLQ MAY be batched such that | Gratuitous responses for a single LLQ MAY be batched such that | |||
multiple changes are communicated in a single message. Responses | multiple changes are communicated in a single message. Responses | |||
MUST NOT be batched if this would cause a message that would | MUST NOT be batched if this would cause a message that would | |||
otherwise fit in a single packet to be truncated. While responses | otherwise fit in a single IP packet to be truncated. While responses | |||
MAY be deferred to provide opportunities for batching, responses | MAY be deferred to provide opportunities for batching, responses | |||
SHOULD NOT be delayed, for purposes of batching, for more than 30 | SHOULD NOT be delayed, for purposes of batching, for more than 30 | |||
seconds, as this would cause an unacceptable latency for the client. | seconds, as this would cause an unacceptable latency for the client. | |||
After sending a gratuitous response, the server MUST listen for an | After sending a gratuitous response, the server MUST listen for an | |||
acknowledgment from the client. If the client does not respond, the | acknowledgment from the client. If the client does not respond, the | |||
server MUST resend the response. The server MUST resend two times | server MUST resend the response. The server MUST resend two times | |||
(for a total of 3 transmissions), after which the server MUST | (for a total of 3 transmissions), after which the server MUST | |||
consider the client to be unreachable and delete its LLQ. The server | consider the client to be unreachable and delete its LLQ. The server | |||
MUST listen for 2 seconds before resending the response, 4 more | MUST listen for 2 seconds before resending the response, 4 more | |||
skipping to change at line 744 ¶ | skipping to change at line 748 ¶ | |||
client, either in an initial response or in an Add Event, becomes | client, either in an initial response or in an Add Event, becomes | |||
invalid (normally as a result of being removed via a dynamic update). | invalid (normally as a result of being removed via a dynamic update). | |||
The deleted resource record is sent in the Answer section of the | The deleted resource record is sent in the Answer section of the | |||
event to the client. The resource record TTL is set to -1, | event to the client. The resource record TTL is set to -1, | |||
indicating that the record has been removed. | indicating that the record has been removed. | |||
6.3. Gratuitous Response Acknowledgments | 6.3. Gratuitous Response Acknowledgments | |||
Upon receiving a gratuitous response ("event"), the client MUST send | Upon receiving a gratuitous response ("event"), the client MUST send | |||
an acknowledgment to the server. This acknowledgment is a DNS | an acknowledgment to the server. This acknowledgment is a DNS | |||
response echoing the OPT-RR contained in the event, with the message | response echoing the OPT pseudo-RR contained in the event, with the | |||
ID of the gratuitous response echoed in the message header. The | message ID of the gratuitous response echoed in the message header. | |||
acknowledgment MUST be sent to the source IP address and port from | The acknowledgment MUST be sent to the source IP address and port | |||
which the event originated. | from which the event originated. | |||
7. LLQ Lease-Life Expiration | 7. LLQ Lease-Life Expiration | |||
7.1. Refresh Request | 7.1. Refresh Request | |||
If the client desires to maintain the LLQ beyond the duration | If the client desires to maintain the LLQ beyond the duration | |||
specified in the LEASE-LIFE field of the ACK + Answers | specified in the LLQ-LEASE field of the ACK + Answers | |||
(Section 5.2.4), the client MUST send a Refresh Request. A Refresh | (Section 5.2.4), the client MUST send a Refresh Request. A Refresh | |||
Request is identical to an LLQ Challenge Response (Section 5.2.3) but | Request is identical to an LLQ Challenge Response (Section 5.2.3) but | |||
with the LLQ-OPCODE set to LLQ-REFRESH. Unlike a Challenge Response, | with the LLQ-OPCODE set to LLQ-REFRESH. Unlike a Challenge Response, | |||
a Refresh Request returns no answers. | a Refresh Request returns no answers. | |||
The client SHOULD refresh an LLQ when 80% of its lease life has | The client SHOULD refresh an LLQ when 80% of its LLQ-LEASE has | |||
elapsed. | elapsed. | |||
As a means of reducing network traffic, when constructing refresh | As a means of reducing network traffic, when constructing refresh | |||
messages, the client SHOULD include all LLQs established with a given | messages the client SHOULD include all LLQs established with a given | |||
server, even those not yet close to expiration. However, at least | server, even those not yet close to expiration. However, at least | |||
one LLQ MUST have elapsed at least 80% of its original LEASE-LIFE. | one LLQ MUST have elapsed at least 80% of its original LLQ-LEASE. | |||
The client MUST NOT include additional LLQs if doing so would cause | The client MUST NOT include additional LLQs if doing so would cause | |||
the message to no longer fit in a single packet. In this case, the | the message to no longer fit in a single IP packet. In this case, | |||
LLQs furthest from expiration should be omitted such that the message | the LLQs furthest from expiration should be omitted such that the | |||
fits in a single packet. (These LLQs SHOULD be refreshed in a | message fits in a single IP packet. (These LLQs SHOULD be refreshed | |||
separate message when 80% of one or more of their lease lives have | in a separate message when 80% of one or more of their lease lives | |||
elapsed.) When refreshing multiple LLQs simultaneously, the message | have elapsed.) When refreshing multiple LLQs simultaneously, the | |||
contains multiple questions and a single OPT-RR with multiple LLQ | message contains multiple questions and a single OPT pseudo-RR with | |||
metadata sections, one per question, with the metadata sections in | multiple LLQ OPTIONS, one per question, with the LLQ OPTIONS in the | |||
the same order as the questions they correspond to. | same order as the questions they correspond to. | |||
The client SHOULD specify the original lease life granted in the LLQ | The client SHOULD specify the original LLQ-LEASE granted in the LLQ | |||
response as the desired LEASE-LIFE in the refresh request. If | response as the desired LLQ-LEASE in the Refresh Request. If | |||
refreshing multiple LLQs simultaneously, the client SHOULD request | refreshing multiple LLQs simultaneously, the client SHOULD request | |||
the same lease life for all LLQs being refreshed (with the exception | the same LLQ-LEASE for all LLQs being refreshed (with the exception | |||
of termination requests; see below). | of termination requests; see below). | |||
To terminate an LLQ prior to its scheduled expiration (for instance, | To terminate an LLQ prior to its scheduled expiration (for instance, | |||
when the client terminates a DNS Service Discovery browse operation | when the client terminates a DNS Service Discovery browse operation | |||
or when a client is about to go to sleep or shut down), the client | or when a client is about to go to sleep or shut down), the client | |||
specifies a lease life of 0. | specifies an LLQ-LEASE value of 0. | |||
The client MUST listen for an acknowledgment from the server. The | The client MUST listen for an acknowledgment from the server. The | |||
client MAY retry up to two more times (for a total of 3 attempts) | client MAY retry up to two more times (for a total of 3 attempts) | |||
before considering the server down or unreachable. The client MUST | before considering the server down or unreachable. The client MUST | |||
NOT retry a first time before 90% of the lease life has expired and | NOT retry a first time before 90% of the LLQ-LEASE has expired and | |||
MUST NOT retry again before 95% of the lease life has expired. If | MUST NOT retry again before 95% of the LLQ-LEASE has expired. If the | |||
the server is determined to be down, the client MAY periodically | server is determined to be down, the client MAY periodically attempt | |||
attempt to re-establish the LLQ via an LLQ Setup Request message. | to re-establish the LLQ via an LLQ Setup Request message. The client | |||
The client MUST NOT attempt the LLQ Setup Request more than once per | MUST NOT attempt the LLQ Setup Request more than once per hour. | |||
hour. | ||||
7.2. LLQ Refresh Acknowledgment | 7.2. LLQ Refresh Acknowledgment | |||
Upon receiving an LLQ Refresh message, a server MUST send an | Upon receiving an LLQ Refresh message, a server MUST send an | |||
acknowledgment of the Refresh. This acknowledgment is formatted like | acknowledgment of the Refresh. This acknowledgment is formatted like | |||
the Setup ACK described in Section 5.2.3, but with the following | the "ACK + Answers" message described in Section 5.2.4, but with the | |||
variations: | following variations: | |||
The LLQ-OPCODE is set to LLQ-REFRESH. | * It contains no answers. | |||
NO-SUCH-LLQ MUST be returned as an error code if the client attempts | * The LLQ-OPCODE is set to LLQ-REFRESH. | |||
to refresh an expired or non-existent LLQ (as determined by the | ||||
LLQ-ID in the request). | ||||
The LLQ-ID in the acknowledgment is set to the LLQ-ID in the request. | * NO-SUCH-LLQ MUST be returned as an error code if the client | |||
attempts to refresh an expired or non-existent LLQ (as determined | ||||
by the LLQ-ID in the request). | ||||
* The LLQ-ID in the acknowledgment is set to the LLQ-ID in the | ||||
request. | ||||
8. Security Considerations | 8. Security Considerations | |||
Without care taken in the design of protocols such as this, servers | In datagram-based protocols (i.e., protocols running over UDP, or | |||
may be susceptible to denial-of-service (DoS) attacks, and clients | directly of IP, or similar), servers may be susceptible to denial-of- | |||
may be subjected to packet storms. Mechanisms have been added to the | service (DoS) attacks, and clients may be subjected to packet storms. | |||
protocol to limit potential for these attacks. | Carefully designed mechanisms are needed to limit potential for these | |||
attacks. | ||||
Note: This section contains no new protocol elements -- it serves | Note: This section contains no new protocol elements -- it serves | |||
only to explain the rationale behind protocol elements described | only to explain the rationale behind protocol elements described | |||
above as they relate to security. | above as they relate to security. | |||
8.1. Server DoS | 8.1. Server DoS | |||
LLQs require that servers be stateful, maintaining entries for each | LLQs require that servers be stateful, maintaining entries for each | |||
LLQ over a potentially long period of time. If unbounded in | LLQ over a potentially long period of time. If unbounded in | |||
quantity, these entries may overload the server. By returning | quantity, these entries may overload the server. By returning | |||
SERV-FULL in Setup Challenges, the server may limit the maximum | SERV-FULL in Setup Challenges, the server may limit the maximum | |||
number of LLQs it maintains. Additionally, the server may return | number of LLQs it maintains. Additionally, the server may return | |||
SERV-FULL to limit the number of LLQs requested for a single name and | SERV-FULL to limit the number of LLQs requested for a single name and | |||
type or by a single client. This throttling may be in the form of a | type, or by a single client. This throttling may be in the form of a | |||
hard limit, or, preferably, by token-bucket rate limiting. Such rate | hard limit, or, preferably, by token-bucket rate limiting. Such rate | |||
limiting should occur rarely in normal use and is intended to prevent | limiting should occur rarely in normal use and is intended to prevent | |||
DoS attacks -- thus, it is not built into the protocol explicitly but | DoS attacks -- thus, it is not built into the protocol explicitly but | |||
is instead implemented at the discretion of an administrator via the | is instead implemented at the discretion of an administrator via the | |||
SERV-FULL error and the LEASE-LIFE field to indicate a retry time to | SERV-FULL error and the LLQ-LEASE field to indicate a retry time to | |||
the client. | the client. | |||
8.2. Client Packet Storms | 8.2. Client Packet Storms | |||
In addition to protecting the server from DoS attacks, the protocol | In addition to protecting the server from DoS attacks, the LLQ | |||
limits the ability of a malicious host to cause the server to flood a | protocol limits the ability of a malicious host to cause the server | |||
client with packets. This is achieved via the four-way handshake | to flood a client with packets. This is achieved via the four-way | |||
upon setup, demonstrating reachability and willingness of the client | handshake upon setup, demonstrating reachability and willingness of | |||
to participate, and by requiring that gratuitous responses be ACK'd | the client to participate, and by requiring that gratuitous responses | |||
by the client. | be ACK'd by the client. | |||
Additionally, rate limiting by the LLQ client address, as described | Additionally, rate limiting by LLQ client address, as described in | |||
in Section 8.1, serves to limit the number of packets that can be | Section 8.1, serves to limit the number of packets that can be | |||
delivered to an unsuspecting client. | delivered to an unsuspecting client. | |||
8.3. Spoofing | 8.3. Spoofing | |||
A large random ID greatly reduces the risk of an off-path attacker | A large random ID greatly reduces the risk of an off-path attacker | |||
sending spoof packets to the client (containing spoof events) or to | sending spoof packets to the client (containing spoof events) or to | |||
the server (containing phony requests or refreshes). | the server (containing phony requests or refreshes). | |||
9. IANA Considerations | 9. IANA Considerations | |||
skipping to change at line 972 ¶ | skipping to change at line 979 ¶ | |||
In the course of using LLQ since 2005, some problems were discovered. | In the course of using LLQ since 2005, some problems were discovered. | |||
Since no further work is being done on the LLQ protocol, this LLQ | Since no further work is being done on the LLQ protocol, this LLQ | |||
specification will not be updated to remedy these problems. | specification will not be updated to remedy these problems. | |||
LLQ's IETF Standards Track successor, "DNS Push Notifications" | LLQ's IETF Standards Track successor, "DNS Push Notifications" | |||
[RFC8765], does not suffer from these problems, so all existing LLQ | [RFC8765], does not suffer from these problems, so all existing LLQ | |||
implementations are RECOMMENDED to migrate to using DNS Push | implementations are RECOMMENDED to migrate to using DNS Push | |||
Notifications, and all new implementations are RECOMMENDED to | Notifications, and all new implementations are RECOMMENDED to | |||
implement DNS Push Notifications instead of LLQ. | implement DNS Push Notifications instead of LLQ. | |||
Known problems with LLQ are documented here for the record. | Known problems with LLQ are documented here as a cautionary tale | |||
about the challenges of building an application protocol directly | ||||
using datagrams (like IP or UDP) without the benefit of a mature and | ||||
thoroughly reviewed intervening transport layer (such as TCP or | ||||
QUIC). | ||||
An LLQ "Setup Challenge" message from server to client is identical | An LLQ "Setup Challenge" message from server to client is identical | |||
to an LLQ "ACK + Answers" message from server to client when there | to an LLQ "ACK + Answers" message from server to client when there | |||
are no current answers for the query. If there is packet loss, | are no current answers for the query. If there is packet loss, | |||
retransmission, and duplication in the network, then a duplicated | retransmission, and duplication in the network, then a duplicated | |||
"Setup Challenge" message arriving late at the client would look like | "Setup Challenge" message arriving late at the client would look like | |||
an "ACK + Answers" message with no answers, causing the client to | an "ACK + Answers" message with no answers, causing the client to | |||
clear its cache of any records matching the query. | clear its cache of any records matching the query. | |||
Section 5.1 of this LLQ specification states: "Servers MUST NOT | Section 5.1 of this LLQ specification states, "Servers MUST NOT | |||
garbage collect LLQs that fail to complete the four-way handshake | garbage collect LLQs that fail to complete the four-way handshake | |||
until the initially granted LEASE-LIFE has elapsed". This is | until the initially granted LLQ-LEASE has elapsed". This is probably | |||
probably a mistake since it exposes LLQ servers to an easy resource- | a mistake since it exposes LLQ servers to an easy resource-exhaustion | |||
exhaustion denial-of-service attack. DNS Push Notifications is built | denial-of-service attack. LLQ's replacement, DNS Push Notifications | |||
using DNS Stateful Operations [RFC8490], which uses TLS over TCP; a | [RFC8765], is built using DNS Stateful Operations [RFC8490], which | |||
benefit of building on TCP is that there are already established | uses TLS over TCP; a benefit of building on TCP is that there are | |||
industry best practices to guard against SYN flooding and similar | already established industry best practices to guard against SYN | |||
attacks [SYN] [RFC4953]. | flooding and similar attacks [SYN] [RFC4953]. | |||
LLQ is built using UDP, and because the UDP protocol has no | The attempts here to pack multiple questions into a single UDP/IP | |||
standardized way of indicating the start and end of a session, | packet for efficiency are awkward, and lead to error-prone | |||
firewalls and NAT gateways tend to be fairly aggressive about | programming to deal with cases where some requests in a packet | |||
recycling UDP mappings that they believe to be disused [RFC4787] | succeed and other other requests in the same packet fail. Fully | |||
[RFC5382] [RFC7857]. Using a high keepalive traffic rate to maintain | specifying the correct handling in all possible cases would be a lot | |||
firewall or NAT mapping state could remedy this but would largely | of work to document, a lot of work to implement, and even more work | |||
defeat the purpose of using LLQ in the first place, which is to | to thoroughly test. DNS Push Notifications [RFC8765] avoids this | |||
provide efficient change notification without wasteful polling. | problem by using an underlying stream protocol (TLS/TCP) to deal with | |||
Because of this, existing LLQ clients use the NAT Port Mapping | packing small multiple messages into larger IP packets for | |||
Protocol (NAT-PMP) [RFC6886] and/or Port Control Protocol (PCP) | efficiency. | |||
[RFC6887] to establish longer port mapping lifetimes. This solves | ||||
the problem but adds extra complexity and doesn't work with firewalls | In some cases initial LLQ answers are delivered in the "ACK + | |||
and NAT gateways that don't support NAT-PMP or PCP. By using TCP | Answers" message, and in other cases, such as when all the initial | |||
instead of UDP, the DNS Push Notifications protocol benefits from | answers will not fit in a single IP packet, some of the initial | |||
better longevity of sessions through firewalls and NAT gateways that | answers are delivered in a subsequent "Add Event" message. Having | |||
don't support NAT-PMP or PCP. | two different ways to accomplish the same thing increases the | |||
possibility for programming errors. DNS Push Notifications [RFC8765] | ||||
corrects this error by having only one single consistent way to | ||||
deliver results. | ||||
LLQ is built using UDP, and because UDP has no standardized way of | ||||
indicating the start and end of a session, firewalls and NAT gateways | ||||
tend to be fairly aggressive about recycling UDP mappings that they | ||||
believe to be disused [RFC4787] [RFC5382] [RFC7857]. Using a high | ||||
keepalive traffic rate to maintain firewall or NAT mapping state | ||||
could remedy this but would largely defeat the purpose of using LLQ | ||||
in the first place, which is to provide efficient change notification | ||||
without wasteful polling. Because of this, existing LLQ clients use | ||||
the NAT Port Mapping Protocol (NAT-PMP) [RFC6886] and/or Port Control | ||||
Protocol (PCP) [RFC6887] to establish longer port mapping lifetimes. | ||||
This solves the problem but adds extra complexity and doesn't work | ||||
with firewalls and NAT gateways that don't support NAT-PMP or PCP. | ||||
By using TCP instead of UDP, the DNS Push Notifications protocol | ||||
benefits from better longevity of sessions through firewalls and NAT | ||||
gateways that don't support NAT-PMP or PCP. | ||||
Acknowledgments | Acknowledgments | |||
The concepts described in this document were originally explored, | The concepts described in this document were originally explored, | |||
developed, and implemented with help from Chris Sharp and Roger | developed, and implemented with help from Chris Sharp and Roger | |||
Pantos. | Pantos. | |||
In 2005 and 2006, Kiren Sekar made significant contributions to the | Kiren Sekar made significant contributions to the first draft of this | |||
first two versions of this document and wrote much of the code for | document and he wrote much of the code for the implementation of LLQ | |||
the implementation of LLQ, which shipped in Mac OS X 10.4 Tiger in | that shipped in Mac OS X 10.4 Tiger in April 2005. | |||
2005. | ||||
Authors' Addresses | Authors' Addresses | |||
Stuart Cheshire | Stuart Cheshire | |||
Apple Inc. | Apple Inc. | |||
One Apple Park Way | One Apple Park Way | |||
Cupertino, CA 95014 | Cupertino, CA 95014 | |||
United States of America | United States of America | |||
Phone: +1 (408) 996-1010 | Phone: +1 (408) 996-1010 | |||
End of changes. 95 change blocks. | ||||
356 lines changed or deleted | 385 lines changed or added | |||
This html diff was produced by rfcdiff 1.45. The latest version is available from http://tools.ietf.org/tools/rfcdiff/ |