query.c revision b0d415629b9e1bcedfd09ee597414df0a5dee9d4
* client->query.qname was dynamically allocated. * Reset the query state of a client to its default state. * Cancel the fetch if it's running. * Cleanup any active versions. * Clean up free versions. * If we're not freeing everything, we keep the first three * dbversions structures around. * Allocate a name buffer. * Return a name buffer with space for a maximal name, allocating * a new one if necessary. * 'name' is using space in 'dbuf', but 'dbuf' has not yet been * adjusted to take account of that. We do the adjustment. * 'name' is no longer needed. Return it to our pool of temporary * names. If it is using a name buffer, relinquish its exclusive for (i = 0; i < n; i++) {
* We only return ISC_R_NOMEMORY if we couldn't * We may already have done a query related to this * database. If so, we must be sure to make subsequent * queries from the same version. * This is a new zone for this query. Add it to * Find a database to answer the query. * Get the current version of this database. * Now look for an answer in the database. * Either the answer is in the cache, or we * We don't have the data in the cache. If we've got * glue from the zone, use it. * We don't know the answer. * We found an answer, but the cache may be better. * Remember what we've got and go look in the cache. * Otherwise, the glue is the best answer. * We've already got this RRset in the response. * The name exists, but the rdataset does not. * If the dns_name_t we're lookup up is already in the message, * we don't want to trigger the caller's name replacement logic. /* XXXRTH Other requirements. */ * Find a database to answer the query. * Get the current version of this database. * Now look for an answer in the database. * Either the answer is in the cache, or we * don't know it. Go look in the cache. * We don't know the answer. * We don't have the data in the cache. If we've * got glue from the zone, use it. * We don't know the answer. * XXXRTH Explain NXGLUE here. * We found an answer, but the cache may be * better. Remember what we've got and go look in * Note: we only add SIGs if we've added the type they cover, * so we do not need to check if the SIG rdataset is already * We treat type A additional section processing as if it * were "any address type" additional section processing. * We now go looking for A6 and AAAA records, along with * XXXRTH This code could be more efficient. * The cache doesn't have an A6, but we may have * one in the zone's glue. * The cache doesn't have an AAAA, but we may have * one in the zone's glue. * If we haven't added anything, then we're done. * We may have added our rdatasets to an existing name, if so, then * need_addname will be ISC_FALSE. Whether we used an existing name * or a new one, we must set fname to NULL to prevent cleanup. * 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 * 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. Note: we * do NOT include A6 in the list of types with such treatment * in additional data because we'd have to do it for each A6 * XXXRTH We should lower the priority here. Alternatively, * we could raise the priority of glue records. * If we're adding SRV records to the additional data * section, it's helpful if we add the SRV additional data * If we added an A6 rdataset, we should also add everything we * know about the A6 chains. We wait until now to do this so that * they'll come after any additional data added above. * Add an rrset to the additional data section. * Note: we only add SIGs if we've added the type they cover, so * we do not need to check if the SIG rdataset is already in the * In spite of RFC 2535 section 3.5, we don't currently try to add * KEY RRs for the A6 records. It's just too much work. * We don't care if dns_a6_foreach or dns_rdataset_additionaldata() * 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 treat A6 records the same way. * We don't care if query_additional() fails. * XXXRTH We should lower the priority here. Alternatively, * we could raise the priority of glue records. * We've already got an RRset of the given name and type. * There's nothing else to do; * The name doesn't exist. * Note: we only add SIGs if we've added the type they cover, so * we do not need to check if the SIG rdataset is already in the * We have a signature. Add it to the response. * Get resources and make 'name' be the database origin. * This is bad. We tried to get the SOA RR at the zone top * Get resources and make 'name' be the database origin. * This is bad. We tried to get the NS rdataset at the zone * top and it didn't work! * We assume the name data referred to by qname and tname won't * Find the right database. * We're not directly authoritative for this query name, nor * is it a subdomain of any zone for which we're * We'll need some resources... * Now look for the zonecut. * We found a zonecut in the cache, but our * zone delegation is better. * We didn't find anything in the cache, but we * have a zone delegation, so use it. * We've already done query_keepname() on * zfname, so we must set dbuf to NULL to * prevent query_addrrset() from trying to * call query_keepname() again. * XXXRTH OPT still needs to be added. * Should get help with this from rdata.c * Resume a query after recursion. * This is the fetch we've been waiting for. * This is a fetch completion event for a cancelled fetch. * Clean up and don't resume the find. * XXXRTH If this client is shutting down, or this transaction * has timed out, do not resume the find. * We should probably have a "unwait" function that * decrements waiting and tells us whether we should continue, * do nothing, or reset the client (resetting would cause the * client to continue with shutdown if it was in shutdown * Record that we're waiting for an event. A client which * is shutting down will not be destroyed until all the * events have been received. * One-time initialization. * It's especially important to initialize anything that the cleanup * We're returning from recursion. Restore the query context * We'll need some resources... * First we must find the right database. * We're not directly authoritative for this query name, nor * is it a subdomain of any zone for which we're * If we can't use the cache, either because we * don't have one or because its use has been * disallowed, there's no more progress we can make * Get the current version of this database. * Find the first unanswered type in the question section. * We had better have found something! * If there's more than one question, we'll eventually retrieve the * node and iterate it, trying to find answers. For now, we simply * refuse requests with more than one question. * If it's a SIG query, we'll iterate the node. * We'll need some resources... * Now look for an answer in the database. * This case is handled in the main line below. * These cases are handled in the main line below. * The cache doesn't even have the root NS. Get them from * We can't even find the hints for the root * XXXRTH We should trigger root server priming here. * We're authoritative for an ancestor of QNAME. * We don't have a cache, so this is the best * We enable the retrieval of glue for this * database by setting client->query.gluedb. * We might have a better answer or delegation * in the cache. We'll remember the current * values of fname, rdataset, and sigrdataset. * We'll then go looking for QNAME in the * cache. If we find something better, we'll * We've already got a delegation from * authoritative data, and it is better * than what we found in the cache. Use * it instead of the cache delegation. * We've already done query_keepname() on * zfname, so we must set dbuf to NULL to * prevent query_addrrset() from trying to * call query_keepname() again. * We don't clean up zdb here because we * may still need it. It will get cleaned * up by the main cleanup code. * This is the best answer. * If we've got a NXT record, we need to save the * name now because we're going call query_addsoa() * below, and it needs to use the name buffer. * We don't want the cleanup code to try to release * fname if we fail below, so we set it to NULL. * We're not going to use fname, and need to release * our hold on the name buffer so query_addsoa() * Add NXT record if we found one. * We hit a dead end following a CNAME or DNAME. * If we've got a NXT record, we need to save the * name now because we're going call query_addsoa() * below, and it needs to use the name buffer. * We don't want the cleanup code to try to release * fname if we fail below, so we set it to NULL. * We're not going to use fname, and need to release * our hold on the name buffer so query_addsoa() * Add NXT record if we found one. * Set message rcode, if required. * We don't call query_addrrset() because we don't need any * of its extra features (and things would probably break!). * Keep a copy of the rdataset. We have to do this because * query_addrrset may clear 'rdataset' (to prevent the * cleanup code from cleaning it up). * Add the CNAME to the answer section. * We set the PARTIALANSWER attribute so that if anything goes * wrong later on, we'll return what we've got so far. * Reset qname to be the target name of the CNAME and restart * Compare the current qname to the found name. We need * to know how many labels and bits are in common because * we're going to have to split qname later on. * Keep a copy of the rdataset. We have to do this because * query_addrrset may clear 'rdataset' (to prevent the * cleanup code from cleaning it up). * Add the DNAME to the answer section. * We set the PARTIALANSWER attribute so that if anything goes * wrong later on, we'll return what we've got so far. * Get the target name of the DNAME. * Construct the new qname. * RFC 2672, section 4.1, subsection 3c says * we should return YXDOMAIN if the constructed * name would be too long. * Synthesize a CNAME for this DNAME. * We want to synthesize a CNAME since if we don't * then older software that doesn't understand DNAME * will not chain like it should. * We do not try to synthesize a signature because we hope * that security aware servers will understand DNAME. Also, * even if we had an online key, making a signature * on-the-fly is costly, and not really legitimate anyway * since the synthesized CNAME is NOT in the zone. * Switch to the new qname and restart. * Something has gone wrong. * XXXRTH Need to handle zonecuts with special case * We set dbuf to NULL because we only * want the query_keepname() call in * query_addrrset() to be called once. * We shouldn't ever fail to add 'rdataset' * because it's already in the answer. * We're not interested in this rdataset. * We didn't match any rdatasets. * XXXRTH If this is a secure zone and we * didn't find any SIGs, we should generate * an error unless we were searching for * We were searching for SIG records in * a nonsecure zone. Send a "no error, * First we must release fname. * This is the "normal" case -- an ordinary question to which * We shouldn't ever fail to add 'rdataset' * because it's already in the answer. * Remember that we've answered this question. * Add NS records to the authority section (if we haven't already * added them to the answer section). * We're not authoritative, so we must ensure the AA bit * 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? * Ensure that appropriate cleanups occur. * We don't have a cache. Turn off cache support and * If the client doesn't want recursion, or we don't have * a resolver, turn recursion off. * XXXRTH Deal with allow-query and allow-recursion here. * There's more than one QNAME in the question * Check for illegal meta-classes and meta-types in * multiple question queries (edns1 section 5.1). * Check for meta-queries like IXFR and AXFR. break;
/* Let query_find handle it. */ default:
/* TSIG, etc. */ /* This is an ordinary query. */ * Assume authoritative response until it is known to be * Set AD. We need only clear it if we add "pending" data to * Note: as currently written, the server does not return "pending" * data even if a client says it's OK to do so.