123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775 |
- // Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC")
- //
- // Permission to use, copy, modify, and/or 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 ISC DISCLAIMS ALL WARRANTIES WITH
- // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
- // AND FITNESS. IN NO EVENT SHALL ISC 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 <stdint.h>
- #include <netinet/in.h>
- #include <algorithm>
- #include <vector>
- #include <cassert>
- #include <boost/shared_ptr.hpp>
- #include <boost/foreach.hpp>
- #include <exceptions/exceptions.h>
- #include <acl/dns.h>
- #include <acl/loader.h>
- #include <asiodns/asiodns.h>
- #include <asiolink/asiolink.h>
- #include <config/ccsession.h>
- #include <exceptions/exceptions.h>
- #include <util/buffer.h>
- #include <dns/opcode.h>
- #include <dns/rcode.h>
- #include <dns/exceptions.h>
- #include <dns/name.h>
- #include <dns/question.h>
- #include <dns/rrset.h>
- #include <dns/rrttl.h>
- #include <dns/message.h>
- #include <dns/messagerenderer.h>
- #include <server_common/client.h>
- #include <server_common/portconfig.h>
- #include <resolve/recursive_query.h>
- #include "resolver.h"
- #include "resolver_log.h"
- using namespace std;
- using boost::shared_ptr;
- using namespace isc;
- using namespace isc::util;
- using namespace isc::acl;
- using isc::acl::dns::RequestACL;
- using namespace isc::dns;
- using namespace isc::data;
- using namespace isc::config;
- using namespace isc::asiodns;
- using namespace isc::asiolink;
- using namespace isc::server_common;
- using namespace isc::server_common::portconfig;
- class ResolverImpl {
- private:
- // prohibit copy
- ResolverImpl(const ResolverImpl& source);
- ResolverImpl& operator=(const ResolverImpl& source);
- public:
- ResolverImpl() :
- config_session_(NULL),
- query_timeout_(2000),
- client_timeout_(4000),
- lookup_timeout_(30000),
- retries_(3),
- // we apply "reject all" (implicit default of the loader) ACL by
- // default:
- query_acl_(acl::dns::getRequestLoader().load(Element::fromJSON("[]"))),
- rec_query_(NULL)
- {}
- ~ResolverImpl() {
- queryShutdown();
- }
- void querySetup(DNSService& dnss,
- isc::nsas::NameserverAddressStore& nsas,
- isc::cache::ResolverCache& cache)
- {
- assert(!rec_query_); // queryShutdown must be called first
- LOG_DEBUG(resolver_logger, RESOLVER_DBG_INIT, RESOLVER_QUERY_SETUP);
- rec_query_ = new RecursiveQuery(dnss,
- nsas, cache,
- upstream_,
- upstream_root_,
- query_timeout_,
- client_timeout_,
- lookup_timeout_,
- retries_);
- }
- void queryShutdown() {
- // only shut down if we have actually called querySetup before
- // (this is not a safety check, just to prevent logging of
- // actions that are not performed
- if (rec_query_) {
- LOG_DEBUG(resolver_logger, RESOLVER_DBG_INIT,
- RESOLVER_QUERY_SHUTDOWN);
- delete rec_query_;
- rec_query_ = NULL;
- }
- }
- void setForwardAddresses(const AddressList& upstream,
- DNSService *dnss)
- {
- upstream_ = upstream;
- if (dnss) {
- if (!upstream_.empty()) {
- BOOST_FOREACH(const AddressPair& address, upstream) {
- LOG_INFO(resolver_logger, RESOLVER_FORWARD_ADDRESS)
- .arg(address.first).arg(address.second);
- }
- } else {
- LOG_INFO(resolver_logger, RESOLVER_RECURSIVE);
- }
- }
- }
- void setRootAddresses(const AddressList& upstream_root,
- DNSService *dnss)
- {
- upstream_root_ = upstream_root;
- if (dnss) {
- if (!upstream_root_.empty()) {
- BOOST_FOREACH(const AddressPair& address, upstream_root) {
- LOG_INFO(resolver_logger, RESOLVER_SET_ROOT_ADDRESS)
- .arg(address.first).arg(address.second);
- }
- } else {
- LOG_WARN(resolver_logger, RESOLVER_NO_ROOT_ADDRESS);
- }
- }
- }
-
- void resolve(const isc::dns::QuestionPtr& question,
- const isc::resolve::ResolverInterface::CallbackPtr& callback);
- enum NormalQueryResult { RECURSION, DROPPED, ERROR };
- NormalQueryResult processNormalQuery(const IOMessage& io_message,
- MessagePtr query_message,
- MessagePtr answer_message,
- OutputBufferPtr buffer,
- DNSServer* server);
- const RequestACL& getQueryACL() const {
- return (*query_acl_);
- }
- void setQueryACL(shared_ptr<const RequestACL> new_acl) {
- query_acl_ = new_acl;
- }
- /// Currently non-configurable, but will be.
- static const uint16_t DEFAULT_LOCAL_UDPSIZE = 4096;
- /// These members are public because Resolver accesses them directly.
- ModuleCCSession* config_session_;
- /// Addresses of the root nameserver(s)
- AddressList upstream_root_;
- /// Addresses of the forward nameserver
- AddressList upstream_;
- /// Addresses we listen on
- AddressList listen_;
- /// Timeout for outgoing queries in milliseconds
- int query_timeout_;
- /// Timeout for incoming client queries in milliseconds
- int client_timeout_;
- /// Timeout for lookup processing in milliseconds
- int lookup_timeout_;
-
- /// Number of retries after timeout
- unsigned retries_;
- private:
- /// ACL on incoming queries
- shared_ptr<const RequestACL> query_acl_;
- /// Object to handle upstream queries
- RecursiveQuery* rec_query_;
- };
- /*
- * std::for_each has a broken interface. It makes no sense in a language
- * without lambda functions/closures. These two classes emulate the lambda
- * functions so for_each can be used.
- */
- class QuestionInserter {
- public:
- QuestionInserter(MessagePtr message) : message_(message) {}
- void operator()(const QuestionPtr question) {
- message_->addQuestion(question);
- }
- MessagePtr message_;
- };
- // TODO: REMOVE, USE isc::resolve::MakeErrorMessage?
- void
- makeErrorMessage(MessagePtr message, MessagePtr answer_message,
- OutputBufferPtr buffer, const Rcode& rcode)
- {
- // extract the parameters that should be kept.
- // XXX: with the current implementation, it's not easy to set EDNS0
- // depending on whether the query had it. So we'll simply omit it.
- const qid_t qid = message->getQid();
- const bool rd = message->getHeaderFlag(Message::HEADERFLAG_RD);
- const bool cd = message->getHeaderFlag(Message::HEADERFLAG_CD);
- const Opcode& opcode = message->getOpcode();
- vector<QuestionPtr> questions;
- // answer_message is actually ignored right now,
- // see the comment in #607
- answer_message->setRcode(rcode);
- answer_message->setOpcode(opcode);
- answer_message->setQid(qid);
- // If this is an error to a query or notify, we should also copy the
- // question section.
- if (opcode == Opcode::QUERY() || opcode == Opcode::NOTIFY()) {
- questions.assign(message->beginQuestion(), message->endQuestion());
- }
- message->clear(Message::RENDER);
- message->setQid(qid);
- message->setOpcode(opcode);
- message->setHeaderFlag(Message::HEADERFLAG_QR);
- if (rd) {
- message->setHeaderFlag(Message::HEADERFLAG_RD);
- }
- if (cd) {
- message->setHeaderFlag(Message::HEADERFLAG_CD);
- }
- for_each(questions.begin(), questions.end(), QuestionInserter(message));
- message->setRcode(rcode);
- MessageRenderer renderer(*buffer);
- message->toWire(renderer);
- }
- // This is a derived class of \c DNSLookup, to serve as a
- // callback in the asiolink module. It calls
- // Resolver::processMessage() on a single DNS message.
- class MessageLookup : public DNSLookup {
- public:
- MessageLookup(Resolver* srv) : server_(srv) {}
- // \brief Handle the DNS Lookup
- virtual void operator()(const IOMessage& io_message,
- MessagePtr query_message,
- MessagePtr answer_message,
- OutputBufferPtr buffer,
- DNSServer* server) const
- {
- server_->processMessage(io_message, query_message,
- answer_message, buffer, server);
- }
- private:
- Resolver* server_;
- };
- // This is a derived class of \c DNSAnswer, to serve as a
- // callback in the asiolink module. It takes a completed
- // set of answer data from the DNS lookup and assembles it
- // into a wire-format response.
- class MessageAnswer : public DNSAnswer {
- public:
- virtual void operator()(const IOMessage& io_message,
- MessagePtr query_message,
- MessagePtr answer_message,
- OutputBufferPtr buffer) const
- {
- const qid_t qid = query_message->getQid();
- const bool rd = query_message->getHeaderFlag(Message::HEADERFLAG_RD);
- const bool cd = query_message->getHeaderFlag(Message::HEADERFLAG_CD);
-
- // The opcode and question section should have already been set,
- // fill in the final details of the answer message
- answer_message->setQid(qid);
- answer_message->setHeaderFlag(Message::HEADERFLAG_QR);
- answer_message->setHeaderFlag(Message::HEADERFLAG_RA);
- answer_message->setHeaderFlag(Message::HEADERFLAG_RD, rd);
- answer_message->setHeaderFlag(Message::HEADERFLAG_CD, cd);
- // Now we can clear the buffer and render the new message into it
- buffer->clear();
- MessageRenderer renderer(*buffer);
- ConstEDNSPtr edns(query_message->getEDNS());
- const bool dnssec_ok = edns && edns->getDNSSECAwareness();
- if (edns) {
- EDNSPtr edns_response(new EDNS());
- edns_response->setDNSSECAwareness(dnssec_ok);
- // TODO: We should make our own edns bufsize length configurable
- edns_response->setUDPSize(Message::DEFAULT_MAX_EDNS0_UDPSIZE);
- answer_message->setEDNS(edns_response);
- }
- if (io_message.getSocket().getProtocol() == IPPROTO_UDP) {
- if (edns) {
- renderer.setLengthLimit(edns->getUDPSize());
- } else {
- renderer.setLengthLimit(Message::DEFAULT_MAX_UDPSIZE);
- }
- } else {
- renderer.setLengthLimit(65535);
- }
- answer_message->toWire(renderer);
- LOG_DEBUG(resolver_logger, RESOLVER_DBG_DETAIL,
- RESOLVER_DNS_MESSAGE_SENT)
- .arg(renderer.getLength()).arg(*answer_message);
- }
- };
- // This is a derived class of \c SimpleCallback, to serve
- // as a callback in the asiolink module. It checks for queued
- // configuration messages, and executes them if found.
- class ConfigCheck : public SimpleCallback {
- public:
- ConfigCheck(Resolver* srv) : server_(srv) {}
- virtual void operator()(const IOMessage&) const {
- if (server_->getConfigSession()->hasQueuedMsgs()) {
- server_->getConfigSession()->checkCommand();
- }
- }
- private:
- Resolver* server_;
- };
- Resolver::Resolver() :
- impl_(new ResolverImpl()),
- dnss_(NULL),
- checkin_(new ConfigCheck(this)),
- dns_lookup_(new MessageLookup(this)),
- dns_answer_(new MessageAnswer),
- nsas_(NULL),
- cache_(NULL),
- configured_(false)
- {}
- Resolver::~Resolver() {
- delete impl_;
- delete checkin_;
- delete dns_lookup_;
- delete dns_answer_;
- }
- void
- Resolver::setDNSService(isc::asiodns::DNSService& dnss) {
- dnss_ = &dnss;
- }
- void
- Resolver::setNameserverAddressStore(isc::nsas::NameserverAddressStore& nsas)
- {
- nsas_ = &nsas;
- }
- void
- Resolver::setCache(isc::cache::ResolverCache& cache)
- {
- cache_ = &cache;
- }
- void
- Resolver::setConfigSession(ModuleCCSession* config_session) {
- impl_->config_session_ = config_session;
- }
- ModuleCCSession*
- Resolver::getConfigSession() const {
- return (impl_->config_session_);
- }
- void
- Resolver::resolve(const isc::dns::QuestionPtr& question,
- const isc::resolve::ResolverInterface::CallbackPtr& callback)
- {
- impl_->resolve(question, callback);
- }
- void
- Resolver::processMessage(const IOMessage& io_message,
- MessagePtr query_message,
- MessagePtr answer_message,
- OutputBufferPtr buffer,
- DNSServer* server)
- {
- InputBuffer request_buffer(io_message.getData(), io_message.getDataSize());
- // First, check the header part. If we fail even for the base header,
- // just drop the message.
- // In the following code, the debug output is such that there should only be
- // one debug message if packet processing failed. There could be two if
- // it succeeded.
- try {
- query_message->parseHeader(request_buffer);
- // Ignore all responses.
- if (query_message->getHeaderFlag(Message::HEADERFLAG_QR)) {
- LOG_DEBUG(resolver_logger, RESOLVER_DBG_IO, RESOLVER_UNEXPECTED_RESPONSE);
- server->resume(false);
- return;
- }
- } catch (const Exception& ex) {
- LOG_DEBUG(resolver_logger, RESOLVER_DBG_IO, RESOLVER_HEADER_ERROR)
- .arg(ex.what());
- server->resume(false);
- return;
- }
- // Parse the message. On failure, return an appropriate error.
- try {
- query_message->fromWire(request_buffer);
- } catch (const DNSProtocolError& error) {
- LOG_DEBUG(resolver_logger, RESOLVER_DBG_IO, RESOLVER_PROTOCOL_ERROR)
- .arg(error.what()).arg(error.getRcode());
- makeErrorMessage(query_message, answer_message,
- buffer, error.getRcode());
- server->resume(true);
- return;
- } catch (const Exception& ex) {
- LOG_DEBUG(resolver_logger, RESOLVER_DBG_IO, RESOLVER_MESSAGE_ERROR)
- .arg(ex.what()).arg(Rcode::SERVFAIL());
- makeErrorMessage(query_message, answer_message,
- buffer, Rcode::SERVFAIL());
- server->resume(true);
- return;
- } // Other exceptions will be handled at a higher layer.
- // Note: there appears to be no LOG_DEBUG for a successfully-received
- // message. This is not an oversight - it is handled below. In the
- // meantime, output the full message for debug purposes (if requested).
- LOG_DEBUG(resolver_logger, RESOLVER_DBG_DETAIL,
- RESOLVER_DNS_MESSAGE_RECEIVED).arg(*query_message);
- // Perform further protocol-level validation.
- bool send_answer = true;
- if (query_message->getOpcode() == Opcode::NOTIFY()) {
- makeErrorMessage(query_message, answer_message,
- buffer, Rcode::NOTAUTH());
- // Notify arrived, but we are not authoritative.
- LOG_DEBUG(resolver_logger, RESOLVER_DBG_PROCESS,
- RESOLVER_NOTIFY_RECEIVED);
- } else if (query_message->getOpcode() != Opcode::QUERY()) {
- // Unsupported opcode.
- LOG_DEBUG(resolver_logger, RESOLVER_DBG_PROCESS,
- RESOLVER_UNSUPPORTED_OPCODE).arg(query_message->getOpcode());
- makeErrorMessage(query_message, answer_message,
- buffer, Rcode::NOTIMP());
- } else if (query_message->getRRCount(Message::SECTION_QUESTION) != 1) {
- // Not one question
- LOG_DEBUG(resolver_logger, RESOLVER_DBG_PROCESS,
- RESOLVER_NOT_ONE_QUESTION)
- .arg(query_message->getRRCount(Message::SECTION_QUESTION));
- makeErrorMessage(query_message, answer_message, buffer,
- Rcode::FORMERR());
- } else {
- const ResolverImpl::NormalQueryResult result =
- impl_->processNormalQuery(io_message, query_message,
- answer_message, buffer, server);
- if (result == ResolverImpl::RECURSION) {
- // The RecursiveQuery object will post the "resume" event to the
- // DNSServer when an answer arrives, so we don't have to do it now.
- return;
- } else if (result == ResolverImpl::DROPPED) {
- send_answer = false;
- }
- }
- server->resume(send_answer);
- }
- void
- ResolverImpl::resolve(const QuestionPtr& question,
- const isc::resolve::ResolverInterface::CallbackPtr& callback)
- {
- rec_query_->resolve(question, callback);
- }
- ResolverImpl::NormalQueryResult
- ResolverImpl::processNormalQuery(const IOMessage& io_message,
- MessagePtr query_message,
- MessagePtr answer_message,
- OutputBufferPtr buffer,
- DNSServer* server)
- {
- const ConstQuestionPtr question = *query_message->beginQuestion();
- const RRType qtype = question->getType();
- const RRClass qclass = question->getClass();
- // Apply query ACL
- const Client client(io_message);
- const BasicAction query_action(
- getQueryACL().execute(acl::dns::RequestContext(
- client.getRequestSourceIPAddress(),
- query_message->getTSIGRecord())));
- if (query_action == isc::acl::REJECT) {
- LOG_INFO(resolver_logger, RESOLVER_QUERY_REJECTED)
- .arg(question->getName()).arg(qtype).arg(qclass).arg(client);
- makeErrorMessage(query_message, answer_message, buffer,
- Rcode::REFUSED());
- return (ERROR);
- } else if (query_action == isc::acl::DROP) {
- LOG_INFO(resolver_logger, RESOLVER_QUERY_DROPPED)
- .arg(question->getName()).arg(qtype).arg(qclass).arg(client);
- return (DROPPED);
- }
- LOG_DEBUG(resolver_logger, RESOLVER_DBG_IO, RESOLVER_QUERY_ACCEPTED)
- .arg(question->getName()).arg(qtype).arg(question->getClass())
- .arg(client);
- // ACL passed. Reject inappropriate queries for the resolver.
- if (qtype == RRType::AXFR()) {
- if (io_message.getSocket().getProtocol() == IPPROTO_UDP) {
- // Can't process AXFR request received over UDP
- LOG_DEBUG(resolver_logger, RESOLVER_DBG_PROCESS, RESOLVER_AXFR_UDP);
- makeErrorMessage(query_message, answer_message, buffer,
- Rcode::FORMERR());
- } else {
- // ... or over TCP for that matter
- LOG_DEBUG(resolver_logger, RESOLVER_DBG_PROCESS, RESOLVER_AXFR_TCP);
- makeErrorMessage(query_message, answer_message, buffer,
- Rcode::NOTIMP());
- }
- return (ERROR);
- } else if (qtype == RRType::IXFR()) {
- // Can't process IXFR request
- LOG_DEBUG(resolver_logger, RESOLVER_DBG_PROCESS, RESOLVER_IXFR);
- makeErrorMessage(query_message, answer_message, buffer,
- Rcode::NOTIMP());
- return (ERROR);
- } else if (qclass != RRClass::IN()) {
- // Non-IN message received, refuse it.
- LOG_DEBUG(resolver_logger, RESOLVER_DBG_PROCESS, RESOLVER_NON_IN_PACKET)
- .arg(question->getClass());
- makeErrorMessage(query_message, answer_message, buffer,
- Rcode::REFUSED());
- return (ERROR);
- }
- // Everything is okay. Start resolver.
- if (upstream_.empty()) {
- // Processing normal query
- LOG_DEBUG(resolver_logger, RESOLVER_DBG_IO, RESOLVER_NORMAL_QUERY);
- rec_query_->resolve(*question, answer_message, buffer, server);
- } else {
- // Processing forward query
- LOG_DEBUG(resolver_logger, RESOLVER_DBG_IO, RESOLVER_FORWARD_QUERY);
- rec_query_->forward(query_message, answer_message, buffer, server);
- }
- return (RECURSION);
- }
- ConstElementPtr
- Resolver::updateConfig(ConstElementPtr config) {
- LOG_DEBUG(resolver_logger, RESOLVER_DBG_CONFIG, RESOLVER_CONFIG_UPDATED)
- .arg(*config);
- try {
- // Parse forward_addresses
- ConstElementPtr rootAddressesE(config->get("root_addresses"));
- AddressList rootAddresses(parseAddresses(rootAddressesE,
- "root_addresses"));
- ConstElementPtr forwardAddressesE(config->get("forward_addresses"));
- AddressList forwardAddresses(parseAddresses(forwardAddressesE,
- "forward_addresses"));
- ConstElementPtr listenAddressesE(config->get("listen_on"));
- AddressList listenAddresses(parseAddresses(listenAddressesE,
- "listen_on"));
- const ConstElementPtr query_acl_cfg(config->get("query_acl"));
- const shared_ptr<const RequestACL> query_acl =
- query_acl_cfg ? acl::dns::getRequestLoader().load(query_acl_cfg) :
- shared_ptr<RequestACL>();
- bool set_timeouts(false);
- int qtimeout = impl_->query_timeout_;
- int ctimeout = impl_->client_timeout_;
- int ltimeout = impl_->lookup_timeout_;
- unsigned retries = impl_->retries_;
- ConstElementPtr qtimeoutE(config->get("timeout_query")),
- ctimeoutE(config->get("timeout_client")),
- ltimeoutE(config->get("timeout_lookup")),
- retriesE(config->get("retries"));
- if (qtimeoutE) {
- // It should be safe to just get it, the config manager should
- // check for us
- qtimeout = qtimeoutE->intValue();
- if (qtimeout < -1) {
- LOG_ERROR(resolver_logger, RESOLVER_QUERY_TIME_SMALL)
- .arg(qtimeout);
- isc_throw(BadValue, "Query timeout too small");
- }
- set_timeouts = true;
- }
- if (ctimeoutE) {
- ctimeout = ctimeoutE->intValue();
- if (ctimeout < -1) {
- LOG_ERROR(resolver_logger, RESOLVER_CLIENT_TIME_SMALL)
- .arg(ctimeout);
- isc_throw(BadValue, "Client timeout too small");
- }
- set_timeouts = true;
- }
- if (ltimeoutE) {
- ltimeout = ltimeoutE->intValue();
- if (ltimeout < -1) {
- LOG_ERROR(resolver_logger, RESOLVER_LOOKUP_TIME_SMALL)
- .arg(ltimeout);
- isc_throw(BadValue, "Lookup timeout too small");
- }
- set_timeouts = true;
- }
- if (retriesE) {
- // Do the assignment from "retriesE->intValue()" to "retries"
- // _after_ the comparison (as opposed to before it for the timeouts)
- // because "retries" is unsigned.
- if (retriesE->intValue() < 0) {
- LOG_ERROR(resolver_logger, RESOLVER_NEGATIVE_RETRIES)
- .arg(retriesE->intValue());
- isc_throw(BadValue, "Negative number of retries");
- }
- retries = retriesE->intValue();
- set_timeouts = true;
- }
- // Everything OK, so commit the changes
- // listenAddresses can fail to bind, so try them first
- bool need_query_restart = false;
-
- if (listenAddressesE) {
- setListenAddresses(listenAddresses);
- need_query_restart = true;
- }
- if (forwardAddressesE) {
- setForwardAddresses(forwardAddresses);
- need_query_restart = true;
- }
- if (rootAddressesE) {
- setRootAddresses(rootAddresses);
- need_query_restart = true;
- }
- if (set_timeouts) {
- setTimeouts(qtimeout, ctimeout, ltimeout, retries);
- need_query_restart = true;
- }
- if (query_acl) {
- setQueryACL(query_acl);
- }
- if (need_query_restart) {
- impl_->queryShutdown();
- impl_->querySetup(*dnss_, *nsas_, *cache_);
- }
- setConfigured();
- return (isc::config::createAnswer());
- } catch (const isc::Exception& error) {
- // Configuration error
- LOG_ERROR(resolver_logger, RESOLVER_CONFIG_ERROR).arg(error.what());
- return (isc::config::createAnswer(1, error.what()));
- }
- }
- void
- Resolver::setForwardAddresses(const AddressList& addresses)
- {
- impl_->setForwardAddresses(addresses, dnss_);
- }
- void
- Resolver::setRootAddresses(const AddressList& addresses)
- {
- impl_->setRootAddresses(addresses, dnss_);
- }
- bool
- Resolver::isForwarding() const {
- return (!impl_->upstream_.empty());
- }
- AddressList
- Resolver::getForwardAddresses() const {
- return (impl_->upstream_);
- }
- AddressList
- Resolver::getRootAddresses() const {
- return (impl_->upstream_root_);
- }
- void
- Resolver::setListenAddresses(const AddressList& addresses) {
- installListenAddresses(addresses, impl_->listen_, *dnss_);
- }
- void
- Resolver::setTimeouts(int query_timeout, int client_timeout,
- int lookup_timeout, unsigned retries) {
- LOG_DEBUG(resolver_logger, RESOLVER_DBG_CONFIG, RESOLVER_SET_PARAMS)
- .arg(query_timeout).arg(client_timeout).arg(lookup_timeout)
- .arg(retries);
- impl_->query_timeout_ = query_timeout;
- impl_->client_timeout_ = client_timeout;
- impl_->lookup_timeout_ = lookup_timeout;
- impl_->retries_ = retries;
- }
- int
- Resolver::getQueryTimeout() const {
- return impl_->query_timeout_;
- }
- int
- Resolver::getClientTimeout() const {
- return impl_->client_timeout_;
- }
- int
- Resolver::getLookupTimeout() const {
- return impl_->lookup_timeout_;
- }
- int
- Resolver::getRetries() const {
- return impl_->retries_;
- }
- AddressList
- Resolver::getListenAddresses() const {
- return (impl_->listen_);
- }
- const RequestACL&
- Resolver::getQueryACL() const {
- return (impl_->getQueryACL());
- }
- void
- Resolver::setQueryACL(shared_ptr<const RequestACL> new_acl) {
- if (!new_acl) {
- isc_throw(InvalidParameter, "NULL pointer is passed to setQueryACL");
- }
- LOG_INFO(resolver_logger, RESOLVER_SET_QUERY_ACL);
- impl_->setQueryACL(new_acl);
- }
|