]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
- Fix to add EDNS CO flag to testbound and debug message log.
authorW.C.A. Wijngaards <wouter@nlnetlabs.nl>
Mon, 1 Dec 2025 14:29:41 +0000 (15:29 +0100)
committerW.C.A. Wijngaards <wouter@nlnetlabs.nl>
Mon, 1 Dec 2025 14:29:41 +0000 (15:29 +0100)
doc/Changelog
sldns/rrdef.h
sldns/wire2str.c
testcode/testpkts.c
testcode/testpkts.h

index 2ddf13a9b96036a24b044bd93192bf81c630bb5c..eac6aa7f7851fb7e5b37cb0a0e47883db4c23f14 100644 (file)
@@ -1,3 +1,6 @@
+1 December 2025: Wouter
+       - Fix to add EDNS CO flag to testbound and debug message log.
+
 28 November 2025: Yorgos
        - For #1375, there is no DNSTAP environment if it wasn't configured.
 
index 529ef9a84fbd1ff215a6fef774477f3750020801..bbc3d5b866a2809079249eee0bba8d1c17a8008d 100644 (file)
@@ -486,6 +486,7 @@ enum sldns_enum_ede_code
 typedef enum sldns_enum_ede_code sldns_ede_code;
 
 #define LDNS_EDNS_MASK_DO_BIT 0x8000
+#define LDNS_EDNS_MASK_CO_BIT 0x4000
 
 /** TSIG and TKEY extended rcodes (16bit), 0-15 are the normal rcodes. */
 #define LDNS_TSIG_ERROR_NOERROR  0
