memfile_lease_mgr.cc 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594
  1. // Copyright (C) 2012-2014 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // Permission to use, copy, modify, and/or distribute this software for any
  4. // purpose with or without fee is hereby granted, provided that the above
  5. // copyright notice and this permission notice appear in all copies.
  6. //
  7. // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  8. // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  9. // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  10. // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  11. // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  12. // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  13. // PERFORMANCE OF THIS SOFTWARE.
  14. #include <dhcpsrv/cfgmgr.h>
  15. #include <dhcpsrv/dhcpsrv_log.h>
  16. #include <dhcpsrv/memfile_lease_mgr.h>
  17. #include <exceptions/exceptions.h>
  18. #include <iostream>
  19. using namespace isc::dhcp;
  20. Memfile_LeaseMgr::Memfile_LeaseMgr(const ParameterMap& parameters)
  21. : LeaseMgr(parameters) {
  22. // Check the universe and use v4 file or v6 file.
  23. std::string universe = getParameter("universe");
  24. if (universe == "4") {
  25. std::string file4 = initLeaseFilePath(V4);
  26. if (!file4.empty()) {
  27. lease_file4_.reset(new CSVLeaseFile4(file4));
  28. lease_file4_->open();
  29. load4();
  30. }
  31. } else {
  32. std::string file6 = initLeaseFilePath(V6);
  33. if (!file6.empty()) {
  34. lease_file6_.reset(new CSVLeaseFile6(file6));
  35. lease_file6_->open();
  36. load6();
  37. }
  38. }
  39. // If lease persistence have been disabled for both v4 and v6,
  40. // issue a warning. It is ok not to write leases to disk when
  41. // doing testing, but it should not be done in normal server
  42. // operation.
  43. if (!persistLeases(V4) && !persistLeases(V6)) {
  44. LOG_WARN(dhcpsrv_logger, DHCPSRV_MEMFILE_NO_STORAGE);
  45. }
  46. }
  47. Memfile_LeaseMgr::~Memfile_LeaseMgr() {
  48. if (lease_file4_) {
  49. lease_file4_->close();
  50. lease_file4_.reset();
  51. }
  52. if (lease_file6_) {
  53. lease_file6_->close();
  54. lease_file6_.reset();
  55. }
  56. }
  57. bool
  58. Memfile_LeaseMgr::addLease(const Lease4Ptr& lease) {
  59. LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
  60. DHCPSRV_MEMFILE_ADD_ADDR4).arg(lease->addr_.toText());
  61. if (getLease4(lease->addr_)) {
  62. // there is a lease with specified address already
  63. return (false);
  64. }
  65. // Try to write a lease to disk first. If this fails, the lease will
  66. // not be inserted to the memory and the disk and in-memory data will
  67. // remain consistent.
  68. if (persistLeases(V4)) {
  69. lease_file4_->append(*lease);
  70. }
  71. storage4_.insert(lease);
  72. return (true);
  73. }
  74. bool
  75. Memfile_LeaseMgr::addLease(const Lease6Ptr& lease) {
  76. LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
  77. DHCPSRV_MEMFILE_ADD_ADDR6).arg(lease->addr_.toText());
  78. if (getLease6(lease->type_, lease->addr_)) {
  79. // there is a lease with specified address already
  80. return (false);
  81. }
  82. // Try to write a lease to disk first. If this fails, the lease will
  83. // not be inserted to the memory and the disk and in-memory data will
  84. // remain consistent.
  85. if (persistLeases(V6)) {
  86. lease_file6_->append(*lease);
  87. }
  88. storage6_.insert(lease);
  89. return (true);
  90. }
  91. Lease4Ptr
  92. Memfile_LeaseMgr::getLease4(const isc::asiolink::IOAddress& addr) const {
  93. LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
  94. DHCPSRV_MEMFILE_GET_ADDR4).arg(addr.toText());
  95. typedef Lease4Storage::nth_index<0>::type SearchIndex;
  96. const SearchIndex& idx = storage4_.get<0>();
  97. Lease4Storage::iterator l = idx.find(addr);
  98. if (l == storage4_.end()) {
  99. return (Lease4Ptr());
  100. } else {
  101. return (Lease4Ptr(new Lease4(**l)));
  102. }
  103. }
  104. Lease4Collection
  105. Memfile_LeaseMgr::getLease4(const HWAddr& hwaddr) const {
  106. LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
  107. DHCPSRV_MEMFILE_GET_HWADDR).arg(hwaddr.toText());
  108. typedef Lease4Storage::nth_index<0>::type SearchIndex;
  109. Lease4Collection collection;
  110. const SearchIndex& idx = storage4_.get<0>();
  111. for(SearchIndex::const_iterator lease = idx.begin();
  112. lease != idx.end(); ++lease) {
  113. // Every Lease4 has a hardware address, so we can compare it
  114. if ((*lease)->hwaddr_ == hwaddr.hwaddr_) {
  115. collection.push_back((*lease));
  116. }
  117. }
  118. return (collection);
  119. }
  120. Lease4Ptr
  121. Memfile_LeaseMgr::getLease4(const HWAddr& hwaddr, SubnetID subnet_id) const {
  122. LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
  123. DHCPSRV_MEMFILE_GET_SUBID_HWADDR).arg(subnet_id)
  124. .arg(hwaddr.toText());
  125. // We are going to use index #1 of the multi index container.
  126. // We define SearchIndex locally in this function because
  127. // currently only this function uses this index.
  128. typedef Lease4Storage::nth_index<1>::type SearchIndex;
  129. // Get the index.
  130. const SearchIndex& idx = storage4_.get<1>();
  131. // Try to find the lease using HWAddr and subnet id.
  132. SearchIndex::const_iterator lease =
  133. idx.find(boost::make_tuple(hwaddr.hwaddr_, subnet_id));
  134. // Lease was not found. Return empty pointer to the caller.
  135. if (lease == idx.end()) {
  136. return (Lease4Ptr());
  137. }
  138. // Lease was found. Return it to the caller.
  139. return (Lease4Ptr(new Lease4(**lease)));
  140. }
  141. Lease4Collection
  142. Memfile_LeaseMgr::getLease4(const ClientId& client_id) const {
  143. LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
  144. DHCPSRV_MEMFILE_GET_CLIENTID).arg(client_id.toText());
  145. typedef Memfile_LeaseMgr::Lease4Storage::nth_index<0>::type SearchIndex;
  146. Lease4Collection collection;
  147. const SearchIndex& idx = storage4_.get<0>();
  148. for(SearchIndex::const_iterator lease = idx.begin();
  149. lease != idx.end(); ++ lease) {
  150. // client-id is not mandatory in DHCPv4. There can be a lease that does
  151. // not have a client-id. Dereferencing null pointer would be a bad thing
  152. if((*lease)->client_id_ && *(*lease)->client_id_ == client_id) {
  153. collection.push_back((*lease));
  154. }
  155. }
  156. return (collection);
  157. }
  158. Lease4Ptr
  159. Memfile_LeaseMgr::getLease4(const ClientId& client_id,
  160. const HWAddr& hwaddr,
  161. SubnetID subnet_id) const {
  162. LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
  163. DHCPSRV_MEMFILE_GET_CLIENTID_HWADDR_SUBID).arg(client_id.toText())
  164. .arg(hwaddr.toText())
  165. .arg(subnet_id);
  166. // We are going to use index #3 of the multi index container.
  167. // We define SearchIndex locally in this function because
  168. // currently only this function uses this index.
  169. typedef Lease4Storage::nth_index<3>::type SearchIndex;
  170. // Get the index.
  171. const SearchIndex& idx = storage4_.get<3>();
  172. // Try to get the lease using client id, hardware address and subnet id.
  173. SearchIndex::const_iterator lease =
  174. idx.find(boost::make_tuple(client_id.getClientId(), hwaddr.hwaddr_,
  175. subnet_id));
  176. if (lease == idx.end()) {
  177. // Lease was not found. Return empty pointer to the caller.
  178. return (Lease4Ptr());
  179. }
  180. // Lease was found. Return it to the caller.
  181. return (*lease);
  182. }
  183. Lease4Ptr
  184. Memfile_LeaseMgr::getLease4(const ClientId& client_id,
  185. SubnetID subnet_id) const {
  186. LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
  187. DHCPSRV_MEMFILE_GET_SUBID_CLIENTID).arg(subnet_id)
  188. .arg(client_id.toText());
  189. // We are going to use index #2 of the multi index container.
  190. // We define SearchIndex locally in this function because
  191. // currently only this function uses this index.
  192. typedef Lease4Storage::nth_index<2>::type SearchIndex;
  193. // Get the index.
  194. const SearchIndex& idx = storage4_.get<2>();
  195. // Try to get the lease using client id and subnet id.
  196. SearchIndex::const_iterator lease =
  197. idx.find(boost::make_tuple(client_id.getClientId(), subnet_id));
  198. // Lease was not found. Return empty pointer to the caller.
  199. if (lease == idx.end()) {
  200. return (Lease4Ptr());
  201. }
  202. // Lease was found. Return it to the caller.
  203. return (Lease4Ptr(new Lease4(**lease)));
  204. }
  205. Lease6Ptr
  206. Memfile_LeaseMgr::getLease6(Lease::Type type,
  207. const isc::asiolink::IOAddress& addr) const {
  208. LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
  209. DHCPSRV_MEMFILE_GET_ADDR6)
  210. .arg(addr.toText())
  211. .arg(Lease::typeToText(type));
  212. Lease6Storage::iterator l = storage6_.find(addr);
  213. if (l == storage6_.end() || !(*l) || ((*l)->type_ != type)) {
  214. return (Lease6Ptr());
  215. } else {
  216. return (Lease6Ptr(new Lease6(**l)));
  217. }
  218. }
  219. Lease6Collection
  220. Memfile_LeaseMgr::getLeases6(Lease::Type type,
  221. const DUID& duid, uint32_t iaid) const {
  222. LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
  223. DHCPSRV_MEMFILE_GET_IAID_DUID)
  224. .arg(iaid)
  225. .arg(duid.toText())
  226. .arg(Lease::typeToText(type));
  227. // We are going to use index #1 of the multi index container.
  228. typedef Lease6Storage::nth_index<1>::type SearchIndex;
  229. // Get the index.
  230. const SearchIndex& idx = storage6_.get<1>();
  231. // Try to get the lease using the DUID, IAID and lease type.
  232. std::pair<SearchIndex::iterator, SearchIndex::iterator> l =
  233. idx.equal_range(boost::make_tuple(duid.getDuid(), iaid, type));
  234. Lease6Collection collection;
  235. for(SearchIndex::iterator lease = l.first; lease != l.second; ++lease) {
  236. collection.push_back(Lease6Ptr(new Lease6(**lease)));
  237. }
  238. return (collection);
  239. }
  240. Lease6Collection
  241. Memfile_LeaseMgr::getLeases6(Lease::Type type,
  242. const DUID& duid, uint32_t iaid,
  243. SubnetID subnet_id) const {
  244. LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
  245. DHCPSRV_MEMFILE_GET_IAID_SUBID_DUID)
  246. .arg(iaid)
  247. .arg(subnet_id)
  248. .arg(duid.toText())
  249. .arg(Lease::typeToText(type));
  250. // We are going to use index #1 of the multi index container.
  251. typedef Lease6Storage::nth_index<1>::type SearchIndex;
  252. // Get the index.
  253. const SearchIndex& idx = storage6_.get<1>();
  254. // Try to get the lease using the DUID, IAID and lease type.
  255. std::pair<SearchIndex::iterator, SearchIndex::iterator> l =
  256. idx.equal_range(boost::make_tuple(duid.getDuid(), iaid, type));
  257. Lease6Collection collection;
  258. for(SearchIndex::iterator lease = l.first; lease != l.second; ++lease) {
  259. // Filter out the leases which subnet id doesn't match.
  260. if((*lease)->subnet_id_ == subnet_id) {
  261. collection.push_back(Lease6Ptr(new Lease6(**lease)));
  262. }
  263. }
  264. return (collection);
  265. }
  266. void
  267. Memfile_LeaseMgr::updateLease4(const Lease4Ptr& lease) {
  268. LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
  269. DHCPSRV_MEMFILE_UPDATE_ADDR4).arg(lease->addr_.toText());
  270. Lease4Storage::iterator lease_it = storage4_.find(lease->addr_);
  271. if (lease_it == storage4_.end()) {
  272. isc_throw(NoSuchLease, "failed to update the lease with address "
  273. << lease->addr_ << " - no such lease");
  274. }
  275. // Try to write a lease to disk first. If this fails, the lease will
  276. // not be inserted to the memory and the disk and in-memory data will
  277. // remain consistent.
  278. if (persistLeases(V4)) {
  279. lease_file4_->append(*lease);
  280. }
  281. **lease_it = *lease;
  282. }
  283. void
  284. Memfile_LeaseMgr::updateLease6(const Lease6Ptr& lease) {
  285. LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
  286. DHCPSRV_MEMFILE_UPDATE_ADDR6).arg(lease->addr_.toText());
  287. Lease6Storage::iterator lease_it = storage6_.find(lease->addr_);
  288. if (lease_it == storage6_.end()) {
  289. isc_throw(NoSuchLease, "failed to update the lease with address "
  290. << lease->addr_ << " - no such lease");
  291. }
  292. // Try to write a lease to disk first. If this fails, the lease will
  293. // not be inserted to the memory and the disk and in-memory data will
  294. // remain consistent.
  295. if (persistLeases(V6)) {
  296. lease_file6_->append(*lease);
  297. }
  298. **lease_it = *lease;
  299. }
  300. bool
  301. Memfile_LeaseMgr::deleteLease(const isc::asiolink::IOAddress& addr) {
  302. LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
  303. DHCPSRV_MEMFILE_DELETE_ADDR).arg(addr.toText());
  304. if (addr.isV4()) {
  305. // v4 lease
  306. Lease4Storage::iterator l = storage4_.find(addr);
  307. if (l == storage4_.end()) {
  308. // No such lease
  309. return (false);
  310. } else {
  311. if (persistLeases(V4)) {
  312. // Copy the lease. The valid lifetime needs to be modified and
  313. // we don't modify the original lease.
  314. Lease4 lease_copy = **l;
  315. // Setting valid lifetime to 0 means that lease is being
  316. // removed.
  317. lease_copy.valid_lft_ = 0;
  318. lease_file4_->append(lease_copy);
  319. }
  320. storage4_.erase(l);
  321. return (true);
  322. }
  323. } else {
  324. // v6 lease
  325. Lease6Storage::iterator l = storage6_.find(addr);
  326. if (l == storage6_.end()) {
  327. // No such lease
  328. return (false);
  329. } else {
  330. if (persistLeases(V6)) {
  331. // Copy the lease. The lifetimes need to be modified and we
  332. // don't modify the original lease.
  333. Lease6 lease_copy = **l;
  334. // Setting lifetimes to 0 means that lease is being removed.
  335. lease_copy.valid_lft_ = 0;
  336. lease_copy.preferred_lft_ = 0;
  337. lease_file6_->append(lease_copy);
  338. }
  339. storage6_.erase(l);
  340. return (true);
  341. }
  342. }
  343. }
  344. std::string
  345. Memfile_LeaseMgr::getDescription() const {
  346. return (std::string("This is a dummy memfile backend implementation.\n"
  347. "It does not offer any useful lease management and its only\n"
  348. "purpose is to test abstract lease manager API."));
  349. }
  350. void
  351. Memfile_LeaseMgr::commit() {
  352. LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_MEMFILE_COMMIT);
  353. }
  354. void
  355. Memfile_LeaseMgr::rollback() {
  356. LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
  357. DHCPSRV_MEMFILE_ROLLBACK);
  358. }
  359. std::string
  360. Memfile_LeaseMgr::getDefaultLeaseFilePath(Universe u) const {
  361. std::ostringstream s;
  362. s << CfgMgr::instance().getDataDir() << "/kea-leases";
  363. s << (u == V4 ? "4" : "6");
  364. s << ".csv";
  365. return (s.str());
  366. }
  367. std::string
  368. Memfile_LeaseMgr::getLeaseFilePath(Universe u) const {
  369. if (u == V4) {
  370. return (lease_file4_ ? lease_file4_->getFilename() : "");
  371. }
  372. return (lease_file6_ ? lease_file6_->getFilename() : "");
  373. }
  374. bool
  375. Memfile_LeaseMgr::persistLeases(Universe u) const {
  376. // Currently, if the lease file IO is not created, it means that writes to
  377. // disk have been explicitly disabled by the administrator. At some point,
  378. // there may be a dedicated ON/OFF flag implemented to control this.
  379. if (u == V4 && lease_file4_) {
  380. return (true);
  381. }
  382. return (u == V6 && lease_file6_);
  383. }
  384. std::string
  385. Memfile_LeaseMgr::initLeaseFilePath(Universe u) {
  386. std::string persist_val;
  387. try {
  388. persist_val = getParameter("persist");
  389. } catch (const Exception& ex) {
  390. // If parameter persist hasn't been specified, we use a default value
  391. // 'yes'.
  392. persist_val = "true";
  393. }
  394. // If persist_val is 'false' we will not store leases to disk, so let's
  395. // return empty file name.
  396. if (persist_val == "false") {
  397. return ("");
  398. } else if (persist_val != "true") {
  399. isc_throw(isc::BadValue, "invalid value 'persist="
  400. << persist_val << "'");
  401. }
  402. std::string lease_file;
  403. try {
  404. lease_file = getParameter("name");
  405. } catch (const Exception& ex) {
  406. lease_file = getDefaultLeaseFilePath(u);
  407. }
  408. return (lease_file);
  409. }
  410. void
  411. Memfile_LeaseMgr::load4() {
  412. // If lease file hasn't been opened, we are working in non-persistent mode.
  413. // That's fine, just leave.
  414. if (!persistLeases(V4)) {
  415. return;
  416. }
  417. LOG_INFO(dhcpsrv_logger, DHCPSRV_MEMFILE_LEASES_RELOAD4)
  418. .arg(lease_file4_->getFilename());
  419. // Remove existing leases (if any). We will recreate them based on the
  420. // data on disk.
  421. storage4_.clear();
  422. Lease4Ptr lease;
  423. do {
  424. /// @todo Currently we stop parsing on first failure. It is possible
  425. /// that only one (or a few) leases are bad, so in theory we could
  426. /// continue parsing but that would require some error counters to
  427. /// prevent endless loops. That is enhancement for later time.
  428. if (!lease_file4_->next(lease)) {
  429. isc_throw(DbOperationError, "Failed to parse the DHCPv6 lease in"
  430. " the lease file: " << lease_file4_->getReadMsg());
  431. }
  432. // If we got the lease, we update the internal container holding
  433. // leases. Otherwise, we reached the end of file and we leave.
  434. if (lease) {
  435. LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL_DATA,
  436. DHCPSRV_MEMFILE_LEASE_LOAD4)
  437. .arg(lease->toText());
  438. loadLease4(lease);
  439. }
  440. } while (lease);
  441. }
  442. void
  443. Memfile_LeaseMgr::loadLease4(Lease4Ptr& lease) {
  444. // Check if the lease already exists.
  445. Lease4Storage::iterator lease_it = storage4_.find(lease->addr_);
  446. // Lease doesn't exist.
  447. if (lease_it == storage4_.end()) {
  448. // Add the lease only if valid lifetime is greater than 0.
  449. // We use valid lifetime of 0 to indicate that lease should
  450. // be removed.
  451. if (lease->valid_lft_ > 0) {
  452. storage4_.insert(lease);
  453. }
  454. } else {
  455. // We use valid lifetime of 0 to indicate that the lease is
  456. // to be removed. In such case, erase the lease.
  457. if (lease->valid_lft_ == 0) {
  458. storage4_.erase(lease_it);
  459. } else {
  460. // Update existing lease.
  461. **lease_it = *lease;
  462. }
  463. }
  464. }
  465. void
  466. Memfile_LeaseMgr::load6() {
  467. // If lease file hasn't been opened, we are working in non-persistent mode.
  468. // That's fine, just leave.
  469. if (!persistLeases(V6)) {
  470. return;
  471. }
  472. LOG_INFO(dhcpsrv_logger, DHCPSRV_MEMFILE_LEASES_RELOAD6)
  473. .arg(lease_file6_->getFilename());
  474. // Remove existing leases (if any). We will recreate them based on the
  475. // data on disk.
  476. storage6_.clear();
  477. Lease6Ptr lease;
  478. do {
  479. /// @todo Currently we stop parsing on first failure. It is possible
  480. /// that only one (or a few) leases are bad, so in theory we could
  481. /// continue parsing but that would require some error counters to
  482. /// prevent endless loops. That is enhancement for later time.
  483. if (!lease_file6_->next(lease)) {
  484. isc_throw(DbOperationError, "Failed to parse the DHCPv6 lease in"
  485. " the lease file: " << lease_file6_->getReadMsg());
  486. }
  487. // If we got the lease, we update the internal container holding
  488. // leases. Otherwise, we reached the end of file and we leave.
  489. if (lease) {
  490. LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL_DATA,
  491. DHCPSRV_MEMFILE_LEASE_LOAD6)
  492. .arg(lease->toText());
  493. loadLease6(lease);
  494. }
  495. } while (lease);
  496. }
  497. void
  498. Memfile_LeaseMgr::loadLease6(Lease6Ptr& lease) {
  499. // Check if the lease already exists.
  500. Lease6Storage::iterator lease_it = storage6_.find(lease->addr_);
  501. // Lease doesn't exist.
  502. if (lease_it == storage6_.end()) {
  503. // Add the lease only if valid lifetime is greater than 0.
  504. // We use valid lifetime of 0 to indicate that lease should
  505. // be removed.
  506. if (lease->valid_lft_ > 0) {
  507. storage6_.insert(lease);
  508. }
  509. } else {
  510. // We use valid lifetime of 0 to indicate that the lease is
  511. // to be removed. In such case, erase the lease.
  512. if (lease->valid_lft_ == 0) {
  513. storage6_.erase(lease_it);
  514. } else {
  515. // Update existing lease.
  516. **lease_it = *lease;
  517. }
  518. }
  519. }