dhcp6_test_utils.h 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532
  1. // Copyright (C) 2013-2014 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. /// @file dhcp6_test_utils.h
  15. ///
  16. /// @brief This file contains utility classes used for DHCPv6 server testing
  17. #ifndef DHCP6_TEST_UTILS_H
  18. #define DHCP6_TEST_UTILS_H
  19. #include <gtest/gtest.h>
  20. #include <dhcp/pkt6.h>
  21. #include <dhcp/option6_ia.h>
  22. #include <dhcp/option6_iaaddr.h>
  23. #include <dhcp/option6_iaprefix.h>
  24. #include <dhcp/option_int_array.h>
  25. #include <dhcp/option_custom.h>
  26. #include <dhcp/iface_mgr.h>
  27. #include <dhcpsrv/cfgmgr.h>
  28. #include <dhcpsrv/lease_mgr.h>
  29. #include <dhcpsrv/lease_mgr_factory.h>
  30. #include <dhcp6/dhcp6_srv.h>
  31. #include <hooks/hooks_manager.h>
  32. #include <config/ccsession.h>
  33. #include <list>
  34. namespace isc {
  35. namespace test {
  36. /// @brief "naked" Dhcpv6Srv class that exposes internal members
  37. class NakedDhcpv6Srv: public isc::dhcp::Dhcpv6Srv {
  38. public:
  39. NakedDhcpv6Srv(uint16_t port) : isc::dhcp::Dhcpv6Srv(port) {
  40. // Open the "memfile" database for leases
  41. std::string memfile = "type=memfile";
  42. isc::dhcp::LeaseMgrFactory::create(memfile);
  43. }
  44. /// @brief fakes packet reception
  45. /// @param timeout ignored
  46. ///
  47. /// The method receives all packets queued in receive
  48. /// queue, one after another. Once the queue is empty,
  49. /// it initiates the shutdown procedure.
  50. ///
  51. /// See fake_received_ field for description
  52. virtual isc::dhcp::Pkt6Ptr receivePacket(int /*timeout*/) {
  53. // If there is anything prepared as fake incoming
  54. // traffic, use it
  55. if (!fake_received_.empty()) {
  56. isc::dhcp::Pkt6Ptr pkt = fake_received_.front();
  57. fake_received_.pop_front();
  58. return (pkt);
  59. }
  60. // If not, just trigger shutdown and
  61. // return immediately
  62. shutdown();
  63. return (isc::dhcp::Pkt6Ptr());
  64. }
  65. /// @brief fake packet sending
  66. ///
  67. /// Pretend to send a packet, but instead just store
  68. /// it in fake_send_ list where test can later inspect
  69. /// server's response.
  70. virtual void sendPacket(const isc::dhcp::Pkt6Ptr& pkt) {
  71. fake_sent_.push_back(pkt);
  72. }
  73. /// @brief adds a packet to fake receive queue
  74. ///
  75. /// See fake_received_ field for description
  76. void fakeReceive(const isc::dhcp::Pkt6Ptr& pkt) {
  77. fake_received_.push_back(pkt);
  78. }
  79. virtual ~NakedDhcpv6Srv() {
  80. // Close the lease database
  81. isc::dhcp::LeaseMgrFactory::destroy();
  82. }
  83. using Dhcpv6Srv::processSolicit;
  84. using Dhcpv6Srv::processRequest;
  85. using Dhcpv6Srv::processRenew;
  86. using Dhcpv6Srv::processRelease;
  87. using Dhcpv6Srv::processClientFqdn;
  88. using Dhcpv6Srv::createNameChangeRequests;
  89. using Dhcpv6Srv::createRemovalNameChangeRequest;
  90. using Dhcpv6Srv::createStatusCode;
  91. using Dhcpv6Srv::selectSubnet;
  92. using Dhcpv6Srv::testServerID;
  93. using Dhcpv6Srv::sanityCheck;
  94. using Dhcpv6Srv::classifyPacket;
  95. using Dhcpv6Srv::loadServerID;
  96. using Dhcpv6Srv::writeServerID;
  97. using Dhcpv6Srv::unpackOptions;
  98. using Dhcpv6Srv::name_change_reqs_;
  99. /// @brief packets we pretend to receive
  100. ///
  101. /// Instead of setting up sockets on interfaces that change between
  102. /// OSes, it is much easier to fake packet reception. This is a list
  103. /// of packets that we pretend to have received. You can schedule
  104. /// new packets to be received using fakeReceive() and
  105. /// NakedDhcpv6Srv::receivePacket() methods.
  106. std::list<isc::dhcp::Pkt6Ptr> fake_received_;
  107. std::list<isc::dhcp::Pkt6Ptr> fake_sent_;
  108. };
  109. static const char* DUID_FILE = "server-id-test.txt";
  110. // test fixture for any tests requiring blank/empty configuration
  111. // serves as base class for additional tests
  112. class NakedDhcpv6SrvTest : public ::testing::Test {
  113. public:
  114. NakedDhcpv6SrvTest() : rcode_(-1) {
  115. // it's ok if that fails. There should not be such a file anyway
  116. unlink(DUID_FILE);
  117. const isc::dhcp::IfaceMgr::IfaceCollection& ifaces =
  118. isc::dhcp::IfaceMgr::instance().getIfaces();
  119. // There must be some interface detected
  120. if (ifaces.empty()) {
  121. // We can't use ASSERT in constructor
  122. ADD_FAILURE() << "No interfaces detected.";
  123. }
  124. valid_iface_ = ifaces.begin()->getName();
  125. }
  126. // Generate IA_NA or IA_PD option with specified parameters
  127. boost::shared_ptr<isc::dhcp::Option6IA> generateIA
  128. (uint16_t type, uint32_t iaid, uint32_t t1, uint32_t t2);
  129. /// @brief generates interface-id option, based on text
  130. ///
  131. /// @param iface_id textual representation of the interface-id content
  132. ///
  133. /// @return pointer to the option object
  134. isc::dhcp::OptionPtr generateInterfaceId(const std::string& iface_id) {
  135. isc::dhcp::OptionBuffer tmp(iface_id.begin(), iface_id.end());
  136. return (isc::dhcp::OptionPtr
  137. (new isc::dhcp::Option(isc::dhcp::Option::V6,
  138. D6O_INTERFACE_ID, tmp)));
  139. }
  140. // Generate client-id option
  141. isc::dhcp::OptionPtr generateClientId(size_t duid_size = 32) {
  142. isc::dhcp::OptionBuffer clnt_duid(duid_size);
  143. for (int i = 0; i < duid_size; i++) {
  144. clnt_duid[i] = 100 + i;
  145. }
  146. duid_ = isc::dhcp::DuidPtr(new isc::dhcp::DUID(clnt_duid));
  147. return (isc::dhcp::OptionPtr
  148. (new isc::dhcp::Option(isc::dhcp::Option::V6, D6O_CLIENTID,
  149. clnt_duid.begin(),
  150. clnt_duid.begin() + duid_size)));
  151. }
  152. // Checks if server response (ADVERTISE or REPLY) includes proper
  153. // server-id.
  154. void checkServerId(const isc::dhcp::Pkt6Ptr& rsp,
  155. const isc::dhcp::OptionPtr& expected_srvid)
  156. {
  157. // check that server included its server-id
  158. isc::dhcp::OptionPtr tmp = rsp->getOption(D6O_SERVERID);
  159. EXPECT_EQ(tmp->getType(), expected_srvid->getType() );
  160. ASSERT_EQ(tmp->len(), expected_srvid->len() );
  161. EXPECT_TRUE(tmp->getData() == expected_srvid->getData());
  162. }
  163. // Checks if server response (ADVERTISE or REPLY) includes proper
  164. // client-id.
  165. void checkClientId(const isc::dhcp::Pkt6Ptr& rsp,
  166. const isc::dhcp::OptionPtr& expected_clientid)
  167. {
  168. // check that server included our own client-id
  169. isc::dhcp::OptionPtr tmp = rsp->getOption(D6O_CLIENTID);
  170. ASSERT_TRUE(tmp);
  171. EXPECT_EQ(expected_clientid->getType(), tmp->getType());
  172. ASSERT_EQ(expected_clientid->len(), tmp->len());
  173. // check that returned client-id is valid
  174. EXPECT_TRUE(expected_clientid->getData() == tmp->getData());
  175. }
  176. // Checks if server response is a NAK
  177. void checkNakResponse(const isc::dhcp::Pkt6Ptr& rsp,
  178. uint8_t expected_message_type,
  179. uint32_t expected_transid,
  180. uint16_t expected_status_code)
  181. {
  182. // Check if we get response at all
  183. checkResponse(rsp, expected_message_type, expected_transid);
  184. // Check that IA_NA was returned
  185. isc::dhcp::OptionPtr option_ia_na = rsp->getOption(D6O_IA_NA);
  186. ASSERT_TRUE(option_ia_na);
  187. // check that the status is no address available
  188. boost::shared_ptr<isc::dhcp::Option6IA> ia =
  189. boost::dynamic_pointer_cast<isc::dhcp::Option6IA>(option_ia_na);
  190. ASSERT_TRUE(ia);
  191. checkIA_NAStatusCode(ia, expected_status_code);
  192. }
  193. // Checks that server rejected IA_NA, i.e. that it has no addresses and
  194. // that expected status code really appears there. In some limited cases
  195. // (reply to RELEASE) it may be used to verify positive case, where
  196. // IA_NA response is expected to not include address.
  197. //
  198. // Status code indicates type of error encountered (in theory it can also
  199. // indicate success, but servers typically don't send success status
  200. // as this is the default result and it saves bandwidth)
  201. void checkIA_NAStatusCode
  202. (const boost::shared_ptr<isc::dhcp::Option6IA>& ia,
  203. uint16_t expected_status_code)
  204. {
  205. // Make sure there is no address assigned.
  206. EXPECT_FALSE(ia->getOption(D6O_IAADDR));
  207. // T1, T2 should be zeroed
  208. EXPECT_EQ(0, ia->getT1());
  209. EXPECT_EQ(0, ia->getT2());
  210. isc::dhcp::OptionCustomPtr status =
  211. boost::dynamic_pointer_cast<isc::dhcp::OptionCustom>
  212. (ia->getOption(D6O_STATUS_CODE));
  213. // It is ok to not include status success as this is the default
  214. // behavior
  215. if (expected_status_code == STATUS_Success && !status) {
  216. return;
  217. }
  218. EXPECT_TRUE(status);
  219. if (status) {
  220. // We don't have dedicated class for status code, so let's
  221. // just interpret first 2 bytes as status. Remainder of the
  222. // status code option content is just a text explanation
  223. // what went wrong.
  224. EXPECT_EQ(static_cast<uint16_t>(expected_status_code),
  225. status->readInteger<uint16_t>(0));
  226. }
  227. }
  228. void checkMsgStatusCode(const isc::dhcp::Pkt6Ptr& msg,
  229. uint16_t expected_status)
  230. {
  231. isc::dhcp::OptionCustomPtr status =
  232. boost::dynamic_pointer_cast<isc::dhcp::OptionCustom>
  233. (msg->getOption(D6O_STATUS_CODE));
  234. // It is ok to not include status success as this is the default
  235. // behavior
  236. if (expected_status == STATUS_Success && !status) {
  237. return;
  238. }
  239. EXPECT_TRUE(status);
  240. if (status) {
  241. // We don't have dedicated class for status code, so let's
  242. // just interpret first 2 bytes as status. Remainder of the
  243. // status code option content is just a text explanation
  244. // what went wrong.
  245. EXPECT_EQ(static_cast<uint16_t>(expected_status),
  246. status->readInteger<uint16_t>(0));
  247. }
  248. }
  249. // Basic checks for generated response (message type and transaction-id).
  250. void checkResponse(const isc::dhcp::Pkt6Ptr& rsp,
  251. uint8_t expected_message_type,
  252. uint32_t expected_transid) {
  253. ASSERT_TRUE(rsp);
  254. EXPECT_EQ(expected_message_type, rsp->getType());
  255. EXPECT_EQ(expected_transid, rsp->getTransid());
  256. }
  257. virtual ~NakedDhcpv6SrvTest() {
  258. // Let's clean up if there is such a file.
  259. unlink(DUID_FILE);
  260. isc::hooks::HooksManager::preCalloutsLibraryHandle()
  261. .deregisterAllCallouts("buffer6_receive");
  262. isc::hooks::HooksManager::preCalloutsLibraryHandle()
  263. .deregisterAllCallouts("buffer6_send");
  264. isc::hooks::HooksManager::preCalloutsLibraryHandle()
  265. .deregisterAllCallouts("lease6_renew");
  266. isc::hooks::HooksManager::preCalloutsLibraryHandle()
  267. .deregisterAllCallouts("lease6_release");
  268. isc::hooks::HooksManager::preCalloutsLibraryHandle()
  269. .deregisterAllCallouts("pkt6_receive");
  270. isc::hooks::HooksManager::preCalloutsLibraryHandle()
  271. .deregisterAllCallouts("pkt6_send");
  272. isc::hooks::HooksManager::preCalloutsLibraryHandle()
  273. .deregisterAllCallouts("subnet6_select");
  274. };
  275. // A DUID used in most tests (typically as client-id)
  276. isc::dhcp::DuidPtr duid_;
  277. int rcode_;
  278. isc::data::ConstElementPtr comment_;
  279. // Name of a valid network interface
  280. std::string valid_iface_;
  281. };
  282. // Provides suport for tests against a preconfigured subnet6
  283. // extends upon NakedDhcp6SrvTest
  284. class Dhcpv6SrvTest : public NakedDhcpv6SrvTest {
  285. public:
  286. /// Name of the server-id file (used in server-id tests)
  287. /// @brief Constructor that initalizes a simple default configuration
  288. ///
  289. /// Sets up a single subnet6 with one pool for addresses and second
  290. /// pool for prefixes.
  291. Dhcpv6SrvTest() {
  292. subnet_ = isc::dhcp::Subnet6Ptr
  293. (new isc::dhcp::Subnet6(isc::asiolink::IOAddress("2001:db8:1::"),
  294. 48, 1000, 2000, 3000, 4000));
  295. pool_ = isc::dhcp::Pool6Ptr
  296. (new isc::dhcp::Pool6(isc::dhcp::Lease::TYPE_NA,
  297. isc::asiolink::IOAddress("2001:db8:1:1::"),
  298. 64));
  299. subnet_->addPool(pool_);
  300. isc::dhcp::CfgMgr::instance().deleteSubnets6();
  301. isc::dhcp::CfgMgr::instance().addSubnet6(subnet_);
  302. // configure PD pool
  303. pd_pool_ = isc::dhcp::Pool6Ptr
  304. (new isc::dhcp::Pool6(isc::dhcp::Lease::TYPE_PD,
  305. isc::asiolink::IOAddress("2001:db8:1:2::"),
  306. 64, 80));
  307. subnet_->addPool(pd_pool_);
  308. }
  309. /// @brief destructor
  310. ///
  311. /// Removes existing configuration.
  312. ~Dhcpv6SrvTest() {
  313. isc::dhcp::CfgMgr::instance().deleteSubnets6();
  314. };
  315. /// @brief Checks that server response (ADVERTISE or REPLY) contains proper
  316. /// IA_NA option
  317. ///
  318. /// @param rsp server's response
  319. /// @param expected_iaid expected IAID value
  320. /// @param expected_t1 expected T1 value
  321. /// @param expected_t2 expected T2 value
  322. /// @return IAADDR option for easy chaining with checkIAAddr method
  323. boost::shared_ptr<isc::dhcp::Option6IAAddr>
  324. checkIA_NA(const isc::dhcp::Pkt6Ptr& rsp, uint32_t expected_iaid,
  325. uint32_t expected_t1, uint32_t expected_t2);
  326. /// @brief Checks that server response (ADVERTISE or REPLY) contains proper
  327. /// IA_PD option
  328. ///
  329. /// @param rsp server's response
  330. /// @param expected_iaid expected IAID value
  331. /// @param expected_t1 expected T1 value
  332. /// @param expected_t2 expected T2 value
  333. /// @return IAPREFIX option for easy chaining with checkIAAddr method
  334. boost::shared_ptr<isc::dhcp::Option6IAPrefix>
  335. checkIA_PD(const isc::dhcp::Pkt6Ptr& rsp, uint32_t expected_iaid,
  336. uint32_t expected_t1, uint32_t expected_t2);
  337. // Check that generated IAADDR option contains expected address
  338. // and lifetime values match the configured subnet
  339. void checkIAAddr(const boost::shared_ptr<isc::dhcp::Option6IAAddr>& addr,
  340. const isc::asiolink::IOAddress& expected_addr,
  341. isc::dhcp::Lease::Type type) {
  342. // Check that the assigned address is indeed from the configured pool.
  343. // Note that when comparing addresses, we compare the textual
  344. // representation. IOAddress does not support being streamed to
  345. // an ostream, which means it can't be used in EXPECT_EQ.
  346. EXPECT_TRUE(subnet_->inPool(type, addr->getAddress()));
  347. EXPECT_EQ(expected_addr.toText(), addr->getAddress().toText());
  348. EXPECT_EQ(addr->getPreferred(), subnet_->getPreferred());
  349. EXPECT_EQ(addr->getValid(), subnet_->getValid());
  350. }
  351. // Checks if the lease sent to client is present in the database
  352. // and is valid when checked agasint the configured subnet
  353. isc::dhcp::Lease6Ptr checkLease
  354. (const isc::dhcp::DuidPtr& duid, const isc::dhcp::OptionPtr& ia_na,
  355. boost::shared_ptr<isc::dhcp::Option6IAAddr> addr);
  356. /// @brief Verifies received IAPrefix option
  357. ///
  358. /// Verifies if the received IAPrefix option matches the lease in the
  359. /// database.
  360. ///
  361. /// @param duid client's DUID
  362. /// @param ia_pd IA_PD option that contains the IAPRefix option
  363. /// @param prefix pointer to the IAPREFIX option
  364. /// @return corresponding IPv6 lease (if found)
  365. isc::dhcp::Lease6Ptr checkPdLease
  366. (const isc::dhcp::DuidPtr& duid, const isc::dhcp::OptionPtr& ia_pd,
  367. boost::shared_ptr<isc::dhcp::Option6IAPrefix> prefix);
  368. /// @brief Creates a message with specified IA
  369. ///
  370. /// A utility function that creates a message of the specified type with
  371. /// a specified container (IA_NA or IA_PD) and an address or prefix
  372. /// inside it.
  373. ///
  374. /// @param message_type type of the message (e.g. DHCPV6_SOLICIT)
  375. /// @param lease_type type of a lease (TYPE_NA or TYPE_PD)
  376. /// @param addr address or prefix to use in IADDRESS or IAPREFIX options
  377. /// @param prefix_len length of the prefix (used for prefixes only)
  378. /// @param iaid IA identifier (used in IA_XX option)
  379. /// @return created message
  380. isc::dhcp::Pkt6Ptr
  381. createMessage(uint8_t message_type, isc::dhcp::Lease::Type lease_type,
  382. const isc::asiolink::IOAddress& addr,
  383. const uint8_t prefix_len, uint32_t iaid);
  384. /// @brief Performs basic (positive) RENEW test
  385. ///
  386. /// See renewBasic and pdRenewBasic tests for detailed explanation.
  387. /// In essence the test attempts to perform a successful RENEW scenario.
  388. ///
  389. /// This method does not throw, but uses gtest macros to signify failures.
  390. ///
  391. /// @param type type (TYPE_NA or TYPE_PD)
  392. /// @param existing_addr address to be preinserted into the database
  393. /// @param renew_addr address being sent in RENEW
  394. /// @param prefix_len length of the prefix (128 for addresses)
  395. void
  396. testRenewBasic(isc::dhcp::Lease::Type type,
  397. const std::string& existing_addr,
  398. const std::string& renew_addr, const uint8_t prefix_len);
  399. /// @brief Performs negative RENEW test
  400. ///
  401. /// See renewReject and pdRenewReject tests for detailed explanation.
  402. /// In essence the test attempts to perform couple failed RENEW scenarios.
  403. ///
  404. /// This method does not throw, but uses gtest macros to signify failures.
  405. ///
  406. /// @param type type (TYPE_NA or TYPE_PD)
  407. /// @param addr address being sent in RENEW
  408. void
  409. testRenewReject(isc::dhcp::Lease::Type type,
  410. const isc::asiolink::IOAddress& addr);
  411. /// @brief Performs basic (positive) RELEASE test
  412. ///
  413. /// See releaseBasic and pdReleaseBasic tests for detailed explanation.
  414. /// In essence the test attempts to perform a successful RELEASE scenario.
  415. ///
  416. /// This method does not throw, but uses gtest macros to signify failures.
  417. ///
  418. /// @param type type (TYPE_NA or TYPE_PD)
  419. /// @param existing address to be preinserted into the database
  420. /// @param release_addr address being sent in RELEASE
  421. void
  422. testReleaseBasic(isc::dhcp::Lease::Type type,
  423. const isc::asiolink::IOAddress& existing,
  424. const isc::asiolink::IOAddress& release_addr);
  425. /// @brief Performs negative RELEASE test
  426. ///
  427. /// See releaseReject and pdReleaseReject tests for detailed
  428. /// explanation. In essence the test attempts to perform couple
  429. /// failed RELEASE scenarios.
  430. ///
  431. /// This method does not throw, but uses gtest macros to signify failures.
  432. ///
  433. /// @param type type (TYPE_NA or TYPE_PD)
  434. /// @param addr address being sent in RELEASE
  435. void
  436. testReleaseReject(isc::dhcp::Lease::Type type,
  437. const isc::asiolink::IOAddress& addr);
  438. // see wireshark.cc for descriptions
  439. // The descriptions are too large and too closely related to the
  440. // code, so it is kept in .cc rather than traditionally in .h
  441. isc::dhcp::Pkt6Ptr captureSimpleSolicit();
  442. isc::dhcp::Pkt6Ptr captureRelayedSolicit();
  443. isc::dhcp::Pkt6Ptr captureDocsisRelayedSolicit();
  444. isc::dhcp::Pkt6Ptr captureeRouterRelayedSolicit();
  445. /// @brief Auxiliary method that sets Pkt6 fields
  446. ///
  447. /// Used to reconstruct captured packets. Sets UDP ports, interface names,
  448. /// and other fields to some believable values.
  449. /// @param pkt packet that will have its fields set
  450. void captureSetDefaultFields(const isc::dhcp::Pkt6Ptr& pkt);
  451. /// A subnet used in most tests
  452. isc::dhcp::Subnet6Ptr subnet_;
  453. /// A normal, non-temporary pool used in most tests
  454. isc::dhcp::Pool6Ptr pool_;
  455. /// A prefix pool used in most tests
  456. isc::dhcp::Pool6Ptr pd_pool_;
  457. };
  458. }; // end of isc::test namespace
  459. }; // end of isc namespace
  460. #endif // DHCP6_TEST_UTILS_H