Kea 1.5.0
csv_lease_file4.cc
Go to the documentation of this file.
1// Copyright (C) 2014-2018 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>
9#include <ctime>
10
11using namespace isc::asiolink;
12using namespace isc::data;
13using namespace isc::util;
14
15namespace isc {
16namespace dhcp {
17
18CSVLeaseFile4::CSVLeaseFile4(const std::string& filename)
19 : VersionedCSVFile(filename) {
20 initColumns();
21}
22
23void
24CSVLeaseFile4::open(const bool seek_to_end) {
25 // Call the base class to open the file
26 VersionedCSVFile::open(seek_to_end);
27
28 // and clear any statistics we may have
30}
31
32void
34 // Bump the number of write attempts
35 ++writes_;
36
38 row.writeAt(getColumnIndex("address"), lease.addr_.toText());
39 if (!lease.hwaddr_) {
40 // Bump the error counter
42
43 isc_throw(BadValue, "Lease4 must have hardware address specified.");
44 }
45 row.writeAt(getColumnIndex("hwaddr"), lease.hwaddr_->toText(false));
46 // Client id may be unset (NULL).
47 if (lease.client_id_) {
48 row.writeAt(getColumnIndex("client_id"), lease.client_id_->toText());
49 }
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("fqdn_fwd"), lease.fqdn_fwd_);
54 row.writeAt(getColumnIndex("fqdn_rev"), lease.fqdn_rev_);
55 row.writeAt(getColumnIndex("hostname"), lease.hostname_);
56 row.writeAt(getColumnIndex("state"), lease.state_);
57 // User context is optional.
58 if (lease.getContext()) {
59 row.writeAt(getColumnIndex("user_context"), lease.getContext()->str());
60 }
61
62 try {
63 VersionedCSVFile::append(row);
64 } catch (const std::exception&) {
65 // Catch any errors so we can bump the error counter than rethrow it
67 throw;
68 }
69
70 // Bump the number of leases written
72}
73
74bool
76 // Bump the number of read attempts
77 ++reads_;
78
79 // Read the CSV row and try to create a lease from the values read.
80 // This may easily result in exception. We don't want this function
81 // to throw exceptions, so we catch them all and rather return the
82 // false value.
83 try {
84 // Get the row of CSV values.
85 CSVRow row;
87 // The empty row signals EOF.
88 if (row == CSVFile::EMPTY_ROW()) {
89 lease.reset();
90 return (true);
91 }
92
93 // Get client id. It is possible that the client id is empty and the
94 // returned pointer is NULL. This is ok, but if the client id is NULL,
95 // we need to be careful to not use the NULL pointer.
96 ClientIdPtr client_id = readClientId(row);
97 std::vector<uint8_t> client_id_vec;
98 if (client_id) {
99 client_id_vec = client_id->getClientId();
100 }
101 size_t client_id_len = client_id_vec.size();
102
103 // Get the HW address. It should never be empty and the readHWAddr checks
104 // that.
105 HWAddr hwaddr = readHWAddr(row);
106 uint32_t state = readState(row);
107 if (hwaddr.hwaddr_.empty() && state != Lease::STATE_DECLINED) {
108 isc_throw(isc::BadValue, "A blank hardware address is only"
109 " valid for declined leases");
110 }
111
112 // Get the user context (can be NULL).
113 ConstElementPtr ctx = readContext(row);
114
115 lease.reset(new Lease4(readAddress(row),
116 HWAddrPtr(new HWAddr(hwaddr)),
117 client_id_vec.empty() ? NULL : &client_id_vec[0],
118 client_id_len,
119 readValid(row),
120 0, 0, // t1, t2 = 0
121 readCltt(row),
122 readSubnetID(row),
123 readFqdnFwd(row),
124 readFqdnRev(row),
125 readHostname(row)));
126 lease->state_ = state;
127
128 if (ctx) {
129 lease->setContext(ctx);
130 }
131
132 } catch (std::exception& ex) {
133 // bump the read error count
134 ++read_errs_;
135
136 // The lease might have been created, so let's set it back to NULL to
137 // signal that lease hasn't been parsed.
138 lease.reset();
139 setReadMsg(ex.what());
140 return (false);
141 }
142
143 // bump the number of leases read
144 ++read_leases_;
145
146 return (true);
147}
148
149void
150CSVLeaseFile4::initColumns() {
151 addColumn("address", "1.0");
152 addColumn("hwaddr", "1.0");
153 addColumn("client_id", "1.0");
154 addColumn("valid_lifetime", "1.0");
155 addColumn("expire", "1.0");
156 addColumn("subnet_id", "1.0");
157 addColumn("fqdn_fwd", "1.0");
158 addColumn("fqdn_rev", "1.0");
159 addColumn("hostname", "1.0");
160 addColumn("state", "2.0", "0");
161 addColumn("user_context", "2.1");
162 // Any file with less than hostname is invalid
163 setMinimumValidColumns("hostname");
164}
165
167CSVLeaseFile4::readAddress(const CSVRow& row) {
168 IOAddress address(row.readAt(getColumnIndex("address")));
169 return (address);
170}
171
172HWAddr
173CSVLeaseFile4::readHWAddr(const CSVRow& row) {
174 HWAddr hwaddr = HWAddr::fromText(row.readAt(getColumnIndex("hwaddr")));
175 return (hwaddr);
176}
177
179CSVLeaseFile4::readClientId(const CSVRow& row) {
180 std::string client_id = row.readAt(getColumnIndex("client_id"));
181 // NULL client ids are allowed in DHCPv4.
182 if (client_id.empty()) {
183 return (ClientIdPtr());
184 }
185 ClientIdPtr cid = ClientId::fromText(client_id);
186 return (cid);
187}
188
189uint32_t
190CSVLeaseFile4::readValid(const CSVRow& row) {
191 uint32_t valid =
192 row.readAndConvertAt<uint32_t>(getColumnIndex("valid_lifetime"));
193 return (valid);
194}
195
196time_t
197CSVLeaseFile4::readCltt(const CSVRow& row) {
198 time_t cltt =
199 static_cast<time_t>(row.readAndConvertAt<uint64_t>(getColumnIndex("expire"))
200 - readValid(row));
201 return (cltt);
202}
203
205CSVLeaseFile4::readSubnetID(const CSVRow& row) {
206 SubnetID subnet_id =
207 row.readAndConvertAt<SubnetID>(getColumnIndex("subnet_id"));
208 return (subnet_id);
209}
210
211bool
212CSVLeaseFile4::readFqdnFwd(const CSVRow& row) {
213 bool fqdn_fwd = row.readAndConvertAt<bool>(getColumnIndex("fqdn_fwd"));
214 return (fqdn_fwd);
215}
216
217bool
218CSVLeaseFile4::readFqdnRev(const CSVRow& row) {
219 bool fqdn_rev = row.readAndConvertAt<bool>(getColumnIndex("fqdn_rev"));
220 return (fqdn_rev);
221}
222
223std::string
224CSVLeaseFile4::readHostname(const CSVRow& row) {
225 std::string hostname = row.readAt(getColumnIndex("hostname"));
226 return (hostname);
227}
228
229uint32_t
230CSVLeaseFile4::readState(const util::CSVRow& row) {
231 uint32_t state = row.readAndConvertAt<uint32_t>(getColumnIndex("state"));
232 return (state);
233}
234
236CSVLeaseFile4::readContext(const util::CSVRow& row) {
237 std::string user_context = row.readAt(getColumnIndex("user_context"));
238 if (user_context.empty()) {
239 return (ConstElementPtr());
240 }
241 ConstElementPtr ctx = Element::fromJSON(user_context);
242 if (!ctx || (ctx->getType() != Element::map)) {
243 isc_throw(isc::BadValue, "user context '" << user_context
244 << "' is not a JSON map");
245 }
246 return (ctx);
247}
248
249} // end of namespace isc::dhcp
250} // end of namespace isc
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
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:750
void append(const Lease4 &lease)
Appends the lease record to the CSV file.
CSVLeaseFile4(const std::string &filename)
Constructor.
virtual void open(const bool seek_to_end=false)
Opens a lease file.
bool next(Lease4Ptr &lease)
Reads next lease from the CSV file.
static ClientIdPtr fromText(const std::string &text)
Create client identifier from the textual format.
Definition: duid.cc:131
uint32_t write_leases_
Number of lease written.
uint32_t read_leases_
Number of leases read.
uint32_t reads_
Number of attempts to read a lease.
void clearStatistics()
Clears the statistics.
uint32_t writes_
Number of attempts to write a lease.
uint32_t write_errs_
Number of errors when writing.
uint32_t read_errs_
Number of errors when reading.
size_t getColumnCount() const
Returns the number of columns in the file.
Definition: csv_file.h:335
static CSVRow EMPTY_ROW()
Represents empty row.
Definition: csv_file.h:423
void setReadMsg(const std::string &read_msg)
Sets error message after row validation.
Definition: csv_file.h:418
size_t getColumnIndex(const std::string &col_name) const
Returns the index of the column having specified name.
Definition: csv_file.cc:206
Represents a single row of the CSV file.
Definition: csv_file.h:51
T readAndConvertAt(const size_t at) const
Retrieves a value from the internal container.
Definition: csv_file.h:135
void writeAt(const size_t at, const char *value)
Replaces the value at specified index.
Definition: csv_file.cc:58
std::string readAt(const size_t at) const
Retrieves a value from the internal container.
Definition: csv_file.cc:39
Implements a CSV file that supports multiple versions of the file's "schema".
virtual void open(const bool seek_to_end=false)
Opens existing file or creates a new one.
void setMinimumValidColumns(const std::string &column_name)
Sets the minimum number of valid columns based on a given column.
bool next(CSVRow &row)
Reads next row from the file file.
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.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
boost::shared_ptr< const Element > ConstElementPtr
Definition: data.h:23
boost::shared_ptr< HWAddr > HWAddrPtr
Shared pointer to a hardware address structure.
Definition: hwaddr.h:154
uint32_t SubnetID
Unique identifier for a subnet (both v4 and v6)
Definition: lease.h:24
boost::shared_ptr< ClientId > ClientIdPtr
Shared pointer to a Client ID.
Definition: duid.h:105
boost::shared_ptr< Lease4 > Lease4Ptr
Pointer to a Lease4 structure.
Definition: lease.h:248
Definition: edns.h:19
Defines the logger used by the top-level component of kea-dhcp-ddns.
data::ConstElementPtr getContext() const
Returns const pointer to the user context.
Definition: user_context.h:24
Hardware type that represents information from DHCPv4 packet.
Definition: hwaddr.h:20
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
std::vector< uint8_t > hwaddr_
Definition: hwaddr.h:98
Structure that holds a lease for IPv4 address.
Definition: lease.h:256
ClientIdPtr client_id_
Client identifier.
Definition: lease.h:262
SubnetID subnet_id_
Subnet identifier.
Definition: lease.h:136
uint32_t valid_lft_
Valid lifetime.
Definition: lease.h:125
static const uint32_t STATE_DECLINED
Declined lease.
Definition: lease.h:64
std::string hostname_
Client hostname.
Definition: lease.h:141
uint32_t state_
Holds the lease state(s).
Definition: lease.h:167
bool fqdn_fwd_
Forward zone updated?
Definition: lease.h:146
time_t cltt_
Client last transmission time.
Definition: lease.h:131
HWAddrPtr hwaddr_
Client's MAC/hardware address.
Definition: lease.h:156
bool fqdn_rev_
Reverse zone updated?
Definition: lease.h:151
isc::asiolink::IOAddress addr_
IPv4 ot IPv6 address.
Definition: lease.h:102