hooks_unittest.cc 75 KB

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