Kea 3.3.3
host_cache_parsers.cc
Go to the documentation of this file.
1// Copyright (C) 2020-2026 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
12
13#include <boost/lexical_cast.hpp>
14#include <boost/pointer_cast.hpp>
15
16using namespace isc::asiolink;
17using namespace isc::data;
18using namespace isc::dhcp;
19using namespace std;
20
21namespace isc {
22namespace host_cache {
23
26 { "maximum", Element::integer, "0" }
27};
28
30void
32 ElementPtr mutable_cfg;
33 if (config) {
34 mutable_cfg = boost::const_pointer_cast<Element>(config);
35 } else {
36 mutable_cfg = Element::createMap();
37 }
38
39 if (!mutable_cfg || (mutable_cfg->getType() != Element::map)) {
40 isc_throw(ConfigError, "Host Cache config is not a map");
41 }
42
43 try {
44 setDefaults(mutable_cfg, HOST_CACHE_DEFAULTS);
45
46 int64_t maximum = getInteger(mutable_cfg, "maximum");
47 if (maximum < 0) {
48 isc_throw(ConfigError, "Host Cache maximum parameter is negative");
49 }
50 if (maximum > MAXIMUM) {
51 isc_throw(ConfigError, "Host Cache maximum parameter is too large "
52 << "(" << maximum << " > " << MAXIMUM << ")");
53 }
54 hcref.setMaximum(static_cast<size_t>(maximum));
55 } catch (const ConfigError&) {
56 throw;
57 } catch (const exception& ex) {
58 isc_throw(ConfigError, ex.what());
59 }
60}
61
64 try {
65 // Scan critical parameters
66 string identifier;
67 string identifier_name;
68 string hostname;
69 ConstElementPtr user_context;
70 auto& map = entry->mapValue();
71 for (auto const& element : map) {
72 if ((element.first == "hw-address") ||
73 (element.first == "duid") ||
74 (element.first == "circuit-id") ||
75 (element.first == "client-id") ||
76 (element.first == "flex-id")) {
77 if (!identifier_name.empty()) {
78 isc_throw(ConfigError, "the '" << element.first
79 << "' and '" << identifier_name
80 << "' are mutually exclusive");
81 }
82 identifier = element.second->stringValue();
83 identifier_name = element.first;
84 continue;
85 }
86
87 if (element.first == "hostname") {
88 hostname = element.second->stringValue();
89 continue;
90 }
91
92 if (element.first == "user-context") {
93 user_context = element.second;
94 continue;
95 }
96 }
97
98 // Host identifier is a must.
99 if (identifier_name.empty()) {
100 isc_throw(ConfigError, "no identifier");
101 }
102
103 // Create a host object from the basic parameters we already parsed.
104 HostPtr host;
105 host.reset(new Host(identifier, identifier_name,
106 SubnetID(SUBNET_ID_UNUSED),
107 SubnetID(SUBNET_ID_UNUSED),
108 IOAddress("0.0.0.0"), hostname));
109 // Add user context
110 if (user_context) {
111 host->setContext(user_context);
112 }
113
114 // Scan other parameters
115 for (auto const& element : map) {
116 if ((element.first == "hw-address") ||
117 (element.first == "duid") ||
118 (element.first == "circuit-id") ||
119 (element.first == "client-id") ||
120 (element.first == "flex-id") ||
121 (element.first == "hostname") ||
122 (element.first == "user-context")) {
123 continue;
124 }
125
126 if (element.first == "subnet-id4") {
127 host->setIPv4SubnetID(element.second->intValue());
128 continue;
129 }
130
131 if (element.first == "subnet-id6") {
132 host->setIPv6SubnetID(element.second->intValue());
133 continue;
134 }
135
136 if (element.first == "option-data4") {
137 CfgOptionPtr cfg_option = host->getCfgOption4();
138 OptionDataListParser parser(AF_INET);
139 parser.parse(cfg_option, element.second);
140 continue;
141 }
142
143 if (element.first == "option-data6") {
144 CfgOptionPtr cfg_option = host->getCfgOption6();
145 OptionDataListParser parser(AF_INET6);
146 parser.parse(cfg_option, element.second);
147 continue;
148 }
149
150 if (element.first == "ip-address") {
151 host->setIPv4Reservation(IOAddress(element.second->stringValue()));
152 continue;
153 }
154
155 if (element.first == "next-server") {
156 host->setNextServer(IOAddress(element.second->stringValue()));
157 continue;
158 }
159
160 if (element.first == "server-hostname") {
161 host->setServerHostname(element.second->stringValue());
162 continue;
163 }
164
165 if (element.first == "boot-file-name") {
166 host->setBootFileName(element.second->stringValue());
167 continue;
168 }
169
170 if (element.first == "client-classes4") {
171 auto const& classes = element.second->listValue();
172 for (auto const& cclass : classes) {
173 host->addClientClass4(cclass->stringValue());
174 }
175 continue;
176 }
177
178 if (element.first == "client-classes6") {
179 auto const& classes = element.second->listValue();
180 for (auto const& cclass : classes) {
181 host->addClientClass6(cclass->stringValue());
182 }
183 continue;
184 }
185
186 if (element.first == "ip-addresses") {
187 auto const& addresses = element.second->listValue();
188 for (auto const& addr : addresses) {
189 string address = addr->stringValue();
190 host->addReservation(IPv6Resrv(IPv6Resrv::TYPE_NA,
191 IOAddress(address),
192 128));
193 }
194 continue;
195 }
196
197 if (element.first == "prefixes") {
198 auto& prefixes = element.second->listValue();
199 for (auto const& pref : prefixes) {
200 string prefix = pref->stringValue();
201 uint8_t len = 128;
202 size_t pos = prefix.find('/');
203 if (pos == string::npos) {
204 isc_throw(ConfigError, "bad prefix (no /)");
205 } else if (pos > prefix.length() - 1) {
206 isc_throw(ConfigError, "bad prefix (end /)");
207 }
208 try {
209 string preflen = prefix.substr(pos + 1);
210 len = boost::lexical_cast<unsigned>(preflen);
211 } catch (const boost::bad_lexical_cast&) {
212 isc_throw(ConfigError, "bad prefix length");
213 }
214 prefix.erase(pos);
215
216 host->addReservation(IPv6Resrv(IPv6Resrv::TYPE_PD,
217 IOAddress(prefix),
218 len));
219 }
220 continue;
221 }
222
223 if (element.first == "host-id") {
224 int64_t hid = element.second->intValue();
225 host->setHostId(static_cast<uint64_t>(hid));
226 continue;
227 }
228
229 if (element.first == "negative") {
230 host->setNegative(element.second->boolValue());
231 continue;
232 }
233
234 isc_throw(ConfigError, "unknown parameter: " << element.first);
235 }
236 return (host);
237
238 } catch (const ConfigError&) {
239 throw;
240 } catch (const exception& ex) {
241 isc_throw(ConfigError, ex.what());
242 }
243}
244
245} // end of namespace isc::host_cache
246} // end of namespace isc
@ map
Definition data.h:160
@ integer
Definition data.h:153
static ElementPtr createMap(const Position &pos=ZERO_POSITION())
Creates an empty MapElement type ElementPtr.
Definition data.cc:355
An exception that is thrown if an error occurs while configuring any server.
static int64_t getInteger(isc::data::ConstElementPtr scope, const std::string &name)
Returns an integer parameter from a scope.
static size_t setDefaults(isc::data::ElementPtr scope, const SimpleDefaults &default_values)
Sets the default values.
Represents a device with IPv4 and/or IPv6 reservations.
Definition host.h:330
IPv6 reservation for a host.
Definition host.h:166
Parser for option data values within a subnet.
void parse(const CfgOptionPtr &cfg, isc::data::ConstElementPtr option_data_list, bool encapsulate=true)
Parses a list of options, instantiates them and stores in cfg.
static const int64_t MAXIMUM
Absolute maximum number of elements.
static const data::SimpleDefaults HOST_CACHE_DEFAULTS
Defaults for Host Cache configuration.
void parse(HostCache &hcref, const data::ConstElementPtr &config)
Parses Host Cache configuration.
dhcp::HostPtr parse(const data::ConstElementPtr &entry)
Parses Host Cache entry.
Host Cache implementation.
Definition host_cache.h:35
virtual void setMaximum(size_t maximum)
Set maximum number of cached hosts (0 means unbound).
Definition host_cache.cc:49
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
boost::shared_ptr< const Element > ConstElementPtr
Definition data.h:30
std::vector< SimpleDefault > SimpleDefaults
This specifies all default values in a given scope (e.g. a subnet).
boost::shared_ptr< Element > ElementPtr
Definition data.h:29
boost::shared_ptr< CfgOption > CfgOptionPtr
Non-const pointer.
Definition cfg_option.h:983
boost::shared_ptr< Host > HostPtr
Pointer to the Host object.
Definition host.h:840
uint32_t SubnetID
Defines unique IPv4 or IPv6 subnet identifier.
Definition subnet_id.h:25
Defines the logger used by the top-level component of kea-lfc.