2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-09-01 15:05:23 +00:00

1887. [func] Detect duplicates of UDP queries we are recursing on

and drop them.  New stats category "duplicates".
                        [RT #14892]
This commit is contained in:
Mark Andrews
2005-06-17 01:58:23 +00:00
parent 83a56f1e4f
commit 9b80f3a7c7
8 changed files with 124 additions and 35 deletions

View File

@@ -1,3 +1,7 @@
1887. [func] Detect duplicates of UDP queries we are recursing on
and drop them. New stats category "duplicates".
[RT #14892]
1886. [bug] Fix unreasonably low quantum on call to 1886. [bug] Fix unreasonably low quantum on call to
dns_rbt_destroy2(). Remove unnecessay unhash_node() dns_rbt_destroy2(). Remove unnecessay unhash_node()
call. [RT #14919] call. [RT #14919]

View File

@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE. * PERFORMANCE OF THIS SOFTWARE.
*/ */
/* $Id: query.c,v 1.266 2005/05/16 05:33:42 marka Exp $ */ /* $Id: query.c,v 1.267 2005/06/17 01:58:21 marka Exp $ */
/*! \file */ /*! \file */
@@ -161,7 +161,10 @@ query_error(ns_client_t *client, isc_result_t result) {
static void static void
query_next(ns_client_t *client, isc_result_t result) { query_next(ns_client_t *client, isc_result_t result) {
inc_stats(client, dns_statscounter_failure); if (result == DNS_R_DUPLICATE)
inc_stats(client, dns_statscounter_duplicate);
else
inc_stats(client, dns_statscounter_failure);
ns_client_next(client, result); ns_client_next(client, result);
} }
@@ -2681,6 +2684,7 @@ query_recurse(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qdomain,
{ {
isc_result_t result; isc_result_t result;
dns_rdataset_t *rdataset, *sigrdataset; dns_rdataset_t *rdataset, *sigrdataset;
isc_sockaddr_t *peeraddr;
inc_stats(client, dns_statscounter_recursion); inc_stats(client, dns_statscounter_recursion);
@@ -2744,14 +2748,19 @@ query_recurse(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qdomain,
if (client->query.timerset == ISC_FALSE) if (client->query.timerset == ISC_FALSE)
ns_client_settimeout(client, 60); ns_client_settimeout(client, 60);
result = dns_resolver_createfetch(client->view->resolver, if ((client->attributes & NS_CLIENTATTR_TCP) == 0)
client->query.qname, peeraddr = &client->peeraddr;
qtype, qdomain, nameservers, else
NULL, client->query.fetchoptions, peeraddr = NULL;
client->task, result = dns_resolver_createfetch2(client->view->resolver,
query_resume, client, client->query.qname,
rdataset, sigrdataset, qtype, qdomain, nameservers,
&client->query.fetch); NULL, peeraddr, client->message->id,
client->query.fetchoptions,
client->task,
query_resume, client,
rdataset, sigrdataset,
&client->query.fetch);
if (result == ISC_R_SUCCESS) { if (result == ISC_R_SUCCESS) {
/* /*
@@ -3219,7 +3228,10 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
if (result == ISC_R_SUCCESS) if (result == ISC_R_SUCCESS)
client->query.attributes |= client->query.attributes |=
NS_QUERYATTR_RECURSING; NS_QUERYATTR_RECURSING;
else { else if (result == DNS_R_DUPLICATE) {
/* Duplicate query. */
QUERY_ERROR(result);
} else {
/* Unable to recurse. */ /* Unable to recurse. */
QUERY_ERROR(DNS_R_SERVFAIL); QUERY_ERROR(DNS_R_SERVFAIL);
} }
@@ -3389,6 +3401,8 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
if (result == ISC_R_SUCCESS) if (result == ISC_R_SUCCESS)
client->query.attributes |= client->query.attributes |=
NS_QUERYATTR_RECURSING; NS_QUERYATTR_RECURSING;
else if (result == DNS_R_DUPLICATE)
QUERY_ERROR(result);
else else
QUERY_ERROR(DNS_R_SERVFAIL); QUERY_ERROR(DNS_R_SERVFAIL);
} else { } else {
@@ -3930,13 +3944,22 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
if (eresult != ISC_R_SUCCESS && if (eresult != ISC_R_SUCCESS &&
(!PARTIALANSWER(client) || WANTRECURSION(client))) { (!PARTIALANSWER(client) || WANTRECURSION(client))) {
/* if (eresult == DNS_R_DUPLICATE) {
* If we don't have any answer to give the client, /*
* or if the client requested recursion and thus wanted * This was a duplicate query that we are
* the complete answer, send an error response. * recursing on. Don't send a response now.
*/ * The original query will still cause a response.
query_error(client, eresult); */
ns_client_detach(&client); query_next(client, eresult);
} else {
/*
* If we don't have any answer to give the client,
* or if the client requested recursion and thus wanted
* the complete answer, send an error response.
*/
query_error(client, eresult);
}
ns_client_detach(&client);
} else if (!RECURSING(client)) { } else if (!RECURSING(client)) {
/* /*
* We are done. Set up sortlist data for the message * We are done. Set up sortlist data for the message

View File

@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE. * PERFORMANCE OF THIS SOFTWARE.
*/ */
/* $Id: resolver.h,v 1.45 2005/06/07 00:16:01 marka Exp $ */ /* $Id: resolver.h,v 1.46 2005/06/17 01:58:23 marka Exp $ */
#ifndef DNS_RESOLVER_H #ifndef DNS_RESOLVER_H
#define DNS_RESOLVER_H 1 #define DNS_RESOLVER_H 1
@@ -65,9 +65,9 @@ ISC_LANG_BEGINDECLS
* 'node', 'rdataset', and 'sigrdataset' may be bound. It is the * 'node', 'rdataset', and 'sigrdataset' may be bound. It is the
* receiver's responsibility to detach before freeing the event. * receiver's responsibility to detach before freeing the event.
* \brief * \brief
* 'rdataset' and 'sigrdataset' are the values that were supplied when * 'rdataset', 'sigrdataset', 'client' and 'id' are the values that were
* dns_resolver_createfetch() was called. They are returned to the * supplied when dns_resolver_createfetch() was called. They are returned
* caller so that they may be freed. * to the caller so that they may be freed.
*/ */
typedef struct dns_fetchevent { typedef struct dns_fetchevent {
ISC_EVENT_COMMON(struct dns_fetchevent); ISC_EVENT_COMMON(struct dns_fetchevent);
@@ -79,6 +79,8 @@ typedef struct dns_fetchevent {
dns_rdataset_t * rdataset; dns_rdataset_t * rdataset;
dns_rdataset_t * sigrdataset; dns_rdataset_t * sigrdataset;
dns_fixedname_t foundname; dns_fixedname_t foundname;
isc_sockaddr_t * client;
dns_messageid_t id;
} dns_fetchevent_t; } dns_fetchevent_t;
/* /*
@@ -240,6 +242,18 @@ dns_resolver_createfetch(dns_resolver_t *res, dns_name_t *name,
dns_rdataset_t *rdataset, dns_rdataset_t *rdataset,
dns_rdataset_t *sigrdataset, dns_rdataset_t *sigrdataset,
dns_fetch_t **fetchp); dns_fetch_t **fetchp);
isc_result_t
dns_resolver_createfetch2(dns_resolver_t *res, dns_name_t *name,
dns_rdatatype_t type,
dns_name_t *domain, dns_rdataset_t *nameservers,
dns_forwarders_t *forwarders,
isc_sockaddr_t *client, isc_uint16_t id,
unsigned int options, isc_task_t *task,
isc_taskaction_t action, void *arg,
dns_rdataset_t *rdataset,
dns_rdataset_t *sigrdataset,
dns_fetch_t **fetchp);
/*%< /*%<
* Recurse to answer a question. * Recurse to answer a question.
* *
@@ -262,6 +276,10 @@ dns_resolver_createfetch(dns_resolver_t *res, dns_name_t *name,
*\li The values of 'rdataset' and 'sigrdataset' will be returned in *\li The values of 'rdataset' and 'sigrdataset' will be returned in
* the FETCHDONE event. * the FETCHDONE event.
* *
*\li 'client' and 'id' are used for duplicate query detection. '*client'
* must remain stable until after 'action' has been called or
* dns_resolver_cancelfetch() is called.
*
* Requires: * Requires:
* *
*\li 'res' is a valid resolver that has been frozen. *\li 'res' is a valid resolver that has been frozen.
@@ -277,6 +295,8 @@ dns_resolver_createfetch(dns_resolver_t *res, dns_name_t *name,
* *
*\li 'forwarders' is NULL. *\li 'forwarders' is NULL.
* *
*\li 'client' is a valid sockaddr or NULL.
*
*\li 'options' contains valid options. *\li 'options' contains valid options.
* *
*\li 'rdataset' is a valid, disassociated rdataset. *\li 'rdataset' is a valid, disassociated rdataset.
@@ -288,6 +308,7 @@ dns_resolver_createfetch(dns_resolver_t *res, dns_name_t *name,
* Returns: * Returns:
* *
*\li #ISC_R_SUCCESS Success *\li #ISC_R_SUCCESS Success
*\li #DNS_R_DUPLICATE
* *
*\li Many other values are possible, all of which indicate failure. *\li Many other values are possible, all of which indicate failure.
*/ */

View File

@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE. * PERFORMANCE OF THIS SOFTWARE.
*/ */
/* $Id: result.h,v 1.109 2005/05/19 04:59:04 marka Exp $ */ /* $Id: result.h,v 1.110 2005/06/17 01:58:23 marka Exp $ */
#ifndef DNS_RESULT_H #ifndef DNS_RESULT_H
#define DNS_RESULT_H 1 #define DNS_RESULT_H 1
@@ -146,8 +146,9 @@
#define DNS_R_MUSTBESECURE (ISC_RESULTCLASS_DNS + 100) #define DNS_R_MUSTBESECURE (ISC_RESULTCLASS_DNS + 100)
#define DNS_R_COVERINGNSEC (ISC_RESULTCLASS_DNS + 101) #define DNS_R_COVERINGNSEC (ISC_RESULTCLASS_DNS + 101)
#define DNS_R_MXISADDRESS (ISC_RESULTCLASS_DNS + 102) #define DNS_R_MXISADDRESS (ISC_RESULTCLASS_DNS + 102)
#define DNS_R_DUPLICATE (ISC_RESULTCLASS_DNS + 103)
#define DNS_R_NRESULTS 103 /*%< Number of results */ #define DNS_R_NRESULTS 104 /*%< Number of results */
/* /*
* DNS wire format rcodes. * DNS wire format rcodes.

View File

@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE. * PERFORMANCE OF THIS SOFTWARE.
*/ */
/* $Id: stats.h,v 1.7 2005/04/29 00:23:04 marka Exp $ */ /* $Id: stats.h,v 1.8 2005/06/17 01:58:23 marka Exp $ */
#ifndef DNS_STATS_H #ifndef DNS_STATS_H
#define DNS_STATS_H 1 #define DNS_STATS_H 1
@@ -33,10 +33,11 @@ typedef enum {
dns_statscounter_nxrrset = 2, /*%< NXRRSET result */ dns_statscounter_nxrrset = 2, /*%< NXRRSET result */
dns_statscounter_nxdomain = 3, /*%< NXDOMAIN result */ dns_statscounter_nxdomain = 3, /*%< NXDOMAIN result */
dns_statscounter_recursion = 4, /*%< Recursion was used */ dns_statscounter_recursion = 4, /*%< Recursion was used */
dns_statscounter_failure = 5 /*%< Some other failure */ dns_statscounter_failure = 5, /*%< Some other failure */
dns_statscounter_duplicate = 6 /*%< Duplicate query */
} dns_statscounter_t; } dns_statscounter_t;
#define DNS_STATS_NCOUNTERS 6 #define DNS_STATS_NCOUNTERS 7
LIBDNS_EXTERNAL_DATA extern const char *dns_statscounter_names[]; LIBDNS_EXTERNAL_DATA extern const char *dns_statscounter_names[];

View File

@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE. * PERFORMANCE OF THIS SOFTWARE.
*/ */
/* $Id: resolver.c,v 1.310 2005/06/07 00:27:33 marka Exp $ */ /* $Id: resolver.c,v 1.311 2005/06/17 01:58:22 marka Exp $ */
/*! \file */ /*! \file */
@@ -2633,8 +2633,9 @@ fctx_start(isc_task_t *task, isc_event_t *event) {
*/ */
static inline isc_result_t static inline isc_result_t
fctx_join(fetchctx_t *fctx, isc_task_t *task, isc_taskaction_t action, fctx_join(fetchctx_t *fctx, isc_task_t *task, isc_sockaddr_t *client,
void *arg, dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset, dns_messageid_t id, isc_taskaction_t action, void *arg,
dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
dns_fetch_t *fetch) dns_fetch_t *fetch)
{ {
isc_task_t *clone; isc_task_t *clone;
@@ -2664,6 +2665,8 @@ fctx_join(fetchctx_t *fctx, isc_task_t *task, isc_taskaction_t action,
event->rdataset = rdataset; event->rdataset = rdataset;
event->sigrdataset = sigrdataset; event->sigrdataset = sigrdataset;
event->fetch = fetch; event->fetch = fetch;
event->client = client;
event->id = id;
dns_fixedname_init(&event->foundname); dns_fixedname_init(&event->foundname);
/* /*
@@ -6156,6 +6159,24 @@ dns_resolver_createfetch(dns_resolver_t *res, dns_name_t *name,
dns_rdataset_t *rdataset, dns_rdataset_t *rdataset,
dns_rdataset_t *sigrdataset, dns_rdataset_t *sigrdataset,
dns_fetch_t **fetchp) dns_fetch_t **fetchp)
{
return (dns_resolver_createfetch2(res, name, type, domain,
nameservers, forwarders, NULL, 0,
options, task, action, arg,
rdataset, sigrdataset, fetchp));
}
isc_result_t
dns_resolver_createfetch2(dns_resolver_t *res, dns_name_t *name,
dns_rdatatype_t type,
dns_name_t *domain, dns_rdataset_t *nameservers,
dns_forwarders_t *forwarders,
isc_sockaddr_t *client, dns_messageid_t id,
unsigned int options, isc_task_t *task,
isc_taskaction_t action, void *arg,
dns_rdataset_t *rdataset,
dns_rdataset_t *sigrdataset,
dns_fetch_t **fetchp)
{ {
dns_fetch_t *fetch; dns_fetch_t *fetch;
fetchctx_t *fctx = NULL; fetchctx_t *fctx = NULL;
@@ -6206,6 +6227,22 @@ dns_resolver_createfetch(dns_resolver_t *res, dns_name_t *name,
break; break;
} }
} }
/*
* Is this a duplicate?
*/
if (fctx != NULL && client != NULL) {
dns_fetchevent_t *fevent;
for (fevent = ISC_LIST_HEAD(fctx->events);
fevent != NULL;
fevent = ISC_LIST_NEXT(fevent, ev_link)) {
if (fevent->client != NULL && fevent->id == id &&
isc_sockaddr_equal(fevent->client, client)) {
result = DNS_R_DUPLICATE;
goto unlock;
}
}
}
/* /*
* If we didn't have a fetch, would attach to a done fetch, this * If we didn't have a fetch, would attach to a done fetch, this
@@ -6225,7 +6262,7 @@ dns_resolver_createfetch(dns_resolver_t *res, dns_name_t *name,
new_fctx = ISC_TRUE; new_fctx = ISC_TRUE;
} }
result = fctx_join(fctx, task, action, arg, result = fctx_join(fctx, task, client, id, action, arg,
rdataset, sigrdataset, fetch); rdataset, sigrdataset, fetch);
if (new_fctx) { if (new_fctx) {
if (result == ISC_R_SUCCESS) { if (result == ISC_R_SUCCESS) {

View File

@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE. * PERFORMANCE OF THIS SOFTWARE.
*/ */
/* $Id: result.c,v 1.120 2005/05/19 04:59:03 marka Exp $ */ /* $Id: result.c,v 1.121 2005/06/17 01:58:22 marka Exp $ */
/*! \file */ /*! \file */
@@ -154,7 +154,8 @@ static const char *text[DNS_R_NRESULTS] = {
"must-be-secure", /*%< 100 DNS_R_MUSTBESECURE */ "must-be-secure", /*%< 100 DNS_R_MUSTBESECURE */
"covering NSEC record returned", /*%< 101 DNS_R_COVERINGNSEC */ "covering NSEC record returned", /*%< 101 DNS_R_COVERINGNSEC */
"MX is an address" /*%< 102 DNS_R_MXISADDRESS */ "MX is an address", /*%< 102 DNS_R_MXISADDRESS */
"duplicate query" /*%< 103 DNS_R_DUPLICATE */
}; };
static const char *rcode_text[DNS_R_NRCODERESULTS] = { static const char *rcode_text[DNS_R_NRCODERESULTS] = {

View File

@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE. * PERFORMANCE OF THIS SOFTWARE.
*/ */
/* $Id: stats.c,v 1.8 2005/04/29 00:22:52 marka Exp $ */ /* $Id: stats.c,v 1.9 2005/06/17 01:58:22 marka Exp $ */
/*! \file */ /*! \file */
@@ -32,7 +32,8 @@ LIBDNS_EXTERNAL_DATA const char *dns_statscounter_names[DNS_STATS_NCOUNTERS] =
"nxrrset", "nxrrset",
"nxdomain", "nxdomain",
"recursion", "recursion",
"failure" "failure",
"duplicate"
}; };
isc_result_t isc_result_t