Kea: csv_lease_file6.cc Source File

| Kea 2.2.0

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>
10#include <dhcpsrv/csv_lease_file6.h>
11
12#include <ctime>
13
14using namespace isc::asiolink;
15using namespace isc::data;
16using namespace isc::util;
17
18namespace isc {
19namespace dhcp {
20
21CSVLeaseFile6::CSVLeaseFile6(const std::string& filename)
22 : VersionedCSVFile(filename) {
23 initColumns();
24}
25
26void
27CSVLeaseFile6::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
32 clearStatistics();
33}
34
35void
36CSVLeaseFile6::append(const Lease6& lease) {
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
84bool
85CSVLeaseFile6::next(Lease6Ptr& lease) {
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) {
116 isc_throw(isc::BadValue,
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
140void
141CSVLeaseFile6::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
169 Lease::Type
170CSVLeaseFile6::readType(const CSVRow& row) {
171 return (static_cast<Lease::Type>
172 (row.readAndConvertAt<int>(getColumnIndex("lease_type"))));
173}
174
175 IOAddress
176CSVLeaseFile6::readAddress(const CSVRow& row) {
177 IOAddress address(row.readAt(getColumnIndex("address")));
178 return (address);
179}
180
181 DuidPtr
182CSVLeaseFile6::readDUID(const util::CSVRow& row) {
183 DuidPtr duid(new DUID(DUID::fromText(row.readAt(getColumnIndex("duid")))));
184 return (duid);
185}
186
187uint32_t
188CSVLeaseFile6::readIAID(const CSVRow& row) {
189 uint32_t iaid = row.readAndConvertAt<uint32_t>(getColumnIndex("iaid"));
190 return (iaid);
191}
192
193uint32_t
194CSVLeaseFile6::readPreferred(const CSVRow& row) {
195 uint32_t pref =
196 row.readAndConvertAt<uint32_t>(getColumnIndex("pref_lifetime"));
197 return (pref);
198}
199
200uint32_t
201CSVLeaseFile6::readValid(const CSVRow& row) {
202 uint32_t valid =
203 row.readAndConvertAt<uint32_t>(getColumnIndex("valid_lifetime"));
204 return (valid);
205}
206
207uint32_t
208CSVLeaseFile6::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
216CSVLeaseFile6::readSubnetID(const CSVRow& row) {
217 SubnetID subnet_id =
218 row.readAndConvertAt<SubnetID>(getColumnIndex("subnet_id"));
219 return (subnet_id);
220}
221
222uint8_t
223CSVLeaseFile6::readPrefixLen(const CSVRow& row) {
224 int prefixlen = row.readAndConvertAt<int>(getColumnIndex("prefix_len"));
225 return (static_cast<uint8_t>(prefixlen));
226}
227
228bool
229CSVLeaseFile6::readFqdnFwd(const CSVRow& row) {
230 bool fqdn_fwd = row.readAndConvertAt<bool>(getColumnIndex("fqdn_fwd"));
231 return (fqdn_fwd);
232}
233
234bool
235CSVLeaseFile6::readFqdnRev(const CSVRow& row) {
236 bool fqdn_rev = row.readAndConvertAt<bool>(getColumnIndex("fqdn_rev"));
237 return (fqdn_rev);
238}
239
240std::string
241CSVLeaseFile6::readHostname(const CSVRow& row) {
242 std::string hostname = row.readAtEscaped(getColumnIndex("hostname"));
243 return (hostname);
244}
245
246 HWAddrPtr
247CSVLeaseFile6::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.
268 LOG_WARN(dhcpsrv_logger, DHCPSRV_MEMFILE_READ_HWADDR_FAIL)
269 .arg(ex.what());
270
271 return (HWAddrPtr());
272 }
273}
274
275uint32_t
276CSVLeaseFile6::readState(const util::CSVRow& row) {
277 uint32_t state = row.readAndConvertAt<uint32_t>(getColumnIndex("state"));
278 return (state);
279}
280
281 ConstElementPtr
282CSVLeaseFile6::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
295 Optional<uint16_t>
296CSVLeaseFile6::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
304 Optional<uint32_t>
305CSVLeaseFile6::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
isc::BadValue
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
Definition: exceptions/exceptions.h:132
isc::asiolink::IOAddress
The IOAddress class represents an IP addresses (version agnostic)
Definition: io_address.h:45
isc::asiolink::IOAddress::toText
std::string toText() const
Convert the address to a string.
Definition: io_address.cc:52
isc::data::Element::map
@ map
Definition: data.h:155
isc::data::Element::fromJSON
static ElementPtr fromJSON(const std::string &in, bool preproc=false)
These functions will parse the given string (JSON) representation of a compound element.
Definition: data.cc:764
isc::dhcp::CSVLeaseFile6::next
bool next(Lease6Ptr &lease)
Reads next lease from the CSV file.
Definition: csv_lease_file6.cc:85
isc::dhcp::CSVLeaseFile6::append
void append(const Lease6 &lease)
Appends the lease record to the CSV file.
Definition: csv_lease_file6.cc:36
isc::dhcp::CSVLeaseFile6::open
virtual void open(const bool seek_to_end=false)
Opens a lease file.
Definition: csv_lease_file6.cc:27
isc::dhcp::CSVLeaseFile6::CSVLeaseFile6
CSVLeaseFile6(const std::string &filename)
Constructor.
Definition: csv_lease_file6.cc:21
isc::dhcp::DUID::fromText
static DUID fromText(const std::string &text)
Create DUID from the textual format.
Definition: duid.cc:62
isc::dhcp::DUID::EMPTY
static const DUID & EMPTY()
Defines the constant "empty" DUID.
Definition: duid.cc:69
isc::dhcp::LeaseFileStats::write_leases_
uint32_t write_leases_
Number of lease written.
Definition: lease_file_stats.h:85
isc::dhcp::LeaseFileStats::read_leases_
uint32_t read_leases_
Number of leases read.
Definition: lease_file_stats.h:76
isc::dhcp::LeaseFileStats::reads_
uint32_t reads_
Number of attempts to read a lease.
Definition: lease_file_stats.h:73
isc::dhcp::LeaseFileStats::clearStatistics
void clearStatistics()
Clears the statistics.
Definition: lease_file_stats.h:62
isc::dhcp::LeaseFileStats::writes_
uint32_t writes_
Number of attempts to write a lease.
Definition: lease_file_stats.h:82
isc::dhcp::LeaseFileStats::write_errs_
uint32_t write_errs_
Number of errors when writing.
Definition: lease_file_stats.h:88
isc::dhcp::LeaseFileStats::read_errs_
uint32_t read_errs_
Number of errors when reading.
Definition: lease_file_stats.h:79
isc::util::CSVFile::getColumnCount
size_t getColumnCount() const
Returns the number of columns in the file.
Definition: csv_file.h:403
isc::util::CSVFile::setReadMsg
void setReadMsg(const std::string &read_msg)
Sets error message after row validation.
Definition: csv_file.h:486
isc::util::CSVFile::getColumnIndex
size_t getColumnIndex(const std::string &col_name) const
Returns the index of the column having specified name.
Definition: csv_file.cc:237
isc::util::CSVRow
Represents a single row of the CSV file.
Definition: csv_file.h:51
isc::util::CSVRow::readAndConvertAt
T readAndConvertAt(const size_t at) const
Retrieves a value from the internal container.
Definition: csv_file.h:156
isc::util::CSVRow::readAtEscaped
std::string readAtEscaped(const size_t at) const
Retrieves a value from the internal container, free of escaped characters.
Definition: csv_file.cc:66
isc::util::CSVRow::writeAt
void writeAt(const size_t at, const char *value)
Replaces the value at specified index.
Definition: csv_file.cc:84
isc::util::CSVRow::readAt
std::string readAt(const size_t at) const
Retrieves a value from the internal container.
Definition: csv_file.cc:60
isc::util::CSVRow::writeAtEscaped
void writeAtEscaped(const size_t at, const std::string &value)
Replaces the value at the specified index with a value that has had special characters escaped.
Definition: csv_file.cc:90
isc::util::Optional< uint16_t >
isc::util::Optional::valueOr
T valueOr(T const &or_value) const
Retrieves the encapsulated value if specified, or the given value otherwise.
Definition: optional.h:124
isc::util::VersionedCSVFile
Implements a CSV file that supports multiple versions of the file's "schema".
Definition: versioned_csv_file.h:120
isc::util::VersionedCSVFile::setMinimumValidColumns
void setMinimumValidColumns(const std::string &column_name)
Sets the minimum number of valid columns based on a given column.
Definition: versioned_csv_file.cc:33
isc::util::VersionedCSVFile::addColumn
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.
Definition: versioned_csv_file.cc:24
csv_lease_file6.h
dhcpsrv_log.h
isc_throw
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
Definition: exceptions/exceptions.h:210
isc::dhcp::HWAddr::HWADDR_SOURCE_UNKNOWN
static const uint32_t HWADDR_SOURCE_UNKNOWN
Used when actual origin is not known, e.g.
Definition: hwaddr.h:41
LOG_WARN
#define LOG_WARN(LOGGER, MESSAGE)
Macro to conveniently test warn output and log it.
Definition: macros.h:26
isc::asiolink
Definition: addr_utilities.cc:170
isc::data
Definition: base_stamped_element.cc:12
isc::data::ConstElementPtr
boost::shared_ptr< const Element > ConstElementPtr
Definition: data.h:27
isc::dhcp::dhcpsrv_logger
isc::log::Logger dhcpsrv_logger("dhcpsrv")
DHCP server library Logger.
Definition: dhcpsrv_log.h:56
isc::dhcp::DHCPSRV_MEMFILE_READ_HWADDR_FAIL
const isc::log::MessageID DHCPSRV_MEMFILE_READ_HWADDR_FAIL
Definition: dhcpsrv_messages.h:114
isc::dhcp::DuidPtr
boost::shared_ptr< DUID > DuidPtr
Definition: duid.h:20
isc::dhcp::Lease6Ptr
boost::shared_ptr< Lease6 > Lease6Ptr
Pointer to a Lease6 structure.
Definition: lease.h:503
isc::dhcp::HWAddrPtr
boost::shared_ptr< HWAddr > HWAddrPtr
Shared pointer to a hardware address structure.
Definition: hwaddr.h:154
isc::dhcp::SubnetID
uint32_t SubnetID
Defines unique IPv4 or IPv6 subnet identifier.
Definition: subnet_id.h:24
isc::dhcp::HTYPE_ETHER
@ HTYPE_ETHER
Ethernet 10Mbps.
Definition: dhcp4.h:56
isc::util
Definition: edns.h:19
isc
Defines the logger used by the top-level component of kea-lfc.
Definition: agent_parser.cc:143
isc::data::UserContext::getContext
data::ConstElementPtr getContext() const
Returns const pointer to the user context.
Definition: user_context.h:24
isc::dhcp::HWAddr::fromText
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
isc::dhcp::Lease6
Structure that holds a lease for IPv6 address and/or prefix.
Definition: lease.h:514
isc::dhcp::Lease6::type_
Lease::Type type_
Lease type.
Definition: lease.h:519
isc::dhcp::Lease6::iaid_
uint32_t iaid_
Identity Association Identifier (IAID)
Definition: lease.h:531
isc::dhcp::Lease6::preferred_lft_
uint32_t preferred_lft_
Preferred lifetime.
Definition: lease.h:540
isc::dhcp::Lease6::duid_
DuidPtr duid_
Client identifier.
Definition: lease.h:534
isc::dhcp::Lease6::prefixlen_
uint8_t prefixlen_
IPv6 prefix length.
Definition: lease.h:524
isc::dhcp::Lease::subnet_id_
SubnetID subnet_id_
Subnet identifier.
Definition: lease.h:154
isc::dhcp::Lease::valid_lft_
uint32_t valid_lft_
Valid lifetime.
Definition: lease.h:125
isc::dhcp::Lease::basicStatesToText
static std::string basicStatesToText(const uint32_t state)
Returns name(s) of the basic lease state(s).
Definition: lease.cc:90
isc::dhcp::Lease::STATE_DECLINED
static const uint32_t STATE_DECLINED
Declined lease.
Definition: lease.h:72
isc::dhcp::Lease::Type
Type
Type of lease or pool.
Definition: lease.h:46
isc::dhcp::Lease::hostname_
std::string hostname_
Client hostname.
Definition: lease.h:159
isc::dhcp::Lease::state_
uint32_t state_
Holds the lease state(s).
Definition: lease.h:185
isc::dhcp::Lease::fqdn_fwd_
bool fqdn_fwd_
Forward zone updated?
Definition: lease.h:164
isc::dhcp::Lease::cltt_
time_t cltt_
Client last transmission time.
Definition: lease.h:143
isc::dhcp::Lease::hwaddr_
HWAddrPtr hwaddr_
Client's MAC/hardware address.
Definition: lease.h:174
isc::dhcp::Lease::fqdn_rev_
bool fqdn_rev_
Reverse zone updated?
Definition: lease.h:169
isc::dhcp::Lease::addr_
isc::asiolink::IOAddress addr_
IPv4 ot IPv6 address.
Definition: lease.h:120