]> git.ipfire.org Git - thirdparty/ldns.git/commitdiff
RFC 9824: Compact Denial of Existence in DNSSEC
authorWillem Toorop <willem@nlnetlabs.nl>
Mon, 17 Nov 2025 14:29:19 +0000 (15:29 +0100)
committerWillem Toorop <willem@nlnetlabs.nl>
Mon, 17 Nov 2025 14:29:19 +0000 (15:29 +0100)
All the bits and pieces from IANA's DNS Parameters page
Plus updated Extended DNS Errors

Changelog
examples/ldns-dpa.c
examples/ldns-testpkts.c
examples/ldns-testpkts.h
host2str.c
ldns/edns.h
ldns/packet.h
ldns/rr.h
packet.c

index de6f69ebef562709a4295a6658bacd25934b397e..56c097a9bb7cef81e0b9b40cc9146a206734e27b 100644 (file)
--- a/Changelog
+++ b/Changelog
@@ -24,6 +24,8 @@
        * PR #282: ensure returning pkt with LDNS_STATUS_OK. Thanks grobian.
        * PR #286: Fix RR Type AMTRELAY type nogateway, to print relay '.',
          and memory leaks in parsing it.
+       * DSYNC is no longer a draft RR type and compiled by default
+       * RFC 9824 support: Compact Denial of Existence in DNSSEC
 
 1.8.4  2024-07-19
        * Fix building documentation in build directory.
