resolver.cc 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775
  1. // Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // Permission to use, copy, modify, and/or distribute this software for any
  4. // purpose with or without fee is hereby granted, provided that the above
  5. // copyright notice and this permission notice appear in all copies.
  6. //
  7. // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  8. // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  9. // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  10. // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  11. // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  12. // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  13. // PERFORMANCE OF THIS SOFTWARE.
  14. #include <config.h>
  15. #include <stdint.h>
  16. #include <netinet/in.h>
  17. #include <algorithm>
  18. #include <vector>
  19. #include <cassert>
  20. #include <boost/shared_ptr.hpp>
  21. #include <boost/foreach.hpp>
  22. #include <exceptions/exceptions.h>
  23. #include <acl/dns.h>
  24. #include <acl/loader.h>
  25. #include <asiodns/asiodns.h>
  26. #include <asiolink/asiolink.h>
  27. #include <config/ccsession.h>
  28. #include <exceptions/exceptions.h>
  29. #include <util/buffer.h>
  30. #include <dns/opcode.h>
  31. #include <dns/rcode.h>
  32. #include <dns/exceptions.h>
  33. #include <dns/name.h>
  34. #include <dns/question.h>
  35. #include <dns/rrset.h>
  36. #include <dns/rrttl.h>
  37. #include <dns/message.h>
  38. #include <dns/messagerenderer.h>
  39. #include <server_common/client.h>
  40. #include <server_common/portconfig.h>
  41. #include <resolve/recursive_query.h>
  42. #include "resolver.h"
  43. #include "resolver_log.h"
  44. using namespace std;
  45. using boost::shared_ptr;
  46. using namespace isc;
  47. using namespace isc::util;
  48. using namespace isc::acl;
  49. using isc::acl::dns::RequestACL;
  50. using namespace isc::dns;
  51. using namespace isc::data;
  52. using namespace isc::config;
  53. using namespace isc::asiodns;
  54. using namespace isc::asiolink;
  55. using namespace isc::server_common;
  56. using namespace isc::server_common::portconfig;
  57. class ResolverImpl {
  58. private:
  59. // prohibit copy
  60. ResolverImpl(const ResolverImpl& source);
  61. ResolverImpl& operator=(const ResolverImpl& source);
  62. public:
  63. ResolverImpl() :
  64. config_session_(NULL),
  65. query_timeout_(2000),
  66. client_timeout_(4000),
  67. lookup_timeout_(30000),
  68. retries_(3),
  69. // we apply "reject all" (implicit default of the loader) ACL by
  70. // default:
  71. query_acl_(acl::dns::getRequestLoader().load(Element::fromJSON("[]"))),
  72. rec_query_(NULL)
  73. {}
  74. ~ResolverImpl() {
  75. queryShutdown();
  76. }
  77. void querySetup(DNSService& dnss,
  78. isc::nsas::NameserverAddressStore& nsas,
  79. isc::cache::ResolverCache& cache)
  80. {
  81. assert(!rec_query_); // queryShutdown must be called first
  82. LOG_DEBUG(resolver_logger, RESOLVER_DBG_INIT, RESOLVER_QUERY_SETUP);
  83. rec_query_ = new RecursiveQuery(dnss,
  84. nsas, cache,
  85. upstream_,
  86. upstream_root_,
  87. query_timeout_,
  88. client_timeout_,
  89. lookup_timeout_,
  90. retries_);
  91. }
  92. void queryShutdown() {
  93. // only shut down if we have actually called querySetup before
  94. // (this is not a safety check, just to prevent logging of
  95. // actions that are not performed
  96. if (rec_query_) {
  97. LOG_DEBUG(resolver_logger, RESOLVER_DBG_INIT,
  98. RESOLVER_QUERY_SHUTDOWN);
  99. delete rec_query_;
  100. rec_query_ = NULL;
  101. }
  102. }
  103. void setForwardAddresses(const AddressList& upstream,
  104. DNSService *dnss)
  105. {
  106. upstream_ = upstream;
  107. if (dnss) {
  108. if (!upstream_.empty()) {
  109. BOOST_FOREACH(const AddressPair& address, upstream) {
  110. LOG_INFO(resolver_logger, RESOLVER_FORWARD_ADDRESS)
  111. .arg(address.first).arg(address.second);
  112. }
  113. } else {
  114. LOG_INFO(resolver_logger, RESOLVER_RECURSIVE);
  115. }
  116. }
  117. }
  118. void setRootAddresses(const AddressList& upstream_root,
  119. DNSService *dnss)
  120. {
  121. upstream_root_ = upstream_root;
  122. if (dnss) {
  123. if (!upstream_root_.empty()) {
  124. BOOST_FOREACH(const AddressPair& address, upstream_root) {
  125. LOG_INFO(resolver_logger, RESOLVER_SET_ROOT_ADDRESS)
  126. .arg(address.first).arg(address.second);
  127. }
  128. } else {
  129. LOG_WARN(resolver_logger, RESOLVER_NO_ROOT_ADDRESS);
  130. }
  131. }
  132. }
  133. void resolve(const isc::dns::QuestionPtr& question,
  134. const isc::resolve::ResolverInterface::CallbackPtr& callback);
  135. enum NormalQueryResult { RECURSION, DROPPED, ERROR };
  136. NormalQueryResult processNormalQuery(const IOMessage& io_message,
  137. MessagePtr query_message,
  138. MessagePtr answer_message,
  139. OutputBufferPtr buffer,
  140. DNSServer* server);
  141. const RequestACL& getQueryACL() const {
  142. return (*query_acl_);
  143. }
  144. void setQueryACL(shared_ptr<const RequestACL> new_acl) {
  145. query_acl_ = new_acl;
  146. }
  147. /// Currently non-configurable, but will be.
  148. static const uint16_t DEFAULT_LOCAL_UDPSIZE = 4096;
  149. /// These members are public because Resolver accesses them directly.
  150. ModuleCCSession* config_session_;
  151. /// Addresses of the root nameserver(s)
  152. AddressList upstream_root_;
  153. /// Addresses of the forward nameserver
  154. AddressList upstream_;
  155. /// Addresses we listen on
  156. AddressList listen_;
  157. /// Timeout for outgoing queries in milliseconds
  158. int query_timeout_;
  159. /// Timeout for incoming client queries in milliseconds
  160. int client_timeout_;
  161. /// Timeout for lookup processing in milliseconds
  162. int lookup_timeout_;
  163. /// Number of retries after timeout
  164. unsigned retries_;
  165. private:
  166. /// ACL on incoming queries
  167. shared_ptr<const RequestACL> query_acl_;
  168. /// Object to handle upstream queries
  169. RecursiveQuery* rec_query_;
  170. };
  171. /*
  172. * std::for_each has a broken interface. It makes no sense in a language
  173. * without lambda functions/closures. These two classes emulate the lambda
  174. * functions so for_each can be used.
  175. */
  176. class QuestionInserter {
  177. public:
  178. QuestionInserter(MessagePtr message) : message_(message) {}
  179. void operator()(const QuestionPtr question) {
  180. message_->addQuestion(question);
  181. }
  182. MessagePtr message_;
  183. };
  184. // TODO: REMOVE, USE isc::resolve::MakeErrorMessage?
  185. void
  186. makeErrorMessage(MessagePtr message, MessagePtr answer_message,
  187. OutputBufferPtr buffer, const Rcode& rcode)
  188. {
  189. // extract the parameters that should be kept.
  190. // XXX: with the current implementation, it's not easy to set EDNS0
  191. // depending on whether the query had it. So we'll simply omit it.
  192. const qid_t qid = message->getQid();
  193. const bool rd = message->getHeaderFlag(Message::HEADERFLAG_RD);
  194. const bool cd = message->getHeaderFlag(Message::HEADERFLAG_CD);
  195. const Opcode& opcode = message->getOpcode();
  196. vector<QuestionPtr> questions;
  197. // answer_message is actually ignored right now,
  198. // see the comment in #607
  199. answer_message->setRcode(rcode);
  200. answer_message->setOpcode(opcode);
  201. answer_message->setQid(qid);
  202. // If this is an error to a query or notify, we should also copy the
  203. // question section.
  204. if (opcode == Opcode::QUERY() || opcode == Opcode::NOTIFY()) {
  205. questions.assign(message->beginQuestion(), message->endQuestion());
  206. }
  207. message->clear(Message::RENDER);
  208. message->setQid(qid);
  209. message->setOpcode(opcode);
  210. message->setHeaderFlag(Message::HEADERFLAG_QR);
  211. if (rd) {
  212. message->setHeaderFlag(Message::HEADERFLAG_RD);
  213. }
  214. if (cd) {
  215. message->setHeaderFlag(Message::HEADERFLAG_CD);
  216. }
  217. for_each(questions.begin(), questions.end(), QuestionInserter(message));
  218. message->setRcode(rcode);
  219. MessageRenderer renderer(*buffer);
  220. message->toWire(renderer);
  221. }
  222. // This is a derived class of \c DNSLookup, to serve as a
  223. // callback in the asiolink module. It calls
  224. // Resolver::processMessage() on a single DNS message.
  225. class MessageLookup : public DNSLookup {
  226. public:
  227. MessageLookup(Resolver* srv) : server_(srv) {}
  228. // \brief Handle the DNS Lookup
  229. virtual void operator()(const IOMessage& io_message,
  230. MessagePtr query_message,
  231. MessagePtr answer_message,
  232. OutputBufferPtr buffer,
  233. DNSServer* server) const
  234. {
  235. server_->processMessage(io_message, query_message,
  236. answer_message, buffer, server);
  237. }
  238. private:
  239. Resolver* server_;
  240. };
  241. // This is a derived class of \c DNSAnswer, to serve as a
  242. // callback in the asiolink module. It takes a completed
  243. // set of answer data from the DNS lookup and assembles it
  244. // into a wire-format response.
  245. class MessageAnswer : public DNSAnswer {
  246. public:
  247. virtual void operator()(const IOMessage& io_message,
  248. MessagePtr query_message,
  249. MessagePtr answer_message,
  250. OutputBufferPtr buffer) const
  251. {
  252. const qid_t qid = query_message->getQid();
  253. const bool rd = query_message->getHeaderFlag(Message::HEADERFLAG_RD);
  254. const bool cd = query_message->getHeaderFlag(Message::HEADERFLAG_CD);
  255. // The opcode and question section should have already been set,
  256. // fill in the final details of the answer message
  257. answer_message->setQid(qid);
  258. answer_message->setHeaderFlag(Message::HEADERFLAG_QR);
  259. answer_message->setHeaderFlag(Message::HEADERFLAG_RA);
  260. answer_message->setHeaderFlag(Message::HEADERFLAG_RD, rd);
  261. answer_message->setHeaderFlag(Message::HEADERFLAG_CD, cd);
  262. // Now we can clear the buffer and render the new message into it
  263. buffer->clear();
  264. MessageRenderer renderer(*buffer);
  265. ConstEDNSPtr edns(query_message->getEDNS());
  266. const bool dnssec_ok = edns && edns->getDNSSECAwareness();
  267. if (edns) {
  268. EDNSPtr edns_response(new EDNS());
  269. edns_response->setDNSSECAwareness(dnssec_ok);
  270. // TODO: We should make our own edns bufsize length configurable
  271. edns_response->setUDPSize(Message::DEFAULT_MAX_EDNS0_UDPSIZE);
  272. answer_message->setEDNS(edns_response);
  273. }
  274. if (io_message.getSocket().getProtocol() == IPPROTO_UDP) {
  275. if (edns) {
  276. renderer.setLengthLimit(edns->getUDPSize());
  277. } else {
  278. renderer.setLengthLimit(Message::DEFAULT_MAX_UDPSIZE);
  279. }
  280. } else {
  281. renderer.setLengthLimit(65535);
  282. }
  283. answer_message->toWire(renderer);
  284. LOG_DEBUG(resolver_logger, RESOLVER_DBG_DETAIL,
  285. RESOLVER_DNS_MESSAGE_SENT)
  286. .arg(renderer.getLength()).arg(*answer_message);
  287. }
  288. };
  289. // This is a derived class of \c SimpleCallback, to serve
  290. // as a callback in the asiolink module. It checks for queued
  291. // configuration messages, and executes them if found.
  292. class ConfigCheck : public SimpleCallback {
  293. public:
  294. ConfigCheck(Resolver* srv) : server_(srv) {}
  295. virtual void operator()(const IOMessage&) const {
  296. if (server_->getConfigSession()->hasQueuedMsgs()) {
  297. server_->getConfigSession()->checkCommand();
  298. }
  299. }
  300. private:
  301. Resolver* server_;
  302. };
  303. Resolver::Resolver() :
  304. impl_(new ResolverImpl()),
  305. dnss_(NULL),
  306. checkin_(new ConfigCheck(this)),
  307. dns_lookup_(new MessageLookup(this)),
  308. dns_answer_(new MessageAnswer),
  309. nsas_(NULL),
  310. cache_(NULL),
  311. configured_(false)
  312. {}
  313. Resolver::~Resolver() {
  314. delete impl_;
  315. delete checkin_;
  316. delete dns_lookup_;
  317. delete dns_answer_;
  318. }
  319. void
  320. Resolver::setDNSService(isc::asiodns::DNSService& dnss) {
  321. dnss_ = &dnss;
  322. }
  323. void
  324. Resolver::setNameserverAddressStore(isc::nsas::NameserverAddressStore& nsas)
  325. {
  326. nsas_ = &nsas;
  327. }
  328. void
  329. Resolver::setCache(isc::cache::ResolverCache& cache)
  330. {
  331. cache_ = &cache;
  332. }
  333. void
  334. Resolver::setConfigSession(ModuleCCSession* config_session) {
  335. impl_->config_session_ = config_session;
  336. }
  337. ModuleCCSession*
  338. Resolver::getConfigSession() const {
  339. return (impl_->config_session_);
  340. }
  341. void
  342. Resolver::resolve(const isc::dns::QuestionPtr& question,
  343. const isc::resolve::ResolverInterface::CallbackPtr& callback)
  344. {
  345. impl_->resolve(question, callback);
  346. }
  347. void
  348. Resolver::processMessage(const IOMessage& io_message,
  349. MessagePtr query_message,
  350. MessagePtr answer_message,
  351. OutputBufferPtr buffer,
  352. DNSServer* server)
  353. {
  354. InputBuffer request_buffer(io_message.getData(), io_message.getDataSize());
  355. // First, check the header part. If we fail even for the base header,
  356. // just drop the message.
  357. // In the following code, the debug output is such that there should only be
  358. // one debug message if packet processing failed. There could be two if
  359. // it succeeded.
  360. try {
  361. query_message->parseHeader(request_buffer);
  362. // Ignore all responses.
  363. if (query_message->getHeaderFlag(Message::HEADERFLAG_QR)) {
  364. LOG_DEBUG(resolver_logger, RESOLVER_DBG_IO, RESOLVER_UNEXPECTED_RESPONSE);
  365. server->resume(false);
  366. return;
  367. }
  368. } catch (const Exception& ex) {
  369. LOG_DEBUG(resolver_logger, RESOLVER_DBG_IO, RESOLVER_HEADER_ERROR)
  370. .arg(ex.what());
  371. server->resume(false);
  372. return;
  373. }
  374. // Parse the message. On failure, return an appropriate error.
  375. try {
  376. query_message->fromWire(request_buffer);
  377. } catch (const DNSProtocolError& error) {
  378. LOG_DEBUG(resolver_logger, RESOLVER_DBG_IO, RESOLVER_PROTOCOL_ERROR)
  379. .arg(error.what()).arg(error.getRcode());
  380. makeErrorMessage(query_message, answer_message,
  381. buffer, error.getRcode());
  382. server->resume(true);
  383. return;
  384. } catch (const Exception& ex) {
  385. LOG_DEBUG(resolver_logger, RESOLVER_DBG_IO, RESOLVER_MESSAGE_ERROR)
  386. .arg(ex.what()).arg(Rcode::SERVFAIL());
  387. makeErrorMessage(query_message, answer_message,
  388. buffer, Rcode::SERVFAIL());
  389. server->resume(true);
  390. return;
  391. } // Other exceptions will be handled at a higher layer.
  392. // Note: there appears to be no LOG_DEBUG for a successfully-received
  393. // message. This is not an oversight - it is handled below. In the
  394. // meantime, output the full message for debug purposes (if requested).
  395. LOG_DEBUG(resolver_logger, RESOLVER_DBG_DETAIL,
  396. RESOLVER_DNS_MESSAGE_RECEIVED).arg(*query_message);
  397. // Perform further protocol-level validation.
  398. bool send_answer = true;
  399. if (query_message->getOpcode() == Opcode::NOTIFY()) {
  400. makeErrorMessage(query_message, answer_message,
  401. buffer, Rcode::NOTAUTH());
  402. // Notify arrived, but we are not authoritative.
  403. LOG_DEBUG(resolver_logger, RESOLVER_DBG_PROCESS,
  404. RESOLVER_NOTIFY_RECEIVED);
  405. } else if (query_message->getOpcode() != Opcode::QUERY()) {
  406. // Unsupported opcode.
  407. LOG_DEBUG(resolver_logger, RESOLVER_DBG_PROCESS,
  408. RESOLVER_UNSUPPORTED_OPCODE).arg(query_message->getOpcode());
  409. makeErrorMessage(query_message, answer_message,
  410. buffer, Rcode::NOTIMP());
  411. } else if (query_message->getRRCount(Message::SECTION_QUESTION) != 1) {
  412. // Not one question
  413. LOG_DEBUG(resolver_logger, RESOLVER_DBG_PROCESS,
  414. RESOLVER_NOT_ONE_QUESTION)
  415. .arg(query_message->getRRCount(Message::SECTION_QUESTION));
  416. makeErrorMessage(query_message, answer_message, buffer,
  417. Rcode::FORMERR());
  418. } else {
  419. const ResolverImpl::NormalQueryResult result =
  420. impl_->processNormalQuery(io_message, query_message,
  421. answer_message, buffer, server);
  422. if (result == ResolverImpl::RECURSION) {
  423. // The RecursiveQuery object will post the "resume" event to the
  424. // DNSServer when an answer arrives, so we don't have to do it now.
  425. return;
  426. } else if (result == ResolverImpl::DROPPED) {
  427. send_answer = false;
  428. }
  429. }
  430. server->resume(send_answer);
  431. }
  432. void
  433. ResolverImpl::resolve(const QuestionPtr& question,
  434. const isc::resolve::ResolverInterface::CallbackPtr& callback)
  435. {
  436. rec_query_->resolve(question, callback);
  437. }
  438. ResolverImpl::NormalQueryResult
  439. ResolverImpl::processNormalQuery(const IOMessage& io_message,
  440. MessagePtr query_message,
  441. MessagePtr answer_message,
  442. OutputBufferPtr buffer,
  443. DNSServer* server)
  444. {
  445. const ConstQuestionPtr question = *query_message->beginQuestion();
  446. const RRType qtype = question->getType();
  447. const RRClass qclass = question->getClass();
  448. // Apply query ACL
  449. const Client client(io_message);
  450. const BasicAction query_action(
  451. getQueryACL().execute(acl::dns::RequestContext(
  452. client.getRequestSourceIPAddress(),
  453. query_message->getTSIGRecord())));
  454. if (query_action == isc::acl::REJECT) {
  455. LOG_INFO(resolver_logger, RESOLVER_QUERY_REJECTED)
  456. .arg(question->getName()).arg(qtype).arg(qclass).arg(client);
  457. makeErrorMessage(query_message, answer_message, buffer,
  458. Rcode::REFUSED());
  459. return (ERROR);
  460. } else if (query_action == isc::acl::DROP) {
  461. LOG_INFO(resolver_logger, RESOLVER_QUERY_DROPPED)
  462. .arg(question->getName()).arg(qtype).arg(qclass).arg(client);
  463. return (DROPPED);
  464. }
  465. LOG_DEBUG(resolver_logger, RESOLVER_DBG_IO, RESOLVER_QUERY_ACCEPTED)
  466. .arg(question->getName()).arg(qtype).arg(question->getClass())
  467. .arg(client);
  468. // ACL passed. Reject inappropriate queries for the resolver.
  469. if (qtype == RRType::AXFR()) {
  470. if (io_message.getSocket().getProtocol() == IPPROTO_UDP) {
  471. // Can't process AXFR request received over UDP
  472. LOG_DEBUG(resolver_logger, RESOLVER_DBG_PROCESS, RESOLVER_AXFR_UDP);
  473. makeErrorMessage(query_message, answer_message, buffer,
  474. Rcode::FORMERR());
  475. } else {
  476. // ... or over TCP for that matter
  477. LOG_DEBUG(resolver_logger, RESOLVER_DBG_PROCESS, RESOLVER_AXFR_TCP);
  478. makeErrorMessage(query_message, answer_message, buffer,
  479. Rcode::NOTIMP());
  480. }
  481. return (ERROR);
  482. } else if (qtype == RRType::IXFR()) {
  483. // Can't process IXFR request
  484. LOG_DEBUG(resolver_logger, RESOLVER_DBG_PROCESS, RESOLVER_IXFR);
  485. makeErrorMessage(query_message, answer_message, buffer,
  486. Rcode::NOTIMP());
  487. return (ERROR);
  488. } else if (qclass != RRClass::IN()) {
  489. // Non-IN message received, refuse it.
  490. LOG_DEBUG(resolver_logger, RESOLVER_DBG_PROCESS, RESOLVER_NON_IN_PACKET)
  491. .arg(question->getClass());
  492. makeErrorMessage(query_message, answer_message, buffer,
  493. Rcode::REFUSED());
  494. return (ERROR);
  495. }
  496. // Everything is okay. Start resolver.
  497. if (upstream_.empty()) {
  498. // Processing normal query
  499. LOG_DEBUG(resolver_logger, RESOLVER_DBG_IO, RESOLVER_NORMAL_QUERY);
  500. rec_query_->resolve(*question, answer_message, buffer, server);
  501. } else {
  502. // Processing forward query
  503. LOG_DEBUG(resolver_logger, RESOLVER_DBG_IO, RESOLVER_FORWARD_QUERY);
  504. rec_query_->forward(query_message, answer_message, buffer, server);
  505. }
  506. return (RECURSION);
  507. }
  508. ConstElementPtr
  509. Resolver::updateConfig(ConstElementPtr config) {
  510. LOG_DEBUG(resolver_logger, RESOLVER_DBG_CONFIG, RESOLVER_CONFIG_UPDATED)
  511. .arg(*config);
  512. try {
  513. // Parse forward_addresses
  514. ConstElementPtr rootAddressesE(config->get("root_addresses"));
  515. AddressList rootAddresses(parseAddresses(rootAddressesE,
  516. "root_addresses"));
  517. ConstElementPtr forwardAddressesE(config->get("forward_addresses"));
  518. AddressList forwardAddresses(parseAddresses(forwardAddressesE,
  519. "forward_addresses"));
  520. ConstElementPtr listenAddressesE(config->get("listen_on"));
  521. AddressList listenAddresses(parseAddresses(listenAddressesE,
  522. "listen_on"));
  523. const ConstElementPtr query_acl_cfg(config->get("query_acl"));
  524. const shared_ptr<const RequestACL> query_acl =
  525. query_acl_cfg ? acl::dns::getRequestLoader().load(query_acl_cfg) :
  526. shared_ptr<RequestACL>();
  527. bool set_timeouts(false);
  528. int qtimeout = impl_->query_timeout_;
  529. int ctimeout = impl_->client_timeout_;
  530. int ltimeout = impl_->lookup_timeout_;
  531. unsigned retries = impl_->retries_;
  532. ConstElementPtr qtimeoutE(config->get("timeout_query")),
  533. ctimeoutE(config->get("timeout_client")),
  534. ltimeoutE(config->get("timeout_lookup")),
  535. retriesE(config->get("retries"));
  536. if (qtimeoutE) {
  537. // It should be safe to just get it, the config manager should
  538. // check for us
  539. qtimeout = qtimeoutE->intValue();
  540. if (qtimeout < -1) {
  541. LOG_ERROR(resolver_logger, RESOLVER_QUERY_TIME_SMALL)
  542. .arg(qtimeout);
  543. isc_throw(BadValue, "Query timeout too small");
  544. }
  545. set_timeouts = true;
  546. }
  547. if (ctimeoutE) {
  548. ctimeout = ctimeoutE->intValue();
  549. if (ctimeout < -1) {
  550. LOG_ERROR(resolver_logger, RESOLVER_CLIENT_TIME_SMALL)
  551. .arg(ctimeout);
  552. isc_throw(BadValue, "Client timeout too small");
  553. }
  554. set_timeouts = true;
  555. }
  556. if (ltimeoutE) {
  557. ltimeout = ltimeoutE->intValue();
  558. if (ltimeout < -1) {
  559. LOG_ERROR(resolver_logger, RESOLVER_LOOKUP_TIME_SMALL)
  560. .arg(ltimeout);
  561. isc_throw(BadValue, "Lookup timeout too small");
  562. }
  563. set_timeouts = true;
  564. }
  565. if (retriesE) {
  566. // Do the assignment from "retriesE->intValue()" to "retries"
  567. // _after_ the comparison (as opposed to before it for the timeouts)
  568. // because "retries" is unsigned.
  569. if (retriesE->intValue() < 0) {
  570. LOG_ERROR(resolver_logger, RESOLVER_NEGATIVE_RETRIES)
  571. .arg(retriesE->intValue());
  572. isc_throw(BadValue, "Negative number of retries");
  573. }
  574. retries = retriesE->intValue();
  575. set_timeouts = true;
  576. }
  577. // Everything OK, so commit the changes
  578. // listenAddresses can fail to bind, so try them first
  579. bool need_query_restart = false;
  580. if (listenAddressesE) {
  581. setListenAddresses(listenAddresses);
  582. need_query_restart = true;
  583. }
  584. if (forwardAddressesE) {
  585. setForwardAddresses(forwardAddresses);
  586. need_query_restart = true;
  587. }
  588. if (rootAddressesE) {
  589. setRootAddresses(rootAddresses);
  590. need_query_restart = true;
  591. }
  592. if (set_timeouts) {
  593. setTimeouts(qtimeout, ctimeout, ltimeout, retries);
  594. need_query_restart = true;
  595. }
  596. if (query_acl) {
  597. setQueryACL(query_acl);
  598. }
  599. if (need_query_restart) {
  600. impl_->queryShutdown();
  601. impl_->querySetup(*dnss_, *nsas_, *cache_);
  602. }
  603. setConfigured();
  604. return (isc::config::createAnswer());
  605. } catch (const isc::Exception& error) {
  606. // Configuration error
  607. LOG_ERROR(resolver_logger, RESOLVER_CONFIG_ERROR).arg(error.what());
  608. return (isc::config::createAnswer(1, error.what()));
  609. }
  610. }
  611. void
  612. Resolver::setForwardAddresses(const AddressList& addresses)
  613. {
  614. impl_->setForwardAddresses(addresses, dnss_);
  615. }
  616. void
  617. Resolver::setRootAddresses(const AddressList& addresses)
  618. {
  619. impl_->setRootAddresses(addresses, dnss_);
  620. }
  621. bool
  622. Resolver::isForwarding() const {
  623. return (!impl_->upstream_.empty());
  624. }
  625. AddressList
  626. Resolver::getForwardAddresses() const {
  627. return (impl_->upstream_);
  628. }
  629. AddressList
  630. Resolver::getRootAddresses() const {
  631. return (impl_->upstream_root_);
  632. }
  633. void
  634. Resolver::setListenAddresses(const AddressList& addresses) {
  635. installListenAddresses(addresses, impl_->listen_, *dnss_);
  636. }
  637. void
  638. Resolver::setTimeouts(int query_timeout, int client_timeout,
  639. int lookup_timeout, unsigned retries) {
  640. LOG_DEBUG(resolver_logger, RESOLVER_DBG_CONFIG, RESOLVER_SET_PARAMS)
  641. .arg(query_timeout).arg(client_timeout).arg(lookup_timeout)
  642. .arg(retries);
  643. impl_->query_timeout_ = query_timeout;
  644. impl_->client_timeout_ = client_timeout;
  645. impl_->lookup_timeout_ = lookup_timeout;
  646. impl_->retries_ = retries;
  647. }
  648. int
  649. Resolver::getQueryTimeout() const {
  650. return impl_->query_timeout_;
  651. }
  652. int
  653. Resolver::getClientTimeout() const {
  654. return impl_->client_timeout_;
  655. }
  656. int
  657. Resolver::getLookupTimeout() const {
  658. return impl_->lookup_timeout_;
  659. }
  660. int
  661. Resolver::getRetries() const {
  662. return impl_->retries_;
  663. }
  664. AddressList
  665. Resolver::getListenAddresses() const {
  666. return (impl_->listen_);
  667. }
  668. const RequestACL&
  669. Resolver::getQueryACL() const {
  670. return (impl_->getQueryACL());
  671. }
  672. void
  673. Resolver::setQueryACL(shared_ptr<const RequestACL> new_acl) {
  674. if (!new_acl) {
  675. isc_throw(InvalidParameter, "NULL pointer is passed to setQueryACL");
  676. }
  677. LOG_INFO(resolver_logger, RESOLVER_SET_QUERY_ACL);
  678. impl_->setQueryACL(new_acl);
  679. }