dhcp6_test_utils.h 21 KB

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