From 5c66c48a1ba66f2ebd94030f5970aadfe3726a50 Mon Sep 17 00:00:00 2001 From: "W.C.A. Wijngaards" Date: Mon, 1 Dec 2025 15:29:41 +0100 Subject: [PATCH] - Fix to add EDNS CO flag to testbound and debug message log. --- doc/Changelog | 3 +++ sldns/rrdef.h | 1 + sldns/wire2str.c | 2 ++ testcode/testpkts.c | 45 +++++++++++++++++++++++++++++++++++++-------- testcode/testpkts.h | 2 ++ 5 files changed, 45 insertions(+), 8 deletions(-) diff --git a/doc/Changelog b/doc/Changelog index 2ddf13a9b..eac6aa7f7 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -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. diff --git a/sldns/rrdef.h b/sldns/rrdef.h index 529ef9a84..bbc3d5b86 100644 --- a/sldns/rrdef.h +++ b/sldns/rrdef.h @@ -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 diff --git a/sldns/wire2str.c b/sldns/wire2str.c index f4b01b028..75b8f37b0 100644 --- a/sldns/wire2str.c +++ b/sldns/wire2str.c @@ -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) { diff --git a/testcode/testpkts.c b/testcode/testpkts.c index 612461063..8b92df2e7 100644 --- a/testcode/testpkts.c +++ b/testcode/testpkts.c @@ -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; diff --git a/testcode/testpkts.h b/testcode/testpkts.h index c6a3725f3..e36802dbc 100644 --- a/testcode/testpkts.h +++ b/testcode/testpkts.h @@ -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 */ -- 2.47.3