resolver.cc 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789
  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. // This is a derived class of \c SimpleCallback, to serve
  293. // as a callback in the asiolink module. It checks for queued
  294. // configuration messages, and executes them if found.
  295. class ConfigCheck : public SimpleCallback {
  296. public:
  297. ConfigCheck(Resolver* srv) : server_(srv) {}
  298. virtual void operator()(const IOMessage&) const {
  299. if (server_->getConfigSession()->hasQueuedMsgs()) {
  300. server_->getConfigSession()->checkCommand();
  301. }
  302. }
  303. private:
  304. Resolver* server_;
  305. };
  306. Resolver::Resolver() :
  307. impl_(new ResolverImpl()),
  308. dnss_(NULL),
  309. checkin_(NULL),
  310. dns_lookup_(NULL),
  311. dns_answer_(new MessageAnswer),
  312. nsas_(NULL),
  313. cache_(NULL)
  314. {
  315. // Operations referring to "this" must be done in the constructor body
  316. // (some compilers will issue warnings if "this" is referred to in the
  317. // initialization list).
  318. checkin_ = new ConfigCheck(this);
  319. dns_lookup_ = new MessageLookup(this);
  320. }
  321. Resolver::~Resolver() {
  322. delete impl_;
  323. delete checkin_;
  324. delete dns_lookup_;
  325. delete dns_answer_;
  326. }
  327. void
  328. Resolver::setDNSService(isc::asiodns::DNSServiceBase& dnss) {
  329. dnss_ = &dnss;
  330. }
  331. void
  332. Resolver::setNameserverAddressStore(isc::nsas::NameserverAddressStore& nsas)
  333. {
  334. nsas_ = &nsas;
  335. }
  336. void
  337. Resolver::setCache(isc::cache::ResolverCache& cache)
  338. {
  339. cache_ = &cache;
  340. }
  341. void
  342. Resolver::setConfigSession(ModuleCCSession* config_session) {
  343. impl_->config_session_ = config_session;
  344. }
  345. ModuleCCSession*
  346. Resolver::getConfigSession() const {
  347. return (impl_->config_session_);
  348. }
  349. void
  350. Resolver::resolve(const isc::dns::QuestionPtr& question,
  351. const isc::resolve::ResolverInterface::CallbackPtr& callback)
  352. {
  353. impl_->resolve(question, callback);
  354. }
  355. void
  356. Resolver::processMessage(const IOMessage& io_message,
  357. MessagePtr query_message,
  358. MessagePtr answer_message,
  359. OutputBufferPtr buffer,
  360. DNSServer* server)
  361. {
  362. InputBuffer request_buffer(io_message.getData(), io_message.getDataSize());
  363. // First, check the header part. If we fail even for the base header,
  364. // just drop the message.
  365. // In the following code, the debug output is such that there should only be
  366. // one debug message if packet processing failed. There could be two if
  367. // it succeeded.
  368. try {
  369. query_message->parseHeader(request_buffer);
  370. // Ignore all responses.
  371. if (query_message->getHeaderFlag(Message::HEADERFLAG_QR)) {
  372. LOG_DEBUG(resolver_logger, RESOLVER_DBG_IO,
  373. RESOLVER_UNEXPECTED_RESPONSE);
  374. server->resume(false);
  375. return;
  376. }
  377. } catch (const Exception& ex) {
  378. LOG_DEBUG(resolver_logger, RESOLVER_DBG_IO,
  379. RESOLVER_HEADER_PROCESSING_FAILED).arg(ex.what());
  380. server->resume(false);
  381. return;
  382. }
  383. // Parse the message. On failure, return an appropriate error.
  384. try {
  385. query_message->fromWire(request_buffer);
  386. } catch (const DNSProtocolError& error) {
  387. LOG_DEBUG(resolver_logger, RESOLVER_DBG_IO,
  388. RESOLVER_PROTOCOL_BODY_PARSE_FAILED)
  389. .arg(error.what()).arg(error.getRcode());
  390. makeErrorMessage(query_message, answer_message,
  391. buffer, error.getRcode());
  392. server->resume(true);
  393. return;
  394. } catch (const Exception& ex) {
  395. LOG_DEBUG(resolver_logger, RESOLVER_DBG_IO,
  396. RESOLVER_MESSAGE_PROCESSING_FAILED)
  397. .arg(ex.what()).arg(Rcode::SERVFAIL());
  398. makeErrorMessage(query_message, answer_message,
  399. buffer, Rcode::SERVFAIL());
  400. server->resume(true);
  401. return;
  402. } // Other exceptions will be handled at a higher layer.
  403. // Note: there appears to be no LOG_DEBUG for a successfully-received
  404. // message. This is not an oversight - it is handled below. In the
  405. // meantime, output the full message for debug purposes (if requested).
  406. LOG_DEBUG(resolver_logger, RESOLVER_DBG_DETAIL,
  407. RESOLVER_DNS_MESSAGE_RECEIVED).arg(*query_message);
  408. // Perform further protocol-level validation.
  409. bool send_answer = true;
  410. if (query_message->getOpcode() == Opcode::NOTIFY()) {
  411. makeErrorMessage(query_message, answer_message,
  412. buffer, Rcode::NOTAUTH());
  413. // Notify arrived, but we are not authoritative.
  414. LOG_DEBUG(resolver_logger, RESOLVER_DBG_PROCESS,
  415. RESOLVER_NOTIFY_RECEIVED);
  416. } else if (query_message->getOpcode() != Opcode::QUERY()) {
  417. // Unsupported opcode.
  418. LOG_DEBUG(resolver_logger, RESOLVER_DBG_PROCESS,
  419. RESOLVER_UNSUPPORTED_OPCODE).arg(query_message->getOpcode());
  420. makeErrorMessage(query_message, answer_message,
  421. buffer, Rcode::NOTIMP());
  422. } else if (query_message->getRRCount(Message::SECTION_QUESTION) != 1) {
  423. // Not one question
  424. LOG_DEBUG(resolver_logger, RESOLVER_DBG_PROCESS,
  425. RESOLVER_NOT_ONE_QUESTION)
  426. .arg(query_message->getRRCount(Message::SECTION_QUESTION));
  427. makeErrorMessage(query_message, answer_message, buffer,
  428. Rcode::FORMERR());
  429. } else {
  430. const ResolverImpl::NormalQueryResult result =
  431. impl_->processNormalQuery(io_message, query_message,
  432. answer_message, buffer, server);
  433. if (result == ResolverImpl::RECURSION) {
  434. // The RecursiveQuery object will post the "resume" event to the
  435. // DNSServer when an answer arrives, so we don't have to do it now.
  436. return;
  437. } else if (result == ResolverImpl::DROPPED) {
  438. send_answer = false;
  439. }
  440. }
  441. server->resume(send_answer);
  442. }
  443. void
  444. ResolverImpl::resolve(const QuestionPtr& question,
  445. const isc::resolve::ResolverInterface::CallbackPtr& callback)
  446. {
  447. rec_query_->resolve(question, callback);
  448. }
  449. ResolverImpl::NormalQueryResult
  450. ResolverImpl::processNormalQuery(const IOMessage& io_message,
  451. MessagePtr query_message,
  452. MessagePtr answer_message,
  453. OutputBufferPtr buffer,
  454. DNSServer* server)
  455. {
  456. const ConstQuestionPtr question = *query_message->beginQuestion();
  457. const RRType qtype = question->getType();
  458. // Make cppcheck happy with the reference.
  459. const RRClass& qclass = question->getClass();
  460. // Apply query ACL
  461. const Client client(io_message);
  462. const BasicAction query_action(
  463. getQueryACL().execute(acl::dns::RequestContext(
  464. client.getRequestSourceIPAddress(),
  465. query_message->getTSIGRecord())));
  466. if (query_action == isc::acl::REJECT) {
  467. LOG_INFO(resolver_logger, RESOLVER_QUERY_REJECTED)
  468. .arg(question->getName()).arg(qtype).arg(qclass).arg(client);
  469. makeErrorMessage(query_message, answer_message, buffer,
  470. Rcode::REFUSED());
  471. return (ERROR);
  472. } else if (query_action == isc::acl::DROP) {
  473. LOG_INFO(resolver_logger, RESOLVER_QUERY_DROPPED)
  474. .arg(question->getName()).arg(qtype).arg(qclass).arg(client);
  475. return (DROPPED);
  476. }
  477. LOG_DEBUG(resolver_logger, RESOLVER_DBG_IO, RESOLVER_QUERY_ACCEPTED)
  478. .arg(question->getName()).arg(qtype).arg(question->getClass())
  479. .arg(client);
  480. // ACL passed. Reject inappropriate queries for the resolver.
  481. if (qtype == RRType::AXFR()) {
  482. if (io_message.getSocket().getProtocol() == IPPROTO_UDP) {
  483. // Can't process AXFR request received over UDP
  484. LOG_DEBUG(resolver_logger, RESOLVER_DBG_PROCESS, RESOLVER_AXFR_UDP);
  485. makeErrorMessage(query_message, answer_message, buffer,
  486. Rcode::FORMERR());
  487. } else {
  488. // ... or over TCP for that matter
  489. LOG_DEBUG(resolver_logger, RESOLVER_DBG_PROCESS, RESOLVER_AXFR_TCP);
  490. makeErrorMessage(query_message, answer_message, buffer,
  491. Rcode::NOTIMP());
  492. }
  493. return (ERROR);
  494. } else if (qtype == RRType::IXFR()) {
  495. // Can't process IXFR request
  496. LOG_DEBUG(resolver_logger, RESOLVER_DBG_PROCESS, RESOLVER_IXFR);
  497. makeErrorMessage(query_message, answer_message, buffer,
  498. Rcode::NOTIMP());
  499. return (ERROR);
  500. } else if (qclass != RRClass::IN()) {
  501. // Non-IN message received, refuse it.
  502. LOG_DEBUG(resolver_logger, RESOLVER_DBG_PROCESS, RESOLVER_NON_IN_PACKET)
  503. .arg(question->getClass());
  504. makeErrorMessage(query_message, answer_message, buffer,
  505. Rcode::REFUSED());
  506. return (ERROR);
  507. }
  508. // Everything is okay. Start resolver.
  509. if (upstream_.empty()) {
  510. // Processing normal query
  511. LOG_DEBUG(resolver_logger, RESOLVER_DBG_IO, RESOLVER_NORMAL_QUERY);
  512. rec_query_->resolve(*question, answer_message, buffer, server);
  513. } else {
  514. // Processing forward query
  515. LOG_DEBUG(resolver_logger, RESOLVER_DBG_IO, RESOLVER_FORWARD_QUERY);
  516. rec_query_->forward(query_message, answer_message, buffer, server);
  517. }
  518. return (RECURSION);
  519. }
  520. ConstElementPtr
  521. Resolver::updateConfig(ConstElementPtr config, bool startup) {
  522. LOG_DEBUG(resolver_logger, RESOLVER_DBG_CONFIG, RESOLVER_CONFIG_UPDATED)
  523. .arg(*config);
  524. try {
  525. // Parse forward_addresses
  526. ConstElementPtr rootAddressesE(config->get("root_addresses"));
  527. AddressList rootAddresses(parseAddresses(rootAddressesE,
  528. "root_addresses"));
  529. ConstElementPtr forwardAddressesE(config->get("forward_addresses"));
  530. AddressList forwardAddresses(parseAddresses(forwardAddressesE,
  531. "forward_addresses"));
  532. ConstElementPtr listenAddressesE(config->get("listen_on"));
  533. AddressList listenAddresses(parseAddresses(listenAddressesE,
  534. "listen_on"));
  535. const ConstElementPtr query_acl_cfg(config->get("query_acl"));
  536. const boost::shared_ptr<const RequestACL> query_acl =
  537. query_acl_cfg ? acl::dns::getRequestLoader().load(query_acl_cfg) :
  538. boost::shared_ptr<RequestACL>();
  539. bool set_timeouts(false);
  540. int qtimeout = impl_->query_timeout_;
  541. int ctimeout = impl_->client_timeout_;
  542. int ltimeout = impl_->lookup_timeout_;
  543. unsigned retries = impl_->retries_;
  544. ConstElementPtr qtimeoutE(config->get("timeout_query")),
  545. ctimeoutE(config->get("timeout_client")),
  546. ltimeoutE(config->get("timeout_lookup")),
  547. retriesE(config->get("retries"));
  548. if (qtimeoutE) {
  549. // It should be safe to just get it, the config manager should
  550. // check for us
  551. qtimeout = qtimeoutE->intValue();
  552. if (qtimeout < -1) {
  553. LOG_ERROR(resolver_logger, RESOLVER_QUERY_TIME_SMALL)
  554. .arg(qtimeout);
  555. isc_throw(BadValue, "Query timeout too small");
  556. }
  557. set_timeouts = true;
  558. }
  559. if (ctimeoutE) {
  560. ctimeout = ctimeoutE->intValue();
  561. if (ctimeout < -1) {
  562. LOG_ERROR(resolver_logger, RESOLVER_CLIENT_TIME_SMALL)
  563. .arg(ctimeout);
  564. isc_throw(BadValue, "Client timeout too small");
  565. }
  566. set_timeouts = true;
  567. }
  568. if (ltimeoutE) {
  569. ltimeout = ltimeoutE->intValue();
  570. if (ltimeout < -1) {
  571. LOG_ERROR(resolver_logger, RESOLVER_LOOKUP_TIME_SMALL)
  572. .arg(ltimeout);
  573. isc_throw(BadValue, "Lookup timeout too small");
  574. }
  575. set_timeouts = true;
  576. }
  577. if (retriesE) {
  578. // Do the assignment from "retriesE->intValue()" to "retries"
  579. // _after_ the comparison (as opposed to before it for the timeouts)
  580. // because "retries" is unsigned.
  581. if (retriesE->intValue() < 0) {
  582. LOG_ERROR(resolver_logger, RESOLVER_NEGATIVE_RETRIES)
  583. .arg(retriesE->intValue());
  584. isc_throw(BadValue, "Negative number of retries");
  585. }
  586. retries = retriesE->intValue();
  587. set_timeouts = true;
  588. }
  589. // Everything OK, so commit the changes
  590. // listenAddresses can fail to bind, so try them first
  591. bool need_query_restart = false;
  592. if (!startup && listenAddressesE) {
  593. setListenAddresses(listenAddresses);
  594. need_query_restart = true;
  595. }
  596. if (forwardAddressesE) {
  597. setForwardAddresses(forwardAddresses);
  598. need_query_restart = true;
  599. }
  600. if (rootAddressesE) {
  601. setRootAddresses(rootAddresses);
  602. need_query_restart = true;
  603. }
  604. if (set_timeouts) {
  605. setTimeouts(qtimeout, ctimeout, ltimeout, retries);
  606. need_query_restart = true;
  607. }
  608. if (query_acl) {
  609. setQueryACL(query_acl);
  610. }
  611. if (startup && listenAddressesE) {
  612. setListenAddresses(listenAddresses);
  613. need_query_restart = true;
  614. }
  615. if (need_query_restart) {
  616. impl_->queryShutdown();
  617. impl_->querySetup(*dnss_, *nsas_, *cache_);
  618. }
  619. return (isc::config::createAnswer());
  620. } catch (const isc::Exception& error) {
  621. // Configuration error
  622. LOG_ERROR(resolver_logger, RESOLVER_CONFIG_ERROR).arg(error.what());
  623. return (isc::config::createAnswer(1, error.what()));
  624. }
  625. }
  626. void
  627. Resolver::setForwardAddresses(const AddressList& addresses)
  628. {
  629. impl_->setForwardAddresses(addresses, dnss_);
  630. }
  631. void
  632. Resolver::setRootAddresses(const AddressList& addresses)
  633. {
  634. impl_->setRootAddresses(addresses, dnss_);
  635. }
  636. bool
  637. Resolver::isForwarding() const {
  638. return (!impl_->upstream_.empty());
  639. }
  640. AddressList
  641. Resolver::getForwardAddresses() const {
  642. return (impl_->upstream_);
  643. }
  644. AddressList
  645. Resolver::getRootAddresses() const {
  646. return (impl_->upstream_root_);
  647. }
  648. void
  649. Resolver::setListenAddresses(const AddressList& addresses) {
  650. installListenAddresses(addresses, impl_->listen_, *dnss_);
  651. }
  652. void
  653. Resolver::setTimeouts(int query_timeout, int client_timeout,
  654. int lookup_timeout, unsigned retries) {
  655. LOG_DEBUG(resolver_logger, RESOLVER_DBG_CONFIG, RESOLVER_SET_PARAMS)
  656. .arg(query_timeout).arg(client_timeout).arg(lookup_timeout)
  657. .arg(retries);
  658. impl_->query_timeout_ = query_timeout;
  659. impl_->client_timeout_ = client_timeout;
  660. impl_->lookup_timeout_ = lookup_timeout;
  661. impl_->retries_ = retries;
  662. }
  663. int
  664. Resolver::getQueryTimeout() const {
  665. return impl_->query_timeout_;
  666. }
  667. int
  668. Resolver::getClientTimeout() const {
  669. return impl_->client_timeout_;
  670. }
  671. int
  672. Resolver::getLookupTimeout() const {
  673. return impl_->lookup_timeout_;
  674. }
  675. int
  676. Resolver::getRetries() const {
  677. return impl_->retries_;
  678. }
  679. AddressList
  680. Resolver::getListenAddresses() const {
  681. return (impl_->listen_);
  682. }
  683. const RequestACL&
  684. Resolver::getQueryACL() const {
  685. return (impl_->getQueryACL());
  686. }
  687. void
  688. Resolver::setQueryACL(boost::shared_ptr<const RequestACL> new_acl) {
  689. if (!new_acl) {
  690. isc_throw(InvalidParameter, "NULL pointer is passed to setQueryACL");
  691. }
  692. LOG_INFO(resolver_logger, RESOLVER_SET_QUERY_ACL);
  693. impl_->setQueryACL(new_acl);
  694. }