memfile_lease_mgr.cc 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  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. // Get the lease files locations.
  23. lease_file4_ = initLeaseFilePath(V4);
  24. lease_file6_ = initLeaseFilePath(V6);
  25. }
  26. Memfile_LeaseMgr::~Memfile_LeaseMgr() {
  27. }
  28. bool
  29. Memfile_LeaseMgr::addLease(const Lease4Ptr& lease) {
  30. LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
  31. DHCPSRV_MEMFILE_ADD_ADDR4).arg(lease->addr_.toText());
  32. if (getLease4(lease->addr_)) {
  33. // there is a lease with specified address already
  34. return (false);
  35. }
  36. storage4_.insert(lease);
  37. return (true);
  38. }
  39. bool
  40. Memfile_LeaseMgr::addLease(const Lease6Ptr& lease) {
  41. LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
  42. DHCPSRV_MEMFILE_ADD_ADDR6).arg(lease->addr_.toText());
  43. if (getLease6(lease->type_, lease->addr_)) {
  44. // there is a lease with specified address already
  45. return (false);
  46. }
  47. storage6_.insert(lease);
  48. return (true);
  49. }
  50. Lease4Ptr
  51. Memfile_LeaseMgr::getLease4(const isc::asiolink::IOAddress& addr) const {
  52. LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
  53. DHCPSRV_MEMFILE_GET_ADDR4).arg(addr.toText());
  54. typedef Lease4Storage::nth_index<0>::type SearchIndex;
  55. const SearchIndex& idx = storage4_.get<0>();
  56. Lease4Storage::iterator l = idx.find(addr);
  57. if (l == storage4_.end()) {
  58. return (Lease4Ptr());
  59. } else {
  60. return (Lease4Ptr(new Lease4(**l)));
  61. }
  62. }
  63. Lease4Collection
  64. Memfile_LeaseMgr::getLease4(const HWAddr& hwaddr) const {
  65. LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
  66. DHCPSRV_MEMFILE_GET_HWADDR).arg(hwaddr.toText());
  67. typedef Lease4Storage::nth_index<0>::type SearchIndex;
  68. Lease4Collection collection;
  69. const SearchIndex& idx = storage4_.get<0>();
  70. for(SearchIndex::const_iterator lease = idx.begin();
  71. lease != idx.end(); ++lease) {
  72. // Every Lease4 has a hardware address, so we can compare it
  73. if ((*lease)->hwaddr_ == hwaddr.hwaddr_) {
  74. collection.push_back((*lease));
  75. }
  76. }
  77. return (collection);
  78. }
  79. Lease4Ptr
  80. Memfile_LeaseMgr::getLease4(const HWAddr& hwaddr, SubnetID subnet_id) const {
  81. LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
  82. DHCPSRV_MEMFILE_GET_SUBID_HWADDR).arg(subnet_id)
  83. .arg(hwaddr.toText());
  84. // We are going to use index #1 of the multi index container.
  85. // We define SearchIndex locally in this function because
  86. // currently only this function uses this index.
  87. typedef Lease4Storage::nth_index<1>::type SearchIndex;
  88. // Get the index.
  89. const SearchIndex& idx = storage4_.get<1>();
  90. // Try to find the lease using HWAddr and subnet id.
  91. SearchIndex::const_iterator lease =
  92. idx.find(boost::make_tuple(hwaddr.hwaddr_, subnet_id));
  93. // Lease was not found. Return empty pointer to the caller.
  94. if (lease == idx.end()) {
  95. return (Lease4Ptr());
  96. }
  97. // Lease was found. Return it to the caller.
  98. return (Lease4Ptr(new Lease4(**lease)));
  99. }
  100. Lease4Collection
  101. Memfile_LeaseMgr::getLease4(const ClientId& client_id) const {
  102. LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
  103. DHCPSRV_MEMFILE_GET_CLIENTID).arg(client_id.toText());
  104. typedef Memfile_LeaseMgr::Lease4Storage::nth_index<0>::type SearchIndex;
  105. Lease4Collection collection;
  106. const SearchIndex& idx = storage4_.get<0>();
  107. for(SearchIndex::const_iterator lease = idx.begin();
  108. lease != idx.end(); ++ lease) {
  109. // client-id is not mandatory in DHCPv4. There can be a lease that does
  110. // not have a client-id. Dereferencing null pointer would be a bad thing
  111. if((*lease)->client_id_ && *(*lease)->client_id_ == client_id) {
  112. collection.push_back((*lease));
  113. }
  114. }
  115. return (collection);
  116. }
  117. Lease4Ptr
  118. Memfile_LeaseMgr::getLease4(const ClientId& client_id,
  119. const HWAddr& hwaddr,
  120. SubnetID subnet_id) const {
  121. LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
  122. DHCPSRV_MEMFILE_GET_CLIENTID_HWADDR_SUBID).arg(client_id.toText())
  123. .arg(hwaddr.toText())
  124. .arg(subnet_id);
  125. // We are going to use index #3 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<3>::type SearchIndex;
  129. // Get the index.
  130. const SearchIndex& idx = storage4_.get<3>();
  131. // Try to get the lease using client id, hardware address and subnet id.
  132. SearchIndex::const_iterator lease =
  133. idx.find(boost::make_tuple(client_id.getClientId(), hwaddr.hwaddr_,
  134. subnet_id));
  135. if (lease == idx.end()) {
  136. // Lease was not found. Return empty pointer to the caller.
  137. return (Lease4Ptr());
  138. }
  139. // Lease was found. Return it to the caller.
  140. return (*lease);
  141. }
  142. Lease4Ptr
  143. Memfile_LeaseMgr::getLease4(const ClientId& client_id,
  144. SubnetID subnet_id) const {
  145. LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
  146. DHCPSRV_MEMFILE_GET_SUBID_CLIENTID).arg(subnet_id)
  147. .arg(client_id.toText());
  148. // We are going to use index #2 of the multi index container.
  149. // We define SearchIndex locally in this function because
  150. // currently only this function uses this index.
  151. typedef Lease4Storage::nth_index<2>::type SearchIndex;
  152. // Get the index.
  153. const SearchIndex& idx = storage4_.get<2>();
  154. // Try to get the lease using client id and subnet id.
  155. SearchIndex::const_iterator lease =
  156. idx.find(boost::make_tuple(client_id.getClientId(), subnet_id));
  157. // Lease was not found. Return empty pointer to the caller.
  158. if (lease == idx.end()) {
  159. return (Lease4Ptr());
  160. }
  161. // Lease was found. Return it to the caller.
  162. return (Lease4Ptr(new Lease4(**lease)));
  163. }
  164. Lease6Ptr
  165. Memfile_LeaseMgr::getLease6(Lease::Type /* not used yet */,
  166. const isc::asiolink::IOAddress& addr) const {
  167. LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
  168. DHCPSRV_MEMFILE_GET_ADDR6).arg(addr.toText());
  169. Lease6Storage::iterator l = storage6_.find(addr);
  170. if (l == storage6_.end()) {
  171. return (Lease6Ptr());
  172. } else {
  173. return (Lease6Ptr(new Lease6(**l)));
  174. }
  175. }
  176. Lease6Collection
  177. Memfile_LeaseMgr::getLeases6(Lease::Type /* not used yet */,
  178. const DUID& duid, uint32_t iaid) const {
  179. LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
  180. DHCPSRV_MEMFILE_GET_IAID_DUID).arg(iaid).arg(duid.toText());
  181. /// @todo Not implemented.
  182. return (Lease6Collection());
  183. }
  184. Lease6Collection
  185. Memfile_LeaseMgr::getLeases6(Lease::Type /* not used yet */,
  186. const DUID& duid, uint32_t iaid,
  187. SubnetID subnet_id) const {
  188. LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
  189. DHCPSRV_MEMFILE_GET_IAID_SUBID_DUID)
  190. .arg(iaid).arg(subnet_id).arg(duid.toText());
  191. // We are going to use index #1 of the multi index container.
  192. // We define SearchIndex locally in this function because
  193. // currently only this function uses this index.
  194. typedef Lease6Storage::nth_index<1>::type SearchIndex;
  195. // Get the index.
  196. const SearchIndex& idx = storage6_.get<1>();
  197. // Try to get the lease using the DUID, IAID and Subnet ID.
  198. SearchIndex::const_iterator lease =
  199. idx.find(boost::make_tuple(duid.getDuid(), iaid, subnet_id));
  200. // Lease was not found. Return empty pointer.
  201. if (lease == idx.end()) {
  202. return (Lease6Collection());
  203. }
  204. // Lease was found, return it to the caller.
  205. /// @todo: allow multiple leases for a single duid+iaid+subnet_id tuple
  206. Lease6Collection collection;
  207. collection.push_back(Lease6Ptr(new Lease6(**lease)));
  208. return (collection);
  209. }
  210. void
  211. Memfile_LeaseMgr::updateLease4(const Lease4Ptr& lease) {
  212. LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
  213. DHCPSRV_MEMFILE_UPDATE_ADDR4).arg(lease->addr_.toText());
  214. Lease4Storage::iterator lease_it = storage4_.find(lease->addr_);
  215. if (lease_it == storage4_.end()) {
  216. isc_throw(NoSuchLease, "failed to update the lease with address "
  217. << lease->addr_ << " - no such lease");
  218. }
  219. **lease_it = *lease;
  220. }
  221. void
  222. Memfile_LeaseMgr::updateLease6(const Lease6Ptr& lease) {
  223. LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
  224. DHCPSRV_MEMFILE_UPDATE_ADDR6).arg(lease->addr_.toText());
  225. Lease6Storage::iterator lease_it = storage6_.find(lease->addr_);
  226. if (lease_it == storage6_.end()) {
  227. isc_throw(NoSuchLease, "failed to update the lease with address "
  228. << lease->addr_ << " - no such lease");
  229. }
  230. **lease_it = *lease;
  231. }
  232. bool
  233. Memfile_LeaseMgr::deleteLease(const isc::asiolink::IOAddress& addr) {
  234. LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
  235. DHCPSRV_MEMFILE_DELETE_ADDR).arg(addr.toText());
  236. if (addr.isV4()) {
  237. // v4 lease
  238. Lease4Storage::iterator l = storage4_.find(addr);
  239. if (l == storage4_.end()) {
  240. // No such lease
  241. return (false);
  242. } else {
  243. storage4_.erase(l);
  244. return (true);
  245. }
  246. } else {
  247. // v6 lease
  248. Lease6Storage::iterator l = storage6_.find(addr);
  249. if (l == storage6_.end()) {
  250. // No such lease
  251. return (false);
  252. } else {
  253. storage6_.erase(l);
  254. return (true);
  255. }
  256. }
  257. }
  258. std::string
  259. Memfile_LeaseMgr::getDescription() const {
  260. return (std::string("This is a dummy memfile backend implementation.\n"
  261. "It does not offer any useful lease management and its only\n"
  262. "purpose is to test abstract lease manager API."));
  263. }
  264. void
  265. Memfile_LeaseMgr::commit() {
  266. LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_MEMFILE_COMMIT);
  267. }
  268. void
  269. Memfile_LeaseMgr::rollback() {
  270. LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
  271. DHCPSRV_MEMFILE_ROLLBACK);
  272. }
  273. std::string
  274. Memfile_LeaseMgr::getDefaultLeaseFilePath(Universe u) const {
  275. std::ostringstream s;
  276. s << CfgMgr::instance().getDataDir() << "/kea-leases";
  277. s << (u == V4 ? "4" : "6");
  278. s << ".csv";
  279. return (s.str());
  280. }
  281. bool
  282. Memfile_LeaseMgr::persistLeases(Universe u) const {
  283. // Currently, if the lease file is empty, it means that writes to disk have
  284. // been explicitly disabled by the administrator. At some point, there may
  285. // be a dedicated ON/OFF flag implemented to control this.
  286. return (u == V4 ? !lease_file4_.empty() : !lease_file6_.empty());
  287. }
  288. std::string
  289. Memfile_LeaseMgr::initLeaseFilePath(Universe u) {
  290. std::string param_name = (u == V4 ? "leasefile4" : "leasefile6");
  291. std::string lease_file;
  292. try {
  293. lease_file = getParameter(param_name);
  294. } catch (const Exception& ex) {
  295. lease_file = getDefaultLeaseFilePath(u);
  296. }
  297. return (lease_file);
  298. }