- Fix to add EDNS CO flag to testbound and debug message log.

This commit is contained in:
W.C.A. Wijngaards 2025-12-01 15:29:41 +01:00
parent 83336477c6
commit 5c66c48a1b
5 changed files with 45 additions and 8 deletions

View 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.

View 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

View 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) {

View 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;

View 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 */