recursive_query_unittest.cc 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032
  1. // Copyright (C) 2011 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 <sys/types.h>
  16. #include <sys/socket.h>
  17. #include <sys/time.h>
  18. #include <cstring>
  19. #include <boost/noncopyable.hpp>
  20. #include <boost/lexical_cast.hpp>
  21. #include <boost/bind.hpp>
  22. #include <boost/scoped_ptr.hpp>
  23. #include <boost/date_time/posix_time/posix_time_types.hpp>
  24. #include <gtest/gtest.h>
  25. #include <exceptions/exceptions.h>
  26. #include <dns/tests/unittest_util.h>
  27. #include <dns/rcode.h>
  28. #include <util/buffer.h>
  29. #include <util/unittests/resolver.h>
  30. #include <dns/message.h>
  31. #include <dns/rdataclass.h>
  32. #include <nsas/nameserver_address_store.h>
  33. #include <cache/resolver_cache.h>
  34. #include <resolve/resolve.h>
  35. // IMPORTANT: We shouldn't directly use ASIO definitions in this test.
  36. // In particular, we must not include asio.hpp in this file.
  37. // The asiolink module is primarily intended to be a wrapper that hide the
  38. // details of the underlying implementations. We need to test the wrapper
  39. // level behaviors. In addition, some compilers reject to compile this file
  40. // if we include asio.hpp unless we specify a special compiler option.
  41. // If we need to test something at the level of underlying ASIO and need
  42. // their definition, that test should go to asiolink/internal/tests.
  43. #include <resolve/recursive_query.h>
  44. #include <asiodns/dns_lookup.h>
  45. #include <asiolink/io_socket.h>
  46. #include <asiolink/io_service.h>
  47. #include <asiolink/io_message.h>
  48. #include <asiolink/io_error.h>
  49. #include <asiolink/simple_callback.h>
  50. using isc::UnitTestUtil;
  51. using namespace std;
  52. using namespace isc::asiodns;
  53. using namespace isc::asiolink;
  54. using namespace isc::dns;
  55. using namespace isc::util;
  56. using boost::scoped_ptr;
  57. namespace isc {
  58. namespace asiodns {
  59. // This is defined in recursive_query.cc, but not in header (it's not public
  60. // function). So bring it in to be tested.
  61. std::string
  62. deepestDelegation(Name name, RRClass rrclass,
  63. isc::cache::ResolverCache& cache);
  64. }
  65. }
  66. namespace {
  67. const char* const TEST_SERVER_PORT = "53535";
  68. const char* const TEST_CLIENT_PORT = "53536";
  69. const char* const TEST_IPV6_ADDR = "::1";
  70. const char* const TEST_IPV4_ADDR = "127.0.0.1";
  71. // This data is intended to be valid as a DNS/TCP-like message: the first
  72. // two octets encode the length of the rest of the data. This is crucial
  73. // for the tests below.
  74. const uint8_t test_data[] = {0, 4, 1, 2, 3, 4};
  75. // This function returns an addrinfo structure for use by tests.
  76. struct addrinfo*
  77. resolveAddress(const int protocol, const char* const addr,
  78. const char* const port)
  79. {
  80. struct addrinfo hints;
  81. memset(&hints, 0, sizeof(hints));
  82. hints.ai_family = AF_UNSPEC; // let the address decide it.
  83. hints.ai_socktype = (protocol == IPPROTO_UDP) ? SOCK_DGRAM : SOCK_STREAM;
  84. hints.ai_protocol = protocol;
  85. hints.ai_flags = AI_NUMERICSERV;
  86. struct addrinfo* res;
  87. const int error = getaddrinfo(addr, port, &hints, &res);
  88. if (error != 0) {
  89. isc_throw(IOError, "getaddrinfo failed: " << gai_strerror(error));
  90. }
  91. return (res);
  92. }
  93. // convenience shortcut of the other version using different addresses and
  94. // ports depending on whether we're testing IPv4 or v6, TCP or UDP, and
  95. // client or server operation.
  96. struct addrinfo*
  97. resolveAddress(const int family, const int protocol, const bool client) {
  98. return (resolveAddress(protocol,
  99. (family == AF_INET6) ? TEST_IPV6_ADDR :
  100. TEST_IPV4_ADDR,
  101. client ? TEST_CLIENT_PORT : TEST_SERVER_PORT));
  102. }
  103. // A helper holder of addrinfo so we can safely release the resource
  104. // either when leaving the defined scope either normally or due to exception.
  105. struct ScopedAddrInfo {
  106. ScopedAddrInfo(struct addrinfo* res) : res_(res) {}
  107. ~ScopedAddrInfo() { freeaddrinfo(res_); }
  108. struct addrinfo* res_;
  109. };
  110. // Similar to ScopedAddrInfo but for socket FD. It also supports the "release"
  111. // operation so it can release the ownership of the FD.
  112. // This is made non copyable to avoid making an accidental copy, which could
  113. // result in duplicate close.
  114. struct ScopedSocket : private boost::noncopyable {
  115. ScopedSocket() : s_(-1) {}
  116. ScopedSocket(int s) : s_(s) {}
  117. ~ScopedSocket() {
  118. if (s_ >= 0) {
  119. close(s_);
  120. }
  121. }
  122. void reset(int new_s) {
  123. if (s_ >= 0) {
  124. close(s_);
  125. }
  126. s_ = new_s;
  127. }
  128. int release() {
  129. int s = s_;
  130. s_ = -1;
  131. return (s);
  132. }
  133. int s_;
  134. };
  135. // This fixture is a framework for various types of network operations
  136. // using the ASIO interfaces. Each test case creates an IOService object,
  137. // opens a local "client" socket for testing, sends data via the local socket
  138. // to the service that would run in the IOService object.
  139. // A mock callback function (an ASIOCallBack object) is registered with the
  140. // IOService object, so the test code should be able to examine the data
  141. // received on the server side. It then checks the received data matches
  142. // expected parameters.
  143. // If initialization parameters of the IOService should be modified, the test
  144. // case can do it using the setDNSService() method.
  145. // Note: the set of tests in RecursiveQueryTest use actual network services and may
  146. // involve undesirable side effects such as blocking.
  147. class RecursiveQueryTest : public ::testing::Test {
  148. protected:
  149. RecursiveQueryTest();
  150. ~RecursiveQueryTest() {
  151. // It would delete itself, but after the io_service_, which could
  152. // segfailt in case there were unhandled requests
  153. resolver_.reset();
  154. }
  155. // Send a test UDP packet to a mock server
  156. void sendUDP(const int family) {
  157. ScopedAddrInfo sai(resolveAddress(family, IPPROTO_UDP, false));
  158. struct addrinfo* res = sai.res_;
  159. sock_.reset(socket(res->ai_family, res->ai_socktype,
  160. res->ai_protocol));
  161. if (sock_.s_ < 0) {
  162. isc_throw(IOError, "failed to open test socket");
  163. }
  164. const int cc = sendto(sock_.s_, test_data, sizeof(test_data), 0,
  165. res->ai_addr, res->ai_addrlen);
  166. if (cc != sizeof(test_data)) {
  167. isc_throw(IOError, "unexpected sendto result: " << cc);
  168. }
  169. io_service_->run();
  170. }
  171. // Send a test TCP packet to a mock server
  172. void sendTCP(const int family) {
  173. ScopedAddrInfo sai(resolveAddress(family, IPPROTO_TCP, false));
  174. struct addrinfo* res = sai.res_;
  175. sock_.reset(socket(res->ai_family, res->ai_socktype,
  176. res->ai_protocol));
  177. if (sock_.s_ < 0) {
  178. isc_throw(IOError, "failed to open test socket");
  179. }
  180. if (connect(sock_.s_, res->ai_addr, res->ai_addrlen) < 0) {
  181. isc_throw(IOError, "failed to connect to the test server");
  182. }
  183. const int cc = send(sock_.s_, test_data, sizeof(test_data), 0);
  184. if (cc != sizeof(test_data)) {
  185. isc_throw(IOError, "unexpected send result: " << cc);
  186. }
  187. io_service_->run();
  188. }
  189. // Receive a UDP packet from a mock server; used for testing
  190. // recursive lookup. The caller must place a RecursiveQuery
  191. // on the IO Service queue before running this routine.
  192. void recvUDP(const int family, void* buffer, size_t& size) {
  193. ScopedAddrInfo sai(resolveAddress(family, IPPROTO_UDP, true));
  194. struct addrinfo* res = sai.res_;
  195. sock_.reset(socket(res->ai_family, res->ai_socktype,
  196. res->ai_protocol));
  197. if (sock_.s_ < 0) {
  198. isc_throw(IOError, "failed to open test socket");
  199. }
  200. if (bind(sock_.s_, res->ai_addr, res->ai_addrlen) < 0) {
  201. isc_throw(IOError, "bind failed: " << strerror(errno));
  202. }
  203. // The IO service queue should have a RecursiveQuery object scheduled
  204. // to run at this point. This call will cause it to begin an
  205. // async send, then return.
  206. io_service_->run_one();
  207. // ... and this one will block until the send has completed
  208. io_service_->run_one();
  209. // Now we attempt to recv() whatever was sent.
  210. // XXX: there's no guarantee the receiving socket can immediately get
  211. // the packet. Normally we can perform blocking recv to wait for it,
  212. // but in theory it's even possible that the packet is lost.
  213. // In order to prevent the test from hanging in such a worst case
  214. // we add an ad hoc timeout.
  215. const struct timeval timeo = { 10, 0 };
  216. int recv_options = 0;
  217. if (setsockopt(sock_.s_, SOL_SOCKET, SO_RCVTIMEO, &timeo,
  218. sizeof(timeo))) {
  219. if (errno == ENOPROTOOPT) {
  220. // Workaround for Solaris: it doesn't accept SO_RCVTIMEO
  221. // with the error of ENOPROTOOPT. Since this is a workaround
  222. // for rare error cases anyway, we simply switch to the
  223. // "don't wait" mode. If we still find an error in recv()
  224. // can happen often we'll consider a more complete solution.
  225. recv_options = MSG_DONTWAIT;
  226. } else {
  227. isc_throw(IOError, "set RCVTIMEO failed: " << strerror(errno));
  228. }
  229. }
  230. const int ret = recv(sock_.s_, buffer, size, recv_options);
  231. if (ret < 0) {
  232. isc_throw(IOError, "recvfrom failed: " << strerror(errno));
  233. }
  234. // Pass the message size back via the size parameter
  235. size = ret;
  236. }
  237. void
  238. addServer(const string& address, const char* const port, int protocol) {
  239. ScopedAddrInfo sai(resolveAddress(protocol, address.c_str(), port));
  240. struct addrinfo* res = sai.res_;
  241. const int family = res->ai_family;
  242. ScopedSocket sock(socket(res->ai_family, res->ai_socktype,
  243. res->ai_protocol));
  244. const int s = sock.s_;
  245. if (s < 0) {
  246. isc_throw(isc::Unexpected, "failed to open a test socket");
  247. }
  248. const int on = 1;
  249. if (family == AF_INET6) {
  250. if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) ==
  251. -1) {
  252. isc_throw(isc::Unexpected,
  253. "failed to set socket option(IPV6_V6ONLY)");
  254. }
  255. }
  256. if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) {
  257. isc_throw(isc::Unexpected,
  258. "failed to set socket option(SO_REUSEADDR)");
  259. }
  260. if (bind(s, res->ai_addr, res->ai_addrlen) != 0) {
  261. isc_throw(isc::Unexpected, "failed to bind a test socket");
  262. }
  263. if (protocol == IPPROTO_TCP) {
  264. dns_service_->addServerTCPFromFD(sock.release(), family);
  265. } else {
  266. dns_service_->addServerUDPFromFD(sock.release(), family);
  267. }
  268. }
  269. // Set up an IO Service queue using the specified address
  270. void setDNSService(const string& address) {
  271. setDNSService();
  272. addServer(address, TEST_SERVER_PORT, IPPROTO_TCP);
  273. addServer(address, TEST_SERVER_PORT, IPPROTO_UDP);
  274. }
  275. // Set up an IO Service queue using the "any" address, on IPv4 if
  276. // 'use_ipv4' is true and on IPv6 if 'use_ipv6' is true.
  277. void setDNSService(const bool use_ipv4, const bool use_ipv6) {
  278. setDNSService();
  279. if (use_ipv6) {
  280. addServer("::", TEST_SERVER_PORT, IPPROTO_TCP);
  281. addServer("::", TEST_SERVER_PORT, IPPROTO_UDP);
  282. }
  283. if (use_ipv4) {
  284. addServer("0.0.0.0", TEST_SERVER_PORT, IPPROTO_TCP);
  285. addServer("0.0.0.0", TEST_SERVER_PORT, IPPROTO_UDP);
  286. }
  287. }
  288. // Set up empty DNS Service
  289. // Set up an IO Service queue without any addresses
  290. void setDNSService() {
  291. io_service_.reset(new IOService());
  292. callback_.reset(new ASIOCallBack(this));
  293. dns_service_.reset(new DNSService(*io_service_, callback_.get(), NULL,
  294. NULL));
  295. }
  296. // Run a simple server test, on either IPv4 or IPv6, and over either
  297. // UDP or TCP. Calls the sendUDP() or sendTCP() methods, which will
  298. // start the IO Service queue. The UDPServer or TCPServer that was
  299. // created by setIOService() will receive the test packet and issue a
  300. // callback, which enables us to check that the data it received
  301. // matches what we sent.
  302. void doTest(const int family, const int protocol) {
  303. if (protocol == IPPROTO_UDP) {
  304. sendUDP(family);
  305. } else {
  306. sendTCP(family);
  307. }
  308. // There doesn't seem to be an effective test for the validity of
  309. // 'native'.
  310. // One thing we are sure is it must be different from our local socket.
  311. EXPECT_NE(sock_.s_, callback_native_);
  312. EXPECT_EQ(protocol, callback_protocol_);
  313. EXPECT_EQ(family == AF_INET6 ? TEST_IPV6_ADDR : TEST_IPV4_ADDR,
  314. callback_address_);
  315. const uint8_t* expected_data =
  316. protocol == IPPROTO_UDP ? test_data : test_data + 2;
  317. const size_t expected_datasize =
  318. protocol == IPPROTO_UDP ? sizeof(test_data) :
  319. sizeof(test_data) - 2;
  320. EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, &callback_data_[0],
  321. callback_data_.size(),
  322. expected_data, expected_datasize);
  323. }
  324. protected:
  325. // This is a nonfunctional mockup of a DNSServer object. Its purpose
  326. // is to resume after a recursive query or other asynchronous call
  327. // has completed.
  328. class MockServer : public DNSServer {
  329. public:
  330. explicit MockServer(IOService& io_service,
  331. SimpleCallback* checkin = NULL,
  332. DNSLookup* lookup = NULL,
  333. DNSAnswer* answer = NULL) :
  334. io_(io_service),
  335. done_(false),
  336. message_(new Message(Message::PARSE)),
  337. answer_message_(new Message(Message::RENDER)),
  338. respbuf_(new OutputBuffer(0)),
  339. checkin_(checkin), lookup_(lookup), answer_(answer)
  340. {}
  341. void operator()(asio::error_code ec = asio::error_code(),
  342. size_t length = 0)
  343. {}
  344. void resume(const bool) {
  345. // should never be called in our tests
  346. }
  347. DNSServer* clone() {
  348. MockServer* s = new MockServer(*this);
  349. return (s);
  350. }
  351. inline void asyncLookup() {
  352. if (lookup_) {
  353. (*lookup_)(*io_message_, message_, answer_message_,
  354. respbuf_, this);
  355. }
  356. }
  357. protected:
  358. IOService& io_;
  359. bool done_;
  360. private:
  361. // Currently unused; these will be used for testing
  362. // asynchronous lookup calls via the asyncLookup() method
  363. boost::shared_ptr<isc::asiolink::IOMessage> io_message_;
  364. isc::dns::MessagePtr message_;
  365. isc::dns::MessagePtr answer_message_;
  366. isc::util::OutputBufferPtr respbuf_;
  367. // Callback functions provided by the caller
  368. const SimpleCallback* checkin_;
  369. const DNSLookup* lookup_;
  370. const DNSAnswer* answer_;
  371. };
  372. // This version of mock server just stops the io_service when it is resumed
  373. class MockServerStop : public MockServer {
  374. public:
  375. explicit MockServerStop(IOService& io_service, bool* done) :
  376. MockServer(io_service),
  377. done_(done)
  378. {}
  379. void resume(const bool done) {
  380. *done_ = done;
  381. io_.stop();
  382. }
  383. DNSServer* clone() {
  384. return (new MockServerStop(*this));
  385. }
  386. private:
  387. bool* done_;
  388. };
  389. // This version of mock server just stops the io_service when it is resumed
  390. // the second time. (Used in the clientTimeout test, where resume
  391. // is called initially with the error answer, and later when the
  392. // lookup times out, it is called without an answer to send back)
  393. class MockServerStop2 : public MockServer {
  394. public:
  395. explicit MockServerStop2(IOService& io_service,
  396. bool* done1, bool* done2) :
  397. MockServer(io_service),
  398. done1_(done1),
  399. done2_(done2),
  400. stopped_once_(false)
  401. {}
  402. void resume(const bool done) {
  403. if (stopped_once_) {
  404. *done2_ = done;
  405. io_.stop();
  406. } else {
  407. *done1_ = done;
  408. stopped_once_ = true;
  409. }
  410. }
  411. DNSServer* clone() {
  412. return (new MockServerStop2(*this));
  413. }
  414. private:
  415. bool* done1_;
  416. bool* done2_;
  417. bool stopped_once_;
  418. };
  419. private:
  420. class ASIOCallBack : public SimpleCallback {
  421. public:
  422. ASIOCallBack(RecursiveQueryTest* test_obj) : test_obj_(test_obj) {}
  423. void operator()(const IOMessage& io_message) const {
  424. test_obj_->callBack(io_message);
  425. }
  426. private:
  427. RecursiveQueryTest* test_obj_;
  428. };
  429. void callBack(const IOMessage& io_message) {
  430. callback_protocol_ = io_message.getSocket().getProtocol();
  431. callback_native_ = io_message.getSocket().getNative();
  432. callback_address_ =
  433. io_message.getRemoteEndpoint().getAddress().toText();
  434. callback_data_.assign(
  435. static_cast<const uint8_t*>(io_message.getData()),
  436. static_cast<const uint8_t*>(io_message.getData()) +
  437. io_message.getDataSize());
  438. io_service_->stop();
  439. }
  440. protected:
  441. // We use a pointer for io_service_, because for some tests we
  442. // need to recreate a new one within one onstance of this class
  443. scoped_ptr<IOService> io_service_;
  444. scoped_ptr<DNSService> dns_service_;
  445. scoped_ptr<isc::nsas::NameserverAddressStore> nsas_;
  446. isc::cache::ResolverCache cache_;
  447. scoped_ptr<ASIOCallBack> callback_;
  448. int callback_protocol_;
  449. int callback_native_;
  450. string callback_address_;
  451. vector<uint8_t> callback_data_;
  452. ScopedSocket sock_;
  453. boost::shared_ptr<isc::util::unittests::TestResolver> resolver_;
  454. };
  455. RecursiveQueryTest::RecursiveQueryTest() :
  456. dns_service_(NULL), callback_(NULL), callback_protocol_(0),
  457. callback_native_(-1), resolver_(new isc::util::unittests::TestResolver())
  458. {
  459. io_service_.reset(new IOService());
  460. setDNSService(true, true);
  461. nsas_.reset(new isc::nsas::NameserverAddressStore(resolver_));
  462. }
  463. TEST_F(RecursiveQueryTest, v6UDPSend) {
  464. doTest(AF_INET6, IPPROTO_UDP);
  465. }
  466. TEST_F(RecursiveQueryTest, v6TCPSend) {
  467. doTest(AF_INET6, IPPROTO_TCP);
  468. }
  469. TEST_F(RecursiveQueryTest, v4UDPSend) {
  470. doTest(AF_INET, IPPROTO_UDP);
  471. }
  472. TEST_F(RecursiveQueryTest, v4TCPSend) {
  473. doTest(AF_INET, IPPROTO_TCP);
  474. }
  475. TEST_F(RecursiveQueryTest, v6UDPSendSpecific) {
  476. // Explicitly set a specific address to be bound to the socket.
  477. // The subsequent test does not directly ensures the underlying socket
  478. // is bound to the expected address, but the success of the tests should
  479. // reasonably suggest it works as intended.
  480. // Specifying an address also implicitly means the service runs in a
  481. // single address-family mode. In tests using TCP we can confirm that
  482. // by trying to make a connection and seeing a failure. In UDP, it'd be
  483. // more complicated because we need to use a connected socket and catch
  484. // an error on a subsequent read operation. We could do it, but for
  485. // simplicity we only tests the easier cases for now.
  486. setDNSService(TEST_IPV6_ADDR);
  487. doTest(AF_INET6, IPPROTO_UDP);
  488. }
  489. TEST_F(RecursiveQueryTest, v6TCPSendSpecific) {
  490. setDNSService(TEST_IPV6_ADDR);
  491. doTest(AF_INET6, IPPROTO_TCP);
  492. EXPECT_THROW(sendTCP(AF_INET), IOError);
  493. }
  494. TEST_F(RecursiveQueryTest, v4UDPSendSpecific) {
  495. setDNSService(TEST_IPV4_ADDR);
  496. doTest(AF_INET, IPPROTO_UDP);
  497. }
  498. TEST_F(RecursiveQueryTest, v4TCPSendSpecific) {
  499. setDNSService(TEST_IPV4_ADDR);
  500. doTest(AF_INET, IPPROTO_TCP);
  501. EXPECT_THROW(sendTCP(AF_INET6), IOError);
  502. }
  503. TEST_F(RecursiveQueryTest, v6AddServer) {
  504. setDNSService();
  505. addServer(TEST_IPV6_ADDR, TEST_SERVER_PORT, IPPROTO_TCP);
  506. doTest(AF_INET6, IPPROTO_TCP);
  507. EXPECT_THROW(sendTCP(AF_INET), IOError);
  508. }
  509. TEST_F(RecursiveQueryTest, v4AddServer) {
  510. setDNSService();
  511. addServer(TEST_IPV4_ADDR, TEST_SERVER_PORT, IPPROTO_TCP);
  512. doTest(AF_INET, IPPROTO_TCP);
  513. EXPECT_THROW(sendTCP(AF_INET6), IOError);
  514. }
  515. TEST_F(RecursiveQueryTest, clearServers) {
  516. setDNSService();
  517. dns_service_->clearServers();
  518. EXPECT_THROW(sendTCP(AF_INET), IOError);
  519. EXPECT_THROW(sendTCP(AF_INET6), IOError);
  520. }
  521. TEST_F(RecursiveQueryTest, v6TCPOnly) {
  522. // Open only IPv6 TCP socket. A subsequent attempt of establishing an
  523. // IPv4/TCP connection should fail. See above for why we only test this
  524. // for TCP.
  525. setDNSService(false, true);
  526. EXPECT_THROW(sendTCP(AF_INET), IOError);
  527. }
  528. TEST_F(RecursiveQueryTest, v4TCPOnly) {
  529. setDNSService(true, false);
  530. EXPECT_THROW(sendTCP(AF_INET6), IOError);
  531. }
  532. vector<pair<string, uint16_t> >
  533. singleAddress(const string &address, uint16_t port) {
  534. vector<pair<string, uint16_t> > result;
  535. result.push_back(pair<string, uint16_t>(address, port));
  536. return (result);
  537. }
  538. TEST_F(RecursiveQueryTest, recursiveSetupV4) {
  539. setDNSService(true, false);
  540. uint16_t port = boost::lexical_cast<uint16_t>(TEST_CLIENT_PORT);
  541. EXPECT_NO_THROW(RecursiveQuery(*dns_service_,
  542. *nsas_, cache_,
  543. singleAddress(TEST_IPV4_ADDR, port),
  544. singleAddress(TEST_IPV4_ADDR, port)));
  545. }
  546. TEST_F(RecursiveQueryTest, recursiveSetupV6) {
  547. setDNSService(false, true);
  548. uint16_t port = boost::lexical_cast<uint16_t>(TEST_CLIENT_PORT);
  549. EXPECT_NO_THROW(RecursiveQuery(*dns_service_,
  550. *nsas_, cache_,
  551. singleAddress(TEST_IPV6_ADDR, port),
  552. singleAddress(TEST_IPV6_ADDR,port)));
  553. }
  554. // XXX:
  555. // This is very inadequate unit testing. It should be generalized into
  556. // a routine that can do this with variable address family, address, and
  557. // port, and with the various callbacks defined in such a way as to ensure
  558. // full code coverage including error cases.
  559. TEST_F(RecursiveQueryTest, forwarderSend) {
  560. setDNSService(true, false);
  561. // Note: We use the test prot plus one to ensure we aren't binding
  562. // to the same port as the actual server
  563. uint16_t port = boost::lexical_cast<uint16_t>(TEST_CLIENT_PORT);
  564. MockServer server(*io_service_);
  565. RecursiveQuery rq(*dns_service_,
  566. *nsas_, cache_,
  567. singleAddress(TEST_IPV4_ADDR, port),
  568. singleAddress(TEST_IPV4_ADDR, port));
  569. Question q(Name("example.com"), RRClass::IN(), RRType::TXT());
  570. Message query_message(Message::RENDER);
  571. isc::resolve::initResponseMessage(q, query_message);
  572. OutputBufferPtr buffer(new OutputBuffer(0));
  573. MessagePtr answer(new Message(Message::RENDER));
  574. rq.forward(ConstMessagePtr(&query_message), answer, buffer, &server);
  575. char data[4096];
  576. size_t size = sizeof(data);
  577. ASSERT_NO_THROW(recvUDP(AF_INET, data, size));
  578. Message m(Message::PARSE);
  579. InputBuffer ibuf(data, size);
  580. // Make sure we can parse the message that was sent
  581. EXPECT_NO_THROW(m.parseHeader(ibuf));
  582. EXPECT_NO_THROW(m.fromWire(ibuf));
  583. // Check that the question sent matches the one we wanted
  584. QuestionPtr q2 = *m.beginQuestion();
  585. EXPECT_EQ(q.getName(), q2->getName());
  586. EXPECT_EQ(q.getType(), q2->getType());
  587. EXPECT_EQ(q.getClass(), q2->getClass());
  588. }
  589. int
  590. createTestSocket() {
  591. ScopedAddrInfo sai(resolveAddress(AF_INET, IPPROTO_UDP, true));
  592. struct addrinfo* res = sai.res_;
  593. ScopedSocket sock(socket(res->ai_family, res->ai_socktype,
  594. res->ai_protocol));
  595. if (sock.s_ < 0) {
  596. isc_throw(IOError, "failed to open test socket");
  597. }
  598. if (bind(sock.s_, res->ai_addr, res->ai_addrlen) < 0) {
  599. isc_throw(IOError, "failed to bind test socket");
  600. }
  601. return (sock.release());
  602. }
  603. int
  604. setSocketTimeout(int sock, size_t tv_sec, size_t tv_usec) {
  605. const struct timeval timeo = { tv_sec, tv_usec };
  606. int recv_options = 0;
  607. if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &timeo, sizeof(timeo))) {
  608. if (errno == ENOPROTOOPT) { // see RecursiveQueryTest::recvUDP()
  609. recv_options = MSG_DONTWAIT;
  610. } else {
  611. isc_throw(IOError, "set RCVTIMEO failed: " << strerror(errno));
  612. }
  613. }
  614. return (recv_options);
  615. }
  616. // try to read from the socket max time
  617. // *num is incremented for every succesfull read
  618. // returns true if it can read max times, false otherwise
  619. bool tryRead(int sock, int recv_options, size_t max, int* num) {
  620. size_t i = 0;
  621. do {
  622. char inbuff[512];
  623. if (recv(sock, inbuff, sizeof(inbuff), recv_options) < 0) {
  624. return false;
  625. } else {
  626. ++i;
  627. ++*num;
  628. }
  629. } while (i < max);
  630. return true;
  631. }
  632. // Mock resolver callback for testing forward query.
  633. class MockResolverCallback : public isc::resolve::ResolverInterface::Callback {
  634. public:
  635. enum ResultValue {
  636. DEFAULT = 0,
  637. SUCCESS = 1,
  638. FAILURE = 2
  639. };
  640. MockResolverCallback(DNSServer* server):
  641. result(DEFAULT),
  642. server_(server->clone())
  643. {}
  644. ~MockResolverCallback() {
  645. delete server_;
  646. }
  647. void success(const isc::dns::MessagePtr response) {
  648. result = SUCCESS;
  649. server_->resume(true);
  650. }
  651. void failure() {
  652. result = FAILURE;
  653. server_->resume(false);
  654. }
  655. uint32_t result;
  656. private:
  657. DNSServer* server_;
  658. };
  659. // Test query timeout, set query timeout is lower than client timeout
  660. // and lookup timeout.
  661. TEST_F(RecursiveQueryTest, forwardQueryTimeout) {
  662. // Prepare the service (we do not use the common setup, we do not answer
  663. setDNSService();
  664. // Prepare the socket
  665. sock_.reset(createTestSocket());
  666. // Prepare the server
  667. bool done(true);
  668. MockServerStop server(*io_service_, &done);
  669. // Do the answer
  670. const uint16_t port = boost::lexical_cast<uint16_t>(TEST_CLIENT_PORT);
  671. RecursiveQuery query(*dns_service_,
  672. *nsas_, cache_,
  673. singleAddress(TEST_IPV4_ADDR, port),
  674. singleAddress(TEST_IPV4_ADDR, port),
  675. 10, 4000, 3000, 2);
  676. Question question(Name("example.net"), RRClass::IN(), RRType::A());
  677. OutputBufferPtr buffer(new OutputBuffer(0));
  678. MessagePtr answer(new Message(Message::RENDER));
  679. Message query_message(Message::RENDER);
  680. isc::resolve::initResponseMessage(question, query_message);
  681. boost::shared_ptr<MockResolverCallback> callback(new MockResolverCallback(&server));
  682. query.forward(ConstMessagePtr(&query_message), answer, buffer, &server, callback);
  683. // Run the test
  684. io_service_->run();
  685. EXPECT_EQ(callback->result, MockResolverCallback::FAILURE);
  686. }
  687. // If we set client timeout to lower than querytimeout, we should
  688. // get a failure answer
  689. // (no actual answer is given here yet. TODO the returned error message
  690. // should be tested)
  691. TEST_F(RecursiveQueryTest, forwardClientTimeout) {
  692. // Prepare the service (we do not use the common setup, we do not answer
  693. setDNSService();
  694. sock_.reset(createTestSocket());
  695. // Prepare the server
  696. bool done1(true);
  697. MockServerStop server(*io_service_, &done1);
  698. MessagePtr answer(new Message(Message::RENDER));
  699. // Do the answer
  700. const uint16_t port = boost::lexical_cast<uint16_t>(TEST_CLIENT_PORT);
  701. RecursiveQuery query(*dns_service_,
  702. *nsas_, cache_,
  703. singleAddress(TEST_IPV4_ADDR, port),
  704. singleAddress(TEST_IPV4_ADDR, port),
  705. 1000, 10, 4000, 4);
  706. Question q(Name("example.net"), RRClass::IN(), RRType::A());
  707. OutputBufferPtr buffer(new OutputBuffer(0));
  708. Message query_message(Message::RENDER);
  709. isc::resolve::initResponseMessage(q, query_message);
  710. boost::shared_ptr<MockResolverCallback> callback(new MockResolverCallback(&server));
  711. query.forward(ConstMessagePtr(&query_message), answer, buffer, &server, callback);
  712. // Run the test
  713. io_service_->run();
  714. EXPECT_EQ(callback->result, MockResolverCallback::FAILURE);
  715. }
  716. // If we set lookup timeout to lower than querytimeout, the lookup
  717. // will fail.
  718. TEST_F(RecursiveQueryTest, forwardLookupTimeout) {
  719. // Prepare the service (we do not use the common setup, we do not answer
  720. setDNSService();
  721. // Prepare the socket
  722. sock_.reset(createTestSocket());
  723. // Prepare the server
  724. bool done(true);
  725. MockServerStop server(*io_service_, &done);
  726. MessagePtr answer(new Message(Message::RENDER));
  727. // Do the answer
  728. const uint16_t port = boost::lexical_cast<uint16_t>(TEST_CLIENT_PORT);
  729. RecursiveQuery query(*dns_service_,
  730. *nsas_, cache_,
  731. singleAddress(TEST_IPV4_ADDR, port),
  732. singleAddress(TEST_IPV4_ADDR, port),
  733. 1000, 4000, 10, 5);
  734. Question question(Name("example.net"), RRClass::IN(), RRType::A());
  735. OutputBufferPtr buffer(new OutputBuffer(0));
  736. Message query_message(Message::RENDER);
  737. isc::resolve::initResponseMessage(question, query_message);
  738. boost::shared_ptr<MockResolverCallback> callback(new MockResolverCallback(&server));
  739. query.forward(ConstMessagePtr(&query_message), answer, buffer, &server, callback);
  740. // Run the test
  741. io_service_->run();
  742. EXPECT_EQ(callback->result, MockResolverCallback::FAILURE);
  743. }
  744. // Set everything very low and see if this doesn't cause weird
  745. // behaviour
  746. TEST_F(RecursiveQueryTest, lowtimeouts) {
  747. // Prepare the service (we do not use the common setup, we do not answer
  748. setDNSService();
  749. // Prepare the socket
  750. sock_.reset(createTestSocket());
  751. // Prepare the server
  752. bool done(true);
  753. MockServerStop server(*io_service_, &done);
  754. MessagePtr answer(new Message(Message::RENDER));
  755. // Do the answer
  756. const uint16_t port = boost::lexical_cast<uint16_t>(TEST_CLIENT_PORT);
  757. RecursiveQuery query(*dns_service_,
  758. *nsas_, cache_,
  759. singleAddress(TEST_IPV4_ADDR, port),
  760. singleAddress(TEST_IPV4_ADDR, port),
  761. 1, 1, 1, 1);
  762. Question question(Name("example.net"), RRClass::IN(), RRType::A());
  763. OutputBufferPtr buffer(new OutputBuffer(0));
  764. Message query_message(Message::RENDER);
  765. isc::resolve::initResponseMessage(question, query_message);
  766. boost::shared_ptr<MockResolverCallback> callback(new MockResolverCallback(&server));
  767. query.forward(ConstMessagePtr(&query_message), answer, buffer, &server, callback);
  768. // Run the test
  769. io_service_->run();
  770. EXPECT_EQ(callback->result, MockResolverCallback::FAILURE);
  771. }
  772. // as mentioned above, we need a more better framework for this,
  773. // in addition to that, this sends out queries into the world
  774. // (which we should catch somehow and fake replies for)
  775. // for the skeleton code, it shouldn't be too much of a problem
  776. // Ok so even we don't all have access to the DNS world right now,
  777. // so disabling these tests too.
  778. TEST_F(RecursiveQueryTest, DISABLED_recursiveSendOk) {
  779. setDNSService(true, false);
  780. bool done;
  781. MockServerStop server(*io_service_, &done);
  782. vector<pair<string, uint16_t> > empty_vector;
  783. RecursiveQuery rq(*dns_service_, *nsas_, cache_, empty_vector,
  784. empty_vector, 10000, 0);
  785. Question q(Name("www.isc.org"), RRClass::IN(), RRType::A());
  786. OutputBufferPtr buffer(new OutputBuffer(0));
  787. MessagePtr answer(new Message(Message::RENDER));
  788. rq.resolve(q, answer, buffer, &server);
  789. io_service_->run();
  790. // Check that the answer we got matches the one we wanted
  791. EXPECT_EQ(Rcode::NOERROR(), answer->getRcode());
  792. ASSERT_EQ(1, answer->getRRCount(Message::SECTION_ANSWER));
  793. RRsetPtr a = *answer->beginSection(Message::SECTION_ANSWER);
  794. EXPECT_EQ(q.getName(), a->getName());
  795. EXPECT_EQ(q.getType(), a->getType());
  796. EXPECT_EQ(q.getClass(), a->getClass());
  797. EXPECT_EQ(1, a->getRdataCount());
  798. }
  799. // see comments at previous test
  800. TEST_F(RecursiveQueryTest, DISABLED_recursiveSendNXDOMAIN) {
  801. setDNSService(true, false);
  802. bool done;
  803. MockServerStop server(*io_service_, &done);
  804. vector<pair<string, uint16_t> > empty_vector;
  805. RecursiveQuery rq(*dns_service_, *nsas_, cache_, empty_vector,
  806. empty_vector, 10000, 0);
  807. Question q(Name("wwwdoesnotexist.isc.org"), RRClass::IN(), RRType::A());
  808. OutputBufferPtr buffer(new OutputBuffer(0));
  809. MessagePtr answer(new Message(Message::RENDER));
  810. rq.resolve(q, answer, buffer, &server);
  811. io_service_->run();
  812. // Check that the answer we got matches the one we wanted
  813. EXPECT_EQ(Rcode::NXDOMAIN(), answer->getRcode());
  814. EXPECT_EQ(0, answer->getRRCount(Message::SECTION_ANSWER));
  815. }
  816. // Test that we don't start at root when we have a lower NS cached.
  817. TEST_F(RecursiveQueryTest, CachedNS) {
  818. setDNSService(true, true);
  819. // Check we have a reasonable fallback - if there's nothing of interest
  820. // in the cache, start at root.
  821. EXPECT_EQ(".", deepestDelegation(Name("www.somewhere.deep.example.org"),
  822. RRClass::IN(), cache_));
  823. // Prefill the cache. There's a zone with a NS and IP address for one
  824. // of them (to see that one is enough) and another deeper one, with NS,
  825. // but without IP.
  826. RRsetPtr nsUpper(new RRset(Name("example.org"), RRClass::IN(),
  827. RRType::NS(), RRTTL(300)));
  828. nsUpper->addRdata(rdata::generic::NS(Name("ns.example.org")));
  829. nsUpper->addRdata(rdata::generic::NS(Name("ns2.example.org")));
  830. RRsetPtr nsLower(new RRset(Name("somewhere.deep.example.org"),
  831. RRClass::IN(), RRType::NS(), RRTTL(300)));
  832. nsLower->addRdata(rdata::generic::NS(Name("ns.somewhere.deep.example.org"))
  833. );
  834. RRsetPtr nsIp(new RRset(Name("ns2.example.org"), RRClass::IN(),
  835. RRType::A(), RRTTL(300)));
  836. nsIp->addRdata(rdata::in::A("192.0.2.1"));
  837. // Make sure the test runs in the correct environment (we don't test
  838. // the cache, but we need it to unswer this way for the test, so we
  839. // just make sure)
  840. ASSERT_TRUE(cache_.update(nsUpper));
  841. ASSERT_TRUE(cache_.update(nsLower));
  842. ASSERT_TRUE(cache_.update(nsIp));
  843. RRsetPtr deepest(cache_.lookupDeepestNS(Name(
  844. "www.somewhere.deep.example.org"), RRClass::IN()));
  845. ASSERT_NE(RRsetPtr(), deepest);
  846. ASSERT_EQ(nsLower->getName(), deepest->getName());
  847. // Direct check of the function that chooses the delegation point
  848. // It should not use nsLower, because we don't have IP address for
  849. // that one. But it can choose nsUpper.
  850. EXPECT_EQ("example.org.",
  851. deepestDelegation(Name("www.somewhere.deep.example.org"),
  852. RRClass::IN(), cache_));
  853. // Now more complex and indirect test:
  854. // We ask it to resolve the name for us. It will pick up a delegation
  855. // point and ask NSAS for it. NSAS will in turn ask resolver for NS record
  856. // of the delegation point. We then pick it up from the fake resolver
  857. // and check it is the correct one. This checks the delegation point
  858. // travels safely trough the whole path there (it would be enough to check
  859. // it up to NSAS, but replacing NSAS is more complicated, so we just
  860. // include in the test as well for simplicity).
  861. // Prepare the recursive query
  862. vector<pair<string, uint16_t> > roots;
  863. roots.push_back(pair<string, uint16_t>("192.0.2.2", 53));
  864. RecursiveQuery rq(*dns_service_, *nsas_, cache_,
  865. vector<pair<string, uint16_t> >(), roots);
  866. // Ask a question at the bottom. It should not use the lower NS, because
  867. // it would lead to a loop in NS. But it can use the nsUpper one, it has
  868. // an IP address and we can avoid asking root.
  869. Question q(Name("www.somewhere.deep.example.org"), RRClass::IN(),
  870. RRType::A());
  871. OutputBufferPtr buffer(new OutputBuffer(0));
  872. MessagePtr answer(new Message(Message::RENDER));
  873. // The server is here so we have something to pass there
  874. MockServer server(*io_service_);
  875. rq.resolve(q, answer, buffer, &server);
  876. // We don't need to run the service in this test. We are interested only
  877. // in the place it starts resolving at
  878. // Look what is asked by NSAS - it should be our delegation point.
  879. EXPECT_NO_THROW(EXPECT_EQ(nsUpper->getName(),
  880. (*resolver_)[0]->getName()) <<
  881. "It starts resolving at the wrong place") <<
  882. "It does not ask NSAS anything, how does it know where to send?";
  883. }
  884. // TODO: add tests that check whether the cache is updated on succesfull
  885. // responses, and not updated on failures.
  886. }