resolver.cc 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771
  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 <sys/types.h>
  17. #include <netinet/in.h>
  18. #include <algorithm>
  19. #include <vector>
  20. #include <cassert>
  21. #include <boost/shared_ptr.hpp>
  22. #include <boost/foreach.hpp>
  23. #include <exceptions/exceptions.h>
  24. #include <acl/dns.h>
  25. #include <acl/loader.h>
  26. #include <asiodns/asiodns.h>
  27. #include <asiolink/asiolink.h>
  28. #include <config/ccsession.h>
  29. #include <exceptions/exceptions.h>
  30. #include <util/buffer.h>
  31. #include <dns/opcode.h>
  32. #include <dns/rcode.h>
  33. #include <dns/exceptions.h>
  34. #include <dns/name.h>
  35. #include <dns/question.h>
  36. #include <dns/rrset.h>
  37. #include <dns/rrttl.h>
  38. #include <dns/message.h>
  39. #include <dns/messagerenderer.h>
  40. #include <server_common/client.h>
  41. #include <server_common/portconfig.h>
  42. #include <resolve/recursive_query.h>
  43. #include "resolver.h"
  44. #include "resolver_log.h"
  45. using namespace std;
  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(DNSServiceBase& 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. DNSServiceBase* dnss)
  105. {
  106. upstream_ = upstream;
  107. if (dnss != NULL) {
  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. DNSServiceBase* dnss)
  120. {
  121. upstream_root_ = upstream_root;
  122. if (dnss != NULL) {
  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(boost::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. boost::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;
  220. renderer.setBuffer(buffer.get());
  221. message->toWire(renderer);
  222. }
  223. // This is a derived class of \c DNSLookup, to serve as a
  224. // callback in the asiolink module. It calls
  225. // Resolver::processMessage() on a single DNS message.
  226. class MessageLookup : public DNSLookup {
  227. public:
  228. MessageLookup(Resolver* srv) : server_(srv) {}
  229. // \brief Handle the DNS Lookup
  230. virtual void operator()(const IOMessage& io_message,
  231. MessagePtr query_message,
  232. MessagePtr answer_message,
  233. OutputBufferPtr buffer,
  234. DNSServer* server) const
  235. {
  236. server_->processMessage(io_message, query_message,
  237. answer_message, buffer, server);
  238. }
  239. private:
  240. Resolver* server_;
  241. };
  242. // This is a derived class of \c DNSAnswer, to serve as a
  243. // callback in the asiolink module. It takes a completed
  244. // set of answer data from the DNS lookup and assembles it
  245. // into a wire-format response.
  246. class MessageAnswer : public DNSAnswer {
  247. public:
  248. virtual void operator()(const IOMessage& io_message,
  249. MessagePtr query_message,
  250. MessagePtr answer_message,
  251. OutputBufferPtr buffer) const
  252. {
  253. const qid_t qid = query_message->getQid();
  254. const bool rd = query_message->getHeaderFlag(Message::HEADERFLAG_RD);
  255. const bool cd = query_message->getHeaderFlag(Message::HEADERFLAG_CD);
  256. // The opcode and question section should have already been set,
  257. // fill in the final details of the answer message
  258. answer_message->setQid(qid);
  259. answer_message->setHeaderFlag(Message::HEADERFLAG_QR);
  260. answer_message->setHeaderFlag(Message::HEADERFLAG_RA);
  261. answer_message->setHeaderFlag(Message::HEADERFLAG_RD, rd);
  262. answer_message->setHeaderFlag(Message::HEADERFLAG_CD, cd);
  263. // Now we can clear the buffer and render the new message into it
  264. buffer->clear();
  265. MessageRenderer renderer;
  266. renderer.setBuffer(buffer.get());
  267. ConstEDNSPtr edns(query_message->getEDNS());
  268. const bool dnssec_ok = edns && edns->getDNSSECAwareness();
  269. if (edns) {
  270. EDNSPtr edns_response(new EDNS());
  271. edns_response->setDNSSECAwareness(dnssec_ok);
  272. // TODO: We should make our own edns bufsize length configurable
  273. edns_response->setUDPSize(Message::DEFAULT_MAX_EDNS0_UDPSIZE);
  274. answer_message->setEDNS(edns_response);
  275. }
  276. if (io_message.getSocket().getProtocol() == IPPROTO_UDP) {
  277. if (edns) {
  278. renderer.setLengthLimit(edns->getUDPSize());
  279. } else {
  280. renderer.setLengthLimit(Message::DEFAULT_MAX_UDPSIZE);
  281. }
  282. } else {
  283. renderer.setLengthLimit(65535);
  284. }
  285. answer_message->toWire(renderer);
  286. renderer.setBuffer(NULL);
  287. LOG_DEBUG(resolver_logger, RESOLVER_DBG_DETAIL,
  288. RESOLVER_DNS_MESSAGE_SENT)
  289. .arg(renderer.getLength()).arg(*answer_message);
  290. }
  291. };
  292. Resolver::Resolver() :
  293. impl_(new ResolverImpl()),
  294. dnss_(NULL),
  295. dns_lookup_(NULL),
  296. dns_answer_(new MessageAnswer),
  297. nsas_(NULL),
  298. cache_(NULL)
  299. {
  300. // Operations referring to "this" must be done in the constructor body
  301. // (some compilers will issue warnings if "this" is referred to in the
  302. // initialization list).
  303. dns_lookup_ = new MessageLookup(this);
  304. }
  305. Resolver::~Resolver() {
  306. delete impl_;
  307. delete dns_lookup_;
  308. delete dns_answer_;
  309. }
  310. void
  311. Resolver::setDNSService(isc::asiodns::DNSServiceBase& dnss) {
  312. dnss_ = &dnss;
  313. }
  314. void
  315. Resolver::setNameserverAddressStore(isc::nsas::NameserverAddressStore& nsas)
  316. {
  317. nsas_ = &nsas;
  318. }
  319. void
  320. Resolver::setCache(isc::cache::ResolverCache& cache)
  321. {
  322. cache_ = &cache;
  323. }
  324. void
  325. Resolver::setConfigSession(ModuleCCSession* config_session) {
  326. impl_->config_session_ = config_session;
  327. }
  328. ModuleCCSession*
  329. Resolver::getConfigSession() const {
  330. return (impl_->config_session_);
  331. }
  332. void
  333. Resolver::resolve(const isc::dns::QuestionPtr& question,
  334. const isc::resolve::ResolverInterface::CallbackPtr& callback)
  335. {
  336. impl_->resolve(question, callback);
  337. }
  338. void
  339. Resolver::processMessage(const IOMessage& io_message,
  340. MessagePtr query_message,
  341. MessagePtr answer_message,
  342. OutputBufferPtr buffer,
  343. DNSServer* server)
  344. {
  345. InputBuffer request_buffer(io_message.getData(), io_message.getDataSize());
  346. // First, check the header part. If we fail even for the base header,
  347. // just drop the message.
  348. // In the following code, the debug output is such that there should only be
  349. // one debug message if packet processing failed. There could be two if
  350. // it succeeded.
  351. try {
  352. query_message->parseHeader(request_buffer);
  353. // Ignore all responses.
  354. if (query_message->getHeaderFlag(Message::HEADERFLAG_QR)) {
  355. LOG_DEBUG(resolver_logger, RESOLVER_DBG_IO,
  356. RESOLVER_UNEXPECTED_RESPONSE);
  357. server->resume(false);
  358. return;
  359. }
  360. } catch (const isc::Exception& ex) {
  361. LOG_DEBUG(resolver_logger, RESOLVER_DBG_IO,
  362. RESOLVER_HEADER_PROCESSING_FAILED).arg(ex.what());
  363. server->resume(false);
  364. return;
  365. }
  366. // Parse the message. On failure, return an appropriate error.
  367. try {
  368. query_message->fromWire(request_buffer);
  369. } catch (const DNSProtocolError& error) {
  370. LOG_DEBUG(resolver_logger, RESOLVER_DBG_IO,
  371. RESOLVER_PROTOCOL_BODY_PARSE_FAILED)
  372. .arg(error.what()).arg(error.getRcode());
  373. makeErrorMessage(query_message, answer_message,
  374. buffer, error.getRcode());
  375. server->resume(true);
  376. return;
  377. } catch (const isc::Exception& ex) {
  378. LOG_DEBUG(resolver_logger, RESOLVER_DBG_IO,
  379. RESOLVER_MESSAGE_PROCESSING_FAILED)
  380. .arg(ex.what()).arg(Rcode::SERVFAIL());
  381. makeErrorMessage(query_message, answer_message,
  382. buffer, Rcode::SERVFAIL());
  383. server->resume(true);
  384. return;
  385. } // Other exceptions will be handled at a higher layer.
  386. // Note: there appears to be no LOG_DEBUG for a successfully-received
  387. // message. This is not an oversight - it is handled below. In the
  388. // meantime, output the full message for debug purposes (if requested).
  389. LOG_DEBUG(resolver_logger, RESOLVER_DBG_DETAIL,
  390. RESOLVER_DNS_MESSAGE_RECEIVED).arg(*query_message);
  391. // Perform further protocol-level validation.
  392. bool send_answer = true;
  393. if (query_message->getOpcode() == Opcode::NOTIFY()) {
  394. makeErrorMessage(query_message, answer_message,
  395. buffer, Rcode::NOTAUTH());
  396. // Notify arrived, but we are not authoritative.
  397. LOG_DEBUG(resolver_logger, RESOLVER_DBG_PROCESS,
  398. RESOLVER_NOTIFY_RECEIVED);
  399. } else if (query_message->getOpcode() != Opcode::QUERY()) {
  400. // Unsupported opcode.
  401. LOG_DEBUG(resolver_logger, RESOLVER_DBG_PROCESS,
  402. RESOLVER_UNSUPPORTED_OPCODE).arg(query_message->getOpcode());
  403. makeErrorMessage(query_message, answer_message,
  404. buffer, Rcode::NOTIMP());
  405. } else if (query_message->getRRCount(Message::SECTION_QUESTION) != 1) {
  406. // Not one question
  407. LOG_DEBUG(resolver_logger, RESOLVER_DBG_PROCESS,
  408. RESOLVER_NOT_ONE_QUESTION)
  409. .arg(query_message->getRRCount(Message::SECTION_QUESTION));
  410. makeErrorMessage(query_message, answer_message, buffer,
  411. Rcode::FORMERR());
  412. } else {
  413. const ResolverImpl::NormalQueryResult result =
  414. impl_->processNormalQuery(io_message, query_message,
  415. answer_message, buffer, server);
  416. if (result == ResolverImpl::RECURSION) {
  417. // The RecursiveQuery object will post the "resume" event to the
  418. // DNSServer when an answer arrives, so we don't have to do it now.
  419. return;
  420. } else if (result == ResolverImpl::DROPPED) {
  421. send_answer = false;
  422. }
  423. }
  424. server->resume(send_answer);
  425. }
  426. void
  427. ResolverImpl::resolve(const QuestionPtr& question,
  428. const isc::resolve::ResolverInterface::CallbackPtr& callback)
  429. {
  430. rec_query_->resolve(question, callback);
  431. }
  432. ResolverImpl::NormalQueryResult
  433. ResolverImpl::processNormalQuery(const IOMessage& io_message,
  434. MessagePtr query_message,
  435. MessagePtr answer_message,
  436. OutputBufferPtr buffer,
  437. DNSServer* server)
  438. {
  439. const ConstQuestionPtr question = *query_message->beginQuestion();
  440. const RRType qtype = question->getType();
  441. // Make cppcheck happy with the reference.
  442. const RRClass& qclass = question->getClass();
  443. // Apply query ACL
  444. const Client client(io_message);
  445. const BasicAction query_action(
  446. getQueryACL().execute(acl::dns::RequestContext(
  447. client.getRequestSourceIPAddress(),
  448. query_message->getTSIGRecord())));
  449. if (query_action == isc::acl::REJECT) {
  450. LOG_INFO(resolver_logger, RESOLVER_QUERY_REJECTED)
  451. .arg(question->getName()).arg(qtype).arg(qclass).arg(client);
  452. makeErrorMessage(query_message, answer_message, buffer,
  453. Rcode::REFUSED());
  454. return (ERROR);
  455. } else if (query_action == isc::acl::DROP) {
  456. LOG_INFO(resolver_logger, RESOLVER_QUERY_DROPPED)
  457. .arg(question->getName()).arg(qtype).arg(qclass).arg(client);
  458. return (DROPPED);
  459. }
  460. LOG_DEBUG(resolver_logger, RESOLVER_DBG_IO, RESOLVER_QUERY_ACCEPTED)
  461. .arg(question->getName()).arg(qtype).arg(question->getClass())
  462. .arg(client);
  463. // ACL passed. Reject inappropriate queries for the resolver.
  464. if (qtype == RRType::AXFR()) {
  465. if (io_message.getSocket().getProtocol() == IPPROTO_UDP) {
  466. // Can't process AXFR request received over UDP
  467. LOG_DEBUG(resolver_logger, RESOLVER_DBG_PROCESS, RESOLVER_AXFR_UDP);
  468. makeErrorMessage(query_message, answer_message, buffer,
  469. Rcode::FORMERR());
  470. } else {
  471. // ... or over TCP for that matter
  472. LOG_DEBUG(resolver_logger, RESOLVER_DBG_PROCESS, RESOLVER_AXFR_TCP);
  473. makeErrorMessage(query_message, answer_message, buffer,
  474. Rcode::NOTIMP());
  475. }
  476. return (ERROR);
  477. } else if (qtype == RRType::IXFR()) {
  478. // Can't process IXFR request
  479. LOG_DEBUG(resolver_logger, RESOLVER_DBG_PROCESS, RESOLVER_IXFR);
  480. makeErrorMessage(query_message, answer_message, buffer,
  481. Rcode::NOTIMP());
  482. return (ERROR);
  483. } else if (qclass != RRClass::IN()) {
  484. // Non-IN message received, refuse it.
  485. LOG_DEBUG(resolver_logger, RESOLVER_DBG_PROCESS, RESOLVER_NON_IN_PACKET)
  486. .arg(question->getClass());
  487. makeErrorMessage(query_message, answer_message, buffer,
  488. Rcode::REFUSED());
  489. return (ERROR);
  490. }
  491. // Everything is okay. Start resolver.
  492. if (upstream_.empty()) {
  493. // Processing normal query
  494. LOG_DEBUG(resolver_logger, RESOLVER_DBG_IO, RESOLVER_NORMAL_QUERY);
  495. rec_query_->resolve(*question, answer_message, buffer, server);
  496. } else {
  497. // Processing forward query
  498. LOG_DEBUG(resolver_logger, RESOLVER_DBG_IO, RESOLVER_FORWARD_QUERY);
  499. rec_query_->forward(query_message, answer_message, buffer, server);
  500. }
  501. return (RECURSION);
  502. }
  503. ConstElementPtr
  504. Resolver::updateConfig(ConstElementPtr config, bool startup) {
  505. LOG_DEBUG(resolver_logger, RESOLVER_DBG_CONFIG, RESOLVER_CONFIG_UPDATED)
  506. .arg(*config);
  507. try {
  508. // Parse forward_addresses
  509. ConstElementPtr rootAddressesE(config->get("root_addresses"));
  510. AddressList rootAddresses(parseAddresses(rootAddressesE,
  511. "root_addresses"));
  512. ConstElementPtr forwardAddressesE(config->get("forward_addresses"));
  513. AddressList forwardAddresses(parseAddresses(forwardAddressesE,
  514. "forward_addresses"));
  515. ConstElementPtr listenAddressesE(config->get("listen_on"));
  516. AddressList listenAddresses(parseAddresses(listenAddressesE,
  517. "listen_on"));
  518. const ConstElementPtr query_acl_cfg(config->get("query_acl"));
  519. const boost::shared_ptr<const RequestACL> query_acl =
  520. query_acl_cfg ? acl::dns::getRequestLoader().load(query_acl_cfg) :
  521. boost::shared_ptr<RequestACL>();
  522. bool set_timeouts(false);
  523. int qtimeout = impl_->query_timeout_;
  524. int ctimeout = impl_->client_timeout_;
  525. int ltimeout = impl_->lookup_timeout_;
  526. unsigned retries = impl_->retries_;
  527. ConstElementPtr qtimeoutE(config->get("timeout_query")),
  528. ctimeoutE(config->get("timeout_client")),
  529. ltimeoutE(config->get("timeout_lookup")),
  530. retriesE(config->get("retries"));
  531. if (qtimeoutE) {
  532. // It should be safe to just get it, the config manager should
  533. // check for us
  534. qtimeout = qtimeoutE->intValue();
  535. if (qtimeout < -1) {
  536. LOG_ERROR(resolver_logger, RESOLVER_QUERY_TIME_SMALL)
  537. .arg(qtimeout);
  538. isc_throw(BadValue, "Query timeout too small");
  539. }
  540. set_timeouts = true;
  541. }
  542. if (ctimeoutE) {
  543. ctimeout = ctimeoutE->intValue();
  544. if (ctimeout < -1) {
  545. LOG_ERROR(resolver_logger, RESOLVER_CLIENT_TIME_SMALL)
  546. .arg(ctimeout);
  547. isc_throw(BadValue, "Client timeout too small");
  548. }
  549. set_timeouts = true;
  550. }
  551. if (ltimeoutE) {
  552. ltimeout = ltimeoutE->intValue();
  553. if (ltimeout < -1) {
  554. LOG_ERROR(resolver_logger, RESOLVER_LOOKUP_TIME_SMALL)
  555. .arg(ltimeout);
  556. isc_throw(BadValue, "Lookup timeout too small");
  557. }
  558. set_timeouts = true;
  559. }
  560. if (retriesE) {
  561. // Do the assignment from "retriesE->intValue()" to "retries"
  562. // _after_ the comparison (as opposed to before it for the timeouts)
  563. // because "retries" is unsigned.
  564. if (retriesE->intValue() < 0) {
  565. LOG_ERROR(resolver_logger, RESOLVER_NEGATIVE_RETRIES)
  566. .arg(retriesE->intValue());
  567. isc_throw(BadValue, "Negative number of retries");
  568. }
  569. retries = retriesE->intValue();
  570. set_timeouts = true;
  571. }
  572. // Everything OK, so commit the changes
  573. // listenAddresses can fail to bind, so try them first
  574. bool need_query_restart = false;
  575. if (!startup && listenAddressesE) {
  576. setListenAddresses(listenAddresses);
  577. need_query_restart = true;
  578. }
  579. if (forwardAddressesE) {
  580. setForwardAddresses(forwardAddresses);
  581. need_query_restart = true;
  582. }
  583. if (rootAddressesE) {
  584. setRootAddresses(rootAddresses);
  585. need_query_restart = true;
  586. }
  587. if (set_timeouts) {
  588. setTimeouts(qtimeout, ctimeout, ltimeout, retries);
  589. need_query_restart = true;
  590. }
  591. if (query_acl) {
  592. setQueryACL(query_acl);
  593. }
  594. if (startup && listenAddressesE) {
  595. setListenAddresses(listenAddresses);
  596. need_query_restart = true;
  597. }
  598. if (need_query_restart) {
  599. impl_->queryShutdown();
  600. impl_->querySetup(*dnss_, *nsas_, *cache_);
  601. }
  602. return (isc::config::createAnswer());
  603. } catch (const isc::Exception& error) {
  604. // Configuration error
  605. LOG_ERROR(resolver_logger, RESOLVER_CONFIG_ERROR).arg(error.what());
  606. return (isc::config::createAnswer(1, error.what()));
  607. }
  608. }
  609. void
  610. Resolver::setForwardAddresses(const AddressList& addresses)
  611. {
  612. impl_->setForwardAddresses(addresses, dnss_);
  613. }
  614. void
  615. Resolver::setRootAddresses(const AddressList& addresses)
  616. {
  617. impl_->setRootAddresses(addresses, dnss_);
  618. }
  619. bool
  620. Resolver::isForwarding() const {
  621. return (!impl_->upstream_.empty());
  622. }
  623. AddressList
  624. Resolver::getForwardAddresses() const {
  625. return (impl_->upstream_);
  626. }
  627. AddressList
  628. Resolver::getRootAddresses() const {
  629. return (impl_->upstream_root_);
  630. }
  631. void
  632. Resolver::setListenAddresses(const AddressList& addresses) {
  633. installListenAddresses(addresses, impl_->listen_, *dnss_);
  634. }
  635. void
  636. Resolver::setTimeouts(int query_timeout, int client_timeout,
  637. int lookup_timeout, unsigned retries) {
  638. LOG_DEBUG(resolver_logger, RESOLVER_DBG_CONFIG, RESOLVER_SET_PARAMS)
  639. .arg(query_timeout).arg(client_timeout).arg(lookup_timeout)
  640. .arg(retries);
  641. impl_->query_timeout_ = query_timeout;
  642. impl_->client_timeout_ = client_timeout;
  643. impl_->lookup_timeout_ = lookup_timeout;
  644. impl_->retries_ = retries;
  645. }
  646. int
  647. Resolver::getQueryTimeout() const {
  648. return impl_->query_timeout_;
  649. }
  650. int
  651. Resolver::getClientTimeout() const {
  652. return impl_->client_timeout_;
  653. }
  654. int
  655. Resolver::getLookupTimeout() const {
  656. return impl_->lookup_timeout_;
  657. }
  658. int
  659. Resolver::getRetries() const {
  660. return impl_->retries_;
  661. }
  662. AddressList
  663. Resolver::getListenAddresses() const {
  664. return (impl_->listen_);
  665. }
  666. const RequestACL&
  667. Resolver::getQueryACL() const {
  668. return (impl_->getQueryACL());
  669. }
  670. void
  671. Resolver::setQueryACL(boost::shared_ptr<const RequestACL> new_acl) {
  672. if (!new_acl) {
  673. isc_throw(InvalidParameter, "NULL pointer is passed to setQueryACL");
  674. }
  675. LOG_INFO(resolver_logger, RESOLVER_SET_QUERY_ACL);
  676. impl_->setQueryACL(new_acl);
  677. }