resolver.cc 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627
  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 <netinet/in.h>
  16. #include <algorithm>
  17. #include <vector>
  18. #include <cassert>
  19. #include <asiolink/asiolink.h>
  20. #include <asiolink/ioaddress.h>
  21. #include <boost/foreach.hpp>
  22. #include <boost/lexical_cast.hpp>
  23. #include <config/ccsession.h>
  24. #include <exceptions/exceptions.h>
  25. #include <dns/opcode.h>
  26. #include <dns/rcode.h>
  27. #include <dns/buffer.h>
  28. #include <dns/exceptions.h>
  29. #include <dns/name.h>
  30. #include <dns/question.h>
  31. #include <dns/rrset.h>
  32. #include <dns/rrttl.h>
  33. #include <dns/message.h>
  34. #include <dns/messagerenderer.h>
  35. #include <log/dummylog.h>
  36. #include <resolver/resolver.h>
  37. using namespace std;
  38. using namespace isc;
  39. using namespace isc::dns;
  40. using namespace isc::data;
  41. using namespace isc::config;
  42. using isc::log::dlog;
  43. using namespace asiolink;
  44. typedef pair<string, uint16_t> addr_t;
  45. class ResolverImpl {
  46. private:
  47. // prohibit copy
  48. ResolverImpl(const ResolverImpl& source);
  49. ResolverImpl& operator=(const ResolverImpl& source);
  50. public:
  51. ResolverImpl() :
  52. config_session_(NULL),
  53. timeout_(2000),
  54. retries_(3),
  55. rec_query_(NULL)
  56. {}
  57. ~ResolverImpl() {
  58. queryShutdown();
  59. }
  60. void querySetup(DNSService& dnss) {
  61. assert(!rec_query_); // queryShutdown must be called first
  62. dlog("Query setup");
  63. rec_query_ = new RecursiveQuery(dnss, upstream_, upstream_root_, timeout_, retries_);
  64. }
  65. void queryShutdown() {
  66. // only shut down if we have actually called querySetup before
  67. // (this is not a safety check, just to prevent logging of
  68. // actions that are not performed
  69. if (rec_query_) {
  70. dlog("Query shutdown");
  71. delete rec_query_;
  72. rec_query_ = NULL;
  73. }
  74. }
  75. void setForwardAddresses(const vector<addr_t>& upstream,
  76. DNSService *dnss)
  77. {
  78. upstream_ = upstream;
  79. if (dnss) {
  80. if (!upstream_.empty()) {
  81. dlog("Setting forward addresses:");
  82. BOOST_FOREACH(const addr_t& address, upstream) {
  83. dlog(" " + address.first + ":" +
  84. boost::lexical_cast<string>(address.second));
  85. }
  86. } else {
  87. dlog("No forward addresses, running in recursive mode");
  88. }
  89. }
  90. }
  91. void setRootAddresses(const vector<addr_t>& upstream_root,
  92. DNSService *dnss)
  93. {
  94. queryShutdown();
  95. upstream_root_ = upstream_root;
  96. if (dnss) {
  97. if (!upstream_root_.empty()) {
  98. dlog("Setting root addresses:");
  99. BOOST_FOREACH(const addr_t& address, upstream_root) {
  100. dlog(" " + address.first + ":" +
  101. boost::lexical_cast<string>(address.second));
  102. }
  103. } else {
  104. dlog("No root addresses");
  105. }
  106. querySetup(*dnss);
  107. }
  108. }
  109. void processNormalQuery(const Question& question,
  110. MessagePtr answer_message,
  111. OutputBufferPtr buffer,
  112. DNSServer* server);
  113. /// Currently non-configurable, but will be.
  114. static const uint16_t DEFAULT_LOCAL_UDPSIZE = 4096;
  115. /// These members are public because Resolver accesses them directly.
  116. ModuleCCSession* config_session_;
  117. /// Addresses of the root nameserver(s)
  118. vector<addr_t> upstream_root_;
  119. /// Addresses of the forward nameserver
  120. vector<addr_t> upstream_;
  121. /// Addresses we listen on
  122. vector<addr_t> listen_;
  123. /// Time in milliseconds, to timeout
  124. int timeout_;
  125. /// Number of retries after timeout
  126. unsigned retries_;
  127. private:
  128. /// Object to handle upstream queries
  129. RecursiveQuery* rec_query_;
  130. };
  131. /*
  132. * std::for_each has a broken interface. It makes no sense in a language
  133. * without lambda functions/closures. These two classes emulate the lambda
  134. * functions so for_each can be used.
  135. */
  136. class QuestionInserter {
  137. public:
  138. QuestionInserter(MessagePtr message) : message_(message) {}
  139. void operator()(const QuestionPtr question) {
  140. dlog(string("Adding question ") + question->getName().toText() +
  141. " to message");
  142. message_->addQuestion(question);
  143. }
  144. MessagePtr message_;
  145. };
  146. void
  147. makeErrorMessage(MessagePtr message, OutputBufferPtr buffer,
  148. const Rcode& rcode)
  149. {
  150. // extract the parameters that should be kept.
  151. // XXX: with the current implementation, it's not easy to set EDNS0
  152. // depending on whether the query had it. So we'll simply omit it.
  153. const qid_t qid = message->getQid();
  154. const bool rd = message->getHeaderFlag(Message::HEADERFLAG_RD);
  155. const bool cd = message->getHeaderFlag(Message::HEADERFLAG_CD);
  156. const Opcode& opcode = message->getOpcode();
  157. vector<QuestionPtr> questions;
  158. // If this is an error to a query or notify, we should also copy the
  159. // question section.
  160. if (opcode == Opcode::QUERY() || opcode == Opcode::NOTIFY()) {
  161. questions.assign(message->beginQuestion(), message->endQuestion());
  162. }
  163. message->clear(Message::RENDER);
  164. message->setQid(qid);
  165. message->setOpcode(opcode);
  166. message->setHeaderFlag(Message::HEADERFLAG_QR);
  167. if (rd) {
  168. message->setHeaderFlag(Message::HEADERFLAG_RD);
  169. }
  170. if (cd) {
  171. message->setHeaderFlag(Message::HEADERFLAG_CD);
  172. }
  173. for_each(questions.begin(), questions.end(), QuestionInserter(message));
  174. message->setRcode(rcode);
  175. MessageRenderer renderer(*buffer);
  176. message->toWire(renderer);
  177. dlog(string("Sending an error response (") +
  178. boost::lexical_cast<string>(renderer.getLength()) + " bytes):\n" +
  179. message->toText());
  180. }
  181. // This is a derived class of \c DNSLookup, to serve as a
  182. // callback in the asiolink module. It calls
  183. // Resolver::processMessage() on a single DNS message.
  184. class MessageLookup : public DNSLookup {
  185. public:
  186. MessageLookup(Resolver* srv) : server_(srv) {}
  187. // \brief Handle the DNS Lookup
  188. virtual void operator()(const IOMessage& io_message,
  189. MessagePtr query_message,
  190. MessagePtr answer_message,
  191. OutputBufferPtr buffer,
  192. DNSServer* server) const
  193. {
  194. server_->processMessage(io_message, query_message,
  195. answer_message, buffer, server);
  196. }
  197. private:
  198. Resolver* server_;
  199. };
  200. // This is a derived class of \c DNSAnswer, to serve as a
  201. // callback in the asiolink module. It takes a completed
  202. // set of answer data from the DNS lookup and assembles it
  203. // into a wire-format response.
  204. class MessageAnswer : public DNSAnswer {
  205. public:
  206. virtual void operator()(const IOMessage& io_message,
  207. MessagePtr query_message,
  208. MessagePtr answer_message,
  209. OutputBufferPtr buffer) const
  210. {
  211. const qid_t qid = query_message->getQid();
  212. const bool rd = query_message->getHeaderFlag(Message::HEADERFLAG_RD);
  213. const bool cd = query_message->getHeaderFlag(Message::HEADERFLAG_CD);
  214. const Opcode& opcode = query_message->getOpcode();
  215. // Fill in the final details of the answer message
  216. answer_message->setQid(qid);
  217. answer_message->setOpcode(opcode);
  218. answer_message->setHeaderFlag(Message::HEADERFLAG_QR);
  219. answer_message->setHeaderFlag(Message::HEADERFLAG_RA);
  220. if (rd) {
  221. answer_message->setHeaderFlag(Message::HEADERFLAG_RD);
  222. }
  223. if (cd) {
  224. answer_message->setHeaderFlag(Message::HEADERFLAG_CD);
  225. }
  226. vector<QuestionPtr> questions;
  227. questions.assign(query_message->beginQuestion(), query_message->endQuestion());
  228. for_each(questions.begin(), questions.end(), QuestionInserter(answer_message));
  229. // Now we can clear the buffer and render the new message into it
  230. buffer->clear();
  231. MessageRenderer renderer(*buffer);
  232. ConstEDNSPtr edns(query_message->getEDNS());
  233. const bool dnssec_ok = edns && edns->getDNSSECAwareness();
  234. if (edns) {
  235. EDNSPtr edns_response(new EDNS());
  236. edns_response->setDNSSECAwareness(dnssec_ok);
  237. // TODO: We should make our own edns bufsize length configurable
  238. edns_response->setUDPSize(Message::DEFAULT_MAX_EDNS0_UDPSIZE);
  239. answer_message->setEDNS(edns_response);
  240. }
  241. if (io_message.getSocket().getProtocol() == IPPROTO_UDP) {
  242. if (edns) {
  243. renderer.setLengthLimit(edns->getUDPSize());
  244. } else {
  245. renderer.setLengthLimit(Message::DEFAULT_MAX_UDPSIZE);
  246. }
  247. } else {
  248. renderer.setLengthLimit(65535);
  249. }
  250. answer_message->toWire(renderer);
  251. dlog(string("sending a response (") +
  252. boost::lexical_cast<string>(renderer.getLength()) + "bytes): \n" +
  253. answer_message->toText());
  254. }
  255. };
  256. // This is a derived class of \c SimpleCallback, to serve
  257. // as a callback in the asiolink module. It checks for queued
  258. // configuration messages, and executes them if found.
  259. class ConfigCheck : public SimpleCallback {
  260. public:
  261. ConfigCheck(Resolver* srv) : server_(srv) {}
  262. virtual void operator()(const IOMessage&) const {
  263. if (server_->getConfigSession()->hasQueuedMsgs()) {
  264. server_->getConfigSession()->checkCommand();
  265. }
  266. }
  267. private:
  268. Resolver* server_;
  269. };
  270. Resolver::Resolver() :
  271. impl_(new ResolverImpl()),
  272. checkin_(new ConfigCheck(this)),
  273. dns_lookup_(new MessageLookup(this)),
  274. dns_answer_(new MessageAnswer)
  275. {}
  276. Resolver::~Resolver() {
  277. delete impl_;
  278. delete checkin_;
  279. delete dns_lookup_;
  280. delete dns_answer_;
  281. dlog("Deleting the Resolver",true);
  282. }
  283. void
  284. Resolver::setDNSService(asiolink::DNSService& dnss) {
  285. dnss_ = &dnss;
  286. }
  287. void
  288. Resolver::setConfigSession(ModuleCCSession* config_session) {
  289. impl_->config_session_ = config_session;
  290. }
  291. ModuleCCSession*
  292. Resolver::getConfigSession() const {
  293. return (impl_->config_session_);
  294. }
  295. void
  296. Resolver::processMessage(const IOMessage& io_message,
  297. MessagePtr query_message,
  298. MessagePtr answer_message,
  299. OutputBufferPtr buffer,
  300. DNSServer* server)
  301. {
  302. dlog("Got a DNS message");
  303. InputBuffer request_buffer(io_message.getData(), io_message.getDataSize());
  304. // First, check the header part. If we fail even for the base header,
  305. // just drop the message.
  306. try {
  307. query_message->parseHeader(request_buffer);
  308. // Ignore all responses.
  309. if (query_message->getHeaderFlag(Message::HEADERFLAG_QR)) {
  310. dlog("Received unexpected response, ignoring");
  311. server->resume(false);
  312. return;
  313. }
  314. } catch (const Exception& ex) {
  315. dlog(string("DNS packet exception: ") + ex.what(),true);
  316. server->resume(false);
  317. return;
  318. }
  319. // Parse the message. On failure, return an appropriate error.
  320. try {
  321. query_message->fromWire(request_buffer);
  322. } catch (const DNSProtocolError& error) {
  323. dlog(string("returning ") + error.getRcode().toText() + ": " +
  324. error.what());
  325. makeErrorMessage(query_message, buffer, error.getRcode());
  326. server->resume(true);
  327. return;
  328. } catch (const Exception& ex) {
  329. dlog(string("returning SERVFAIL: ") + ex.what());
  330. makeErrorMessage(query_message, buffer, Rcode::SERVFAIL());
  331. server->resume(true);
  332. return;
  333. } // other exceptions will be handled at a higher layer.
  334. dlog("received a message:\n" + query_message->toText());
  335. // Perform further protocol-level validation.
  336. bool sendAnswer = true;
  337. if (query_message->getOpcode() == Opcode::NOTIFY()) {
  338. makeErrorMessage(query_message, buffer, Rcode::NOTAUTH());
  339. dlog("Notify arrived, but we are not authoritative");
  340. } else if (query_message->getOpcode() != Opcode::QUERY()) {
  341. dlog("Unsupported opcode (got: " + query_message->getOpcode().toText() +
  342. ", expected: " + Opcode::QUERY().toText());
  343. makeErrorMessage(query_message, buffer, Rcode::NOTIMP());
  344. } else if (query_message->getRRCount(Message::SECTION_QUESTION) != 1) {
  345. dlog("The query contained " +
  346. boost::lexical_cast<string>(query_message->getRRCount(
  347. Message::SECTION_QUESTION) + " questions, exactly one expected"));
  348. makeErrorMessage(query_message, buffer, Rcode::FORMERR());
  349. } else {
  350. ConstQuestionPtr question = *query_message->beginQuestion();
  351. const RRType &qtype = question->getType();
  352. if (qtype == RRType::AXFR()) {
  353. if (io_message.getSocket().getProtocol() == IPPROTO_UDP) {
  354. makeErrorMessage(query_message, buffer, Rcode::FORMERR());
  355. } else {
  356. makeErrorMessage(query_message, buffer, Rcode::NOTIMP());
  357. }
  358. } else if (qtype == RRType::IXFR()) {
  359. makeErrorMessage(query_message, buffer, Rcode::NOTIMP());
  360. } else {
  361. // The RecursiveQuery object will post the "resume" event to the
  362. // DNSServer when an answer arrives, so we don't have to do it now.
  363. sendAnswer = false;
  364. impl_->processNormalQuery(*question, answer_message,
  365. buffer, server);
  366. }
  367. }
  368. if (sendAnswer) {
  369. server->resume(true);
  370. }
  371. }
  372. void
  373. ResolverImpl::processNormalQuery(const Question& question,
  374. MessagePtr answer_message,
  375. OutputBufferPtr buffer,
  376. DNSServer* server)
  377. {
  378. dlog("Processing normal query");
  379. rec_query_->sendQuery(question, answer_message, buffer, server);
  380. }
  381. namespace {
  382. vector<addr_t>
  383. parseAddresses(ConstElementPtr addresses) {
  384. vector<addr_t> result;
  385. if (addresses) {
  386. if (addresses->getType() == Element::list) {
  387. for (size_t i(0); i < addresses->size(); ++ i) {
  388. ConstElementPtr addrPair(addresses->get(i));
  389. ConstElementPtr addr(addrPair->get("address"));
  390. ConstElementPtr port(addrPair->get("port"));
  391. if (!addr || ! port) {
  392. isc_throw(BadValue, "Address must contain both the IP"
  393. "address and port");
  394. }
  395. try {
  396. IOAddress(addr->stringValue());
  397. if (port->intValue() < 0 ||
  398. port->intValue() > 0xffff) {
  399. isc_throw(BadValue, "Bad port value (" <<
  400. port->intValue() << ")");
  401. }
  402. result.push_back(addr_t(addr->stringValue(),
  403. port->intValue()));
  404. }
  405. catch (const TypeError &e) { // Better error message
  406. isc_throw(TypeError,
  407. "Address must be a string and port an integer");
  408. }
  409. }
  410. } else if (addresses->getType() != Element::null) {
  411. isc_throw(TypeError,
  412. "root_addresses, forward_addresses, and listen_on config element must be a list");
  413. }
  414. }
  415. return (result);
  416. }
  417. }
  418. ConstElementPtr
  419. Resolver::updateConfig(ConstElementPtr config) {
  420. dlog("New config comes: " + config->toWire());
  421. try {
  422. // Parse forward_addresses
  423. ConstElementPtr rootAddressesE(config->get("root_addresses"));
  424. vector<addr_t> rootAddresses(parseAddresses(rootAddressesE));
  425. ConstElementPtr forwardAddressesE(config->get("forward_addresses"));
  426. vector<addr_t> forwardAddresses(parseAddresses(forwardAddressesE));
  427. ConstElementPtr listenAddressesE(config->get("listen_on"));
  428. vector<addr_t> listenAddresses(parseAddresses(listenAddressesE));
  429. bool set_timeouts(false);
  430. int timeout = impl_->timeout_;
  431. unsigned retries = impl_->retries_;
  432. ConstElementPtr timeoutE(config->get("timeout")),
  433. retriesE(config->get("retries"));
  434. if (timeoutE) {
  435. // It should be safe to just get it, the config manager should
  436. // check for us
  437. timeout = timeoutE->intValue();
  438. if (timeout < -1) {
  439. isc_throw(BadValue, "Timeout too small");
  440. }
  441. set_timeouts = true;
  442. }
  443. if (retriesE) {
  444. if (retriesE->intValue() < 0) {
  445. isc_throw(BadValue, "Negative number of retries");
  446. }
  447. retries = retriesE->intValue();
  448. set_timeouts = true;
  449. }
  450. // Everything OK, so commit the changes
  451. // listenAddresses can fail to bind, so try them first
  452. bool need_query_restart = false;
  453. if (listenAddressesE) {
  454. setListenAddresses(listenAddresses);
  455. need_query_restart = true;
  456. }
  457. if (forwardAddressesE) {
  458. setForwardAddresses(forwardAddresses);
  459. need_query_restart = true;
  460. }
  461. if (rootAddressesE) {
  462. setRootAddresses(rootAddresses);
  463. }
  464. if (set_timeouts) {
  465. setTimeouts(timeout, retries);
  466. need_query_restart = true;
  467. }
  468. if (need_query_restart) {
  469. impl_->queryShutdown();
  470. impl_->querySetup(*dnss_);
  471. }
  472. return (isc::config::createAnswer());
  473. } catch (const isc::Exception& error) {
  474. dlog(string("error in config: ") + error.what(),true);
  475. return (isc::config::createAnswer(1, error.what()));
  476. }
  477. }
  478. void
  479. Resolver::setForwardAddresses(const vector<addr_t>& addresses)
  480. {
  481. impl_->setForwardAddresses(addresses, dnss_);
  482. }
  483. void
  484. Resolver::setRootAddresses(const vector<addr_t>& addresses)
  485. {
  486. impl_->setRootAddresses(addresses, dnss_);
  487. }
  488. bool
  489. Resolver::isForwarding() const {
  490. return (!impl_->upstream_.empty());
  491. }
  492. vector<addr_t>
  493. Resolver::getForwardAddresses() const {
  494. return (impl_->upstream_);
  495. }
  496. vector<addr_t>
  497. Resolver::getRootAddresses() const {
  498. return (impl_->upstream_root_);
  499. }
  500. namespace {
  501. void
  502. setAddresses(DNSService *service, const vector<addr_t>& addresses) {
  503. service->clearServers();
  504. BOOST_FOREACH(const addr_t &address, addresses) {
  505. service->addServer(address.second, address.first);
  506. }
  507. }
  508. }
  509. void
  510. Resolver::setListenAddresses(const vector<addr_t>& addresses) {
  511. try {
  512. dlog("Setting listen addresses:");
  513. BOOST_FOREACH(const addr_t& addr, addresses) {
  514. dlog(" " + addr.first + ":" +
  515. boost::lexical_cast<string>(addr.second));
  516. }
  517. setAddresses(dnss_, addresses);
  518. impl_->listen_ = addresses;
  519. }
  520. catch (const exception& e) {
  521. /*
  522. * We couldn't set it. So return it back. If that fails as well,
  523. * we have a problem.
  524. *
  525. * If that fails, bad luck, but we are useless anyway, so just die
  526. * and let boss start us again.
  527. */
  528. dlog(string("Unable to set new address: ") + e.what(),true);
  529. try {
  530. setAddresses(dnss_, impl_->listen_);
  531. }
  532. catch (const exception& e2) {
  533. dlog(string("Unable to recover from error;"),true);
  534. dlog(string("Rollback failed with: ") + e2.what(),true);
  535. abort();
  536. }
  537. throw e; // Let it fly a little bit further
  538. }
  539. }
  540. void
  541. Resolver::setTimeouts(int timeout, unsigned retries) {
  542. dlog("Setting timeout to " + boost::lexical_cast<string>(timeout) +
  543. " and retry count to " + boost::lexical_cast<string>(retries));
  544. impl_->timeout_ = timeout;
  545. impl_->retries_ = retries;
  546. }
  547. pair<int, unsigned>
  548. Resolver::getTimeouts() const {
  549. return (pair<int, unsigned>(impl_->timeout_, impl_->retries_));
  550. }
  551. vector<addr_t>
  552. Resolver::getListenAddresses() const {
  553. return (impl_->listen_);
  554. }