Measure cryptographic work done by DNSSEC.

This commit is contained in:
Simon Kelley
2024-01-01 17:17:25 +00:00
parent 51471cafa5
commit 59d30390c9
3 changed files with 63 additions and 33 deletions

View File

@@ -796,7 +796,7 @@ struct frec {
struct blockdata *stash; /* Saved reply, whilst we validate */ struct blockdata *stash; /* Saved reply, whilst we validate */
size_t stash_len; size_t stash_len;
#ifdef HAVE_DNSSEC #ifdef HAVE_DNSSEC
int class, work_counter; int class, work_counter, validate_counter;
struct frec *dependent; /* Query awaiting internally-generated DNSKEY or DS query */ struct frec *dependent; /* Query awaiting internally-generated DNSKEY or DS query */
struct frec *next_dependent; /* list of above. */ struct frec *next_dependent; /* list of above. */
struct frec *blocking_query; /* Query which is blocking us. */ struct frec *blocking_query; /* Query which is blocking us. */
@@ -1417,10 +1417,12 @@ int in_zone(struct auth_zone *zone, char *name, char **cut);
/* dnssec.c */ /* dnssec.c */
#ifdef HAVE_DNSSEC #ifdef HAVE_DNSSEC
size_t dnssec_generate_query(struct dns_header *header, unsigned char *end, char *name, int class, int type, int edns_pktsz); size_t dnssec_generate_query(struct dns_header *header, unsigned char *end, char *name, int class, int type, int edns_pktsz);
int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int class); int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, char *name,
int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int class); char *keyname, int class, int *validate_count);
int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char *name,
char *keyname, int class, int *validate_count);
int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int *class, int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int *class,
int check_unsigned, int *neganswer, int *nons, int *nsec_ttl); int check_unsigned, int *neganswer, int *nons, int *nsec_ttl, int *validate_count);
int dnskey_keytag(int alg, int flags, unsigned char *key, int keylen); int dnskey_keytag(int alg, int flags, unsigned char *key, int keylen);
size_t filter_rrsigs(struct dns_header *header, size_t plen); size_t filter_rrsigs(struct dns_header *header, size_t plen);
int setup_timestamp(void); int setup_timestamp(void);

View File