index f4b01b0280de71cd46a7b216525969a4553f3a16..75b8f37b026fdec92ab803992209d207e2477c92 100644 (file)
@@ -2486,6 +2486,8 @@ int sldns_wire2str_edns_scan(uint8_t** data, size_t* data_len, char** str,
        w += sldns_str_print(str, str_len, " flags:");
        if((edns_bits & LDNS_EDNS_MASK_DO_BIT))
                w += sldns_str_print(str, str_len, " do");
+       if((edns_bits & LDNS_EDNS_MASK_CO_BIT))
+               w += sldns_str_print(str, str_len, " co");
        /* the extended rcode is the value set, shifted four bits,
         * and or'd with the original rcode */
        if(ext_rcode) {
index 6124610634813d1f9b5f09ba5630358b3b6883ea..8b92df2e729cf37ce8a9b144dc6ec16e3673fc7a 100644 (file)
@@ -135,6 +135,8 @@ static void matchline(char* line, struct entry* e)
                        e->match_ttl = 1;
                } else if(str_keyword(&parse, "DO")) {
                        e->match_do = 1;
+               } else if(str_keyword(&parse, "CO")) {
+                       e->match_co = 1;
                } else if(str_keyword(&parse, "noedns")) {
                        e->match_noedns = 1;
                } else if(str_keyword(&parse, "ednsdata")) {
@@ -178,7 +180,7 @@ static void matchline(char* line, struct entry* e)
 
 /** parse REPLY line */
 static void replyline(char* line, uint8_t* reply, size_t reply_len,
-       int* do_flag)
+       int* do_flag, int* co_flag)
 {
        char* parse = line;
        if(reply_len < LDNS_HEADER_SIZE) error("packet too short for header");
@@ -236,6 +238,8 @@ static void replyline(char* line, uint8_t* reply, size_t reply_len,
                        LDNS_AD_SET(reply);
                } else if(str_keyword(&parse, "DO")) {
                        *do_flag = 1;
+               } else if(str_keyword(&parse, "CO")) {
+                       *co_flag = 1;
                } else {
                        error("could not parse REPLY: '%s'", parse);
                }
@@ -289,6 +293,7 @@ static struct entry* new_entry(void)
        e->match_all_noedns = 0;
        e->match_ttl = 0;
        e->match_do = 0;
+       e->match_co = 0;
        e->match_noedns = 0;
        e->match_serial = 0;
        e->ixfr_soa_serial = 0;
@@ -521,15 +526,17 @@ static void add_rr(char* rrstr, uint8_t* pktbuf, size_t pktsize,
 
 /* add EDNS 4096 opt record */
 static void
-add_edns(uint8_t* pktbuf, size_t pktsize, int do_flag, uint8_t *ednsdata,
-       uint16_t ednslen, size_t* pktlen)
+add_edns(uint8_t* pktbuf, size_t pktsize, int do_flag, int co_flag,
+       uint8_t *ednsdata, uint16_t ednslen, size_t* pktlen)
 {
        uint8_t edns[] = {0x00, /* root label */
                0x00, LDNS_RR_TYPE_OPT, /* type */
                0x04, 0xD0, /* class is UDPSIZE 1232 */
                0x00, /* TTL[0] is ext rcode */
                0x00, /* TTL[1] is edns version */
-               (uint8_t)(do_flag?0x80:0x00), 0x00, /* TTL[2-3] is edns flags, DO */
+               (uint8_t)(do_flag?0x80:0x00)
+               | (uint8_t)(co_flag?0x40:0x00)
+               , 0x00, /* TTL[2-3] is edns flags, DO */
                (uint8_t)((ednslen >> 8) & 0xff),
                (uint8_t)(ednslen  & 0xff), /* rdatalength */
        };
@@ -561,6 +568,7 @@ read_entry(FILE* in, const char* name, struct sldns_file_parse_state* pstate,
        uint8_t pktbuf[MAX_PACKETLEN];
        size_t pktlen = LDNS_HEADER_SIZE;
        int do_flag = 0; /* DO flag in EDNS */
+       int co_flag = 0; /* CO flag in EDNS */
        memset(pktbuf, 0, pktlen); /* ID = 0, FLAGS="", and rr counts 0 */
 
        while(fgets(line, (int)sizeof(line), in) != NULL) {
@@ -598,7 +606,7 @@ read_entry(FILE* in, const char* name, struct sldns_file_parse_state* pstate,
                if(str_keyword(&parse, "MATCH")) {
                        matchline(parse, current);
                } else if(str_keyword(&parse, "REPLY")) {
-                       replyline(parse, pktbuf, pktlen, &do_flag);
+                       replyline(parse, pktbuf, pktlen, &do_flag, &co_flag);
                } else if(str_keyword(&parse, "ADJUST")) {
                        adjustline(parse, current, cur_reply);
                } else if(str_keyword(&parse, "EXTRA_PACKET")) {
@@ -654,15 +662,16 @@ read_entry(FILE* in, const char* name, struct sldns_file_parse_state* pstate,
                        if(hex_ednsdata_buffer)
                                sldns_buffer_free(hex_ednsdata_buffer);
                        if(pktlen != 0) {
-                               if(do_flag || cur_reply->raw_ednsdata) {
+                               if(do_flag || co_flag
+                                       || cur_reply->raw_ednsdata) {
                                        if(cur_reply->raw_ednsdata &&
                                                sldns_buffer_limit(cur_reply->raw_ednsdata))
-                                               add_edns(pktbuf, sizeof(pktbuf), do_flag,
+                                               add_edns(pktbuf, sizeof(pktbuf), do_flag, co_flag,
                                                        sldns_buffer_begin(cur_reply->raw_ednsdata),
                                                        (uint16_t)sldns_buffer_limit(cur_reply->raw_ednsdata),
                                                        &pktlen);
                                        else
-                                               add_edns(pktbuf, sizeof(pktbuf), do_flag,
+                                               add_edns(pktbuf, sizeof(pktbuf), do_flag, co_flag,
                                                        NULL, 0, &pktlen);
                                }
                                cur_reply->reply_pkt = memdup(pktbuf, pktlen);
@@ -909,6 +918,22 @@ get_do_flag(uint8_t* pkt, size_t len)
        return (int)(edns_bits&LDNS_EDNS_MASK_DO_BIT);
 }
 
+/** return true if the CO flag is set */
+static int
+get_co_flag(uint8_t* pkt, size_t len)
+{
+       uint16_t edns_bits;
+       uint8_t* walk = pkt;
+       size_t walk_len = len;
+       if(!pkt_find_edns_opt(&walk, &walk_len)) {
+               return 0;
+       }
+       if(walk_len < 6)
+               return 0; /* malformed */
+       edns_bits = sldns_read_uint16(walk+4);
+       return (int)(edns_bits&LDNS_EDNS_MASK_CO_BIT);
+}
+
 /** Snips the specified EDNS option out of the OPT record and puts it in the
  *  provided buffer. The buffer should be able to hold any opt data ie 65535.
  *  Returns the length of the option written,
@@ -1654,6 +1679,10 @@ find_match(struct entry* entries, uint8_t* query_pkt, size_t len,
                        verbose(3, "no DO bit set\n");
                        continue;
                }
+               if(p->match_co && !get_co_flag(query_pkt, len)) {
+                       verbose(3, "no CO bit set\n");
+                       continue;
+               }
                if(p->match_noedns && get_has_edns(query_pkt, len)) {
                        verbose(3, "bad; EDNS OPT present\n");
                        continue;
index c6a3725f368ebc2d25fa8a05bcfe3026ba50ff21..e36802dbc8ac2a1eef6db8e8be732518546588aa 100644 (file)
@@ -218,6 +218,8 @@ struct entry {
        uint8_t match_ttl;
        /** match DO bit */
        uint8_t match_do;
+       /** match CO bit */
+       uint8_t match_co;
        /** match absence of EDNS OPT record in query */
        uint8_t match_noedns;
        /** match edns data field given in hex */