query.c revision f988b6764d2289711ed372fb6b3584a671bfd983
/*
* Copyright (C) 1999 Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
* ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
* CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
*/
#include <config.h>
#include <isc/assertions.h>
#include <dns/dispatch.h>
#include <dns/rdataset.h>
#include <dns/rdatasetiter.h>
static inline void
}
}
}
static void
(void)result;
}
void
}
static inline isc_result_t
if (result != ISC_R_SUCCESS)
return (result);
return (ISC_R_SUCCESS);
}
static inline isc_dynbuffer_t *
isc_region_t r;
if (result != ISC_R_SUCCESS)
return (NULL);
}
if (r.length < 255) {
if (result != ISC_R_SUCCESS)
return (NULL);
}
return (dbuf);
}
return (query_newnamebuf(client));
}
static isc_result_t
isc_region_t r;
isc_buffer_t b;
/* XXXRTH Other requirements. */
/*
* XXXRTH Should special case 'A' type. If type is 'A', we should
* look for A6 and AAAA too.
*/
/*
* Get the resources we'll need.
*/
return (ISC_R_NOMEMORY);
if (result != ISC_R_SUCCESS)
return (result);
dns_name_setbuffer(fname, &b);
&rdataset);
if (result != ISC_R_SUCCESS)
return (result);
/*
* Find a database to answer the query.
*/
return (ISC_R_SUCCESS);
/*
* Now look for an answer in the database.
*/
switch (result) {
case DNS_R_SUCCESS:
case DNS_R_GLUE:
dns_db_detach(&db);
break;
case DNS_R_NXRDATASET:
case DNS_R_ZONECUT:
dns_db_detach(&db);
return (ISC_R_SUCCESS);
case DNS_R_CNAME:
case DNS_R_DNAME:
case DNS_R_DELEGATION:
dns_db_detach(&db);
return (ISC_R_SUCCESS);
default:
dns_db_detach(&db);
return (ISC_R_SUCCESS);
}
/*
* Record the space we consumed from the namebuf.
*/
dns_name_toregion(fname, &r);
/*
* This is not strictly necessary, but is done to emphasize
* that the name's dedicated buffer, which is on our stack,
* is no longer used. It also prevents any later accidental
* use of the dedicated buffer.
*/
/*
* Suppress duplicates.
*/
for (section = DNS_SECTION_ANSWER;
section++) {
if (result == ISC_R_SUCCESS) {
/*
* We've already got this RRset in the response.
*/
return (ISC_R_SUCCESS);
}
}
/*
* In a few cases, we want to add additional data for additional
* data. It's simpler to just deal with special cases here than
* to try to create a general purpose mechanism and allow the
* rdata implementations to do it themselves.
*
* This involves recursion, but the depth is limited. The
* most complex case is adding a SRV rdataset, which involves
* recursing to add address records, which in turn can cause
* recursion to add KEYs.
*/
type == dns_rdatatype_a6) {
/*
* RFC 2535 section 3.5 says that when A or AAAA records are
* retrieved as additional data, any KEY RRs for the owner name
* should be added to the additional data section. We include
* A6 in the list of types with such treatment.
*
* XXXRTH We should lower the priority here. Alternatively,
* we could raise the priority of glue records.
*/
} else if (type == dns_rdatatype_srv) {
/*
* If we're adding SRV records to the additional data
* section, it's helpful if we add the SRV additional data
* as well.
*/
return (dns_rdataset_additionaldata(rdataset,
client));
}
return (ISC_R_SUCCESS);
}
static inline void
{
/*
* We don't care if dns_rdataset_additionaldata() fails.
*/
client);
/*
* RFC 2535 section 3.5 says that when NS, SOA, A, or AAAA records
* are retrieved, any KEY RRs for the owner name should be added
* to the additional data section. We include A6 in the list of
* types with such treatment.
*
* We don't care if query_additional() fails.
*/
type == dns_rdatatype_a6) {
/*
* XXXRTH We should lower the priority here. Alternatively,
* we could raise the priority of glue records.
*/
}
}
static isc_result_t
unsigned int section;
isc_region_t r;
isc_buffer_t b;
unsigned int cname_hops;
unsigned int dname_hops;
/*
* One-time initialization.
*/
cname_hops = 0;
dname_hops = 0;
/*
* Find answers to questions.
*/
do {
/*
* Per iteration initialization.
*/
/*
* Get the resources we'll need.
*/
if (first_time)
return (DNS_R_SERVFAIL);
else
return (ISC_R_SUCCESS);
}
if (result != ISC_R_SUCCESS) {
if (first_time)
return (result);
else
return (ISC_R_SUCCESS);
}
dns_name_setbuffer(fname, &b);
&rdataset);
if (result != ISC_R_SUCCESS) {
if (first_time)
return (result);
else
return (ISC_R_SUCCESS);
}
/*
* XXXRTH Problem areas.
*
* If we're authoritative for both a parent and a child, the
* child is non-secure, and we are asked for the KEY of the
* nonsecure child, we need to get it from the parent.
* If we're not auth for the parent, then we have to go
* looking for it in the cache. How do we even know who
* the parent is? We probably won't find this KEY when doing
* additional data KEY retrievals, but that's probably OK,
* since it's a SHOULD not a MUST. We don't want to be doing
* tons of work just to fill out additional data.
*
* Similar problems occur with NXT queries, since there can
* be NXT records at a delegation point in both the parent
* and the child. RFC 2535 section 5.5 says that on explicit
* query we should return both, if available. That seems
* to imply we shouldn't recurse to get the missing one
* if only one is available. Is that right?
*/
/*
* Find a database to answer the query.
*/
&db);
if (first_time)
return (DNS_R_SERVFAIL);
else
return (ISC_R_SUCCESS);
}
/*
* Now look for an answer in the database.
*/
if (dns_db_iszone(db))
switch (result) {
case DNS_R_SUCCESS:
case DNS_R_DNAME:
break;
case DNS_R_CNAME:
cname_hops++;
&tname);
if (result != ISC_R_SUCCESS)
goto cleanup_rdataset;
if (result != ISC_R_SUCCESS)
goto cleanup_rdataset;
dns_name_fromregion(tname, &r);
break;
case DNS_R_GLUE:
case DNS_R_ZONECUT:
case DNS_R_DELEGATION:
break;
case DNS_R_NXRDATASET:
goto cleanup_node;
case DNS_R_NXDOMAIN:
if (first_time)
goto cleanup_db;
default:
goto cleanup_db;
}
/*
* Record the space we consumed from the namebuf.
*/
dns_name_toregion(fname, &r);
/*
* This is not strictly necessary, but is done to emphasize
* that the name's dedicated buffer, which is on our stack,
* is no longer used. It also prevents any later accidental
* use of the dedicated buffer.
*/
if (result == DNS_R_DELEGATION) {
/*
* XXXRTH This is where we'll set up a resolver
* fetch if recursion is allowed. We'll need
* to handle the glue case too.
* Also, we'll probably need to split find()
* up into a series of event callbacks.
*/
/*
* The following is the "no recursion" case.
*/
/*
* We don't have to set DNS_DBFIND_VALIDDATEGLUE
* because since we'll be processing the NS records
* we know the glue is good.
*/
} else if (type == dns_rdatatype_any) {
/*
* XXXRTH Need to handle zonecuts with special case
* code.
*/
&rdsiter);
if (result == ISC_R_SUCCESS)
while (result == ISC_R_SUCCESS) {
&rdataset);
if (result == ISC_R_SUCCESS) {
}
}
if (result != DNS_R_NOMORE) {
goto cleanup_node;
}
} else {
}
if (!auth && first_time)
dns_db_detach(&db);
return (ISC_R_SUCCESS);
dns_db_detach(&db);
return (result);
}
void
/*
* Ensure that appropriate cleanups occur.
*/
/*
* XXXRTH Deal with allow-query and allow-recursion here. Also,
* If the view doesn't have a cache or a resolver, then
* NS_QUERYATTR_RECURSIONOK and NS_QUERYATTR_CACHEOK should
* be turned off.
*/
if (result != ISC_R_SUCCESS) {
return;
}
/*
* Assume authoritative response until it is known to be
* otherwise.
*/
/*
* If the client doesn't want recursion, turn it off.
*/
/*
* Get the question name.
*/
if (result != ISC_R_SUCCESS) {
return;
}
if (result != ISC_R_NOMORE) {
if (result == ISC_R_SUCCESS) {
/*
* There's more than one QNAME in the question
* section.
*/
} else
return;
}
/*
*
*/
if (result != ISC_R_SUCCESS) {
return;
}
}
}