index 46d8f9ad7baa735fd339fe25617a12326b6528fd..9c7578a72e04296275b2650d57674f68d298428e 100644 (file)
@@ -85,6 +85,7 @@ enum enum_match_ids {
        MATCH_EDNS,
        MATCH_EDNS_PACKETSIZE,
        MATCH_DO,
+       MATCH_CO,
        MATCH_QUESTION_SIZE,
        MATCH_ANSWER_SIZE,
        MATCH_AUTHORITY_SIZE,
@@ -237,6 +238,7 @@ const match_table matches[] = {
        { MATCH_RD, "rd", "value of rd bit", TYPE_BOOL },
        { MATCH_EDNS, "edns", "existence of edns rr", TYPE_BOOL },
        { MATCH_DO, "do", "value of do bit", TYPE_BOOL },
+       { MATCH_CO, "co", "value of co bit", TYPE_BOOL },
        { MATCH_QUESTION_SIZE, "questionsize", "number of rrs in the question section", TYPE_INT },
        { MATCH_ANSWER_SIZE, "answersize", "number of rrs in the answer section", TYPE_INT },
        { MATCH_AUTHORITY_SIZE, "authoritysize", "number of rrs in the authority section", TYPE_INT },
@@ -1129,6 +1131,7 @@ value_matches(match_id id,
                case MATCH_CD:
                case MATCH_RD:
                case MATCH_DO:
+               case MATCH_CO:
                case MATCH_PACKETSIZE:
                case MATCH_EDNS:
                case MATCH_EDNS_PACKETSIZE:
@@ -1214,6 +1217,9 @@ get_string_value(match_id id, ldns_pkt *pkt, ldns_rdf *src_addr, ldns_rdf *dst_a
                case MATCH_DO:
                        snprintf(val, valsize, "%u", (unsigned int) ldns_pkt_edns_do(pkt));
                        break;
+               case MATCH_CO:
+                       snprintf(val, valsize, "%u", (unsigned int) ldns_pkt_edns_co(pkt));
+                       break;
                case MATCH_QUESTION_SIZE:
                        snprintf(val, valsize, "%u", (unsigned int) ldns_pkt_qdcount(pkt));
                        break;
index 033b96013784adb014d0ae6b0bc42bb6150044c7..c74f0f75477f50b2485fb138cd5c2621f830edc5 100644 (file)
@@ -114,6 +114,8 @@ static void matchline(char* line, struct entry* e)
                        e->match_ttl = true;
                } else if(str_keyword(&parse, "DO")) {
                        e->match_do = true;
+               } else if(str_keyword(&parse, "CO")) {
+                       e->match_co = true;
                } else if(str_keyword(&parse, "noedns")) {
                        e->match_noedns = true;
                } else if(str_keyword(&parse, "ednsdata")) {
@@ -202,6 +204,9 @@ static void replyline(char* line, ldns_pkt *reply)
                } else if(str_keyword(&parse, "DO")) {
                        ldns_pkt_set_edns_udp_size(reply, 4096);
                        ldns_pkt_set_edns_do(reply, true);
+               } else if(str_keyword(&parse, "CO")) {
+                       ldns_pkt_set_edns_udp_size(reply, 4096);
+                       ldns_pkt_set_edns_co(reply, true);
                } else {
                        error("could not parse REPLY: '%s'", parse);
                }
@@ -246,6 +251,7 @@ static struct entry* new_entry(void)
        e->match_all = false;
        e->match_ttl = false;
        e->match_do = false;
+       e->match_co = false;
        e->match_noedns = false;
        e->match_serial = false;
        e->ixfr_soa_serial = 0;
@@ -794,6 +800,10 @@ find_match(struct entry* entries, ldns_pkt* query_pkt,
                        verbose(3, "no DO bit set\n");
                        continue;
                }
+               if(p->match_co && !ldns_pkt_edns_co(query_pkt)) {
+                       verbose(3, "no CO bit set\n");
+                       continue;
+               }
                if(p->match_noedns && ldns_pkt_edns(query_pkt)) {
                        verbose(3, "bad; EDNS OPT present\n");
                        continue;
index 0a20d016ae483a6ed68f5a66721ddd4dabda83dc..33b58740ee161e0d115da11c29db83369f4884b3 100644 (file)
@@ -180,6 +180,8 @@ struct entry {
        bool match_ttl;
        /** match DO bit */
        bool match_do;
+       /** match CO bit */
+       bool match_co;
        /** match absence of EDNS OPT record in query */
        bool match_noedns;
        /** match edns data field given in hex */
index d0a20d42503fca01effb01b9410be7856e1311ba..9f2795afadba1a4f475c90ab9bc06e88fa3368db 100644 (file)
@@ -2590,6 +2590,18 @@ ldns_edns_ede2buffer_str(ldns_buffer* output, uint8_t* data, size_t len)
        case LDNS_EDE_TOO_EARLY:
                ldns_buffer_printf(output, " 26 (Too Early)");
                break;
+       case LDNS_EDE_UNSUPPORTED_NSEC3_ITERATIONS_VALUE:
+               ldns_buffer_printf(output, " 27 (Unsupported NSEC3 Iterations Value)");
+               break;
+       case LDNS_EDE_UNABLE_TO_CONFORM_TO_POLICY:
+               ldns_buffer_printf(output, " 28 (Unable to conform to policy)");
+               break;
+       case LDNS_EDE_SYNTHESIZED:
+               ldns_buffer_printf(output, " 29 (Synthesized)");
+               break;
+       case LDNS_EDE_INVALID_QUERY_TYPE:
+               ldns_buffer_printf(output, " 30 (Invalid Query Type)");
+               break;
        default:
                ldns_buffer_printf(output, " %02x", data[0]);
                ldns_buffer_printf(output, " %02x", data[1]);
@@ -2818,6 +2830,9 @@ ldns_pkt2buffer_str_fmt(ldns_buffer *output,
                        if (ldns_pkt_edns_do(pkt)) {
                                ldns_buffer_printf(output, " do");
                        }
+                       if (ldns_pkt_edns_co(pkt)) {
+                               ldns_buffer_printf(output, " co");
+                       }
                        /* the extended rcode is the value set, shifted four bits,
                         * and or'd with the original rcode */
                        if (ldns_pkt_edns_extended_rcode(pkt)) {
index a33ed05576794302de3a10872ce9034eafc7470e..7e51ab322ceaa45036b6a4fa7277d7357b367192 100644 (file)
@@ -76,7 +76,11 @@ enum ldns_edns_enum_ede_code
        LDNS_EDE_NETWORK_ERROR = 23,
        LDNS_EDE_INVALID_DATA = 24,
        LDNS_EDE_SIGNATURE_EXPIRED_BEFORE_VALID = 25,
-       LDNS_EDE_TOO_EARLY = 26
+       LDNS_EDE_TOO_EARLY = 26, /* RFC 9250 */
+       LDNS_EDE_UNSUPPORTED_NSEC3_ITERATIONS_VALUE = 27, /* RFC 9276 */
+       LDNS_EDE_UNABLE_TO_CONFORM_TO_POLICY = 28, /* draft-homburg-dnsop-codcp-00 */
+       LDNS_EDE_SYNTHESIZED = 29, /* https://github.com/PowerDNS/pdns/pull/12334 */
+       LDNS_EDE_INVALID_QUERY_TYPE = 30 /* RFC 9824 */
 };
 typedef enum ldns_edns_enum_ede_code ldns_edns_ede_code;
 
index 2c60609fc07af6cfa9e7523609cf5b39f982cbce..974944149a27a990ad011b7c78acc64618158ad5 100644 (file)
@@ -709,6 +709,19 @@ bool ldns_pkt_edns_do(const ldns_pkt *packet);
  */
 void ldns_pkt_set_edns_do(ldns_pkt *packet, bool value);
 
+/**
+ * return the packet's edns co bit
+ * \param[in] packet the packet
+ * \return the bit's value
+ */
+bool ldns_pkt_edns_co(const ldns_pkt *packet);
+/**
+ * Set the packet's edns co bit
+ * \param[in] packet the packet
+ * \param[in] value the bit's new value
+ */
+void ldns_pkt_set_edns_co(ldns_pkt *packet, bool value);
+
 /**
  * return the packet's EDNS header bits that are unassigned.
  */
index 159a91b7dc77825447653e2449df5ce7f72e05cf..dbffc83986d04a2230c8214532527efa8848f4f2 100644 (file)
--- a/ldns/rr.h
+++ b/ldns/rr.h
@@ -211,7 +211,7 @@ enum ldns_enum_rr_type
        LDNS_RR_TYPE_EUI48 = 108, /* RFC 7043 */
        LDNS_RR_TYPE_EUI64 = 109, /* RFC 7043 */
 
-       LDNS_RR_TYPE_NXNAME = 128, /* draft-ietf-dnsop-compact-denial-of-existence */
+       LDNS_RR_TYPE_NXNAME = 128, /* RFC 9824 */
 
        LDNS_RR_TYPE_TKEY = 249, /* RFC 2930 */
        LDNS_RR_TYPE_TSIG = 250,
index 059cc09b0f976e098eb33e31c2849a740b7ee29e..cc38f7d4863fd24bbbec7a07ae991a1527f2edb9 100644 (file)
--- a/packet.c
+++ b/packet.c
  */
 
 #define LDNS_EDNS_MASK_DO_BIT 0x8000
-#define LDNS_EDNS_MASK_UNASSIGNED (0xFFFF & ~LDNS_EDNS_MASK_DO_BIT)
+#define LDNS_EDNS_MASK_CO_BIT 0x4000
+#define LDNS_EDNS_MASK_UNASSIGNED (0xFFFF & ~( LDNS_EDNS_MASK_DO_BIT \
+                                             | LDNS_EDNS_MASK_CO_BIT ))
+
 
 /* TODO defines for 3600 */
 /* convert to and from numerical flag values */
@@ -243,6 +246,22 @@ ldns_pkt_set_edns_do(ldns_pkt *packet, bool value)
        }
 }
 
+bool
+ldns_pkt_edns_co(const ldns_pkt *packet)
+{
+       return (packet->_edns_z & LDNS_EDNS_MASK_CO_BIT);
+}
+
+void
+ldns_pkt_set_edns_co(ldns_pkt *packet, bool value)
+{
+       if (value) {
+               packet->_edns_z = packet->_edns_z | LDNS_EDNS_MASK_CO_BIT;
+       } else {
+               packet->_edns_z = packet->_edns_z & ~LDNS_EDNS_MASK_CO_BIT;
+       }
+}
+
 uint16_t
 ldns_pkt_edns_unassigned(const ldns_pkt *packet)
 {
@@ -753,6 +772,7 @@ ldns_pkt_edns(const ldns_pkt *pkt)
                ldns_pkt_edns_extended_rcode(pkt) > 0 ||
                ldns_pkt_edns_data(pkt) ||
                ldns_pkt_edns_do(pkt) ||
+               ldns_pkt_edns_co(pkt) ||
                pkt->_edns_list ||
                 pkt->_edns_present
               );
@@ -1254,6 +1274,7 @@ ldns_pkt_clone(const ldns_pkt *pkt)
                ldns_pkt_set_edns_data(new_pkt, 
                        ldns_rdf_clone(ldns_pkt_edns_data(pkt)));
        ldns_pkt_set_edns_do(new_pkt, ldns_pkt_edns_do(pkt));
+       ldns_pkt_set_edns_co(new_pkt, ldns_pkt_edns_co(pkt));
        if (pkt->_edns_list)
                ldns_pkt_set_edns_option_list(new_pkt,
                        ldns_edns_option_list_clone(pkt->_edns_list));