Kea  2.1.7-git
csv_lease_file6.cc
Go to the documentation of this file.
1 // Copyright (C) 2014-2022 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 
7 #include <config.h>
8 
9 #include <dhcpsrv/dhcpsrv_log.h>
11 
12 #include <ctime>
13 
14 using namespace isc::asiolink;
15 using namespace isc::data;
16 using namespace isc::util;
17 
18 namespace isc {
19 namespace dhcp {
20 
21 CSVLeaseFile6::CSVLeaseFile6(const std::string& filename)
22  : VersionedCSVFile(filename) {
23  initColumns();
24 }
25 
26 void
27 CSVLeaseFile6::open(const bool seek_to_end) {
28  // Call the base class to open the file
29  VersionedCSVFile::open(seek_to_end);
30 
31  // and clear any statistics we may have
33 }
34 
35 void
37  // Bump the number of write attempts
38  ++writes_;
39 
40  if (((!(lease.duid_)) || (*(lease.duid_) == DUID::EMPTY())) &&
41  (lease.state_ != Lease::STATE_DECLINED)) {
42  ++write_errs_;
43  isc_throw(BadValue, "Lease6: " << lease.addr_.toText() << ", state: "
44  << Lease::basicStatesToText(lease.state_) << ", has no DUID");
45  }
46 
47  CSVRow row(getColumnCount());
48  row.writeAt(getColumnIndex("address"), lease.addr_.toText());
49  row.writeAt(getColumnIndex("duid"), lease.duid_->toText());
50  row.writeAt(getColumnIndex("valid_lifetime"), lease.valid_lft_);
51  row.writeAt(getColumnIndex("expire"), static_cast<uint64_t>(lease.cltt_) + lease.valid_lft_);
52  row.writeAt(getColumnIndex("subnet_id"), lease.subnet_id_);
53  row.writeAt(getColumnIndex("pref_lifetime"), lease.preferred_lft_);
54  row.writeAt(getColumnIndex("lease_type"), lease.type_);
55  row.writeAt(getColumnIndex("iaid"), lease.iaid_);
56  row.writeAt(getColumnIndex("prefix_len"),
57  static_cast<int>(lease.prefixlen_));
58  row.writeAt(getColumnIndex("fqdn_fwd"), lease.fqdn_fwd_);
59  row.writeAt(getColumnIndex("fqdn_rev"), lease.fqdn_rev_);
60  row.writeAtEscaped(getColumnIndex("hostname"), lease.hostname_);
61  // We may not have hardware information.
62  if (lease.hwaddr_) {
63  row.writeAt(getColumnIndex("hwaddr"), lease.hwaddr_->toText(false));
64  row.writeAt(getColumnIndex("hwtype"), lease.hwaddr_->htype_);
65  row.writeAt(getColumnIndex("hwaddr_source"), lease.hwaddr_->source_);
66  }
67  row.writeAt(getColumnIndex("state"), lease.state_);
68  // User context is optional.
69  if (lease.getContext()) {
70  row.writeAtEscaped(getColumnIndex("user_context"), lease.getContext()->str());
71  }
72  try {
73  VersionedCSVFile::append(row);
74  } catch (const std::exception&) {
75  // Catch any errors so we can bump the error counter than rethrow it
76  ++write_errs_;
77  throw;
78  }
79 
80  // Bump the number of leases written
81  ++write_leases_;
82 }
83 
84 bool
86  // Bump the number of read attempts
87  ++reads_;
88 
89  // Read the CSV row and try to create a lease from the values read.
90  // This may easily result in exception. We don't want this function
91  // to throw exceptions, so we catch them all and rather return the
92  // false value.
93  try {
94  // Get the row of CSV values.
95  CSVRow row;
96  VersionedCSVFile::next(row);
97  // The empty row signals EOF.
98  if (row == CSVFile::EMPTY_ROW()) {
99  lease.reset();
100  return (true);
101  }
102 
103  lease.reset(new Lease6(readType(row), readAddress(row), readDUID(row),
104  readIAID(row), readPreferred(row),
105  readValid(row),
106  readSubnetID(row),
107  readHWAddr(row),
108  readPrefixLen(row)));
109  lease->cltt_ = readCltt(row);
110  lease->fqdn_fwd_ = readFqdnFwd(row);
111  lease->fqdn_rev_ = readFqdnRev(row);
112  lease->hostname_ = readHostname(row);
113  lease->state_ = readState(row);
114  if ((*lease->duid_ == DUID::EMPTY())
115  && lease->state_ != Lease::STATE_DECLINED) {
117  "The Empty DUID is only valid for declined leases");
118  }
119  ConstElementPtr ctx = readContext(row);
120  if (ctx) {
121  lease->setContext(ctx);
122  }
123  } catch (const std::exception& ex) {
124  // bump the read error count
125  ++read_errs_;
126 
127  // The lease might have been created, so let's set it back to NULL to
128  // signal that lease hasn't been parsed.
129  lease.reset();
130  setReadMsg(ex.what());
131  return (false);
132  }
133 
134  // bump the number of leases read
135  ++read_leases_;
136 
137  return (true);
138 }
139 
140 void
141 CSVLeaseFile6::initColumns() {
142  addColumn("address", "1.0");
143  addColumn("duid", "1.0");
144  addColumn("valid_lifetime", "1.0");
145  addColumn("expire", "1.0");
146  addColumn("subnet_id", "1.0");
147  addColumn("pref_lifetime", "1.0");
148  addColumn("lease_type", "1.0");
149  addColumn("iaid", "1.0");
150  addColumn("prefix_len", "1.0");
151  addColumn("fqdn_fwd", "1.0");
152  addColumn("fqdn_rev", "1.0");
153  addColumn("hostname", "1.0");
154  addColumn("hwaddr", "2.0");
155  addColumn("state", "3.0", "0" /* == STATE_DEFAULT */);
156  addColumn("user_context", "3.1");
157 
158  // Default not added for hwtype and hwaddr_source, because they depend on
159  // hwaddr having value. When a CSV lease having a hwaddr is upgraded to 4.0,
160  // hwtype will have value "1" meaning HTYPE_ETHER and
161  // hwaddr_source will have value "0" meaning HWADDR_SOURCE_UNKNOWN.
162  addColumn("hwtype", "4.0");
163  addColumn("hwaddr_source", "4.0");
164 
165  // Any file with less than hostname is invalid
166  setMinimumValidColumns("hostname");
167 }
168 
170 CSVLeaseFile6::readType(const CSVRow& row) {
171  return (static_cast<Lease::Type>
172  (row.readAndConvertAt<int>(getColumnIndex("lease_type"))));
173 }
174 
175 IOAddress
176 CSVLeaseFile6::readAddress(const CSVRow& row) {
177  IOAddress address(row.readAt(getColumnIndex("address")));
178  return (address);
179 }
180 
181 DuidPtr
182 CSVLeaseFile6::readDUID(const util::CSVRow& row) {
183  DuidPtr duid(new DUID(DUID::fromText(row.readAt(getColumnIndex("duid")))));
184  return (duid);
185 }
186 
187 uint32_t
188 CSVLeaseFile6::readIAID(const CSVRow& row) {
189  uint32_t iaid = row.readAndConvertAt<uint32_t>(getColumnIndex("iaid"));
190  return (iaid);
191 }
192 
193 uint32_t
194 CSVLeaseFile6::readPreferred(const CSVRow& row) {
195  uint32_t pref =
196  row.readAndConvertAt<uint32_t>(getColumnIndex("pref_lifetime"));
197  return (pref);
198 }
199 
200 uint32_t
201 CSVLeaseFile6::readValid(const CSVRow& row) {
202  uint32_t valid =
203  row.readAndConvertAt<uint32_t>(getColumnIndex("valid_lifetime"));
204  return (valid);
205 }
206 
207 uint32_t
208 CSVLeaseFile6::readCltt(const CSVRow& row) {
209  time_t cltt =
210  static_cast<time_t>(row.readAndConvertAt<uint64_t>(getColumnIndex("expire"))
211  - readValid(row));
212  return (cltt);
213 }
214 
215 SubnetID
216 CSVLeaseFile6::readSubnetID(const CSVRow& row) {
217  SubnetID subnet_id =
218  row.readAndConvertAt<SubnetID>(getColumnIndex("subnet_id"));
219  return (subnet_id);
220 }
221 
222 uint8_t
223 CSVLeaseFile6::readPrefixLen(const CSVRow& row) {
224  int prefixlen = row.readAndConvertAt<int>(getColumnIndex("prefix_len"));
225  return (static_cast<uint8_t>(prefixlen));
226 }
227 
228 bool
229 CSVLeaseFile6::readFqdnFwd(const CSVRow& row) {
230  bool fqdn_fwd = row.readAndConvertAt<bool>(getColumnIndex("fqdn_fwd"));
231  return (fqdn_fwd);
232 }
233 
234 bool
235 CSVLeaseFile6::readFqdnRev(const CSVRow& row) {
236  bool fqdn_rev = row.readAndConvertAt<bool>(getColumnIndex("fqdn_rev"));
237  return (fqdn_rev);
238 }
239 
240 std::string
241 CSVLeaseFile6::readHostname(const CSVRow& row) {
242  std::string hostname = row.readAtEscaped(getColumnIndex("hostname"));
243  return (hostname);
244 }
245 
246 HWAddrPtr
247 CSVLeaseFile6::readHWAddr(const CSVRow& row) {
248 
249  try {
250  uint16_t const hwtype(readHWType(row).valueOr(HTYPE_ETHER));
251  HWAddr hwaddr(
252  HWAddr::fromText(row.readAt(getColumnIndex("hwaddr")), hwtype));
253  if (hwaddr.hwaddr_.empty()) {
254  return (HWAddrPtr());
255  }
256  hwaddr.source_ =
257  readHWAddrSource(row).valueOr(HWAddr::HWADDR_SOURCE_UNKNOWN);
258 
261 
262  // Let's return a pointer to new freshly created copy.
263  return (HWAddrPtr(new HWAddr(hwaddr)));
264 
265  } catch (const std::exception& ex) {
266  // That's worse. There was something in the file, but its conversion
267  // to HWAddr failed. Let's log it on warning and carry on.
269  .arg(ex.what());
270 
271  return (HWAddrPtr());
272  }
273 }
274 
275 uint32_t
276 CSVLeaseFile6::readState(const util::CSVRow& row) {
277  uint32_t state = row.readAndConvertAt<uint32_t>(getColumnIndex("state"));
278  return (state);
279 }
280 
282 CSVLeaseFile6::readContext(const util::CSVRow& row) {
283  std::string user_context = row.readAtEscaped(getColumnIndex("user_context"));
284  if (user_context.empty()) {
285  return (ConstElementPtr());
286  }
287  ConstElementPtr ctx = Element::fromJSON(user_context);
288  if (!ctx || (ctx->getType() != Element::map)) {
289  isc_throw(isc::BadValue, "user context '" << user_context
290  << "' is not a JSON map");
291  }
292  return (ctx);
293 }
294 
296 CSVLeaseFile6::readHWType(const CSVRow& row) {
297  size_t const index(getColumnIndex("hwtype"));
298  if (row.readAt(index).empty()) {
299  return Optional<uint16_t>();
300  }
301  return row.readAndConvertAt<uint16_t>(index);
302 }
303 
305 CSVLeaseFile6::readHWAddrSource(const CSVRow& row) {
306  size_t const index(getColumnIndex("hwaddr_source"));
307  if (row.readAt(index).empty()) {
308  return Optional<uint16_t>();
309  }
310  return row.readAndConvertAt<uint32_t>(index);
311 }
312 
313 } // end of namespace isc::dhcp
314 } // end of namespace isc
T readAndConvertAt(const size_t at) const
Retrieves a value from the internal container.
Definition: csv_file.h:156
#define LOG_WARN(LOGGER, MESSAGE)
Macro to conveniently test warn output and log it.
Definition: macros.h:26
uint32_t state_
Holds the lease state(s).
Definition: lease.h:179
boost::shared_ptr< DUID > DuidPtr
Definition: duid.h:20
HWAddrPtr hwaddr_
Client&#39;s MAC/hardware address.
Definition: lease.h:168
uint32_t iaid_
Identity Association Identifier (IAID)
Definition: lease.h:515
size_t getColumnCount() const
Returns the number of columns in the file.
Definition: csv_file.h:403
data::ConstElementPtr getContext() const
Returns const pointer to the user context.
Definition: user_context.h:24
bool fqdn_rev_
Reverse zone updated?
Definition: lease.h:163
uint32_t reads_
Number of attempts to read a lease.
boost::shared_ptr< HWAddr > HWAddrPtr
Shared pointer to a hardware address structure.
Definition: hwaddr.h:154
static const uint32_t HWADDR_SOURCE_UNKNOWN
Used when actual origin is not known, e.g.
Definition: hwaddr.h:41
time_t cltt_
Client last transmission time.
Definition: lease.h:137
bool next(Lease6Ptr &lease)
Reads next lease from the CSV file.
uint32_t preferred_lft_
Preferred lifetime.
Definition: lease.h:524
static const DUID & EMPTY()
Defines the constant "empty" DUID.
Definition: duid.cc:69
bool fqdn_fwd_
Forward zone updated?
Definition: lease.h:158
uint32_t writes_
Number of attempts to write a lease.
std::vector< uint8_t > hwaddr_
Definition: hwaddr.h:98
static DUID fromText(const std::string &text)
Create DUID from the textual format.
Definition: duid.cc:62
uint32_t write_leases_
Number of lease written.
std::string hostname_
Client hostname.
Definition: lease.h:153
SubnetID subnet_id_
Subnet identifier.
Definition: lease.h:148
Holds DUID (DHCPv6 Unique Identifier)
Definition: duid.h:27
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
Definition: edns.h:19
void setMinimumValidColumns(const std::string &column_name)
Sets the minimum number of valid columns based on a given column.
boost::shared_ptr< const Element > ConstElementPtr
Definition: data.h:27
DuidPtr duid_
Client identifier.
Definition: lease.h:518
Structure that holds a lease for IPv6 address and/or prefix.
Definition: lease.h:498
Represents a single row of the CSV file.
Definition: csv_file.h:51
void setReadMsg(const std::string &read_msg)
Sets error message after row validation.
Definition: csv_file.h:486
Lease::Type type_
Lease type.
Definition: lease.h:503
uint8_t prefixlen_
IPv6 prefix length.
Definition: lease.h:508
void clearStatistics()
Clears the statistics.
uint32_t write_errs_
Number of errors when writing.
virtual void open(const bool seek_to_end=false)
Opens a lease file.
Ethernet 10Mbps.
Definition: dhcp4.h:56
void append(const Lease6 &lease)
Appends the lease record to the CSV file.
Defines the logger used by the top-level component of kea-lfc.
T valueOr(T const &or_value) const
Retrieves the encapsulated value if specified, or the given value otherwise.
Definition: optional.h:124
void addColumn(const std::string &col_name, const std::string &version, const std::string &default_value="")
Adds metadata for a single column to the schema.
Implements a CSV file that supports multiple versions of the file&#39;s "schema".
static HWAddr fromText(const std::string &text, const uint16_t htype=HTYPE_ETHER)
Creates instance of the hardware address from textual format.
Definition: hwaddr.cc:70
Type
Type of lease or pool.
Definition: lease.h:45
size_t getColumnIndex(const std::string &col_name) const
Returns the index of the column having specified name.
Definition: csv_file.cc:237
std::string readAt(const size_t at) const
Retrieves a value from the internal container.
Definition: csv_file.cc:60
static std::string basicStatesToText(const uint32_t state)
Returns name(s) of the basic lease state(s).
Definition: lease.cc:90
Hardware type that represents information from DHCPv4 packet.
Definition: hwaddr.h:20
isc::asiolink::IOAddress addr_
IPv4 ot IPv6 address.
Definition: lease.h:114
const isc::log::MessageID DHCPSRV_MEMFILE_READ_HWADDR_FAIL
isc::log::Logger dhcpsrv_logger("dhcpsrv")
DHCP server library Logger.
Definition: dhcpsrv_log.h:56
std::string readAtEscaped(const size_t at) const
Retrieves a value from the internal container, free of escaped characters.
Definition: csv_file.cc:66
static const uint32_t STATE_DECLINED
Declined lease.
Definition: lease.h:71
uint32_t read_leases_
Number of leases read.
uint32_t source_
Hardware address source.
Definition: hwaddr.h:113
uint32_t valid_lft_
Valid lifetime.
Definition: lease.h:119
boost::shared_ptr< Lease6 > Lease6Ptr
Pointer to a Lease6 structure.
Definition: lease.h:487
uint32_t read_errs_
Number of errors when reading.
uint32_t SubnetID
Defines unique IPv4 or IPv6 subnet identifier.
Definition: subnet_id.h:24