csv_lease_file6.cc 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. // Copyright (C) 2014-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 <dhcpsrv/dhcpsrv_log.h>
  8. #include <dhcpsrv/csv_lease_file6.h>
  9. using namespace isc::asiolink;
  10. using namespace isc::util;
  11. namespace isc {
  12. namespace dhcp {
  13. CSVLeaseFile6::CSVLeaseFile6(const std::string& filename)
  14. : VersionedCSVFile(filename) {
  15. initColumns();
  16. }
  17. void
  18. CSVLeaseFile6::open(const bool seek_to_end) {
  19. // Call the base class to open the file
  20. VersionedCSVFile::open(seek_to_end);
  21. // and clear any statistics we may have
  22. clearStatistics();
  23. }
  24. void
  25. CSVLeaseFile6::append(const Lease6& lease) {
  26. // Bump the number of write attempts
  27. ++writes_;
  28. CSVRow row(getColumnCount());
  29. row.writeAt(getColumnIndex("address"), lease.addr_.toText());
  30. row.writeAt(getColumnIndex("duid"), lease.duid_->toText());
  31. row.writeAt(getColumnIndex("valid_lifetime"), lease.valid_lft_);
  32. row.writeAt(getColumnIndex("expire"), lease.cltt_ + lease.valid_lft_);
  33. row.writeAt(getColumnIndex("subnet_id"), lease.subnet_id_);
  34. row.writeAt(getColumnIndex("pref_lifetime"), lease.preferred_lft_);
  35. row.writeAt(getColumnIndex("lease_type"), lease.type_);
  36. row.writeAt(getColumnIndex("iaid"), lease.iaid_);
  37. row.writeAt(getColumnIndex("prefix_len"),
  38. static_cast<int>(lease.prefixlen_));
  39. row.writeAt(getColumnIndex("fqdn_fwd"), lease.fqdn_fwd_);
  40. row.writeAt(getColumnIndex("fqdn_rev"), lease.fqdn_rev_);
  41. row.writeAt(getColumnIndex("hostname"), lease.hostname_);
  42. if (lease.hwaddr_) {
  43. // We may not have hardware information
  44. row.writeAt(getColumnIndex("hwaddr"), lease.hwaddr_->toText(false));
  45. }
  46. row.writeAt(getColumnIndex("state"), lease.state_);
  47. try {
  48. VersionedCSVFile::append(row);
  49. } catch (const std::exception&) {
  50. // Catch any errors so we can bump the error counter than rethrow it
  51. ++write_errs_;
  52. throw;
  53. }
  54. // Bump the number of leases written
  55. ++write_leases_;
  56. }
  57. bool
  58. CSVLeaseFile6::next(Lease6Ptr& lease) {
  59. // Bump the number of read attempts
  60. ++reads_;
  61. // Read the CSV row and try to create a lease from the values read.
  62. // This may easily result in exception. We don't want this function
  63. // to throw exceptions, so we catch them all and rather return the
  64. // false value.
  65. try {
  66. // Get the row of CSV values.
  67. CSVRow row;
  68. VersionedCSVFile::next(row);
  69. // The empty row signals EOF.
  70. if (row == CSVFile::EMPTY_ROW()) {
  71. lease.reset();
  72. return (true);
  73. }
  74. lease.reset(new Lease6(readType(row), readAddress(row), readDUID(row),
  75. readIAID(row), readPreferred(row),
  76. readValid(row), 0, 0, // t1, t2 = 0
  77. readSubnetID(row),
  78. readHWAddr(row),
  79. readPrefixLen(row)));
  80. lease->cltt_ = readCltt(row);
  81. lease->fqdn_fwd_ = readFqdnFwd(row);
  82. lease->fqdn_rev_ = readFqdnRev(row);
  83. lease->hostname_ = readHostname(row);
  84. lease->state_ = readState(row);
  85. if ((*lease->duid_ == DUID::EMPTY())
  86. && lease->state_ != Lease::STATE_DECLINED) {
  87. isc_throw(isc::BadValue, "The Empty DUID is"
  88. "only valid for declined leases");
  89. }
  90. } catch (std::exception& ex) {
  91. // bump the read error count
  92. ++read_errs_;
  93. // The lease might have been created, so let's set it back to NULL to
  94. // signal that lease hasn't been parsed.
  95. lease.reset();
  96. setReadMsg(ex.what());
  97. return (false);
  98. }
  99. // bump the number of leases read
  100. ++read_leases_;
  101. return (true);
  102. }
  103. void
  104. CSVLeaseFile6::initColumns() {
  105. addColumn("address", "1.0");
  106. addColumn("duid", "1.0");
  107. addColumn("valid_lifetime", "1.0");
  108. addColumn("expire", "1.0");
  109. addColumn("subnet_id", "1.0");
  110. addColumn("pref_lifetime", "1.0");
  111. addColumn("lease_type", "1.0");
  112. addColumn("iaid", "1.0");
  113. addColumn("prefix_len", "1.0");
  114. addColumn("fqdn_fwd", "1.0");
  115. addColumn("fqdn_rev", "1.0");
  116. addColumn("hostname", "1.0");
  117. addColumn("hwaddr", "2.0");
  118. addColumn("state", "3.0", "0");
  119. // Any file with less than hostname is invalid
  120. setMinimumValidColumns("hostname");
  121. }
  122. Lease::Type
  123. CSVLeaseFile6::readType(const CSVRow& row) {
  124. return (static_cast<Lease::Type>
  125. (row.readAndConvertAt<int>(getColumnIndex("lease_type"))));
  126. }
  127. IOAddress
  128. CSVLeaseFile6::readAddress(const CSVRow& row) {
  129. IOAddress address(row.readAt(getColumnIndex("address")));
  130. return (address);
  131. }
  132. DuidPtr
  133. CSVLeaseFile6::readDUID(const util::CSVRow& row) {
  134. DuidPtr duid(new DUID(DUID::fromText(row.readAt(getColumnIndex("duid")))));
  135. return (duid);
  136. }
  137. uint32_t
  138. CSVLeaseFile6::readIAID(const CSVRow& row) {
  139. uint32_t iaid = row.readAndConvertAt<uint32_t>(getColumnIndex("iaid"));
  140. return (iaid);
  141. }
  142. uint32_t
  143. CSVLeaseFile6::readPreferred(const CSVRow& row) {
  144. uint32_t pref =
  145. row.readAndConvertAt<uint32_t>(getColumnIndex("pref_lifetime"));
  146. return (pref);
  147. }
  148. uint32_t
  149. CSVLeaseFile6::readValid(const CSVRow& row) {
  150. uint32_t valid =
  151. row.readAndConvertAt<uint32_t>(getColumnIndex("valid_lifetime"));
  152. return (valid);
  153. }
  154. uint32_t
  155. CSVLeaseFile6::readCltt(const CSVRow& row) {
  156. uint32_t cltt = row.readAndConvertAt<uint32_t>(getColumnIndex("expire"))
  157. - readValid(row);
  158. return (cltt);
  159. }
  160. SubnetID
  161. CSVLeaseFile6::readSubnetID(const CSVRow& row) {
  162. SubnetID subnet_id =
  163. row.readAndConvertAt<SubnetID>(getColumnIndex("subnet_id"));
  164. return (subnet_id);
  165. }
  166. uint8_t
  167. CSVLeaseFile6::readPrefixLen(const CSVRow& row) {
  168. int prefixlen = row.readAndConvertAt<int>(getColumnIndex("prefix_len"));
  169. return (static_cast<uint8_t>(prefixlen));
  170. }
  171. bool
  172. CSVLeaseFile6::readFqdnFwd(const CSVRow& row) {
  173. bool fqdn_fwd = row.readAndConvertAt<bool>(getColumnIndex("fqdn_fwd"));
  174. return (fqdn_fwd);
  175. }
  176. bool
  177. CSVLeaseFile6::readFqdnRev(const CSVRow& row) {
  178. bool fqdn_rev = row.readAndConvertAt<bool>(getColumnIndex("fqdn_rev"));
  179. return (fqdn_rev);
  180. }
  181. std::string
  182. CSVLeaseFile6::readHostname(const CSVRow& row) {
  183. std::string hostname = row.readAt(getColumnIndex("hostname"));
  184. return (hostname);
  185. }
  186. HWAddrPtr
  187. CSVLeaseFile6::readHWAddr(const CSVRow& row) {
  188. try {
  189. const HWAddr& hwaddr = HWAddr::fromText(row.readAt(getColumnIndex("hwaddr")));
  190. if (hwaddr.hwaddr_.empty()) {
  191. return (HWAddrPtr());
  192. }
  193. /// @todo: HWAddr returns an object, not a pointer. Without HWAddr
  194. /// refactoring, at least one copy is unavoidable.
  195. // Let's return a pointer to new freshly created copy.
  196. return (HWAddrPtr(new HWAddr(hwaddr)));
  197. } catch (const std::exception& ex) {
  198. // That's worse. There was something in the file, but its conversion
  199. // to HWAddr failed. Let's log it on warning and carry on.
  200. LOG_WARN(dhcpsrv_logger, DHCPSRV_MEMFILE_READ_HWADDR_FAIL)
  201. .arg(ex.what());
  202. return (HWAddrPtr());
  203. }
  204. }
  205. uint32_t
  206. CSVLeaseFile6::readState(const util::CSVRow& row) {
  207. uint32_t state = row.readAndConvertAt<uint32_t>(getColumnIndex("state"));
  208. return (state);
  209. }
  210. } // end of namespace isc::dhcp
  211. } // end of namespace isc