@@ -445,7 +445,7 @@ static int explore_rrset(struct dns_header *header, size_t plen, int class, int
*/ */
static int validate_rrset(time_t now, struct dns_header *header, size_t plen, int class, int type, int sigidx, int rrsetidx, static int validate_rrset(time_t now, struct dns_header *header, size_t plen, int class, int type, int sigidx, int rrsetidx,
char *name, char *keyname, char **wildcard_out, struct blockdata *key, int keylen, char *name, char *keyname, char **wildcard_out, struct blockdata *key, int keylen,
int algo_in, int keytag_in, unsigned long *ttl_out) int algo_in, int keytag_in, unsigned long *ttl_out, int *validate_counter)
{ {
unsigned char *p; unsigned char *p;
int rdlen, j, name_labels, algo, labels, key_tag, sig_fail_cnt; int rdlen, j, name_labels, algo, labels, key_tag, sig_fail_cnt;
@@ -655,8 +655,10 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
if (key) if (key)
{ {
if (algo_in == algo && keytag_in == key_tag && if (algo_in == algo && keytag_in == key_tag)
verify(key, keylen, sig, sig_len, digest, hash->digest_size, algo)) (*validate_counter)++;
if (verify(key, keylen, sig, sig_len, digest, hash->digest_size, algo))
return STAT_SECURE; return STAT_SECURE;
} }
else else
@@ -667,6 +669,8 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
crecp->addr.key.keytag == key_tag && crecp->addr.key.keytag == key_tag &&
crecp->uid == (unsigned int)class) crecp->uid == (unsigned int)class)
{ {
(*validate_counter)++;
if (verify(crecp->addr.key.keydata, crecp->addr.key.keylen, sig, sig_len, digest, hash->digest_size, algo)) if (verify(crecp->addr.key.keydata, crecp->addr.key.keylen, sig, sig_len, digest, hash->digest_size, algo))
return (labels < name_labels) ? STAT_SECURE_WILDCARD : STAT_SECURE; return (labels < name_labels) ? STAT_SECURE_WILDCARD : STAT_SECURE;
@@ -699,7 +703,8 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
STAT_NEED_DS DS records to validate a key not found, name in keyname STAT_NEED_DS DS records to validate a key not found, name in keyname
STAT_NEED_KEY DNSKEY records to validate a key not found, name in keyname STAT_NEED_KEY DNSKEY records to validate a key not found, name in keyname
*/ */
int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int class) int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, char *name,
char *keyname, int class, int *validate_counter)
{ {
unsigned char *psave, *p = (unsigned char *)(header+1); unsigned char *psave, *p = (unsigned char *)(header+1);
struct crec *crecp, *recp1; struct crec *crecp, *recp1;
@@ -806,6 +811,7 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch
hash->update(ctx, (unsigned int)wire_len, (unsigned char *)name); hash->update(ctx, (unsigned int)wire_len, (unsigned char *)name);
hash->update(ctx, (unsigned int)rdlen, psave); hash->update(ctx, (unsigned int)rdlen, psave);
hash->digest(ctx, hash->digest_size, digest); hash->digest(ctx, hash->digest_size, digest);
(*validate_counter)++; /* computing a hash is a unit of crypto work. */
from_wire(name); from_wire(name);
@@ -833,7 +839,7 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch
failflags &= ~DNSSEC_FAIL_NOSIG; failflags &= ~DNSSEC_FAIL_NOSIG;
rc = validate_rrset(now, header, plen, class, T_DNSKEY, sigcnt, rrcnt, name, keyname, rc = validate_rrset(now, header, plen, class, T_DNSKEY, sigcnt, rrcnt, name, keyname,
NULL, key, rdlen - 4, algo, keytag, &sig_ttl); NULL, key, rdlen - 4, algo, keytag, &sig_ttl, validate_counter);
if (STAT_ISEQUAL(rc, STAT_ABANDONED)) if (STAT_ISEQUAL(rc, STAT_ABANDONED))
return STAT_ABANDONED; return STAT_ABANDONED;
@@ -958,7 +964,8 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch
STAT_ABANDONED resource exhaustion. STAT_ABANDONED resource exhaustion.
*/ */
int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int class) int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char *name,
char *keyname, int class, int *validate_counter)
{ {
unsigned char *p = (unsigned char *)(header+1); unsigned char *p = (unsigned char *)(header+1);
int qtype, qclass, rc, i, neganswer = 0, nons = 0, servfail = 0, neg_ttl = 0, found_supported = 0; int qtype, qclass, rc, i, neganswer = 0, nons = 0, servfail = 0, neg_ttl = 0, found_supported = 0;
@@ -983,7 +990,7 @@ int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char
servfail = neganswer = nons = 1; servfail = neganswer = nons = 1;
else else
{ {
rc = dnssec_validate_reply(now, header, plen, name, keyname, NULL, 0, &neganswer, &nons, &neg_ttl); rc = dnssec_validate_reply(now, header, plen, name, keyname, NULL, 0, &neganswer, &nons, &neg_ttl, validate_counter);
if (STAT_ISEQUAL(rc, STAT_INSECURE)) if (STAT_ISEQUAL(rc, STAT_INSECURE))
{ {
@@ -1466,8 +1473,8 @@ static int check_nsec3_coverage(struct dns_header *header, size_t plen, int dige
} }
/* returns 0 on success, or DNSSEC_FAIL_* value on failure. */ /* returns 0 on success, or DNSSEC_FAIL_* value on failure. */
static int prove_non_existence_nsec3(struct dns_header *header, size_t plen, unsigned char **nsecs, int nsec_count, static int prove_non_existence_nsec3(struct dns_header *header, size_t plen, unsigned char **nsecs, int nsec_count, char *workspace1,
char *workspace1, char *workspace2, char *name, int type, char *wildname, int *nons) char *workspace2, char *name, int type, char *wildname, int *nons, int *validate_counter)
{ {
unsigned char *salt, *p, *digest; unsigned char *salt, *p, *digest;
int digest_len, i, iterations, salt_len, base32_len, algo = 0; int digest_len, i, iterations, salt_len, base32_len, algo = 0;
@@ -1551,6 +1558,7 @@ static int prove_non_existence_nsec3(struct dns_header *header, size_t plen, uns
nsecs[i] = nsec3p; nsecs[i] = nsec3p;
} }
(*validate_counter)++;
if ((digest_len = hash_name(name, &digest, hash, salt, salt_len, iterations)) == 0) if ((digest_len = hash_name(name, &digest, hash, salt, salt_len, iterations)) == 0)
return DNSSEC_FAIL_NONSEC; return DNSSEC_FAIL_NONSEC;
@@ -1570,6 +1578,7 @@ static int prove_non_existence_nsec3(struct dns_header *header, size_t plen, uns
if (wildname && hostname_isequal(closest_encloser, wildname)) if (wildname && hostname_isequal(closest_encloser, wildname))
break; break;
(*validate_counter)++;
if ((digest_len = hash_name(closest_encloser, &digest, hash, salt, salt_len, iterations)) == 0) if ((digest_len = hash_name(closest_encloser, &digest, hash, salt, salt_len, iterations)) == 0)
return DNSSEC_FAIL_NONSEC; return DNSSEC_FAIL_NONSEC;
@@ -1598,6 +1607,7 @@ static int prove_non_existence_nsec3(struct dns_header *header, size_t plen, uns
return DNSSEC_FAIL_NONSEC; return DNSSEC_FAIL_NONSEC;
/* Look for NSEC3 that proves the non-existence of the next-closest encloser */ /* Look for NSEC3 that proves the non-existence of the next-closest encloser */
(*validate_counter)++;
if ((digest_len = hash_name(next_closest, &digest, hash, salt, salt_len, iterations)) == 0) if ((digest_len = hash_name(next_closest, &digest, hash, salt, salt_len, iterations)) == 0)
return DNSSEC_FAIL_NONSEC; return DNSSEC_FAIL_NONSEC;
@@ -1613,6 +1623,7 @@ static int prove_non_existence_nsec3(struct dns_header *header, size_t plen, uns
wildcard--; wildcard--;
*wildcard = '*'; *wildcard = '*';
(*validate_counter)++;
if ((digest_len = hash_name(wildcard, &digest, hash, salt, salt_len, iterations)) == 0) if ((digest_len = hash_name(wildcard, &digest, hash, salt, salt_len, iterations)) == 0)
return DNSSEC_FAIL_NONSEC; return DNSSEC_FAIL_NONSEC;
@@ -1624,7 +1635,8 @@ static int prove_non_existence_nsec3(struct dns_header *header, size_t plen, uns
} }
/* returns 0 on success, or DNSSEC_FAIL_* value on failure. */ /* returns 0 on success, or DNSSEC_FAIL_* value on failure. */
static int prove_non_existence(struct dns_header *header, size_t plen, char *keyname, char *name, int qtype, int qclass, char *wildname, int *nons, int *nsec_ttl) static int prove_non_existence(struct dns_header *header, size_t plen, char *keyname, char *name, int qtype, int qclass,
char *wildname, int *nons, int *nsec_ttl, int *validate_counter)
{ {
static unsigned char **nsecset = NULL, **rrsig_labels = NULL; static unsigned char **nsecset = NULL, **rrsig_labels = NULL;
static int nsecset_sz = 0, rrsig_labels_sz = 0; static int nsecset_sz = 0, rrsig_labels_sz = 0;
@@ -1743,7 +1755,7 @@ static int prove_non_existence(struct dns_header *header, size_t plen, char *key
if (type_found == T_NSEC) if (type_found == T_NSEC)
return prove_non_existence_nsec(header, plen, nsecset, rrsig_labels, nsecs_found, daemon->workspacename, keyname, name, qtype, nons); return prove_non_existence_nsec(header, plen, nsecset, rrsig_labels, nsecs_found, daemon->workspacename, keyname, name, qtype, nons);
else if (type_found == T_NSEC3) else if (type_found == T_NSEC3)
return prove_non_existence_nsec3(header, plen, nsecset, nsecs_found, daemon->workspacename, keyname, name, qtype, wildname, nons); return prove_non_existence_nsec3(header, plen, nsecset, nsecs_found, daemon->workspacename, keyname, name, qtype, wildname, nons, validate_counter);
else else
return DNSSEC_FAIL_NONSEC; return DNSSEC_FAIL_NONSEC;
} }
@@ -1850,7 +1862,7 @@ static int zone_status(char *name, int class, char *keyname, time_t now)
if the nons argument is non-NULL. if the nons argument is non-NULL.
*/ */
int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname,
int *class, int check_unsigned, int *neganswer, int *nons, int *nsec_ttl) int *class, int check_unsigned, int *neganswer, int *nons, int *nsec_ttl, int *validate_counter)
{ {
static unsigned char **targets = NULL; static unsigned char **targets = NULL;
static int target_sz = 0; static int target_sz = 0;
@@ -2025,7 +2037,7 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
{ {
unsigned long sig_ttl; unsigned long sig_ttl;
rc = validate_rrset(now, header, plen, class1, type1, sigcnt, rc = validate_rrset(now, header, plen, class1, type1, sigcnt,
rrcnt, name, keyname, &wildname, NULL, 0, 0, 0, &sig_ttl); rrcnt, name, keyname, &wildname, NULL, 0, 0, 0, &sig_ttl, validate_counter);
if (STAT_ISEQUAL(rc, STAT_BOGUS) || STAT_ISEQUAL(rc, STAT_NEED_KEY) || STAT_ISEQUAL(rc, STAT_NEED_DS) || STAT_ISEQUAL(rc, STAT_ABANDONED)) if (STAT_ISEQUAL(rc, STAT_BOGUS) || STAT_ISEQUAL(rc, STAT_NEED_KEY) || STAT_ISEQUAL(rc, STAT_NEED_DS) || STAT_ISEQUAL(rc, STAT_ABANDONED))
{ {
@@ -2061,7 +2073,7 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
That's not a problem since if the RRsets later fail That's not a problem since if the RRsets later fail
we'll return BOGUS then. */ we'll return BOGUS then. */
if (STAT_ISEQUAL(rc, STAT_SECURE_WILDCARD) && if (STAT_ISEQUAL(rc, STAT_SECURE_WILDCARD) &&
((rc_nsec = prove_non_existence(header, plen, keyname, name, type1, class1, wildname, NULL, NULL))) != 0) ((rc_nsec = prove_non_existence(header, plen, keyname, name, type1, class1, wildname, NULL, NULL, validate_counter))) != 0)
return STAT_BOGUS | rc_nsec; return STAT_BOGUS | rc_nsec;
rc = STAT_SECURE; rc = STAT_SECURE;
@@ -2087,7 +2099,7 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
/* For anything other than a DS record, this situation is OK if either /* For anything other than a DS record, this situation is OK if either
the answer is in an unsigned zone, or there's a NSEC records. */ the answer is in an unsigned zone, or there's a NSEC records. */
if ((rc_nsec = prove_non_existence(header, plen, keyname, name, qtype, qclass, NULL, nons, nsec_ttl)) != 0) if ((rc_nsec = prove_non_existence(header, plen, keyname, name, qtype, qclass, NULL, nons, nsec_ttl, validate_counter)) != 0)
{ {
/* Empty DS without NSECS */ /* Empty DS without NSECS */
if (qtype == T_DS) if (qtype == T_DS)

View File

@@ -16,6 +16,8 @@
#include "dnsmasq.h" #include "dnsmasq.h"
static int vchwm = 0; /* TODO */
static struct frec *get_new_frec(time_t now, struct server *serv, int force); static struct frec *get_new_frec(time_t now, struct server *serv, int force);
static struct frec *lookup_frec(unsigned short id, int fd, void *hash, int *firstp, int *lastp); static struct frec *lookup_frec(unsigned short id, int fd, void *hash, int *firstp, int *lastp);
static struct frec *lookup_frec_by_query(void *hash, unsigned int flags, unsigned int flagmask); static struct frec *lookup_frec_by_query(void *hash, unsigned int flags, unsigned int flagmask);
@@ -339,6 +341,7 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
forward->flags |= FREC_AD_QUESTION; forward->flags |= FREC_AD_QUESTION;
#ifdef HAVE_DNSSEC #ifdef HAVE_DNSSEC
forward->work_counter = DNSSEC_WORK; forward->work_counter = DNSSEC_WORK;
forward->validate_counter = 0;
if (do_bit) if (do_bit)
forward->flags |= FREC_DO_QUESTION; forward->flags |= FREC_DO_QUESTION;
#endif #endif
@@ -892,6 +895,8 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server
static void dnssec_validate(struct frec *forward, struct dns_header *header, static void dnssec_validate(struct frec *forward, struct dns_header *header,
ssize_t plen, int status, time_t now) ssize_t plen, int status, time_t now)
{ {
struct frec *orig;
daemon->log_display_id = forward->frec_src.log_id; daemon->log_display_id = forward->frec_src.log_id;
/* We've had a reply already, which we're validating. Ignore this duplicate */ /* We've had a reply already, which we're validating. Ignore this duplicate */
@@ -917,19 +922,22 @@ static void dnssec_validate(struct frec *forward, struct dns_header *header,
} }
} }
/* Find the original query that started it all.... */
for (orig = forward; orig->dependent; orig = orig->dependent);
/* As soon as anything returns BOGUS, we stop and unwind, to do otherwise /* As soon as anything returns BOGUS, we stop and unwind, to do otherwise
would invite infinite loops, since the answers to DNSKEY and DS queries would invite infinite loops, since the answers to DNSKEY and DS queries
will not be cached, so they'll be repeated. */ will not be cached, so they'll be repeated. */
if (!STAT_ISEQUAL(status, STAT_BOGUS) && !STAT_ISEQUAL(status, STAT_TRUNCATED) && !STAT_ISEQUAL(status, STAT_ABANDONED)) if (!STAT_ISEQUAL(status, STAT_BOGUS) && !STAT_ISEQUAL(status, STAT_TRUNCATED) && !STAT_ISEQUAL(status, STAT_ABANDONED))
{ {
if (forward->flags & FREC_DNSKEY_QUERY) if (forward->flags & FREC_DNSKEY_QUERY)
status = dnssec_validate_by_ds(now, header, plen, daemon->namebuff, daemon->keyname, forward->class); status = dnssec_validate_by_ds(now, header, plen, daemon->namebuff, daemon->keyname, forward->class, &orig->validate_counter);
else if (forward->flags & FREC_DS_QUERY) else if (forward->flags & FREC_DS_QUERY)
status = dnssec_validate_ds(now, header, plen, daemon->namebuff, daemon->keyname, forward->class); status = dnssec_validate_ds(now, header, plen, daemon->namebuff, daemon->keyname, forward->class, &orig->validate_counter);
else else
status = dnssec_validate_reply(now, header, plen, daemon->namebuff, daemon->keyname, &forward->class, status = dnssec_validate_reply(now, header, plen, daemon->namebuff, daemon->keyname, &forward->class,
!option_bool(OPT_DNSSEC_IGN_NS) && (forward->sentto->flags & SERV_DO_DNSSEC), !option_bool(OPT_DNSSEC_IGN_NS) && (forward->sentto->flags & SERV_DO_DNSSEC),
NULL, NULL, NULL); NULL, NULL, NULL, &orig->validate_counter);
if (STAT_ISEQUAL(status, STAT_ABANDONED)) if (STAT_ISEQUAL(status, STAT_ABANDONED))
{ {
@@ -986,15 +994,11 @@ static void dnssec_validate(struct frec *forward, struct dns_header *header,
else else
{ {
struct server *server; struct server *server;
struct frec *orig;
void *hash; void *hash;
size_t nn; size_t nn;
int serverind, fd; int serverind, fd;
struct randfd_list *rfds = NULL; struct randfd_list *rfds = NULL;
/* Find the original query that started it all.... */
for (orig = forward; orig->dependent; orig = orig->dependent);
/* Make sure we don't expire and free the orig frec during the /* Make sure we don't expire and free the orig frec during the
allocation of a new one: third arg of get_new_frec() does that. */ allocation of a new one: third arg of get_new_frec() does that. */
if ((serverind = dnssec_server(forward->sentto, daemon->keyname, NULL, NULL)) != -1 && if ((serverind = dnssec_server(forward->sentto, daemon->keyname, NULL, NULL)) != -1 &&
@@ -1347,6 +1351,11 @@ static void return_reply(time_t now, struct frec *forward, struct dns_header *he
log_query(F_SECSTAT, domain, &a, result, 0); log_query(F_SECSTAT, domain, &a, result, 0);
} }
} }
if (forward->validate_counter > vchwm)
vchwm = forward->validate_counter;
if (extract_request(header, n, daemon->namebuff, NULL))
my_syslog(LOG_INFO, "Validate_counter %s is %d, HWM is %d", daemon->namebuff, forward->validate_counter, vchwm); /* TODO */
#endif #endif
if (option_bool(OPT_NO_REBIND)) if (option_bool(OPT_NO_REBIND))
@@ -2028,7 +2037,7 @@ static ssize_t tcp_talk(int first, int last, int start, unsigned char *packet,
/* Recurse down the key hierarchy */ /* Recurse down the key hierarchy */
static int tcp_key_recurse(time_t now, int status, struct dns_header *header, size_t n, static int tcp_key_recurse(time_t now, int status, struct dns_header *header, size_t n,
int class, char *name, char *keyname, struct server *server, int class, char *name, char *keyname, struct server *server,
int have_mark, unsigned int mark, int *keycount) int have_mark, unsigned int mark, int *keycount, int *validatecount)
{ {
int first, last, start, new_status; int first, last, start, new_status;
unsigned char *packet = NULL; unsigned char *packet = NULL;
@@ -2043,13 +2052,13 @@ static int tcp_key_recurse(time_t now, int status, struct dns_header *header, si
if (--(*keycount) == 0) if (--(*keycount) == 0)
new_status = STAT_ABANDONED; new_status = STAT_ABANDONED;
else if (STAT_ISEQUAL(status, STAT_NEED_KEY)) else if (STAT_ISEQUAL(status, STAT_NEED_KEY))
new_status = dnssec_validate_by_ds(now, header, n, name, keyname, class); new_status = dnssec_validate_by_ds(now, header, n, name, keyname, class, validatecount);
else if (STAT_ISEQUAL(status, STAT_NEED_DS)) else if (STAT_ISEQUAL(status, STAT_NEED_DS))
new_status = dnssec_validate_ds(now, header, n, name, keyname, class); new_status = dnssec_validate_ds(now, header, n, name, keyname, class, validatecount);
else else
new_status = dnssec_validate_reply(now, header, n, name, keyname, &class, new_status = dnssec_validate_reply(now, header, n, name, keyname, &class,
!option_bool(OPT_DNSSEC_IGN_NS) && (server->flags & SERV_DO_DNSSEC), !option_bool(OPT_DNSSEC_IGN_NS) && (server->flags & SERV_DO_DNSSEC),
NULL, NULL, NULL); NULL, NULL, NULL, validatecount);
if (STAT_ISEQUAL(new_status, STAT_ABANDONED)) if (STAT_ISEQUAL(new_status, STAT_ABANDONED))
{ {
@@ -2093,7 +2102,8 @@ static int tcp_key_recurse(time_t now, int status, struct dns_header *header, si
log_query_mysockaddr(F_NOEXTRA | F_DNSSEC | F_SERVER, keyname, &server->addr, log_query_mysockaddr(F_NOEXTRA | F_DNSSEC | F_SERVER, keyname, &server->addr,
STAT_ISEQUAL(new_status, STAT_NEED_KEY) ? "dnssec-query[DNSKEY]" : "dnssec-query[DS]", 0); STAT_ISEQUAL(new_status, STAT_NEED_KEY) ? "dnssec-query[DNSKEY]" : "dnssec-query[DS]", 0);
new_status = tcp_key_recurse(now, new_status, new_header, m, class, name, keyname, server, have_mark, mark, keycount); new_status = tcp_key_recurse(now, new_status, new_header, m, class, name, keyname, server,
have_mark, mark, keycount, validatecount);
daemon->log_display_id = log_save; daemon->log_display_id = log_save;
@@ -2399,8 +2409,9 @@ unsigned char *tcp_request(int confd, time_t now,
if (option_bool(OPT_DNSSEC_VALID) && !checking_disabled && (master->flags & SERV_DO_DNSSEC)) if (option_bool(OPT_DNSSEC_VALID) && !checking_disabled && (master->flags & SERV_DO_DNSSEC))
{ {
int keycount = DNSSEC_WORK; /* Limit to number of DNSSEC questions, to catch loops and avoid filling cache. */ int keycount = DNSSEC_WORK; /* Limit to number of DNSSEC questions, to catch loops and avoid filling cache. */
int validatecount = 0; /* How many validations we did */
int status = tcp_key_recurse(now, STAT_OK, header, m, 0, daemon->namebuff, daemon->keyname, int status = tcp_key_recurse(now, STAT_OK, header, m, 0, daemon->namebuff, daemon->keyname,
serv, have_mark, mark, &keycount); serv, have_mark, mark, &keycount, &validatecount);
char *result, *domain = "result"; char *result, *domain = "result";
union all_addr a; union all_addr a;
@@ -2426,6 +2437,11 @@ unsigned char *tcp_request(int confd, time_t now,
} }
log_query(F_SECSTAT, domain, &a, result, 0); log_query(F_SECSTAT, domain, &a, result, 0);
if (validatecount > vchwm)
vchwm = validatecount;
if (extract_request(header, m, daemon->namebuff, NULL))
my_syslog(LOG_INFO, "Validate_counter %s is %d, HWM is %d", daemon->namebuff, validatecount, vchwm); /* TODO */
} }
#endif #endif