mirror of
https://github.com/pi-hole/dnsmasq.git
synced 2025-12-19 10:18:25 +00:00
Measure cryptographic work done by DNSSEC.
This commit is contained in:
@@ -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);
|
||||||
|
|||||||
42
src/dnssec.c
42
src/dnssec.c
@@ -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)
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user