Changes between Version 10 and Version 11 of EDNS0


Ignore:
Timestamp:
07/01/2013 10:14:29 AM (3 years ago)
Author:
rwall
Comment:

Tidied up formatting and added some more bullet points

Legend:

Unmodified
Added
Removed
Modified
  • EDNS0

    v10 v11  
    11= EDNS Plan =
    22
    3 An attempt to understand the pieces of EDNS0 and the changes necessary to have Twisted Names support it:
     3An attempt to understand the pieces of EDNS0 and DNSSEC and the
     4changes necessary to have Twisted Names support it:
    45
    56[[PageOutline(2-4)]]
    67
     8== Overview ==
     9Twisted.names includes widely used public APIs that have existed for
     10over twelve years (r440).
     11
     12However many of these existing APIs are inelegant and too broad. eg
     13 * [/documents/current/api/twisted.names.dns.Message.html]
     14So we will introduce new EDNS related classes with carefully designed,
     15minimal public APIs. New APIs will be designed for maximum usability
     16but as narrow as possible, to minimise future backwards compatibility
     17complications.
     18
     19Twisted has a strict wiki:CompatibilityPolicy. So we will aim for zero
     20changes to existing public APIs.
     21
     22Existing classes will be wrapped where appropriate and in other cases,
     23shared functionality will be re-factored for reuse in new classes.
     24 * #6382
     25 * wiki:TheWayWeDoThingsNow
     26 * http://pyvideo.org/video/1684/the-end-of-object-inheritance-the-beginning-of
     27
     28With the introduction of the new EDNS APIs, old sub-optimal APIs can
     29then be deprecated and eventually removed in future releases.
     30 * #1216
     31
     32Before designing and implementing new APIs, we will examine existing
     33open source DNS projects for APIs and code that we can reuse /
     34integrate.
     35 * https://www.nlnetlabs.nl/projects/ldns/index.html
     36 * http://trac.secdev.org/scapy/ticket/84
     37 * http://doc.powerdns.com/html/recursor-design-and-engineering.html#idp9245952
     38 * https://bazaar.launchpad.net/~ubuntu-branches/ubuntu/saucy/bind9/saucy/view/head:/lib/dns/message.c
     39
     40Use of an existing Python DNS library (or a C library with Python
     41bindings) will be considered if it is well written, actively
     42maintained, well tested and has a compatible licence. However the
     43potential time savings from reusing an existing library will be
     44weighed against the overhead of introducing an additional Twisted
     45install dependency. eg
     46 * http://www.dnspython.org/
     47
     48Below are some specific examples of new APIs that we plan to
     49introduce.
    750
    851== EDNS0 ==
    952
    1053=== [ticket:5668 OPT record] ===
    11       - Explicit OPT record class/type
    12         - Teach cache about it - MUST NOT BE CACHED
    13           - EDNSMessage will remove OPT records during decoding so they
    14             may never be seen by cache or clients if EDNSMessage
    15             becomes the standard message factory for DNSDatagramProtocol.
    16         - Teach recursive resolver about it - MUST NOT BE FORWARDED
    17         - Teach loaders about - MUST NOT BE LOADED FROM MASTER FILE
    18       - ~~Extended label ("0" "1" type) parsing~~ (REJECTED BY 2671bis)
    19       - Maximum UDP datagram size field
    20       - Arbitrary extension support (attribute/value pairs in RDATA section)
     54 1. Explicit OPT record class/type
     55    1. wrap the existing RRHeader class - to minimise code duplication
     56       and maintenance overhead by only requiring a single
     57       implementation of RRHeader byte string parser.
     58    2. extracts OPT specific header fields from the equivalent RRHeader
     59       fields.
     60    3. Maximum UDP datagram size field
     61    4. Arbitrary extension support (attribute/value pairs in RDATA section)
     62    5. OPTHeader will encode and decode OPT variable options in an
     63       underlying UnknownRecord payload class.
     64 2. Discussion
     65    1. Teach cache about it - MUST NOT BE CACHED
     66    2. Teach recursive resolver about it - MUST NOT BE FORWARDED
     67    3. EDNSMessage will remove OPT records during decoding so they may
     68       never be seen by cache or clients if EDNSMessage becomes the
     69       standard message factory for DNSDatagramProtocol.
     70    4. Teach loaders about - MUST NOT BE LOADED FROM MASTER FILE
     71    5. ~~Extended label ("0" "1" type) parsing~~ (REJECTED BY 2671bis)
    2172
    2273=== [ticket:5675 Extended Message object with additional EDNS0 items] ===
    23       - Subclass of Message? (no! subclassing is bad!)
    24       - maxSize (Message has it already, can we re-use it?)
    25       - Extended RCODE - partly defined by RCODE field in OPT record
    26 
    27 === Configure Max payload size ===
    28 
    29 Accept max UDP size as configuration?
    30 
    31 Determine it from system automatically?
    32       - Server and client need this
     74 1. Write a new EDNSMessage class.
     75    1. It will wrap the existing dns.Message class.
     76    2. Its decode method will extract an OPT record from the additional
     77       section and merge its attributes with those of the underlying
     78       non-EDNS Message.
     79    3. Its encode method will check for EDNS specific attributes (eg
     80       RCODE > 15) and add an OPT record to the additional records of
     81       its underlying Message class before encoding.
     82 2. Discussion
     83    1. maxSize (Message has it already, can we re-use it?)
    3384
    3485=== [ticket:5670 Client] ===
    35       - Automatically send EDNS0 queries
    36       - Fall back to DNS queries when detecting server does not support EDNS0?
     86 1. A new EDNSAgent client API
     87    1. Automatically send EDNS0 queries
     88    2. Fall back to DNS queries when detecting server does not support EDNS0?
     89    3. It will be modelled on twisted.web.client.Agent which was
     90       introduced to replace the old twisted.web.client APIs.
     91    4. Agents can be chainable / composable.
     92    5. Eg An EDNSAgent will be introduced with a fixed maxUdpPayloadSize parameter.
     93    6. Another AutoMTUDiscoveryAgent can wrap EDNSAgent and will reissue
     94       queries with successively lower advertised UDP payload size until
     95       a response is received.
     96    7. A future DNSSECValidatingAgent can validate responses by issuing
     97       queries for the DS and DNSKEY records from the root down.
     98 2. Discussion
     99    1. How to choose max UDP size?
     100       1. Accept max UDP size as configuration?
     101       2. Determine it from system automatically?
     102       3. Server and client need this
    37103
    38104=== [ticket:5669 Server] ===
    39       - Send EDNS0 responses to EDNS0 queries
    40       - (Do not send EDNS0 responses to DNS queries)
    41 
     105 1. A new EDNS server API
     106    1. Send EDNS0 responses to EDNS0 queries
     107    2. (Do not send EDNS0 responses to DNS queries)
     108    3. Ensures the EDNS requests are responded to using the advertised
     109       UDP payload size.
     110    4. Limits additional RRSETs so that responses fit the client max UDP
     111       payload size or marks response Messages truncated.
     112    5. Sets EDNS RCODEs in response to malformed EDNS requests.
     113
     114== RRSET improvements ==
     115
     116DNSSEC seems to rely on stable RRSETs. eg for signatures, for
     117predictable caching of records and signatures, for predictable
     118truncation of large DNSSEC responses.
     119
     120There appear to be various problems with twisted.names current
     121handling of RRSETs.
     122
     123=== Canonical Form and Order of Resource Records ===
     124
     125https://tools.ietf.org/html/rfc4034#section-6
     126
     127RRSETs must be arranged in canonical order before their signatures are
     128calculated / verified.
     129
     130This ticket will introduce an algorithm for sorting records
     131according to the rules described in
     132https://tools.ietf.org/html/rfc4034#section-6.
     133
     134Sorting appears to be the responsibility of the verifying client
     135not the server.
     136
     137The fact that Bind has config options for changing the order of
     138RRSETS on the server side and the client side suggests that the
     139canonical ordering of records should be done only for the purpose
     140of DNSSEC validation. It should probably not change the order of
     141records returned by various IResolver methods.
     142
     143 * http://www.zytrax.com/books/dns/ch7/queries.html#rrset-order
     144
     145=== Serving RRSETs ===
     146
     147twisted.names.dns.Message should follow the guidance in RFC2181
     148regarding the handling of TTLs for records in the same
     149RRSET. Alternatively consider handling this higher up in
     150t.n.authority.FileAuthority, t.n.cache, t.n.resolver etc.
     151
     152 * https://tools.ietf.org/html/rfc2181#section-5
     153 * https://tools.ietf.org/html/rfc2181#section-5.2
     154 * "the use of differing TTLs in an RRSet is hereby deprecated,
     155   the TTLs of all RRs in an RRSet must be the same"
     156 * "In no case may a server send an RRSet with TTLs not all
     157   equal."
     158 * https://tools.ietf.org/html/rfc2181#section-5.5
     159 * "A Resource Record Set should only be included once in any DNS
     160   reply.  It may occur in any of the Answer, Authority, or
     161   Additional Information sections, as required.  However it
     162   should not be repeated in the same, or any other, section,
     163   except where explicitly required by a specification."
     164
     165=== Receiving RRSETs ===
     166
     167twisted.names.client should somehow signal an error if it receives
     168RRSETs whose RRs have different TTLs.
     169
     170twisted.names.resolver,root should discard RRSETs whose RRs have
     171diffent TTLs.
     172
     173 * https://tools.ietf.org/html/rfc2181#section-5.2
     174 * "Should a client receive a response containing RRs from an
     175   RRSet with differing TTLs, it should treat this as an error.
     176   If the RRSet concerned is from a non-authoritative source for
     177   this data, the client should simply ignore the RRSet,"
     178
     179=== Caching RRSETs ===
     180
     181twisted.names.cache should follow the RRSET ranking guidance when
     182serving and replacing items in its cache.
     183
     184 * https://tools.ietf.org/html/rfc2181#section-5.4
     185 * "Servers must never merge RRs from a response with RRs in their
     186   cache to form an RRSet.  If a response contains data that would
     187   form an RRSet with data in a server's cache the server must
     188   either ignore the RRs in the response, or discard the entire
     189   RRSet currently in the cache, as appropriate."
     190 * https://tools.ietf.org/html/rfc2181#section-5.4.1
     191 * "When considering whether to accept an RRSet in a reply, or
     192   retain an RRSet already in its cache instead, a server should
     193   consider the relative likely trustworthiness of the various
     194   data"
     195
     196=== Selective truncate ===
     197
     198twisted.names.dns.Message currently truncates messages based on the
     199combined length of the answer, auth, and additional sections. Instead
     200it (or something higher up) should look at the length of the answers
     201and only set the truncate flag if the entire answers RRSET is greater
     202than the maxPayloadSize. If there is room, the auth and additional
     203records can also be included, but entire RRSETs must be included or
     204none.
     205
     206 * https://tools.ietf.org/html/rfc2181#section-9
     207 * "The TC bit should be set in responses only when an RRSet is
     208   required as a part of the response, but could not be included
     209   in its entirety."
    42210
    43211== DNSSEC ==
    44212
    45     Much of this work (including tests) has already been implemented by
    46     BobNovas in two large patches attached to original
    47     tickets: #5450, #5453, #5454. Look there before implementing
    48     anything from scratch.
     213Much of this work (including tests) has already been implemented by
     214BobNovas in two large patches attached to original
     215tickets: #5450, #5453, #5454. Look there before implementing anything
     216from scratch.
    49217
    50218=== New DNSSEC Records and Lookup Methods ===
    51 
    52        DNSSEC introduces six new resource record types. Each new record
    53        type will require a new dns.Record subclass and a new
    54        lookupMethod added to t.i.interfaces.IResolver,
    55        t.n.common.ResolverBase and a corresponding free function in
    56        t.n.client.
    57 
    58        For ease of review, this work can be split into six tickets.
    59 
    60        These new records can be implemented independently of EDNS and
    61        independently of DNSSEC validation and new DNSSEC related message
    62        headers.
    63 
    64        Initially, this will allow twisted.names clients to explicitly
    65        request these DNSSEC related records.
    66 
    67        lookupZone will return DNSSEC related records when transferring
    68        from DNSSEC authoritative servers.
    69 
    70        t.n.secondary.SecondaryAuthority will download DNSSEC records and
    71        serve them when queries specifically ask for them by type.
    72 
    73        t.n.authority.FileAuthority will load DNSSEC records and serve
    74        them when queries specifically ask for them by type.
    75 
    76        * DNSKey
    77          https://tools.ietf.org/html/rfc4034#section-2
    78        * RRSIG
    79          https://tools.ietf.org/html/rfc4034#section-3
    80        * NSEC
    81          https://tools.ietf.org/html/rfc4034#section-4
    82        * DS
    83          https://tools.ietf.org/html/rfc4034#section-5
    84        * NSEC3
    85          https://tools.ietf.org/html/rfc5155#section-3
    86        * NSEC3Param
    87          https://tools.ietf.org/html/rfc5155#section-4
    88 
    89 
    90 === RRSET improvements ===
    91 
    92        DNSSEC seems to rely on stable RRSETs. eg for signatures, for
    93        predictable caching of records and signatures, for predictable
    94        truncation of large DNSSEC responses.
    95 
    96        There appear to be various problems with twisted.names current
    97        handling of RRSETs.
    98 
    99 ==== Canonical Form and Order of Resource Records ====
    100 
    101           https://tools.ietf.org/html/rfc4034#section-6
    102 
    103           RRSETs must be arranged in canonical order before their signatures are
    104           calculated / verified.
    105 
    106           This ticket will introduce an algorithm for sorting records
    107           according to the rules described in
    108           https://tools.ietf.org/html/rfc4034#section-6.
    109 
    110           Sorting appears to be the responsibility of the verifying client
    111           not the server.
    112 
    113           The fact that Bind has config options for changing the order of
    114           RRSETS on the server side and the client side suggests that the
    115           canonical ordering of records should be done only for the purpose
    116           of DNSSEC validation. It should probably not change the order of
    117           records returned by various IResolver methods.
    118 
    119           * http://www.zytrax.com/books/dns/ch7/queries.html#rrset-order
    120 
    121 ==== Serving RRSETs ====
    122 
    123           twisted.names.dns.Message should follow the guidance in RFC2181
    124           regarding the handling of TTLs for records in the same
    125           RRSET. Alternatively consider handling this higher up in
    126           t.n.authority.FileAuthority, t.n.cache, t.n.resolver etc.
    127 
    128           * https://tools.ietf.org/html/rfc2181#section-5
    129           * https://tools.ietf.org/html/rfc2181#section-5.2
    130           * "the use of differing TTLs in an RRSet is hereby deprecated,
    131             the TTLs of all RRs in an RRSet must be the same"
    132           * "In no case may a server send an RRSet with TTLs not all
    133             equal."
    134           * https://tools.ietf.org/html/rfc2181#section-5.5
    135           * "A Resource Record Set should only be included once in any DNS
    136             reply.  It may occur in any of the Answer, Authority, or
    137             Additional Information sections, as required.  However it
    138             should not be repeated in the same, or any other, section,
    139             except where explicitly required by a specification."
    140 
    141 ==== Receiving RRSETs ====
    142 
    143           twisted.names.client should somehow signal an error if it
    144           receives RRSETs whose RRs have different TTLs.
    145 
    146           twisted.names.resolver,root should discard RRSETs whose RRs
    147           have diffent TTLs.
    148 
    149           * https://tools.ietf.org/html/rfc2181#section-5.2
    150           * "Should a client receive a response containing RRs from an
    151             RRSet with differing TTLs, it should treat this as an error.
    152             If the RRSet concerned is from a non-authoritative source for
    153             this data, the client should simply ignore the RRSet,"
    154 
    155 ==== Caching RRSETs ====
    156 
    157           twisted.names.cache should follow the RRSET ranking guidance
    158           when serving and replacing items in its cache.
    159 
    160           * https://tools.ietf.org/html/rfc2181#section-5.4
    161           * "Servers must never merge RRs from a response with RRs in their
    162             cache to form an RRSet.  If a response contains data that would
    163             form an RRSet with data in a server's cache the server must
    164             either ignore the RRs in the response, or discard the entire
    165             RRSet currently in the cache, as appropriate."
    166           * https://tools.ietf.org/html/rfc2181#section-5.4.1
    167           * "When considering whether to accept an RRSet in a reply, or
    168             retain an RRSet already in its cache instead, a server should
    169             consider the relative likely trustworthiness of the various
    170             data"
    171 
    172 ==== Selective truncate ====
    173 
    174           twisted.names.dns.Message currently truncates messages based on
    175           the combined length of the answer, auth, and additional
    176           sections. Instead it (or something higher up) should look at
    177           the length of the answers and only set the truncate flag if the
    178           entire answers RRSET is greater than the
    179           maxPayloadSize. If there is room, the auth and additional
    180           records can also be included, but entire RRSETs must be
    181           included or none.
    182 
    183           * https://tools.ietf.org/html/rfc2181#section-9
    184           * "The TC bit should be set in responses only when an RRSet is
    185             required as a part of the response, but could not be included
    186             in its entirety."
    187 
    188 ==== Security-aware Non-validating Client ====
    189 
    190        A twisted.names.client will be able to generate EDNS queries with
    191        one or both the DO bit and the AD bit set.
    192 
    193        It will examine the state of the AD bit in the response to
    194        determine whether the upstream resolver claims to have validated
    195        the records in the response.
    196 
    197        If the DO bit was set, it will expect to receive DNSSEC related
    198        records in the response.
    199 
    200        https://tools.ietf.org/html/rfc4035#section-4.9
    201 
    202 ==== Validating Client ====
    203 
    204        A twisted.names.client which sends DO + CD flagged queries and
    205        performs its own validation of the returned DNSSEC signatures.
    206 
    207        TODO: needs more thought.
    208 
    209 ==== Validating Recursive / Forwarding Server ====
    210 
    211        This can use the Validating client API above, but may need to do
    212        some processing of answers based on the query flags.
    213 
    214        TODO: needs more thought.
    215 
    216 ==== DNSSEC Aware Authoritative Server ====
    217 
    218        A twisted.names.authority API which knows where and when to
    219        include RRSIG, DNSKEY, NSEC, NSEC3 records etc with responses.
    220 
    221        The actual generation of the DNSSEC records can be performed
    222        using external tools such as
    223        [http://linux.die.net/man/8/dnssec-signzone dnssec-signzone]
    224 
    225        TODO: needs more thought.
     219 1. DNSSEC introduces six new resource record types. Each new record
     220    type will require a new dns.Record subclass and a new lookupMethod
     221    added to t.i.interfaces.IResolver, t.n.common.ResolverBase and a
     222    corresponding free function in t.n.client.
     223    1. DNSKey
     224       https://tools.ietf.org/html/rfc4034#section-2
     225    2. RRSIG
     226       https://tools.ietf.org/html/rfc4034#section-3
     227    3. NSEC
     228       https://tools.ietf.org/html/rfc4034#section-4
     229    4. DS
     230       https://tools.ietf.org/html/rfc4034#section-5
     231    5. NSEC3
     232       https://tools.ietf.org/html/rfc5155#section-3
     233    6. NSEC3Param
     234       https://tools.ietf.org/html/rfc5155#section-4
     235 2. For ease of review, this work can be split into six tickets.
     236 3. These new records can be implemented independently of EDNS and
     237    independently of DNSSEC validation and new DNSSEC related message
     238    headers.
     239 4. Initially, this will allow twisted.names clients to explicitly
     240    request these DNSSEC related records.
     241 5. lookupZone will return DNSSEC related records when transferring
     242    from DNSSEC authoritative servers.
     243 6. t.n.secondary.SecondaryAuthority will download DNSSEC records and
     244    serve them when queries specifically ask for them by type.
     245 7. t.n.authority.FileAuthority will load DNSSEC records and serve
     246    them when queries specifically ask for them by type.
     247
     248
     249=== Security-aware Non-validating Client ===
     250
     251A twisted.names.client will be able to generate EDNS queries with one
     252or both the DO bit and the AD bit set.
     253
     254It will examine the state of the AD bit in the response to determine
     255whether the upstream resolver claims to have validated the records in
     256the response.
     257
     258If the DO bit was set, it will expect to receive DNSSEC related
     259records in the response.
     260
     261https://tools.ietf.org/html/rfc4035#section-4.9
     262
     263
     264=== Validating Client ===
     265
     266A twisted.names.client which sends DO + CD flagged queries and
     267performs its own validation of the returned DNSSEC signatures.
     268
     269TODO: needs more thought.
     270
     271=== Validating Recursive / Forwarding Server ===
     272
     273This can use the Validating client API above, but may need to do some
     274processing of answers based on the query flags.
     275
     276TODO: needs more thought.
     277
     278=== DNSSEC Aware Authoritative Server ===
     279
     280A twisted.names.authority API which knows where and when to include
     281RRSIG, DNSKEY, NSEC, NSEC3 records etc with responses.
     282
     283The actual generation of the DNSSEC records can be performed using
     284external tools such as
     285[http://linux.die.net/man/8/dnssec-signzone dnssec-signzone]
     286
     287TODO: needs more thought.
    226288
    227289== RFCs ==
    228290
    229    General:
    230     - [https://tools.ietf.org/html/rfc1034 1034:DOMAIN NAMES - CONCEPTS AND FACILITIES]
    231     - [https://tools.ietf.org/html/rfc1035 1035: DOMAIN NAMES - IMPLEMENTATION AND SPECIFICATION]
    232     - [https://tools.ietf.org/html/rfc2181 2181: Clarifications to the DNS Specification]
    233     - [https://tools.ietf.org/html/rfc4697 4697: Observed DNS Resolution Misbehavior]
    234     - [https://tools.ietf.org/html/rfc5625 5625: DNS Proxy Implementation Guidelines]
    235 
    236    EDNS:
    237     - [http://tools.ietf.org/html/rfc6891 6891: Extension Mechanisms for DNS (EDNS(0))]
    238 
    239    DNSSEC:
    240     - [https://tools.ietf.org/html/rfc4033 4033: DNS Security Introduction and Requirements]
    241     - [https://tools.ietf.org/html/rfc4034 4034: Resource Records for the DNS Security Extensions]
    242     - [https://tools.ietf.org/html/rfc4035 4035: Protocol Modifications for the DNS Security Extensions]
    243     - [https://tools.ietf.org/html/rfc5155 5155: DNS Security (DNSSEC) Hashed Authenticated Denial of Existence]
    244     - [https://tools.ietf.org/html/rfc6781 6781: DNSSEC Operational Practices, Version 2]
    245     - [https://tools.ietf.org/html/rfc6840 6840: Clarifications and Implementation Notes for DNS Security (DNSSEC)]
    246     - [https://tools.ietf.org/html/rfc3833 3833: Threat Analysis of the Domain Name System (DNS)]
     291=== General ===
     292 1. [https://tools.ietf.org/html/rfc1034 1034:DOMAIN NAMES - CONCEPTS AND FACILITIES]
     293 2. [https://tools.ietf.org/html/rfc1035 1035: DOMAIN NAMES - IMPLEMENTATION AND SPECIFICATION]
     294 3. [https://tools.ietf.org/html/rfc2181 2181: Clarifications to the DNS Specification]
     295 4. [https://tools.ietf.org/html/rfc4697 4697: Observed DNS Resolution Misbehavior]
     296 5. [https://tools.ietf.org/html/rfc5625 5625: DNS Proxy Implementation Guidelines]
     297
     298=== EDNS ===
     299 1. [http://tools.ietf.org/html/rfc6891 6891: Extension Mechanisms for DNS (EDNS(0))]
     300
     301=== DNSSEC ===
     302 1. [https://tools.ietf.org/html/rfc4033 4033: DNS Security Introduction and Requirements]
     303 2. [https://tools.ietf.org/html/rfc4034 4034: Resource Records for the DNS Security Extensions]
     304 3. [https://tools.ietf.org/html/rfc4035 4035: Protocol Modifications for the DNS Security Extensions]
     305 4. [https://tools.ietf.org/html/rfc5155 5155: DNS Security (DNSSEC) Hashed Authenticated Denial of Existence]
     306 5. [https://tools.ietf.org/html/rfc6781 6781: DNSSEC Operational Practices, Version 2]
     307 6. [https://tools.ietf.org/html/rfc6840 6840: Clarifications and Implementation Notes for DNS Security (DNSSEC)]
     308 7. [https://tools.ietf.org/html/rfc3833 3833: Threat Analysis of the Domain Name System (DNS)]
    247309
    248310== MISC / TODO / Notes ==
    249     1. "If a query message with more than one OPT RR is received, a
    250        FORMERR (RCODE=1) MUST be returned."
    251        [https://tools.ietf.org/html/rfc6891#section-6.1.1 RFC6891 6.1.1]
    252 
    253        * Multiple OPT RR will be detected in EDNSMessage.decode
    254        * If multiple OPT RR are detected, set EDNSMessage.decodingErrors.append(EFORMAT)
    255        * DNSServerFactory.messageReceived checks message.decodingErrors
    256        * If not empty, it sets message.rCode =
    257          message.decodingErrors.pop(0) before sending the message back
    258          to client without further processing.
    259        * If DNSServerFactory.verbose logging is enabled, all message.decodingErrors will
    260          be logged.
    261        * I tested Google DNS and Bind Authoritative DNS responses to
    262          multi OPT queries.
    263          * Google seems to ignore all but the first OPT RR and responds
    264            without error.
    265          * Bind responds with RCODE=1
    266          * https://bazaar.launchpad.net/~ubuntu-branches/ubuntu/saucy/bind9/saucy/view/head:/lib/dns/message.c#L1274
    267            {{{
    268                   } else if (rdtype == dns_rdatatype_opt) {
    269                           /*
    270            * The name of an OPT record must be ".", it
    271            * must be in the additional data section, and
    272            * it must be the first OPT we've seen.
    273                            */
    274                           if (!dns_name_equal(dns_rootname, name) ||
    275                               msg->opt != NULL)
    276                                   DO_FORMERR;
    277                           skip_name_search = ISC_TRUE;
    278                           skip_type_search = ISC_TRUE;
    279             }}}
    280          * PowerDNS appears to ignore all but the first OPT RR (untested)
    281            https://github.com/PowerDNS/pdns/blob/master/pdns/dnsrecords.cc#L375
    282            {{{
    283 
    284            bool getEDNSOpts(const MOADNSParser& mdp, EDNSOpts* eo)
    285            {
    286              if(mdp.d_header.arcount && !mdp.d_answers.empty()) {
    287                BOOST_FOREACH(const MOADNSParser::answers_t::value_type& val, mdp.d_answers) {
    288                  if(val.first.d_place == DNSRecord::Additional && val.first.d_type == QType::OPT) {
    289                    eo->d_packetsize=val.first.d_class;
    290 
    291                    EDNS0Record stuff;
    292                    uint32_t ttl=ntohl(val.first.d_ttl);
    293                    memcpy(&stuff, &ttl, sizeof(stuff));
    294 
    295                    eo->d_extRCode=stuff.extRCode;
    296                    eo->d_version=stuff.version;
    297                    eo->d_Z = ntohs(stuff.Z);
    298                    OPTRecordContent* orc =
    299                      dynamic_cast<OPTRecordContent*>(val.first.d_content.get());
    300                    if(!orc)
    301                      return false;
    302                    orc->getData(eo->d_options);
    303                    return true;
    304                  }
    305                }
    306              }
    307              return false;
    308            }
    309 
    310            }}}
    311 
    312     2. "EXTENDED-RCODE Forms the upper 8 bits of extended 12-bit RCODE"
    313        [https://tools.ietf.org/html/rfc6891#section-6.1.3 RFC6891 6.1.3]
    314 
    315        * Decode: EDNSMessage.decode will merge the RCODE and
    316          OPTHeader.extendedRCODE setting the  rCode attribute.
    317 
    318        * Encode: If rCode is > 15, EDNSMessage.encode will set the lower
    319          4 bits as RCODE and set the upper 8 bits on a new or existing
    320          OPTHeader which will be added to the additional section.
    321 
    322     3. "VERSION Indicates the implementation level of the setter"
    323        [https://tools.ietf.org/html/rfc6891#section-6.1.3 RFC6891 6.1.3]
    324 
    325        * "If a responder does not implement the VERSION level of the
    326          request, then it MUST respond with RCODE=BADVERS"
    327 
    328          * Decode: in EDNSMessage.decode, if version > 0, EDNSMessage.decodingErrors.append(EBADVERS)
    329 
    330        * "This document assigns EDNS Extended RCODE 16 to "BADVERS" in
    331          the DNS RCODES registry" https://tools.ietf.org/html/rfc6891#section-9
    332 
    333          * Create dns.EBADVERS = 16
    334 
    335     4. "DO DNSSEC OK bit as defined by [RFC3225]." https://tools.ietf.org/html/rfc6891#section-6.1.4
    336 
    337        * Set EDNSMessage.dnssecOK during decode using value from
    338          OPTHeader.dnssecOK.
    339 
    340        * Add or update an existing OPTHeader instance during encode.
     311 1. "If a query message with more than one OPT RR is received, a
     312    FORMERR (RCODE=1) MUST be returned."
     313    [https://tools.ietf.org/html/rfc6891#section-6.1.1 RFC6891 6.1.1]
     314    1. Multiple OPT RR will be detected in EDNSMessage.decode
     315    2. If multiple OPT RR are detected, set EDNSMessage.decodingErrors.append(EFORMAT)
     316    3. DNSServerFactory.messageReceived checks message.decodingErrors
     317    4. If not empty, it sets message.rCode =
     318       message.decodingErrors.pop(0) before sending the message back
     319       to client without further processing.
     320    5. If DNSServerFactory.verbose logging is enabled, all message.decodingErrors will
     321       be logged.
     322    6. I tested Google DNS and Bind Authoritative DNS responses to
     323       multi OPT queries.
     324       1. Google seems to ignore all but the first OPT RR and responds
     325          without error.
     326       2. Bind responds with RCODE=1
     327       3. https://bazaar.launchpad.net/~ubuntu-branches/ubuntu/saucy/bind9/saucy/view/head:/lib/dns/message.c#L1274
     328          {{{
     329
     330          } else if (rdtype == dns_rdatatype_opt) {
     331                  /*
     332          * The name of an OPT record must be ".", it
     333          * must be in the additional data section, and
     334          * it must be the first OPT we've seen.
     335                   */
     336                  if (!dns_name_equal(dns_rootname, name) ||
     337                      msg->opt != NULL)
     338                          DO_FORMERR;
     339                  skip_name_search = ISC_TRUE;
     340                  skip_type_search = ISC_TRUE;
     341
     342          }}}
     343       4. PowerDNS appears to ignore all but the first OPT RR (untested)
     344          https://github.com/PowerDNS/pdns/blob/master/pdns/dnsrecords.cc#L375
     345          {{{
     346
     347          bool getEDNSOpts(const MOADNSParser& mdp, EDNSOpts* eo)
     348          {
     349            if(mdp.d_header.arcount && !mdp.d_answers.empty()) {
     350              BOOST_FOREACH(const MOADNSParser::answers_t::value_type& val, mdp.d_answers) {
     351                if(val.first.d_place == DNSRecord::Additional && val.first.d_type == QType::OPT) {
     352                  eo->d_packetsize=val.first.d_class;
     353
     354                  EDNS0Record stuff;
     355                  uint32_t ttl=ntohl(val.first.d_ttl);
     356                  memcpy(&stuff, &ttl, sizeof(stuff));
     357
     358                  eo->d_extRCode=stuff.extRCode;
     359                  eo->d_version=stuff.version;
     360                  eo->d_Z = ntohs(stuff.Z);
     361                  OPTRecordContent* orc =
     362                    dynamic_cast<OPTRecordContent*>(val.first.d_content.get());
     363                  if(!orc)
     364                    return false;
     365                  orc->getData(eo->d_options);
     366                  return true;
     367                }
     368              }
     369            }
     370            return false;
     371          }
     372
     373          }}}
     374
     375 2. "EXTENDED-RCODE Forms the upper 8 bits of extended 12-bit RCODE"
     376    [https://tools.ietf.org/html/rfc6891#section-6.1.3 RFC6891 6.1.3]
     377    1. Decode: EDNSMessage.decode will merge the RCODE and
     378       OPTHeader.extendedRCODE setting the  rCode attribute.
     379    2. Encode: If rCode is > 15, EDNSMessage.encode will set the lower
     380       4 bits as RCODE and set the upper 8 bits on a new or existing
     381       OPTHeader which will be added to the additional section.
     382
     383 3. "VERSION Indicates the implementation level of the setter"
     384    [https://tools.ietf.org/html/rfc6891#section-6.1.3 RFC6891 6.1.3]
     385    1. "If a responder does not implement the VERSION level of the
     386       request, then it MUST respond with RCODE=BADVERS"
     387       1. Decode: in EDNSMessage.decode, if version > 0, EDNSMessage.decodingErrors.append(EBADVERS)
     388
     389    2. "This document assigns EDNS Extended RCODE 16 to "BADVERS" in
     390       the DNS RCODES registry" https://tools.ietf.org/html/rfc6891#section-9
     391       1. Create dns.EBADVERS = 16
     392
     393 4. "DO DNSSEC OK bit as defined by [RFC3225]." https://tools.ietf.org/html/rfc6891#section-6.1.4
     394    1. Set EDNSMessage.dnssecOK during decode using value from
     395       OPTHeader.dnssecOK.
     396    2. Add or update an existing OPTHeader instance during encode.