hooks_unittest.cc 59 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625
  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. #include <config.h>
  15. #include <asiolink/io_address.h>
  16. #include <dhcp/dhcp6.h>
  17. #include <dhcp/duid.h>
  18. #include <dhcp6/json_config_parser.h>
  19. #include <dhcp/dhcp6.h>
  20. #include <dhcpsrv/cfgmgr.h>
  21. #include <dhcpsrv/lease_mgr.h>
  22. #include <dhcpsrv/lease_mgr_factory.h>
  23. #include <dhcpsrv/utils.h>
  24. #include <util/buffer.h>
  25. #include <util/range_utilities.h>
  26. #include <hooks/server_hooks.h>
  27. #include <dhcp6/tests/dhcp6_test_utils.h>
  28. #include <dhcp6/tests/dhcp6_client.h>
  29. #include <dhcp/tests/iface_mgr_test_config.h>
  30. #include <dhcp/tests/pkt_captures.h>
  31. #include <cc/command_interpreter.h>
  32. #include <boost/scoped_ptr.hpp>
  33. #include <gtest/gtest.h>
  34. #include <unistd.h>
  35. #include <fstream>
  36. #include <iostream>
  37. #include <sstream>
  38. using namespace isc;
  39. using namespace isc::data;
  40. using namespace isc::dhcp::test;
  41. using namespace isc::asiolink;
  42. using namespace isc::dhcp;
  43. using namespace isc::util;
  44. using namespace isc::hooks;
  45. using namespace std;
  46. // namespace has to be named, because friends are defined in Dhcpv6Srv class
  47. // Maybe it should be isc::test?
  48. namespace {
  49. // Checks if hooks are implemented properly.
  50. TEST_F(Dhcpv6SrvTest, Hooks) {
  51. NakedDhcpv6Srv srv(0);
  52. // check if appropriate hooks are registered
  53. int hook_index_buffer6_receive = -1;
  54. int hook_index_buffer6_send = -1;
  55. int hook_index_lease6_renew = -1;
  56. int hook_index_lease6_release = -1;
  57. int hook_index_pkt6_received = -1;
  58. int hook_index_select_subnet = -1;
  59. int hook_index_pkt6_send = -1;
  60. // check if appropriate indexes are set
  61. EXPECT_NO_THROW(hook_index_buffer6_receive = ServerHooks::getServerHooks()
  62. .getIndex("buffer6_receive"));
  63. EXPECT_NO_THROW(hook_index_buffer6_send = ServerHooks::getServerHooks()
  64. .getIndex("buffer6_send"));
  65. EXPECT_NO_THROW(hook_index_lease6_renew = ServerHooks::getServerHooks()
  66. .getIndex("lease6_renew"));
  67. EXPECT_NO_THROW(hook_index_lease6_release = ServerHooks::getServerHooks()
  68. .getIndex("lease6_release"));
  69. EXPECT_NO_THROW(hook_index_pkt6_received = ServerHooks::getServerHooks()
  70. .getIndex("pkt6_receive"));
  71. EXPECT_NO_THROW(hook_index_select_subnet = ServerHooks::getServerHooks()
  72. .getIndex("subnet6_select"));
  73. EXPECT_NO_THROW(hook_index_pkt6_send = ServerHooks::getServerHooks()
  74. .getIndex("pkt6_send"));
  75. EXPECT_TRUE(hook_index_pkt6_received > 0);
  76. EXPECT_TRUE(hook_index_select_subnet > 0);
  77. EXPECT_TRUE(hook_index_pkt6_send > 0);
  78. EXPECT_TRUE(hook_index_buffer6_receive > 0);
  79. EXPECT_TRUE(hook_index_buffer6_send > 0);
  80. EXPECT_TRUE(hook_index_lease6_renew > 0);
  81. EXPECT_TRUE(hook_index_lease6_release > 0);
  82. }
  83. /// @brief a class dedicated to Hooks testing in DHCPv6 server
  84. ///
  85. /// This class has a number of static members, because each non-static
  86. /// method has implicit 'this' parameter, so it does not match callout
  87. /// signature and couldn't be registered. Furthermore, static methods
  88. /// can't modify non-static members (for obvious reasons), so many
  89. /// fields are declared static. It is still better to keep them as
  90. /// one class rather than unrelated collection of global objects.
  91. class HooksDhcpv6SrvTest : public Dhcpv6SrvTest {
  92. public:
  93. /// @brief creates Dhcpv6Srv and prepares buffers for callouts
  94. HooksDhcpv6SrvTest() {
  95. // Allocate new DHCPv6 Server
  96. srv_.reset(new NakedDhcpv6Srv(0));
  97. // Clear static buffers
  98. resetCalloutBuffers();
  99. }
  100. /// @brief destructor (deletes Dhcpv6Srv)
  101. ~HooksDhcpv6SrvTest() {
  102. }
  103. /// @brief creates an option with specified option code
  104. ///
  105. /// This method is static, because it is used from callouts
  106. /// that do not have a pointer to HooksDhcpv6SSrvTest object
  107. ///
  108. /// @param option_code code of option to be created
  109. ///
  110. /// @return pointer to create option object
  111. static OptionPtr createOption(uint16_t option_code) {
  112. uint8_t payload[] = {
  113. 0xa, 0xb, 0xc, 0xe, 0xf, 0x10, 0x11, 0x12, 0x13, 0x14
  114. };
  115. OptionBuffer tmp(payload, payload + sizeof(payload));
  116. return OptionPtr(new Option(Option::V6, option_code, tmp));
  117. }
  118. /// test callback that stores received callout name and pkt6 value
  119. /// @param callout_handle handle passed by the hooks framework
  120. /// @return always 0
  121. static int
  122. pkt6_receive_callout(CalloutHandle& callout_handle) {
  123. callback_name_ = string("pkt6_receive");
  124. callout_handle.getArgument("query6", callback_pkt6_);
  125. callback_argument_names_ = callout_handle.getArgumentNames();
  126. return (0);
  127. }
  128. /// test callback that changes client-id value
  129. /// @param callout_handle handle passed by the hooks framework
  130. /// @return always 0
  131. static int
  132. pkt6_receive_change_clientid(CalloutHandle& callout_handle) {
  133. Pkt6Ptr pkt;
  134. callout_handle.getArgument("query6", pkt);
  135. // Get rid of the old client-id
  136. pkt->delOption(D6O_CLIENTID);
  137. // Add a new option
  138. pkt->addOption(createOption(D6O_CLIENTID));
  139. // Carry on as usual
  140. return pkt6_receive_callout(callout_handle);
  141. }
  142. /// Test callback that deletes client-id
  143. /// @param callout_handle handle passed by the hooks framework
  144. /// @return always 0
  145. static int
  146. pkt6_receive_delete_clientid(CalloutHandle& callout_handle) {
  147. Pkt6Ptr pkt;
  148. callout_handle.getArgument("query6", pkt);
  149. // Get rid of the old client-id
  150. pkt->delOption(D6O_CLIENTID);
  151. // Carry on as usual
  152. return pkt6_receive_callout(callout_handle);
  153. }
  154. /// Test callback that sets skip flag
  155. /// @param callout_handle handle passed by the hooks framework
  156. /// @return always 0
  157. static int
  158. pkt6_receive_skip(CalloutHandle& callout_handle) {
  159. Pkt6Ptr pkt;
  160. callout_handle.getArgument("query6", pkt);
  161. callout_handle.setStatus(CalloutHandle::NEXT_STEP_SKIP);
  162. // Carry on as usual
  163. return pkt6_receive_callout(callout_handle);
  164. }
  165. /// Test callback that stores received callout name and pkt6 value
  166. /// @param callout_handle handle passed by the hooks framework
  167. /// @return always 0
  168. static int
  169. buffer6_receive_callout(CalloutHandle& callout_handle) {
  170. callback_name_ = string("buffer6_receive");
  171. callout_handle.getArgument("query6", callback_pkt6_);
  172. callback_argument_names_ = callout_handle.getArgumentNames();
  173. return (0);
  174. }
  175. /// Test callback that changes first byte of client-id value
  176. /// @param callout_handle handle passed by the hooks framework
  177. /// @return always 0
  178. static int
  179. buffer6_receive_change_clientid(CalloutHandle& callout_handle) {
  180. Pkt6Ptr pkt;
  181. callout_handle.getArgument("query6", pkt);
  182. // If there is at least one option with data
  183. if (pkt->data_.size() > Pkt6::DHCPV6_PKT_HDR_LEN + Option::OPTION6_HDR_LEN) {
  184. // Offset of the first byte of the first option. Let's set this byte
  185. // to some new value that we could later check
  186. pkt->data_[Pkt6::DHCPV6_PKT_HDR_LEN + Option::OPTION6_HDR_LEN] = 0xff;
  187. }
  188. // Carry on as usual
  189. return buffer6_receive_callout(callout_handle);
  190. }
  191. /// Test callback that deletes client-id
  192. /// @param callout_handle handle passed by the hooks framework
  193. /// @return always 0
  194. static int
  195. buffer6_receive_delete_clientid(CalloutHandle& callout_handle) {
  196. Pkt6Ptr pkt;
  197. callout_handle.getArgument("query6", pkt);
  198. // this is modified SOLICIT (with missing mandatory client-id)
  199. uint8_t data[] = {
  200. 1, // type 1 = SOLICIT
  201. 0xca, 0xfe, 0x01, // trans-id = 0xcafe01
  202. 0, 3, // option type 3 (IA_NA)
  203. 0, 12, // option length 12
  204. 0, 0, 0, 1, // iaid = 1
  205. 0, 0, 0, 0, // T1 = 0
  206. 0, 0, 0, 0 // T2 = 0
  207. };
  208. OptionBuffer modifiedMsg(data, data + sizeof(data));
  209. pkt->data_ = modifiedMsg;
  210. // carry on as usual
  211. return buffer6_receive_callout(callout_handle);
  212. }
  213. /// Test callback that sets skip flag
  214. /// @param callout_handle handle passed by the hooks framework
  215. /// @return always 0
  216. static int
  217. buffer6_receive_skip(CalloutHandle& callout_handle) {
  218. callout_handle.setStatus(CalloutHandle::NEXT_STEP_SKIP);
  219. // Carry on as usual
  220. return buffer6_receive_callout(callout_handle);
  221. }
  222. /// Test callback that stores received callout name and pkt6 value
  223. /// @param callout_handle handle passed by the hooks framework
  224. /// @return always 0
  225. static int
  226. pkt6_send_callout(CalloutHandle& callout_handle) {
  227. callback_name_ = string("pkt6_send");
  228. callout_handle.getArgument("response6", callback_pkt6_);
  229. callback_argument_names_ = callout_handle.getArgumentNames();
  230. return (0);
  231. }
  232. // Test callback that changes server-id
  233. /// @param callout_handle handle passed by the hooks framework
  234. /// @return always 0
  235. static int
  236. pkt6_send_change_serverid(CalloutHandle& callout_handle) {
  237. Pkt6Ptr pkt;
  238. callout_handle.getArgument("response6", pkt);
  239. // Get rid of the old server-id
  240. pkt->delOption(D6O_SERVERID);
  241. // Add a new option
  242. pkt->addOption(createOption(D6O_SERVERID));
  243. // Carry on as usual
  244. return pkt6_send_callout(callout_handle);
  245. }
  246. /// Test callback that deletes server-id
  247. /// @param callout_handle handle passed by the hooks framework
  248. /// @return always 0
  249. static int
  250. pkt6_send_delete_serverid(CalloutHandle& callout_handle) {
  251. Pkt6Ptr pkt;
  252. callout_handle.getArgument("response6", pkt);
  253. // Get rid of the old client-id
  254. pkt->delOption(D6O_SERVERID);
  255. // Carry on as usual
  256. return pkt6_send_callout(callout_handle);
  257. }
  258. /// Test callback that sets skip flag
  259. /// @param callout_handle handle passed by the hooks framework
  260. /// @return always 0
  261. static int
  262. pkt6_send_skip(CalloutHandle& callout_handle) {
  263. Pkt6Ptr pkt;
  264. callout_handle.getArgument("response6", pkt);
  265. callout_handle.setStatus(CalloutHandle::NEXT_STEP_SKIP);
  266. // carry on as usual
  267. return pkt6_send_callout(callout_handle);
  268. }
  269. /// Test callback that stores received callout name and subnet6 values
  270. /// @param callout_handle handle passed by the hooks framework
  271. /// @return always 0
  272. static int
  273. subnet6_select_callout(CalloutHandle& callout_handle) {
  274. callback_name_ = string("subnet6_select");
  275. callout_handle.getArgument("query6", callback_pkt6_);
  276. callout_handle.getArgument("subnet6", callback_subnet6_);
  277. callout_handle.getArgument("subnet6collection", callback_subnet6collection_);
  278. callback_argument_names_ = callout_handle.getArgumentNames();
  279. return (0);
  280. }
  281. /// Test callback that picks the other subnet if possible.
  282. /// @param callout_handle handle passed by the hooks framework
  283. /// @return always 0
  284. static int
  285. subnet6_select_different_subnet_callout(CalloutHandle& callout_handle) {
  286. // Call the basic callout to record all passed values
  287. subnet6_select_callout(callout_handle);
  288. const Subnet6Collection* subnets;
  289. Subnet6Ptr subnet;
  290. callout_handle.getArgument("subnet6", subnet);
  291. callout_handle.getArgument("subnet6collection", subnets);
  292. // Let's change to a different subnet
  293. if (subnets->size() > 1) {
  294. subnet = (*subnets)[1]; // Let's pick the other subnet
  295. callout_handle.setArgument("subnet6", subnet);
  296. }
  297. return (0);
  298. }
  299. /// Test callback that stores received callout name and pkt6 value
  300. /// @param callout_handle handle passed by the hooks framework
  301. /// @return always 0
  302. static int
  303. lease6_renew_callout(CalloutHandle& callout_handle) {
  304. callback_name_ = string("lease6_renew");
  305. callout_handle.getArgument("query6", callback_pkt6_);
  306. callout_handle.getArgument("lease6", callback_lease6_);
  307. callout_handle.getArgument("ia_na", callback_ia_na_);
  308. callback_argument_names_ = callout_handle.getArgumentNames();
  309. return (0);
  310. }
  311. /// The following values are used by the callout to override
  312. /// renewed lease parameters
  313. static const uint32_t override_iaid_;
  314. static const uint32_t override_t1_;
  315. static const uint32_t override_t2_;
  316. static const uint32_t override_preferred_;
  317. static const uint32_t override_valid_;
  318. /// Test callback that overrides received lease. It updates
  319. /// T1, T2, preferred and valid lifetimes
  320. /// @param callout_handle handle passed by the hooks framework
  321. /// @return always 0
  322. static int
  323. lease6_renew_update_callout(CalloutHandle& callout_handle) {
  324. callback_name_ = string("lease6_renew");
  325. callout_handle.getArgument("query6", callback_pkt6_);
  326. callout_handle.getArgument("lease6", callback_lease6_);
  327. callout_handle.getArgument("ia_na", callback_ia_na_);
  328. // Let's override some values in the lease
  329. callback_lease6_->iaid_ = override_iaid_;
  330. callback_lease6_->t1_ = override_t1_;
  331. callback_lease6_->t2_ = override_t2_;
  332. callback_lease6_->preferred_lft_ = override_preferred_;
  333. callback_lease6_->valid_lft_ = override_valid_;
  334. // Override the values to be sent to the client as well
  335. callback_ia_na_->setIAID(override_iaid_);
  336. callback_ia_na_->setT1(override_t1_);
  337. callback_ia_na_->setT2(override_t2_);
  338. callback_argument_names_ = callout_handle.getArgumentNames();
  339. return (0);
  340. }
  341. /// Test callback that sets the skip flag
  342. /// @param callout_handle handle passed by the hooks framework
  343. /// @return always 0
  344. static int
  345. lease6_renew_skip_callout(CalloutHandle& callout_handle) {
  346. callback_name_ = string("lease6_renew");
  347. callout_handle.setStatus(CalloutHandle::NEXT_STEP_SKIP);
  348. return (0);
  349. }
  350. /// Test callback that stores received callout name passed parameters
  351. /// @param callout_handle handle passed by the hooks framework
  352. /// @return always 0
  353. static int
  354. lease6_release_callout(CalloutHandle& callout_handle) {
  355. callback_name_ = string("lease6_release");
  356. callout_handle.getArgument("query6", callback_pkt6_);
  357. callout_handle.getArgument("lease6", callback_lease6_);
  358. callback_argument_names_ = callout_handle.getArgumentNames();
  359. return (0);
  360. }
  361. /// Test callback that sets the skip flag
  362. /// @param callout_handle handle passed by the hooks framework
  363. /// @return always 0
  364. static int
  365. lease6_release_skip_callout(CalloutHandle& callout_handle) {
  366. callback_name_ = string("lease6_release");
  367. callout_handle.setStatus(CalloutHandle::NEXT_STEP_SKIP);
  368. return (0);
  369. }
  370. /// Lease6_decline test callback
  371. ///
  372. /// Stores all parameters in callback_* fields.
  373. ///
  374. /// @param callout_handle handle passed by the hooks framework
  375. /// @return always 0
  376. static int
  377. lease6_decline_callout(CalloutHandle& callout_handle) {
  378. callback_name_ = string("lease6_decline");
  379. callout_handle.getArgument("query6", callback_pkt6_);
  380. callout_handle.getArgument("lease6", callback_lease6_);
  381. return (0);
  382. }
  383. /// Lease6_decline callout that sets status to SKIP
  384. ///
  385. /// @param callout_handle handle passed by the hooks framework
  386. /// @return always 0
  387. static int
  388. lease6_decline_skip_callout(CalloutHandle& callout_handle) {
  389. callout_handle.setStatus(CalloutHandle::NEXT_STEP_SKIP);
  390. return (lease6_decline_callout(callout_handle));
  391. }
  392. /// Lease6_decline callout that sets status to DROP
  393. ///
  394. /// @param callout_handle handle passed by the hooks framework
  395. /// @return always 0
  396. static int
  397. lease6_decline_drop_callout(CalloutHandle& callout_handle) {
  398. callout_handle.setStatus(CalloutHandle::NEXT_STEP_DROP);
  399. return (lease6_decline_callout(callout_handle));
  400. }
  401. /// Resets buffers used to store data received by callouts
  402. void resetCalloutBuffers() {
  403. callback_name_ = string("");
  404. callback_pkt6_.reset();
  405. callback_subnet6_.reset();
  406. callback_lease6_.reset();
  407. callback_ia_na_.reset();
  408. callback_subnet6collection_ = NULL;
  409. callback_argument_names_.clear();
  410. }
  411. /// Pointer to Dhcpv6Srv that is used in tests
  412. boost::scoped_ptr<NakedDhcpv6Srv> srv_;
  413. // The following fields are used in testing pkt6_receive_callout
  414. /// String name of the received callout
  415. static string callback_name_;
  416. /// Pkt6 structure returned in the callout
  417. static Pkt6Ptr callback_pkt6_;
  418. /// Pointer to lease6
  419. static Lease6Ptr callback_lease6_;
  420. /// Pointer to IA_NA option being renewed
  421. static boost::shared_ptr<Option6IA> callback_ia_na_;
  422. /// Pointer to a subnet received by callout
  423. static Subnet6Ptr callback_subnet6_;
  424. /// A list of all available subnets (received by callout)
  425. static const Subnet6Collection* callback_subnet6collection_;
  426. /// A list of all received arguments
  427. static vector<string> callback_argument_names_;
  428. };
  429. // The following parameters are used by callouts to override
  430. // renewed lease parameters
  431. const uint32_t HooksDhcpv6SrvTest::override_iaid_ = 1000;
  432. const uint32_t HooksDhcpv6SrvTest::override_t1_ = 1001;
  433. const uint32_t HooksDhcpv6SrvTest::override_t2_ = 1002;
  434. const uint32_t HooksDhcpv6SrvTest::override_preferred_ = 1003;
  435. const uint32_t HooksDhcpv6SrvTest::override_valid_ = 1004;
  436. // The following fields are used in testing pkt6_receive_callout.
  437. // See fields description in the class for details
  438. string HooksDhcpv6SrvTest::callback_name_;
  439. Pkt6Ptr HooksDhcpv6SrvTest::callback_pkt6_;
  440. Subnet6Ptr HooksDhcpv6SrvTest::callback_subnet6_;
  441. const Subnet6Collection* HooksDhcpv6SrvTest::callback_subnet6collection_;
  442. vector<string> HooksDhcpv6SrvTest::callback_argument_names_;
  443. Lease6Ptr HooksDhcpv6SrvTest::callback_lease6_;
  444. boost::shared_ptr<Option6IA> HooksDhcpv6SrvTest::callback_ia_na_;
  445. // Checks if callouts installed on pkt6_receive are indeed called and the
  446. // all necessary parameters are passed.
  447. //
  448. // Note that the test name does not follow test naming convention,
  449. // but the proper hook name is "buffer6_receive".
  450. TEST_F(HooksDhcpv6SrvTest, simpleBuffer6Receive) {
  451. // Install pkt6_receive_callout
  452. EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
  453. "buffer6_receive", buffer6_receive_callout));
  454. // Let's create a simple SOLICIT
  455. Pkt6Ptr sol = Pkt6Ptr(PktCaptures::captureSimpleSolicit());
  456. // Simulate that we have received that traffic
  457. srv_->fakeReceive(sol);
  458. // Server will now process to run its normal loop, but instead of calling
  459. // IfaceMgr::receive6(), it will read all packets from the list set by
  460. // fakeReceive()
  461. // In particular, it should call registered buffer6_receive callback.
  462. srv_->run();
  463. // Check that the callback called is indeed the one we installed
  464. EXPECT_EQ("buffer6_receive", callback_name_);
  465. // Check that pkt6 argument passing was successful and returned proper value
  466. EXPECT_TRUE(callback_pkt6_.get() == sol.get());
  467. // Check that all expected parameters are there
  468. vector<string> expected_argument_names;
  469. expected_argument_names.push_back(string("query6"));
  470. EXPECT_TRUE(expected_argument_names == callback_argument_names_);
  471. }
  472. // Checks if callouts installed on buffer6_receive is able to change
  473. // the values and the parameters are indeed used by the server.
  474. TEST_F(HooksDhcpv6SrvTest, valueChangeBuffer6Receive) {
  475. // Install pkt6_receive_callout
  476. EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
  477. "buffer6_receive", buffer6_receive_change_clientid));
  478. // Let's create a simple SOLICIT
  479. Pkt6Ptr sol = Pkt6Ptr(PktCaptures::captureSimpleSolicit());
  480. // Simulate that we have received that traffic
  481. srv_->fakeReceive(sol);
  482. // Server will now process to run its normal loop, but instead of calling
  483. // IfaceMgr::receive6(), it will read all packets from the list set by
  484. // fakeReceive()
  485. // In particular, it should call registered pkt6_receive callback.
  486. srv_->run();
  487. // Check that the server did send a response
  488. ASSERT_EQ(1, srv_->fake_sent_.size());
  489. // Make sure that we received a response
  490. Pkt6Ptr adv = srv_->fake_sent_.front();
  491. ASSERT_TRUE(adv);
  492. // Get client-id...
  493. OptionPtr clientid = adv->getOption(D6O_CLIENTID);
  494. ASSERT_TRUE(clientid);
  495. // ... and check if it is the modified value
  496. EXPECT_EQ(0xff, clientid->getData()[0]);
  497. }
  498. // Checks if callouts installed on buffer6_receive is able to delete
  499. // existing options and that change impacts server processing (mandatory
  500. // client-id option is deleted, so the packet is expected to be dropped)
  501. TEST_F(HooksDhcpv6SrvTest, deleteClientIdBuffer6Receive) {
  502. // Install pkt6_receive_callout
  503. EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
  504. "buffer6_receive", buffer6_receive_delete_clientid));
  505. // Let's create a simple SOLICIT
  506. Pkt6Ptr sol = Pkt6Ptr(PktCaptures::captureSimpleSolicit());
  507. // Simulate that we have received that traffic
  508. srv_->fakeReceive(sol);
  509. // Server will now process to run its normal loop, but instead of calling
  510. // IfaceMgr::receive6(), it will read all packets from the list set by
  511. // fakeReceive()
  512. // In particular, it should call registered pkt6_receive callback.
  513. srv_->run();
  514. // Check that the server dropped the packet and did not send a response
  515. ASSERT_EQ(0, srv_->fake_sent_.size());
  516. }
  517. // Checks if callouts installed on buffer6_received is able to set skip flag that
  518. // will cause the server to not process the packet (drop), even though it is valid.
  519. TEST_F(HooksDhcpv6SrvTest, skipBuffer6Receive) {
  520. // Install pkt6_receive_callout
  521. EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
  522. "buffer6_receive", buffer6_receive_skip));
  523. // Let's create a simple SOLICIT
  524. Pkt6Ptr sol = Pkt6Ptr(PktCaptures::captureSimpleSolicit());
  525. // Simulate that we have received that traffic
  526. srv_->fakeReceive(sol);
  527. // Server will now process to run its normal loop, but instead of calling
  528. // IfaceMgr::receive6(), it will read all packets from the list set by
  529. // fakeReceive()
  530. // In particular, it should call registered pkt6_receive callback.
  531. srv_->run();
  532. // Check that the server dropped the packet and did not produce any response
  533. ASSERT_EQ(0, srv_->fake_sent_.size());
  534. }
  535. // Checks if callouts installed on pkt6_receive are indeed called and the
  536. // all necessary parameters are passed.
  537. //
  538. // Note that the test name does not follow test naming convention,
  539. // but the proper hook name is "pkt6_receive".
  540. TEST_F(HooksDhcpv6SrvTest, simplePkt6Receive) {
  541. // Install pkt6_receive_callout
  542. EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
  543. "pkt6_receive", pkt6_receive_callout));
  544. // Let's create a simple SOLICIT
  545. Pkt6Ptr sol = Pkt6Ptr(PktCaptures::captureSimpleSolicit());
  546. // Simulate that we have received that traffic
  547. srv_->fakeReceive(sol);
  548. // Server will now process to run its normal loop, but instead of calling
  549. // IfaceMgr::receive6(), it will read all packets from the list set by
  550. // fakeReceive()
  551. // In particular, it should call registered pkt6_receive callback.
  552. srv_->run();
  553. // Check that the callback called is indeed the one we installed
  554. EXPECT_EQ("pkt6_receive", callback_name_);
  555. // Check that pkt6 argument passing was successful and returned proper value
  556. EXPECT_TRUE(callback_pkt6_.get() == sol.get());
  557. // Check that all expected parameters are there
  558. vector<string> expected_argument_names;
  559. expected_argument_names.push_back(string("query6"));
  560. EXPECT_TRUE(expected_argument_names == callback_argument_names_);
  561. }
  562. // Checks if callouts installed on pkt6_received is able to change
  563. // the values and the parameters are indeed used by the server.
  564. TEST_F(HooksDhcpv6SrvTest, valueChangePkt6Receive) {
  565. // Install pkt6_receive_callout
  566. EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
  567. "pkt6_receive", pkt6_receive_change_clientid));
  568. // Let's create a simple SOLICIT
  569. Pkt6Ptr sol = Pkt6Ptr(PktCaptures::captureSimpleSolicit());
  570. // Simulate that we have received that traffic
  571. srv_->fakeReceive(sol);
  572. // Server will now process to run its normal loop, but instead of calling
  573. // IfaceMgr::receive6(), it will read all packets from the list set by
  574. // fakeReceive()
  575. // In particular, it should call registered pkt6_receive callback.
  576. srv_->run();
  577. // Check that the server did send a response
  578. ASSERT_EQ(1, srv_->fake_sent_.size());
  579. // Make sure that we received a response
  580. Pkt6Ptr adv = srv_->fake_sent_.front();
  581. ASSERT_TRUE(adv);
  582. // Get client-id...
  583. OptionPtr clientid = adv->getOption(D6O_CLIENTID);
  584. // ... and check if it is the modified value
  585. OptionPtr expected = createOption(D6O_CLIENTID);
  586. EXPECT_TRUE(clientid->equals(expected));
  587. }
  588. // Checks if callouts installed on pkt6_received is able to delete
  589. // existing options and that change impacts server processing (mandatory
  590. // client-id option is deleted, so the packet is expected to be dropped)
  591. TEST_F(HooksDhcpv6SrvTest, deleteClientIdPkt6Receive) {
  592. // Install pkt6_receive_callout
  593. EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
  594. "pkt6_receive", pkt6_receive_delete_clientid));
  595. // Let's create a simple SOLICIT
  596. Pkt6Ptr sol = Pkt6Ptr(PktCaptures::captureSimpleSolicit());
  597. // Simulate that we have received that traffic
  598. srv_->fakeReceive(sol);
  599. // Server will now process to run its normal loop, but instead of calling
  600. // IfaceMgr::receive6(), it will read all packets from the list set by
  601. // fakeReceive()
  602. // In particular, it should call registered pkt6_receive callback.
  603. srv_->run();
  604. // Check that the server dropped the packet and did not send a response
  605. ASSERT_EQ(0, srv_->fake_sent_.size());
  606. }
  607. // Checks if callouts installed on pkt6_received is able to set skip flag that
  608. // will cause the server to not process the packet (drop), even though it is valid.
  609. TEST_F(HooksDhcpv6SrvTest, skipPkt6Receive) {
  610. // Install pkt6_receive_callout
  611. EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
  612. "pkt6_receive", pkt6_receive_skip));
  613. // Let's create a simple SOLICIT
  614. Pkt6Ptr sol = Pkt6Ptr(PktCaptures::captureSimpleSolicit());
  615. // Simulate that we have received that traffic
  616. srv_->fakeReceive(sol);
  617. // Server will now process to run its normal loop, but instead of calling
  618. // IfaceMgr::receive6(), it will read all packets from the list set by
  619. // fakeReceive()
  620. // In particular, it should call registered pkt6_receive callback.
  621. srv_->run();
  622. // Check that the server dropped the packet and did not produce any response
  623. ASSERT_EQ(0, srv_->fake_sent_.size());
  624. }
  625. // Checks if callouts installed on pkt6_send are indeed called and the
  626. // all necessary parameters are passed.
  627. TEST_F(HooksDhcpv6SrvTest, simplePkt6Send) {
  628. // Install pkt6_receive_callout
  629. EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
  630. "pkt6_send", pkt6_send_callout));
  631. // Let's create a simple SOLICIT
  632. Pkt6Ptr sol = Pkt6Ptr(PktCaptures::captureSimpleSolicit());
  633. // Simulate that we have received that traffic
  634. srv_->fakeReceive(sol);
  635. // Server will now process to run its normal loop, but instead of calling
  636. // IfaceMgr::receive6(), it will read all packets from the list set by
  637. // fakeReceive()
  638. // In particular, it should call registered pkt6_receive callback.
  639. srv_->run();
  640. // Check that the callback called is indeed the one we installed
  641. EXPECT_EQ("pkt6_send", callback_name_);
  642. // Check that there is one packet sent
  643. ASSERT_EQ(1, srv_->fake_sent_.size());
  644. Pkt6Ptr adv = srv_->fake_sent_.front();
  645. // Check that pkt6 argument passing was successful and returned proper value
  646. EXPECT_TRUE(callback_pkt6_.get() == adv.get());
  647. // Check that all expected parameters are there
  648. vector<string> expected_argument_names;
  649. expected_argument_names.push_back(string("response6"));
  650. EXPECT_TRUE(expected_argument_names == callback_argument_names_);
  651. }
  652. // Checks if callouts installed on pkt6_send is able to change
  653. // the values and the packet sent contains those changes
  654. TEST_F(HooksDhcpv6SrvTest, valueChangePkt6Send) {
  655. // Install pkt6_receive_callout
  656. EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
  657. "pkt6_send", pkt6_send_change_serverid));
  658. // Let's create a simple SOLICIT
  659. Pkt6Ptr sol = Pkt6Ptr(PktCaptures::captureSimpleSolicit());
  660. // Simulate that we have received that traffic
  661. srv_->fakeReceive(sol);
  662. // Server will now process to run its normal loop, but instead of calling
  663. // IfaceMgr::receive6(), it will read all packets from the list set by
  664. // fakeReceive()
  665. // In particular, it should call registered pkt6_receive callback.
  666. srv_->run();
  667. // Check that the server did send a response
  668. ASSERT_EQ(1, srv_->fake_sent_.size());
  669. // Make sure that we received a response
  670. Pkt6Ptr adv = srv_->fake_sent_.front();
  671. ASSERT_TRUE(adv);
  672. // Get client-id...
  673. OptionPtr clientid = adv->getOption(D6O_SERVERID);
  674. // ... and check if it is the modified value
  675. OptionPtr expected = createOption(D6O_SERVERID);
  676. EXPECT_TRUE(clientid->equals(expected));
  677. }
  678. // Checks if callouts installed on pkt6_send is able to delete
  679. // existing options and that server applies those changes. In particular,
  680. // we are trying to send a packet without server-id. The packet should
  681. // be sent
  682. TEST_F(HooksDhcpv6SrvTest, deleteServerIdPkt6Send) {
  683. // Install pkt6_receive_callout
  684. EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
  685. "pkt6_send", pkt6_send_delete_serverid));
  686. // Let's create a simple SOLICIT
  687. Pkt6Ptr sol = Pkt6Ptr(PktCaptures::captureSimpleSolicit());
  688. // Simulate that we have received that traffic
  689. srv_->fakeReceive(sol);
  690. // Server will now process to run its normal loop, but instead of calling
  691. // IfaceMgr::receive6(), it will read all packets from the list set by
  692. // fakeReceive()
  693. // In particular, it should call registered pkt6_receive callback.
  694. srv_->run();
  695. // Check that the server indeed sent a malformed ADVERTISE
  696. ASSERT_EQ(1, srv_->fake_sent_.size());
  697. // Get that ADVERTISE
  698. Pkt6Ptr adv = srv_->fake_sent_.front();
  699. ASSERT_TRUE(adv);
  700. // Make sure that it does not have server-id
  701. EXPECT_FALSE(adv->getOption(D6O_SERVERID));
  702. }
  703. // Checks if callouts installed on pkt6_skip is able to set skip flag that
  704. // will cause the server to not process the packet (drop), even though it is valid.
  705. TEST_F(HooksDhcpv6SrvTest, skipPkt6Send) {
  706. // Install pkt6_receive_callout
  707. EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
  708. "pkt6_send", pkt6_send_skip));
  709. // Let's create a simple REQUEST
  710. Pkt6Ptr sol = Pkt6Ptr(PktCaptures::captureSimpleSolicit());
  711. // Simulate that we have received that traffic
  712. srv_->fakeReceive(sol);
  713. // Server will now process to run its normal loop, but instead of calling
  714. // IfaceMgr::receive6(), it will read all packets from the list set by
  715. // fakeReceive()
  716. // In particular, it should call registered pkt6_receive callback.
  717. srv_->run();
  718. // Check that the server send the packet
  719. ASSERT_EQ(1, srv_->fake_sent_.size());
  720. // But the sent packet should have 0 length (we told the server to
  721. // skip pack(), but did not do packing outselves)
  722. Pkt6Ptr sent = srv_->fake_sent_.front();
  723. // The actual size of sent packet should be 0
  724. EXPECT_EQ(0, sent->getBuffer().getLength());
  725. }
  726. // This test checks if subnet6_select callout is triggered and reports
  727. // valid parameters
  728. TEST_F(HooksDhcpv6SrvTest, subnet6Select) {
  729. // Install pkt6_receive_callout
  730. EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
  731. "subnet6_select", subnet6_select_callout));
  732. // Configure 2 subnets, both directly reachable over local interface
  733. // (let's not complicate the matter with relays)
  734. string config = "{ \"interfaces-config\": {"
  735. " \"interfaces\": [ \"*\" ]"
  736. "},"
  737. "\"preferred-lifetime\": 3000,"
  738. "\"rebind-timer\": 2000, "
  739. "\"renew-timer\": 1000, "
  740. "\"subnet6\": [ { "
  741. " \"pools\": [ { \"pool\": \"2001:db8:1::/64\" } ],"
  742. " \"subnet\": \"2001:db8:1::/48\", "
  743. " \"interface\": \"" + valid_iface_ + "\" "
  744. " }, {"
  745. " \"pools\": [ { \"pool\": \"2001:db8:2::/64\" } ],"
  746. " \"subnet\": \"2001:db8:2::/48\" "
  747. " } ],"
  748. "\"valid-lifetime\": 4000 }";
  749. ElementPtr json = Element::fromJSON(config);
  750. ConstElementPtr status;
  751. // Configure the server and make sure the config is accepted
  752. EXPECT_NO_THROW(status = configureDhcp6Server(*srv_, json));
  753. ASSERT_TRUE(status);
  754. comment_ = isc::config::parseAnswer(rcode_, status);
  755. ASSERT_EQ(0, rcode_);
  756. CfgMgr::instance().commit();
  757. // Prepare solicit packet. Server should select first subnet for it
  758. Pkt6Ptr sol = Pkt6Ptr(new Pkt6(DHCPV6_SOLICIT, 1234));
  759. sol->setRemoteAddr(IOAddress("fe80::abcd"));
  760. sol->setIface(valid_iface_);
  761. sol->addOption(generateIA(D6O_IA_NA, 234, 1500, 3000));
  762. OptionPtr clientid = generateClientId();
  763. sol->addOption(clientid);
  764. // Pass it to the server and get an advertise
  765. Pkt6Ptr adv = srv_->processSolicit(sol);
  766. // Check if we get response at all
  767. ASSERT_TRUE(adv);
  768. // Check that the callback called is indeed the one we installed
  769. EXPECT_EQ("subnet6_select", callback_name_);
  770. // Check that pkt6 argument passing was successful and returned proper value
  771. EXPECT_TRUE(callback_pkt6_.get() == sol.get());
  772. const Subnet6Collection* exp_subnets =
  773. CfgMgr::instance().getCurrentCfg()->getCfgSubnets6()->getAll();
  774. // The server is supposed to pick the first subnet, because of matching
  775. // interface. Check that the value is reported properly.
  776. ASSERT_TRUE(callback_subnet6_);
  777. EXPECT_EQ(callback_subnet6_.get(), exp_subnets->front().get());
  778. // Server is supposed to report two subnets
  779. ASSERT_EQ(exp_subnets->size(), callback_subnet6collection_->size());
  780. // Compare that the available subnets are reported as expected
  781. EXPECT_TRUE((*exp_subnets)[0].get() == (*callback_subnet6collection_)[0].get());
  782. EXPECT_TRUE((*exp_subnets)[1].get() == (*callback_subnet6collection_)[1].get());
  783. }
  784. // This test checks if callout installed on subnet6_select hook point can pick
  785. // a different subnet.
  786. TEST_F(HooksDhcpv6SrvTest, subnet6SselectChange) {
  787. // Install pkt6_receive_callout
  788. EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
  789. "subnet6_select", subnet6_select_different_subnet_callout));
  790. // Configure 2 subnets, both directly reachable over local interface
  791. // (let's not complicate the matter with relays)
  792. string config = "{ \"interfaces-config\": {"
  793. " \"interfaces\": [ \"*\" ]"
  794. "},"
  795. "\"preferred-lifetime\": 3000,"
  796. "\"rebind-timer\": 2000, "
  797. "\"renew-timer\": 1000, "
  798. "\"subnet6\": [ { "
  799. " \"pools\": [ { \"pool\": \"2001:db8:1::/64\" } ],"
  800. " \"subnet\": \"2001:db8:1::/48\", "
  801. " \"interface\": \"" + valid_iface_ + "\" "
  802. " }, {"
  803. " \"pools\": [ { \"pool\": \"2001:db8:2::/64\" } ],"
  804. " \"subnet\": \"2001:db8:2::/48\" "
  805. " } ],"
  806. "\"valid-lifetime\": 4000 }";
  807. ElementPtr json = Element::fromJSON(config);
  808. ConstElementPtr status;
  809. // Configure the server and make sure the config is accepted
  810. EXPECT_NO_THROW(status = configureDhcp6Server(*srv_, json));
  811. ASSERT_TRUE(status);
  812. comment_ = isc::config::parseAnswer(rcode_, status);
  813. ASSERT_EQ(0, rcode_);
  814. CfgMgr::instance().commit();
  815. // Prepare solicit packet. Server should select first subnet for it
  816. Pkt6Ptr sol = Pkt6Ptr(new Pkt6(DHCPV6_SOLICIT, 1234));
  817. sol->setRemoteAddr(IOAddress("fe80::abcd"));
  818. sol->setIface(valid_iface_);
  819. sol->addOption(generateIA(D6O_IA_NA, 234, 1500, 3000));
  820. OptionPtr clientid = generateClientId();
  821. sol->addOption(clientid);
  822. // Pass it to the server and get an advertise
  823. Pkt6Ptr adv = srv_->processSolicit(sol);
  824. // Check if we get response at all
  825. ASSERT_TRUE(adv);
  826. // The response should have an address from second pool, so let's check it
  827. OptionPtr tmp = adv->getOption(D6O_IA_NA);
  828. ASSERT_TRUE(tmp);
  829. boost::shared_ptr<Option6IA> ia = boost::dynamic_pointer_cast<Option6IA>(tmp);
  830. ASSERT_TRUE(ia);
  831. tmp = ia->getOption(D6O_IAADDR);
  832. ASSERT_TRUE(tmp);
  833. boost::shared_ptr<Option6IAAddr> addr_opt =
  834. boost::dynamic_pointer_cast<Option6IAAddr>(tmp);
  835. ASSERT_TRUE(addr_opt);
  836. // Get all subnets and use second subnet for verification
  837. const Subnet6Collection* subnets =
  838. CfgMgr::instance().getCurrentCfg()->getCfgSubnets6()->getAll();
  839. ASSERT_EQ(2, subnets->size());
  840. // Advertised address must belong to the second pool (in subnet's range,
  841. // in dynamic pool)
  842. EXPECT_TRUE((*subnets)[1]->inRange(addr_opt->getAddress()));
  843. EXPECT_TRUE((*subnets)[1]->inPool(Lease::TYPE_NA, addr_opt->getAddress()));
  844. }
  845. // This test verifies that incoming (positive) RENEW can be handled properly,
  846. // and the lease6_renew callouts are triggered.
  847. TEST_F(HooksDhcpv6SrvTest, basicLease6Renew) {
  848. NakedDhcpv6Srv srv(0);
  849. // Install pkt6_receive_callout
  850. EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
  851. "lease6_renew", lease6_renew_callout));
  852. const IOAddress addr("2001:db8:1:1::cafe:babe");
  853. const uint32_t iaid = 234;
  854. // Generate client-id also duid_
  855. OptionPtr clientid = generateClientId();
  856. // Check that the address we are about to use is indeed in pool
  857. ASSERT_TRUE(subnet_->inPool(Lease::TYPE_NA, addr));
  858. // Note that preferred, valid, T1 and T2 timers and CLTT are set to invalid
  859. // value on purpose. They should be updated during RENEW.
  860. Lease6Ptr lease(new Lease6(Lease::TYPE_NA, addr, duid_, iaid,
  861. 501, 502, 503, 504, subnet_->getID(),
  862. HWAddrPtr(), 0));
  863. lease->cltt_ = 1234;
  864. ASSERT_TRUE(LeaseMgrFactory::instance().addLease(lease));
  865. // Check that the lease is really in the database
  866. Lease6Ptr l = LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA,
  867. addr);
  868. ASSERT_TRUE(l);
  869. // Check that T1, T2, preferred, valid and cltt really set and not using
  870. // previous (500, 501, etc.) values
  871. EXPECT_NE(l->t1_, subnet_->getT1());
  872. EXPECT_NE(l->t2_, subnet_->getT2());
  873. EXPECT_NE(l->preferred_lft_, subnet_->getPreferred());
  874. EXPECT_NE(l->valid_lft_, subnet_->getValid());
  875. EXPECT_NE(l->cltt_, time(NULL));
  876. // Let's create a RENEW
  877. Pkt6Ptr req = Pkt6Ptr(new Pkt6(DHCPV6_RENEW, 1234));
  878. req->setRemoteAddr(IOAddress("fe80::abcd"));
  879. req->setIface("eth0");
  880. boost::shared_ptr<Option6IA> ia = generateIA(D6O_IA_NA, iaid, 1500, 3000);
  881. OptionPtr renewed_addr_opt(new Option6IAAddr(D6O_IAADDR, addr, 300, 500));
  882. ia->addOption(renewed_addr_opt);
  883. req->addOption(ia);
  884. req->addOption(clientid);
  885. // Server-id is mandatory in RENEW
  886. req->addOption(srv.getServerID());
  887. // Pass it to the server and hope for a REPLY
  888. Pkt6Ptr reply = srv.processRenew(req);
  889. ASSERT_TRUE(reply);
  890. // Check that the callback called is indeed the one we installed
  891. EXPECT_EQ("lease6_renew", callback_name_);
  892. // Check that appropriate parameters are passed to the callouts
  893. EXPECT_TRUE(callback_pkt6_);
  894. EXPECT_TRUE(callback_lease6_);
  895. EXPECT_TRUE(callback_ia_na_);
  896. // Check if all expected parameters were really received
  897. vector<string> expected_argument_names;
  898. expected_argument_names.push_back("query6");
  899. expected_argument_names.push_back("lease6");
  900. expected_argument_names.push_back("ia_na");
  901. sort(callback_argument_names_.begin(), callback_argument_names_.end());
  902. sort(expected_argument_names.begin(), expected_argument_names.end());
  903. EXPECT_TRUE(callback_argument_names_ == expected_argument_names);
  904. // Check if we get response at all
  905. checkResponse(reply, DHCPV6_REPLY, 1234);
  906. OptionPtr tmp = reply->getOption(D6O_IA_NA);
  907. ASSERT_TRUE(tmp);
  908. // Check that IA_NA was returned and that there's an address included
  909. boost::shared_ptr<Option6IAAddr> addr_opt = checkIA_NA(reply, 234, subnet_->getT1(),
  910. subnet_->getT2());
  911. ASSERT_TRUE(addr_opt);
  912. // Check that the lease is really in the database
  913. l = checkLease(duid_, reply->getOption(D6O_IA_NA), addr_opt);
  914. ASSERT_TRUE(l);
  915. // Check that the lease has been returned
  916. ASSERT_TRUE(callback_lease6_);
  917. // Check that the returned lease6 in callout is the same as the one in the
  918. // database
  919. EXPECT_TRUE(*callback_lease6_ == *l);
  920. }
  921. // This test verifies that incoming (positive) RENEW can be handled properly,
  922. // and the lease6_renew callouts are able to change the lease being updated.
  923. TEST_F(HooksDhcpv6SrvTest, leaseUpdateLease6Renew) {
  924. NakedDhcpv6Srv srv(0);
  925. // Install pkt6_receive_callout
  926. EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
  927. "lease6_renew", lease6_renew_update_callout));
  928. const IOAddress addr("2001:db8:1:1::cafe:babe");
  929. const uint32_t iaid = 234;
  930. // Generate client-id also duid_
  931. OptionPtr clientid = generateClientId();
  932. // Check that the address we are about to use is indeed in pool
  933. ASSERT_TRUE(subnet_->inPool(Lease::TYPE_NA, addr));
  934. // Note that preferred, valid, T1 and T2 timers and CLTT are set to invalid
  935. // value on purpose. They should be updated during RENEW.
  936. Lease6Ptr lease(new Lease6(Lease::TYPE_NA, addr, duid_, iaid,
  937. 501, 502, 503, 504, subnet_->getID(),
  938. HWAddrPtr(), 0));
  939. lease->cltt_ = 1234;
  940. ASSERT_TRUE(LeaseMgrFactory::instance().addLease(lease));
  941. // Check that the lease is really in the database
  942. Lease6Ptr l = LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA,
  943. addr);
  944. ASSERT_TRUE(l);
  945. // Check that T1, T2, preferred, valid and cltt really set and not using
  946. // previous (500, 501, etc.) values
  947. EXPECT_NE(l->t1_, subnet_->getT1());
  948. EXPECT_NE(l->t2_, subnet_->getT2());
  949. EXPECT_NE(l->preferred_lft_, subnet_->getPreferred());
  950. EXPECT_NE(l->valid_lft_, subnet_->getValid());
  951. EXPECT_NE(l->cltt_, time(NULL));
  952. // Let's create a RENEW
  953. Pkt6Ptr req = Pkt6Ptr(new Pkt6(DHCPV6_RENEW, 1234));
  954. req->setRemoteAddr(IOAddress("fe80::abcd"));
  955. req->setIface("eth0");
  956. boost::shared_ptr<Option6IA> ia = generateIA(D6O_IA_NA, iaid, 1500, 3000);
  957. OptionPtr renewed_addr_opt(new Option6IAAddr(D6O_IAADDR, addr, 300, 500));
  958. ia->addOption(renewed_addr_opt);
  959. req->addOption(ia);
  960. req->addOption(clientid);
  961. // Server-id is mandatory in RENEW
  962. req->addOption(srv.getServerID());
  963. // Pass it to the server and hope for a REPLY
  964. Pkt6Ptr reply = srv.processRenew(req);
  965. ASSERT_TRUE(reply);
  966. // Check if we get response at all
  967. checkResponse(reply, DHCPV6_REPLY, 1234);
  968. OptionPtr tmp = reply->getOption(D6O_IA_NA);
  969. ASSERT_TRUE(tmp);
  970. // Check that IA_NA was returned and that there's an address included
  971. boost::shared_ptr<Option6IAAddr> addr_opt = checkIA_NA(reply, 1000, 1001, 1002);
  972. ASSERT_TRUE(addr_opt);
  973. // Check that the lease is really in the database
  974. l = checkLease(duid_, reply->getOption(D6O_IA_NA), addr_opt);
  975. ASSERT_TRUE(l);
  976. // Check that we chose the distinct override values
  977. ASSERT_NE(override_t1_, subnet_->getT1());
  978. ASSERT_NE(override_t2_, subnet_->getT2());
  979. ASSERT_NE(override_preferred_, subnet_->getPreferred());
  980. EXPECT_NE(override_valid_, subnet_->getValid());
  981. // Check that T1, T2, preferred, valid were overridden the the callout
  982. EXPECT_EQ(override_t1_, l->t1_);
  983. EXPECT_EQ(override_t2_, l->t2_);
  984. EXPECT_EQ(override_preferred_, l->preferred_lft_);
  985. EXPECT_EQ(override_valid_, l->valid_lft_);
  986. // Checking for CLTT is a bit tricky if we want to avoid off by 1 errors
  987. int32_t cltt = static_cast<int32_t>(l->cltt_);
  988. int32_t expected = static_cast<int32_t>(time(NULL));
  989. // Equality or difference by 1 between cltt and expected is ok.
  990. EXPECT_GE(1, abs(cltt - expected));
  991. EXPECT_TRUE(LeaseMgrFactory::instance().deleteLease(addr_opt->getAddress()));
  992. }
  993. // This test verifies that incoming (positive) RENEW can be handled properly,
  994. // and the lease6_renew callouts are able to set the skip flag that will
  995. // reject the renewal
  996. TEST_F(HooksDhcpv6SrvTest, skipLease6Renew) {
  997. NakedDhcpv6Srv srv(0);
  998. // Install pkt6_receive_callout
  999. EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
  1000. "lease6_renew", lease6_renew_skip_callout));
  1001. const IOAddress addr("2001:db8:1:1::cafe:babe");
  1002. const uint32_t iaid = 234;
  1003. // Generate client-id also duid_
  1004. OptionPtr clientid = generateClientId();
  1005. // Check that the address we are about to use is indeed in pool
  1006. ASSERT_TRUE(subnet_->inPool(Lease::TYPE_NA, addr));
  1007. // Note that preferred, valid, T1 and T2 timers and CLTT are set to invalid
  1008. // value on purpose. They should be updated during RENEW.
  1009. Lease6Ptr lease(new Lease6(Lease::TYPE_NA, addr, duid_, iaid,
  1010. 501, 502, 503, 504, subnet_->getID(),
  1011. HWAddrPtr(), 0));
  1012. lease->cltt_ = 1234;
  1013. ASSERT_TRUE(LeaseMgrFactory::instance().addLease(lease));
  1014. // Check that the lease is really in the database
  1015. Lease6Ptr l = LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA,
  1016. addr);
  1017. ASSERT_TRUE(l);
  1018. // Check that T1, T2, preferred, valid and cltt really set and not using
  1019. // previous (500, 501, etc.) values
  1020. EXPECT_NE(l->t1_, subnet_->getT1());
  1021. EXPECT_NE(l->t2_, subnet_->getT2());
  1022. EXPECT_NE(l->preferred_lft_, subnet_->getPreferred());
  1023. EXPECT_NE(l->valid_lft_, subnet_->getValid());
  1024. EXPECT_NE(l->cltt_, time(NULL));
  1025. // Let's create a RENEW
  1026. Pkt6Ptr req = Pkt6Ptr(new Pkt6(DHCPV6_RENEW, 1234));
  1027. req->setRemoteAddr(IOAddress("fe80::abcd"));
  1028. req->setIface("eth0");
  1029. boost::shared_ptr<Option6IA> ia = generateIA(D6O_IA_NA, iaid, 1500, 3000);
  1030. OptionPtr renewed_addr_opt(new Option6IAAddr(D6O_IAADDR, addr, 300, 500));
  1031. ia->addOption(renewed_addr_opt);
  1032. req->addOption(ia);
  1033. req->addOption(clientid);
  1034. // Server-id is mandatory in RENEW
  1035. req->addOption(srv.getServerID());
  1036. // Pass it to the server and hope for a REPLY
  1037. Pkt6Ptr reply = srv.processRenew(req);
  1038. ASSERT_TRUE(reply);
  1039. // Check that our callback was called
  1040. EXPECT_EQ("lease6_renew", callback_name_);
  1041. l = LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA, addr);
  1042. // Check that the old values are still there and they were not
  1043. // updated by the renewal
  1044. EXPECT_NE(l->t1_, subnet_->getT1());
  1045. EXPECT_NE(l->t2_, subnet_->getT2());
  1046. EXPECT_NE(l->preferred_lft_, subnet_->getPreferred());
  1047. EXPECT_NE(l->valid_lft_, subnet_->getValid());
  1048. EXPECT_NE(l->cltt_, time(NULL));
  1049. }
  1050. // This test verifies that incoming (positive) RELEASE can be handled properly,
  1051. // that a REPLY is generated, that the response has status code and that the
  1052. // lease is indeed removed from the database.
  1053. //
  1054. // expected:
  1055. // - returned REPLY message has copy of client-id
  1056. // - returned REPLY message has server-id
  1057. // - returned REPLY message has IA that does not include an IAADDR
  1058. // - lease is actually removed from LeaseMgr
  1059. TEST_F(HooksDhcpv6SrvTest, basicLease6Release) {
  1060. NakedDhcpv6Srv srv(0);
  1061. // Install pkt6_receive_callout
  1062. EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
  1063. "lease6_release", lease6_release_callout));
  1064. const IOAddress addr("2001:db8:1:1::cafe:babe");
  1065. const uint32_t iaid = 234;
  1066. // Generate client-id also duid_
  1067. OptionPtr clientid = generateClientId();
  1068. // Check that the address we are about to use is indeed in pool
  1069. ASSERT_TRUE(subnet_->inPool(Lease::TYPE_NA, addr));
  1070. // Note that preferred, valid, T1 and T2 timers and CLTT are set to invalid
  1071. // value on purpose. They should be updated during RENEW.
  1072. Lease6Ptr lease(new Lease6(Lease::TYPE_NA, addr, duid_, iaid,
  1073. 501, 502, 503, 504, subnet_->getID(),
  1074. HWAddrPtr(), 0));
  1075. lease->cltt_ = 1234;
  1076. ASSERT_TRUE(LeaseMgrFactory::instance().addLease(lease));
  1077. // Check that the lease is really in the database
  1078. Lease6Ptr l = LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA,
  1079. addr);
  1080. ASSERT_TRUE(l);
  1081. // Let's create a RELEASE
  1082. Pkt6Ptr req = Pkt6Ptr(new Pkt6(DHCPV6_RELEASE, 1234));
  1083. req->setRemoteAddr(IOAddress("fe80::abcd"));
  1084. boost::shared_ptr<Option6IA> ia = generateIA(D6O_IA_NA, iaid, 1500, 3000);
  1085. OptionPtr released_addr_opt(new Option6IAAddr(D6O_IAADDR, addr, 300, 500));
  1086. ia->addOption(released_addr_opt);
  1087. req->addOption(ia);
  1088. req->addOption(clientid);
  1089. // Server-id is mandatory in RELEASE
  1090. req->addOption(srv.getServerID());
  1091. // Pass it to the server and hope for a REPLY
  1092. Pkt6Ptr reply = srv.processRelease(req);
  1093. ASSERT_TRUE(reply);
  1094. // Check that the callback called is indeed the one we installed
  1095. EXPECT_EQ("lease6_release", callback_name_);
  1096. // Check that appropriate parameters are passed to the callouts
  1097. EXPECT_TRUE(callback_pkt6_);
  1098. EXPECT_TRUE(callback_lease6_);
  1099. // Check if all expected parameters were really received
  1100. vector<string> expected_argument_names;
  1101. expected_argument_names.push_back("query6");
  1102. expected_argument_names.push_back("lease6");
  1103. sort(callback_argument_names_.begin(), callback_argument_names_.end());
  1104. sort(expected_argument_names.begin(), expected_argument_names.end());
  1105. EXPECT_TRUE(callback_argument_names_ == expected_argument_names);
  1106. // Check that the lease is really gone in the database
  1107. // get lease by address
  1108. l = LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA, addr);
  1109. ASSERT_FALSE(l);
  1110. // Get lease by subnetid/duid/iaid combination
  1111. l = LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA, *duid_, iaid,
  1112. subnet_->getID());
  1113. ASSERT_FALSE(l);
  1114. }
  1115. // This test verifies that incoming (positive) RELEASE can be handled properly,
  1116. // that a REPLY is generated, that the response has status code and that the
  1117. // lease is indeed removed from the database.
  1118. //
  1119. // expected:
  1120. // - returned REPLY message has copy of client-id
  1121. // - returned REPLY message has server-id
  1122. // - returned REPLY message has IA that does not include an IAADDR
  1123. // - lease is actually removed from LeaseMgr
  1124. TEST_F(HooksDhcpv6SrvTest, skipLease6Release) {
  1125. NakedDhcpv6Srv srv(0);
  1126. // Install pkt6_receive_callout
  1127. EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
  1128. "lease6_release", lease6_release_skip_callout));
  1129. const IOAddress addr("2001:db8:1:1::cafe:babe");
  1130. const uint32_t iaid = 234;
  1131. // Generate client-id also duid_
  1132. OptionPtr clientid = generateClientId();
  1133. // Check that the address we are about to use is indeed in pool
  1134. ASSERT_TRUE(subnet_->inPool(Lease::TYPE_NA, addr));
  1135. // Note that preferred, valid, T1 and T2 timers and CLTT are set to invalid
  1136. // value on purpose. They should be updated during RENEW.
  1137. Lease6Ptr lease(new Lease6(Lease::TYPE_NA, addr, duid_, iaid,
  1138. 501, 502, 503, 504, subnet_->getID(),
  1139. HWAddrPtr(), 0));
  1140. lease->cltt_ = 1234;
  1141. ASSERT_TRUE(LeaseMgrFactory::instance().addLease(lease));
  1142. // Check that the lease is really in the database
  1143. Lease6Ptr l = LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA,
  1144. addr);
  1145. ASSERT_TRUE(l);
  1146. // Let's create a RELEASE
  1147. Pkt6Ptr req = Pkt6Ptr(new Pkt6(DHCPV6_RELEASE, 1234));
  1148. req->setRemoteAddr(IOAddress("fe80::abcd"));
  1149. boost::shared_ptr<Option6IA> ia = generateIA(D6O_IA_NA, iaid, 1500, 3000);
  1150. OptionPtr released_addr_opt(new Option6IAAddr(D6O_IAADDR, addr, 300, 500));
  1151. ia->addOption(released_addr_opt);
  1152. req->addOption(ia);
  1153. req->addOption(clientid);
  1154. // Server-id is mandatory in RELEASE
  1155. req->addOption(srv.getServerID());
  1156. // Pass it to the server and hope for a REPLY
  1157. Pkt6Ptr reply = srv.processRelease(req);
  1158. ASSERT_TRUE(reply);
  1159. // Check that the callback called is indeed the one we installed
  1160. EXPECT_EQ("lease6_release", callback_name_);
  1161. // Check that the lease is still there
  1162. // get lease by address
  1163. l = LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA,
  1164. addr);
  1165. ASSERT_TRUE(l);
  1166. // Get lease by subnetid/duid/iaid combination
  1167. l = LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA, *duid_, iaid,
  1168. subnet_->getID());
  1169. ASSERT_TRUE(l);
  1170. }
  1171. // This test checks that the basic decline hook (lease6_decline) is
  1172. // triggered properly.
  1173. TEST_F(HooksDhcpv6SrvTest, basicLease6Decline) {
  1174. IfaceMgrTestConfig test_config(true);
  1175. // Install lease6_decline callout
  1176. EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
  1177. "lease6_decline", lease6_decline_callout));
  1178. // Get an address and decline it. DUIDs, IAID match and we send valid
  1179. // address, so the decline procedure should be successful.
  1180. Dhcp6Client client;
  1181. acquireAndDecline(client, "01:02:03:04:05:06", 1234, "01:02:03:04:05:06",
  1182. 1234, VALID_ADDR, SHOULD_PASS);
  1183. // Check that the proper callback was called.
  1184. EXPECT_EQ("lease6_decline", callback_name_);
  1185. // And valid parameters were passed.
  1186. ASSERT_TRUE(callback_pkt6_);
  1187. ASSERT_TRUE(callback_lease6_);
  1188. // Test sanity check - it was a decline, right?
  1189. EXPECT_EQ(DHCPV6_DECLINE, callback_pkt6_->getType());
  1190. // Get the address from this decline.
  1191. OptionPtr ia = callback_pkt6_->getOption(D6O_IA_NA);
  1192. ASSERT_TRUE(ia);
  1193. boost::shared_ptr<Option6IAAddr> addr_opt =
  1194. boost::dynamic_pointer_cast<Option6IAAddr>(ia->getOption(D6O_IAADDR));
  1195. ASSERT_TRUE(addr_opt);
  1196. IOAddress addr(addr_opt->getAddress());
  1197. // Now get a lease from the database.
  1198. Lease6Ptr from_mgr = LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA,
  1199. addr);
  1200. ASSERT_TRUE(from_mgr);
  1201. // Now check that it's indeed declined.
  1202. EXPECT_EQ(Lease::STATE_DECLINED, from_mgr->state_);
  1203. // And that the parameters passed to callout are consistent with the database
  1204. EXPECT_EQ(addr, from_mgr->addr_);
  1205. EXPECT_EQ(addr, callback_lease6_->addr_);
  1206. }
  1207. // Test that the lease6_decline hook point can handle SKIP status.
  1208. TEST_F(HooksDhcpv6SrvTest, lease6DeclineSkip) {
  1209. IfaceMgrTestConfig test_config(true);
  1210. // Install lease6_decline callout. It will set the status to skip
  1211. EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
  1212. "lease6_decline", lease6_decline_skip_callout));
  1213. // Get an address and decline it. DUIDs, IAID match and we send valid
  1214. // address, so the decline procedure should be successful.
  1215. Dhcp6Client client;
  1216. acquireAndDecline(client, "01:02:03:04:05:06", 1234, "01:02:03:04:05:06",
  1217. 1234, VALID_ADDR, SHOULD_FAIL);
  1218. // Check that the proper callback was called.
  1219. EXPECT_EQ("lease6_decline", callback_name_);
  1220. // And valid parameters were passed.
  1221. ASSERT_TRUE(callback_pkt6_);
  1222. ASSERT_TRUE(callback_lease6_);
  1223. // Test sanity check - it was a decline, right?
  1224. EXPECT_EQ(DHCPV6_DECLINE, callback_pkt6_->getType());
  1225. // Get the address from this decline.
  1226. OptionPtr ia = callback_pkt6_->getOption(D6O_IA_NA);
  1227. ASSERT_TRUE(ia);
  1228. boost::shared_ptr<Option6IAAddr> addr_opt =
  1229. boost::dynamic_pointer_cast<Option6IAAddr>(ia->getOption(D6O_IAADDR));
  1230. ASSERT_TRUE(addr_opt);
  1231. IOAddress addr(addr_opt->getAddress());
  1232. // Now get a lease from the database.
  1233. Lease6Ptr from_mgr = LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA,
  1234. addr);
  1235. ASSERT_TRUE(from_mgr);
  1236. // Now check that it's NOT declined.
  1237. EXPECT_EQ(Lease::STATE_DEFAULT, from_mgr->state_);
  1238. // And that the parameters passed to callout are consistent with the database
  1239. EXPECT_EQ(addr, from_mgr->addr_);
  1240. EXPECT_EQ(addr, callback_lease6_->addr_);
  1241. }
  1242. // Test that the lease6_decline hook point can handle DROP status.
  1243. TEST_F(HooksDhcpv6SrvTest, lease6DeclineDrop) {
  1244. IfaceMgrTestConfig test_config(true);
  1245. // Install lease6_decline callout. It will set the status to skip
  1246. EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
  1247. "lease6_decline", lease6_decline_drop_callout));
  1248. // Get an address and decline it. DUIDs, IAID match and we send valid
  1249. // address, so it would work, but the callout sets status to DROP, so
  1250. // the server should not update the lease and should not send back any
  1251. // packets.
  1252. Dhcp6Client client;
  1253. acquireAndDecline(client, "01:02:03:04:05:06", 1234, "01:02:03:04:05:06",
  1254. 1234, VALID_ADDR, SHOULD_FAIL);
  1255. // Check that the proper callback was called.
  1256. EXPECT_EQ("lease6_decline", callback_name_);
  1257. // And valid parameters were passed.
  1258. ASSERT_TRUE(callback_pkt6_);
  1259. ASSERT_TRUE(callback_lease6_);
  1260. // Test sanity check - it was a decline, right?
  1261. EXPECT_EQ(DHCPV6_DECLINE, callback_pkt6_->getType());
  1262. // Get the address from this decline.
  1263. OptionPtr ia = callback_pkt6_->getOption(D6O_IA_NA);
  1264. ASSERT_TRUE(ia);
  1265. boost::shared_ptr<Option6IAAddr> addr_opt =
  1266. boost::dynamic_pointer_cast<Option6IAAddr>(ia->getOption(D6O_IAADDR));
  1267. ASSERT_TRUE(addr_opt);
  1268. IOAddress addr(addr_opt->getAddress());
  1269. // Now get a lease from the database.
  1270. Lease6Ptr from_mgr = LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA,
  1271. addr);
  1272. ASSERT_TRUE(from_mgr);
  1273. // Now check that it's NOT declined.
  1274. EXPECT_EQ(Lease::STATE_DEFAULT, from_mgr->state_);
  1275. }
  1276. } // end of anonymous namespace