From: Willem Toorop Date: Mon, 17 Nov 2025 14:29:19 +0000 (+0100) Subject: RFC 9824: Compact Denial of Existence in DNSSEC X-Git-Tag: 1.9.0-rc.1~16 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=940dab7dd38ee3da46d00933965c286807d8f339;p=thirdparty%2Fldns.git RFC 9824: Compact Denial of Existence in DNSSEC All the bits and pieces from IANA's DNS Parameters page Plus updated Extended DNS Errors --- diff --git a/Changelog b/Changelog index de6f69eb..56c097a9 100644 --- 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. diff --git a/examples/ldns-dpa.c b/examples/ldns-dpa.c index 46d8f9ad..9c7578a7 100644 --- a/examples/ldns-dpa.c +++ b/examples/ldns-dpa.c @@ -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; diff --git a/examples/ldns-testpkts.c b/examples/ldns-testpkts.c index 033b9601..c74f0f75 100644 --- a/examples/ldns-testpkts.c +++ b/examples/ldns-testpkts.c @@ -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; diff --git a/examples/ldns-testpkts.h b/examples/ldns-testpkts.h index 0a20d016..33b58740 100644 --- a/examples/ldns-testpkts.h +++ b/examples/ldns-testpkts.h @@ -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 */ diff --git a/host2str.c b/host2str.c index d0a20d42..9f2795af 100644 --- a/host2str.c +++ b/host2str.c @@ -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)) { diff --git a/ldns/edns.h b/ldns/edns.h index a33ed055..7e51ab32 100644 --- a/ldns/edns.h +++ b/ldns/edns.h @@ -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; diff --git a/ldns/packet.h b/ldns/packet.h index 2c60609f..97494414 100644 --- a/ldns/packet.h +++ b/ldns/packet.h @@ -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. */ diff --git a/ldns/rr.h b/ldns/rr.h index 159a91b7..dbffc839 100644 --- 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, diff --git a/packet.c b/packet.c index 059cc09b..cc38f7d4 100644 --- a/packet.c +++ b/packet.c @@ -26,7 +26,10 @@ */ #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));